summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog32
-rw-r--r--NEWS13
-rw-r--r--src/actions.c14
-rw-r--r--src/actions.h2
-rw-r--r--src/data.h9
-rw-r--r--src/events.c2
-rw-r--r--src/globals.c4
-rw-r--r--src/globals.h4
-rw-r--r--src/group.c16
-rw-r--r--src/group.h1
-rw-r--r--src/main.c10
-rw-r--r--src/screen.c19
-rw-r--r--src/screen.h1
-rw-r--r--src/window.c121
14 files changed, 234 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index c171068..85c59b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/NEWS b/NEWS
index 46a1e04..2cf77c6 100644
--- a/NEWS
+++ b/NEWS
@@ -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. */
diff --git a/src/data.h b/src/data.h
index acb9cee..638697b 100644
--- a/src/data.h
+++ b/src/data.h
@@ -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);
diff --git a/src/main.c b/src/main.c
index 123445f..7dd1f07 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)