diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | src/actions.c | 9 | ||||
-rw-r--r-- | src/actions.h | 1 | ||||
-rw-r--r-- | src/communications.c | 64 | ||||
-rw-r--r-- | src/data.h | 3 | ||||
-rw-r--r-- | src/events.c | 63 | ||||
-rw-r--r-- | src/main.c | 4 |
7 files changed, 156 insertions, 10 deletions
@@ -1,3 +1,25 @@ +2001-03-28 Shawn <sabetts@vcn.bc.ca> + + * src/main.c (main): initialize rp_command_request and + rp_command_result. + + * src/data.h (rp_command_request): new global + (rp_command_result): new global + + * src/events.c (execute_remote_command): new function + (receive_command): loops through the list of command requests + calling execute_remote_command on each one. + (property_notify): better detection of command requests. + + * src/communications.c (recieve_command_result): new function + (send_command): creates a new window to attach the command + to. Waits for confirmation that the command has been executed. + + * src/actions.h (cmd_echo): new prototype + + * src/actions.c (cmd_echo): new function + (user_commands): update "echo" entry + 2001-03-22 Gergely Nagy <8@free.bsd.hu> * debian/control: removed build-dependency on x-terminal-emulator, diff --git a/src/actions.c b/src/actions.c index debc821..44017fd 100644 --- a/src/actions.c +++ b/src/actions.c @@ -147,12 +147,12 @@ user_command user_commands[] = {"bind", cmd_bind, arg_VOID}, {"source", cmd_source, arg_STRING}, {"escape", cmd_escape, arg_STRING}, + {"echo", cmd_echo, arg_STRING}, /* the following screen commands may or may not be able to be implemented. See the screen documentation for what should be emulated with these commands */ - {"echo", cmd_unimplemented, arg_VOID}, {"stuff", cmd_unimplemented, arg_VOID}, {"number", cmd_unimplemented, arg_VOID}, {"hardcopy", cmd_unimplemented, arg_VOID}, @@ -754,3 +754,10 @@ cmd_escape (void *data) message (" escape: could not parse key description "); } } + +/* User accessible call to display the passed in string. */ +void +cmd_echo (void *data) +{ + if (data) message ((char *)data); +} diff --git a/src/actions.h b/src/actions.h index b23fc59..7d0633e 100644 --- a/src/actions.h +++ b/src/actions.h @@ -62,6 +62,7 @@ void cmd_bind (void* data); void cmd_source (void* data); void cmd_maximize (void *data); void cmd_escape (void *data); +void cmd_echo (void *data); /* void cmd_xterm (void *data); */ diff --git a/src/communications.c b/src/communications.c index f87e115..0a0194d 100644 --- a/src/communications.c +++ b/src/communications.c @@ -67,9 +67,69 @@ send_kill () } } +/* Sending commands to ratpoison */ + +static void +recieve_command_result (Window w) +{ + Atom type_ret; + int format_ret; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *result; + + + if (XGetWindowProperty (dpy, w, rp_command_result, + 0, 0, False, XA_STRING, + &type_ret, &format_ret, &nitems, &bytes_after, + &result) == Success + && + XGetWindowProperty (dpy, w, rp_command_result, + 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), + True, XA_STRING, &type_ret, &format_ret, &nitems, + &bytes_after, &result) == Success) + { + if (result) + { + printf ("%s\n", result); + } + XFree (result); + } +} + int send_command (unsigned char *cmd) { - return XChangeProperty (dpy, DefaultRootWindow (dpy), rp_command, XA_STRING, - 8, PropModeAppend, cmd, strlen (cmd) + 1); + Window w; + int done = 0; + + w = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy), + 0, 0, 1, 1, 0, 0, 0); + + // Select first to avoid race condition + XSelectInput (dpy, w, PropertyChangeMask); + + XChangeProperty (dpy, w, rp_command, XA_STRING, + 8, PropModeReplace, cmd, strlen (cmd) + 1); + + XChangeProperty (dpy, DefaultRootWindow (dpy), + rp_command_request, XA_WINDOW, + 8, PropModeAppend, (unsigned char *)&w, sizeof (Window)); + + while (!done) + { + XEvent ev; + + XMaskEvent (dpy, PropertyChangeMask, &ev); + if (ev.xproperty.atom == rp_command_result + && ev.xproperty.state == PropertyNewValue) + { + recieve_command_result(ev.xproperty.window); + done = 1; + } + } + + XDestroyWindow (dpy, w); + + return 1; } @@ -124,6 +124,9 @@ extern Display *dpy; extern Atom rp_restart; extern Atom rp_kill; extern Atom rp_command; +extern Atom rp_command_request; +extern Atom rp_command_result; + extern Atom wm_state; extern Atom wm_change_state; diff --git a/src/events.c b/src/events.c index f32b4fa..9d8f140 100644 --- a/src/events.c +++ b/src/events.c @@ -286,7 +286,7 @@ configure_request (XConfigureRequestEvent *e) static void client_msg (XClientMessageEvent *ev) { - PRINT_DEBUG ("Recieved client message.\n"); + PRINT_DEBUG ("Received client message.\n"); if (ev->message_type == rp_restart) { @@ -382,8 +382,12 @@ key_press (XEvent *ev) } } -void -receive_command() +/* Read a command off the window and execute it. Some commands return + text. This text is passed back using the RP_COMMAND_RESULT + Atom. The client will wait for this property change so something + must be returned. */ +static void +execute_remote_command (Window w) { Atom type_ret; int format_ret; @@ -391,12 +395,12 @@ receive_command() unsigned long bytes_after; unsigned char *req; - if (XGetWindowProperty (dpy, DefaultRootWindow (dpy), rp_command, + if (XGetWindowProperty (dpy, w, rp_command, 0, 0, False, XA_STRING, &type_ret, &format_ret, &nitems, &bytes_after, &req) == Success && - XGetWindowProperty (dpy, DefaultRootWindow (dpy), rp_command, + XGetWindowProperty (dpy, w, rp_command, 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), True, XA_STRING, &type_ret, &format_ret, &nitems, &bytes_after, &req) == Success) @@ -414,6 +418,50 @@ receive_command() } } +/* Command requests are posted as a property change using the + RP_COMMAND_REQUEST Atom on the root window. A Command request is a + Window that holds the actual command as a property using the + RP_COMMAND Atom. receive_command reads the list of Windows and + executes their associated command. */ +static void +receive_command () +{ + Atom type_ret; + int format_ret; + unsigned long nitems; + unsigned long bytes_after; + void *prop_return; + + do + { + if (XGetWindowProperty (dpy, DefaultRootWindow (dpy), + rp_command_request, 0, + sizeof (Window) / 4 + (sizeof (Window) % 4 ?1:0), + True, XA_WINDOW, &type_ret, &format_ret, &nitems, + &bytes_after, (unsigned char **)&prop_return) == Success) + { + if (prop_return) + { + Window w; + + w = *(Window *)prop_return; + XFree (prop_return); + + execute_remote_command (w); + XChangeProperty (dpy, w, rp_command_result, XA_STRING, + 8, PropModeReplace, "Success", 8); + } + else + { + PRINT_DEBUG ("Couldn't get RP_COMMAND_REQUEST Property\n"); + } + + PRINT_DEBUG ("command requests: %ld\n", nitems); + } + } while (nitems > 0); + +} + void property_notify (XEvent *ev) { @@ -421,8 +469,9 @@ property_notify (XEvent *ev) PRINT_DEBUG ("atom: %ld\n", ev->xproperty.atom); - if (ev->xproperty.atom == rp_command - && ev->xproperty.window == DefaultRootWindow (dpy)) + if (ev->xproperty.atom == rp_command_request + && ev->xproperty.window == DefaultRootWindow (dpy) + && ev->xproperty.state == PropertyNewValue) { PRINT_DEBUG ("ratpoison command\n"); receive_command(); @@ -51,6 +51,8 @@ Atom wm_colormaps; Atom rp_restart; Atom rp_kill; Atom rp_command; +Atom rp_command_request; +Atom rp_command_result; screen_info *screens; int num_screens; @@ -365,6 +367,8 @@ main (int argc, char *argv[]) rp_restart = XInternAtom (dpy, "RP_RESTART", False); rp_kill = XInternAtom (dpy, "RP_KILL", False); rp_command = XInternAtom (dpy, "RP_COMMAND", False); + rp_command_request = XInternAtom (dpy, "RP_COMMAND_REQUEST", False); + rp_command_result = XInternAtom (dpy, "RP_COMMAND_RESULT", False); if (do_kill) { |