summaryrefslogtreecommitdiff
path: root/Development/Documentation/CursorHandling.mdwn
diff options
context:
space:
mode:
authorJoe Rayhawk <jrayhawk@freedesktop.org>2013-07-08 07:19:36 +0000
committerJoe Rayhawk <jrayhawk@freedesktop.org>2013-07-08 07:19:36 +0000
commit4e020a8ca7ab7059d9ead20cee91e7ad2899cae2 (patch)
treeb43aa26cbec12b1590afc8eff9a7f22d1320782a /Development/Documentation/CursorHandling.mdwn
parente0cf8f569dfddbf5c8a5e2038e8235ebca385911 (diff)
moin2mdwn: convert page Development/Documentation/CursorHandling
Diffstat (limited to 'Development/Documentation/CursorHandling.mdwn')
-rw-r--r--Development/Documentation/CursorHandling.mdwn48
1 files changed, 48 insertions, 0 deletions
diff --git a/Development/Documentation/CursorHandling.mdwn b/Development/Documentation/CursorHandling.mdwn
new file mode 100644
index 00000000..0ee8e688
--- /dev/null
+++ b/Development/Documentation/CursorHandling.mdwn
@@ -0,0 +1,48 @@
+
+This is documentation about the cursor handling, not about the cursor rendering!
+
+Generally, a _[[CursorRec|CursorRec]]_ gets allocated only once and used multiple times to save memory. Two functions are responsible for allocating cursors: _AllocCursorARGB()_ and _[[AllocGlyphCursor|AllocGlyphCursor]]()_. The matching Xlib functions would be _XCreateCursor()_ and _XCreateGlyphCursor()_.
+
+The [[CursorRec|CursorRec]] contains a number of things, we will focus on the _refcnt_ here. The _refcnt_ is used to track how many instances of the cursor are used and to avoid freeing memory too early. The _refcnt_ is increased when
+
+1. a client gets a reference to a cursor
+1. a window uses the cursor
+1. a pointer uses the cursor
+1. a pointer uses the cursor as part of a grab.
+When you create a cursor, it will have a _refcnt_ of 1 (the client has a reference to it after all). Each time you use Xlib's _XDefineCursor()_ or _XChangeWindowAttributes()_, the window obtains a reference to the cursor and increases the _refcnt_. And each time the pointer passes into a window that has a cursor set, _[[ChangeToCursor|ChangeToCursor]]()_ will change the pointer's cursor and increase the _refcnt_. Using the cursor for a sprite does NOT change the _refcnt_!
+
+The _refcnt_ is decreased in _[[FreeCursor|FreeCursor]]()_. When the _refcnt_ hits 0, the memory for the cursor is freed. Make sure that when you call _[[FreeCursor|FreeCursor]]()_, nothing in your codepath references the address anymore. The usual way to do this is something like
+[[!format txt """
+ CursorPtr pOldCursor = device->spriteInfo->sprite->current;
+ device->spriteInfo->sprite->current = NULL;
+ FreeCursor(pOldCursor, 0);
+"""]]
+The value of _pOldCursor_ is undefined after _[[FreeCursor|FreeCursor]]()_.
+
+_[[FreeCursor|FreeCursor]]()_ is called from several points. Each time the cursor leaves a window, _[[CheckMotion|CheckMotion]]()_ call _[[PostNewCursor|PostNewCursor]]()_, which may call _[[ChangeToCursor|ChangeToCursor]]()_. When the client issues a _[[FreeCursor|FreeCursor]]_ request. Each time a window changes the cursor (_[[ChangeWindowAttributes|ChangeWindowAttributes]]()_). When a grab with a cursor is deactivated. And on _[[CloseDownClient|CloseDownClient]]()_, when all the resources are freed for the client. And quite a few more.
+
+
+### Animated cursors
+
+Animated cursors are part of the XRender extension. All they are is a list of standard cursors with a delay between them. The memory is a standard _[[CursorRec|CursorRec]]_, with an _[[AnimCursorRec|AnimCursorRec]]_ and several _[[AnimCursElt|AnimCursElt]]_ attached to the end of the struct. The latter two contain the _[[CursorRec|CursorRec]]_ that make up the animated cursor's frames. Animated cursors are identified with a special pattern in the _[[CursorRec|CursorRec]]_s _bits_ field. See _[[AnimCursorCreate|AnimCursorCreate]]()_.
+
+So for an animated cursor with 3 frames, the memory looks something like this.
+[[!format txt """
+[ CursorRec ][ AnimCursorRec ][AnimCursElt][AnimCursElt][AnimCursElt]
+ | | |
+[ CursorRec ] <------------------- | |
+[ CursorRec ] <--------------------------------- |
+[ CursorRec ] <----------------------------------------------
+"""]]
+Each cursor that is used in an animated cursor has the _refcnt_ increased, and likewise decreased via _[[FreeCursor|FreeCursor]]()_ when the animated cursor is deleted. If a window or pointer uses a animated cursor, they use the animated cursor struct, never directly any of the cursors that make up the frames.
+
+X uses a _[[BlockHandler|BlockHandler]]_ to do stuff when nothing else needs to be done. Such as redrawing mouse cursors. The animated cursor code adds itself to the block handler and _[[AnimCurScreenBlockHandler|AnimCurScreenBlockHandler]]()_ is called regularly.
+
+Display of an animated cursor uses set of static variables in _animcur.c_. The currently displayed animated cursor is saved, and each time the block handler is called, it checks
+
+* whether the current cursor is an animated cursor.
+* if so, if the timeout for the next frame has passed already
+* if so, display the next frame
+* if so, save the timeout for the next frame in the static struct
+* update wakeup handler to wake up for next timeout.
+--- [[CategoryServerInternals|CategoryServerInternals]]