xserver: Branch 'master' - 5 commits
Peter Hutterer
whot at kemper.freedesktop.org
Thu Feb 12 20:51:14 PST 2009
dix/enterleave.c | 103 ++++++++++++++++++++-----------------
dix/events.c | 70 +++++++++++++------------
dix/main.c | 1
dix/ptrveloc.c | 144 +++++++++++++++++++++++++++++++++-------------------
include/dix.h | 3 -
include/inputstr.h | 58 ++++++++++++++++++--
include/ptrveloc.h | 2
include/windowstr.h | 4 -
8 files changed, 239 insertions(+), 146 deletions(-)
New commits:
commit 340f1576afcdaf883d185da356e5d6282aa65e19
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Thu Feb 12 10:44:27 2009 +1000
dix: remove DefineInitialRootWindow()
Obsolete.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
diff --git a/dix/events.c b/dix/events.c
index 14a0e5e..598dc75 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2662,17 +2662,6 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
#endif
/**
- * Called from main() with the root window on the first screen. Used to do a
- * lot more when MPX wasn't around yet. Things change.
- *
- * Should delete this now? -ds
- */
-void
-DefineInitialRootWindow(WindowPtr win)
-{
-}
-
-/**
* Initialize a sprite for the given device and set it to some sane values. If
* the device already has a sprite alloc'd, don't realloc but just reset to
* default values.
diff --git a/dix/main.c b/dix/main.c
index 3c25e2e..1c66c86 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -362,7 +362,6 @@ int main(int argc, char *argv[], char *envp[])
for (i = 0; i < screenInfo.numScreens; i++)
InitRootWindow(WindowTable[i]);
- DefineInitialRootWindow(WindowTable[0]);
InitCoreDevices();
InitInput(argc, argv);
diff --git a/include/dix.h b/include/dix.h
index 658dd29..8d6b9ff 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -376,9 +376,6 @@ extern _X_EXPORT int DeliverDeviceEvents(
DeviceIntPtr /* dev */,
int /* count */);
-extern _X_EXPORT void DefineInitialRootWindow(
- WindowPtr /* win */);
-
extern _X_EXPORT void InitializeSprite(
DeviceIntPtr /* pDev */,
WindowPtr /* pWin */);
commit c178c3f814f7666f43cbf47d24c7543b289f9b1a
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Thu Feb 12 15:29:38 2009 +1000
dix: doxygen-ify enterleave.c
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
diff --git a/dix/enterleave.c b/dix/enterleave.c
index b8de9f0..2f2cff4 100644
--- a/dix/enterleave.c
+++ b/dix/enterleave.c
@@ -34,8 +34,11 @@
#include "exglobals.h"
#include "enterleave.h"
-/* @file This file describes the model for sending core enter/leave events and
- * focus in/out in the case of multiple pointers/keyboard foci
+/**
+ * @file
+ * This file describes the model for sending core enter/leave events and
+ * focus in/out in the case of multiple pointers/keyboard foci.
+ *
* Since we can't send more than one Enter or Leave/Focus in or out event per
* window to a core client without confusing it, this is a rather complicated
* approach.
@@ -49,7 +52,7 @@
* http://lists.freedesktop.org/archives/xorg/2008-December/041740.html
*
* Additional notes:
- * -) The core protocol spec says that "In a LeaveNotify event, if a child of the
+ * - The core protocol spec says that "In a LeaveNotify event, if a child of the
* event window contains the initial position of the pointer, then the child
* component is set to that child. Otherwise, it is None. For an EnterNotify
* event, if a child of the event window contains the final pointer position,
@@ -58,7 +61,7 @@
* By inference, this means that only NotifyVirtual or NotifyNonlinearVirtual
* events may have a subwindow set to other than None.
*
- * -) NotifyPointer events may be sent if the focus changes from window A to
+ * - NotifyPointer events may be sent if the focus changes from window A to
* B. The assumption used in this model is that NotifyPointer events are only
* sent for the pointer paired with the keyboard that is involved in the focus
* events. For example, if F(W) changes because of keyboard 2, then
@@ -69,7 +72,7 @@ static WindowPtr PointerWindows[MAXDEVICES];
static WindowPtr FocusWindows[MAXDEVICES];
/**
- * Return TRUE if @win has a pointer within its boundaries, excluding child
+ * Return TRUE if 'win' has a pointer within its boundaries, excluding child
* window.
*/
static BOOL
@@ -85,7 +88,7 @@ HasPointer(WindowPtr win)
}
/**
- * Return TRUE if at least one keyboard focus is set to @win (excluding
+ * Return TRUE if at least one keyboard focus is set to 'win' (excluding
* descendants of win).
*/
static BOOL
@@ -100,7 +103,7 @@ HasFocus(WindowPtr win)
}
/**
- * Return the window the device @dev is currently on.
+ * Return the window the device dev is currently on.
*/
static WindowPtr
PointerWin(DeviceIntPtr dev)
@@ -109,7 +112,7 @@ PointerWin(DeviceIntPtr dev)
}
/**
- * Search for the first window below @win that has a pointer directly within
+ * Search for the first window below 'win' that has a pointer directly within
* it's boundaries (excluding boundaries of its own descendants).
*
* @return The child window that has the pointer within its boundaries or
@@ -129,7 +132,7 @@ FirstPointerChild(WindowPtr win)
}
/**
- * Search for the first window below @win that has a focus directly within
+ * Search for the first window below 'win' that has a focus directly within
* it's boundaries (excluding boundaries of its own descendants).
*
* @return The child window that has the pointer within its boundaries or
@@ -150,7 +153,7 @@ FirstFocusChild(WindowPtr win)
}
/**
- * Set the presence flag for @dev to mark that it is now in @win.
+ * Set the presence flag for dev to mark that it is now in 'win'.
*/
void
EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode)
@@ -159,7 +162,7 @@ EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode)
}
/**
- * Unset the presence flag for @dev to mark that it is not in @win anymore.
+ * Unset the presence flag for dev to mark that it is not in 'win' anymore.
*/
static void
LeaveWindow(DeviceIntPtr dev, WindowPtr win, int mode)
@@ -168,7 +171,7 @@ LeaveWindow(DeviceIntPtr dev, WindowPtr win, int mode)
}
/**
- * Set the presence flag for @dev to mark that it is now in @win.
+ * Set the presence flag for dev to mark that it is now in 'win'.
*/
void
SetFocusIn(DeviceIntPtr dev, WindowPtr win)
@@ -177,7 +180,7 @@ SetFocusIn(DeviceIntPtr dev, WindowPtr win)
}
/**
- * Unset the presence flag for @dev to mark that it is not in @win anymore.
+ * Unset the presence flag for dev to mark that it is not in 'win' anymore.
*/
void
SetFocusOut(DeviceIntPtr dev, WindowPtr win)
@@ -189,7 +192,11 @@ SetFocusOut(DeviceIntPtr dev, WindowPtr win)
/**
- * @return The window that is the first ancestor of both a and b.
+ * Return the common ancestor of 'a' and 'b' (if one exists).
+ * @param a A window with the same ancestor as b.
+ * @param b A window with the same ancestor as a.
+ * @return The window that is the first ancestor of both 'a' and 'b', or the
+ * NullWindow if they do not have a common ancestor.
*/
WindowPtr
CommonAncestor(
@@ -203,10 +210,11 @@ CommonAncestor(
/**
- * Send enter notifies to all windows between @ancestor and @child (excluding
+ * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
* both). Events are sent running up the window hierarchy. This function
* recurses.
- * If @core is TRUE, core events are sent, otherwise XI events will be sent.
+ *
+ * @param core If TRUE, core events are sent, otherwise XI events will be sent.
*/
static void
DeviceEnterNotifies(DeviceIntPtr dev,
@@ -225,7 +233,7 @@ DeviceEnterNotifies(DeviceIntPtr dev,
}
/**
- * Send enter notifies to all windows between @ancestor and @child (excluding
+ * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
* both). Events are sent running down the window hierarchy. This function
* recurses.
*/
@@ -310,7 +318,7 @@ CoreLeaveNotifies(DeviceIntPtr dev,
}
/**
- * Send leave notifies to all windows between @child and @ancestor.
+ * Send leave notifies to all windows between 'child' and 'ancestor'.
* Events are sent running up the hierarchy.
*/
static void
@@ -333,8 +341,8 @@ DeviceLeaveNotifies(DeviceIntPtr dev,
}
/**
- * Pointer @dev moves from @A to @B and @A neither a descendant of @B nor is
- * @B a descendant of @A.
+ * Pointer dev moves from A to B and A neither a descendant of B nor is
+ * B a descendant of A.
*/
static void
CoreEnterLeaveNonLinear(DeviceIntPtr dev,
@@ -418,7 +426,7 @@ CoreEnterLeaveNonLinear(DeviceIntPtr dev,
}
/**
- * Pointer @dev moves from @A to @B and @A is a descendant of @B.
+ * Pointer dev moves from A to B and A is a descendant of B.
*/
static void
CoreEnterLeaveToAncestor(DeviceIntPtr dev,
@@ -476,7 +484,7 @@ CoreEnterLeaveToAncestor(DeviceIntPtr dev,
/**
- * Pointer @dev moves from @A to @B and @B is a descendant of @A.
+ * Pointer dev moves from A to B and B is a descendant of A.
*/
static void
CoreEnterLeaveToDescendant(DeviceIntPtr dev,
@@ -605,7 +613,7 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
}
/**
- * Send focus out events to all windows between @child and @ancestor.
+ * Send focus out events to all windows between 'child' and 'ancestor'.
* Events are sent running up the hierarchy.
*/
static void
@@ -625,7 +633,7 @@ DeviceFocusOutEvents(DeviceIntPtr dev,
/**
- * Send enter notifies to all windows between @ancestor and @child (excluding
+ * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
* both). Events are sent running up the window hierarchy. This function
* recurses.
*/
@@ -645,7 +653,7 @@ DeviceFocusInEvents(DeviceIntPtr dev,
}
/**
- * Send FocusIn events to all windows between @ancestor and @child (excluding
+ * Send FocusIn events to all windows between 'ancestor' and 'child' (excluding
* both). Events are sent running down the window hierarchy. This function
* recurses.
*/
@@ -727,13 +735,13 @@ CoreFocusOutEvents(DeviceIntPtr dev,
/**
* Send FocusOut(NotifyPointer) events from the current pointer window (which
- * is a descendant of @pwin_parent) up to (excluding) @pwin_parent.
+ * is a descendant of pwin_parent) up to (excluding) pwin_parent.
*
- * NotifyPointer events are only sent for the device paired with @dev.
+ * NotifyPointer events are only sent for the device paired with dev.
*
- * If the current pointer window is a descendat of @exclude or an ancestor of
- * @exclude, no events are sent. Note: If the current pointer IS @exclude,
- * events are sent!
+ * If the current pointer window is a descendant of 'exclude' or an ancestor of
+ * 'exclude', no events are sent. If the current pointer IS 'exclude', events
+ * are sent!
*/
static void
CoreFocusOutNotifyPointerEvents(DeviceIntPtr dev,
@@ -782,13 +790,13 @@ CoreFocusInRecurse(DeviceIntPtr dev,
/**
- * Send FocusIn(NotifyPointer) events from @pwin_parent down to
- * including the current pointer window (which is a descendant of @pwin_parent).
- * If @inclusive is TRUE, @pwin_parent will receive the event too.
+ * Send FocusIn(NotifyPointer) events from pwin_parent down to
+ * including the current pointer window (which is a descendant of pwin_parent).
*
- * @pwin is the pointer window.
- *
- * If the current pointer window is a child of @exclude, no events are sent.
+ * @param pwin The pointer window.
+ * @param exclude If the pointer window is a child of 'exclude', no events are
+ * sent.
+ * @param inclusive If TRUE, pwin_parent will receive the event too.
*/
static void
CoreFocusInNotifyPointerEvents(DeviceIntPtr dev,
@@ -812,8 +820,8 @@ CoreFocusInNotifyPointerEvents(DeviceIntPtr dev,
/**
- * Focus of @dev moves from @A to @B and @A neither a descendant of @B nor is
- * @B a descendant of @A.
+ * Focus of dev moves from A to B and A neither a descendant of B nor is
+ * B a descendant of A.
*/
static void
CoreFocusNonLinear(DeviceIntPtr dev,
@@ -910,7 +918,7 @@ CoreFocusNonLinear(DeviceIntPtr dev,
/**
- * Focus of @dev moves from @A to @B and @A is a descendant of @B.
+ * Focus of dev moves from A to B and A is a descendant of B.
*/
static void
CoreFocusToAncestor(DeviceIntPtr dev,
@@ -971,7 +979,7 @@ CoreFocusToAncestor(DeviceIntPtr dev,
}
/**
- * Focus of @dev moves from @A to @B and @B is a descendant of @A.
+ * Focus of dev moves from A to B and B is a descendant of A.
*/
static void
CoreFocusToDescendant(DeviceIntPtr dev,
@@ -1068,7 +1076,7 @@ CoreFocusPointerRootNoneSwitch(DeviceIntPtr dev,
if (!HasOtherPointer(root, GetPairedDevice(dev)) && !FirstFocusChild(root))
{
/* If pointer was on PointerRootWin and changes to NoneWin, and
- * the pointer paired with @dev is below the current root window,
+ * the pointer paired with dev is below the current root window,
* do a NotifyPointer run. */
if (dev->focus && dev->focus->win == PointerRootWin &&
B != PointerRootWin)
@@ -1087,8 +1095,8 @@ CoreFocusPointerRootNoneSwitch(DeviceIntPtr dev,
}
/**
- * Focus moves from window @A to PointerRoot or to None.
- * Assumption: @A is a valid window and not PointerRoot or None.
+ * Focus moves from window A to PointerRoot or to None.
+ * Assumption: A is a valid window and not PointerRoot or None.
*/
static void
CoreFocusToPointerRootOrNone(DeviceIntPtr dev,
@@ -1136,8 +1144,8 @@ CoreFocusToPointerRootOrNone(DeviceIntPtr dev,
}
/**
- * Focus moves from PointerRoot or None to a window @to.
- * Assumption: @to is a valid window and not PointerRoot or None.
+ * Focus moves from PointerRoot or None to a window B.
+ * Assumption: B is a valid window and not PointerRoot or None.
*/
static void
CoreFocusFromPointerRootOrNone(DeviceIntPtr dev,
@@ -1160,7 +1168,7 @@ CoreFocusFromPointerRootOrNone(DeviceIntPtr dev,
if (!HasFocus(root) && !FirstFocusChild(root))
{
/* If pointer was on PointerRootWin and changes to NoneWin, and
- * the pointer paired with @dev is below the current root window,
+ * the pointer paired with dev is below the current root window,
* do a NotifyPointer run. */
if (dev->focus && dev->focus->win == PointerRootWin &&
B != PointerRootWin)
@@ -1229,6 +1237,9 @@ CoreFocusEvents(DeviceIntPtr dev,
SetFocusIn(dev, to);
}
+/**
+ * The root window the given device is currently on.
+ */
#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
static void
commit cc696a2b7928ec497b6a0df3602fc70dec83a629
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Thu Feb 12 15:05:57 2009 +1000
Doxygen-ify bits of events.c
diff --git a/dix/events.c b/dix/events.c
index d34d739..14a0e5e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -107,7 +107,7 @@ of the copyright holder.
******************************************************************/
-/** @file
+/** @file events.c
* This file handles event delivery and a big part of the server-side protocol
* handling (the parts for input devices).
*/
@@ -163,9 +163,7 @@ typedef const char *string;
#include "enterleave.h"
-/**
- * Extension events type numbering starts at EXTENSION_EVENT_BASE.
- */
+/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */
#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
#define AllButtonsMask ( \
@@ -246,30 +244,35 @@ InputInfo inputInfo;
/**
* syncEvents is the global structure for queued events.
+ *
* Devices can be frozen through GrabModeSync pointer grabs. If this is the
* case, events from these devices are added to "pending" instead of being
* processed normally. When the device is unfrozen, events in "pending" are
* replayed and processed as if they would come from the device directly.
- *
- * pending ... list of queued events
- * pendtail ... last event in list
- * replayDev ... The device to replay events for. Only set in AllowEvents, in
- * which case it is set to the device specified in the request.
- * replayWin ... the window the events are supposed to be replayed on. This
- * window may be set to the grab's window (but only when
- * Replay{Pointer|Keyboard} is given in the XAllowEvents
- * request.
- * playingEvents ... flag to indicate whether we're in the process of
- * replaying events. Only set in ComputeFreezes().
*/
static struct {
- QdEventPtr pending, *pendtail;
+ QdEventPtr pending, /**< list of queued events */
+ *pendtail; /**< last event in list */
+ /** The device to replay events for. Only set in AllowEvents(), in which
+ * case it is set to the device specified in the request. */
DeviceIntPtr replayDev; /* kludgy rock to put flag for */
+
+ /**
+ * The window the events are supposed to be replayed on.
+ * This window may be set to the grab's window (but only when
+ * Replay{Pointer|Keyboard} is given in the XAllowEvents()
+ * request. */
WindowPtr replayWin; /* ComputeFreezes */
+ /**
+ * Flag to indicate whether we're in the process of
+ * replaying events. Only set in ComputeFreezes(). */
Bool playingEvents;
TimeStamp time;
} syncEvents;
+/**
+ * The root window the given device is currently on.
+ */
#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
static xEvent* swapEvent = NULL;
@@ -277,6 +280,7 @@ static int swapEventLen = 0;
/**
* Convert the given event type from an XI event to a core event.
+ * @param[in] The XI 1.x event type.
* @return The matching core event type or 0 if there is none.
*/
int
@@ -298,8 +302,8 @@ XItoCoreType(int xitype)
}
/**
- * True if device owns a cursor, false if device shares a cursor sprite with
- * another device.
+ * @return true if the device owns a cursor, false if device shares a cursor
+ * sprite with another device.
*/
Bool
DevHasCursor(DeviceIntPtr pDev)
@@ -308,7 +312,7 @@ DevHasCursor(DeviceIntPtr pDev)
}
/*
- * Return true if a device is a pointer, check is the same as used by XI to
+ * @return true if a device is a pointer, check is the same as used by XI to
* fill the 'use' field.
*/
Bool
@@ -318,7 +322,7 @@ IsPointerDevice(DeviceIntPtr dev)
}
/*
- * Return true if a device is a keyboard, check is the same as used by XI to
+ * @return true if a device is a keyboard, check is the same as used by XI to
* fill the 'use' field.
*
* Some pointer devices have keys as well (e.g. multimedia keys). Try to not
commit 8364bf7374aa5f6d991700f0c02921dc6c638c9f
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Wed Feb 11 16:06:36 2009 +1000
Document the event masks.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
diff --git a/dix/events.c b/dix/events.c
index 0db2d6a..d34d739 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -345,11 +345,20 @@ static Mask lastEventMask;
extern int DeviceMotionNotify;
+#define CantBeFiltered NoEventMask
/**
- * Event filters. One set of filters for each device, but only the first layer
+ * Event masks for each event type.
+ *
+ * One set of filters for each device, but only the first layer
* is initialized. The rest is memcpy'd in InitEvents.
+ *
+ * Filters are used whether a given event may be delivered to a client,
+ * usually in the form of if (window-event-mask & filter); then deliver event.
+ *
+ * One notable filter is for PointerMotion/DevicePointerMotion events. Each
+ * time a button is pressed, the filter is modified to also contain the
+ * matching ButtonXMotion mask.
*/
-#define CantBeFiltered NoEventMask
static Mask filters[MAXDEVICES][128] = {
{
NoSuchEvent, /* 0 */
@@ -3621,7 +3630,7 @@ FixKeyState (xEvent *xE, DeviceIntPtr keybd)
* The otherEventMasks on a WindowOptional is the combination of all event
* masks set by all clients on the window.
* deliverableEventMask is the combination of the eventMask and the
- * otherEventMask.
+ * otherEventMask plus the events that may be propagated to the parent.
*
* Traverses to siblings and parents of the window.
*/
diff --git a/include/inputstr.h b/include/inputstr.h
index 2b6de02..bed71be 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -65,24 +65,66 @@ SOFTWARE.
#define EMASKSIZE MAXDEVICES + 1
-/* Kludge: OtherClients and InputClients must be compatible, see code */
-
+/**
+ * This struct stores the core event mask for each client except the client
+ * that created the window.
+ *
+ * Each window that has events selected from other clients has at least one of
+ * these masks. If multiple clients selected for events on the same window,
+ * these masks are in a linked list.
+ *
+ * The event mask for the client that created the window is stored in
+ * win->eventMask instead.
+ *
+ * The resource id is simply a fake client ID to associate this mask with a
+ * client.
+ *
+ * Kludge: OtherClients and InputClients must be compatible, see code.
+ */
typedef struct _OtherClients {
- OtherClientsPtr next;
- XID resource; /* id for putting into resource manager */
- Mask mask;
+ OtherClientsPtr next; /**< Pointer to the next mask */
+ XID resource; /**< id for putting into resource manager */
+ Mask mask; /**< Core event mask */
} OtherClients;
+/**
+ * This struct stores the XI event mask for each client.
+ *
+ * Each window that has events selected has at least one of these masks. If
+ * multiple client selected for events on the same window, these masks are in
+ * a linked list.
+ */
typedef struct _InputClients {
- InputClientsPtr next;
- XID resource; /* id for putting into resource manager */
- Mask mask[EMASKSIZE];
+ InputClientsPtr next; /**< Pointer to the next mask */
+ XID resource; /**< id for putting into resource manager */
+ Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */
} InputClients;
+/**
+ * Combined XI event masks from all devices.
+ *
+ * This is the XI equivalent of the deliverableEvents, eventMask and
+ * dontPropagate mask of the WindowRec (or WindowOptRec).
+ *
+ * A window that has an XI client selecting for events has exactly one
+ * OtherInputMasks struct and exactly one InputClients struct hanging off
+ * inputClients. Each further client appends to the inputClients list.
+ * Each Mask field is per-device, with the device id as the index.
+ * Exception: for non-device events (Presence events), the MAX_DEVICES
+ * deviceid is used.
+ */
typedef struct _OtherInputMasks {
+ /**
+ * Bitwise OR of all masks by all clients and the window's parent's masks.
+ */
Mask deliverableEvents[EMASKSIZE];
+ /**
+ * Bitwise OR of all masks by all clients on this window.
+ */
Mask inputEvents[EMASKSIZE];
+ /** The do-not-propagate masks for each device. */
Mask dontPropagateMask[EMASKSIZE];
+ /** The clients that selected for events */
InputClientsPtr inputClients;
} OtherInputMasks;
diff --git a/include/windowstr.h b/include/windowstr.h
index 8ce3230..720803a 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -153,8 +153,8 @@ typedef struct _Window {
RegionRec borderSize;
DDXPointRec origin; /* position relative to parent */
unsigned short borderWidth;
- unsigned short deliverableEvents;
- Mask eventMask;
+ unsigned short deliverableEvents; /* all masks from all clients */
+ Mask eventMask; /* mask from the creating client */
PixUnion background;
PixUnion border;
pointer backStorage; /* null when BS disabled */
commit ed9d58c3c25ee1b3dedbc4c116823c263ccf164d
Author: Simon Thum <simon.thum at gmx.de>
Date: Sun Feb 8 17:21:09 2009 +0100
dix: refactor pointer acceleration
The algorithm is split in a 2D-specific and a general part.
This potentially allows to accelerate more than just screen motion.
A state machine is intoduced to make code more explicit and readable.
It also improves handling of 'phase 1' mickeys when axial correction
kicks in (corner case).
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c
index dcf91df..30e0207 100644
--- a/dix/ptrveloc.c
+++ b/dix/ptrveloc.c
@@ -81,7 +81,8 @@ SimpleSmoothProfile(DeviceVelocityPtr pVel, float velocity,
float threshold, float acc);
static PointerAccelerationProfileFunc
GetAccelerationProfile(DeviceVelocityPtr s, int profile_num);
-
+static short
+ProcessVelocityData(DeviceVelocityPtr s, float distance, int diff);
/*#define PTRACCEL_DEBUGGING*/
@@ -519,38 +520,35 @@ GetAxis(int dx, int dy){
return 1;
if(dy == 1 || dy == -1)
return 2;
- return -1;
- }else{
- return -1;
}
+ return -1;
}
/**
- * Perform velocity approximation
+ * Perform velocity approximation based on 2D 'mickeys' (mouse motion delta).
* return true if non-visible state reset is suggested
*/
static short
-ProcessVelocityData(
+ProcessVelocityData2D(
DeviceVelocityPtr s,
int dx,
int dy,
int time)
{
- float cvelocity;
+ float distance;
int diff = time - s->lrm_time;
int cur_ax, last_ax;
- short reset = (diff >= s->reset_time);
+ BOOL reset;
- /* remember last round's result */
- s->last_velocity = s->velocity;
cur_ax = GetAxis(dx, dy);
last_ax = GetAxis(s->last_dx, s->last_dy);
- if(cur_ax != last_ax && cur_ax != -1 && last_ax != -1 && !reset){
+ if(cur_ax != last_ax && cur_ax != -1 && last_ax != -1 &&
+ diff < s->reset_time){
/* correct for the error induced when diagonal movements are
- reported as alternating axis mickeys */
+ reported as alternating axis-aligned mickeys */
dx += s->last_dx;
dy += s->last_dy;
diff += s->last_diff;
@@ -560,6 +558,33 @@ ProcessVelocityData(
s->last_diff = diff;
}
+ distance = (float)sqrt(dx*dx + dy*dy);
+
+ s->lrm_time = time;
+
+ reset = ProcessVelocityData(s, distance, diff);
+
+ if(reset)
+ s->last_diff = 1;
+ return reset;
+}
+
+/**
+ * Perform velocity approximation given a one-dimensional delta.
+ * return true if non-visible state reset is suggested
+ */
+static short
+ProcessVelocityData(
+ DeviceVelocityPtr s,
+ float distance,
+ int diff)
+{
+ float cvelocity;
+ int phase;
+
+ /* remember previous result */
+ s->last_velocity = s->velocity;
+
/*
* cvelocity is not a real velocity yet, more a motion delta. constant
* acceleration is multiplied here to make the velocity an on-screen
@@ -567,9 +592,7 @@ ProcessVelocityData(
* make multiple devices with widely varying ConstantDecelerations respond
* similar to acceleration controls.
*/
- cvelocity = (float)sqrt(dx*dx + dy*dy) * s->const_acceleration;
-
- s->lrm_time = time;
+ cvelocity = distance * s->const_acceleration;
if (s->reset_time < 0 || diff < 0) { /* reset disabled or timer overrun? */
/* simply set velocity from current movement, no reset. */
@@ -577,6 +600,24 @@ ProcessVelocityData(
return FALSE;
}
+ /* try to determine 'phase', i.e. whether we process the first(0),
+ * second(1) or any following motion event of a stroke(2) */
+ if(diff >= s->reset_time && cvelocity < 10){
+ phase = 0;
+ }else{
+ switch(s->last_phase){
+ case 0:
+ case 1:
+ phase = s->last_phase + 1;
+ break;
+ default:
+ phase = 2;
+ break;
+ }
+ }
+ s->last_phase = phase;
+ DebugAccelF("(dix ptracc) phase: %i\n", phase);
+
if (diff == 0)
diff = 1; /* prevent div-by-zero, though it shouldn't happen anyway*/
@@ -584,47 +625,47 @@ ProcessVelocityData(
so we multiply by some per-device adjustable factor) */
cvelocity = cvelocity * s->corr_mul / (float)diff;
- /* short-circuit: when nv-reset the rest can be skipped */
- if(reset == TRUE){
+ switch(phase){
+ case 0:
/*
- * we don't really have a velocity here, since diff includes inactive
- * time. This is dealt with in ComputeAcceleration.
+ * First event of a stroke.
+ * We don't really have a velocity here, since diff includes inactive
+ * time. This is dealt with in ComputeAcceleration. Here we cancel out
+ * remnants from previous strokes which the user is presumably
+ * not aware of (non-visible state reset).
*/
StuffFilterChain(s, cvelocity);
s->velocity = s->last_velocity = cvelocity;
- s->last_reset = TRUE;
DebugAccelF("(dix ptracc) non-visible state reset\n");
return TRUE;
- }
-
- if(s->last_reset == TRUE){
+ case 1:
/*
* when here, we're probably processing the second mickey of a starting
* stroke. This happens to be the first time we can reasonably pretend
* that cvelocity is an actual velocity. Thus, to opt precision, we
* stuff that into the filter chain.
*/
- s->last_reset = FALSE;
DebugAccelF("(dix ptracc) after-reset vel:%.3f\n", cvelocity);
StuffFilterChain(s, cvelocity);
s->velocity = cvelocity;
return FALSE;
+ default:
+ /* normal operarion: feed into filter chain */
+ FeedFilterChain(s, cvelocity, diff);
+
+ /* perform coupling and decide final value */
+ s->velocity = QueryFilterChain(s, cvelocity);
+
+ DebugAccelF(
+ "(dix ptracc) guess: vel=%.3f diff=%d %i|%i|%i|%i|%i|%i|%i|%i|%i\n",
+ s->velocity, diff,
+ s->statistics.filter_usecount[0], s->statistics.filter_usecount[1],
+ s->statistics.filter_usecount[2], s->statistics.filter_usecount[3],
+ s->statistics.filter_usecount[4], s->statistics.filter_usecount[5],
+ s->statistics.filter_usecount[6], s->statistics.filter_usecount[7],
+ s->statistics.filter_usecount[8]);
+ return FALSE;
}
-
- /* feed into filter chain */
- FeedFilterChain(s, cvelocity, diff);
-
- /* perform coupling and decide final value */
- s->velocity = QueryFilterChain(s, cvelocity);
-
- DebugAccelF("(dix ptracc) guess: vel=%.3f diff=%d %i|%i|%i|%i|%i|%i|%i|%i|%i\n",
- s->velocity, diff,
- s->statistics.filter_usecount[0], s->statistics.filter_usecount[1],
- s->statistics.filter_usecount[2], s->statistics.filter_usecount[3],
- s->statistics.filter_usecount[4], s->statistics.filter_usecount[5],
- s->statistics.filter_usecount[6], s->statistics.filter_usecount[7],
- s->statistics.filter_usecount[8]);
- return FALSE;
}
@@ -696,7 +737,7 @@ ComputeAcceleration(
float acc){
float res;
- if(vel->last_reset){
+ if(vel->last_phase == 0){
DebugAccelF("(dix ptracc) profile skipped\n");
/*
* This is intended to override the first estimate of a stroke,
@@ -1009,6 +1050,7 @@ acceleratePointerPredictable(
DeviceVelocityPtr velocitydata =
(DeviceVelocityPtr) pDev->valuator->accelScheme.accelData;
float fdx, fdy; /* no need to init */
+ Bool soften = TRUE;
if (!num_valuators || !valuators || !velocitydata)
return;
@@ -1023,16 +1065,15 @@ acceleratePointerPredictable(
}
if (dx || dy){
- /* reset nonvisible state? */
- if (ProcessVelocityData(velocitydata, dx , dy, evtime)) {
- /* set to center of pixel. makes sense as long as there are no
- * means of passing on sub-pixel values.
+ /* reset non-visible state? */
+ if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) {
+ /* if nv-reset: set to center of pixel.
+ * makes sense as long as there are no means of passing on
+ * sub-pixel values to apps(XI2?). If you remove it, make
+ * sure suitable rounding is applied below.
*/
pDev->last.remainder[0] = pDev->last.remainder[1] = 0.5f;
- /* prevent softening (somewhat quirky solution,
- as it depends on the algorithm) */
- velocitydata->last_dx = dx;
- velocitydata->last_dy = dy;
+ soften = FALSE;
}
if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
@@ -1044,9 +1085,10 @@ acceleratePointerPredictable(
if(mult != 1.0 || velocitydata->const_acceleration != 1.0) {
ApplySofteningAndConstantDeceleration( velocitydata,
- dx, dy,
- &fdx, &fdy,
- mult > 1.0);
+ dx, dy,
+ &fdx, &fdy,
+ (mult > 1.0) && soften);
+
if (dx) {
pDev->last.remainder[0] = mult * fdx + pDev->last.remainder[0];
*px = (int)pDev->last.remainder[0];
diff --git a/include/ptrveloc.h b/include/ptrveloc.h
index 096dea8..f9933c9 100644
--- a/include/ptrveloc.h
+++ b/include/ptrveloc.h
@@ -83,7 +83,7 @@ typedef struct _DeviceVelocityRec {
int lrm_time; /* time the last motion event was processed */
int last_dx, last_dy; /* last motion delta */
int last_diff; /* last time-difference */
- Bool last_reset; /* whether a nv-reset occurred just before */
+ int last_phase; /* phase of last/current estimate */
float corr_mul; /* config: multiply this into velocity */
float const_acceleration; /* config: (recipr.) const deceleration */
float min_acceleration; /* config: minimum acceleration */
More information about the xorg-commit
mailing list