On Thu, 31 May 2001, Andreas Beck wrote:
> We have a problem with the way inputs are handled, when you ggiJoin multiple
> visuals:
>
> I am using a program that displays computer tomography data in 4 windows
> (the three major planes XY, XZ, YZ and an information window) and I need to
> react to mouse and keyboard events on all windows and of course I don't want
> to poll. For now, I just ggiJoin them, but that leads to the following
> behaviour:
>
> The program will segfault on ggiClose, if you join inputs, because the
> inputs you join to another visual effectively get destroyed when the "main"
> input gets destroyed. This is documented behaviour and reasonable, but we
> have to make a way to let LibGGI know that ggiJoin was used this way.
While we are at it we might as well create giiSplitInputs/ggiSplitInputs
such that a visual can yank its original input back out of a join,
rather than being forced to abandon it entirely.
I just coded this (haven't tested) -- does it look about right?
--
Brian
int giiSplitInputs(struct gii_input *inp, struct gii_input **newhand,
uint32 origin, uint32 flags)
{
struct gii_input *idx;
flags = 0; /* Silence, GCC! Flags is reserved for later use
when asking an input driver-lib to split off an
individual origin. */
if (inp == NULL) return GGI_EARGINVAL;
if (_gii_threadsafe) {
ggLock(inp->queue->mutex);
ggLock(inp->mutex);
}
if (inp->next == inp) return GGI_ENOTFOUND;
idx = inp;
do {
if ((origin == idx->origin) || (origin == 0)) {
_giiEvQueueAllocate(idx);
if (inp == idx) {
if (_gii_threadsafe)
ggUnlock(inp->next->queue->mutex);
inp->next->prev = inp->prev;
inp->prev->next = inp->next;
*newhand = inp->next;
inp->next = inp;
inp->prev = inp;
if (_gii_threadsafe) ggUnlock(inp->mutex);
/* newhand may still be a joined input,
* so we inform the user of that. */
return 1;
}
if (_gii_threadsafe) ggLock(idx->mutex);
idx->prev->next = idx->next;
idx->next->prev = idx->prev;
*newhand = idx;
idx->next = idx;
idx->prev = idx;
if (_gii_threadsafe) {
ggUnlock(inp->queue->mutex);
ggUnlock(inp->mutex);
ggUnlock(idx->mutex);
}
return GGI_OK;
}
idx = idx->next;
} while (idx != inp);
if (_gii_threadsafe) {
ggUnlock(inp->queue->mutex);
ggUnlock(inp->mutex);
}
return GGI_ENOTFOUND;
}