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;
}

Reply via email to