diff options
author | Peter Hutterer <peter.hutterer@redhat.com> | 2008-11-14 15:29:01 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@redhat.com> | 2008-11-25 09:21:46 +1000 |
commit | 724f83b87bb16472d4c328e35d2a477384b29f84 (patch) | |
tree | 3b56d1c624d8dea8d791d601b41baf391133d977 /dix/enterleave.c | |
parent | 7d3e595f93dcd3d334e766a9dea602c05affdbaf (diff) |
dix: add FirstPointerChild, FirstPointerAncestor auxiliary functions.
FirstPointerChild: Return the first child that has a pointer within its
boundaries.
FirstPointerAncestor: return the first ancestor with a child within its
boundaries.
These are required for the updated enter/leave model.
Signed-off-by: Peter Hutterer <peter.hutterer@redhat.com>
Diffstat (limited to 'dix/enterleave.c')
-rw-r--r-- | dix/enterleave.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/dix/enterleave.c b/dix/enterleave.c index 57d1f1e09..0f3b12f6a 100644 --- a/dix/enterleave.c +++ b/dix/enterleave.c @@ -153,6 +153,106 @@ LeaveNotifies(DeviceIntPtr dev, } /** + * Search for the first window below @win that has a pointer directly within + * it's boundaries (excluding boundaries of its own descendants). + * Windows including @exclude and its descendants are ignored. + * + * @return The child window that has the pointer within its boundaries or + * NULL. + */ +static WindowPtr +FirstPointerChild(WindowPtr win, WindowPtr exclude) +{ + static WindowPtr *queue = NULL; + static int queue_size = 256; /* allocated size of queue */ + + WindowPtr child = NULL; + int queue_len = 0; /* no of elements in queue */ + int queue_head = 0; /* pos of current element */ + + if (!win || win == exclude || !win->firstChild) + return NULL; + + if (!queue && !(queue = xcalloc(queue_size, sizeof(WindowPtr)))) + FatalError("[dix] FirstPointerChild: OOM.\n"); + + queue[0] = win; + queue_head = 0; + queue_len = 1; + + while (queue_len--) + { + if (queue[queue_head] == exclude) + { + queue_head = (queue_head + 1) % queue_size; + continue; + } + + if (queue[queue_head] != win && HasPointer(queue[queue_head])) + return queue[queue_head]; + + child = queue[queue_head]->firstChild; + /* pop children onto queue */ + while(child) + { + queue_len++; + if (queue_len >= queue_size) + { + const int inc = 256; + + queue = xrealloc(queue, (queue_size + inc) * sizeof(WindowPtr)); + if (!queue) + FatalError("[dix] FirstPointerChild: OOM.\n"); + + /* Are we wrapped around? */ + if (queue_head + queue_len > queue_size) + { + memmove(&queue[queue_head + inc], &queue[queue_head], + (queue_size - queue_head) * sizeof(WindowPtr)); + queue_head += inc; + } + + queue_size += inc; + } + + queue[(queue_head + queue_len) % queue_size] = child; + child = child->nextSib; + } + + queue_head = (queue_head + 1) % queue_size; + } + + return NULL; +} + +/** + * Find the first parent of @win that has a pointer or has a child window with + * a pointer. Traverses up to (and including) the root window if @stopBefore + * is NULL, otherwise it stops at @stopBefore. + * Neither @win nor @win's descendants nor @stopBefore are tested for having a + * pointer. + * + * @return the window or NULL if @stopBefore was reached. + */ +static WindowPtr +FirstPointerAncestor(WindowPtr win, WindowPtr stopBefore) +{ + WindowPtr parent; + + parent = win->parent; + + while(parent && parent != stopBefore) + { + if (HasPointer(parent) || FirstPointerChild(parent, win)) + return parent; + + parent = parent->parent; + } + + return NULL; +} + +/** * Figure out if enter/leave events are necessary and send them to the * appropriate windows. * |