Applied all debian/patches from glsdk-6_00_00_07 release
authorNikhil Devshatwar <a0132237@ti.com>
Mon, 10 Jun 2013 13:56:00 +0000 (19:26 +0530)
committerNikhil Devshatwar <a0132237@ti.com>
Mon, 10 Jun 2013 13:56:00 +0000 (19:26 +0530)
xserver repository has some prerelease debian patches imported
Which could not be traced into upstream
Therefore pushing debian tree as development tree
Also adding debian/patches as last commit

69 files changed:
Xext/security.c
Xi/exevents.c
configure.ac
dix/dispatch.c
dix/dixutils.c
dix/events.c
dix/getevents.c
dix/touch.c
exa/exa_priv.h
exa/exa_unaccel.c
glx/glxdricommon.c
hw/dmx/dmxinit.c
hw/kdrive/src/kdrive.c
hw/vfb/InitOutput.c
hw/xfree86/common/extramodes
hw/xfree86/common/xf86AutoConfig.c
hw/xfree86/common/xf86Config.c
hw/xfree86/common/xf86Events.c
hw/xfree86/common/xf86Globals.c
hw/xfree86/common/xf86Helper.c
hw/xfree86/common/xf86Init.c
hw/xfree86/common/xf86Priv.h
hw/xfree86/common/xf86VidMode.c
hw/xfree86/common/xf86pciBus.c
hw/xfree86/common/xisb.c
hw/xfree86/dri2/dri2.c
hw/xfree86/dri2/dri2.h
hw/xfree86/dri2/dri2ext.c
hw/xfree86/man/xorg.conf.man
hw/xfree86/modes/xf86Crtc.c
hw/xfree86/modes/xf86Crtc.h
hw/xfree86/modes/xf86Cursors.c
hw/xfree86/modes/xf86RandR12.c
hw/xfree86/modes/xf86Rotate.c
hw/xfree86/os-support/linux/lnx_init.c
hw/xfree86/os-support/linux/lnx_video.c
hw/xnest/Init.c
hw/xquartz/darwin.c
hw/xwin/InitOutput.c
include/Xprintf.h
include/dix-config.h.in
include/dix.h
include/dixstruct.h
include/input.h
include/os.h
include/protocol-versions.h
include/xorg-config.h.in
mi/midispcur.c
mi/mipointer.c
miext/cw/cw_render.c
os/log.c
os/osinit.c
os/utils.c
os/xprintf.c
os/xsha1.c
randr/randr.c
randr/rroutput.c
randr/rrscreen.c
test/Makefile.am
test/gtest/Makefile.am [new file with mode: 0644]
test/gtest/dummy.conf [new file with mode: 0644]
test/gtest/xfixes_barriers.cpp [new file with mode: 0644]
xfixes/cursor.c
xfixes/xfixes.c
xfixes/xfixes.h
xfixes/xfixesint.h
xkb/README.compiled
xkb/ddxLoad.c
xkb/xkbActions.c

index aa78e540d5a87f045d0c14a25b72eb66dfdb23e0..5595e089cfdbbb5d71993543f6af38ad39a17963 100644 (file)
@@ -269,10 +269,10 @@ SecurityComputeAuthorizationTimeout(
     /* maxSecs is the number of full seconds that can be expressed in
      * 32 bits worth of milliseconds
      */
-    CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND;
+    CARD32 maxSecs = (CARD32)(MAXINT) / (CARD32)MILLI_PER_SECOND;
 
     if (seconds > maxSecs)
-    { /* only come here if we want to wait more than 49 days */
+    { /* only come here if we want to wait more than 24 days */
        pAuth->secondsRemaining = seconds - maxSecs;
        return maxSecs * MILLI_PER_SECOND;
     }
@@ -310,8 +310,6 @@ SecurityAuthorizationExpired(
 {
     SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval;
 
-    assert(pAuth->timer == timer);
-
     if (pAuth->secondsRemaining)
     {
        return SecurityComputeAuthorizationTimeout(pAuth,
index d71e604350beb307f6814b4f7655f319c24c1638..1a5ee97ea61f62ba4947394f3403aea323eab658 100644 (file)
@@ -1147,6 +1147,48 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
     FreeEventList(tel, GetMaximumEventsNum());
 }
 
+/**
+ * Find the oldest touch that still has a pointer emulation client.
+ *
+ * Pointer emulation can only be performed for the oldest touch. Otherwise, the
+ * order of events seen by the client will be wrong. This function helps us find
+ * the next touch to be emulated.
+ *
+ * @param dev The device to find touches for.
+ */
+static TouchPointInfoPtr
+FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = NULL;
+    int i;
+
+    for (i = 0; i < dev->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = dev->touch->touches + i;
+        int j;
+
+        if (!ti->active || !ti->emulate_pointer)
+            continue;
+
+        for (j = 0; j < ti->num_listeners; j++) {
+            if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
+                ti->listeners[j].type == LISTENER_POINTER_REGULAR)
+                break;
+        }
+        if (j == ti->num_listeners)
+            continue;
+
+        if (!oldest) {
+            oldest = ti;
+            continue;
+        }
+
+        if (oldest->client_id - ti->client_id < UINT_MAX / 2)
+            oldest = ti;
+    }
+
+    return oldest;
+}
+
 /**
  * If the current owner has rejected the event, deliver the
  * TouchOwnership/TouchBegin to the next item in the sprite stack.
@@ -1159,8 +1201,16 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
         ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener);
-    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
+    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) {
+        /* We can't punt to a pointer listener unless all older pointer
+         * emulated touches have been seen already. */
+        if ((ti->listeners[0].type == LISTENER_POINTER_GRAB ||
+             ti->listeners[0].type == LISTENER_POINTER_REGULAR) &&
+            ti != FindOldestPointerEmulatedTouch(dev))
+            return;
+
         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
+    }
 
     /* If we've just removed the last grab and the touch has physically
      * ended, send a TouchEnd event too and finalise the touch. */
@@ -1176,6 +1226,25 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
         ActivateEarlyAccept(dev, ti);
 }
 
+/**
+ * Check the oldest touch to see if it needs to be replayed to its pointer
+ * owner.
+ *
+ * Touch event propagation is paused if it hits a pointer listener while an
+ * older touch with a pointer listener is waiting on accept or reject. This
+ * function will restart propagation of a paused touch if needed.
+ *
+ * @param dev The device to check touches for.
+ */
+static void
+CheckOldestTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
+
+    if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
+        TouchPuntToNextOwner(dev, oldest, NULL);
+}
+
 /**
  * Process a touch rejection.
  *
@@ -1205,14 +1274,6 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
         }
     }
 
-    /* If there are no other listeners left, and the touchpoint is pending
-     * finish, then we can just kill it now. */
-    if (ti->num_listeners == 1 && ti->pending_finish)
-    {
-        TouchEndTouch(sourcedev, ti);
-        return;
-    }
-
     /* Remove the resource from the listener list, updating
      * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
     if (TouchRemoveListener(ti, resource))
@@ -1226,6 +1287,10 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * the TouchOwnership or TouchBegin event to the new owner. */
     if (ev && ti->num_listeners > 0 && was_owner)
         TouchPuntToNextOwner(sourcedev, ti, ev);
+    else if (ti->num_listeners == 0)
+        TouchEndTouch(sourcedev, ti);
+
+    CheckOldestTouch(sourcedev);
 }
 
 /**
@@ -1243,9 +1308,18 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (ev->reason == XIRejectTouch)
         TouchRejected(dev, ti, ev->resource, ev);
     else if (ev->reason == XIAcceptTouch) {
+        int i;
+
+        /* Go through the motions of ending the touch if the listener has
+         * already seen the end. This ensures that the touch record is ended in
+         * the server. */
+        if (ti->listeners[0].state == LISTENER_HAS_END)
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
+
         /* The touch owner has accepted the touch.  Send TouchEnd events to
          * everyone else, and truncate the list of listeners. */
-        EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
+        for (i = 1; i < ti->num_listeners; i++)
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
 
         while (ti->num_listeners > 1)
             TouchRemoveListener(ti, ti->listeners[1].listener);
@@ -1295,6 +1369,7 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
 {
      int rc;
      InputClients *iclients = NULL;
+     *mask = NULL;
 
     if (listener->type == LISTENER_GRAB ||
         listener->type == LISTENER_POINTER_GRAB)
@@ -1344,6 +1419,9 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             BUG_WARN(!iclients);
             if (!iclients)
                 return FALSE;
+
+            *mask = iclients->xi2mask;
+            *client = rClient(iclients);
         } else if (listener->level == XI)
         {
             int xi_type = GetXIType(TouchGetPointerEventType(ev));
@@ -1354,20 +1432,22 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             BUG_WARN(!iclients);
             if (!iclients)
                 return FALSE;
+
+            *client = rClient(iclients);
         } else
         {
             int coretype = GetCoreType(TouchGetPointerEventType(ev));
             Mask core_filter = event_get_filter_from_type(dev, coretype);
+            OtherClients *oclients;
 
             /* all others */
-            nt_list_for_each_entry(iclients, (InputClients*)wOtherClients(*win), next)
-                if (iclients->mask[XIAllDevices] & core_filter)
+            nt_list_for_each_entry(oclients, (InputClients*)wOtherClients(*win), next)
+                if (oclients->mask & core_filter)
                     break;
-            /* if owner selected, iclients is NULL */
+            /* if owner selected, oclients is NULL */
+            *client = oclients ? rClient(oclients) : wClient(*win);
         }
 
-        *client = iclients ? rClient(iclients) : wClient(*win);
-        *mask = iclients ? iclients->xi2mask : NULL;
         *grab = NULL;
     }
 
@@ -1422,11 +1502,21 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent
             if (!deliveries)
                 DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
 
+            /* We must accept the touch sequence once a pointer listener has
+             * received one event past ButtonPress. */
+            if (deliveries && ev->any.type != ET_TouchBegin &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID))
+                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+
             if (ev->any.type == ET_TouchEnd &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab &&
-                GrabIsPointerGrab(grab))
+                GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab)(dev);
+                CheckOldestTouch(dev);
+                return Success;
+            }
         }
     } else
     {
@@ -1546,12 +1636,43 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         touchid = ev->device_event.touchid;
 
+    if (emulate_pointer)
+        UpdateDeviceState(dev, &ev->device_event);
+
     if (type == ET_TouchBegin) {
         ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
                              emulate_pointer);
     } else
         ti = TouchFindByClientID(dev, touchid);
 
+    /* Under the following circumstances we create a new touch record for an
+     * existing touch:
+     *
+     * - The touch may be pointer emulated
+     * - An explicit grab is active on the device
+     * - The grab is a pointer grab
+     *
+     * This allows for an explicit grab to receive pointer events for an already
+     * active touch.
+     */
+    if (!ti && type != ET_TouchBegin && emulate_pointer &&
+        dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
+        (dev->deviceGrab.grab->grabtype == CORE ||
+         dev->deviceGrab.grab->grabtype == XI ||
+         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) {
+        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+                             emulate_pointer);
+        if (!ti) {
+            DebugF("[Xi] %s: Failed to create new dix record for explicitly "
+                   "grabbed touchpoint %d\n",
+                   dev->name, type, touchid);
+            return;
+        }
+
+        TouchBuildSprite(dev, ti, ev);
+        TouchSetupListeners(dev, ti, ev);
+    }
+
     if (!ti)
     {
         DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
@@ -1569,9 +1690,11 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
         CheckMotion(&ev->device_event, dev);
 
     /* Make sure we have a valid window trace for event delivery; must be
-     * called after event type mutation. */
+     * called after event type mutation. Touch end events are always processed
+     * in order to end touch records. */
     /* FIXME: check this */
-    if (!TouchEnsureSprite(dev, ti, ev))
+    if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
+        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
         return;
 
     /* TouchOwnership events are handled separately from the rest, as they
@@ -1807,6 +1930,14 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
     {
         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                        grab, xi2mask);
+
+        if (ti->num_listeners > 1) {
+            ev->any.type = ET_TouchUpdate;
+            ev->device_event.flags |= TOUCH_PENDING_END;
+            if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
+                ti->pending_finish = TRUE;
+        }
+
         goto out;
     }
 
@@ -1917,9 +2048,6 @@ DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
         DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
     }
-
-    if (ti->emulate_pointer)
-        UpdateDeviceState(dev, &ev->device_event);
 }
 
 int
index 5e29b2a4715685263a98cb1738e2ba6ba0dbae35..56c5c6aac2017f8ebdb5ce349a8bea7612093ed6 100644 (file)
@@ -210,7 +210,8 @@ dnl Checks for library functions.
 AC_FUNC_VPRINTF
 AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \
                strtol getopt getopt_long vsnprintf walkcontext backtrace \
-               getisax getzoneid shmctl64 strcasestr ffs vasprintf])
+               getisax getzoneid shmctl64 strcasestr ffs vasprintf issetugid \
+               getresuid])
 AC_FUNC_ALLOCA
 dnl Old HAS_* names used in os/*.c.
 AC_CHECK_FUNC([getdtablesize],
@@ -480,6 +481,10 @@ AC_ARG_WITH(module-dir,      AS_HELP_STRING([--with-module-dir=DIR],
                                  [Directory where modules are installed (default: $libdir/xorg/modules)]),
                                [ moduledir="$withval" ],
                                [ moduledir="${libdir}/xorg/modules" ])
+AC_ARG_WITH(extra-module-dir,AS_HELP_STRING([--with-extra-module-dir=DIR],
+                                 [Extra module directory to search for modules before the default one (default: empty)]),
+                               [ extra_moduledir="$withval" ],
+                               [ extra_moduledir="" ])
 AC_ARG_WITH(log-dir,         AS_HELP_STRING([--with-log-dir=DIR],
                                  [Directory where log files are kept (default: $localstatedir/log)]),
                                [ logdir="$withval" ],
@@ -528,9 +533,9 @@ AC_MSG_RESULT([$FONTPATH])
 AC_ARG_WITH(xkb-path,         AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]),
                                [ XKBPATH="$withval" ],
                                [ XKBPATH="${datadir}/X11/xkb" ])
-AC_ARG_WITH(xkb-output,       AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]),
+AC_ARG_WITH(xkb-output,       AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${localstatedir}/cache/xkb)]),
                                [ XKBOUTPUT="$withval" ],
-                               [ XKBOUTPUT="compiled" ])
+                               [ XKBOUTPUT="${localstatedir}/cache/xkb" ])
 AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES],
                                    [Keyboard ruleset (default: base/evdev)]),
                                 [ XKB_DFLT_RULES="$withval" ],
@@ -1179,7 +1184,7 @@ AC_DEFINE_DIR(XKB_BIN_DIRECTORY, XKB_BIN_DIRECTORY, [Path to XKB bin dir])
 dnl Make sure XKM_OUTPUT_DIR is an absolute path
 XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1`
 if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then
-   XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT"
+   AC_MSG_ERROR([xkb-output must be an absolute path.])
 fi
 
 dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed
@@ -1322,7 +1327,7 @@ CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
 
 # SHA1 hashing
 AC_ARG_WITH([sha1],
-            [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto],
+            [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto|nettle],
                             [choose SHA1 implementation])])
 AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes])
 if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then
@@ -1405,6 +1410,16 @@ if test "x$with_sha1" = xlibcrypto; then
                SHA1_CFLAGS="$OPENSSL_CFLAGS"
        fi
 fi
+AC_CHECK_LIB([nettle], [nettle_sha1_init], [HAVE_LIBNETTLE=yes])
+if test "x$with_sha1" = x && test "x$HAVE_LIBNETTLE" = xyes; then
+       with_sha1=nettle
+fi
+if test "x$with_sha1" = xnettle; then
+       AC_DEFINE([HAVE_SHA1_IN_LIBNETTLE], [1],
+                 [Use libnettle SHA1 functions])
+       # XXX hack for d-i: use the static lib
+       SHA1_LIBS=-l:libnettle.a
+fi
 AC_MSG_CHECKING([for SHA1 implementation])
 if test "x$with_sha1" = x; then
        AC_MSG_ERROR([No suitable SHA1 implementation found])
@@ -1758,6 +1773,7 @@ if test "x$XORG" = xyes; then
        AC_DEFINE_DIR(XF86CONFIGFILE, XF86CONFIGFILE, [Name of configuration file])
        AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory])
        AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path])
+       AC_DEFINE_DIR(EXTRA_MODULE_PATH, extra_moduledir, [Extra module search path, searched before the default one])
        AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path])
        AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location])
        AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
@@ -2139,6 +2155,25 @@ AC_SUBST([prefix])
 
 AC_CONFIG_COMMANDS([sdksyms], [touch hw/xfree86/sdksyms.dep])
 
+AC_PROG_CXX
+
+PKG_CHECK_MODULES(XORG_GTEST, xorg-gtest,
+        [have_xorg_gtest="yes"],
+        [AC_MSG_WARN([xorg-gtest not installed, tests will not be built])])
+AM_CONDITIONAL([HAVE_XORG_GTEST], [test "x$have_xorg_gtest" = xyes])
+AC_SUBST([XORG_GTEST_CFLAGS])
+AC_SUBST([XORG_GTEST_LIBS])
+
+PKG_CHECK_MODULES([XFIXES], xfixes, [have_xfixes="yes"], [have_xfixes="no"])
+AM_CONDITIONAL([HAVE_XFIXES], [test "x$have_xfixes" = xyes])
+AC_SUBST([XFIXES_CFLAGS])
+AC_SUBST([XFIXES_LIBS])
+
+PKG_CHECK_MODULES([XTEST], xtst, [have_xtest="yes"], [have_xtest="no"])
+AM_CONDITIONAL([HAVE_XTEST], [test "x$have_xtest" = xyes])
+AC_SUBST([XTEST_CFLAGS])
+AC_SUBST([XTEST_LIBS])
+
 AC_OUTPUT([
 Makefile
 glx/Makefile
@@ -2238,6 +2273,7 @@ hw/kdrive/linux/Makefile
 hw/kdrive/src/Makefile
 test/Makefile
 test/xi2/Makefile
+test/gtest/Makefile
 xserver.ent
 xorg-server.pc
 ])
index 8f910f4a93ad1e0d7087993bb8af4a850916e1e4..5a0aa31160f4804a1d713469daede9de83cf55ff 100644 (file)
@@ -215,7 +215,7 @@ UpdateCurrentTimeIf(void)
     systime.milliseconds = GetTimeInMillis();
     if (systime.milliseconds < currentTime.milliseconds)
        systime.months++;
-    if (*checkForInput[0] == *checkForInput[1])
+    if (CompareTimeStamps(systime, currentTime) == LATER)
        currentTime = systime;
 }
 
@@ -408,6 +408,9 @@ Dispatch(void)
                }
                /* now, finally, deal with client requests */
 
+                /* Update currentTime so request time checks, such as for input
+                 * device grabs, are calculated correctly */
+                UpdateCurrentTimeIf();
                result = ReadRequestFromClient(client);
                if (result <= 0) 
                {
index cfb03974d8d5595bca9717227d12583314885ff8..08d9d1b1b1473b63eba87ba8f4ebe8f94c8100ba 100644 (file)
@@ -224,7 +224,15 @@ dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
 {
     int rc;
     rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access);
-    return (rc == BadDrawable) ? BadWindow : rc;
+    /* dixLookupDrawable returns BadMatch iff id is a valid Drawable
+       but is not a Window. Users of dixLookupWindow expect a BadWindow
+       error in this case; they don't care that it's a valid non-Window XID */
+    if (rc == BadMatch)
+       rc = BadWindow;
+    /* Similarly, users of dixLookupWindow don't want BadDrawable. */
+    if (rc == BadDrawable)
+       rc = BadWindow;
+    return rc;
 }
 
 int
@@ -529,7 +537,7 @@ ProcessWorkQueue(void)
        {
            /* remove q from the list */
            *p = q->next;    /* don't fetch until after func called */
-           free(q);
+           (*q->destroyProc) (q);
        }
        else
        {
@@ -552,7 +560,7 @@ ProcessWorkQueueZombies(void)
            (void) (*q->function) (q->client, q->closure);
            /* remove q from the list */
            *p = q->next;    /* don't fetch until after func called */
-           free(q);
+           (*q->destroyProc) (q);
        }
        else
        {
@@ -562,6 +570,12 @@ ProcessWorkQueueZombies(void)
     workQueueLast = p;
 }
 
+static void
+FreeWorkQueueItem (WorkQueuePtr this)
+{
+    free(this);
+}
+
 Bool
 QueueWorkProc (
     Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
@@ -575,12 +589,22 @@ QueueWorkProc (
     q->function = function;
     q->client = client;
     q->closure = closure;
+    q->destroyProc = FreeWorkQueueItem;
     q->next = NULL;
     *workQueueLast = q;
     workQueueLast = &q->next;
     return TRUE;
 }
 
+Bool
+QueueWorkItem (WorkQueuePtr item)
+{
+    item->next = NULL;
+    *workQueueLast = item;
+    workQueueLast = &item->next;
+    return TRUE;
+}
+
 /*
  * Manage a queue of sleeping clients, awakening them
  * when requested, by using the OS functions IgnoreClient
index 01952551cd0906e08d47d955c15822568ba21693..6e64197a83ad747fe96f8a79b0d00a4574516f9b 100644 (file)
@@ -1312,14 +1312,10 @@ ComputeFreezes(void)
         {
             if (IsTouchEvent((InternalEvent*)event))
             {
-                InternalEvent *events = InitEventList(GetMaximumEventsNum());
-                int i, nev;
                 TouchPointInfoPtr ti = TouchFindByClientID(replayDev, event->touchid);
                 BUG_WARN(!ti);
-                nev = GetTouchOwnershipEvents(events, replayDev, ti, XIRejectTouch, ti->listeners[0].listener, 0);
-                for (i = 0; i < nev; i++)
-                    mieqProcessDeviceEvent(replayDev, events + i, NULL);
-                ProcessInputEvents();
+
+                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
             } else if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
                 DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
             else
@@ -1458,6 +1454,38 @@ ReattachToOldMaster(DeviceIntPtr dev)
     }
 }
 
+/**
+ * Update touch records when an explicit grab is activated. Any touches owned by
+ * the grabbing client are updated so the listener state reflects the new grab.
+ */
+static void
+UpdateTouchesForGrab(DeviceIntPtr mouse)
+{
+    int i;
+
+    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
+        return;
+
+    for (i = 0; i < mouse->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = mouse->touch->touches + i;
+        GrabPtr grab = mouse->deviceGrab.grab;
+
+        if (ti->active &&
+            CLIENT_BITS(ti->listeners[0].listener) == grab->resource) {
+            ti->listeners[0].listener = grab->resource;
+            ti->listeners[0].level = grab->grabtype;
+            ti->listeners[0].state = LISTENER_IS_OWNER;
+            ti->listeners[0].window = grab->window;
+
+            if (grab->grabtype == CORE || grab->grabtype == XI ||
+                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
+                ti->listeners[0].type = LISTENER_POINTER_GRAB;
+            else
+                ti->listeners[0].type = LISTENER_GRAB;
+        }
+    }
+}
+
 /**
  * Activate a pointer grab on the given device. A pointer grab will cause all
  * core pointer events of this device to be delivered to the grabbing client only.
@@ -1509,6 +1537,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
     grabinfo->fromPassiveGrab = isPassive;
     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
     PostNewCursor(mouse);
+    UpdateTouchesForGrab(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
 
@@ -1524,6 +1553,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     DeviceIntPtr dev;
     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
                         mouse->deviceGrab.implicitGrab);
+    XID grab_resource = grab->resource;
+    int i;
 
     TouchRemovePointerGrab(mouse);
 
@@ -1549,6 +1580,15 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
         ReattachToOldMaster(mouse);
 
     ComputeFreezes();
+
+    /* If an explicit grab was deactivated, we must remove it from the head of
+     * all the touches' listener lists. */
+    for (i = 0; mouse->touch && i < mouse->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = mouse->touch->touches + i;
+
+        if (ti->active && TouchResourceIsOwner(ti, grab_resource))
+            TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
+    }
 }
 
 /**
@@ -5309,8 +5349,7 @@ ProcQueryPointer(ClientPtr client)
     memset(&rep, 0, sizeof(xQueryPointerReply));
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
-    rep.mask = mouse->button ? (mouse->button->state) : 0;
-    rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
+    rep.mask = event_get_corestate(mouse, keyboard);
     rep.length = 0;
     rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
     rep.rootX = pSprite->hot.x;
index fd5998d7e6475de46072f84346bd56f91c76e55b..9be7430462dacb20d653a6816da81de32b986487 100644 (file)
  */
 InternalEvent* InputEventList = NULL;
 
+/**
+ * xfixes/cursor.c wants the unclamped (x,y) values for velocity
+ * calculation.  Export them here.
+ */
+int unclamped_prex = -1, unclamped_prey = -1;
+
 /**
  * Pick some arbitrary size for Xi motion history.
  */
@@ -911,7 +917,15 @@ positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
     /* miPointerSetPosition takes care of crossing screens for us, as well as
      * clipping to the current screen. Coordinates returned are in desktop
      * coord system */
+    /**
+     * Hack to pass the unclipped values through to the pointer barrier code.
+     * Required (for now) to calculate the velocity.
+     */
+    unclamped_prex = (int)floor(*screenx) - scr->x;
+    unclamped_prey = (int)floor(*screeny) - scr->y;
     scr = miPointerSetPosition(dev, mode, screenx, screeny);
+    unclamped_prex = -1;
+    unclamped_prey = -1;
 
     /* If we were constrained, rescale x/y from the screen coordinates so
      * the device valuators reflect the correct position. For screen
@@ -1579,6 +1593,9 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
     /* Now turn the smooth-scrolling axes back into emulated button presses
      * for legacy clients, based on the integer delta between before and now */
     for (i = 0; i < valuator_mask_size(&mask); i++) {
+        if (i >= pDev->valuator->numAxes)
+            break;
+
         if (!valuator_mask_isset(&mask, i))
             continue;
 
index 0aa24f293d6c9ea630dbcd1f61daceaaacf15fa2..8c13c758621e91ce3b76e9f5e718200f6d82c260 100644 (file)
@@ -375,13 +375,6 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
     if (ti->emulate_pointer)
     {
         GrabPtr grab;
-        DeviceEvent ev;
-        memset(&ev, 0, sizeof(ev));
-        ev.type = ET_TouchEnd;
-        ev.detail.button = 1;
-        ev.touchid = ti->client_id;
-        ev.flags = TOUCH_POINTER_EMULATED|TOUCH_END;
-        UpdateDeviceState(dev, &ev);
 
         if ((grab = dev->deviceGrab.grab))
         {
@@ -496,10 +489,22 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
     flags = TOUCH_CLIENT_ID|TOUCH_REPLAYING;
     if (ti->emulate_pointer)
         flags |= TOUCH_POINTER_EMULATED;
-    /* send fake begin event to next owner */
+    /* Generate events based on a fake touch begin event to get DCCE events if
+     * needed */
+    /* FIXME: This needs to be cleaned up */
     nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
-    for (i = 0; i < nev; i++)
-        DeliverTouchEvents(dev, ti, tel + i, resource);
+    for (i = 0; i < nev; i++) {
+        /* Send saved touch begin event */
+        if (tel[i].any.type == ET_TouchBegin) {
+            DeviceEvent *ev = &ti->history[0];
+            ev->flags |= TOUCH_REPLAYING;
+            DeliverTouchEvents(dev, ti, (InternalEvent*)ev, resource);
+        }
+        else {/* Send DCCE event */
+            tel[i].any.time = ti->history[0].time;
+            DeliverTouchEvents(dev, ti, tel + i, resource);
+        }
+    }
 
     valuator_mask_free(&mask);
     FreeEventList(tel, GetMaximumEventsNum());
@@ -558,22 +563,12 @@ TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
  * TouchBegin events.
  */
 Bool
-TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                  InternalEvent *ev)
+TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+                 InternalEvent *ev)
 {
     TouchClassPtr t = sourcedev->touch;
     SpritePtr sprite = &ti->sprite;
 
-    /* We may not have a sprite if there are no applicable grabs or
-     * event selections, or if they've disappeared, or if all the grab
-     * owners have rejected the touch.  Don't bother delivering motion
-     * events if not, but TouchEnd events still need to be processed so
-     * we can call FinishTouchPoint and release it for later use. */
-    if (ev->any.type == ET_TouchEnd)
-        return TRUE;
-    else if (ev->any.type != ET_TouchBegin)
-        return (sprite->spriteTraceGood > 0);
-
     if (t->mode == XIDirectTouch)
     {
         /* Focus immediately under the touchpoint in direct touch mode.
@@ -844,6 +839,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
     {
         int coretype = GetCoreType(TouchGetPointerEventType(ev));
         Mask core_filter = event_get_filter_from_type(dev, coretype);
+        OtherClients *oclients;
 
         /* window owner */
         if (IsMaster(dev) && (win->eventMask & core_filter))
@@ -856,13 +852,12 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
         }
 
         /* all others */
-        nt_list_for_each_entry(iclients, (InputClients*)wOtherClients(win), next)
-        {
-            if (!(iclients->mask[XIAllDevices] & core_filter))
+        nt_list_for_each_entry(oclients, wOtherClients(win), next) {
+            if (!(oclients->mask & core_filter))
                 continue;
 
             TouchEventHistoryAllocate(ti);
-            TouchAddListener(ti, iclients->resource, CORE,
+            TouchAddListener(ti, oclients->resource, CORE,
                              type, LISTENER_AWAITING_BEGIN, win);
             return TRUE;
         }
@@ -897,6 +892,11 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
     if (dev->deviceGrab.grab)
         TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
 
+    /* We set up an active touch listener for existing touches, but not any
+     * passive grab or regular listeners. */
+    if (ev->any.type != ET_TouchBegin)
+        return;
+
     /* First, find all grabbing clients from the root window down
      * to the deepest child window. */
     for (i = 0; i < sprite->spriteTraceGood; i++)
@@ -987,16 +987,49 @@ TouchListenerGone(XID resource)
     FreeEventList(events, GetMaximumEventsNum());
 }
 
+int
+TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener,
+                          int mode)
+{
+    InternalEvent *events;
+    int nev;
+    int i;
+
+    if (listener > 0) {
+        if (mode == XIRejectTouch)
+            TouchRejected(dev, ti, ti->listeners[listener].listener, NULL);
+        else
+            ti->listeners[listener].state = LISTENER_EARLY_ACCEPT;
+
+        return Success;
+    }
+
+    events = InitEventList(GetMaximumEventsNum());
+    if (!events) {
+        BUG_WARN_MSG(TRUE, "Failed to allocate touch ownership events\n");
+        return BadAlloc;
+    }
+
+    nev = GetTouchOwnershipEvents(events, dev, ti, mode,
+                                  ti->listeners[0].listener, 0);
+    BUG_WARN_MSG(nev == 0, "Failed to get touch ownership events\n");
+
+    for (i = 0; i < nev; i++)
+        mieqProcessDeviceEvent(dev, events + i, NULL);
+
+    ProcessInputEvents();
+
+    FreeEventList(events, GetMaximumEventsNum());
+
+    return nev ? Success : BadMatch;
+}
+
 int
 TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
                   uint32_t touchid, Window grab_window, XID *error)
 {
     TouchPointInfoPtr ti;
-    int nev, i;
-    InternalEvent *events = InitEventList(GetMaximumEventsNum());
-
-    if (!events)
-        return BadAlloc;
+    int i;
 
     if (!dev->touch)
     {
@@ -1020,25 +1053,5 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
     if (i == ti->num_listeners)
         return BadAccess;
 
-    if (i > 0)
-    {
-        if (mode == XIRejectTouch)
-            TouchRejected(dev, ti, ti->listeners[i].listener, NULL);
-        else
-            ti->listeners[i].state = LISTENER_EARLY_ACCEPT;
-
-        return Success;
-    }
-
-    nev = GetTouchOwnershipEvents(events, dev, ti, mode,
-                                  ti->listeners[0].listener, 0);
-    if (nev == 0)
-        return BadAlloc;
-    for (i = 0; i < nev; i++)
-        mieqProcessDeviceEvent(dev, events + i, NULL);
-
-    ProcessInputEvents();
-
-    FreeEventList(events, GetMaximumEventsNum());
-    return Success;
+    return TouchListenerAcceptReject(dev, ti, i, mode);
 }
index 70de4bd6f04c545ed2a6176f99d8f523039221da..60aa32882f1e38c0c90c7238c4b655014675625c 100644 (file)
@@ -206,6 +206,7 @@ typedef struct {
     RegionRec srcReg;
     RegionRec maskReg;
     PixmapPtr srcPix;
+    PixmapPtr maskPix;
 
 } ExaScreenPrivRec, *ExaScreenPrivPtr;
 
index 219f903b2cb3e9750220d120c48f384a33fda714..7d83d150fdaaa25906a94605cf95f28e3109c4a8 100644 (file)
@@ -448,6 +448,13 @@ ExaSrcValidate(DrawablePtr pDrawable,
     RegionPtr dst;
     int xoff, yoff;
 
+    if (pExaScr->srcPix == pPix)
+        dst = &pExaScr->srcReg;
+    else if (pExaScr->maskPix == pPix)
+        dst = &pExaScr->maskReg;
+    else
+        return;
+
     exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
 
     box.x1 = x + xoff;
@@ -455,9 +462,6 @@ ExaSrcValidate(DrawablePtr pDrawable,
     box.x2 = box.x1 + width;
     box.y2 = box.y1 + height;
 
-    dst = (pExaScr->srcPix == pPix) ? &pExaScr->srcReg :
-       &pExaScr->maskReg;
-
     RegionInit(&reg, &box, 1);
     RegionUnion(dst, dst, &reg);
     RegionUninit(&reg);
@@ -506,17 +510,20 @@ ExaPrepareCompositeReg(ScreenPtr  pScreen,
            RegionTranslate(pSrc->pCompositeClip,
                             -pSrc->pDrawable->x,
                             -pSrc->pDrawable->y);
-    }
+    } else
+        pExaScr->srcPix = NULL;
 
     if (pMask && pMask->pDrawable) {
        pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
        RegionNull(&pExaScr->maskReg);
        maskReg = &pExaScr->maskReg;
+       pExaScr->maskPix = pMaskPix;
        if (pMask != pDst && pMask != pSrc)
            RegionTranslate(pMask->pCompositeClip,
                             -pMask->pDrawable->x,
                             -pMask->pDrawable->y);
-    }
+    } else
+        pExaScr->maskPix = NULL;
 
     RegionTranslate(pDst->pCompositeClip,
                     -pDst->pDrawable->x,
index 9149e0db16b3557f11705b6944c48efe39979570..f601f744356019dcf1d3554da26d76b823dec0aa 100644 (file)
@@ -217,6 +217,7 @@ glxProbeDriver(const char *driverName,
     void *driver;
     char filename[PATH_MAX];
     const __DRIextension **extensions;
+    int from = X_ERROR;
 
     snprintf(filename, sizeof filename, "%s/%s_dri.so",
              dri_driver_path, driverName);
@@ -248,7 +249,9 @@ glxProbeDriver(const char *driverName,
     }
 
     if (*coreExt == NULL || *renderExt == NULL) {
-       LogMessage(X_ERROR,
+       if (!strcmp(driverName, "nouveau"))
+           from = X_INFO;
+       LogMessage(from,
                   "AIGLX error: %s does not export required DRI extension\n",
                   driverName);
        goto cleanup_failure;
index bc1509b35eddb2e1b56c4d808f5d5c9c475b3218..5d48f2a665eb40fe234963b25a428f2f00b70327 100644 (file)
@@ -821,7 +821,7 @@ static void dmxSetDefaultFontPath(char *fp)
 /** This function is called in Xserver/os/utils.c from \a AbortServer().
  * We must ensure that backend and console state is restored in the
  * event the server shutdown wasn't clean. */
-void AbortDDX(enum ExitCode error)
+void SigAbortDDX(int signo, enum ExitCode error)
 {
     int i;
 
@@ -839,6 +839,11 @@ void ddxBeforeReset(void)
 }
 #endif
 
+void AbortDDX(enum ExitCode error)
+{
+    SigAbortDDX(0, error);
+}
+
 /** This function is called in Xserver/dix/main.c from \a main() when
  * dispatchException & DE_TERMINATE (which is the only way to exit the
  * main loop without an interruption. */
index 8dd039e1d176d8d6b7faeeddda368f87f83cbb47..b6d35662b2f52b37f84564120a9d77782165ffba 100644 (file)
@@ -232,7 +232,7 @@ KdProcessSwitch (void)
 }
 
 void
-AbortDDX(enum ExitCode error)
+SigAbortDDX(int signo, enum ExitCode error)
 {
     KdDisableScreens ();
     if (kdOsFuncs)
@@ -248,6 +248,11 @@ AbortDDX(enum ExitCode error)
         OsAbort();
 }
 
+AbortDDX(enum ExitCode error)
+{
+    SigAbortDDX(0, error);
+}
+
 void
 ddxGiveUp (enum ExitCode error)
 {
index c17f12c3834b098be57f05587cf77b22954eae47..1ab6749106cd62692c4400cfcf0200a1d226ca7d 100644 (file)
@@ -201,11 +201,17 @@ ddxGiveUp(enum ExitCode error)
 }
 
 void
-AbortDDX(enum ExitCode error)
+SigAbortDDX(int signo, enum ExitCode error)
 {
     ddxGiveUp(error);
 }
-
+void
+AbortDDX(enum ExitCode error)
+{
+    SigAbortDDX(0, error);
+}
 #ifdef __APPLE__
 void
 DarwinHandleGUI(int argc, char *argv[])
index 450502670286a6b449763ee1afebd1c30f494a6e..282b2f78fd6a645e23db09aae4d6a05130c44aad 100644 (file)
@@ -3,16 +3,75 @@
 //
 // $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.5 2002/06/05 19:43:05 dawes Exp $
 //
+// NOTE:  Please keep all video modes sorted in order of X res, then Y res for
+//        ease of maintenance and readability.
 
 # 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz
 ModeLine "832x624" 57.284 832  864  928 1152  624  625  628  667 -Hsync -Vsync
 
+# 1152x864 @ 60.00 Hz (GTF) hsync: 53.70 kHz; pclk: 81.62 MHz
+Modeline "1152x864"  81.62  1152 1216 1336 1520  864 865 868 895  -HSync +Vsync
+
+# 1152x864 @ 70.00 Hz (GTF) hsync: 63.00 kHz; pclk: 96.77 MHz
+Modeline "1152x864"  96.77  1152 1224 1344 1536  864 865 868 900  -HSync +Vsync
+
+# 1152x864 @ 75.00 Hz (GTF) hsync: 67.65 kHz; pclk: 104.99 MHz
+Modeline "1152x864"  104.99  1152 1224 1352 1552  864 865 868 902  -HSync +Vsync
+
+# 1152x864 @ 85.00 Hz (GTF) hsync: 77.10 kHz; pclk: 119.65 MHz
+Modeline "1152x864"  119.65  1152 1224 1352 1552  864 865 868 907  -HSync +Vsync
+
+# 1152x864 @ 85Hz (Red Hat custom modeline)
+ModeLine "1152x864"  121.5 1152 1216 1344 1568    864  865  868  911 +hsync -vsync
+
+# 1152x864 @ 100.00 Hz (GTF) hsync: 91.50 kHz; pclk: 143.47 MHz
+Modeline "1152x864"  143.47  1152 1232 1360 1568  864 865 868 915  -HSync +Vsync
+
+# 1360x768 59.96 Hz (CVT) hsync: 47.37 kHz; pclk: 72.00 MHz
+Modeline "1360x768"   72.00  1360 1408 1440 1520  768 771 781 790 +hsync -vsync
+
+# 1360x768 59.80 Hz (CVT) hsync: 47.72 kHz; pclk: 84.75 MHz
+Modeline "1360x768"   84.75  1360 1432 1568 1776  768 771 781 798 -hsync +vsync
+
 # 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz
 ModeLine "1400x1050" 122.0 1400 1488 1640 1880   1050 1052 1064 1082 +hsync +vsync
 
+# 1400x1050 @ 70.00 Hz (GTF) hsync: 76.51 kHz; pclk: 145.06 MHz
+Modeline "1400x1050"  145.06  1400 1496 1648 1896  1050 1051 1054 1093  -HSync +Vsync
+
 # 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz
 ModeLine "1400x1050" 155.8 1400 1464 1784 1912   1050 1052 1064 1090 +hsync +vsync
 
+# 1400x1050 @ 85.00 Hz (GTF) hsync: 93.76 kHz; pclk: 179.26 MHz
+Modeline "1400x1050"  179.26  1400 1504 1656 1912  1050 1051 1054 1103  -HSync +Vsync
+
+# 1440x900 @ 60.00 Hz (CVT) field rate 59.89 Hz; hsync: 55.93 kHz; pclk: 106.50 MHz
+Modeline "1440x900"  106.50  1440 1520 1672 1904  900 903 909 934  -HSync +Vsync
+
+# 1600x1024 for SGI 1600 SW
+ModeLine "1600x1024" 103.125 1600 1600 1656 1664 1024 1024 1029 1030 +Hsync +Vsync
+
+# 1680x1050 59.88 Hz (CVT 1.76MA-R) hsync: 64.67 kHz; pclk: 119.00 MHz
+Modeline "1680x1050"  119.00  1680 1728 1760 1840  1050 1053 1059 1080 +hsync -vsync
+
+# 1680x1050 59.95 Hz (CVT 1.76MA) hsync: 65.29 kHz; pclk: 146.25 MHz
+Modeline "1680x1050"  146.25  1680 1784 1960 2240  1050 1053 1059 1089 -hsync +vsync
+
+# 1680x1050 69.88 Hz (CVT) hsync: 76.58 kHz; pclk: 174.00 MHz
+Modeline "1680x1050"  174.00  1680 1800 1976 2272  1050 1053 1059 1096 -hsync +vsync
+
+# 1680x1050 74.89 Hz (CVT 1.76MA) hsync: 82.31 kHz; pclk: 187.00 MHz
+Modeline "1680x1050"  187.00  1680 1800 1976 2272  1050 1053 1059 1099 -hsync +vsync
+
+# 1680x1050 84.94 Hz (CVT 1.76MA) hsync: 93.86 kHz; pclk: 214.75 MHz
+Modeline "1680x1050"  214.75  1680 1808 1984 2288  1050 1053 1059 1105 -hsync +vsync
+
+# 1920x1080 59.93 Hz (CVT 2.07M9-R) hsync: 66.59 kHz; pclk: 138.50 MHz
+Modeline "1920x1080"  138.50  1920 1968 2000 2080  1080 1083 1088 1111 +hsync -vsync
+
+# 1920x1200 59.95 Hz (CVT 2.30MA-R) hsync: 74.04 kHz; pclk: 154.00 MHz
+Modeline "1920x1200"  154.00  1920 1968 2000 2080  1200 1203 1209 1235 +hsync -vsync
+
 # 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz
 Modeline "1920x1440" 341.35  1920 2072 2288 2656  1440 1441 1444 1512 -hsync +vsync
 
index 5c6e7210cb76bd62d3d0597b5f139d8e826b17ee..f0e3f4767086cdf917efb30319f82d6c2db8be56 100644 (file)
 # include "xf86sbusBus.h"
 #endif
 
+#if defined(__arm__) && defined(__linux__)
+# include "loaderProcs.h"
+# include <sys/types.h> /* For opendir in test_sysfs_device */
+# include <dirent.h>    /* For opendir in test_sysfs_device */
+#endif
+
 #ifdef sun
 # include <sys/visual_io.h>
 # include <ctype.h>
        "\tDevice\t" BUILTIN_DEVICE_NAME "\n" \
        "EndSection\n\n"
 
+#define BUILTIN_SCREEN_SECTION_PROPRIETARY \
+       "Section \"Screen\"\n" \
+       "\tIdentifier\t" BUILTIN_SCREEN_NAME "\n" \
+       "\tDevice\t" BUILTIN_DEVICE_NAME "\n" \
+       "\tDefaultDepth\t24\n" \
+       "EndSection\n\n"
+
 #define BUILTIN_LAYOUT_SECTION_PRE \
        "Section \"ServerLayout\"\n" \
        "\tIdentifier\t\"Builtin Default Layout\"\n"
@@ -153,7 +166,10 @@ xf86AutoConfig(void)
     for (p = deviceList; *p; p++) {
        snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION, *p, 0, *p);
        AppendToConfig(buf);
-       snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, *p, 0, *p, 0);
+       if( strcmp(*p, "fglrx") == 0 || strcmp(*p, "nvidia") == 0)
+               snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION_PROPRIETARY, *p, 0, *p, 0);
+       else
+               snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, *p, 0, *p, 0);
        AppendToConfig(buf);
     }
 
@@ -188,6 +204,26 @@ xf86AutoConfig(void)
     return ret == CONFIG_OK;
 }
 
+#if defined(__arm__) && defined(__linux__)
+static int
+test_sysfs_device (char * device_name, char * driver_name)
+{
+    DIR* dir = opendir("/sys/devices/platform");
+    struct dirent *current_dir;
+    int len = strlen(device_name);
+
+    while (current_dir = readdir(dir)) {
+        if (strlen(current_dir->d_name) >= len && strncmp(device_name, current_dir->d_name, len) == 0)
+            break;
+    }
+    closedir(dir);
+    if(!current_dir)
+        return 0;
+
+    return 1;
+}
+#endif /* defined(__arm__) && defined(__linux__) */
+
 static void
 listPossibleVideoDrivers(char *matches[], int nmatches)
 {
@@ -272,6 +308,17 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
 #if !defined(__linux__) && defined(__sparc__)
        matches[i++] = xnfstrdup("wsfb");
 #else
+#if defined(__linux__) && defined(__arm__)
+        if (test_sysfs_device("mxc_gpu", "imx"))
+           matches[i++] = xnfstrdup("imx");
+        else if (test_sysfs_device("dovefb", "dovefb"))
+           matches[i++] = xnfstrdup("dovefb");
+        else if (test_sysfs_device("omap", "pvr")) {
+           matches[i++] = xnfstrdup("pvr");
+           matches[i++] = xnfstrdup("omap");
+        } else if (test_sysfs_device("omapfb", "omapfb"))
+           matches[i++] = xnfstrdup("omapfb");
+#endif /* defined(__linux__) && defined(__arm__) */
        matches[i++] = xnfstrdup("fbdev");
 #endif
     }
index b831d9a91c4a35f4ed0c27807f09c82ab95b4af4..b43db43499614d5d25682f30f6c28421ee7464ae 100644 (file)
@@ -72,8 +72,8 @@
  * These paths define the way the config file search is done.  The escape
  * sequences are documented in parser/scan.c.
  */
-#ifndef ROOT_CONFIGPATH
-#define ROOT_CONFIGPATH        "%A," "%R," \
+#ifndef ALL_CONFIGPATH
+#define ALL_CONFIGPATH "%A," "%R," \
                        "/etc/X11/%R," "%P/etc/X11/%R," \
                        "%E," "%F," \
                        "/etc/X11/%F," "%P/etc/X11/%F," \
@@ -83,8 +83,8 @@
                        "%P/lib/X11/%X.%H," \
                        "%P/lib/X11/%X"
 #endif
-#ifndef USER_CONFIGPATH
-#define USER_CONFIGPATH        "/etc/X11/%S," "%P/etc/X11/%S," \
+#ifndef RESTRICTED_CONFIGPATH
+#define RESTRICTED_CONFIGPATH  "/etc/X11/%S," "%P/etc/X11/%S," \
                        "/etc/X11/%G," "%P/etc/X11/%G," \
                        "/etc/X11/%X," "/etc/%X," \
                        "%P/etc/X11/%X.%H," \
                        "%P/lib/X11/%X.%H," \
                        "%P/lib/X11/%X"
 #endif
-#ifndef ROOT_CONFIGDIRPATH
-#define ROOT_CONFIGDIRPATH     "%A," "%R," \
+#ifndef ALL_CONFIGDIRPATH
+#define ALL_CONFIGDIRPATH      "%A," "%R," \
                                "/etc/X11/%R," "%C/X11/%R," \
                                "/etc/X11/%X," "%C/X11/%X"
 #endif
-#ifndef USER_CONFIGDIRPATH
-#define USER_CONFIGDIRPATH     "/etc/X11/%R," "%C/X11/%R," \
-                               "/etc/X11/%X," "%C/X11/%X"
+#ifndef RESTRICTED_CONFIGDIRPATH
+#define RESTRICTED_CONFIGDIRPATH       "/etc/X11/%R," "%C/X11/%R," \
+                                       "/etc/X11/%X," "%C/X11/%X"
 #endif
 #ifndef SYS_CONFIGDIRPATH
 #define SYS_CONFIGDIRPATH      "/usr/share/X11/%X," "%D/X11/%X"
@@ -628,11 +628,21 @@ configFiles(XF86ConfFilesPtr fileconf)
   
   /* ModulePath */
 
-  if (fileconf) {
-    if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) {
+  if (xf86ModPathFrom != X_CMDLINE) {
+    if (fileconf && fileconf->file_modulepath) {
       xf86ModulePath = fileconf->file_modulepath;
       xf86ModPathFrom = X_CONFIG;
     }
+    else if (strcmp(xf86ExtraModulePath, "") != 0) {
+      char *newpath = malloc(strlen(xf86ExtraModulePath)
+                            + strlen(xf86ModulePath)
+                            + 2);
+      strcpy(newpath, xf86ExtraModulePath);
+      strcat(newpath, ",");
+      strcat(newpath, xf86ModulePath);
+
+      xf86ModulePath = newpath;
+    }
   }
 
   xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath);
@@ -2343,12 +2353,12 @@ xf86HandleConfigFile(Bool autoconfig)
     Bool implicit_layout = FALSE;
 
     if (!autoconfig) {
-       if (getuid() == 0) {
-           filesearch = ROOT_CONFIGPATH;
-           dirsearch = ROOT_CONFIGDIRPATH;
+       if (!xf86PrivsElevated()) {
+           filesearch = ALL_CONFIGPATH;
+           dirsearch = ALL_CONFIGDIRPATH;
        } else {
-           filesearch = USER_CONFIGPATH;
-           dirsearch = USER_CONFIGDIRPATH;
+           filesearch = RESTRICTED_CONFIGPATH;
+           dirsearch = RESTRICTED_CONFIGDIRPATH;
        }
 
        if (xf86ConfigFile)
index 41ffabde36674db53b517cf03d092b5a2f8fbb4a..3718767a4122b3bb685dc5a7636f15e6518b0e03 100644 (file)
@@ -270,10 +270,10 @@ xf86Wakeup(pointer blockData, int err, pointer pReadmask)
        }
     }
 
-    if (err >= 0) { /* we don't want the handlers called if select() */
-       IHPtr ih;   /* returned with an error condition, do we?      */
-       
-       for (ih = InputHandlers; ih; ih = ih->next) {
+    if (err >= 0) {       /* we don't want the handlers called if select() */
+        IHPtr ih, ih_tmp; /* returned with an error condition, do we?      */
+
+        nt_list_for_each_entry_safe(ih, ih_tmp, InputHandlers, next) {
            if (ih->enabled && ih->fd >= 0 && ih->ihproc &&
                (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) {
                ih->ihproc(ih->fd, ih->data);
@@ -348,6 +348,8 @@ xf86InterceptSigIll(void (*sigillhandler)(void))
 int
 xf86SigWrapper(int signo)
 {
+  static Bool beenhere = FALSE;
+
   if ((signo == SIGILL) && xf86SigIllHandler) {
     (*xf86SigIllHandler)();
     return 0; /* continue */
index 16d55577e5d8079f64ecf11a2ee7d354a8727c0d..beb7baba07004000d1f116e84abce05d06c6c311 100644 (file)
@@ -139,6 +139,7 @@ xf86InfoRec xf86Info = {
 const char *xf86ConfigFile = NULL;
 const char *xf86ConfigDir = NULL;
 const char *xf86ModulePath = DEFAULT_MODULE_PATH;
+const char *xf86ExtraModulePath = EXTRA_MODULE_PATH;
 MessageType xf86ModPathFrom = X_DEFAULT;
 const char *xf86LogFile = DEFAULT_LOGPREFIX;
 MessageType xf86LogFileFrom = X_DEFAULT;
@@ -155,6 +156,7 @@ int xf86NumDrivers = 0;
 InputDriverPtr *xf86InputDriverList = NULL;
 int xf86NumInputDrivers = 0;
 int xf86NumScreens = 0;
+Bool xf86AttemptedFallback = FALSE;
 
 const char *xf86VisualNames[] = {
        "StaticGray",
index f8e6c8b41a8e29959d86dac8f1ed0bca7e188767..8be78994c9dcb17902a40938f5051a1268a265de 100644 (file)
@@ -1036,25 +1036,13 @@ void
 xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
                va_list args)
 {
-    char *tmpFormat;
-
     /* Prefix the scrnIndex name to the format string. */
     if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
-       xf86Screens[scrnIndex]->name) {
-       tmpFormat = malloc(strlen(format) +
-                          strlen(xf86Screens[scrnIndex]->name) +
-                          PREFIX_SIZE + 1);
-       if (!tmpFormat)
-           return;
-
-       snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ",
-                xf86Screens[scrnIndex]->name, scrnIndex);
-
-       strcat(tmpFormat, format);
-       LogVMessageVerb(type, verb, tmpFormat, args);
-       free(tmpFormat);
-    } else
-       LogVMessageVerb(type, verb, format, args);
+        xf86Screens[scrnIndex]->name)
+        LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
+                          xf86Screens[scrnIndex]->name, scrnIndex);
+    else
+        LogVMessageVerb(type, verb, format, args);
 }
 #undef PREFIX_SIZE
 
@@ -1087,15 +1075,18 @@ void
 xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
                 va_list args)
 {
-    char *msg;
+    const char *driverName = NULL;
+    const char *deviceName = NULL;
 
-    if (asprintf(&msg, "%s: %s: %s", dev->drv->driverName, dev->name, format)
-       == -1) {
-       LogVMessageVerb(type, verb, "%s", args);
-    } else {
-       LogVMessageVerb(type, verb, msg, args);
-       free(msg);
+    /* Prefix driver and device names to formatted message. */
+    if (dev) {
+        deviceName = dev->name;
+        if (dev->drv)
+            driverName = dev->drv->driverName;
     }
+
+    LogHdrMessageVerb(type, verb, format, args, "%s: %s: ", driverName,
+                      deviceName);
 }
 
 /* Print input driver message, with verbose level specified directly */
index 5ee68cd2657cfe414c5ad2290fe4306e9f04a303..b5105cd893cfba4254c7cf01cd8f999fea0e5728 100644 (file)
@@ -236,6 +236,65 @@ xf86PrintMarkers(void)
   LogPrintMarkers();
 }
 
+Bool xf86PrivsElevated(void)
+{
+  static Bool privsTested = FALSE;
+  static Bool privsElevated = TRUE;
+
+  if (!privsTested) {
+#if defined(WIN32)
+    privsElevated = FALSE;
+#else
+    if ((getuid() != geteuid()) || (getgid() != getegid())) {
+      privsElevated = TRUE;
+    } else {
+#if defined(HAVE_ISSETUGID)
+      privsElevated = issetugid();
+#elif defined(HAVE_GETRESUID)
+      uid_t ruid, euid, suid;
+      gid_t rgid, egid, sgid;
+
+      if ((getresuid(&ruid, &euid, &suid) == 0) &&
+          (getresgid(&rgid, &egid, &sgid) == 0)) {
+        privsElevated = (euid != suid) || (egid != sgid);
+      }
+      else {
+        printf("Failed getresuid or getresgid");
+        /* Something went wrong, make defensive assumption */
+        privsElevated = TRUE;
+      }
+#else
+      if (getuid()==0) {
+        /* running as root: uid==euid==0 */
+        privsElevated = FALSE;
+      }
+      else {
+        /*
+         * If there are saved ID's the process might still be privileged
+         * even though the above test succeeded. If issetugid() and
+         * getresgid() aren't available, test this by trying to set
+         * euid to 0.
+         */
+        unsigned int oldeuid;
+        oldeuid = geteuid();
+
+        if (seteuid(0) != 0) {
+          privsElevated = FALSE;
+        } else {
+          if (seteuid(oldeuid) != 0) {
+            FatalError("Failed to drop privileges.  Exiting\n");
+          }
+          privsElevated = TRUE;
+        }
+      }
+#endif
+    }
+#endif
+    privsTested = TRUE;
+  }
+  return privsElevated;
+}
+
 static Bool
 xf86CreateRootWindow(WindowPtr pWin)
 {
@@ -411,20 +470,34 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
       free(optionlist);
     }
 
+Fallback:
     /* Load all driver modules specified in the config file */
     /* If there aren't any specified in the config file, autoconfig them */
     /* FIXME: Does not handle multiple active screen sections, but I'm not
      * sure if we really want to handle that case*/
     configured_device = xf86ConfigLayout.screens->screen->device;
-    if ((!configured_device) || (!configured_device->driver)) {
+    if (xf86AttemptedFallback) {
+        configured_device->driver = NULL;
+        if (!autoConfigDevice(configured_device)) {
+            xf86Msg(X_ERROR, "Auto configuration on fallback failed\n");
+            return;
+        }
+    }
+    else if ((!configured_device) || (!configured_device->driver)) {
         if (!autoConfigDevice(configured_device)) {
             xf86Msg(X_ERROR, "Automatic driver configuration failed\n");
             return ;
         }
     }
     if ((modulelist = xf86DriverlistFromConfig())) {
-      xf86LoadModules(modulelist, NULL);
-      free(modulelist);
+      if (!xf86LoadModules(modulelist, NULL) && !xf86AttemptedFallback) {
+          free(modulelist);
+          xf86AttemptedFallback = TRUE;
+          goto Fallback;
+      }
+      else {
+          free(modulelist);
+      }
     }
 
     /* Load all input driver modules specified in the config file. */
@@ -483,8 +556,15 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
     else
        xf86Info.dontVTSwitch = TRUE;
 
-    if (xf86BusConfig() == FALSE)
-        return;
+    if (xf86BusConfig() == FALSE) {
+        if (!xf86AttemptedFallback) {
+            xf86AttemptedFallback = TRUE;
+            goto Fallback;
+        }
+        else {
+            return;
+        }
+    }
 
     xf86PostProbe();
 
@@ -864,6 +944,9 @@ OsVendorInit(void)
 
   if (!beenHere) {
     umask(022);
+    /* have glibc report internal abort traces to stderr instead of
+       the controlling terminal */
+    setenv("LIBC_FATAL_STDERR_","1",0);
     xf86LogInit();
   }
 
@@ -877,7 +960,7 @@ OsVendorInit(void)
 
 #ifdef O_NONBLOCK
   if (!beenHere) {
-    if (geteuid() == 0 && getuid() != geteuid())
+    if (xf86PrivsElevated())
     {
       int status;
 
@@ -894,14 +977,17 @@ OsVendorInit(void)
 }
 
 /*
- * ddxGiveUp --
+ * ddxSigGiveUp --
  *      Device dependent cleanup. Called by by dix before normal server death.
  *      For SYSV386 we must switch the terminal back to normal mode. No error-
  *      checking here, since there should be restored as much as possible.
+ *
+ *      If a non-zero signo is passed, re-raise that signal rather than
+ *      calling abort().
  */
 
 void
-ddxGiveUp(enum ExitCode error)
+ddxSigGiveUp(int signo, enum ExitCode error)
 {
     int i;
 
@@ -928,24 +1014,46 @@ ddxGiveUp(enum ExitCode error)
     if (xorgHWOpenConsole)
        xf86CloseConsole();
 
+    ErrorF (" ddxSigGiveUp: Closing log\n");
+
     xf86CloseLog(error);
 
     /* If an unexpected signal was caught, dump a core for debugging */
-    if (xf86Info.caughtSignal)
-       OsAbort();
+    if (xf86Info.caughtSignal) {
+        if (signo != 0) {
+            raise(signo);
+        } else {
+            OsAbort();
+        }
+    }
 }
 
+/*
+ * ddxGiveUp --
+ *      Device dependent cleanup. Called by by dix before normal server death.
+ *      For SYSV386 we must switch the terminal back to normal mode. No error-
+ *      checking here, since there should be restored as much as possible.
+ */
+
+void
+ddxGiveUp(enum ExitCode error)
+{
+    ddxSigGiveUp(0, error);
+}
 
 
 /*
- * AbortDDX --
+ * SigAbortDDX --
  *      DDX - specific abort routine.  Called by AbortServer(). The attempt is
  *      made to restore all original setting of the displays. Also all devices
  *      are closed.
+ *
+ *      If a non-zero signo is passed, re-raise that signal rather than calling
+ *      abort()
  */
 
 void
-AbortDDX(enum ExitCode error)
+SigAbortDDX(int signo, enum ExitCode error)
 {
   int i;
 
@@ -978,7 +1086,20 @@ AbortDDX(enum ExitCode error)
    * This is needed for an abnormal server exit, since the normal exit stuff
    * MUST also be performed (i.e. the vt must be left in a defined state)
    */
-  ddxGiveUp(error);
+  ddxSigGiveUp(signo, error);
+}
+
+/*
+ * AbortDDX --
+ *      DDX - specific abort routine.  The attempt is made to restore
+ *      all original setting of the displays. Also all devices are
+ *      closed.
+ */
+
+void
+AbortDDX(enum ExitCode error)
+{
+    SigAbortDDX(0, error);
 }
 
 void
@@ -1048,10 +1169,11 @@ ddxProcessArgument(int argc, char **argv, int i)
       FatalError("Required argument to %s not specified\n", argv[i]);  \
     }
 
-  /* First the options that are only allowed for root */
+  /* First the options that are not allowed with elevated privileges */
   if (!strcmp(argv[i], "-modulepath") || !strcmp(argv[i], "-logfile")) {
-    if ( (geteuid() == 0) && (getuid() != 0) ) {
-      FatalError("The '%s' option can only be used by root.\n", argv[i]);
+    if (xf86PrivsElevated()) {
+      FatalError("The '%s' option cannot be used with "
+                 "elevated privileges.\n", argv[i]);
     }
     else if (!strcmp(argv[i], "-modulepath"))
     {
@@ -1079,9 +1201,9 @@ ddxProcessArgument(int argc, char **argv, int i)
   if (!strcmp(argv[i], "-config") || !strcmp(argv[i], "-xf86config"))
   {
     CHECK_FOR_REQUIRED_ARGUMENT();
-    if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) {
+    if (xf86PrivsElevated() && !xf86PathIsSafe(argv[i + 1])) {
       FatalError("\nInvalid argument for %s\n"
-         "\tFor non-root users, the file specified with %s must be\n"
+         "\tWith elevated privileges, the file specified with %s must be\n"
          "\ta relative path and must not contain any \"..\" elements.\n"
          "\tUsing default "__XCONFIGFILE__" search path.\n\n",
          argv[i], argv[i]);
@@ -1092,9 +1214,9 @@ ddxProcessArgument(int argc, char **argv, int i)
   if (!strcmp(argv[i], "-configdir"))
   {
     CHECK_FOR_REQUIRED_ARGUMENT();
-    if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) {
+    if (xf86PrivsElevated() && !xf86PathIsSafe(argv[i + 1])) {
       FatalError("\nInvalid argument for %s\n"
-         "\tFor non-root users, the file specified with %s must be\n"
+         "\tWith elevated privileges, the file specified with %s must be\n"
          "\ta relative path and must not contain any \"..\" elements.\n"
          "\tUsing default "__XCONFIGDIR__" search path.\n\n",
          argv[i], argv[i]);
@@ -1368,7 +1490,7 @@ ddxUseMsg(void)
   ErrorF("\n");
   ErrorF("\n");
   ErrorF("Device Dependent Usage\n");
-  if (getuid() == 0 || geteuid() != 0)
+  if (!xf86PrivsElevated())
   {
     ErrorF("-modulepath paths      specify the module search path\n");
     ErrorF("-logfile file          specify a log file name\n");
index 1fe3d7e0dc30a41e16fcdd046b9da3520f958f2f..fba23350d3b142890abcd1b6101cd077ee03e2ac 100644 (file)
@@ -75,6 +75,7 @@ extern _X_EXPORT  char *xf86ServerName;
 
 extern _X_EXPORT  xf86InfoRec xf86Info;
 extern _X_EXPORT  const char *xf86ModulePath;
+extern _X_EXPORT  const char *xf86ExtraModulePath;
 extern _X_EXPORT  MessageType xf86ModPathFrom;
 extern _X_EXPORT  const char *xf86LogFile;
 extern _X_EXPORT  MessageType xf86LogFileFrom;
@@ -86,6 +87,7 @@ extern _X_EXPORT  int xf86NumDrivers;
 extern _X_EXPORT  Bool xf86Resetting;
 extern _X_EXPORT  Bool xf86Initialising;
 extern _X_EXPORT  int xf86NumScreens;
+extern _X_EXPORT  Bool xf86AttemptedFallback;
 extern _X_EXPORT  const char *xf86VisualNames[];
 extern _X_EXPORT  int xf86Verbose;                 /* verbosity level */
 extern _X_EXPORT  int xf86LogVerbose;          /* log file verbosity level */
@@ -147,6 +149,7 @@ extern _X_EXPORT Bool xf86LoadModules(char **list, pointer *optlist);
 extern _X_EXPORT int xf86SetVerbosity(int verb);
 extern _X_EXPORT int xf86SetLogVerbosity(int verb);
 extern _X_EXPORT Bool xf86CallDriverProbe( struct _DriverRec * drv, Bool detect_only );
+extern _X_EXPORT Bool xf86PrivsElevated(void);
 
 #endif /* _NO_XF86_PROTOTYPES */
 
index 2ae5484e3369f454482a418d33e7c6b7ddcb3bc8..d419326c1870a7c5fdead39c4da844dd29e85648 100644 (file)
@@ -225,6 +225,9 @@ VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock)
            return FALSE;
 
     pVidMode = VMPTR(pScrn->pScreen);
+    if (pScrn->modes == NULL)
+        return FALSE;
+
     pVidMode->First = pScrn->modes;
     pVidMode->Next =  pVidMode->First->next;
 
index 447b19229aea5e84ec49f48ed1bfbbdaa366c87a..70b3952304a83f25e0a3e6be6c8bb7c1109d8c18 100644 (file)
@@ -147,8 +147,8 @@ xf86PciProbe(void)
                    primaryBus.id.pci = info;
                } else {
                    xf86Msg(X_NOTICE,
-                           "More than one possible primary device found\n");
-                   primaryBus.type ^= (BusType)(-1);
+                           "More than one possible primary device found.  Using first one seen.\n");
+                    break;
                }
            }
        }
@@ -1107,7 +1107,10 @@ videoPtrToDriverList(struct pci_device *dev,
        case 0x1142:                driverList[0] = "apm"; break;
        case 0xedd8:                driverList[0] = "ark"; break;
        case 0x1a03:                driverList[0] = "ast"; break;
-       case 0x1002:                driverList[0] = "ati"; break;
+       case 0x1002:
+           driverList[0] = "fglrx";
+           driverList[1] = "ati";
+           break;
        case 0x102c:                driverList[0] = "chips"; break;
        case 0x1013:                driverList[0] = "cirrus"; break;
        case 0x3d3d:                driverList[0] = "glint"; break;
@@ -1123,7 +1126,25 @@ videoPtrToDriverList(struct pci_device *dev,
            break;
        case 0x102b:                driverList[0] = "mga";      break;
        case 0x10c8:                driverList[0] = "neomagic"; break;
-       case 0x10de: case 0x12d2:   driverList[0] = "nv";       break;
+       case 0x10de: case 0x12d2:
+           driverList[0] = "nvidia";
+           switch (dev->device_id) {
+           /* NV1 */
+           case 0x0008:
+           case 0x0009:
+               driverList[1] = "vesa";
+               break;
+           /* NV3 */
+           case 0x0018:
+           case 0x0019:
+               driverList[1] = "nv";
+               break;
+           default:
+               driverList[1] = "nouveau";
+               driverList[2] = "nv";
+               break;
+           }
+           break;
        case 0x1106:                driverList[0] = "openchrome"; break;
         case 0x1b36:               driverList[0] = "qxl"; break;
        case 0x1163:                driverList[0] = "rendition"; break;
index e4c8bf25c081b940b409facf721cde6d4fc4cc21..dd62b891e9cf23971c9fe302291615c565cd15bc 100644 (file)
@@ -98,6 +98,9 @@ XisbRead (XISBuffer *b)
 {
        int ret;
 
+        if (b == NULL)
+            return -2;
+
        if (b->current >= b->end)
        {
                if (b->block_duration >= 0)
index f7f700004da8d827acb8453d723ee2105cddc832..471494a198845c7c1372c29682f4a0fe1db4330f 100644 (file)
@@ -91,6 +91,8 @@ typedef struct _DRI2Screen {
     int                                 refcnt;
     unsigned int                numDrivers;
     const char                 **driverNames;
+    unsigned int                numFormats;
+    unsigned int               *formats;
     const char                 *deviceName;
     int                                 fd;
     unsigned int                lastSequence;
@@ -102,12 +104,29 @@ typedef struct _DRI2Screen {
     DRI2GetMSCProcPtr           GetMSC;
     DRI2ScheduleWaitMSCProcPtr  ScheduleWaitMSC;
     DRI2AuthMagicProcPtr        AuthMagic;
+    DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
+    DRI2SwapLimitValidateProcPtr SwapLimitValidate;
+    DRI2GetExtraBufferNamesProcPtr GetExtraBufferNames;
+    DRI2CreateBufferVidProcPtr  CreateBufferVid;
+    DRI2ScheduleSwapVidProcPtr  ScheduleSwapVid;
+    DRI2SetAttributeProcPtr     SetAttribute;
+    DRI2GetAttributeProcPtr     GetAttribute;
 
     HandleExposuresProcPtr       HandleExposures;
 
     ConfigNotifyProcPtr                 ConfigNotify;
 } DRI2ScreenRec;
 
+static Bool
+supports_video(DRI2ScreenPtr ds)
+{
+    /* it would be easier if we had a way to track the driverType in the
+     * DRI2DrawablePtr.. but the DRI2DrawablePtr isn't created at the
+     * time of DRI2Connect()..
+     */
+    return ds && ds->numFormats && ds->CreateBufferVid && ds->ScheduleSwapVid;
+}
+
 static DRI2ScreenPtr
 DRI2GetScreen(ScreenPtr pScreen)
 {
@@ -179,6 +198,7 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
     pPriv->last_swap_ust = 0;
     list_init(&pPriv->reference_list);
     pPriv->serialNumber = DRI2DrawableSerial(pDraw);
+    pPriv->needInvalidate = FALSE;
 
     if (pDraw->type == DRAWABLE_WINDOW) {
        pWin = (WindowPtr) pDraw;
@@ -191,6 +211,35 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
     return pPriv;
 }
 
+Bool
+DRI2SwapLimit(DrawablePtr pDraw, int swap_limit)
+{
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+    DRI2ScreenPtr ds;
+    if (!pPriv)
+       return FALSE;
+
+    ds = pPriv->dri2_screen;
+
+    if (!ds->SwapLimitValidate
+       || !ds->SwapLimitValidate(pDraw, swap_limit))
+       return FALSE;
+
+    pPriv->swap_limit = swap_limit;
+
+    /* Check throttling */
+    if (pPriv->swapsPending >= pPriv->swap_limit)
+       return TRUE;
+
+    if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) {
+       if (pPriv->blockedClient) {
+           AttendClient(pPriv->blockedClient);
+           pPriv->blockedClient = NULL;
+       }
+    }
+
+    return TRUE;
+}
 typedef struct DRI2DrawableRefRec {
     XID                  id;
     XID                  dri2_id;
@@ -264,15 +313,26 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id,
     return Success;
 }
 
+static void destroy_buffers(DrawablePtr pDraw, DRI2BufferPtr *buffers, int count)
+{
+    if (buffers != NULL) {
+       DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+       int i;
+       for (i = 0; i < count; i++)
+           if (buffers[i])
+               (*ds->DestroyBuffer)(pDraw, buffers[i]);
+
+       free(buffers);
+    }
+}
+
 static int DRI2DrawableGone(pointer p, XID id)
 {
     DRI2DrawablePtr pPriv = p;
-    DRI2ScreenPtr   ds = pPriv->dri2_screen;
     DRI2DrawableRefPtr ref, next;
     WindowPtr pWin;
     PixmapPtr pPixmap;
     DrawablePtr pDraw;
-    int i;
 
     list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
        if (ref->dri2_id == id) {
@@ -304,12 +364,7 @@ static int DRI2DrawableGone(pointer p, XID id)
        dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
     }
 
-    if (pPriv->buffers != NULL) {
-       for (i = 0; i < pPriv->bufferCount; i++)
-           (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
-
-       free(pPriv->buffers);
-    }
+    destroy_buffers(pDraw, pPriv->buffers, pPriv->bufferCount);
 
     free(pPriv);
 
@@ -317,7 +372,7 @@ static int DRI2DrawableGone(pointer p, XID id)
 }
 
 static int
-find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
+find_attachment(DRI2DrawablePtr pPriv, unsigned attachment, DRI2BufferPtr *buf)
 {
     int i;
 
@@ -328,6 +383,8 @@ find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
     for (i = 0; i < pPriv->bufferCount; i++) {
        if ((pPriv->buffers[i] != NULL)
            && (pPriv->buffers[i]->attachment == attachment)) {
+           if (buf)
+               *buf = pPriv->buffers[i];
            return i;
        }
     }
@@ -335,15 +392,28 @@ find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
     return -1;
 }
 
+static Bool
+valid_format(DRI2ScreenPtr ds, unsigned int format)
+{
+    int i;
+    for (i = 0; i < ds->numFormats; i++) {
+       if (format == ds->formats[i]) {
+           return TRUE;
+       }
+    }
+    return FALSE;
+}
+
 static Bool
 allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
                         DRI2DrawablePtr pPriv,
                         unsigned int attachment, unsigned int format,
                         int dimensions_match, DRI2BufferPtr *buffer)
 {
-    int old_buf = find_attachment(pPriv, attachment);
+    int old_buf = find_attachment(pPriv, attachment, NULL);
 
     if ((old_buf < 0)
+       || attachment == DRI2BufferFrontLeft
        || !dimensions_match
        || (pPriv->buffers[old_buf]->format != format)) {
        *buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
@@ -352,6 +422,8 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
 
     } else {
        *buffer = pPriv->buffers[old_buf];
+       if (ds->ReuseBufferNotify)
+               (*ds->ReuseBufferNotify)(pDraw, *buffer);
        pPriv->buffers[old_buf] = NULL;
        return FALSE;
     }
@@ -361,18 +433,7 @@ static void
 update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw,
                             DRI2BufferPtr *buffers, int out_count, int *width, int *height)
 {
-    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
-    int i;
-
-    if (pPriv->buffers != NULL) {
-       for (i = 0; i < pPriv->bufferCount; i++) {
-           if (pPriv->buffers[i] != NULL) {
-               (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
-           }
-       }
-
-       free(pPriv->buffers);
-    }
+    destroy_buffers(pDraw, pPriv->buffers, pPriv->bufferCount);
 
     pPriv->buffers = buffers;
     pPriv->bufferCount = out_count;
@@ -417,6 +478,15 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
        const unsigned attachment = *(attachments++);
        const unsigned format = (has_format) ? *(attachments++) : 0;
 
+       /* note: don't require a valid format for old drivers which don't
+        * register their supported formats..
+        */
+       if (has_format && (ds->numFormats > 0) && !valid_format(ds, format)) {
+           xf86DrvMsg(pDraw->pScreen->myNum, X_ERROR,
+                   "[DRI2] %s: bad format: %d\n", __func__, format);
+           goto err_out;
+       }
+
        if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
                                     format, dimensions_match,
                                     &buffers[i]))
@@ -506,19 +576,11 @@ err_out:
 
     *out_count = 0;
 
-    if (buffers) {
-       for (i = 0; i < count; i++) {
-           if (buffers[i] != NULL)
-               (*ds->DestroyBuffer)(pDraw, buffers[i]);
-       }
+    destroy_buffers(pDraw, buffers, count);
 
-       free(buffers);
-       buffers = NULL;
-    }
+    update_dri2_drawable_buffers(pPriv, pDraw, NULL, *out_count, width, height);
 
-    update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width, height);
-
-    return buffers;
+    return NULL;
 }
 
 DRI2BufferPtr *
@@ -537,6 +599,95 @@ DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
                          out_count, TRUE);
 }
 
+DRI2BufferPtr *
+DRI2GetBuffersVid(DrawablePtr pDraw, int width, int height,
+       unsigned int *attachments, int count, int *out_count)
+{
+    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+    DRI2BufferPtr  *buffers;
+    int i, n = 0;
+
+    if (!pPriv || !supports_video(ds)) {
+       *out_count = 0;
+       return NULL;
+    }
+
+    buffers = calloc(count, sizeof(buffers[0]));
+    if (!buffers)
+       goto err_out;
+
+    for (i = 0; i < count; i++) {
+       DRI2BufferPtr buf;
+       const unsigned attachment = *(attachments++);
+       const unsigned format = *(attachments++);
+
+       /* grow array of stored buffers if needed: */
+       if (attachment >= pPriv->bufferCount) {
+           int n = attachment + 1;
+           DRI2BufferPtr *newBuffers = realloc(pPriv->buffers,
+                   sizeof(pPriv->buffers[0]) * n);
+           if (!newBuffers) {
+               xf86DrvMsg(pDraw->pScreen->myNum, X_ERROR,
+                       "[DRI2] %s: allocation failed for buffer: %d\n",
+                       __func__, attachment);
+               goto err_out;
+           }
+           pPriv->buffers = newBuffers;
+           memset(&pPriv->buffers[pPriv->bufferCount], 0,
+                   (n - pPriv->bufferCount) * sizeof(pPriv->buffers[0]));
+           pPriv->bufferCount = n;
+       }
+
+       /* destroy any previous buffer at this attachment slot */
+       if (pPriv->buffers[attachment]) {
+           (*ds->DestroyBuffer)(pDraw, pPriv->buffers[attachment]);
+           pPriv->buffers[attachment] = NULL;
+       }
+
+       if ((width == 0) && (height == 0)) {
+           /* client just wanted us to delete the buffer */
+           continue;
+       }
+
+       if (!valid_format(ds, format)) {
+           xf86DrvMsg(pDraw->pScreen->myNum, X_ERROR,
+                   "[DRI2] %s: bad format: %d\n", __func__, format);
+           goto err_out;
+       }
+
+       if (attachment == DRI2BufferFrontLeft) {
+           buf = (*ds->CreateBuffer)(pDraw, attachment, format);
+           /* note: don't expose front buffer to client */
+       } else {
+           buf = (*ds->CreateBufferVid)(pDraw, attachment, format, width, height);
+           buffers[n++] = buf;
+       }
+
+       if (! buf) {
+           goto err_out;
+       }
+
+       pPriv->buffers[attachment] = buf;
+    }
+
+    *out_count = n;
+
+    return buffers;
+
+err_out:
+
+    *out_count = 0;
+
+    for (i = 0; i < n; i++)
+       if (buffers[i])
+           pPriv->buffers[buffers[i]->attachment] = NULL;
+
+    destroy_buffers(pDraw, buffers, n);
+
+    return NULL;
+}
+
 static void
 DRI2InvalidateDrawable(DrawablePtr pDraw)
 {
@@ -549,7 +700,7 @@ DRI2InvalidateDrawable(DrawablePtr pDraw)
     pPriv->needInvalidate = FALSE;
 
     list_for_each_entry(ref, &pPriv->reference_list, link)
-       ref->invalidate(pDraw, ref->priv);
+       ref->invalidate(pDraw, ref->priv, ref->id);
 }
 
 /*
@@ -609,22 +760,14 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
 {
     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
     DRI2DrawablePtr pPriv;
-    DRI2BufferPtr   pDestBuffer, pSrcBuffer;
-    int                    i;
+    DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
 
     pPriv = DRI2GetDrawable(pDraw);
     if (pPriv == NULL)
        return BadDrawable;
 
-    pDestBuffer = NULL;
-    pSrcBuffer = NULL;
-    for (i = 0; i < pPriv->bufferCount; i++)
-    {
-       if (pPriv->buffers[i]->attachment == dest)
-           pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
-       if (pPriv->buffers[i]->attachment == src)
-           pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
-    }
+    find_attachment(pPriv, dest, &pDestBuffer);
+    find_attachment(pPriv, src, &pSrcBuffer);
     if (pSrcBuffer == NULL || pDestBuffer == NULL)
        return BadValue;
 
@@ -792,31 +935,41 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
     return FALSE;
 }
 
-int
-DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
-               CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
-               DRI2SwapEventPtr func, void *data)
+/*
+ * A TraverseTree callback to invalidate all windows using the same
+ * pixmap
+ */
+static int
+DRI2InvalidateWalk(WindowPtr pWin, pointer data)
+{
+    if (pWin->drawable.pScreen->GetWindowPixmap(pWin) != data)
+       return WT_DONTWALKCHILDREN;
+    DRI2InvalidateDrawable(&pWin->drawable);
+    return WT_WALKCHILDREN;
+}
+
+static int
+swap_buffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+            CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+            DRI2SwapEventPtr func, void *data,
+            Bool vid, unsigned int source, BoxPtr b)
 {
     ScreenPtr       pScreen = pDraw->pScreen;
     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
-    DRI2DrawablePtr pPriv;
+    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
     DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
-    int             ret, i;
+    int             ret;
     CARD64          ust, current_msc;
 
-    pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL) {
+    if ((pPriv == NULL) || (vid && !supports_video(ds))) {
         xf86DrvMsg(pScreen->myNum, X_ERROR,
                   "[DRI2] %s: bad drawable\n", __func__);
        return BadDrawable;
     }
 
-    for (i = 0; i < pPriv->bufferCount; i++) {
-       if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
-           pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
-       if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
-           pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
-    }
+    find_attachment(pPriv, DRI2BufferFrontLeft, &pDestBuffer);
+    find_attachment(pPriv, source, &pSrcBuffer);
+
     if (pSrcBuffer == NULL || pDestBuffer == NULL) {
         xf86DrvMsg(pScreen->myNum, X_ERROR,
                   "[DRI2] %s: drawable has no back or front?\n", __func__);
@@ -824,7 +977,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
     }
 
     /* Old DDX or no swap interval, just blit */
-    if (!ds->ScheduleSwap || !pPriv->swap_interval) {
+    if ((!ds->ScheduleSwap || !pPriv->swap_interval) && !vid) {
        BoxRec box;
        RegionRec region;
 
@@ -860,7 +1013,6 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
 
            if (current_msc < pPriv->last_swap_target)
                pPriv->last_swap_target = current_msc;
-
        }
 
        /*
@@ -876,8 +1028,14 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
     }
 
     pPriv->swapsPending++;
-    ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
-                             swap_target, divisor, remainder, func, data);
+    if (vid) {
+       DrawablePtr osd = NULL;  // TODO
+       ret = (*ds->ScheduleSwapVid)(client, pDraw, pDestBuffer, pSrcBuffer,
+               b, osd, swap_target, divisor, remainder, func, data);
+    } else {
+       ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
+               swap_target, divisor, remainder, func, data);
+    }
     if (!ret) {
        pPriv->swapsPending--; /* didn't schedule */
         xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -892,11 +1050,50 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
      */
     *swap_target = pPriv->swap_count + pPriv->swapsPending;
 
+    if (vid) {
+       return Success;
+    }
+
+    if (pDraw->type == DRAWABLE_WINDOW) {
+       WindowPtr       pWin = (WindowPtr) pDraw;
+       PixmapPtr       pPixmap = pScreen->GetWindowPixmap(pWin);
+
+       /*
+        * Find the top-most window using this pixmap
+        */
+       while (pWin->parent && pScreen->GetWindowPixmap(pWin->parent) == pPixmap)
+           pWin = pWin->parent;
+
+       /*
+        * Walk the sub-tree to invalidate all of the
+        * windows using the same pixmap
+        */
+       TraverseTree(pWin, DRI2InvalidateWalk, pPixmap);
+       DRI2InvalidateDrawable(&pPixmap->drawable);
+    } else
     DRI2InvalidateDrawable(pDraw);
 
     return Success;
 }
 
+int
+DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+               CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+               DRI2SwapEventPtr func, void *data)
+{
+    return swap_buffers(client, pDraw, target_msc, divisor, remainder,
+           swap_target, func, data, FALSE, DRI2BufferBackLeft, NULL);
+}
+
+int
+DRI2SwapBuffersVid(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+               CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+               unsigned int source, BoxPtr b, DRI2SwapEventPtr func, void *data)
+{
+    return swap_buffers(client, pDraw, target_msc, divisor, remainder,
+           swap_target, func, data, TRUE, source, b);
+}
+
 void
 DRI2SwapInterval(DrawablePtr pDrawable, int interval)
 {
@@ -1014,6 +1211,77 @@ DRI2HasSwapControl(ScreenPtr pScreen)
     return ds->ScheduleSwap && ds->GetMSC;
 }
 
+#define ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+/* length in multiple of CARD32's, passed in value should be copied by
+ * receiver
+ */
+int
+DRI2SetAttribute(DrawablePtr pDraw, Atom attribute, int len, const CARD32 *val)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    int ret = BadMatch;
+
+    if (!supports_video(ds)) {
+       return BadDrawable;
+    }
+
+    if (attribute == ATOM("XV_OSD")) {
+    } else if (ds->SetAttribute) {
+       ret = (*ds->SetAttribute)(pDraw, attribute, len, val);
+    }
+
+    return ret;
+}
+
+/* length in multiple of CARD32's, returned val should *not* be free'd
+ * (unlike similar function on client side) to avoid temporary allocation
+ * and extra copy.
+ */
+int
+DRI2GetAttribute(DrawablePtr pDraw, Atom attribute, int *len, const CARD32 **val)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    int ret = BadMatch;
+
+    if (!supports_video(ds)) {
+       return BadDrawable;
+    }
+
+    if (attribute == ATOM("XV_OSD")) {
+    } else if (ds->GetAttribute) {
+       ret = (*ds->GetAttribute)(pDraw, attribute, len, val);
+    }
+
+    return ret;
+}
+
+int
+DRI2GetFormats(ScreenPtr pScreen, unsigned int *nformats, unsigned int **formats)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+    if (! supports_video(ds)) {
+       return BadDrawable;
+    }
+
+    *nformats = ds->numFormats;
+    *formats  = ds->formats;
+
+    return Success;
+}
+
+unsigned int
+DRI2GetExtraBufferNames(DrawablePtr pDraw, DRI2BufferPtr buf,
+       unsigned int **names, unsigned int **pitches)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+    if (ds->GetExtraBufferNames) {
+       return (*ds->GetExtraBufferNames)(pDraw, buf, names, pitches);
+    }
+    return 0;
+}
+
 Bool
 DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
            const char **driverName, const char **deviceName)
@@ -1081,9 +1349,10 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     const char* driverTypeNames[] = {
        "DRI", /* DRI2DriverDRI */
        "VDPAU", /* DRI2DriverVDPAU */
+       "XV", /* DRI2DriverXV */
     };
     unsigned int i;
-    CARD8 cur_minor;
+    CARD8 cur_minor = 1;
 
     if (info->version < 3)
        return FALSE;
@@ -1121,14 +1390,45 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
        ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
        ds->GetMSC = info->GetMSC;
        cur_minor = 3;
-    } else {
-       cur_minor = 1;
     }
 
     if (info->version >= 5) {
         ds->AuthMagic = info->AuthMagic;
     }
 
+    if (info->version >= 6) {
+       ds->ReuseBufferNotify = info->ReuseBufferNotify;
+       ds->SwapLimitValidate = info->SwapLimitValidate;
+    }
+
+    if (info->version >= 7) {
+       if ((info->numDrivers > DRI2DriverXV) &&
+               info->driverNames[DRI2DriverXV]) {
+           /* if driver claims to support DRI2DriverXV, then ensure
+            * it provides the required fxn ptrs:
+            */
+           if (!info->CreateBufferVid || !info->ScheduleSwapVid) {
+               xf86DrvMsg(pScreen->myNum, X_WARNING,
+                       "[DRI2] DRI2DriverXV must implement "
+                       "CreateBuffersVid and ScheduleSwapVid.\n");
+               goto err_out;
+           }
+       }
+       ds->numFormats = info->numFormats;
+       ds->formats = malloc(info->numFormats * sizeof(*ds->formats));
+       if (!ds->formats)
+           goto err_out;
+       memcpy(ds->formats, info->formats,
+               info->numFormats * sizeof(*ds->formats));
+       ds->GetExtraBufferNames = info->GetExtraBufferNames;
+       ds->CreateBufferVid = info->CreateBufferVid;
+       ds->ScheduleSwapVid = info->ScheduleSwapVid;
+       ds->SetAttribute = info->SetAttribute;
+       ds->GetAttribute = info->GetAttribute;
+
+       cur_minor = 4;
+    }
+
     /*
      * if the driver doesn't provide an AuthMagic function or the info struct
      * version is too low, it relies on the old method (using libdrm) or fail
@@ -1178,6 +1478,10 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
 err_out:
     xf86DrvMsg(pScreen->myNum, X_WARNING,
             "[DRI2] Initialization failed for info version %d.\n", info->version);
+    if (ds) {
+       free(ds->formats);
+       free(ds->driverNames);
+    }
     free(ds);
     return FALSE;
 }
index 2a41ead5b134da353e55b6c63c09b86f7b3cd203..81168d71f213a5ef2a720ad1c036f0d9a69f1ae5 100644 (file)
@@ -104,11 +104,72 @@ typedef int               (*DRI2ScheduleSwapProcPtr)(ClientPtr client,
                                                   CARD64 remainder,
                                                   DRI2SwapEventPtr func,
                                                   void *data);
+
+/**
+ * Schedule a video buffer swap
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in.  If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the server may block the client at the next
+ * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
+ * \c DRI2SwapComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * The DDX is responsible for doing an overlay buffer flip/exchange, or
+ * scaling/colorconvert blit when the corresponding event arrives.
+ *
+ * If the target drawable is resized/damaged, or the osd pixmap is changed/
+ * damaged, ScheduleSwapVid can be re-invoked by the core with the same
+ * source buffer to repair the dri2 video drawable.
+ * XXX TODO this part isn't implemented in core yet..
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param pDestBuffer current front buffer
+ * \param pSrcBuffer current back buffer
+ * \param b the crop box
+ * \param osd the on-screen-display overlay pixmap, should be an ARGB pixmap
+ *   that is blended on top of the video as part of swap.  Multiple layers
+ *   to blend over the video should be flattened into a single layer by the
+ *   client
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ * \param func function to call when the swap completes
+ * \param data data for the callback \p func.
+ */
+typedef int            (*DRI2ScheduleSwapVidProcPtr)(ClientPtr client,
+                                                  DrawablePtr pDraw,
+                                                  DRI2BufferPtr pDestBuffer,
+                                                  DRI2BufferPtr pSrcBuffer,
+                                                  BoxPtr b,
+                                                  DrawablePtr osd,
+                                                  CARD64 *target_msc,
+                                                  CARD64 divisor,
+                                                  CARD64 remainder,
+                                                  DRI2SwapEventPtr func,
+                                                  void *data);
+
 typedef DRI2BufferPtr  (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
                                                   unsigned int attachment,
                                                   unsigned int format);
+typedef DRI2BufferPtr  (*DRI2CreateBufferVidProcPtr)(DrawablePtr pDraw,
+                                                  unsigned int attachment,
+                                                  unsigned int format,
+                                                  unsigned int width,
+                                                  unsigned int height);
 typedef void           (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
                                                    DRI2BufferPtr buffer);
+/**
+ * Notifies driver when DRI2GetBuffers reuses a dri2 buffer.
+ *
+ * Driver may rename the dri2 buffer in this notify if it is required.
+ *
+ * \param pDraw drawable whose count we want
+ * \param buffer buffer that will be returned to client
+ */
+typedef void           (*DRI2ReuseBufferNotifyProcPtr)(DrawablePtr pDraw,
+                                                     DRI2BufferPtr buffer);
 /**
  * Get current media stamp counter values
  *
@@ -156,12 +217,62 @@ typedef int               (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
                                                      CARD64 remainder);
 
 typedef void           (*DRI2InvalidateProcPtr)(DrawablePtr pDraw,
-                                                void *data);
+                                                void *data,
+                                                XID id);
+
+/**
+ * DRI2 calls this hook when ever swap_limit is going to be changed. Default
+ * implementation for the hook only accepts one as swap_limit. If driver can
+ * support other swap_limits it has to implement supported limits with this
+ * callback.
+ *
+ * \param pDraw drawable whos swap_limit is going to be changed
+ * \param swap_limit new swap_limit that going to be set
+ * \return TRUE if limit is support, FALSE if not.
+ */
+typedef Bool           (*DRI2SwapLimitValidateProcPtr)(DrawablePtr pDraw,
+                                                       int swap_limit);
+
+
+/**
+ * An ugly approach to avoid changing DRI2BufferPtr and cause ABI breakage
+ * between driver and xserver.  This only needs to be implemented by drivers
+ * supporting planar formats with one buffer per plane.
+ *
+ * This might be a good argument for having drivers in-tree ;-)
+ *
+ * \param pDraw drawable that the buffer belongs to
+ * \param buf the DRI2 buffer
+ * \param names array of buffer names
+ * \param pitches array of buffer pitches
+ * \return the number of additional buffers, ie. for I420 tri-planar buffer,
+ * if represented as multiple buffer names, the Y buffer name would be in
+ * buf->name, this function would return 2, and return the U and V buffer
+ * names by reference.
+ */
+typedef unsigned int   (*DRI2GetExtraBufferNamesProcPtr)(DrawablePtr pDraw,
+       DRI2BufferPtr buf, unsigned int **names, unsigned int **pitches);
+
+/**
+ * Length in multiple of CARD32's, passed in value should be copied by
+ * receiver
+ */
+typedef int (*DRI2SetAttributeProcPtr)(DrawablePtr pDraw, Atom attribute,
+       int len, const CARD32 *val);
+
+/**
+ * Length in multiple of CARD32's, returned val should *not* be free'd
+ * (unlike similar function on client side) to avoid temporary allocation
+ * and extra copy.
+ */
+typedef int (*DRI2GetAttributeProcPtr)(DrawablePtr pDraw, Atom attribute,
+       int *len, const CARD32 **val);
+
 
 /**
  * Version of the DRI2InfoRec structure defined in this header
  */
-#define DRI2INFOREC_VERSION 5
+#define DRI2INFOREC_VERSION 7
 
 typedef struct {
     unsigned int version;      /**< Version of this struct */
@@ -189,6 +300,20 @@ typedef struct {
     /* added in version 5 */
 
     DRI2AuthMagicProcPtr       AuthMagic;
+    /* added in version 6 */
+
+    DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
+    DRI2SwapLimitValidateProcPtr SwapLimitValidate;
+
+    /* added in version 7 */
+
+    unsigned int numFormats;
+    const unsigned int *formats;
+    DRI2GetExtraBufferNamesProcPtr GetExtraBufferNames;
+    DRI2CreateBufferVidProcPtr CreateBufferVid;
+    DRI2ScheduleSwapVidProcPtr ScheduleSwapVid;
+    DRI2SetAttributeProcPtr    SetAttribute;
+    DRI2GetAttributeProcPtr    GetAttribute;
 }  DRI2InfoRec, *DRI2InfoPtr;
 
 extern _X_EXPORT int DRI2EventBase;
@@ -250,11 +375,19 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
        int *width, int *height, unsigned int *attachments, int count,
        int *out_count);
 
+extern _X_EXPORT DRI2BufferPtr * DRI2GetBuffersVid(DrawablePtr pDraw,
+       int width, int height, unsigned int *attachments, int count,
+       int *out_count);
+
 extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
+extern _X_EXPORT Bool DRI2SwapLimit(DrawablePtr pDraw, int swap_limit);
 extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
                                     CARD64 target_msc, CARD64 divisor,
                                     CARD64 remainder, CARD64 *swap_target,
                                     DRI2SwapEventPtr func, void *data);
+extern _X_EXPORT int DRI2SwapBuffersVid(ClientPtr client, DrawablePtr pDraw,
+       CARD64 target_msc, CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+       unsigned int source, BoxPtr b, DRI2SwapEventPtr func, void *data);
 extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
 
 extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
@@ -284,4 +417,22 @@ extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
                                          int frame, unsigned int tv_sec,
                                          unsigned int tv_usec);
 
+extern _X_EXPORT int DRI2SetAttribute(DrawablePtr pDraw, Atom attribute,
+       int len, const CARD32 *val);
+extern _X_EXPORT int DRI2GetAttribute(DrawablePtr pDraw, Atom attribute,
+       int *len, const CARD32 **val);
+extern _X_EXPORT int DRI2GetFormats(ScreenPtr pScreen,
+       unsigned int *nformats, unsigned int **formats);
+
+extern _X_EXPORT unsigned int DRI2GetExtraBufferNames(DrawablePtr pDraw,
+       DRI2BufferPtr buf, unsigned int **names, unsigned int **pitches);
+
+
+/* some utility macros.. maybe could go elsewhere? */
+#define FOURCC(a, b, c, d) (((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )))
+#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
+#ifndef ARRAY_SIZE
+#  define ARRAY_SIZE(_a)   (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
 #endif
index a2198e2558fa1428da0a37df7d5cb3b99d07148e..3fb50394ebef4c10b047b52b0e3c20de217e4cb0 100644 (file)
@@ -78,6 +78,7 @@ ProcDRI2QueryVersion(ClientPtr client)
        swaps(&stuff->length, n);
 
     REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
+
     rep.type = X_Reply;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
@@ -157,7 +158,7 @@ ProcDRI2Authenticate(ClientPtr client)
 }
 
 static void
-DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv)
+DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv, XID id)
 {
     xDRI2InvalidateBuffers event;
     ClientPtr client = priv;
@@ -206,12 +207,13 @@ ProcDRI2DestroyDrawable(ClientPtr client)
 
 
 static int
-send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
+send_buffers_reply(ClientPtr client, DrawablePtr pDrawable, int vid,
                   DRI2BufferPtr *buffers, int count, int width, int height)
 {
     xDRI2GetBuffersReply rep;
-    int skip = 0;
-    int i;
+    int skip = 0, extra = 0;
+    unsigned int *names, *pitches;
+    int i, j;
 
     if (buffers == NULL)
            return BadAlloc;
@@ -227,8 +229,24 @@ send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
        }
     }
 
+    if (vid) {
+       extra = 4 * (count - skip);
+
+       for (i = 0; i < count; i++) {
+           /* Do not send the real front buffer of a window to the client.
+            */
+           if ((pDrawable->type == DRAWABLE_WINDOW)
+                   && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+               continue;
+           }
+
+           extra += 8 * DRI2GetExtraBufferNames(pDrawable, buffers[i],
+                   &names, &pitches);
+       }
+    }
+
     rep.type = X_Reply;
-    rep.length = (count - skip) * sizeof(xDRI2Buffer) / 4;
+    rep.length = ((count - skip) * sizeof(xDRI2Buffer) + extra) / 4;
     rep.sequenceNumber = client->sequence;
     rep.width = width;
     rep.height = height;
@@ -251,6 +269,17 @@ send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
        buffer.cpp = buffers[i]->cpp;
        buffer.flags = buffers[i]->flags;
        WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
+
+       if (vid) {
+           CARD32 n = DRI2GetExtraBufferNames(pDrawable, buffers[i],
+                   &names, &pitches);
+           WriteToClient(client, sizeof(n), &n);
+           for (j = 0; j < n; j++) {
+               CARD32 name = names[j], pitch = pitches[j];
+               WriteToClient(client, sizeof(name), &name);
+               WriteToClient(client, sizeof(pitch), &pitch);
+           }
+       }
     }
     return Success;
 }
@@ -278,8 +307,8 @@ ProcDRI2GetBuffers(ClientPtr client)
                             attachments, stuff->count, &count);
 
 
-    return send_buffers_reply(client, pDrawable, buffers, count, width, height);
-
+    return send_buffers_reply(client, pDrawable, FALSE,
+           buffers, count, width, height);
 }
 
 static int
@@ -303,7 +332,40 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
                                       attachments, stuff->count, &count);
 
-    return send_buffers_reply(client, pDrawable, buffers, count, width, height);
+    return send_buffers_reply(client, pDrawable, FALSE,
+           buffers, count, width, height);
+}
+
+static int
+ProcDRI2GetBuffersVid(ClientPtr client)
+{
+    REQUEST(xDRI2GetBuffersVidReq);
+    DrawablePtr pDrawable;
+    DRI2BufferPtr *buffers;
+    int status, count;
+    unsigned int *attachments;
+
+    REQUEST_FIXED_SIZE(xDRI2GetBuffersVidReq, stuff->count * (2 * 4));
+    if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
+                      &pDrawable, &status))
+       return status;
+
+    if (DRI2ThrottleClient(client, pDrawable))
+       return Success;
+
+    attachments = (unsigned int *) &stuff[1];
+    buffers = DRI2GetBuffersVid(pDrawable, stuff->width, stuff->height,
+                               attachments, stuff->count, &count);
+
+    status = send_buffers_reply(client, pDrawable, TRUE, buffers, count, 0, 0);
+
+    /* note, unlike other DRI2GetBuffers variants, we allow requesting/
+     * returning just a subset of buffers.. so array that is returned is
+     * not the one held in pPriv, so must be free'd
+     */
+    free(buffers);
+
+    return status;
 }
 
 static int
@@ -416,6 +478,53 @@ ProcDRI2SwapBuffers(ClientPtr client)
     return Success;
 }
 
+static int
+ProcDRI2SwapBuffersVid(ClientPtr client)
+{
+    REQUEST(xDRI2SwapBuffersVidReq);
+    xDRI2SwapBuffersReply rep;
+    DrawablePtr pDrawable;
+    CARD64 target_msc, divisor, remainder, swap_target;
+    BoxRec b;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI2SwapBuffersVidReq);
+
+    if (!validDrawable(client, stuff->drawable,
+                      DixReadAccess | DixWriteAccess, &pDrawable, &status))
+       return status;
+
+    /*
+     * Ensures an out of control client can't exhaust our swap queue, and
+     * also orders swaps.
+     */
+    if (DRI2ThrottleClient(client, pDrawable))
+       return Success;
+
+    target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
+    divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
+    remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
+
+    b.x1 = stuff->x1;
+    b.y1 = stuff->y1;
+    b.x2 = stuff->x2;
+    b.y2 = stuff->y2;
+
+    status = DRI2SwapBuffersVid(client, pDrawable, target_msc, divisor, remainder,
+           &swap_target, stuff->source, &b, DRI2SwapEvent, pDrawable);
+    if (status != Success)
+       return BadDrawable;
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    load_swap_reply(&rep, swap_target);
+
+    WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
+
+    return Success;
+}
+
 static void
 load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc)
 {
@@ -538,6 +647,87 @@ ProcDRI2WaitSBC(ClientPtr client)
     return status;
 }
 
+static int
+ProcDRI2SetAttribute(ClientPtr client)
+{
+    REQUEST(xDRI2SetAttributeReq);
+    DrawablePtr pDrawable;
+    int status;
+    int len = (stuff->length * 4 - sizeof(xDRI2SetAttributeReq)) / 4;
+
+    REQUEST_FIXED_SIZE(xDRI2SetAttributeReq, len * 4);
+
+    if (!validDrawable(client, stuff->drawable,
+           DixReadAccess | DixWriteAccess, &pDrawable, &status))
+       return status;
+
+    status = DRI2SetAttribute(pDrawable, stuff->attribute, len,
+           (const CARD32 *)&stuff[1]);
+    if (status != Success)
+       return status;
+
+    return Success;
+}
+
+static int
+ProcDRI2GetAttribute(ClientPtr client)
+{
+    REQUEST(xDRI2GetAttributeReq);
+    xDRI2GetAttributeReply rep;
+    DrawablePtr pDrawable;
+    const CARD32 *val;
+    int status, len;
+
+    REQUEST_SIZE_MATCH(xDRI2GetAttributeReq);
+
+    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+           &status))
+       return status;
+
+    status = DRI2GetAttribute(pDrawable, stuff->attribute, &len, &val);
+    if (status != Success)
+       return status;
+
+    rep.type = X_Reply;
+    rep.length = len;
+    rep.sequenceNumber = client->sequence;
+    WriteToClient(client, sizeof(xDRI2GetAttributeReply), &rep);
+    WriteToClient(client, len * 4, val);
+
+    return Success;
+}
+
+static int
+ProcDRI2GetFormats(ClientPtr client)
+{
+    REQUEST(xDRI2GetFormatsReq);
+    xDRI2GetFormatsReply rep;
+    DrawablePtr pDrawable;
+    unsigned int i, nformats, *formats;
+    int status;
+
+    REQUEST_SIZE_MATCH(xDRI2GetFormatsReq);
+
+    if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+           &status))
+       return status;
+
+    status = DRI2GetFormats(pDrawable->pScreen, &nformats, &formats);
+    if (status != Success)
+       return status;
+
+    rep.type = X_Reply;
+    rep.length = nformats * sizeof(*formats) / 4;
+    rep.sequenceNumber = client->sequence;
+    WriteToClient(client, sizeof(xDRI2GetFormatsReply), &rep);
+
+    for (i = 0; i < nformats; i++) {
+       WriteToClient(client, sizeof(formats[i]), &formats[i]);
+    }
+
+    return Success;
+}
+
 static int
 ProcDRI2Dispatch (ClientPtr client)
 {
@@ -576,6 +766,16 @@ ProcDRI2Dispatch (ClientPtr client)
        return ProcDRI2WaitSBC(client);
     case X_DRI2SwapInterval:
        return ProcDRI2SwapInterval(client);
+    case X_DRI2GetBuffersVid:
+       return ProcDRI2GetBuffersVid(client);
+    case X_DRI2SwapBuffersVid:
+       return ProcDRI2SwapBuffersVid(client);
+    case X_DRI2SetAttribute:
+       return ProcDRI2SetAttribute(client);
+    case X_DRI2GetAttribute:
+       return ProcDRI2GetAttribute(client);
+    case X_DRI2GetFormats:
+       return ProcDRI2GetFormats(client);
     default:
        return BadRequest;
     }
index 8615343f2ba956df38a2c9920ddbc0be16097e48..c057ded8c59be6a35d75f8eb0ac5b7785a043441 100644 (file)
@@ -1837,9 +1837,7 @@ sections have the following format:
 .PP
 The
 .B Identifier
-and
-.B Device
-entries are mandatory.
+entry is mandatory.
 All others are optional.
 .PP
 The
index 8906806cfae9a46a2dea5b1a82e3aeb439f432f8..aac33d32f094dce55f65491dade310321b88482f 100644 (file)
@@ -3102,6 +3102,7 @@ xf86_crtc_box_area(BoxPtr box)
     return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
 }
 
+#ifdef XV
 /*
  * Return the crtc covering 'box'. If two crtcs cover a portion of
  * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
@@ -3190,6 +3191,7 @@ xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
 
     return ret;
 }
+#endif
 
 xf86_crtc_notify_proc_ptr
 xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new)
index 68a968cc2b6f6cf15e05e120184ba27a23a90d46..fca4fe7d9805f18583a9f65265a1ec59e6f3de9d 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2011 Aaron Plattner
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -223,7 +224,7 @@ typedef struct _xf86CrtcFuncs {
 
 } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
 
-#define XF86_CRTC_VERSION 3
+#define XF86_CRTC_VERSION 4
 
 struct _xf86Crtc {
     /**
@@ -361,6 +362,19 @@ struct _xf86Crtc {
      * Clear the shadow
      */
     Bool           shadowClear;
+
+    /**
+     * Indicates that the driver is handling the transform, so the shadow
+     * surface should be disabled.  The driver writes this field before calling
+     * xf86CrtcRotate to indicate that it is handling the transform (including
+     * rotation and reflection).
+     *
+     * Setting this flag also causes the server to stop adjusting the cursor
+     * image and position.
+     *
+     * Added in ABI version 4
+     */
+    Bool           driverIsPerformingTransform;
 };
 
 typedef struct _xf86OutputFuncs {
@@ -889,6 +903,14 @@ xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen);
 extern _X_EXPORT char *
 xf86ConnectorGetName(xf86ConnectorType connector);
 
+/**
+ * Transform the cursor's coordinates based on the crtc transform.  Normally
+ * this is done by the server, but if crtc->driverIsPerformingTransform is TRUE,
+ * then the server does not transform the cursor position automatically.
+ */
+extern _X_EXPORT void
+xf86CrtcTransformCursorPos (xf86CrtcPtr crtc, int *x, int *y);
+
 /*
  * Using the desired mode information in each crtc, set
  * modes (used in EnterVT functions, or at server startup)
@@ -934,6 +956,7 @@ xf86_hide_cursors (ScrnInfoPtr scrn);
 extern _X_EXPORT void
 xf86_cursors_fini (ScreenPtr screen);
 
+#ifdef XV
 /*
  * For overlay video, compute the relevant CRTC and
  * clip video to that.
@@ -952,6 +975,7 @@ xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
                            RegionPtr   reg,
                            INT32       width,
                            INT32       height);
+#endif
     
 extern _X_EXPORT xf86_crtc_notify_proc_ptr
 xf86_wrap_crtc_notify (ScreenPtr pScreen, xf86_crtc_notify_proc_ptr new);
index 066744744578ab90e48b084f5554770bd0601cdd..276bd27bf6a7cb44da38360eb3e24790a0257003 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007 Keith Packard
- * Copyright © 2010 Aaron Plattner
+ * Copyright © 2010-2011 Aaron Plattner
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 #include "cursorstr.h"
 #include "inputstr.h"
 
+/*
+ * Returns the rotation being performed by the server.  If the driver indicates
+ * that it's handling the screen transform, then this returns RR_Rotate_0.
+ */
+static Rotation
+xf86_crtc_cursor_rotation (xf86CrtcPtr crtc)
+{
+    if (crtc->driverIsPerformingTransform)
+       return RR_Rotate_0;
+    return crtc->rotation;
+}
+
 /*
  * Given a screen coordinate, rotate back to a cursor source coordinate
  */
@@ -214,6 +226,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
     int                        xin, yin;
     int                        flags = cursor_info->Flags;
     CARD32             bits;
+    const Rotation     rotation = xf86_crtc_cursor_rotation(crtc);
 
 #ifdef ARGB_CURSOR
     crtc->cursor_argb = FALSE;
@@ -222,7 +235,7 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
     for (y = 0; y < cursor_info->MaxHeight; y++)
        for (x = 0; x < cursor_info->MaxWidth; x++) 
        {
-           xf86_crtc_rotate_coord (crtc->rotation,
+           xf86_crtc_rotate_coord (rotation,
                                    cursor_info->MaxWidth,
                                    cursor_info->MaxHeight,
                                    x, y, &xin, &yin);
@@ -324,7 +337,36 @@ xf86_show_cursors (ScrnInfoPtr scrn)
            xf86_crtc_show_cursor (crtc);
     }
 }
-    
+
+void xf86CrtcTransformCursorPos (xf86CrtcPtr crtc, int *x, int *y)
+{
+    ScrnInfoPtr scrn = crtc->scrn;
+    ScreenPtr screen = scrn->pScreen;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
+    xf86CursorScreenPtr ScreenPriv =
+       (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
+                                             xf86CursorScreenKey);
+    struct pict_f_vector v;
+    int dx, dy;
+
+    v.v[0] = (*x + ScreenPriv->HotX) + 0.5;
+    v.v[1] = (*y + ScreenPriv->HotY) + 0.5;
+    v.v[2] = 1;
+    pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
+    /* cursor will have 0.5 added to it already so floor is sufficent */
+    *x = floor (v.v[0]);
+    *y = floor (v.v[1]);
+    /*
+     * Transform position of cursor upper left corner
+     */
+    xf86_crtc_rotate_coord_back (crtc->rotation, cursor_info->MaxWidth,
+                                cursor_info->MaxHeight, ScreenPriv->HotX,
+                                ScreenPriv->HotY, &dx, &dy);
+    *x -= dx;
+    *y -= dy;
+}
+
 static void
 xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 {
@@ -333,36 +375,12 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
     xf86CursorInfoPtr  cursor_info = xf86_config->cursor_info;
     DisplayModePtr     mode = &crtc->mode;
     Bool               in_range;
-    int                        dx, dy;
 
     /*
      * Transform position of cursor on screen
      */
-    if (crtc->transform_in_use)
-    {
-       ScreenPtr       screen = scrn->pScreen;
-       xf86CursorScreenPtr ScreenPriv =
-           (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
-                                                 xf86CursorScreenKey);
-       struct pict_f_vector   v;
-
-       v.v[0] = (x + ScreenPriv->HotX) + 0.5;
-       v.v[1] = (y + ScreenPriv->HotY) + 0.5;
-       v.v[2] = 1;
-       pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
-       /* cursor will have 0.5 added to it already so floor is sufficent */
-       x = floor (v.v[0]);
-       y = floor (v.v[1]);
-       /*
-        * Transform position of cursor upper left corner
-        */
-       xf86_crtc_rotate_coord_back (crtc->rotation,
-                                    cursor_info->MaxWidth,
-                                    cursor_info->MaxHeight,
-                                    ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
-       x -= dx;
-       y -= dy;
-   }
+    if (crtc->transform_in_use && !crtc->driverIsPerformingTransform)
+       xf86CrtcTransformCursorPos(crtc, &x, &y);
     else
     {
        x -= crtc->x;
@@ -420,12 +438,13 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
     xf86CursorInfoPtr  cursor_info = xf86_config->cursor_info;
     CARD8              *cursor_image;
+    const Rotation     rotation = xf86_crtc_cursor_rotation(crtc);
 
 #ifdef ARGB_CURSOR
     crtc->cursor_argb = FALSE;
 #endif
 
-    if (crtc->rotation == RR_Rotate_0)
+    if (rotation == RR_Rotate_0)
        cursor_image = src;
     else
     {
@@ -439,7 +458,7 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
         for (y = 0; y < cursor_info->MaxHeight; y++)
            for (x = 0; x < cursor_info->MaxWidth; x++) 
            {
-               xf86_crtc_rotate_coord (crtc->rotation,
+               xf86_crtc_rotate_coord (rotation,
                                        cursor_info->MaxWidth,
                                        cursor_info->MaxHeight,
                                        x, y, &xin, &yin);
@@ -532,12 +551,13 @@ xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
     int                        source_height = cursor->bits->height;
     int                        image_width = cursor_info->MaxWidth;
     int                        image_height = cursor_info->MaxHeight;
-    
+    const Rotation     rotation = xf86_crtc_cursor_rotation(crtc);
+
     for (y = 0; y < image_height; y++)
        for (x = 0; x < image_width; x++)
        {
-           xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
-                                   x, y, &xin, &yin);
+           xf86_crtc_rotate_coord (rotation, image_width, image_height, x, y,
+                                   &xin, &yin);
            if (xin < source_width && yin < source_height)
                bits = cursor_source[yin * source_width + xin];
            else
index d5031a2f12799fac14fe62fcf0ca5b283ccba4eb..aa069438d293635c3cae3f4da35469acaf3c1275 100644 (file)
@@ -60,6 +60,9 @@ typedef struct _xf86RandR12Info {
      * See https://bugs.freedesktop.org/show_bug.cgi?id=21554
      */
     xf86EnterVTProc *orig_EnterVT;
+
+    Bool                         panning;
+    ConstrainCursorHarderProcPtr orig_ConstrainCursorHarder;
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
 
 #ifdef RANDR_12_INTERFACE
@@ -678,6 +681,10 @@ xf86RandR12SetConfig (ScreenPtr            pScreen,
     return TRUE;
 }
 
+#define PANNING_ENABLED(crtc)                                           \
+    ((crtc)->panningTotalArea.x2 > (crtc)->panningTotalArea.x1 ||       \
+     (crtc)->panningTotalArea.y2 > (crtc)->panningTotalArea.y1)
+
 static Bool
 xf86RandR12ScreenSetSize (ScreenPtr    pScreen,
                        CARD16          width,
@@ -691,6 +698,7 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
     WindowPtr          pRoot = pScreen->root;
     PixmapPtr          pScrnPix;
     Bool               ret = FALSE;
+    Bool               panning = FALSE;
     int                 c;
 
     if (xf86RandR12Key) {
@@ -711,8 +719,7 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
     /* Update panning information */
     for (c = 0; c < config->num_crtc; c++) {
        xf86CrtcPtr crtc = config->crtc[c];
-       if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 ||
-           crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
+       if (PANNING_ENABLED (crtc)) {
            if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1)
                crtc->panningTotalArea.x2 += width  - pScreen->width;
            if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1)
@@ -723,6 +730,7 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
                crtc->panningTrackingArea.y2 += height - pScreen->height;
            xf86RandR13VerifyPanningArea (crtc, width, height);
            xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+           panning = TRUE;
        }
     }
 
@@ -930,6 +938,7 @@ xf86RandR12CloseScreen (ScreenPtr pScreen)
     randrp = XF86RANDRINFO(pScreen);
 #if RANDR_12_INTERFACE
     xf86Screens[pScreen->myNum]->EnterVT = randrp->orig_EnterVT;
+    pScreen->ConstrainCursorHarder = randrp->orig_ConstrainCursorHarder;
 #endif
 
     free(randrp);
@@ -953,7 +962,8 @@ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
     for (c = 0; c < config->num_crtc; c++) {
        xf86CrtcPtr    crtc = config->crtc[c];
 
-       RRCrtcSetRotations (crtc->randr_crtc, rotations);
+        if (crtc != NULL)
+            RRCrtcSetRotations (crtc->randr_crtc, rotations);
     }
 #endif
     randrp->supported_rotations = rotations;
@@ -1233,6 +1243,7 @@ xf86RandR12CrtcSet (ScreenPtr         pScreen,
            }
            xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height);
            xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+           randrp->panning = PANNING_ENABLED (crtc);
            /*
             * Save the last successful setting for EnterVT
             */
@@ -1666,7 +1677,7 @@ xf86RandR13SetPanning (ScreenPtr           pScreen,
     BoxRec             oldTotalArea;
     BoxRec             oldTrackingArea;
     INT16              oldBorder[4];
-
+    Bool               oldPanning = randrp->panning;
 
     if (crtc->version < 2)
        return FALSE;
@@ -1684,12 +1695,14 @@ xf86RandR13SetPanning (ScreenPtr           pScreen,
 
     if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) {
        xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+        randrp->panning = PANNING_ENABLED (crtc);
        return TRUE;
     } else {
        /* Restore old settings */
        memcpy (&crtc->panningTotalArea,    &oldTotalArea,    sizeof(BoxRec));
        memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec));
        memcpy (crtc->panningBorder,         oldBorder,       4*sizeof(INT16));
+        randrp->panning = oldPanning;
        return FALSE;
     }
 }
@@ -1774,6 +1787,21 @@ xf86RandR12EnterVT (int screen_index, int flags)
     return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */
 }
 
+static void
+xf86RandR13ConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
+{
+    XF86RandRInfoPtr randrp = XF86RANDRINFO(screen);
+
+    if (randrp->panning)
+        return;
+
+    if (randrp->orig_ConstrainCursorHarder) {
+        screen->ConstrainCursorHarder = randrp->orig_ConstrainCursorHarder;
+        screen->ConstrainCursorHarder(dev, screen, mode, x, y);
+        screen->ConstrainCursorHarder = xf86RandR13ConstrainCursorHarder;
+    }
+}
+
 static Bool
 xf86RandR12Init12 (ScreenPtr pScreen)
 {
@@ -1802,6 +1830,10 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
 
+    randrp->panning = FALSE;
+    randrp->orig_ConstrainCursorHarder = pScreen->ConstrainCursorHarder;
+    pScreen->ConstrainCursorHarder = xf86RandR13ConstrainCursorHarder;
+
     if (!xf86RandR12CreateObjects12 (pScreen))
        return FALSE;
 
index 57c3499aca6795cb015f16caf39329aa498c1856..45aabf0250766a40939d277111d535ba9f5251c8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2011 Aaron Plattner
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -84,7 +85,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
     int                        n = RegionNumRects(region);
     BoxPtr             b = RegionRects(region);
     XID                        include_inferiors = IncludeInferiors;
-    
+
+    if (crtc->driverIsPerformingTransform)
+       return;
+
     src = CreatePicture (None,
                         &root->drawable,
                         format,
@@ -290,7 +294,7 @@ xf86RotateDestroy (xf86CrtcPtr crtc)
     }
 
     for (c = 0; c < xf86_config->num_crtc; c++)
-       if (xf86_config->crtc[c]->transform_in_use)
+       if (xf86_config->crtc[c]->rotatedData)
            return;
 
     /*
@@ -414,52 +418,73 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     }
     else
     {
-       /*
-        * these are the size of the shadow pixmap, which
-        * matches the mode, not the pre-rotated copy in the
-        * frame buffer
-        */
-       int         width = crtc->mode.HDisplay;
-       int         height = crtc->mode.VDisplay;
-       void        *shadowData = crtc->rotatedData;
-       PixmapPtr   shadow = crtc->rotatedPixmap;
-       int         old_width = shadow ? shadow->drawable.width : 0;
-       int         old_height = shadow ? shadow->drawable.height : 0;
-
-       /* Allocate memory for rotation */
-       if (old_width != width || old_height != height)
-       {
-           if (shadow || shadowData)
+       if (crtc->driverIsPerformingTransform) {
+           xf86RotateDestroy(crtc);
+       } else {
+           /*
+            * these are the size of the shadow pixmap, which
+            * matches the mode, not the pre-rotated copy in the
+            * frame buffer
+            */
+           int         width = crtc->mode.HDisplay;
+           int         height = crtc->mode.VDisplay;
+           void        *shadowData = crtc->rotatedData;
+           PixmapPtr   shadow = crtc->rotatedPixmap;
+           int         old_width = shadow ? shadow->drawable.width : 0;
+           int         old_height = shadow ? shadow->drawable.height : 0;
+
+           /* Allocate memory for rotation */
+           if (old_width != width || old_height != height)
            {
-               crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
-               crtc->rotatedPixmap = NULL;
-               crtc->rotatedData = NULL;
+               if (shadow || shadowData)
+               {
+                   crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+                   crtc->rotatedPixmap = NULL;
+                   crtc->rotatedData = NULL;
+               }
+               shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
+               if (!shadowData)
+                   goto bail1;
+               crtc->rotatedData = shadowData;
+               /* shadow will be damaged in xf86RotatePrepare */
+           }
+           else
+           {
+               /* mark shadowed area as damaged so it will be repainted */
+               damage = TRUE;
            }
-           shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
-           if (!shadowData)
-               goto bail1;
-           crtc->rotatedData = shadowData;
-           /* shadow will be damaged in xf86RotatePrepare */
-       }
-       else
-       {
-           /* mark shadowed area as damaged so it will be repainted */
-           damage = TRUE;
-       }
 
-       if (!xf86_config->rotation_damage)
-       {
-           /* Create damage structure */
-           xf86_config->rotation_damage = DamageCreate (NULL, NULL,
-                                               DamageReportNone,
-                                               TRUE, pScreen, pScreen);
            if (!xf86_config->rotation_damage)
-               goto bail2;
-           
-           /* Wrap block handler */
-           if (!xf86_config->BlockHandler) {
-               xf86_config->BlockHandler = pScreen->BlockHandler;
-               pScreen->BlockHandler = xf86RotateBlockHandler;
+           {
+               /* Create damage structure */
+               xf86_config->rotation_damage = DamageCreate (NULL, NULL,
+                                                   DamageReportNone,
+                                                   TRUE, pScreen, pScreen);
+               if (!xf86_config->rotation_damage)
+                   goto bail2;
+
+               /* Wrap block handler */
+               if (!xf86_config->BlockHandler) {
+                   xf86_config->BlockHandler = pScreen->BlockHandler;
+                   pScreen->BlockHandler = xf86RotateBlockHandler;
+               }
+           }
+
+           if (0)
+           {
+       bail2:
+               if (shadow || shadowData)
+               {
+                   crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
+                   crtc->rotatedPixmap = NULL;
+                   crtc->rotatedData = NULL;
+               }
+       bail1:
+               if (old_width && old_height)
+                   crtc->rotatedPixmap =
+                       crtc->funcs->shadow_create (crtc, NULL, old_width,
+                                                   old_height);
+               return FALSE;
            }
        }
 #ifdef RANDR_12_INTERFACE
@@ -482,24 +507,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
            }
        }
 #endif
-
-       if (0)
-       {
-    bail2:
-           if (shadow || shadowData)
-           {
-               crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
-               crtc->rotatedPixmap = NULL;
-               crtc->rotatedData = NULL;
-           }
-    bail1:
-           if (old_width && old_height)
-               crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
-                                                                 NULL,
-                                                                 old_width,
-                                                                 old_height);
-           return FALSE;
-       }
        crtc->transform_in_use = TRUE;
     }
     crtc->crtc_to_framebuffer = crtc_to_fb;
index e098e144792d7dec65b50d8916da934cc2686b12..7dd663d1a89679e10eebdd01b8aae6821eff172d 100644 (file)
@@ -41,6 +41,7 @@
 static Bool KeepTty = FALSE;
 static Bool VTSwitch = TRUE;
 static Bool ShareVTs = FALSE;
+Bool NoHwAccess = FALSE;
 static int activeVT = -1;
 
 static char vtname[11];
@@ -319,6 +320,11 @@ xf86ProcessArgument(int argc, char *argv[], int i)
                 ShareVTs = TRUE;
                 return 1;
         }
+       if (!strcmp(argv[i], "-nohwaccess"))
+       {
+               NoHwAccess = TRUE;
+               return(1);
+       }
        if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
        {
                if (sscanf(argv[i], "vt%2d", &xf86Info.vtno) == 0)
@@ -340,4 +346,5 @@ xf86UseMsg(void)
        ErrorF("don't detach controlling tty (for debugging only)\n");
        ErrorF("-novtswitch            don't immediately switch to new VT\n");
        ErrorF("-sharevts              share VTs with another X server\n");
+       ErrorF("-nohwaccess            don't access hardware ports directly\n");
 }
index 468c621939abb0f2fe2481830969e8e9805a51ba..c078c239b9ec27fdd5cf02ff12c95ca501656242 100644 (file)
@@ -50,6 +50,7 @@
 #define MAP_FAILED ((void *)-1)
 #endif
 
+extern Bool NoHwAccess;
 static Bool ExtendedEnabled = FALSE;
 
 #ifdef __ia64__
@@ -497,6 +498,9 @@ xf86EnableIO(void)
        int fd;
        unsigned int ioBase_phys;
 #endif
+       /* Fake it... */
+       if (NoHwAccess)
+               return TRUE;
 
        if (ExtendedEnabled)
                return TRUE;
index af57518ba152664575ba33ead54b035ec6472dea..352dc71342fcb7b1a58dda99f0d51a6462eafb18 100644 (file)
@@ -114,12 +114,17 @@ CloseInput(void)
 /*
  * DDX - specific abort routine.  Called by AbortServer().
  */
-void AbortDDX(enum ExitCode error)
+void SigAbortDDX(int signo, enum ExitCode error)
 {
   xnestDoFullGeneration = True;
   xnestCloseDisplay();
 }
 
+void AbortDDX(enum ExitCode error)
+{
+    SigAbortDDX(0, error);
+}
+
 /* Called by GiveUp(). */
 void ddxGiveUp(enum ExitCode error)
 {
index b483000f897ace90c66bbb67210973bad8e3d339..c2daac38bf02ea43c15e5f7998400038e4b9ef47 100644 (file)
@@ -773,14 +773,20 @@ void ddxGiveUp( enum ExitCode error )
 
 
 /*
- * AbortDDX --
+ * [Sig]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.
  */
 _X_NORETURN
-void AbortDDX( enum ExitCode error ) {
+void SigAbortDDX( int signo, enum ExitCode error )
+{
     ErrorF( "   AbortDDX\n" );
     OsAbort();
 }
 
+_X_NORETURN
+void AbortDDX( enum ExitCode error )
+{
+    SigAbortDDX(signo, error);
+}
index 4fe5053b3dd91179e0162cf5b3353c3e04b0caad..a7b4ac16daf7a9b230c4eaa0a44c1c7ab548d647 100644 (file)
@@ -258,7 +258,7 @@ ddxGiveUp (enum ExitCode error)
 
 /* See Porting Layer Definition - p. 57 */
 void
-AbortDDX (enum ExitCode error)
+SigAbortDDX (int signo, enum ExitCode error)
 {
 #if CYGDEBUG
   winDebug ("AbortDDX\n");
@@ -266,6 +266,12 @@ AbortDDX (enum ExitCode error)
   ddxGiveUp (error);
 }
 
+void
+AbortDDX (enum ExitCode error)
+{
+    SigAbortDDX(0, error);
+}
+
 #ifdef __CYGWIN__
 /* hasmntopt is currently not implemented for cygwin */
 static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt)
index 5177122c90787675c7fc29e0f24fa330a5bcb841..8ffba36cfebba4b5b5ee5f1c63120e28f2d91bcc 100644 (file)
@@ -66,4 +66,16 @@ extern _X_EXPORT int XNFvasprintf (char **ret,
 # define vasprintf Xvasprintf
 #endif
 
+/*
+ * These functions provide a portable implementation of the linux kernel
+ * scnprintf & vscnprintf routines that return the number of bytes actually
+ * copied during a snprintf, (excluding the final '\0').
+ */
+extern _X_EXPORT int
+Xscnprintf(char *s, int n, const char * _X_RESTRICT_KYWD fmt, ...)
+_X_ATTRIBUTE_PRINTF(3,4);
+extern _X_EXPORT int
+Xvscnprintf(char *s, int n, const char * _X_RESTRICT_KYWD fmt, va_list va)
+_X_ATTRIBUTE_PRINTF(3,0);
+
 #endif /* XPRINTF_H */
index 4710ef8813c5171604073e4e1ac933da84935a50..93cd2efd4cd1ba32a5760ea0039b1ee748b5b7ae 100644 (file)
 /* Define to use libsha1 for SHA1 */
 #undef HAVE_SHA1_IN_LIBSHA1
 
+/* Define to use libnettle SHA1 */
+#undef HAVE_SHA1_IN_LIBNETTLE
+
 /* Define to 1 if you have the `shmctl64' function. */
 #undef HAVE_SHMCTL64
 
index 93af49447c93dd8b340b38d22757725eedf6bb23..e88f050320825cda0dc97c0100f1564504a96353 100644 (file)
@@ -266,6 +266,8 @@ extern _X_EXPORT Bool QueueWorkProc(
     pointer /*closure*/
 );
 
+extern _X_EXPORT Bool QueueWorkItem(WorkQueuePtr item);
+
 typedef Bool (* ClientSleepProcPtr)(
     ClientPtr /*client*/,
     pointer /*closure*/);
index 94eb526c5113721e9674818b53d159379a486f0b..9eee5384b745deea5d345b730adb856b88d2c3de 100644 (file)
@@ -153,6 +153,9 @@ typedef struct _WorkQueue {
 );
     ClientPtr   client;
     pointer     closure;
+    void       (*destroyProc) (
+                struct _WorkQueue * /* this */
+);
 }           WorkQueueRec;
 
 extern _X_EXPORT TimeStamp currentTime;
index 8dec9fcbed290771f1dd9c69552572001b3bcf51..27ee9620f317d55f1a3782f9e0fe2d5201a06069 100644 (file)
@@ -624,14 +624,16 @@ extern void TouchAddListener(TouchPointInfoPtr ti, XID resource, enum InputLevel
                              WindowPtr window);
 extern Bool TouchRemoveListener(TouchPointInfoPtr ti, XID resource);
 extern void TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev);
-extern Bool TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                              InternalEvent *ev);
+extern Bool TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+                             InternalEvent *ev);
 extern Bool TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite);
 extern int TouchConvertToPointerEvent(const InternalEvent *ev,
                                       InternalEvent *motion, InternalEvent *button);
 extern int TouchGetPointerEventType(const InternalEvent *ev);
 extern void TouchRemovePointerGrab(DeviceIntPtr dev);
 extern void TouchListenerGone(XID resource);
+extern int TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                                     int listener, int mode);
 extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
                              uint32_t touchid, Window grab_window, XID *error);
 
index c9a8b3e1a19dbc8b5665d32c318f86d94e0a1761..6d98988c44520c71d13ada96ca232104018b146b 100644 (file)
@@ -467,7 +467,9 @@ enum ExitCode {
     EXIT_ERR_DRIVERS   = 3,
 };
 
+extern _X_EXPORT void SigAbortDDX(int signo, enum ExitCode error);
 extern _X_EXPORT void AbortDDX(enum ExitCode error);
+extern _X_EXPORT void ddxSigGiveUp(int signo, enum ExitCode error);
 extern _X_EXPORT void ddxGiveUp(enum ExitCode error);
 extern _X_EXPORT int TimeSinceLastInputEvent(void);
 
@@ -512,6 +514,7 @@ typedef enum {
     X_INFO,                    /* Informational message */
     X_NONE,                    /* No prefix */
     X_NOT_IMPLEMENTED,         /* Not implemented */
+    X_DEBUG,            /* Debug message */
     X_UNKNOWN = -1             /* unknown -- this must always be last */
 } MessageType;
 
@@ -526,6 +529,20 @@ extern _X_EXPORT void LogMessageVerb(MessageType type, int verb, const char *for
                           ...) _X_ATTRIBUTE_PRINTF(3,4);
 extern _X_EXPORT void LogMessage(MessageType type, const char *format, ...)
                        _X_ATTRIBUTE_PRINTF(2,3);
+
+extern _X_EXPORT void
+LogVHdrMessageVerb(MessageType type, int verb,
+                   const char *msg_format, va_list msg_args,
+                   const char *hdr_format, va_list hdr_args)
+_X_ATTRIBUTE_PRINTF(3, 0)
+_X_ATTRIBUTE_PRINTF(5, 0);
+extern _X_EXPORT void
+LogHdrMessageVerb(MessageType type, int verb,
+                  const char *msg_format, va_list msg_args,
+                  const char *hdr_format, ...)
+_X_ATTRIBUTE_PRINTF(3, 0)
+_X_ATTRIBUTE_PRINTF(5, 6);
+
 extern _X_EXPORT void FreeAuditTimer(void);
 extern _X_EXPORT void AuditF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1,2);
 extern _X_EXPORT void VAuditF(const char *f, va_list args) _X_ATTRIBUTE_PRINTF(1,0);
index 479ac2f77c3d82c3864cf3b0564c83b1e56a3bac..f965d6f7e72c38c50dea90cadea5e7c54a057573 100644 (file)
 #define SERVER_XF86VIDMODE_MINOR_VERSION       2
 
 /* Fixes */
-#define SERVER_XFIXES_MAJOR_VERSION            5
+#define SERVER_XFIXES_MAJOR_VERSION            6
 #define SERVER_XFIXES_MINOR_VERSION            0
 
 /* X Input */
index 56ffda21048bfe9c29dbbd1761919b829bc070b0..ea159e31863b07f4caff016e5d7fe6595b98a6da 100644 (file)
@@ -42,6 +42,9 @@
 /* Path to loadable modules. */
 #undef DEFAULT_MODULE_PATH
 
+/* Path to extra loadable modules. */
+#undef EXTRA_MODULE_PATH
+
 /* Path to installed libraries. */
 #undef DEFAULT_LIBRARY_PATH
 
 /* Build with libdrm support */
 #undef WITH_LIBDRM
 
+/* Have setugid */
+#undef HAVE_ISSETUGID
+
+/* Have getresuid */
+#undef HAVE_GETRESUID
+
 #endif /* _XORG_CONFIG_H_ */
index 32c5c9df68dd1f121b228086cadbae85ca93b034..70d5185f6bb4fb3aa27ebc1e84fa7a69d3d6520f 100644 (file)
@@ -479,6 +479,10 @@ miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
     GCPtr          pGC;
 
     pBuffer = miGetDCDevice(pDev, pScreen);
+
+    if (!pBuffer)
+       return FALSE;
+
     pSave = pBuffer->pSave;
 
     pWin = pScreen->root;
index 998c86c15f279a82fc5bac461f653030608b81b5..b456c853d5c0faaa02a8eb5701d2ee7188da0d5b 100644 (file)
@@ -366,6 +366,10 @@ miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
     SetupScreen (pScreen);
     pPointer = MIPOINTER(pDev);
 
+    /* Null pointer causes crash on keyrepeat with Xinerama LP: (#324465) */
+    if (pPointer == NULL)
+        return;
+
     if (pPointer->pScreen != pScreen)
     {
        (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
index 1f990aefae06e337c5251c53830ba6c1a98d42f2..4b5aa325481c81e67e28a374e2b7349ab6ece06f 100644 (file)
@@ -123,10 +123,15 @@ cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off)
        WindowPtr   pWindow = (WindowPtr) pDrawable;
        PixmapPtr   pPixmap = getCwPixmap (pWindow);
 
-       *x_off = pDrawable->x - pPixmap->screen_x;
-       *y_off = pDrawable->y - pPixmap->screen_y;
-
-       return pPicturePrivate->pBackingPicture;
+        if (pDrawable && pPixmap) {
+            *x_off = pDrawable->x - pPixmap->screen_x;
+            *y_off = pDrawable->y - pPixmap->screen_y;
+
+            return pPicturePrivate->pBackingPicture;
+        } else {
+            *x_off = *y_off = 0;
+            return pPicture;
+        }
     }
     else
     {
index f51976284092685c3adfc4eb117394159e6373be..54f6d2efa26a54f5046bfb6ea9869812b215a889 100644 (file)
--- a/os/log.c
+++ b/os/log.c
@@ -89,6 +89,8 @@ OR PERFORMANCE OF THIS SOFTWARE.
 #include <stdlib.h>    /* for malloc() */
 #include <errno.h>
 
+#include <signal.h>    /* for raise() */
+
 #include "input.h"
 #include "site.h"
 #include "opaque.h"
@@ -165,6 +167,12 @@ asm (".desc ___crashreporter_info__, 0x10");
 #ifndef X_NOT_IMPLEMENTED_STRING
 #define X_NOT_IMPLEMENTED_STRING       "(NI)"
 #endif
+#ifndef X_DEBUG_STRING
+#define X_DEBUG_STRING          "(DB)"
+#endif
+#ifndef X_NONE_STRING
+#define X_NONE_STRING           ""
+#endif
 
 /*
  * LogInit is called to start logging to a file.  It is also called (with
@@ -221,7 +229,7 @@ LogInit(const char *fname, const char *backup)
      * needed.
      */
     if (saveBuffer && bufferSize > 0) {
-       free(saveBuffer);       /* Must be free(), not free() */
+       free(saveBuffer);
        saveBuffer = NULL;
        bufferSize = 0;
     }
@@ -263,36 +271,19 @@ LogSetParameter(LogParameter param, int value)
 }
 
 /* This function does the actual log message writes. */
-
-void
-LogVWrite(int verb, const char *f, va_list args)
+static void
+LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
 {
-    static char tmpBuffer[1024];
-    int len = 0;
     static Bool newline = TRUE;
 
-    if (newline) {
-       sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0);
-       len = strlen(tmpBuffer);
-       if (logFile)
-           fwrite(tmpBuffer, len, 1, logFile);
-    }
-
-    /*
-     * Since a va_list can only be processed once, write the string to a
-     * buffer, and then write the buffer out to the appropriate output
-     * stream(s).
-     */
-    if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
-       vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
-       len = strlen(tmpBuffer);
-    }
-    newline = (tmpBuffer[len-1] == '\n');
-    if ((verb < 0 || logVerbosity >= verb) && len > 0)
-       fwrite(tmpBuffer, len, 1, stderr);
-    if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
+    if (verb < 0 || logVerbosity >= verb)
+        fwrite(buf, len, 1, stderr);
+    if (verb < 0 || logFileVerbosity >= verb) {
        if (logFile) {
-           fwrite(tmpBuffer, len, 1, logFile);
+            if (newline)
+                fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0);
+            newline = end_line;
+            fwrite(buf, len, 1, logFile);
            if (logFlush) {
                fflush(logFile);
 #ifndef WIN32
@@ -309,12 +300,18 @@ LogVWrite(int verb, const char *f, va_list args)
                    FatalError("realloc() failed while saving log messages\n");
            }
            bufferUnused -= len;
-           memcpy(saveBuffer + bufferPos, tmpBuffer, len);
+            memcpy(saveBuffer + bufferPos, buf, len);
            bufferPos += len;
        }
     }
 }
 
+void
+LogVWrite(int verb, const char *f, va_list args)
+{
+    return LogVMessageVerb(X_NONE, verb, f, args);
+}
+
 void
 LogWrite(int verb, const char *f, ...)
 {
@@ -325,58 +322,73 @@ LogWrite(int verb, const char *f, ...)
     va_end(args);
 }
 
+/* Returns the Message Type string to prepend to a logging message, or NULL
+ * if the message will be dropped due to insufficient verbosity. */
+static const char *
+LogMessageTypeVerbString(MessageType type, int verb)
+{
+    if (type == X_ERROR)
+        verb = 0;
+
+    if (logVerbosity < verb && logFileVerbosity < verb)
+        return NULL;
+
+    switch (type) {
+    case X_PROBED:
+        return X_PROBE_STRING;
+    case X_CONFIG:
+        return X_CONFIG_STRING;
+    case X_DEFAULT:
+        return X_DEFAULT_STRING;
+    case X_CMDLINE:
+        return X_CMDLINE_STRING;
+    case X_NOTICE:
+        return X_NOTICE_STRING;
+    case X_ERROR:
+        return X_ERROR_STRING;
+    case X_WARNING:
+        return X_WARNING_STRING;
+    case X_INFO:
+        return X_INFO_STRING;
+    case X_NOT_IMPLEMENTED:
+        return X_NOT_IMPLEMENTED_STRING;
+    case X_UNKNOWN:
+        return X_UNKNOWN_STRING;
+    case X_NONE:
+        return X_NONE_STRING;
+    case X_DEBUG:
+        return X_DEBUG_STRING;
+    default:
+        return X_UNKNOWN_STRING;
+    }
+}
+
 void
 LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
 {
-    const char *s  = X_UNKNOWN_STRING;
-    char tmpBuf[1024];
-
-    /* Ignore verbosity for X_ERROR */
-    if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
-       switch (type) {
-       case X_PROBED:
-           s = X_PROBE_STRING;
-           break;
-       case X_CONFIG:
-           s = X_CONFIG_STRING;
-           break;
-       case X_DEFAULT:
-           s = X_DEFAULT_STRING;
-           break;
-       case X_CMDLINE:
-           s = X_CMDLINE_STRING;
-           break;
-       case X_NOTICE:
-           s = X_NOTICE_STRING;
-           break;
-       case X_ERROR:
-           s = X_ERROR_STRING;
-           if (verb > 0)
-               verb = 0;
-           break;
-       case X_WARNING:
-           s = X_WARNING_STRING;
-           break;
-       case X_INFO:
-           s = X_INFO_STRING;
-           break;
-       case X_NOT_IMPLEMENTED:
-           s = X_NOT_IMPLEMENTED_STRING;
-           break;
-       case X_UNKNOWN:
-           s = X_UNKNOWN_STRING;
-           break;
-       case X_NONE:
-           s = NULL;
-           break;
-       }
+    const char *type_str;
+    char buf[1024];
+    const size_t size = sizeof(buf);
+    Bool newline;
+    size_t len = 0;
 
-        /* if s is not NULL we need a space before format */
-        snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
-                                                   s ? " " : "",
-                                                   format);
-        LogVWrite(verb, tmpBuf, args);
-    }
+    type_str = LogMessageTypeVerbString(type, verb);
+    if (!type_str)
+        return;
+
+    /* if type_str is not "", prepend it and ' ', to message */
+    if (type_str[0] != '\0')
+        len += Xscnprintf(&buf[len], size - len, "%s ", type_str);
+
+    if (size - len > 1)
+        len += Xvscnprintf(&buf[len], size - len, format, args);
+
+    /* Force '\n' at end of truncated line */
+    if (size - len == 1)
+        buf[len - 1] = '\n';
+
+    newline = (buf[len - 1] == '\n');
+    LogSWrite(verb, buf, len, newline);
 }
 
 /* Log message with verbosity level specified. */
@@ -401,11 +413,56 @@ LogMessage(MessageType type, const char *format, ...)
     va_end(ap);
 }
 
+void
+LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
+                   va_list msg_args, const char *hdr_format, va_list hdr_args)
+{
+    const char *type_str;
+    char buf[1024];
+    const size_t size = sizeof(buf);
+    Bool newline;
+    size_t len = 0;
+
+    type_str = LogMessageTypeVerbString(type, verb);
+    if (!type_str)
+        return;
+
+    /* if type_str is not "", prepend it and ' ', to message */
+    if (type_str[0] != '\0')
+        len += Xscnprintf(&buf[len], size - len, "%s ", type_str);
+
+    if (hdr_format && size - len > 1)
+        len += Xvscnprintf(&buf[len], size - len, hdr_format, hdr_args);
+
+    if (msg_format && size - len > 1)
+        len += Xvscnprintf(&buf[len], size - len, msg_format, msg_args);
+
+    /* Force '\n' at end of truncated line */
+    if (size - len == 1)
+        buf[len - 1] = '\n';
+
+    newline = (buf[len - 1] == '\n');
+    LogSWrite(verb, buf, len, newline);
+}
+
+void
+LogHdrMessageVerb(MessageType type, int verb, const char *msg_format,
+                  va_list msg_args, const char *hdr_format, ...)
+{
+    va_list hdr_args;
+
+    va_start(hdr_args, hdr_format);
+    LogVHdrMessageVerb(type, verb, msg_format, msg_args, hdr_format, hdr_args);
+    va_end(hdr_args);
+}
+
 void
 AbortServer(void) _X_NORETURN;
+void
+SigAbortServer(int signo) _X_NORETURN;
 
 void
-AbortServer(void)
+SigAbortServer(int signo)
 {
 #ifdef XF86BIGFONT
     XF86BigfontCleanup();
@@ -413,11 +470,22 @@ AbortServer(void)
     CloseWellKnownConnections();
     OsCleanup(TRUE);
     CloseDownDevices();
-    AbortDDX(EXIT_ERR_ABORT);
+    SigAbortDDX(signo, EXIT_ERR_ABORT);
     fflush(stderr);
-    if (CoreDump)
-       OsAbort();
-    exit (1);
+    if (CoreDump) {
+       if (signo != 0)
+           raise(signo);
+       else
+           OsAbort();
+    } else {
+       exit (1);
+    }
+}
+
+void
+AbortServer()
+{
+    SigAbortServer(0);
 }
 
 #define AUDIT_PREFIX "AUDIT: %s: %ld: "
@@ -517,6 +585,27 @@ VAuditF(const char *f, va_list args)
     free(prefix);
 }
 
+void
+FatalSignal(int signo)
+{
+    static Bool beenhere = FALSE;
+
+    if (beenhere)
+       ErrorF("\nFatalSignal re-entered, aborting\n");
+    else
+       ErrorF("\nCaught signal %d (%s). Server aborting\n",
+               signo, strsignal(signo));
+
+    if (!beenhere)
+       OsVendorFatalError();
+    if (!beenhere) {
+       beenhere = TRUE;
+       SigAbortServer(signo);
+    } else
+       abort();
+    /*NOTREACHED*/
+}
+
 void
 FatalError(const char *f, ...)
 {
index 45d202def0b1192e54336dc1af87d414d731af15..ff164d80360c906e535acfa66ba13849a35d4b3c 100644 (file)
@@ -138,13 +138,13 @@ OsSigHandler(int signo)
           case SIGBUS:
           case SIGILL:
           case SIGFPE:
+             signal(signo,SIG_DFL);
              ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
       }
   }
 #endif
 
-  FatalError("Caught signal %d (%s). Server aborting\n",
-            signo, strsignal(signo));
+  FatalSignal(signo);
 }
 
 void
index d9aa65ec74cd9e56132203501bd137c93c09f315..1344f237e7f95045f035c691533624acf0c711fd 100644 (file)
@@ -502,6 +502,7 @@ void UseMsg(void)
     ErrorF("-nolisten string       don't listen on protocol\n");
     ErrorF("-noreset               don't reset after last client exists\n");
     ErrorF("-background [none]     create root window with no background\n");
+    ErrorF("-nr                    (Ubuntu-specific) Synonym for -background none\n");
     ErrorF("-reset                 reset after last client exists\n");
     ErrorF("-p #                   screen-saver pattern duration (minutes)\n");
     ErrorF("-pn                    accept failure to listen on all ports\n");
@@ -840,6 +841,8 @@ ProcessCommandLine(int argc, char *argv[])
                     UseMsg();
             }
         }
+       else if ( strcmp( argv[i], "-nr") == 0)
+           bgNoneRoot = TRUE;
         else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
              if(++i < argc) {
                  long reqSizeArg = atol(argv[i]);
index 254b7374a53d4e598cdef04d0634a36c6fe2be60..8eaccc9d6a726851e19b6042ece71ae15502f842 100644 (file)
@@ -182,6 +182,50 @@ XNFasprintf(char ** ret, const char * _X_RESTRICT_KYWD format, ...)
     return size;
 }
 
+/**
+ * Varargs snprintf that returns the actual number of bytes (excluding final
+ * '\0') that were copied into the buffer.
+ * This is opposed to the normal sprintf() usually returns the number of bytes
+ * that would have been written.
+ *
+ * @param s       buffer to copy into
+ * @param n       size of buffer s
+ * @param format  printf style format string
+ * @param va      variable argument list
+ * @return        number of bytes actually copied, excluding final '\0'
+ */
+int
+Xvscnprintf(char *s, int n, const char *format, va_list args)
+{
+    int x;
+    if (n == 0)
+        return 0;
+    x = vsnprintf(s, n , format, args);
+    return (x >= n) ? (n - 1) : x;
+}
+
+/**
+ * snprintf that returns the actual number of bytes (excluding final '\0') that
+ * were copied into the buffer.
+ * This is opposed to the normal sprintf() usually returns the number of bytes
+ * that would have been written.
+ *
+ * @param s       buffer to copy into
+ * @param n       size of buffer s
+ * @param format  printf style format string
+ * @param ...     arguments for specified format
+ * @return        number of bytes actually copied, excluding final '\0'
+ */
+int Xscnprintf(char *s, int n, const char *format, ...)
+{
+    int x;
+    va_list ap;
+    va_start(ap, format);
+    x = Xvscnprintf(s, n, format, ap);
+    va_end(ap);
+    return x;
+}
+
 /* Old api, now deprecated, may be removed in the future */
 char *
 Xvprintf(const char *format, va_list va)
index 5ea71da46c54f829e15b80937121292bcfaa6626..d9563af4eebdfa6c93932e2daa204687bbb05595 100644 (file)
@@ -127,6 +127,31 @@ int x_sha1_final(void *ctx, unsigned char result[20])
     return 1;
 }
 
+#elif defined(HAVE_SHA1_IN_LIBNETTLE)
+
+# include <nettle/sha.h>
+
+void *x_sha1_init(void)
+{
+    struct sha1_ctx *ctx = xalloc(sizeof(*ctx));
+    if (!ctx)
+       return NULL;
+    sha1_init(ctx);
+    return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+    sha1_update(ctx, size, data);
+    return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+    sha1_digest(ctx, 20, result);
+    return 1;
+}
+
 #else /* Use OpenSSL's libcrypto */
 
 # include <stddef.h>  /* buggy openssl/sha.h wants size_t */
index d33712928aa3e9d0ec3ae86d561dea04cfdac971..a0e542ff7e4830d8c20d1b224db69a4d4fbdf980 100644 (file)
@@ -235,7 +235,7 @@ Bool RRScreenInit(ScreenPtr pScreen)
     /*
      * Calling function best set these function vectors
      */
-    pScrPriv->rrGetInfo = 0;
+    pScrPriv->rrGetInfo = NULL;
     pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
     pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
     
@@ -454,6 +454,9 @@ RRFirstOutput (ScreenPtr pScreen)
     rrScrPriv(pScreen);
     RROutputPtr                    output;
     int        i, j;
+
+    if (!pScrPriv)
+        return NULL;
     
     if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
        return pScrPriv->primaryOutput;
index 5edeb7dd23af7f7db5243f50793fe0b3b39db5a9..94ba8af0dc2f8de6ab18c7931c16720b44fe948e 100644 (file)
@@ -583,7 +583,8 @@ ProcRRSetOutputPrimary(ClientPtr client)
     }
 
     pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
-    RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
+    if (pScrPriv)
+        RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
 
     return Success;
 }
index da6d48d6e0a5ef40058b1d7e35405960989deaad..eb93c33ee1396722c8e98349b0cd0be146d49c58 100644 (file)
@@ -261,6 +261,9 @@ ProcRRSetScreenSize (ClientPtr client)
 
     pScreen = pWin->drawable.pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
+    if (!pScrPriv)
+        return BadMatch;
+
     if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width)
     {
        client->errorValue = stuff->width;
index 28eb21ababb68e537e33253105256cc7c006226e..ed2f2e5315abf0e88a36fec89ef31065b0c5a8f0 100644 (file)
@@ -1,5 +1,10 @@
 if ENABLE_UNIT_TESTS
 SUBDIRS= . xi2
+
+if HAVE_XORG_GTEST
+SUBDIRS+= gtest
+endif
+
 noinst_PROGRAMS = xkb input xtest list misc fixes xfree86 touch
 check_LTLIBRARIES = libxservertest.la
 
diff --git a/test/gtest/Makefile.am b/test/gtest/Makefile.am
new file mode 100644 (file)
index 0000000..56e695c
--- /dev/null
@@ -0,0 +1,27 @@
+check_PROGRAMS = xfixes_barriers
+check_DATA = dummy.conf
+
+TESTS=xfixes_barriers
+
+GTEST_SRC_DIR = /usr/src/gtest
+GTEST_SOURCES = $(GTEST_SRC_DIR)/src/gtest-all.cc
+
+xfixes_barriers_CXXFLAGS = $(AM_CXXFLAGS) \
+       -I$(GTEST_SRC_DIR) \
+       $(XORG_GTEST_CFLAGS) \
+       $(XTEST_CFLAGS) \
+       $(XFIXES_CFLAGS) \
+       -DXORG_BINARY=\"$(top_builddir)/hw/xfree86/Xorg\" \
+       -DXORG_DUMMY_CONF=\"$(abs_srcdir)/dummy.conf\"
+
+xfixes_barriers_LDADD = \
+       $(XFIXES_LIBS) \
+       $(XTEST_LIBS) \
+       $(XORG_GTEST_LIBS) \
+       -lpthread
+
+xfixes_barriers_SOURCES = \
+       xfixes_barriers.cpp
+
+nodist_xfixes_barriers_SOURCES = \
+       $(GTEST_SOURCES)
diff --git a/test/gtest/dummy.conf b/test/gtest/dummy.conf
new file mode 100644 (file)
index 0000000..5600991
--- /dev/null
@@ -0,0 +1,4 @@
+Section "Device"
+    Identifier "Dummy video device"
+    Driver "dummy"
+EndSection
diff --git a/test/gtest/xfixes_barriers.cpp b/test/gtest/xfixes_barriers.cpp
new file mode 100644 (file)
index 0000000..c9bf7f9
--- /dev/null
@@ -0,0 +1,828 @@
+/*
+
+Copyright (c) 2012, Canonical Ltd
+
+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 (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 NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS 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 <iostream>
+#include <sys/time.h>
+#include <unistd.h>
+#include <gtest/gtest.h>
+#include <xorg/gtest/test.h>
+#include <xorg/gtest/environment.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XTest.h>
+#include <X11/extensions/Xfixes.h>
+
+
+int main (int argc, char **argv)
+{
+    ::testing::InitGoogleTest (&argc, argv);
+    xorg::testing::Environment* environment = new xorg::testing::Environment ();
+    environment->set_conf_file (XORG_DUMMY_CONF);
+    environment->set_server (XORG_BINARY);
+    testing::AddGlobalTestEnvironment (environment);
+    return RUN_ALL_TESTS ();
+}
+
+class BarrierTest : public xorg::testing::Test {
+    public:
+    ::Display *dpy;
+    static XErrorEvent *lastError;
+    int xtest_eventbase;
+    int xtest_errorbase;
+    int fixes_eventbase;
+    int fixes_errorbase;
+
+    void AssertPointerPosition (int expected_x, int expected_y)
+    {
+        int x, y, unused_int;
+        unsigned int unused_uint;
+        Window unused_win;
+
+        XQueryPointer (Display (), DefaultRootWindow (Display ()),
+                       &unused_win, &unused_win, &x, &y,
+                       &unused_int, &unused_int, &unused_uint);
+
+        ASSERT_TRUE (x == expected_x && y == expected_y) <<
+            "Incorrect pointer position: Expected ("<<
+            expected_x<< ", "<<expected_y<<"), got "<<
+            "("<<x<<", "<<y<<")\n";
+    }
+
+    bool WaitForXEvent (int msTimeout = 1000)
+    {
+        fd_set fds;
+        int xfd = ConnectionNumber (Display ());
+        struct timeval tv;
+        int retval;
+
+        FD_ZERO (&fds);
+        FD_SET (xfd, &fds);
+
+        tv.tv_sec = msTimeout / 1000;
+        tv.tv_usec = (msTimeout % 1000) * 1000;
+
+        retval = select (xfd + 1, &fds, NULL, NULL, &tv);
+
+        EXPECT_NE (-1, retval)<<"Error waiting for X event";
+
+        return retval;
+    }
+
+    protected:
+    virtual void SetUp ()
+    {
+        ASSERT_NO_FATAL_FAILURE (xorg::testing::Test::SetUp());
+
+        dpy = Display ();
+        int major = 2, minor = 2;
+        ASSERT_TRUE (XTestQueryExtension (dpy,
+                                          &xtest_eventbase, &xtest_errorbase,
+                                          &major, &minor));
+        ASSERT_EQ (2, major);
+        ASSERT_TRUE (minor >= 2);
+
+        major = 6;
+        minor = 0;
+        XFixesQueryVersion (dpy, &major, &minor);
+        ASSERT_EQ (6, major);
+        ASSERT_TRUE (minor >= 0);
+
+        ASSERT_TRUE (XFixesQueryExtension (dpy,
+                                           &fixes_eventbase, &fixes_errorbase));
+
+        lastError = new XErrorEvent;
+        XSetErrorHandler (ErrorHandler);
+    }
+
+    private:
+    static int ErrorHandler (::Display *dpy, XErrorEvent *error)
+    {
+        memcpy (lastError, error, sizeof (*lastError));
+        return 0;
+    }
+};
+
+XErrorEvent *BarrierTest::lastError = NULL;
+
+TEST_F (BarrierTest, CreateVerticalBarrierSucceeds)
+{
+    PointerBarrier barrier;
+    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
+                                          100, 0,
+                                          100, 100,
+                                          0,
+                                          0, NULL);
+    ASSERT_NE(None, barrier);
+}
+
+TEST_F (BarrierTest, CreateHorizontalBarrierSucceds)
+{
+    PointerBarrier barrier;
+    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
+                                          100, 100,
+                                          200, 100,
+                                          0,
+                                          0, NULL);
+    ASSERT_NE(None, barrier);
+}
+
+TEST_F (BarrierTest, CreateNonAxisAlignedBarrierFails)
+{
+    XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
+                                0, 0,
+                                100, 100,
+                                0,
+                                0, NULL);
+    XSync (Display (), false);
+    ASSERT_EQ(BadValue, lastError->error_code);
+}
+
+TEST_F (BarrierTest, VerticalBidirectionalBarrierBlocksRelativeMotion)
+{
+    int barrier_x = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                0, 0, NULL);
+
+    int x = 200, y = 100, dx = -200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion should block on barrier
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y));
+}
+
+TEST_F (BarrierTest, VerticalPositiveXBarrierBlocksMotion)
+{
+    int barrier_x = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                BarrierPositiveX, 0, NULL);
+    int x = 200, y = 100, dx = -200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in -ve X direction should block on barrier
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
+
+    x = 0, y = 100, dx = 200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in +ve X direction should ignore barrier
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, VerticalNegativeXBarrierBlocksMotion)
+{
+    int barrier_x = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                BarrierNegativeX,
+                                0, NULL);
+
+    int x = 200, y = 100, dx = -200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in -ve X direction should ignore barrier
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+
+    x = 0, y = 100, dx = 200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in +ve X direction should block on barrier
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
+}
+
+TEST_F (BarrierTest, HorizontalBidirectionalBarrierBlocksRelativeMotion)
+{
+    int barrier_y = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                0,   barrier_y,
+                                300, barrier_y,
+                                0, 0, NULL);
+
+    int x = 200, y = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in +ve Y direction should block on barrier
+    int dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
+
+    x = 100, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in -ve Y direction should block on barrier
+    dx = 0, dy = -200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
+}
+
+TEST_F (BarrierTest, HorizontalPositiveYBarrierBlocksMotion)
+{
+    int barrier_y = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                0,   barrier_y,
+                                300, barrier_y,
+                                BarrierPositiveY, 0, NULL);
+
+    int x = 200, y = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in +ve Y direction should ignore barrier
+    int dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+
+    x = 100, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in -ve Y direction should block on barrier
+    dx = 0, dy = -200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
+}
+
+TEST_F (BarrierTest, HorizontalNegativeYBarrierBlocksMotion)
+{
+    int barrier_y = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                0,   barrier_y,
+                                300, barrier_y,
+                                BarrierNegativeY, 0, NULL);
+
+    int x = 200, y = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in +ve Y direction should block on barrier
+    int dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
+
+    x = 100, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Relative motion in -ve Y direction should ignore barrier
+    dx = 0, dy = -200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, DestroyPointerBarrierSucceeds)
+{
+    int barrier_x = 100;
+    PointerBarrier barrier;
+    barrier = XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                          barrier_x, 0,
+                                          barrier_x, 300,
+                                          0, 0, NULL);
+
+    int x = 0, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Check that the barrier exists before we destroy it.
+    int dx = 200, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
+
+    // Destroy the barrier...
+    XFixesDestroyPointerBarrier (Display (), barrier);
+
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // There should be no barrier to block this.
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, BarrierIgnoresNonsensicalDirections)
+{
+    int barrier_x = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                BarrierPositiveY | BarrierNegativeY,
+                                0, NULL);
+
+    int x = 200, y = 100;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    int dx = -200, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
+
+    int barrier_y = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                               0,   barrier_y,
+                               400, barrier_y,
+                               BarrierPositiveX | BarrierNegativeX,
+                               0, NULL);
+
+    x = 100, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = 0, dy = -200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
+}
+
+TEST_F (BarrierTest, VerticalBarrierEdges)
+{
+    int barrier_x = 300, barrier_y1 = 300 , barrier_y2 = 500;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, barrier_y1,
+                                barrier_x, barrier_y2,
+                                0, 0, NULL);
+
+    int x = barrier_x + 100, y = barrier_y1 - 1;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should take us past the top of the barrier...
+    int dx = -200, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+
+    x = barrier_x + 100, y = barrier_y1;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should hit the top of the barrier...
+    dx = -200, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
+
+    x = barrier_x + 100, y = barrier_y2;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should hit the bottom of the barrier...
+    dx = -200, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
+
+    x = barrier_x + 100, y = barrier_y2 + 1;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should take us past the bottom of the barrier...
+    dx = -200, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, HorizontalBarrierEdges)
+{
+    int barrier_x1 = 200, barrier_x2 = 500, barrier_y = 300;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x1, barrier_y,
+                                barrier_x2, barrier_y,
+                                0, 0, NULL);
+
+    int x = barrier_x1 - 1, y = barrier_y - 100;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should take us past the left edge of the barrier...
+    int dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+
+    x = barrier_x1, y = barrier_y - 100;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should hit the top of the barrier...
+    dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, barrier_y - 1));
+
+    x = barrier_x2, y = barrier_y - 100;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should hit the bottom of the barrier...
+    dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
+
+    x = barrier_x2 + 1, y = barrier_y - 100;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    // Motion should take us past the bottom of the barrier...
+    dx = 0, dy = 200;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, CornerBlocksMotion)
+{
+    int corner_x, corner_y;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                corner_x, corner_y,
+                                corner_x, corner_y + 300,
+                                0, 0, NULL);
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                corner_x, corner_y,
+                                corner_x + 300, corner_y,
+                                0, 0, NULL);
+
+    int x = corner_x + 100, y = corner_y + 100;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    XTestFakeRelativeMotionEvent (Display (), -200, -200, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (corner_x, corner_y));
+}
+
+TEST_F (BarrierTest, VerticalBarrierWithAdjacentStart)
+{
+    int barrier_x = 350;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 100,
+                                barrier_x, 300,
+                                0, 0, NULL);
+
+    int x = barrier_x, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    int dx = -10, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
+
+    x = barrier_x, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = 10, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+
+    x = barrier_x - 1, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = 10, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
+
+    x = barrier_x - 1, y = 200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = -10, dy = 0;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, HorizontalBarrierWithAdjacentStart)
+{
+    int barrier_y = 300;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                100, barrier_y,
+                                400, barrier_y,
+                                0, 0, NULL);
+
+    int x = 240, y = barrier_y;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    int dx = 0, dy = -10;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
+
+    x = 240, y = barrier_y;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = 0, dy = 10;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+
+    x = 240, y = barrier_y - 1;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = 0, dy = 10;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
+
+    x = 240, y = barrier_y - 1;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    dx = 0, dy = -10;
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
+}
+
+TEST_F (BarrierTest, BarrierNotifyEventFires)
+{
+    int barrier_y = 300;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                100, barrier_y,
+                                400, barrier_y,
+                                0, 0, NULL);
+
+    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
+                              XFixesBarrierHitNotifyMask);
+
+    int x = 240, y = barrier_y + 50;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    XTestFakeRelativeMotionEvent (Display (), 0, -100, 0);
+
+    XFlush (Display ());
+    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
+    while (XPending (Display ())) {
+        XEvent e;
+        XNextEvent (Display (), &e);
+        switch (e.xany.type - fixes_eventbase) {
+            case XFixesBarrierNotify:
+                return;
+        }
+    }
+    FAIL () << "Failed to recieve BarrierNotify event";
+}
+
+TEST_F (BarrierTest, RecieveOneNotifyEventPerHit)
+{
+    int barrier_x = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                0, 0, NULL);
+
+    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
+                              XFixesBarrierHitNotifyMask);
+
+    int x = 200, y = 100, dx = -200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    /* Generate 5 barrier events */
+    for (int i = 0; i < 5; ++i) {
+        XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    }
+
+    int barrierEventCount = 0;
+    XFlush (Display ());
+    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
+    while (XPending (Display ())) {
+        XEvent e;
+        XNextEvent (Display (), &e);
+        switch (e.xany.type - fixes_eventbase) {
+            case XFixesBarrierNotify:
+                barrierEventCount++;
+                break;
+        }
+    }
+    ASSERT_EQ (5, barrierEventCount);
+}
+
+TEST_F (BarrierTest, BarrierEventHasNonZeroVelocity)
+{
+    int barrier_x = 100;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                0, 0, NULL);
+
+    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
+                              XFixesBarrierHitNotifyMask);
+
+    int x = 200, y = 100, dx = -200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    /* One relative event to ensure the server has a non-zero
+     * last-event-time */
+    XTestFakeRelativeMotionEvent (Display (), 10, 10, 0);
+    /* Run the pointer into the barrier */
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    XFlush (Display ());
+    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
+    while (XPending (Display ())) {
+        XEvent e;
+        XNextEvent (Display (), &e);
+        switch (e.xany.type - fixes_eventbase) {
+            case XFixesBarrierNotify:
+                XFixesBarrierNotifyEvent *notify = (XFixesBarrierNotifyEvent *)&e;
+                ASSERT_LT (0, notify->velocity);
+                return;
+        }
+    }
+    FAIL () << "Failed to receive barrier event";
+}
+
+TEST_F (BarrierTest, ScreenEdgeVerticalBarrierEventHasNonZeroVelocity)
+{
+    int barrier_x = 0;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                0, 0, NULL);
+
+    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
+                              XFixesBarrierHitNotifyMask);
+
+    int x = 100, y = 100, dx = -200, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    /* One relative event to ensure the server has a non-zero
+     * last-event-time */
+    XTestFakeRelativeMotionEvent (Display (), 10, 10, 0);
+    /* Run the pointer into the barrier */
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    XFlush (Display ());
+    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
+    while (XPending (Display ())) {
+        XEvent e;
+        XNextEvent (Display (), &e);
+        switch (e.xany.type - fixes_eventbase) {
+            case XFixesBarrierNotify:
+                XFixesBarrierNotifyEvent *notify = (XFixesBarrierNotifyEvent *)&e;
+                ASSERT_LT (0, notify->velocity);
+                return;
+        }
+    }
+    FAIL () << "Failed to receive barrier event";
+}
+
+TEST_F (BarrierTest, ScreenEdgeHorizontalBarrierEventHasNonZeroVelocity)
+{
+    int barrier_y = 0;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                0, barrier_y,
+                                300, barrier_y,
+                                0, 0, NULL);
+
+    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
+                              XFixesBarrierHitNotifyMask);
+
+    int x = 100, y = 100, dx = 0, dy = -200;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    /* One relative event to ensure the server has a non-zero
+     * last-event-time */
+    XTestFakeRelativeMotionEvent (Display (), 10, 10, 0);
+    /* Run the pointer into the barrier */
+    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+
+    XFlush (Display ());
+    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
+    while (XPending (Display ())) {
+        XEvent e;
+        XNextEvent (Display (), &e);
+        switch (e.xany.type - fixes_eventbase) {
+            case XFixesBarrierNotify:
+                XFixesBarrierNotifyEvent *notify = (XFixesBarrierNotifyEvent *)&e;
+                ASSERT_LT (0, notify->velocity);
+                return;
+        }
+    }
+    FAIL () << "Failed to receive barrier event";
+}
+
+TEST_F (BarrierTest, ReceiveOneBarrierEventPerHitOnScreenEdge)
+{
+    int barrier_x = 0;
+    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
+                                barrier_x, 0,
+                                barrier_x, 300,
+                                0, 0, NULL);
+
+    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
+                              XFixesBarrierHitNotifyMask);
+
+    int x = 20, y = 100, dx = -40, dy = 0;
+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
+                          x, y, 0);
+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
+
+    /* Generate 5 barrier events */
+    for (int i = 0; i < 5; ++i) {
+        XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
+    }
+
+    int barrierEventCount = 0;
+    XFlush (Display ());
+    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
+    while (XPending (Display ())) {
+        XEvent e;
+        XNextEvent (Display (), &e);
+        switch (e.xany.type - fixes_eventbase) {
+            case XFixesBarrierNotify:
+                barrierEventCount++;
+                break;
+        }
+    }
+    ASSERT_EQ (5, barrierEventCount);
+}
index 7b01c8b52380a721ca1fa2811f407e662917b4d0..e007b0d2511d1b786c8715ea371be7ed1a76836e 100644 (file)
@@ -61,6 +61,7 @@ static RESTYPE                CursorClientType;
 static RESTYPE         CursorHideCountType;
 static RESTYPE         CursorWindowType;
 RESTYPE                        PointerBarrierType;
+static RESTYPE         PointerBarrierClientType;
 static CursorPtr       CursorCurrent[MAXDEVICES];
 
 static DevPrivateKeyRec CursorScreenPrivateKeyRec;
@@ -119,6 +120,11 @@ struct PointerBarrierClient {
     struct list entry;
 };
 
+/**
+ * Pick up unclamped (x,y) coordinates from dix/getevents
+ */
+extern int unclamped_prex, unclamped_prey;
+
 /*
  * Wrap DisplayCursor to catch cursor change events
  */
@@ -129,6 +135,7 @@ typedef struct _CursorScreen {
     ConstrainCursorHarderProcPtr ConstrainCursorHarder;
     CursorHideCountPtr          pCursorHideCounts;
     struct list                 barriers;
+    struct list                 barrierClients;
 } CursorScreenRec, *CursorScreenPtr;
 
 #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
@@ -1118,7 +1125,8 @@ barrier_is_blocking(const struct PointerBarrier *barrier,
 
     /* Algorithm below doesn't handle edge cases well, hence the extra
      * checks. */
-    if (barrier_is_vertical(barrier)) {
+    if (barrier_is_vertical(barrier) &&
+       (dir & (BarrierPositiveX | BarrierNegativeX))) {
        /* handle immediate barrier adjacency, moving away */
        if (dir & BarrierPositiveX && x1 == barrier->x1)
            return FALSE;
@@ -1129,7 +1137,8 @@ barrier_is_blocking(const struct PointerBarrier *barrier,
            *distance = 0;
            return TRUE;
        }
-    } else {
+    } else if (barrier_is_horizontal(barrier) &&
+               (dir & (BarrierPositiveY | BarrierNegativeY))){
        /* handle immediate barrier adjacency, moving away */
        if (dir & BarrierPositiveY && y1 == barrier->y1)
            return FALSE;
@@ -1231,6 +1240,127 @@ barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y
     }
 }
 
+/*
+ * ConstrainCursorHarder is called from the SIGIO context.
+ * This means we cannot safely send a client event from anything in
+ * CursorConstrainCursorHarder's callgraph.
+ *
+ * Allocate a set of WorkQueue items to use.
+ */
+
+struct BarrierEventStore {
+    WorkQueueRec wq_item;
+    xXFixesBarrierNotifyEvent ev;
+    Bool in_use;
+};
+
+/* Let's guess that 100 events is enough of a buffer. */
+#define BARRIER_EVENT_QUEUE_SIZE 100
+struct BarrierEventStore barrierEventQueue[BARRIER_EVENT_QUEUE_SIZE];
+
+static void
+CursorWorkQueueDestroyProc (WorkQueuePtr this)
+{
+    struct BarrierEventStore *store;
+    store = container_of (this, struct BarrierEventStore, wq_item);
+
+    store->in_use = FALSE;
+}
+
+static Bool
+CursorSendBarrierEvent (ClientPtr client, pointer eventStore)
+{
+    struct BarrierEventStore *store = (struct BarrierEventStore *)eventStore;
+    WriteEventsToClient (client, 1, (xEvent *)&store->ev);
+
+    return TRUE;
+}
+
+static struct BarrierEventStore *
+CursorFindFreeEventStore (void)
+{
+    for (int i = 0; i < BARRIER_EVENT_QUEUE_SIZE; ++i) {
+       if (!barrierEventQueue[i].in_use) {
+           return &barrierEventQueue[i];
+       }
+    }
+    return NULL;
+}
+
+static void
+QueueBarrierEvent(CursorScreenPtr cs, struct PointerBarrier *barrier,
+                 int x, int y, int velocity, Bool threshold_exceeded)
+{
+    PointerBarrierEventClientPtr client;
+    struct BarrierEventStore *store;
+    list_for_each_entry(client, &cs->barrierClients, entry) {
+       store = CursorFindFreeEventStore ();
+       if (store == NULL) {
+           ErrorF ("[xfixes] Barrier event queue full.  Dropping further events\n");
+           return;
+       }
+
+       store->in_use = TRUE;
+
+       store->ev.type = XFixesEventBase + XFixesBarrierNotify;
+       store->ev.subtype = threshold_exceeded ? XFixesBarrierThresholdExceededNotify :
+                                                XFixesBarrierHitNotify;
+       store->ev.event_id = barrier->barrierEventID;
+       store->ev.barrier = barrier->barrier;
+       store->ev.x = x;
+       store->ev.y = y;
+       store->ev.velocity = velocity;
+       store->ev.timestamp = currentTime.milliseconds;
+
+       if (client->client->swapped) {
+           int n;
+
+           swapl(&store->ev.event_id, n);
+           swapl(&store->ev.barrier, n);
+           swaps(&store->ev.x, n);
+           swaps(&store->ev.y, n);
+           swapl(&store->ev.velocity, n);
+           swapl(&store->ev.timestamp, n);
+       }
+
+       store->wq_item.function = CursorSendBarrierEvent;
+       store->wq_item.client = client->client;
+       store->wq_item.closure = store;
+       store->wq_item.destroyProc = CursorWorkQueueDestroyProc;
+
+       QueueWorkItem (&store->wq_item); 
+    }
+}
+
+static void
+barrier_calculate_velocity_components (int x1, int y1, int x2, int y2,
+                                      int *vel_x, int *vel_y)
+{
+    static CARD32 last_timestamp = 0;
+    CARD32 timestamp = GetTimeInMillis();
+    int dx, dy;
+    int dt = timestamp - last_timestamp;
+
+    if (last_timestamp == 0) {
+       /* Not much we can do for the first event */
+       *vel_x = 0;
+       *vel_y = 0;
+       last_timestamp = timestamp;
+       return;
+    }
+
+    /* Lets not divide by zero if we can avoid it */
+    dt = dt > 0 ? dt : 1;
+
+    dx = x2 - x1;
+    dy = y2 - y1;
+
+    *vel_x = abs(dx) * 1000.0 / dt;
+    *vel_y = abs(dy) * 1000.0 / dt;
+
+    last_timestamp = timestamp;
+}
+
 static void
 CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
 {
@@ -1238,12 +1368,23 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x
 
     if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) {
        int ox, oy;
+       int vel_x, vel_y;
        int dir;
        struct PointerBarrier *nearest = NULL;
+       PointerBarrierClientPtr c;
 
        /* where are we coming from */
        miPointerGetPosition(dev, &ox, &oy);
 
+       /* Use the unclamped values, if available.  If not, *x, *y
+        * will have to do.
+        * NOTE: We should never get here with unclamped values unset.
+        */
+       if (unclamped_prex == -1 || unclamped_prey == -1) {
+           unclamped_prex = *x;
+           unclamped_prey = *y;
+       }
+
        /* How this works:
         * Given the origin and the movement vector, get the nearest barrier
         * to the origin that is blocking the movement.
@@ -1251,11 +1392,27 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x
         * Then, check from the clamped intersection to the original
         * destination, again finding the nearest barrier and clamping.
         */
-       dir = barrier_get_direction(ox, oy, *x, *y);
+       dir = barrier_get_direction(ox, oy, unclamped_prex, unclamped_prey);
+       barrier_calculate_velocity_components(ox, oy, unclamped_prex, unclamped_prey, &vel_x, &vel_y);
 
-       nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
+       nearest = barrier_find_nearest(cs, dir, ox, oy, unclamped_prex, unclamped_prey);
        if (nearest) {
-           barrier_clamp_to_barrier(nearest, dir, x, y);
+           int velocity = barrier_is_vertical(nearest) ? vel_x : vel_y;
+           Bool threshold_exceeded = (nearest->velocity != 0) &&
+                                     (velocity > nearest->velocity);
+
+           if (!nearest->lastHit) {
+               /* This is the start of a new barrier event */
+               nearest->barrierEventID++;
+           }
+
+           if ((!threshold_exceeded || nearest->lastHit) &&
+               (nearest->barrierEventID != nearest->releaseEventID)) {
+               barrier_clamp_to_barrier(nearest, dir, x, y);
+               nearest->hit = TRUE;
+           }
+
+           QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
 
            if (barrier_is_vertical(nearest)) {
                dir &= ~(BarrierNegativeX | BarrierPositiveX);
@@ -1265,11 +1422,31 @@ CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x
                oy = *y;
            }
 
-           nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
+           nearest = barrier_find_nearest(cs, dir, ox, oy, unclamped_prex, unclamped_prey);
            if (nearest) {
-               barrier_clamp_to_barrier(nearest, dir, x, y);
+               velocity = barrier_is_vertical(nearest) ? vel_x : vel_y;
+               threshold_exceeded = (nearest->velocity != 0) &&
+                                    (velocity > nearest->velocity);
+
+               if (!nearest->lastHit) {
+                   /* This is the start of a new barrier event */
+                   nearest->barrierEventID++;
+               }
+
+               if ((!threshold_exceeded || nearest->lastHit) &&
+                   (nearest->barrierEventID != nearest->releaseEventID)) {
+                   barrier_clamp_to_barrier(nearest, dir, x, y);
+                   nearest->hit = TRUE;
+               }
+
+               QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
            }
        }
+
+       list_for_each_entry(c, &cs->barriers, entry) {
+           c->barrier.lastHit = c->barrier.hit;
+           c->barrier.hit = FALSE;
+       }
     }
 
     if (cs->ConstrainCursorHarder) {
@@ -1284,15 +1461,45 @@ CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
                           xXFixesCreatePointerBarrierReq *stuff)
 {
     CursorScreenPtr cs = GetCursorScreen(screen);
-    struct PointerBarrierClient *ret = malloc(sizeof(*ret));
+    struct PointerBarrierClient *ret = calloc(sizeof(*ret), 1);
 
     if (ret) {
        ret->screen = screen;
+       ret->barrier.barrier = stuff->barrier;
        ret->barrier.x1 = min(stuff->x1, stuff->x2);
        ret->barrier.x2 = max(stuff->x1, stuff->x2);
        ret->barrier.y1 = min(stuff->y1, stuff->y2);
        ret->barrier.y2 = max(stuff->y1, stuff->y2);
        ret->barrier.directions = stuff->directions & 0x0f;
+       ret->barrier.velocity = 0;
+       ret->barrier.barrierEventID = 0;
+       if (barrier_is_horizontal(&ret->barrier))
+           ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
+       if (barrier_is_vertical(&ret->barrier))
+           ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY);
+       list_add(&ret->entry, &cs->barriers);
+    }
+
+    return ret;
+}
+
+static struct PointerBarrierClient *
+CreatePointerBarrierVelocityClient(ScreenPtr screen, ClientPtr client,
+                          xXFixesCreatePointerBarrierVelocityReq *stuff)
+{
+    CursorScreenPtr cs = GetCursorScreen(screen);
+    struct PointerBarrierClient *ret = calloc(sizeof(*ret), 1);
+
+    if (ret) {
+       ret->screen = screen;
+       ret->barrier.barrier = stuff->barrier;
+       ret->barrier.x1 = min(stuff->x1, stuff->x2);
+       ret->barrier.x2 = max(stuff->x1, stuff->x2);
+       ret->barrier.y1 = min(stuff->y1, stuff->y2);
+       ret->barrier.y2 = max(stuff->y1, stuff->y2);
+       ret->barrier.directions = stuff->directions & 0x0f;
+       ret->barrier.velocity = stuff->velocity;
+       ret->barrier.barrierEventID = 0;
        if (barrier_is_horizontal(&ret->barrier))
            ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
        if (barrier_is_vertical(&ret->barrier))
@@ -1365,6 +1572,69 @@ SProcXFixesCreatePointerBarrier (ClientPtr client)
     return ProcXFixesVector[stuff->xfixesReqType](client);
 }
 
+int
+ProcXFixesCreatePointerBarrierVelocity (ClientPtr client)
+{
+    int err;
+    WindowPtr pWin;
+    struct PointerBarrierClient *barrier;
+    struct PointerBarrier b;
+    REQUEST (xXFixesCreatePointerBarrierVelocityReq);
+
+    REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierVelocityReq);
+    LEGAL_NEW_RESOURCE(stuff->barrier, client);
+
+    err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
+    if (err != Success) {
+       client->errorValue = stuff->window;
+       return err;
+    }
+
+    /* This sure does need fixing. */
+    if (stuff->num_devices)
+       return BadImplementation;
+
+    b.x1 = stuff->x1;
+    b.x2 = stuff->x2;
+    b.y1 = stuff->y1;
+    b.y2 = stuff->y2;
+
+    if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b))
+       return BadValue;
+
+    /* no 0-sized barriers */
+    if (barrier_is_horizontal(&b) && barrier_is_vertical(&b))
+       return BadValue;
+
+    if (!(barrier = CreatePointerBarrierVelocityClient(pWin->drawable.pScreen,
+                                                      client, stuff)))
+       return BadAlloc;
+
+    if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
+       return BadAlloc;
+
+    return Success;
+}
+
+int
+SProcXFixesCreatePointerBarrierVelocity (ClientPtr client)
+{
+    int n;
+    REQUEST(xXFixesCreatePointerBarrierVelocityReq);
+
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
+    swapl(&stuff->barrier, n);
+    swapl(&stuff->window, n);
+    swaps(&stuff->x1, n);
+    swaps(&stuff->y1, n);
+    swaps(&stuff->x2, n);
+    swaps(&stuff->y2, n);
+    swapl(&stuff->directions, n);
+    swapl(&stuff->velocity, n);
+    return ProcXFixesVector[stuff->xfixesReqType](client);
+}
+
 static int
 CursorFreeBarrier(void *data, XID id)
 {
@@ -1421,6 +1691,118 @@ SProcXFixesDestroyPointerBarrier (ClientPtr client)
     return ProcXFixesVector[stuff->xfixesReqType](client);
 }
 
+static int
+CursorFreeBarrierClient(void *data, XID id)
+{
+    PointerBarrierEventClientPtr client = data, c;
+    ScreenPtr screen = client->screen;
+    CursorScreenPtr cs = GetCursorScreen(screen);
+
+    /* find and unlink from the screen private */
+    list_for_each_entry(c, &cs->barrierClients, entry) {
+       if (c == client) {
+           list_del(&c->entry);
+           break;
+       }
+    }
+
+    free(client);
+    return Success;
+}
+
+static struct PointerBarrierEventClient *
+CreatePointerBarrierEventClient(ScreenPtr screen, ClientPtr client,
+                                  xXFixesSelectBarrierInputReq *stuff)
+{
+    CursorScreenPtr cs = GetCursorScreen(screen);
+    struct PointerBarrierEventClient *ret = malloc(sizeof(*ret));
+
+    if (ret) {
+       ret->screen = screen;
+       ret->client = client;
+       ret->eventMask = stuff->eventMask;
+       ret->window = stuff->window;
+       ret->resource = FakeClientID (client->index);
+      list_add(&ret->entry, &cs->barrierClients);
+    }
+
+    return ret;
+}
+
+int
+ProcXFixesSelectBarrierInput (ClientPtr client)
+{
+    int err;
+    WindowPtr pWin;
+    struct PointerBarrierEventClient *eventClient;
+    REQUEST (xXFixesSelectBarrierInputReq);
+
+    REQUEST_SIZE_MATCH(xXFixesSelectBarrierInputReq);
+
+    err = dixLookupWindow(&pWin        , stuff->window, client, DixReadAccess);
+    if (err != Success) {
+       client->errorValue = stuff->window;
+       return err;
+    }
+
+    if (!(eventClient = CreatePointerBarrierEventClient(pWin->drawable.pScreen,
+                                                       client,
+                                                       stuff)))
+      return BadAlloc;
+
+    if (!AddResource (eventClient->resource, PointerBarrierClientType, eventClient))
+      return BadAlloc;
+
+    return Success;
+}
+
+int
+SProcXFixesSelectBarrierInput (ClientPtr client)
+{
+    int n;
+    REQUEST(xXFixesSelectBarrierInputReq);
+
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xXFixesSelectBarrierInputReq);
+    swapl(&stuff->window, n);
+    swapl(&stuff->eventMask, n);
+    return ProcXFixesVector[stuff->xfixesReqType](client);
+}
+
+int
+ProcXFixesBarrierReleasePointer (ClientPtr client)
+{
+    int err;
+    struct PointerBarrier *barrier;
+    REQUEST (xXFixesBarrierReleasePointerReq);
+    REQUEST_SIZE_MATCH(xXFixesBarrierReleasePointerReq);
+
+    err = dixLookupResourceByType((void **)&barrier, stuff->barrier,
+                                 PointerBarrierType, client,
+                                 DixReadAccess);
+    if (err != Success) {
+       client->errorValue = stuff->barrier;
+       return err;
+    }
+
+    barrier->releaseEventID = stuff->event_id;
+
+    return Success;
+}
+
+int
+SProcXFixesBarrierReleasePointer (ClientPtr client)
+{
+    int n;
+    REQUEST(xXFixesBarrierReleasePointerReq);
+
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xXFixesBarrierReleasePointerReq);
+    swapl(&stuff->barrier, n);
+    swapl(&stuff->event_id, n);
+    return ProcXFixesVector[stuff->xfixesReqType](client);
+}
+
 Bool
 XFixesCursorInit (void)
 {
@@ -1441,6 +1823,7 @@ XFixesCursorInit (void)
        if (!cs)
            return FALSE;
        list_init(&cs->barriers);
+       list_init(&cs->barrierClients);
        Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
        Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
        Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
@@ -1455,8 +1838,10 @@ XFixesCursorInit (void)
                                             "XFixesCursorWindow");
     PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
                                              "XFixesPointerBarrier");
+    PointerBarrierClientType = CreateNewResourceType(CursorFreeBarrierClient,
+                                                    "XFixesPointerBarrierClient");
 
     return CursorClientType && CursorHideCountType && CursorWindowType &&
-          PointerBarrierType;
+          PointerBarrierType && PointerBarrierClientType;
 }
 
index e0ebedd80827b028c0c6af0fbc8a0d5e20a24d9d..31182bcb575c717a5057bd433a66708e72a8abc4 100644 (file)
@@ -100,6 +100,7 @@ static const int version_requests[] = {
     X_XFixesExpandRegion,          /* Version 3 */
     X_XFixesShowCursor,                    /* Version 4 */
     X_XFixesDestroyPointerBarrier,  /* Version 5 */
+    X_XFixesBarrierReleasePointer, /* Version 6 */
 };
 
 #define NUM_VERSION_REQUESTS   (sizeof (version_requests) / sizeof (version_requests[0]))
@@ -143,6 +144,10 @@ int        (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
 /*************** Version 5 ****************/
     ProcXFixesCreatePointerBarrier,
     ProcXFixesDestroyPointerBarrier,
+/*************** Version 6 ****************/
+    ProcXFixesCreatePointerBarrierVelocity,
+    ProcXFixesSelectBarrierInput,
+    ProcXFixesBarrierReleasePointer,
 };
 
 static int
@@ -209,6 +214,10 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
 /*************** Version 5 ****************/
     SProcXFixesCreatePointerBarrier,
     SProcXFixesDestroyPointerBarrier,
+/*************** Version 6 ****************/
+    SProcXFixesCreatePointerBarrierVelocity,
+    SProcXFixesSelectBarrierInput,
+    SProcXFixesBarrierReleasePointer,
 };
 
 static int
index 5765e64b54388d3d86930fb61f90eb537aa79afe..8e53c6654176324a8250f524ba04aff1adeb0427 100644 (file)
@@ -28,6 +28,7 @@
 #define _XFIXES_H_
 
 #include "resource.h"
+#include "list.h"
 
 extern _X_EXPORT RESTYPE RegionResType;
 extern _X_EXPORT RESTYPE PointerBarrierType;
@@ -52,9 +53,25 @@ extern _X_EXPORT int XFixesErrorBase;
 extern _X_EXPORT RegionPtr
 XFixesRegionCopy (RegionPtr pRegion);
 
+typedef struct PointerBarrierEventClient *PointerBarrierEventClientPtr;
+
+struct PointerBarrierEventClient {
+    ScreenPtr screen;
+    ClientPtr client;
+    CARD32    eventMask;
+    XID window;
+    XID resource;
+    struct list entry;
+};
+
 struct PointerBarrier {
+    XID    barrier;
     CARD16 x1, x2, y1, y2;
     CARD32 directions;
+    CARD32 velocity;
+    CARD32 barrierEventID;
+    CARD32 releaseEventID;
+    Bool   hit, lastHit;
 };
 
 
index 6ba276e8c557028db576945042daf6af6c565fcf..cb00be6ac70f50a2b7fac596104850ad8158f081 100644 (file)
@@ -59,6 +59,7 @@
 #include "windowstr.h"
 #include "selection.h"
 #include "xfixes.h"
+#include "list.h"
 
 extern int             XFixesEventBase;
 
@@ -293,6 +294,26 @@ ProcXFixesDestroyPointerBarrier (ClientPtr client);
 int
 SProcXFixesDestroyPointerBarrier (ClientPtr client);
 
+/* Version 6 */
+
+int
+ProcXFixesSelectBarrierInput (ClientPtr client);
+
+int
+SProcXFixesSelectBarrierInput (ClientPtr client);
+
+int
+ProcXFixesCreatePointerBarrierVelocity (ClientPtr client);
+
+int
+SProcXFixesCreatePointerBarrierVelocity (ClientPtr client);
+
+int
+ProcXFixesBarrierReleasePointer (ClientPtr client);
+
+int
+SProcXFixesBarrierReleasePointer (ClientPtr client);
+
 /* Xinerama */
 extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
 void PanoramiXFixesInit (void);
index 71caa2f63686447fe463fa510b1c67b8ca90b3cd..a4a2ae0dcf71d93bb5d085b91c32d06bdd390cb5 100644 (file)
@@ -4,10 +4,10 @@ current keymap and/or any scratch keymaps used by clients.  The X server
 or some other tool might destroy or replace the files in this directory,
 so it is not a safe place to store compiled keymaps for long periods of
 time.  The default keymap for any server is usually stored in:
-     X<num>-default.xkm
-where <num> is the display number of the server in question, which makes
-it possible for several servers *on the same host* to share the same 
-directory.
+     server-<SHA1>.xkm
+
+where <SHA1> is the SHA1 hash of keymap source, so that compiled
+keymap of different keymap sources are stored in different files.
 
 Unless the X server is modified, sharing this directory between servers on
 different hosts could cause problems.
index e1020358a6c246bb14a49e4b4a122566255d8409..48204455740381290570701b8e4d61013d80763d 100644 (file)
@@ -30,6 +30,12 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include <xkb-config.h>
 
+#ifdef HAVE_SHA1_IN_LIBGCRYPT /* Use libgcrypt for SHA1 */
+# include <gcrypt.h>
+#else /* Use OpenSSL's libcrypto */
+#warning "xkbcomp caching support disabled"
+#endif
+
 #include <stdio.h>
 #include <ctype.h>
 #include <X11/X.h>
@@ -43,20 +49,9 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define        XKBSRV_NEED_FILE_FUNCS
 #include <xkbsrv.h>
 #include <X11/extensions/XI.h>
+#include <errno.h>
 #include "xkb.h"
 
-       /*
-        * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
-        * relative to the top-level XKB configuration directory.
-        * Making the server write to a subdirectory of that directory
-        * requires some work in the general case (install procedure
-        * has to create links to /var or somesuch on many machines),
-        * so we just compile into /usr/tmp for now.
-        */
-#ifndef XKM_OUTPUT_DIR
-#define        XKM_OUTPUT_DIR  "compiled/"
-#endif
-
 #define        PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\""
 #define        ERROR_PREFIX    "\"> \""
 #define        POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\""
@@ -170,6 +165,47 @@ OutputDirectory(
     }
 }
 
+#ifndef SHA_DIGEST_LENGTH
+#define SHA_DIGEST_LENGTH 20
+#endif
+
+static Bool
+Sha1Asc(char sha1Asc[SHA_DIGEST_LENGTH*2+1], const char * input)
+{
+    int i;
+    unsigned char sha1[SHA_DIGEST_LENGTH];
+
+#ifdef HAVE_SHA1_IN_LIBGCRYPT /* Use libgcrypt for SHA1 */
+    static int init;
+    gcry_md_hd_t h;
+    gcry_error_t err;
+
+    if (!init) {
+       if (!gcry_check_version(NULL))
+           return BadAlloc;
+       gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+       gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+       init = 1;
+    }
+
+    err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
+    if (err)
+       return BadAlloc;
+    gcry_md_write(h, input, strlen(input));
+    memcpy(sha1, gcry_md_read(h, GCRY_MD_SHA1), 20);
+    gcry_md_close(h);
+#endif
+
+    /* convert sha1 to sha1_asc */
+    for(i=0; i<SHA_DIGEST_LENGTH; ++i) {
+        sprintf(sha1Asc+i*2, "%02X", sha1[i]);
+    }
+
+    return Success;
+}
+
+/* call xkbcomp and compile XKB keymap, return xkm file name in
+   nameRtrn */
 static Bool
 XkbDDXCompileKeymapByNames(    XkbDescPtr              xkb,
                                XkbComponentNamesPtr    names,
@@ -179,7 +215,11 @@ XkbDDXCompileKeymapByNames(        XkbDescPtr              xkb,
                                int                     nameRtrnLen)
 {
     FILE *     out;
-    char       *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
+    char *     buf = NULL, xkmfile[PATH_MAX], xkm_output_dir[PATH_MAX];
+    char *     tmpXkmFile = NULL;
+    char *     canonicalXkmFileName = NULL;
+    char       sha1Asc[SHA_DIGEST_LENGTH*2+1], xkbKeyMapBuf[100*1024];
+    int        ret, result;
 
     const char *emptystring = "";
     char *xkbbasedirflag = NULL;
@@ -190,14 +230,67 @@ XkbDDXCompileKeymapByNames(       XkbDescPtr              xkb,
     /* WIN32 has no popen. The input must be stored in a file which is
        used as input for xkbcomp. xkbcomp does not read from stdin. */
     char tmpname[PATH_MAX];
-    const char *xkmfile = tmpname;
+    const char *xkbfile = tmpname;
 #else
-    const char *xkmfile = "-";
+    const char *xkbfile = "-";
 #endif
 
-    snprintf(keymap, sizeof(keymap), "server-%s", display);
+    /* Write keymap source (xkbfile) to memory buffer `xkbKeyMapBuf',
+       of which SHA1 is generated and used as result xkm file name  */
+    memset(xkbKeyMapBuf, 0, sizeof(xkbKeyMapBuf));
+    out = fmemopen(xkbKeyMapBuf, sizeof(xkbKeyMapBuf), "w");
+    if (NULL == out) {
+        ErrorF("[xkb] Open xkbKeyMapBuf for writing failed\n");
+        return FALSE;
+    }
+    ret = XkbWriteXKBKeymapForNames(out, names, xkb, want, need);
+    if (fclose(out) !=0)
+    {
+        ErrorF("[xkb] XkbWriteXKBKeymapForNames error, perhaps xkbKeyMapBuf is too small\n");
+        return FALSE;
+    }
+#ifdef DEBUG
+    if (xkbDebugFlags) {
+       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
+       fputs(xkbKeyMapBuf, stderr);
+    }
+#endif
+    if (!ret) {
+        ErrorF("[xkb] Generating XKB Keymap failed, giving up compiling keymap\n");
+        return FALSE;
+    }
+
+    DebugF("[xkb] computing SHA1 of keymap\n");
+    if (Success == Sha1Asc(sha1Asc, xkbKeyMapBuf)) {
+        snprintf(xkmfile, sizeof(xkmfile), "server-%s", sha1Asc);
+    }
+    else {
+        ErrorF("[xkb] Computing SHA1 of keymap failed, "
+               "using display name instead as xkm file name\n");
+        snprintf(xkmfile, sizeof(xkmfile), "server-%s", display);
+    }
 
     OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
+    /* set nameRtrn, fail if it's too small */
+    if ((strlen(xkmfile)+1 > nameRtrnLen) && nameRtrn) {
+        ErrorF("[xkb] nameRtrn too small to hold xkmfile name\n");
+        return FALSE;
+    }
+    strncpy(nameRtrn, xkmfile, nameRtrnLen);
+
+    /* if the xkm file already exists, reuse it */
+    canonicalXkmFileName = Xprintf("%s%s.xkm", xkm_output_dir, xkmfile);
+    if (access(canonicalXkmFileName, R_OK) == 0) {
+        /* yes, we can reuse the old xkm file */
+        LogMessage(X_INFO, "XKB: reuse xkmfile %s\n", canonicalXkmFileName);
+        result = TRUE;
+        goto _ret;
+    }
+    LogMessage(X_INFO, "XKB: generating xkmfile %s\n", canonicalXkmFileName);
+
+    /* continue to call xkbcomp to compile the keymap. to avoid race
+       condition, we compile it to a tmpfile then rename it to
+       xkmfile */
 
 #ifdef WIN32
     strcpy(tmpname, Win32TempDir());
@@ -222,15 +315,21 @@ XkbDDXCompileKeymapByNames(       XkbDescPtr              xkb,
        }
     }
 
+    if ( (tmpXkmFile = tempnam(xkm_output_dir, NULL)) == NULL ) {
+       ErrorF("[xkb] Can't generate temp xkm file name");
+       result = FALSE;
+       goto _ret;
+    }
+
     if (asprintf(&buf,
                 "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
-                 "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
+                 "-em1 %s -emp %s -eml %s \"%s\"",
                 xkbbindir, xkbbindirsep,
                 ((xkbDebugFlags < 2) ? 1 :
                  ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)),
-                xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
+                xkbbasedirflag ? xkbbasedirflag : "", xkbfile,
                 PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
-                xkm_output_dir, keymap) == -1)
+                tmpXkmFile) == -1)
        buf = NULL;
 
     free(xkbbasedirflag);
@@ -240,6 +339,11 @@ XkbDDXCompileKeymapByNames(        XkbDescPtr              xkb,
         return FALSE;
     }
     
+    /* there's a potential race condition between calling tempnam()
+       and invoking xkbcomp to write the result file (potential temp
+       file name conflicts), but since xkbcomp is a standalone
+       program, we have to live with this */
+
 #ifndef WIN32
     out= Popen(buf,"w");
 #else
@@ -247,30 +351,42 @@ XkbDDXCompileKeymapByNames(       XkbDescPtr              xkb,
 #endif
     
     if (out!=NULL) {
-#ifdef DEBUG
-    if (xkbDebugFlags) {
-       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
-       XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
-    }
-#endif
-       XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
+       /* write XKBKeyMapBuf to xkbcomp */
+       if (EOF==fputs(xkbKeyMapBuf, out))
+       {
+           ErrorF("[xkb] Sending keymap to xkbcomp failed\n");
+           result = FALSE;
+           goto _ret;
+       }
 #ifndef WIN32
        if (Pclose(out)==0)
 #else
        if (fclose(out)==0 && System(buf) >= 0)
 #endif
        {
+           /* xkbcomp success */
             if (xkbDebugFlags)
-                DebugF("[xkb] xkb executes: %s\n",buf);
-           if (nameRtrn) {
-               strncpy(nameRtrn,keymap,nameRtrnLen);
-               nameRtrn[nameRtrnLen-1]= '\0';
-           }
-            free(buf);
-           return TRUE;
+                DebugF("[xkb] xkb executes: %s\n",buf);
+
+           /* if canonicalXkmFileName already exists now, we simply
+              overwrite it, this is OK */
+           ret = rename(tmpXkmFile, canonicalXkmFileName);
+           if (0 != ret) {
+               ErrorF("[xkb] Can't rename %s to %s, error: %s\n",
+                      tmpXkmFile, canonicalXkmFileName,
+                      strerror(errno));
+
+               /* in case of error, don't unlink tmpXkmFile, leave i
+                  for debugging */
+
+               result = FALSE;
+               goto _ret;
+           }
+           result = TRUE;
+           goto _ret;
        }
        else
-           LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
+           LogMessage(X_ERROR, "Error compiling keymap (%s)\n", xkbfile);
 #ifdef WIN32
         /* remove the temporary file */
         unlink(tmpname);
@@ -285,8 +401,17 @@ XkbDDXCompileKeymapByNames(        XkbDescPtr              xkb,
     }
     if (nameRtrn)
        nameRtrn[0]= '\0';
-    free(buf);
-    return FALSE;
+    result = FALSE;
+
+_ret:
+    if (tmpXkmFile)
+       free(tmpXkmFile);
+    if (canonicalXkmFileName)
+       free(canonicalXkmFileName);
+    if (buf)
+       free(buf);
+    
+   return result;
 }
 
 static FILE *
@@ -371,7 +496,6 @@ unsigned    missing;
        DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
     }
     fclose(file);
-    (void) unlink (fileName);
     return (need|want)&(~missing);
 }
 
index cf2073738b00a400dfda0dc792567cce4f46bb53..6083fb1dc11b80a8869a41022fbf1dd56ce262f2 100644 (file)
@@ -328,24 +328,83 @@ _XkbFilterLatchState(     XkbSrvInfoPtr   xkbi,
     return 1;
 }
 
+static int xkbSwitchGroupOnRelease(void)
+{
+    /* TODO: user configuring */
+    return TRUE;
+}
+
+static void xkbUpdateLockedGroup(XkbSrvInfoPtr xkbi, XkbAction* pAction)
+{
+    XkbGroupAction ga = pAction->group;
+    if (ga.flags&XkbSA_GroupAbsolute)
+       xkbi->state.locked_group= XkbSAGroup(&ga);
+    else xkbi->state.locked_group+= XkbSAGroup(&ga);
+}
+
+static XkbFilterPtr _XkbNextFreeFilter(XkbSrvInfoPtr xkbi);
+
 static int
-_XkbFilterLockState(   XkbSrvInfoPtr   xkbi,
+_XkbFilterLockGroup(   XkbSrvInfoPtr   xkbi,
                        XkbFilterPtr    filter,
                        unsigned        keycode,
                        XkbAction *     pAction)
 {
-    if (pAction&&(pAction->type==XkbSA_LockGroup)) {
-       if (pAction->group.flags&XkbSA_GroupAbsolute)
-            xkbi->state.locked_group= XkbSAGroup(&pAction->group);
-       else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
-       return 1;
+    int sendEvent = 1;
+
+    if (!xkbSwitchGroupOnRelease()) {
+       xkbUpdateLockedGroup(xkbi, pAction);
+       return sendEvent;
+    }
+    
+    /* Delay switch till button release */
+    if (filter->keycode==0) {          /* initial press */
+       filter->keycode = keycode;
+       filter->active = 1;
+       filter->filterOthers = 0; /* for what? */
+       filter->filter = _XkbFilterLockGroup;
+
+       /* filter->priv = 0; */
+       filter->upAction = *pAction;
+
+       /* Ok, now we need to simulate the action which would go if this action didn't block it.
+          XkbSA_SetMods is the one: it is to set modifier' flag up. */
+       {
+           XkbStateRec fake_state = xkbi->state;
+           XkbAction act;
+
+           fake_state.mods = 0;
+           act = XkbGetKeyAction(xkbi, &fake_state, keycode);
+
+           /* KLUDGE: XkbSA_SetMods only? */
+           if (act.type == XkbSA_SetMods) { 
+               XkbFilterPtr filter = _XkbNextFreeFilter(xkbi);
+               sendEvent = _XkbFilterSetState(xkbi,filter,keycode,&act);
+           }
+       }
     }
+    else {
+       /* do nothing if some button else is pressed */
+       if (!pAction)
+           xkbUpdateLockedGroup(xkbi, &filter->upAction);
+       filter->active = 0;
+    }
+
+    return sendEvent;
+}
+
+static int
+_XkbFilterLockMods(    XkbSrvInfoPtr   xkbi,
+                       XkbFilterPtr    filter,
+                       unsigned        keycode,
+                       XkbAction *     pAction)
+{
     if (filter->keycode==0) {          /* initial press */
        filter->keycode = keycode;
        filter->active = 1;
        filter->filterOthers = 0;
        filter->priv = xkbi->state.locked_mods&pAction->mods.mask;
-       filter->filter = _XkbFilterLockState;
+       filter->filter = _XkbFilterLockMods;
        filter->upAction = *pAction;
        if (!(filter->upAction.mods.flags&XkbSA_LockNoLock))
            xkbi->state.locked_mods|= pAction->mods.mask;
@@ -1118,9 +1177,12 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
                    sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
                    break;
                case XkbSA_LockMods:
+                   filter = _XkbNextFreeFilter(xkbi);
+                   sendEvent=_XkbFilterLockMods(xkbi,filter,key,&act);
+                   break;
                case XkbSA_LockGroup:
                    filter = _XkbNextFreeFilter(xkbi);
-                   sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
+                   sendEvent=_XkbFilterLockGroup(xkbi,filter,key,&act);
                    break;
                case XkbSA_ISOLock:
                    filter = _XkbNextFreeFilter(xkbi);