Attached is an implementation of giiSplitInputs; I was just able
to verify it working.

Also a couple minor fixes:

1) compiler warning in libtcp fixed
2) demo now sets any.target correctly when trying to
reflect events with ggiEventSend.

Should I commit this?  T minus 24 and counting...

P.S. speaking of giiEventSend, the code (gii.c) contains the following
comment:

   /* FIXME! We should alow this to be or-ed in */
        event->any.origin = GII_EV_ORIGIN_SENDEVENT;

I would propose an alternative solution: don't do this.  Depricate
the use of any.origin when trying to find out if an event is 
real or counterfeit, instead, change the docs to tell people
to check if any.target == GII_EV_TARGET_QUEUE (or if there is another
legitimate use for this, create a new special value.)  This will allow
the emulation of events from multiple origins, so code that actually
does check any.origin can be tested as well, (which I assume is the
reason for the FIXME comment.)

--
Brian
Index: demos/demo.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/demos/demo.c,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 demo.c
--- demos/demo.c        2001/05/12 22:59:55     1.1.1.1
+++ demos/demo.c        2001/06/12 22:00:35
@@ -106,5 +106,5 @@
         * and helper-variables.
         */
-       int x;
+       int x, res;
        struct timeval tval;
 
@@ -135,4 +135,5 @@
                event.any.type=evKeyPress;
                event.any.size=sizeof(gii_key_event);
+               event.any.target=GII_EV_TARGET_QUEUE;
                event.key.label=x;
                event.key.button=x;
@@ -143,9 +144,8 @@
                test_gii_poll(inp,&tval);
        }
-       giiClose(inp);
 
        /* Open some input.
         */
-       if ((inp=giiOpen("input-stdin",NULL)) == NULL) {
+       if ((inp2=giiOpen("input-stdin",NULL)) == NULL) {
                fprintf(stderr,
                        "%s: unable to open stdin-source, exiting.\n",
@@ -159,14 +159,5 @@
                tval.tv_sec = 0;
                tval.tv_usec = 100000*x;
-               test_gii_poll(inp,&tval);
-       }
-       printf("Doing test of input-pcjoy.\n");
-       if ((inp2=giiOpen("input-pcjoy",NULL)) == NULL) {
-               fprintf(stderr,
-                       "%s: unable to open pcjoy-source, exiting.\n",
-                       argv[0]);
-               giiClose(inp);
-               giiExit();
-               exit(1);
+               test_gii_poll(inp2,&tval);
        }
        for(x=0;x<10;x++)
@@ -184,4 +175,73 @@
                tval.tv_sec = 1*x;
                tval.tv_usec = 0;
+               test_gii_poll(inp,&tval);
+       }
+
+       printf("Splitting inputs.\n");
+       res = giiSplitInputs(inp, &inp2, GII_EV_ORIGIN_NONE, 0);
+       if (res == 1) {
+               gii_input_t tmp;
+               tmp = inp2;
+               inp2 = inp;
+               inp = tmp;
+        } else if (res < 0) {
+               fprintf(stderr, "Failed to split inputs\n");
+               giiClose(inp);
+       }
+
+       printf("Doing test of each input from the split.\n");
+       for(x=0;x<3;x++)
+       {
+               event.any.type=evKeyPress;
+               event.any.size=sizeof(gii_key_event);
+               event.any.target=GII_EV_TARGET_QUEUE;
+               event.key.label=x;
+               event.key.button=x;
+               event.key.sym=x;
+               giiEventSend(inp,&event);
+               printf ("No event should be returned here:\n");
+               tval.tv_sec = 0;
+               tval.tv_usec = 100000*x;
+               test_gii_poll(inp2,&tval);
+               printf ("It should be returned here:\n");
+               tval.tv_sec = 0;
+               tval.tv_usec = 100000*x;
+               test_gii_poll(inp,&tval);
+       }
+
+       for(x=0;x<3;x++)
+       {
+               event.any.type=evKeyPress;
+               event.any.size=sizeof(gii_key_event);
+               event.any.target=GII_EV_TARGET_QUEUE;
+               event.key.label=x;
+               event.key.button=x;
+               event.key.sym=x;
+               giiEventSend(inp2,&event);
+               printf ("No event should be returned here:\n");
+               tval.tv_sec = 0;
+               tval.tv_usec = 100000*x;
+               test_gii_poll(inp,&tval);
+               printf ("It should be returned here:\n");
+               tval.tv_sec = 0;
+               tval.tv_usec = 100000*x;
+               test_gii_poll(inp2,&tval);
+       }
+
+       printf("Joining inputs back together.\n");
+       inp=giiJoinInputs(inp,inp2);
+
+       printf("testing rejoined inputs\n");
+       for(x=0;x<5;x++)
+       {
+               event.any.type=evKeyPress;
+               event.any.size=sizeof(gii_key_event);
+               event.any.target=GII_EV_TARGET_QUEUE;
+               event.key.label=x;
+               event.key.button=x;
+               event.key.sym=x;
+               if ( x & 1 ) giiEventSend(inp2,&event);
+               tval.tv_sec = 0;
+               tval.tv_usec = 100000*x;
                test_gii_poll(inp,&tval);
        }
Index: doc/docbook/libgii-input.sgml
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/doc/docbook/libgii-input.sgml,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 libgii-input.sgml
--- doc/docbook/libgii-input.sgml       2001/05/12 23:00:00     1.1.1.1
+++ doc/docbook/libgii-input.sgml       2001/06/12 22:00:35
@@ -13,6 +13,7 @@
 <refname/giiOpen/
 <refname/giiJoinInputs/
+<refname/giiSplitInputs/
 <refname/giiClose/
-<refpurpose/Open, join and close inputs/
+<refpurpose/Open, join, split and close inputs/
 </refnamediv>
 
@@ -37,4 +38,14 @@
 
 <funcprototype>
+<funcdef>int <function/giiSplitInputs/</funcdef>
+<paramdef>
+gii_input_t <parameter/inp/, 
+gii_input_t *<parameter/newhand/,
+uint32 <parameter/origin/,
+uint32 <parameter/flags/
+</paramdef>
+</funcprototype>
+
+<funcprototype>
 <funcdef>int <function/giiClose/</funcdef>
 <paramdef>gii_input_t <parameter/inp/</paramdef>
@@ -80,5 +91,19 @@
 reopened internally. That is, you will not get any startup-events or
 similar the driver generates, though pending events of both old inputs
-are transferred to the newly created input.
+are transferred to the newly created input.  The parameter <parameter/flags/
+is reserved for future use and should be set to 0.
+</para>
+
+<para>
+<function/giiSplitInputs/ splits one of the inputs from a group of
+joined inputs and returns the handle.  The parameter <parameter/origin/
+can be used to choose which input to detach (use GGI_EV_ORIGIN_NONE
+to match any input.)  The detached handle is returned in newhand.  
+Note, though, that if the detached input is the same one given in 
+<parameter/inp/, then the handle returned in <parameter/newhand/ 
+will be that of the rest of the joined inputs instead.  You can tell 
+whether this happened by checking the return code.  Events queued in 
+the joined input for the newly split input are not transferred 
+automatically.  You must drain them out yourself.
 </para>
 
@@ -107,7 +132,14 @@
 </para>
 <para>
-<function/giiClose/ returns <returnvalue/0/ for OK, otherwise an error
-code.
+<function/giiClose/ returns <returnvalue/GGI_OK/ (== 0) for OK, otherwise 
+an error code.
 </para>
+<para>
+<function/giiSplitInputs/ returns <returnvalue/GGI_OK/ (== 0) for normal 
+success, or <returnvalue/1/ if the input which was split off was the same 
+as the one passed in <parameter/inp/ (in which case, newhand may contain 
+a handle to a joined set of visuals.)  Otherwise, it returns an error code.
+</para>
+
 </refsect1>
 
@@ -117,5 +149,5 @@
 <informalexample>
 <programlisting>
-gii_input_t inp,inp2;
+gii_input_t inp, inp2, inp3;
 
 /* Initialize the GII library. This must be called before any other
@@ -133,4 +165,9 @@
         exit(1);
 }
+/* Open evdev for testing ... */
+if ((inp3=giiOpen("input-linux-evdev",NULL)) == NULL) {
+        giiExit();
+        exit(1);
+}
 /* Now join them. Note the usage of _i_n_p_=_giiJoin(inp,inp2);
  * This is the recommended way to do this. */
@@ -139,5 +176,21 @@
    giiClose(inp2) - this happens together with giiClose(inp) ! */
 
+/* Join another */
+inp=giiJoinInputs(inp,inp3);
+
 <replaceable>... do the real work here ...</replaceable>
+
+/* Split one of them back out of the join. */
+res = ggiSplitInputs(inp, &inp2, GII_EV_ORIGIN_NONE, 0);
+if (res == 1) {
+       gii_input_t tmp;
+       tmp = imp2;
+       imp2 = imp1;
+       imp1 = tmp;
+       } 
+else if (res < 0) fprintf(stderr, "Failed to split inputs\n");
+
+/* Close the single input */
+giiClose(inp2);
 
 /* Close the joined input */
Index: doc/man/Makefile.am
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/doc/man/Makefile.am,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 Makefile.am
--- doc/man/Makefile.am 2001/05/12 23:00:00     1.1.1.1
+++ doc/man/Makefile.am 2001/06/12 22:00:35
@@ -2,5 +2,5 @@
        giiEventRead.3gii giiEventSend.3gii giiExit.3gii giiGetEventMask.3gii \
        giiEventsQueued.3gii giiEventSelect.3gii \
-       giiInit.3gii giiJoinInputs.3gii giiOpen.3gii \
+       giiInit.3gii giiSplitInputs.3gii giiJoinInputs.3gii giiOpen.3gii \
        giiPanic.3gii giiRemoveEventMask.3gii giiSetEventMask.3gii \
        libgii.7gii
Index: filter/tcp/libtcp.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/filter/tcp/libtcp.c,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 libtcp.c
--- filter/tcp/libtcp.c 2001/05/12 23:00:04     1.1.1.1
+++ filter/tcp/libtcp.c 2001/06/12 22:00:36
@@ -1,3 +1,3 @@
-/* $Id: libtcp.c,v 1.1.1.1 2001/05/12 23:00:04 cegger Exp $
+/* $Id: libtcp.c,v 1.1.1.1 2001/05/12 23:00:33 cegger Exp $
 ******************************************************************************
 
@@ -259,7 +259,8 @@
 #endif
        int size = sizeof(addr);
+
        int fd;
 
-       fd = accept(priv->listenfd, &addr, &size);
+       fd = accept(priv->listenfd, (struct sockaddr *)&addr, &size);
        if (fd < 0) {
                perror("giitcp: unable to accept connection");
Index: gii/EXPSYMS
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/gii/EXPSYMS,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 EXPSYMS
--- gii/EXPSYMS 2001/05/12 23:00:10     1.1.1.1
+++ gii/EXPSYMS 2001/06/12 22:00:36
@@ -19,4 +19,5 @@
 giiInit
 giiJoinInputs
+giiSplitInputs
 giiMTInit
 giiOpen
Index: gii/gii.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/gii/gii.c,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 gii.c
--- gii/gii.c   2001/05/12 23:00:09     1.1.1.1
+++ gii/gii.c   2001/06/12 22:00:37
@@ -431,5 +431,6 @@
        ggLock(_gii_safe_lock);
 
-       if (!inp->safequeue && (inp->safequeue = _giiEvQueueSetup()) == NULL) {
+       if (inp->safequeue == NULL && 
+           (inp->safequeue = _giiEvQueueSetup()) == NULL) {
                ret = GGI_ENOMEM;
        } else {
@@ -629,7 +630,8 @@
                               target, args, argptr);
                
-               /* Leave space for up to 256 subsystems ...
-                  I don't think we will wrap around - will we ? */
-               _gii_origin_count += GII_MAXSUBLIBS;    /* Start at next boundary */
+               /* Start at next boundary.  This leaves space for up 
+                * to 256 subsystems ...  I don't think we will 
+                * wrap around - will we ? */
+               _gii_origin_count += GII_MAXSUBLIBS; 
                _gii_origin_count &= GII_MAINMASK;
                _gii_origin_count &= ~GII_EV_ORIGIN_SENDEVENT;
@@ -722,9 +724,9 @@
        GIIDPRINT_EVENTS("giiJoinInputs(%p, %p) called\n", inp, inp2);
 
-       if (!inp) {
+       if (inp == NULL) {
                if (inp2) _giiUpdateCache(inp2);
                return inp2;
        }
-       if (!inp2) {
+       if (inp2 == NULL) {
                if (inp) _giiUpdateCache(inp);
                return inp;
@@ -773,4 +775,106 @@
 }
 
+
+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->mutex);
+               ggLock(inp->queue->mutex);
+       }
+
+       if (inp->next == inp) return GGI_ENOTFOUND;
+
+       idx = inp;
+       do {
+               if ((origin == idx->origin) || 
+                   (origin == GII_EV_ORIGIN_NONE)) {
+                       if (inp == idx) {
+
+                               _giiEvQueueAllocate(inp);
+                               inp->safequeue = NULL;
+                               if (inp->cache != NULL) {
+                                       inp->cache->count--;
+                                       if (inp->cache->count == 0) 
+                                               _giiCacheFree(inp->cache);
+                                       inp->cache = _giiCacheAlloc();
+                                       inp->cache->count++;
+                               }
+
+                               if (_gii_threadsafe) {
+                                       ggUnlock(inp->next->queue->mutex);
+                                       ggLock(inp->next->mutex);
+                                       if (inp->next != inp->prev)
+                                               ggLock(inp->prev->mutex);
+                               }
+                               inp->next->prev = inp->prev;
+                               inp->prev->next = inp->next;
+                               *newhand = inp->next;
+                               if (_gii_threadsafe) {
+                                       if (inp->next != inp->prev)
+                                               ggUnlock(inp->prev->mutex);
+                                       ggUnlock(inp->next->mutex);
+                               }
+                               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);
+                               if (idx->next != inp)
+                                       ggLock(inp->next->mutex);
+                               if (idx->prev != inp &&
+                                   idx->next != idx->prev)
+                                       ggLock(inp->prev->mutex);
+                       }
+                       _giiEvQueueAllocate(idx);
+                       inp->safequeue = NULL;
+                       if (idx->cache != NULL) {
+                               idx->cache->count--;
+                               if (idx->cache->count == 0) 
+                                       _giiCacheFree(idx->cache);
+                               idx->cache = _giiCacheAlloc();
+                               idx->cache->count++;
+                       }
+                       idx->prev->next = idx->next;
+                       idx->next->prev = idx->prev;
+                       if (_gii_threadsafe) {
+                               if (idx->prev != inp &&
+                                   idx->next != idx->prev)
+                                       ggUnlock(inp->prev->mutex);
+                               if (idx->next != inp)
+                                       ggUnlock(inp->next->mutex);
+                       }
+                       *newhand = idx;
+                       idx->next = idx;
+                       idx->prev = idx;
+                       if (_gii_threadsafe) {
+                               ggUnlock(idx->mutex);
+                               ggUnlock(inp->queue->mutex);
+                               ggUnlock(inp->mutex);
+                       }
+                       return GGI_OK;
+               }
+               idx = idx->next;
+       } while (idx != inp);
+
+       if (_gii_threadsafe) {
+               ggUnlock(inp->queue->mutex);
+               ggUnlock(inp->mutex);
+       }
+
+       return GGI_ENOTFOUND;
+}
 
 int giiEventsQueued(struct gii_input *inp, gii_event_mask mask)
Index: include/ggi/gii.h
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/include/ggi/gii.h,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 gii.h
--- include/ggi/gii.h   2001/05/12 23:00:11     1.1.1.1
+++ include/ggi/gii.h   2001/06/12 22:00:37
@@ -69,4 +69,6 @@
  */
 gii_input_t giiJoinInputs(gii_input_t inp, gii_input_t inp2);
+int giiSplitInputs(gii_input_t inp, gii_input_t *newhand,
+                  uint32 origin, uint32 flags);
 
 /* Event Handling
Index: input/linux_evdev/input.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/input/linux_evdev/input.c,v
retrieving revision 1.2
diff -U2 -r1.2 input.c
--- input/linux_evdev/input.c   2001/05/13 01:06:04     1.2
+++ input/linux_evdev/input.c   2001/06/12 22:00:37
@@ -207,5 +207,4 @@
 GIIsendevent(gii_input *inp, gii_event *ev)
 {
-  gii_levdev_priv *priv = inp->priv;
   if (ev->any.target != inp->origin &&
       ev->any.target != GII_EV_TARGET_ALL)
@@ -223,5 +222,4 @@
   if (ev->cmd.code == GII_CMDCODE_GETVALINFO)
     {
-      int i;
       gii_cmddata_getvalinfo *vi = (gii_cmddata_getvalinfo *) ev->cmd.data;
       if (vi->number == GII_VAL_QUERY_ALL)
Index: input/tcp/libtcp.c
===================================================================
RCS file: /cvsroot/ggi/ggi-core/libgii/input/tcp/libtcp.c,v
retrieving revision 1.1.1.1
diff -U2 -r1.1.1.1 libtcp.c
--- input/tcp/libtcp.c  2001/05/12 23:00:33     1.1.1.1
+++ input/tcp/libtcp.c  2001/06/12 22:00:37
@@ -259,7 +259,8 @@
 #endif
        int size = sizeof(addr);
+
        int fd;
 
-       fd = accept(priv->listenfd, &addr, &size);
+       fd = accept(priv->listenfd, (struct sockaddr *)&addr, &size);
        if (fd < 0) {
                perror("giitcp: unable to accept connection");












Reply via email to