diff options
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | src/actions.c | 14 | ||||
-rw-r--r-- | src/actions.h | 2 | ||||
-rw-r--r-- | src/data.h | 9 | ||||
-rw-r--r-- | src/events.c | 2 | ||||
-rw-r--r-- | src/globals.c | 4 | ||||
-rw-r--r-- | src/globals.h | 4 | ||||
-rw-r--r-- | src/group.c | 16 | ||||
-rw-r--r-- | src/group.h | 1 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/screen.c | 19 | ||||
-rw-r--r-- | src/screen.h | 1 | ||||
-rw-r--r-- | src/window.c | 121 |
14 files changed, 234 insertions, 14 deletions
@@ -1,3 +1,35 @@ +2005-10-20 Shawn Betts <sabetts@shitbender.gagrod> + + * src/window.c: include unistd.h + (get_child_info): new function + (add_to_window_list): get the window's client's pid if possible + and assign the window the appropriate group and frame. + (add_to_window_list): init intended_frame_number + (save_mouse_position): save the position relative to the window + (give_window_focus): restore the position relative to the window + (set_active_window_body): put the window in the frame contained in + intended_frame_number when appropriate. + + * src/screen.c (screen_find_frame_by_frame): new function + (init_screen): add the net_supported atom to the root window. + + * src/main.c (main): init netwm atoms + + * src/group.c (groups_find_group_by_group): new function + + * src/globals.c (_net_wm_pid, _net_supported): new globals + + * src/data.h (struct rp_window): new field intended_frame_number. + (struct rp_child_info): new fields group, frame, screen. + + * src/actions.c (spawn): call the command directly when new + argument, raw, is non zero. all callers updated. + (spawn): fill in the frame, group and screen for the child. + +2005-10-14 Shawn Betts <sabetts@vcn.bc.ca> + + * src/actions.c (cmd_describekey): print the key name even when it's bound. + 2005-08-23 Shawn Betts <sabetts@vcn.bc.ca> * src/actions.c (cmd_addhook): remove erroneous call to free. @@ -7,6 +7,19 @@ are permitted in any medium without royalty provided the copyright notice and this notice are preserved. * Changes since 1.4.0-beta4 +** _net_wm_pid property supported +ratpoison will put windows that have the _net_wm_pid property into the +frame & group that was current when the windows' client was +launched. for example: + + ratpoison -c split -c gnew -c "exec firefox" -c focus -c gnext + +will Do The Right Thing. + +** set warp change +the mouse position relative to the window is now used, instead of +relative to the root window. + ** new compat command the old def* aliases are depricated and have been moved to this command. Execute it to restore these bindings. diff --git a/src/actions.c b/src/actions.c index 62a5ee9..ff4a5bf 100644 --- a/src/actions.c +++ b/src/actions.c @@ -2452,12 +2452,12 @@ cmd_colon (int interactive, struct cmdarg **args) cmdret * cmd_exec (int interactive, struct cmdarg **args) { - spawn (ARG_STRING(0)); + spawn (ARG_STRING(0), 0); return cmdret_new (RET_SUCCESS, NULL); } int -spawn(char *cmd) +spawn(char *cmd, int raw) { rp_child_info *child; int pid; @@ -2476,6 +2476,9 @@ spawn(char *cmd) #elif defined (HAVE_SETPGRP) setpgrp (0, 0); #endif + /* raw means don't run it through sh. */ + if (raw) + execl (cmd, 0); execl("/bin/sh", "sh", "-c", cmd, 0); _exit(EXIT_FAILURE); } @@ -2488,6 +2491,9 @@ spawn(char *cmd) child->cmd = strdup (cmd); child->pid = pid; child->terminated = 0; + child->frame = current_frame(); + child->group = rp_current_group; + child->screen = current_screen(); list_add (&child->node, &rp_children); @@ -4224,7 +4230,7 @@ cmd_tmpwm (int interactive, struct cmdarg **args) /* Disable our SIGCHLD handler */ set_sig_handler (SIGCHLD, SIG_IGN); /* Launch the new WM and wait for it to terminate. */ - pid = spawn (ARG_STRING(0)); + pid = spawn (ARG_STRING(0), 0); PRINT_DEBUG (("spawn pid: %d\n", pid)); do { @@ -4441,7 +4447,7 @@ cmdret * cmd_verbexec (int interactive, struct cmdarg **args) { marked_message_printf(0, 0, "Running %s", ARG_STRING(0)); - spawn (ARG_STRING(0)); + spawn (ARG_STRING(0), 0); return cmdret_new (RET_SUCCESS, NULL); } diff --git a/src/actions.h b/src/actions.h index 1ced405..da329d2 100644 --- a/src/actions.h +++ b/src/actions.h @@ -96,7 +96,7 @@ user_command struct list_head node; }; -int spawn(char *data); +int spawn(char *data, int raw); cmdret *command (int interactive, char *data); /* command function prototypes. */ @@ -103,6 +103,10 @@ struct rp_window mapped into. */ int frame_number; + /* Sometimes a window is intended for a certain frame. When a window + is mapped and this is >0 then use the frame (if it exists). */ + int intended_frame_number; + struct list_head node; }; @@ -261,6 +265,11 @@ struct rp_child_info /* When this is != 0 then the process finished. */ int terminated; + /* what was current when it was launched? */ + rp_group *group; + rp_frame *frame; + rp_screen *screen; + /* This structure can exist in a list. */ struct list_head node; }; diff --git a/src/events.c b/src/events.c index b190bc6..8115b64 100644 --- a/src/events.c +++ b/src/events.c @@ -618,7 +618,7 @@ property_notify (XEvent *ev) break; default: - PRINT_DEBUG (("Unhandled property notify event\n")); + PRINT_DEBUG (("Unhandled property notify event: %ld\n", ev->xproperty.atom)); break; } } diff --git a/src/globals.c b/src/globals.c index 0358f08..2a954fd 100644 --- a/src/globals.c +++ b/src/globals.c @@ -45,6 +45,10 @@ Atom rp_command_request; Atom rp_command_result; Atom rp_selection; +/* netwm atoms */ +Atom _net_wm_pid; +Atom _net_supported; + int rp_current_screen; rp_screen *screens; int num_screens; diff --git a/src/globals.h b/src/globals.h index bb1ef7e..e8c9c38 100644 --- a/src/globals.h +++ b/src/globals.h @@ -98,6 +98,10 @@ extern Atom wm_delete; extern Atom wm_take_focus; extern Atom wm_colormaps; +/* netwm atoms. */ +Atom _net_wm_pid; +Atom _net_supported; + /* mouse properties */ extern int rat_x; extern int rat_y; diff --git a/src/group.c b/src/group.c index fb5b6db..759f5c9 100644 --- a/src/group.c +++ b/src/group.c @@ -151,6 +151,22 @@ groups_find_group_by_window (rp_window *win) return NULL; } + +/* Return the first group that is g. */ +rp_group * +groups_find_group_by_group (rp_group *g) +{ + rp_group *cur; + + list_for_each_entry (cur, &rp_groups, node) + { + if (cur == g) + return cur; + } + + return NULL; +} + rp_window_elem * group_find_window (struct list_head *list, rp_window *win) { diff --git a/src/group.h b/src/group.h index 32c277c..f315c29 100644 --- a/src/group.h +++ b/src/group.h @@ -44,6 +44,7 @@ rp_window *group_next_window (rp_group *g, rp_window *win); rp_group *groups_find_group_by_name (char *s); rp_group *groups_find_group_by_number (int n); rp_group *groups_find_group_by_window (rp_window *win); +rp_group *groups_find_group_by_group (rp_group *g); rp_window *group_last_window (rp_group *g, rp_screen *screen); @@ -592,9 +592,13 @@ main (int argc, char *argv[]) /* Set ratpoison specific Atoms. */ rp_command = XInternAtom (dpy, "RP_COMMAND", False); + PRINT_DEBUG (("RP_COMMAND = %ld\n", rp_command)); rp_command_request = XInternAtom (dpy, "RP_COMMAND_REQUEST", False); + PRINT_DEBUG (("RP_COMMAND_REQUEST = %ld\n", rp_command_request)); rp_command_result = XInternAtom (dpy, "RP_COMMAND_RESULT", False); + PRINT_DEBUG (("RP_COMMAND_RESULT = %ld\n", rp_command_result)); rp_selection = XInternAtom (dpy, "RP_SELECTION", False); + PRINT_DEBUG (("RP_SELECTION = %ld\n", rp_selection)); if (cmd_count > 0) { @@ -624,6 +628,12 @@ main (int argc, char *argv[]) wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); + /* netwm atoms */ + _net_wm_pid = XInternAtom(dpy, "_NET_WM_PID", False); + PRINT_DEBUG (("_NET_WM_PID = %ld\n", _net_wm_pid)); + _net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False); + PRINT_DEBUG (("_NET_SUPPORTED = %ld\n", _net_supported)); + /* Setup signal handlers. */ XSetErrorHandler(handler); set_sig_handler (SIGALRM, alrm_handler); diff --git a/src/screen.c b/src/screen.c index 0cf47a2..07446d7 100644 --- a/src/screen.c +++ b/src/screen.c @@ -134,6 +134,21 @@ screen_get_frame (rp_screen *s, int frame_num) return NULL; } +rp_frame * +screen_find_frame_by_frame (rp_screen *s, rp_frame *f) +{ + rp_frame *cur; + + list_for_each_entry (cur, &s->frames, node) + { + PRINT_DEBUG (("cur=%p f=%p\n", cur, f)); + if (cur == f) + return cur; + } + + return NULL; +} + /* Given a root window, return the rp_screen struct */ rp_screen * find_screen (Window w) @@ -254,6 +269,10 @@ init_screen (rp_screen *s, int screen_num) | SubstructureRedirectMask | SubstructureNotifyMask ); XSync (dpy, False); + /* Add netwm support. FIXME: I think this is busted. */ + XChangeProperty (dpy, RootWindow (dpy, screen_num), + _net_supported, XA_ATOM, 32, PropModeReplace, &_net_wm_pid, 1); + /* Set the numset for the frames to our global numset. */ s->frames_numset = rp_frame_numset; diff --git a/src/screen.h b/src/screen.h index be319fa..ee5b3eb 100644 --- a/src/screen.h +++ b/src/screen.h @@ -33,6 +33,7 @@ void screen_restore_frameset (rp_screen *s, struct list_head *head); void screen_free_nums (rp_screen *s); void frameset_free (struct list_head *head); rp_frame *screen_get_frame (rp_screen *s, int frame_num); +rp_frame *screen_find_frame_by_frame (rp_screen *s, rp_frame *f); void init_screens (int screen_arg, int screen_num); diff --git a/src/window.c b/src/window.c index cf625ab..04220dc 100644 --- a/src/window.c +++ b/src/window.c @@ -19,6 +19,7 @@ * Boston, MA 02111-1307 USA */ +#include <unistd.h> /* for getsid */ #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -105,11 +106,71 @@ window_name (rp_window *win) return NULL; } +/* FIXME: we need to verify that the window is running on the same + host as something. otherwise there could be overlapping PIDs. */ +static struct rp_child_info * +get_child_info (Window w) +{ + rp_child_info *cur; + int status; + int pid; + Atom type_ret; + int format_ret; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *req; + pid_t sid; + + status = XGetWindowProperty (dpy, w, _net_wm_pid, + 0, 0, False, XA_CARDINAL, + &type_ret, &format_ret, &nitems, &bytes_after, &req); + + if (status != Success || req == NULL) + { + PRINT_DEBUG (("Couldn't get _NET_WM_PID Property\n")); + return NULL; + } + + /* XGetWindowProperty always allocates one extra byte even if + the property is zero length. */ + XFree (req); + + status = XGetWindowProperty (dpy, w, _net_wm_pid, + 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), + False, XA_CARDINAL, &type_ret, &format_ret, &nitems, + &bytes_after, &req); + + if (status != Success || req == NULL) + { + PRINT_DEBUG (("Couldn't get _NET_WM_PID Property\n")); + return NULL; + } + + pid = *((int *)req); + XFree(req); + + PRINT_DEBUG(("pid: %d\n", pid)); + + /* The pids will hopefully be in the same session. */ + sid = getsid (pid); + list_for_each_entry (cur, &rp_children, node) + { + PRINT_DEBUG(("cur->pid=%d sid=%d\n", cur->pid, getsid (cur->pid))); + if (sid == getsid (cur->pid)) + return cur; + } + + return NULL; +} + /* Allocate a new window and add it to the list of managed windows */ rp_window * add_to_window_list (rp_screen *s, Window w) { + struct rp_child_info *child_info; rp_window *new_window; + rp_group *group = NULL; + int frame_num = -1; new_window = xmalloc (sizeof (rp_window)); @@ -119,6 +180,7 @@ add_to_window_list (rp_screen *s, Window w) new_window->state = WithdrawnState; new_window->number = -1; new_window->frame_number = EMPTY; + new_window->intended_frame_number = -1; new_window->named = 0; new_window->hints = XAllocSizeHints (); new_window->colormap = DefaultColormap (dpy, s->screen_num); @@ -140,9 +202,28 @@ add_to_window_list (rp_screen *s, Window w) /* Add the window to the end of the unmapped list. */ list_add_tail (&new_window->node, &rp_unmapped_window); - /* Add the window to the current group. */ - group_add_window (rp_current_group, new_window); + child_info = get_child_info (w); + + if (child_info) { + rp_frame *frame = screen_find_frame_by_frame (child_info->screen, child_info->frame); + PRINT_DEBUG(("frame=%p\n", frame)); + group = groups_find_group_by_group (child_info->group); + if (frame) + frame_num = frame->number; + } + + /* Add the window to the group it's pid was launched in or the + current one. */ + if (group) + group_add_window (group, new_window); + else + group_add_window (rp_current_group, new_window); + + PRINT_DEBUG(("frame_num: %d\n", frame_num)); + if (frame_num >= 0) + new_window->intended_frame_number = frame_num; + return new_window; } @@ -296,7 +377,7 @@ static void save_mouse_position (rp_window *win) { Window root_win, child_win; - int win_x, win_y; + int root_x, root_y; unsigned int mask; /* In the case the XQueryPointer raises a BadWindow error, the @@ -307,7 +388,7 @@ save_mouse_position (rp_window *win) ignore_badwindow++; XQueryPointer (dpy, win->w, &root_win, &child_win, - &win->mouse_x, &win->mouse_y, &win_x, &win_y, &mask); + &root_x, &root_y, &win->mouse_x, &win->mouse_y, &mask); ignore_badwindow--; } @@ -334,7 +415,7 @@ give_window_focus (rp_window *win, rp_window *last_win) if (defaults.warp) { PRINT_DEBUG (("Warp pointer\n")); - XWarpPointer (dpy, None, win->scr->root, + XWarpPointer (dpy, None, win->w, 0, 0, 0, 0, win->mouse_x, win->mouse_y); } @@ -465,24 +546,48 @@ void set_active_window_force (rp_window *win) set_active_window_body(win, 1); } +/* FIXME: This function is probably a mess. I can't remember a time + when I didn't think this. It probably needs to be fixed up. */ void set_active_window_body (rp_window *win, int force) { rp_window *last_win; - rp_frame *frame, *last_frame = NULL; + rp_frame *frame = NULL, *last_frame = NULL; if (win == NULL) return; + PRINT_DEBUG (("intended_frame_number: %d\n", win->intended_frame_number)); + /* With Xinerama, we can move a window over to the current screen; otherwise * we have to switch to the screen that the window belongs to. */ if (rp_have_xinerama) { - frame = screen_get_frame (current_screen(), current_screen()->current_frame); + /* use the intended frame if we can. */ + if (win->intended_frame_number >= 0) + { + frame = screen_get_frame (current_screen(), win->intended_frame_number); + win->intended_frame_number = -1; + if (frame != current_frame()) + last_frame = current_frame(); + } + + if (!frame) + frame = screen_get_frame (current_screen(), current_screen()->current_frame); } else { - frame = screen_get_frame (win->scr, win->scr->current_frame); + /* use the intended frame if we can. */ + if (win->intended_frame_number >= 0) + { + frame = screen_get_frame (win->scr, win->intended_frame_number); + win->intended_frame_number = -1; + if (frame != current_frame()) + last_frame = current_frame(); + } + + if (!frame) + frame = screen_get_frame (win->scr, win->scr->current_frame); } if (frame->dedicated && !force) |