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");