nanogui: Thread: Newbie question--passing events between programs


[<<] [<] Page 1 of 2 [>] [>>]
Subject: Newbie question--passing events between programs
From: Henry Chea ####@####.####
Date: 28 Jan 2002 09:13:59 -0000
Message-Id: <F53B81109388D044A3CF6E7300FF7F0F1E1FE5@gotz-fs1.semcon.se>

Hi all,

In Nano-X I want to create a "control" program that creates and passes
events to "slave" programs.  That is to say that the slave programs listen
for events created by the control program.

Ideally I would like to make a control program that creates and inserts
events into the Nano-X server event queue.  

Can anyone help show me how to do this?

Thanks for the help,

Henry Chea
Semcon Sweden AB
Subject: RE: Newbie question--passing events between programs
From: Henry Chea ####@####.####
Date: 29 Jan 2002 12:26:44 -0000
Message-Id: <F53B81109388D044A3CF6E7300FF7F0F1E1FE7@gotz-fs1.semcon.se>

Hi again,

Yeah I know I'm replying to my own message, but I'm desperate *desperate*!
=)

I have been searching for countless hours how to solve my problem (making a
control program pass events via the Nano-X server to another program that
listens for the events), and have come across what is perhaps the solution
though I do not know how to use it:

GrRegisterInput(int fd)
GrPrepareSelect (int * maxfd , void * rfdset)
and
GrServiceSelect (void * rfdset , GR_FNCALLBACKEVENT fncb)

Those three functions seem to be what I need, but I can't figure out how to
use them nor can I find any documentation/examples on their use (I tried
decifering the source code too but I'm not that smart).

Can someone please help me?  I would be very greatful!

Maybe point me to examples, docs, or perhaps edit my source code below to
show how to solve the problem?

Thanks again,
Henry Chea
Semcon Sweden AB

****************************
//control.c
#include <stdio.h>
#define MWINCLUDECOLORS
#include "microwin/nano-X.h"

GR_WINDOW_ID control_wid;
GR_GC_ID gc;

int control_fd;

void event_handler (GR_EVENT *event);

int main (void)
{
        if ((control_fd = GrOpen()) < 0)
        {
                fprintf (stderr, "GrOpen failed");
                exit (1);
        }


        gc = GrNewGC();
        GrSetGCUseBackground (gc, GR_FALSE);
        GrSetGCForeground (gc, BLUE);

        control_wid = GrNewWindowEx (GR_WM_PROPS_NOMOVE |
                        GR_WM_PROPS_BORDER |
                        GR_WM_PROPS_NOAUTOMOVE |
                        GR_WM_PROPS_NOAUTORESIZE,
                        "Control Window",
                        GR_ROOT_WINDOW_ID,
                        0, 0, 150, 478, YELLOW);

        GrSelectEvents (control_wid, GR_EVENT_MASK_EXPOSURE |
                        GR_EVENT_MASK_BUTTON_DOWN);

        GrMapWindow (control_wid);
        GrMainLoop (event_handler);
}

void event_handler (GR_EVENT *event)
{
        switch (event->type)
        {
        case GR_EVENT_TYPE_EXPOSURE:
                GrText (control_wid, gc, 20, 20,
                        "Click me", -1, GR_TFASCII);
                break;

        case GR_EVENT_TYPE_BUTTON_DOWN:
                GrClearWindow (control_wid , GR_TRUE);
                ???SOMEHOW_SEND_EVENT_TO_NANO-X_HERE???
                break;
        }
}

******************************
//SLAVE.C
#include <stdio.h>
#define MWINCLUDECOLORS
#include "microwin/nano-X.h"

GR_WINDOW_ID slave_wid;
GR_GC_ID gc;

void event_handler (GR_EVENT *event);

int slave_fd;

int main (void)
{
        if ((slave_fd = GrOpen()) < 0)
        {
                fprintf (stderr, "GrOpen failed");
                exit (1);
        }

        gc = GrNewGC();
        GrSetGCUseBackground (gc, GR_FALSE);
        GrSetGCForeground (gc, RED);

        slave_wid = GrNewWindowEx (GR_WM_PROPS_APPFRAME |
                        GR_WM_PROPS_CAPTION |
                        GR_WM_PROPS_CLOSEBOX,
                        "slave Window",
                        GR_ROOT_WINDOW_ID,
                        150, 150, 200, 100, WHITE);

        GrSelectEvents (slave_wid, GR_EVENT_MASK_CLOSE_REQ|
                        ???EVENT_PASSED_FROM_CONTROL_PROGRAM???);

        GrMapWindow (slave_wid);
        GrMainLoop (event_handler);
}

void event_handler (GR_EVENT *event)
{
        switch (event->type)
        {
        case GR_EVENT_TYPE_CLOSE_REQ:
                GrClose();
                exit (0);

        case ???EVENT_PASSED_FROM_CONTROL_PROGRAM???:
                GrText (slave_wid, gc, 50, 50,
                        "Received a message from control", -1, GR_TFASCII);
                break;
        }
}
******************************

-----Original Message-----
From: Henry Chea
To: ####@####.####
Sent: 1/28/2002 10:10 AM
Subject: Newbie question--passing events between programs

Hi all,

In Nano-X I want to create a "control" program that creates and passes
events to "slave" programs.  That is to say that the slave programs
listen for events created by the control program.

Ideally I would like to make a control program that creates and inserts
events into the Nano-X server event queue.  

Can anyone help show me how to do this?

Thanks for the help,

Henry Chea
Semcon Sweden AB
Subject: RE: [nanogui] RE: Newbie question--passing events between program s
From: Henry Chea ####@####.####
Date: 29 Jan 2002 13:19:43 -0000
Message-Id: <F53B81109388D044A3CF6E7300FF7F0F1E1FE8@gotz-fs1.semcon.se>

Thanks for the tip =)

I thought about that, and looking at the nxkbd source showed that it uses a
function "GrInjectKeyboardEvent()", which emulates a keyboard being pressed.
Unfortunately this is not flexible enough for my needs, as I would like to
be able to send info between programs without getting things mixed up with
real keyboard input.

Anybody have more suggestions?

Thanks again,
Henry Chea
Semcon Sweden AB

-----Original Message-----
From: Simon Wood
To: Henry Chea
Sent: 1/29/2002 1:27 PM
Subject: RE: [nanogui] RE: Newbie question--passing events between program s

Hi,
I don't know this is exactly what you're looking for, but I think the
keyboard app (nxKeyboard) pushes stuff back into the system.

Perhaps this could show what to do, or at least part of it.....

Simon.

PS. I'm just guessing so please don't ask me complicated questions that
will make my brain ache.... ;-)
Subject: Re: [nanogui] RE: Newbie question--passing events between programs
From: Jordan Crouse ####@####.####
Date: 29 Jan 2002 15:45:15 -0000
Message-Id: <E16VaOH-00013U-00@ns.censoft.com>

Its very easy - you have two options.  Either you can use the build in IPC 
(which has the advantage of already existing on your system), or you can grow 
your own IPC with a Unix socket.  It works just like a network socket, and it 
has the advantage of being a file descriptor, so you can register it with 
GrRegisterInput() and have Microwindows poll it for you.

Jordan

On Tuesday 29 January 2002 05:23, Henry Chea mentioned:
> Hi again,
>
> Yeah I know I'm replying to my own message, but I'm desperate *desperate*!
> =)
>
> I have been searching for countless hours how to solve my problem (making a
> control program pass events via the Nano-X server to another program that
> listens for the events), and have come across what is perhaps the solution
> though I do not know how to use it:
>
> GrRegisterInput(int fd)
> GrPrepareSelect (int * maxfd , void * rfdset)
> and
> GrServiceSelect (void * rfdset , GR_FNCALLBACKEVENT fncb)
>
> Those three functions seem to be what I need, but I can't figure out how to
> use them nor can I find any documentation/examples on their use (I tried
> decifering the source code too but I'm not that smart).
>
> Can someone please help me?  I would be very greatful!
>
> Maybe point me to examples, docs, or perhaps edit my source code below to
> show how to solve the problem?
>
> Thanks again,
> Henry Chea
> Semcon Sweden AB
>
> ****************************
> //control.c
> #include <stdio.h>
> #define MWINCLUDECOLORS
> #include "microwin/nano-X.h"
>
> GR_WINDOW_ID control_wid;
> GR_GC_ID gc;
>
> int control_fd;
>
> void event_handler (GR_EVENT *event);
>
> int main (void)
> {
>         if ((control_fd = GrOpen()) < 0)
>         {
>                 fprintf (stderr, "GrOpen failed");
>                 exit (1);
>         }
>
>
>         gc = GrNewGC();
>         GrSetGCUseBackground (gc, GR_FALSE);
>         GrSetGCForeground (gc, BLUE);
>
>         control_wid = GrNewWindowEx (GR_WM_PROPS_NOMOVE |
>                         GR_WM_PROPS_BORDER |
>                         GR_WM_PROPS_NOAUTOMOVE |
>                         GR_WM_PROPS_NOAUTORESIZE,
>                         "Control Window",
>                         GR_ROOT_WINDOW_ID,
>                         0, 0, 150, 478, YELLOW);
>
>         GrSelectEvents (control_wid, GR_EVENT_MASK_EXPOSURE |
>                         GR_EVENT_MASK_BUTTON_DOWN);
>
>         GrMapWindow (control_wid);
>         GrMainLoop (event_handler);
> }
>
> void event_handler (GR_EVENT *event)
> {
>         switch (event->type)
>         {
>         case GR_EVENT_TYPE_EXPOSURE:
>                 GrText (control_wid, gc, 20, 20,
>                         "Click me", -1, GR_TFASCII);
>                 break;
>
>         case GR_EVENT_TYPE_BUTTON_DOWN:
>                 GrClearWindow (control_wid , GR_TRUE);
>                 ???SOMEHOW_SEND_EVENT_TO_NANO-X_HERE???
>                 break;
>         }
> }
>
> ******************************
> //SLAVE.C
> #include <stdio.h>
> #define MWINCLUDECOLORS
> #include "microwin/nano-X.h"
>
> GR_WINDOW_ID slave_wid;
> GR_GC_ID gc;
>
> void event_handler (GR_EVENT *event);
>
> int slave_fd;
>
> int main (void)
> {
>         if ((slave_fd = GrOpen()) < 0)
>         {
>                 fprintf (stderr, "GrOpen failed");
>                 exit (1);
>         }
>
>         gc = GrNewGC();
>         GrSetGCUseBackground (gc, GR_FALSE);
>         GrSetGCForeground (gc, RED);
>
>         slave_wid = GrNewWindowEx (GR_WM_PROPS_APPFRAME |
>                         GR_WM_PROPS_CAPTION |
>                         GR_WM_PROPS_CLOSEBOX,
>                         "slave Window",
>                         GR_ROOT_WINDOW_ID,
>                         150, 150, 200, 100, WHITE);
>
>         GrSelectEvents (slave_wid, GR_EVENT_MASK_CLOSE_REQ|
>                         ???EVENT_PASSED_FROM_CONTROL_PROGRAM???);
>
>         GrMapWindow (slave_wid);
>         GrMainLoop (event_handler);
> }
>
> void event_handler (GR_EVENT *event)
> {
>         switch (event->type)
>         {
>         case GR_EVENT_TYPE_CLOSE_REQ:
>                 GrClose();
>                 exit (0);
>
>         case ???EVENT_PASSED_FROM_CONTROL_PROGRAM???:
>                 GrText (slave_wid, gc, 50, 50,
>                         "Received a message from control", -1, GR_TFASCII);
>                 break;
>         }
> }
> ******************************
>
> -----Original Message-----
> From: Henry Chea
> To: ####@####.####
> Sent: 1/28/2002 10:10 AM
> Subject: Newbie question--passing events between programs
>
> Hi all,
>
> In Nano-X I want to create a "control" program that creates and passes
> events to "slave" programs.  That is to say that the slave programs
> listen for events created by the control program.
>
> Ideally I would like to make a control program that creates and inserts
> events into the Nano-X server event queue.
>
> Can anyone help show me how to do this?
>
> Thanks for the help,
>
> Henry Chea
> Semcon Sweden AB
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ####@####.####
> For additional commands, e-mail: ####@####.####
Subject: Re: [nanogui] RE: Newbie question--passing events between programs
From: Alex Holden ####@####.####
Date: 29 Jan 2002 16:36:05 -0000
Message-Id: <3C56CEA0.6020300@linuxhacker.org>

Henry Chea wrote:

> Maybe point me to examples, docs, or perhaps edit my source code below to
> show how to solve the problem?


One way is to use a pipe to send events to the slave.

Something along these lines (completely untested):

//control.c
#include <unistd.h>
#include <stdio.h>
#define MWINCLUDECOLORS
#include "microwin/nano-X.h"

GR_WINDOW_ID control_wid;
GR_GC_ID gc;

int control_fd;
int pipefds[2];

void event_handler (GR_EVENT *event);

int main (void)
{
         pid_t pid;

         if(pipe(pipefds) < 0) {
           fprintf(stderr, "pipe() failed\n");
           exit(1);
         }

         if((pid = fork()) < 0) {
           fprintf(stderr, "fork() failed\n");
	  exit(1);
         } else if(pid > 0) {
           close(pipefds[0]); /* parent closes the output side */
         } else {
           close(pipefds[1]); /* child closes the input side */
           /* Set stdin to the output of the pipe: */
           if(dup2(pipefds[0], STDIN_FILENO) != STDIN_FILENO) {
	    fprintf(stderr, "dup2() failed\n");
             exit(1);
           }
           close(pipefds[0]);
           if(execl("/usr/local/bin/SLAVE", "SLAVE", NULL) < 0) {
             fprintf(stderr, "execl() failed\n");
             exit(1);
           }
         }

         if ((control_fd = GrOpen()) < 0)
         {
                 fprintf (stderr, "GrOpen failed");
                 exit (1);
         }


         gc = GrNewGC();
         GrSetGCUseBackground (gc, GR_FALSE);
         GrSetGCForeground (gc, BLUE);

         control_wid = GrNewWindowEx (GR_WM_PROPS_NOMOVE |
                         GR_WM_PROPS_BORDER |
                         GR_WM_PROPS_NOAUTOMOVE |
                         GR_WM_PROPS_NOAUTORESIZE,
                         "Control Window",
                         GR_ROOT_WINDOW_ID,
                         0, 0, 150, 478, YELLOW);

         GrSelectEvents (control_wid, GR_EVENT_MASK_EXPOSURE |
                         GR_EVENT_MASK_BUTTON_DOWN);

         GrMapWindow (control_wid);
         GrMainLoop (event_handler);
}

void event_handler (GR_EVENT *event)
{
         switch (event->type)
         {
         case GR_EVENT_TYPE_EXPOSURE:
                 GrText (control_wid, gc, 20, 20,
                         "Click me", -1, GR_TFASCII);
                 break;

         case GR_EVENT_TYPE_BUTTON_DOWN:
                 GrClearWindow (control_wid , GR_TRUE);
                 if(write(pipe_fds[1], "1", 1) != 1) {
                   fprintf(stderr, "Couldn't write message to child\n");
                   exit(1);
                 }
                 break;
         }
}

******************************
//SLAVE.C
#include <stdio.h>
#define MWINCLUDECOLORS
#include "microwin/nano-X.h"

GR_WINDOW_ID slave_wid;
GR_GC_ID gc;

void event_handler (GR_EVENT *event);

int slave_fd;

int main (void)
{
         if ((slave_fd = GrOpen()) < 0)
         {
                 fprintf (stderr, "GrOpen failed");
                 exit (1);
         }

         gc = GrNewGC();
         GrSetGCUseBackground (gc, GR_FALSE);
         GrSetGCForeground (gc, RED);


  slave_wid = GrNewWindowEx (GR_WM_PROPS_APPFRAME |
                         GR_WM_PROPS_CAPTION |
                         GR_WM_PROPS_CLOSEBOX,
                         "slave Window",
                         GR_ROOT_WINDOW_ID,
                         150, 150, 200, 100, WHITE);

         GrRegisterInput(STDIN_FILENO);


         GrSelectEvents (slave_wid, GR_EVENT_MASK_CLOSE_REQ|
                         GR_EVENT_TYPE_FDINPUT);

         GrMapWindow (slave_wid);
         GrMainLoop (event_handler);
}

void event_handler (GR_EVENT *event)
{
         char in;

         switch (event->type)
         {
         case GR_EVENT_TYPE_CLOSE_REQ:
                 GrClose();
                 exit (0);

         case GR_EVENT_TYPE_FDINPUT:
                 if(read(STDIN_FILENO, &in, 1) != 1) {
                   fprintf(stderr, "couldn't read event from parent\n");
                   exit(1);
                 }
                 if(in == '1') {
                   GrText (slave_wid, gc, 50, 50,
                         "Button 1 pressed", -1, GR_TFASCII);
                 } else if(in == '2') {
                   GrText (slave_wid, gc, 50, 50,
                         "Button 2 pressed", -1, GR_TFASCII);
                 } else {
                   GrText (slave_wid, gc, 50, 50,
                         "Unknown button pressed", -1, GR_TFASCII);
                 }
                 break;
         }
}
-- 
------------ Alex Holden - http://www.linuxhacker.org ------------
If it doesn't work, you're not hitting it with a big enough hammer

Subject: Re: [nanogui] RE: Newbie question--passing events between programs
From: Alex Holden ####@####.####
Date: 29 Jan 2002 16:42:49 -0000
Message-Id: <3C56D034.1070200@linuxhacker.org>

Alex Holden wrote:

>         GrSelectEvents (slave_wid, GR_EVENT_MASK_CLOSE_REQ|
>                         GR_EVENT_TYPE_FDINPUT);


That should have been GR_EVENT_MASK_FDINPUT of course.

-- 
------------ Alex Holden - http://www.linuxhacker.org ------------
If it doesn't work, you're not hitting it with a big enough hammer

Subject: Re: [nanogui] RE: Newbie question--passing events between program s
From: "Greg Haerr" ####@####.####
Date: 29 Jan 2002 18:00:34 -0000
Message-Id: <010201c1a8ed$000aae20$3aba46a6@xmission.com>

:  I thought about that, and looking at the nxkbd source showed that it uses a
: function "GrInjectKeyboardEvent()", which emulates a keyboard being pressed.
: Unfortunately this is not flexible enough for my needs, as I would like to
: be able to send info between programs without getting things mixed up with
: real keyboard input.

Take a look at the GrRequestClientData and GrSendClientData
calls in nanox/client.c.

Regards,

Greg



Subject: Re: [nanogui] RE: Newbie question--passing events between program s
From: Alex Holden ####@####.####
Date: 29 Jan 2002 18:52:45 -0000
Message-Id: <3C56EE9F.2030600@linuxhacker.org>

Greg Haerr wrote:

> Take a look at the GrRequestClientData and GrSendClientData
> calls in nanox/client.c.

Actually this brings up a point I've been thinking about recently.

Those calls can indeed be used to send generic blocks of data between 
clients, but at the moment it's only really useful for the clipboard 
(selection), because it's necessary to find out the window ID that you 
want to request data from or send data to before you can do it.

I think we should extend this API by adding three more calls to 
implement a list of tags and associated window IDs. That would allow 
clients to advertise their presence to other clients, enabling arbitrary 
IPC via the Nano-X server. That will have two main advantages over using 
ordinary SysV IPC or named sockets or whatever:

* Automatic portability to every architecture that Nano-X runs on.
* Ability to function even if the clients are on different physical 
machines (once we implement networking support).

The calls would look something like this:

/**
  * GrAddTag:
  * @wid: the ID of the window associated with the tag
  * @tag: the tag string
  *
  * Adds the specified tag with the specified window ID to the server tag
  * list. If the tag already exists, its ID is changed to that specified
  * in this call. tag must be a zero terminated string less than ??
  * characters in length.
  */
void GrAddTag(GR_WINDOW_ID wid, GR_CHAR *tag);

/**
  * GrDeleteTag:
  * @tag: the tag string
  *
  * Deletes the specified tag from the server tag list. If no such tag
  * exists, nothing is changed. tag must be a zero terminated string.
  */
void GrDeleteTag(GR_CHAR *tag);

/**
  * GrFindTag:
  * @tag: the tag string
  *
  * Finds the specified tag in the server tag list and returns the
  * ID of the window associated with it. This is typically used to
  * find the ID of a window with a known tag string which you wish to
  * send data to using GrSendClientData() or request data from
  * using GrRequestClientData(). If the tag is not found, -1 is returned.
  * tag must be a zero terminated string.
  */
GR_WINDOW_ID GrFindTag(GR_CHAR *tag);

So with this API in place, Henry would have been able to decide on a tag 
string for his client window (eg. "henrys_client_1") and call in the client:

GrSelectEvents(client_window_id, GR_EVENT_MASK_CLIENT_DATA);
GrAddTag(client_window_id, "henrys_client_1");

Then in the server do:

client_window_id = GrFindTag("henrys_client_1");
GrSendClientData(server_window_id, client_window_id, 0, 5, 5, "hello");

The client would then receive an event with 
type=GR_EVENT_TYPE_CLIENT_DATA, wid=client_window_id, 
rid=server_window_id, serial=0, len=5, datalen=5, and data="hello".

It might be a good idea to automatically clean the tag list when a 
window is destroyed so we don't get stale tags lying around if a client 
crashes or forgets to delete its tags on exit.

-- 
------------ Alex Holden - http://www.linuxhacker.org ------------
If it doesn't work, you're not hitting it with a big enough hammer

Subject: Re: [nanogui] RE: Newbie question--passing events between program s
From: Alex Holden ####@####.####
Date: 29 Jan 2002 18:59:55 -0000
Message-Id: <3C56F052.2090903@linuxhacker.org>

Alex Holden wrote:

> Then in the server do:

BTW, when I said "server" and "client" here I was talking about Henry's 
master and slave client programs, not the Nano-X server and client (my 
apologies for being confusing).

-- 
------------ Alex Holden - http://www.linuxhacker.org ------------
If it doesn't work, you're not hitting it with a big enough hammer

Subject: Re: [nanogui] RE: Newbie question--passing events between program s
From: "Greg Haerr" ####@####.####
Date: 30 Jan 2002 01:53:10 -0000
Message-Id: <01bd01c1a92f$0599b100$3aba46a6@xmission.com>

: /**
:   * GrAddTag:
:   * @wid: the ID of the window associated with the tag
:   * @tag: the tag string
:   *
:   * Adds the specified tag with the specified window ID to the server tag
:   * list. If the tag already exists, its ID is changed to that specified
:   * in this call. tag must be a zero terminated string less than ??
:   * characters in length.
:   */

How about the idea of just implementing window property strings,
ala X?  We need them for certain programs.  This would work
also for your Tag idea if there were global properties as well.

Regards,

Greg







: void GrAddTag(GR_WINDOW_ID wid, GR_CHAR *tag);
: 
: /**
:   * GrDeleteTag:
:   * @tag: the tag string
:   *
:   * Deletes the specified tag from the server tag list. If no such tag
:   * exists, nothing is changed. tag must be a zero terminated string.
:   */
: void GrDeleteTag(GR_CHAR *tag);
: 
: /**
:   * GrFindTag:
:   * @tag: the tag string
:   *
:   * Finds the specified tag in the server tag list and returns the
:   * ID of the window associated with it. This is typically used to
:   * find the ID of a window with a known tag string which you wish to
:   * send data to using GrSendClientData() or request data from
:   * using GrRequestClientData(). If the tag is not found, -1 is returned.
:   * tag must be a zero terminated string.
:   */
: GR_WINDOW_ID GrFindTag(GR_CHAR *tag);
: 
: So with this API in place, Henry would have been able to decide on a tag 
: string for his client window (eg. "henrys_client_1") and call in the client:
: 
: GrSelectEvents(client_window_id, GR_EVENT_MASK_CLIENT_DATA);
: GrAddTag(client_window_id, "henrys_client_1");
: 
: Then in the server do:
: 
: client_window_id = GrFindTag("henrys_client_1");
: GrSendClientData(server_window_id, client_window_id, 0, 5, 5, "hello");
: 
: The client would then receive an event with 
: type=GR_EVENT_TYPE_CLIENT_DATA, wid=client_window_id, 
: rid=server_window_id, serial=0, len=5, datalen=5, and data="hello".
: 
: It might be a good idea to automatically clean the tag list when a 
: window is destroyed so we don't get stale tags lying around if a client 
: crashes or forgets to delete its tags on exit.
: 
: -- 
: ------------ Alex Holden - http://www.linuxhacker.org ------------
: If it doesn't work, you're not hitting it with a big enough hammer
: 

[<<] [<] Page 1 of 2 [>] [>>]


Powered by ezmlm-browse 0.20.