summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsabetts <sabetts>2003-05-16 23:25:06 +0000
committersabetts <sabetts>2003-05-16 23:25:06 +0000
commitcf843449115562fe44be792e37bd78639414da4e (patch)
tree0eba8dbd41b3ad9328b600ca35b4d41e34aaec60
parentbcf85f95069519c29b2263ff5391a4da0442188e (diff)
downloadratpoison-cf843449115562fe44be792e37bd78639414da4e.zip
* src/window.c (add_to_window_list): add the window to the current
group. (find_window_name): search the current group for a matching window. (find_window_other): likewise. (format_window_name): take a rp_window_elem as an argument, not an rp_window. Print the group window's number, not the window's internal number. (get_window_list): loop through the current group. * src/split.c (find_window_for_frame): search the current group for a window to fit in the frame. * src/ratpoison.h: include globals.h and group.h * src/manage.c (unmanage): remove the window from any groups it was in. (map_window): map the window in any groups it is in. (withdraw_window): unmap the window in any groups it is in. * src/main.c: Move all globals to globals.h (main): initialize the group functions. * src/data.h: Move all defines and extern globals to globals.h (struct rp_window_elem): new struct (struct rp_group): likewise * src/actions.h (cmd_gnext): new prototype (cmd_gprev): likewise (cmd_gnew): likewise * src/actions.c (user_commands): new commands gnext, gprev, and gnew (cmd_prev): fix to work with new group code. (cmd_next): likewise (cmd_gnext): new function (cmd_gprev): likewise (cmd_gnew): likewise * src/Makefile.am (ratpoison_SOURCES): add files globals.h, globals.c, group.h and group.c
-rw-r--r--ChangeLog43
-rw-r--r--FAQ20
-rw-r--r--NEWS5
-rw-r--r--src/Makefile.am6
-rw-r--r--src/actions.c191
-rw-r--r--src/actions.h5
-rw-r--r--src/data.h134
-rw-r--r--src/globals.c47
-rw-r--r--src/globals.h103
-rw-r--r--src/group.c272
-rw-r--r--src/group.h31
-rw-r--r--src/main.c45
-rw-r--r--src/manage.c9
-rw-r--r--src/ratpoison.h2
-rw-r--r--src/split.c25
-rw-r--r--src/window.c69
16 files changed, 726 insertions, 281 deletions
diff --git a/ChangeLog b/ChangeLog
index 55d8d97..f51b968 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2003-05-16 Shawn Betts <sabetts@sfu.ca>
+
+ * src/window.c (add_to_window_list): add the window to the current
+ group.
+ (find_window_name): search the current group for a matching
+ window.
+ (find_window_other): likewise.
+ (format_window_name): take a rp_window_elem as an argument, not an
+ rp_window. Print the group window's number, not the window's
+ internal number.
+ (get_window_list): loop through the current group.
+
+ * src/split.c (find_window_for_frame): search the current group
+ for a window to fit in the frame.
+
+ * src/ratpoison.h: include globals.h and group.h
+
+ * src/manage.c (unmanage): remove the window from any groups it
+ was in.
+ (map_window): map the window in any groups it is in.
+ (withdraw_window): unmap the window in any groups it is in.
+
+ * src/main.c: Move all globals to globals.h
+ (main): initialize the group functions.
+
+ * src/data.h: Move all defines and extern globals to globals.h
+ (struct rp_window_elem): new struct
+ (struct rp_group): likewise
+
+ * src/actions.h (cmd_gnext): new prototype
+ (cmd_gprev): likewise
+ (cmd_gnew): likewise
+
+ * src/actions.c (user_commands): new commands gnext, gprev, and gnew
+ (cmd_prev): fix to work with new group code.
+ (cmd_next): likewise
+ (cmd_gnext): new function
+ (cmd_gprev): likewise
+ (cmd_gnew): likewise
+
+ * src/Makefile.am (ratpoison_SOURCES): add files globals.h,
+ globals.c, group.h and group.c
+
2003-05-15 Shawn Betts <sabetts@sfu.ca>
* src/data.h (struct rp_frame): renamed from rp_window_frame. All
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..d7a7d33
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,20 @@
+-*- outline -*-
+Ratpoison Frequently Asked Questions
+
+* Where does the name `ratpoison' come from?
+
+* Where are the window decorations?
+
+* So, what is wrong with the mouse?
+
+* Why can't I move the windows around?
+
+* The Gimp is impossible to use under ratpoison!
+
+* How do I bind something to a single keystroke?
+
+* What about workspaces?
+
+* Can I save and restore frame configurations?
+
+* How do I get rid of that 1 pixel border around some of the windows?
diff --git a/NEWS b/NEWS
index 2a29011..62068ff 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,14 @@
ratpoison NEWS --- history of user-visible changes. -*- outline -*-
* Changes since 1.2.0-beta5
-** command return status
+** shell commands return status
If a command the user executed (with the exec command) returns with a
non-zero exit status, the command and exit status are reported in a
message.
+** new commands gnew, gnext, gprev
+Window are now part of groups. There can be more than one group.
+
* Changes since 1.2.0-beta4
** new commands unmanage and clrunmanaged
Instead of editing conf.h you can use these commands to dynamically
diff --git a/src/Makefile.am b/src/Makefile.am
index 6baf5b0..3e7fd4c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,7 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
-## $Id: Makefile.am,v 1.15 2003/04/08 00:00:49 sabetts Exp $
+## $Id: Makefile.am,v 1.16 2003/05/16 23:25:07 sabetts Exp $
bin_PROGRAMS = ratpoison
@@ -36,6 +36,10 @@ ratpoison_SOURCES = actions.c \
getopt.c \
getopt.h \
getopt1.c \
+ globals.h \
+ globals.c \
+ group.h \
+ group.c \
input.c \
input.h \
linkedlist.h \
diff --git a/src/actions.c b/src/actions.c
index e293aa1..e866953 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -35,69 +35,72 @@ static int key_actions_table_size;
static user_command user_commands[] =
{ /*@begin (tag required for genrpbindings) */
- {"abort", cmd_abort, arg_VOID},
- {"banish", cmd_banish, arg_VOID},
- {"bind", cmd_bind, arg_VOID},
- {"time", cmd_time, arg_VOID},
- {"colon", cmd_colon, arg_STRING},
- {"curframe", cmd_curframe, arg_VOID},
- {"delete", cmd_delete, arg_VOID},
- {"echo", cmd_echo, arg_STRING},
- {"escape", cmd_escape, arg_STRING},
- {"exec", cmd_exec, arg_STRING},
- {"focus", cmd_next_frame, arg_VOID},
- {"focusup", cmd_focusup, arg_VOID},
- {"focusdown", cmd_focusdown, arg_VOID},
- {"focusleft", cmd_focusleft, arg_VOID},
- {"focusright", cmd_focusright, arg_VOID},
- {"focuslast", cmd_focuslast, arg_VOID},
- {"meta", cmd_meta, arg_STRING},
- {"license", cmd_license, arg_VOID},
- {"help", cmd_help, arg_VOID},
- {"hsplit", cmd_h_split, arg_STRING},
- {"kill", cmd_kill, arg_VOID},
- {"redisplay", cmd_redisplay, arg_VOID},
- {"newwm", cmd_newwm, arg_STRING},
- {"next", cmd_next, arg_VOID},
- {"number", cmd_number, arg_STRING},
- {"only", cmd_only, arg_VOID},
- {"other", cmd_other, arg_VOID},
- {"gravity", cmd_gravity, arg_STRING},
- {"prev", cmd_prev, arg_VOID},
- {"quit", cmd_quit, arg_VOID},
- {"remove", cmd_remove, arg_VOID},
- {"rudeness", cmd_rudeness, arg_STRING},
- {"select", cmd_select, arg_STRING},
- {"source", cmd_source, arg_STRING},
- {"split", cmd_h_split, arg_STRING},
- {"title", cmd_rename, arg_STRING},
- {"unbind", cmd_unbind, arg_STRING},
- {"version", cmd_version, arg_VOID},
- {"vsplit", cmd_v_split, arg_STRING},
- {"windows", cmd_windows, arg_VOID},
- {"setenv", cmd_setenv, arg_STRING},
- {"getenv", cmd_getenv, arg_STRING},
- {"chdir", cmd_chdir, arg_STRING},
- {"unsetenv", cmd_unsetenv, arg_STRING},
- {"info", cmd_info, arg_VOID},
- {"lastmsg", cmd_lastmsg, arg_VOID},
- {"restart", cmd_restart, arg_VOID},
- {"startup_message", cmd_startup_message, arg_STRING},
- {"link", cmd_link, arg_STRING},
- {"alias", cmd_alias, arg_STRING},
- {"unalias", cmd_unalias, arg_STRING},
- {"prevscreen", cmd_prevscreen, arg_VOID},
- {"nextscreen", cmd_nextscreen, arg_VOID},
- {"warp", cmd_warp, arg_STRING},
- {"resize", cmd_resize, arg_STRING},
- {"shrink", cmd_shrink, arg_VOID},
- {"tmpwm", cmd_tmpwm, arg_STRING},
- {"fselect", cmd_fselect, arg_VOID},
- {"fdump", cmd_fdump, arg_STRING},
- {"frestore", cmd_frestore, arg_STRING},
- {"verbexec", cmd_verbexec, arg_STRING},
- {"unmanage", cmd_unmanage, arg_STRING},
- {"clrunmanaged", cmd_clrunmanaged, arg_VOID},
+ {"abort", cmd_abort, arg_VOID},
+ {"banish", cmd_banish, arg_VOID},
+ {"bind", cmd_bind, arg_VOID},
+ {"time", cmd_time, arg_VOID},
+ {"colon", cmd_colon, arg_STRING},
+ {"curframe", cmd_curframe, arg_VOID},
+ {"delete", cmd_delete, arg_VOID},
+ {"echo", cmd_echo, arg_STRING},
+ {"escape", cmd_escape, arg_STRING},
+ {"exec", cmd_exec, arg_STRING},
+ {"focus", cmd_next_frame, arg_VOID},
+ {"focusup", cmd_focusup, arg_VOID},
+ {"focusdown", cmd_focusdown, arg_VOID},
+ {"focusleft", cmd_focusleft, arg_VOID},
+ {"focusright", cmd_focusright, arg_VOID},
+ {"focuslast", cmd_focuslast, arg_VOID},
+ {"meta", cmd_meta, arg_STRING},
+ {"license", cmd_license, arg_VOID},
+ {"help", cmd_help, arg_VOID},
+ {"hsplit", cmd_h_split, arg_STRING},
+ {"kill", cmd_kill, arg_VOID},
+ {"redisplay", cmd_redisplay, arg_VOID},
+ {"newwm", cmd_newwm, arg_STRING},
+ {"next", cmd_next, arg_VOID},
+ {"number", cmd_number, arg_STRING},
+ {"only", cmd_only, arg_VOID},
+ {"other", cmd_other, arg_VOID},
+ {"gravity", cmd_gravity, arg_STRING},
+ {"prev", cmd_prev, arg_VOID},
+ {"quit", cmd_quit, arg_VOID},
+ {"remove", cmd_remove, arg_VOID},
+ {"rudeness", cmd_rudeness, arg_STRING},
+ {"select", cmd_select, arg_STRING},
+ {"source", cmd_source, arg_STRING},
+ {"split", cmd_h_split, arg_STRING},
+ {"title", cmd_rename, arg_STRING},
+ {"unbind", cmd_unbind, arg_STRING},
+ {"version", cmd_version, arg_VOID},
+ {"vsplit", cmd_v_split, arg_STRING},
+ {"windows", cmd_windows, arg_VOID},
+ {"setenv", cmd_setenv, arg_STRING},
+ {"getenv", cmd_getenv, arg_STRING},
+ {"chdir", cmd_chdir, arg_STRING},
+ {"unsetenv", cmd_unsetenv, arg_STRING},
+ {"info", cmd_info, arg_VOID},
+ {"lastmsg", cmd_lastmsg, arg_VOID},
+ {"restart", cmd_restart, arg_VOID},
+ {"startup_message", cmd_startup_message, arg_STRING},
+ {"link", cmd_link, arg_STRING},
+ {"alias", cmd_alias, arg_STRING},
+ {"unalias", cmd_unalias, arg_STRING},
+ {"prevscreen", cmd_prevscreen, arg_VOID},
+ {"nextscreen", cmd_nextscreen, arg_VOID},
+ {"warp", cmd_warp, arg_STRING},
+ {"resize", cmd_resize, arg_STRING},
+ {"shrink", cmd_shrink, arg_VOID},
+ {"tmpwm", cmd_tmpwm, arg_STRING},
+ {"fselect", cmd_fselect, arg_VOID},
+ {"fdump", cmd_fdump, arg_STRING},
+ {"frestore", cmd_frestore, arg_STRING},
+ {"verbexec", cmd_verbexec, arg_STRING},
+ {"unmanage", cmd_unmanage, arg_STRING},
+ {"clrunmanaged", cmd_clrunmanaged, arg_VOID},
+ {"gnext", cmd_gnext, arg_VOID},
+ {"gprev", cmd_gprev, arg_VOID},
+ {"gnew", cmd_gnew, arg_VOID},
/* Commands to set default behavior. */
{"defbargravity", cmd_defbargravity, arg_STRING},
@@ -644,26 +647,21 @@ cmd_meta (int interactive, char *data)
char *
cmd_prev (int interactive, char *data)
{
- rp_window *w;
-
- /* If the current frame is empty find the last accessed window and
- put it in the frame */
if (!current_window())
{
- set_active_window (find_window_other());
+ set_active_window (group_prev_window (rp_current_group, NULL));
if (!current_window())
message (MESSAGE_NO_MANAGED_WINDOWS);
-
- return NULL;
}
else
{
- w = find_window_prev (current_window());
+ rp_window *win;
- if (!w)
+ win = group_prev_window (rp_current_group, current_window());
+ if (win == NULL)
message (MESSAGE_NO_OTHER_WINDOW);
else
- set_active_window (w);
+ set_active_window (win);
}
return NULL;
@@ -686,26 +684,21 @@ cmd_prev_frame (int interactive, char *data)
char *
cmd_next (int interactive, char *data)
{
- rp_window *w;
-
- /* If the current frame is empty find the last accessed window and
- put it in the frame */
if (!current_window())
{
- set_active_window (find_window_other());
+ set_active_window (group_next_window (rp_current_group, NULL));
if (!current_window())
message (MESSAGE_NO_MANAGED_WINDOWS);
-
- return NULL;
}
- else
+ else
{
- w = find_window_next (current_window());
+ rp_window *win;
- if (!w)
+ win = group_next_window (rp_current_group, current_window());
+ if (win == NULL)
message (MESSAGE_NO_OTHER_WINDOW);
else
- set_active_window (w);
+ set_active_window (win);
}
return NULL;
@@ -730,7 +723,8 @@ cmd_other (int interactive, char *data)
{
rp_window *w;
- w = find_window_other ();
+/* w = find_window_other (); */
+ w = group_last_window (rp_current_group);
if (!w)
message (MESSAGE_NO_OTHER_WINDOW);
@@ -787,7 +781,7 @@ cmd_select (int interactive, char *data)
/* try by number */
else if ((n = string_to_window_number (str)) >= 0)
{
- if ((w = find_window_number (n)))
+ if ((w = group_find_window_by_number (rp_current_group, n)))
goto_window (w);
else
/* show the window list as feedback */
@@ -1110,9 +1104,7 @@ cmd_time (int interactive, char *data)
/* Assign a new number to a window ala screen's number command. Thanks
to Martin Samuelsson <cosis@lysator.liu.se> for the original
patch. */
-/* FIXME: this function breaks ratpoison because now all frame and
- window references are based on numbers, and this code doesn't
- update the number references after changing the number. */
+/* FIXME: With the new group code, this doesn't work as expected. */
char *
cmd_number (int interactive, char *data)
{
@@ -3165,3 +3157,24 @@ cmd_defwinliststyle (int interactive, char *data)
return NULL;
}
+
+char *
+cmd_gnext (int interactive, char *data)
+{
+ rp_current_group = group_next_group ();
+ return NULL;
+}
+
+char *
+cmd_gprev (int interactive, char *data)
+{
+ rp_current_group = group_prev_group ();
+ return NULL;
+}
+
+char *
+cmd_gnew (int interactive, char *data)
+{
+ rp_current_group = group_add_new_group ();
+ return NULL;
+}
diff --git a/src/actions.h b/src/actions.h
index 168d56a..617f087 100644
--- a/src/actions.h
+++ b/src/actions.h
@@ -45,6 +45,7 @@ char *cmd_alias (int interactive, char *data);
char *cmd_banish (int interactive, char *data);
char *cmd_bind (int interactive, char *data);
char *cmd_chdir (int interactive, char *data);
+char *cmd_clrunmanaged (int interactive, char *data);
char *cmd_colon (int interactive, char *data);
char *cmd_curframe (int interactive, char *data);
char *cmd_defbarborder (int interactive, char *data);
@@ -77,6 +78,9 @@ char *cmd_focusup (int interactive, char *data);
char *cmd_frestore (int interactively, char *data);
char *cmd_fselect (int interactive, char *data);
char *cmd_getenv (int interactive, char *data);
+char *cmd_gnew (int interactive, char *data);
+char *cmd_gnext (int interactive, char *data);
+char *cmd_gprev (int interactive, char *data);
char *cmd_gravity (int interactive, char *data);
char *cmd_h_split (int interactive, char *data);
char *cmd_help (int interactive, char *data);
@@ -117,7 +121,6 @@ char *cmd_unalias (int interactive, char *data);
char *cmd_unbind (int interactive, char *data);
char *cmd_unimplemented (int interactive, char *data);
char *cmd_unmanage (int interactive, char *data);
-char *cmd_clrunmanaged (int interactive, char *data);
char *cmd_unsetenv (int interactive, char *data);
char *cmd_v_split (int interactive, char *data);
char *cmd_verbexec (int interactive, char *data);
diff --git a/src/data.h b/src/data.h
index c14040b..60f7bb9 100644
--- a/src/data.h
+++ b/src/data.h
@@ -29,28 +29,13 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#define FONT_HEIGHT(f) ((f)->max_bounds.ascent + (f)->max_bounds.descent)
-
-#define WIN_EVENTS (StructureNotifyMask | PropertyChangeMask | ColormapChangeMask | FocusChangeMask)
-/* EMPTY is used when a frame doesn't contain a window, or a window
- doesn't have a frame. Any time a field refers to the number of a
- window/frame/screen/etc, Use EMPTY to denote a lack there of. */
-#define EMPTY -1
-
-/* Possible values for defaults.window_list_style */
-#define STYLE_ROW 0
-#define STYLE_COLUMN 1
-
-/* Possible values for defaults.win_name */
-#define WIN_NAME_TITLE 0
-#define WIN_NAME_RES_CLASS 1
-#define WIN_NAME_RES_NAME 2
-
typedef struct rp_window rp_window;
typedef struct rp_screen rp_screen;
typedef struct rp_action rp_action;
typedef struct rp_frame rp_frame;
typedef struct rp_child_info rp_child_info;
+typedef struct rp_group rp_group;
+typedef struct rp_window_elem rp_window_elem;
struct rp_frame
{
@@ -70,11 +55,16 @@ struct rp_window
{
rp_screen *scr;
Window w;
- int number;
int state;
int last_access;
int named;
-
+
+ /* A number uniquely identifying this window. This is a different
+ number than the one given to it by the group it is in. This
+ number is used for internal purposes, whereas the group number is
+ what the user sees. */
+ int number;
+
/* Window name hints. */
char *user_name;
char *wm_name;
@@ -109,6 +99,38 @@ struct rp_window
struct list_head node;
};
+struct rp_window_elem
+{
+ rp_window *win;
+ int number;
+ struct list_head node;
+};
+
+/* An rp_group is a group of windows. By default all windows are added
+ to the same group. But a new group can be created. All new windows
+ will be part of this new current group. The windows of any other
+ group may be visible in another frame, but will not show up in the
+ window list and will not be accessible with select, next, or
+ prev. These window navigation commands only navigate the current
+ group. */
+struct rp_group
+{
+ /* The name and number of this group. This is to allow the user to
+ quickly jump to the desired group. */
+ char *name;
+ int number;
+
+ /* The list of windows participating in this group. */
+ struct list_head mapped_windows, unmapped_windows;
+
+ /* This numset is responsible for giving out numbers for each window
+ in the group. */
+ struct numset *numset;
+
+ /* This structure can exist in a list. */
+ struct list_head node;
+};
+
struct rp_screen
{
GC normal_gc;
@@ -211,58 +233,6 @@ struct rp_child_info
struct list_head node;
};
-/* Each child process is stored in this list. spawn, creates a new
- entry in this list, the SIGCHLD handler sets child.terminated to be
- true and handle_signals in events.c processes each terminated
- process by printing a message saying the process ended and
- displaying it's exit code. */
-extern struct list_head rp_children;
-
-extern struct rp_defaults defaults;
-
-/* The prefix key also known as the command character under screen. */
-extern struct rp_key prefix_key;
-
-/* A list of mapped windows. These windows show up in the window
- list and have a number assigned to them. */
-extern struct list_head rp_mapped_window;
-
-/* A list of unmapped windows. These windows do not have a number
- assigned to them and are not visible/active. */
-extern struct list_head rp_unmapped_window;
-
-extern int rp_current_screen;
-extern rp_screen *screens;
-extern int num_screens;
-
-extern XEvent rp_current_event;
-
-extern Display *dpy;
-extern Atom rp_command;
-extern Atom rp_command_request;
-extern Atom rp_command_result;
-
-extern Atom wm_name;
-extern Atom wm_state;
-extern Atom wm_change_state;
-extern Atom wm_protocols;
-extern Atom wm_delete;
-extern Atom wm_take_focus;
-extern Atom wm_colormaps;
-
-/* mouse properties */
-extern int rat_x;
-extern int rat_y;
-extern int rat_visible;
-
-/* When unmapping or deleting windows, it is sometimes helpful to
- ignore a bad window when attempting to clean the window up. This
- does just that when set to 1 */
-extern int ignore_badwindow;
-
-/* Arguments passed to ratpoison. */
-extern char **myargv;
-
/* These defines should be used to specify the modifier mask for keys
and they are translated into the X11 modifier mask when the time
comes to compare modifier masks. */
@@ -286,26 +256,4 @@ struct modifier_info
unsigned int scroll_lock_mask;
};
-/* Keeps track of which mod mask each modifier is under. */
-extern struct modifier_info rp_modifier_info;
-
-/* nonzero if an alarm signal was raised. This means ratpoison should
- hide its popup windows. */
-extern int alarm_signalled;
-extern int kill_signalled;
-extern int hup_signalled;
-extern int chld_signalled;
-
-/* rudeness levels */
-extern int rp_honour_transient_raise;
-extern int rp_honour_normal_raise;
-extern int rp_honour_transient_map;
-extern int rp_honour_normal_map;
-
-/* Keep track of X11 error messages. */
-extern char *rp_error_msg;
-
-/* Number sets for windows. */
-extern struct numset *rp_window_numset;
-
#endif /* _RATPOISON_DATA_H */
diff --git a/src/globals.c b/src/globals.c
new file mode 100644
index 0000000..d9478bd
--- /dev/null
+++ b/src/globals.c
@@ -0,0 +1,47 @@
+#include "ratpoison.h"
+
+int alarm_signalled = 0;
+int kill_signalled = 0;
+int hup_signalled = 0;
+int chld_signalled = 0;
+int rat_x;
+int rat_y;
+int rat_visible = 1; /* rat is visible by default */
+
+Atom wm_name;
+Atom wm_state;
+Atom wm_change_state;
+Atom wm_protocols;
+Atom wm_delete;
+Atom wm_take_focus;
+Atom wm_colormaps;
+
+Atom rp_command;
+Atom rp_command_request;
+Atom rp_command_result;
+
+int rp_current_screen;
+rp_screen *screens;
+int num_screens;
+Display *dpy;
+
+rp_group *rp_current_group;
+LIST_HEAD (rp_groups);
+LIST_HEAD (rp_children);
+struct rp_defaults defaults;
+
+int ignore_badwindow = 0;
+
+char **myargv;
+
+struct rp_key prefix_key;
+
+struct modifier_info rp_modifier_info;
+
+/* rudeness levels */
+int rp_honour_transient_raise = 1;
+int rp_honour_normal_raise = 1;
+int rp_honour_transient_map = 1;
+int rp_honour_normal_map = 1;
+
+char *rp_error_msg = NULL;
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 0000000..011570e
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,103 @@
+#ifndef GLOBALS_H
+#define GLOBALS_H
+
+#include "data.h"
+
+#define FONT_HEIGHT(f) ((f)->max_bounds.ascent + (f)->max_bounds.descent)
+
+#define WIN_EVENTS (StructureNotifyMask | PropertyChangeMask | ColormapChangeMask | FocusChangeMask)
+/* EMPTY is used when a frame doesn't contain a window, or a window
+ doesn't have a frame. Any time a field refers to the number of a
+ window/frame/screen/etc, Use EMPTY to denote a lack there of. */
+#define EMPTY -1
+
+/* Possible values for defaults.window_list_style */
+#define STYLE_ROW 0
+#define STYLE_COLUMN 1
+
+/* Possible values for defaults.win_name */
+#define WIN_NAME_TITLE 0
+#define WIN_NAME_RES_CLASS 1
+#define WIN_NAME_RES_NAME 2
+
+/* The list of groups. */
+extern struct list_head rp_groups;
+
+extern rp_group *rp_current_group;
+
+/* Each child process is stored in this list. spawn, creates a new
+ entry in this list, the SIGCHLD handler sets child.terminated to be
+ true and handle_signals in events.c processes each terminated
+ process by printing a message saying the process ended and
+ displaying it's exit code. */
+extern struct list_head rp_children;
+
+extern struct rp_defaults defaults;
+
+/* The prefix key also known as the command character under screen. */
+extern struct rp_key prefix_key;
+
+/* A list of mapped windows. These windows show up in the window
+ list and have a number assigned to them. */
+extern struct list_head rp_mapped_window;
+
+/* A list of unmapped windows. These windows do not have a number
+ assigned to them and are not visible/active. */
+extern struct list_head rp_unmapped_window;
+
+extern int rp_current_screen;
+extern rp_screen *screens;
+extern int num_screens;
+
+extern XEvent rp_current_event;
+
+extern Display *dpy;
+extern Atom rp_command;
+extern Atom rp_command_request;
+extern Atom rp_command_result;
+
+extern Atom wm_name;
+extern Atom wm_state;
+extern Atom wm_change_state;
+extern Atom wm_protocols;
+extern Atom wm_delete;
+extern Atom wm_take_focus;
+extern Atom wm_colormaps;
+
+/* mouse properties */
+extern int rat_x;
+extern int rat_y;
+extern int rat_visible;
+
+/* When unmapping or deleting windows, it is sometimes helpful to
+ ignore a bad window when attempting to clean the window up. This
+ does just that when set to 1 */
+extern int ignore_badwindow;
+
+/* Arguments passed to ratpoison. */
+extern char **myargv;
+
+/* Keeps track of which mod mask each modifier is under. */
+extern struct modifier_info rp_modifier_info;
+
+/* nonzero if an alarm signal was raised. This means ratpoison should
+ hide its popup windows. */
+extern int alarm_signalled;
+extern int kill_signalled;
+extern int hup_signalled;
+extern int chld_signalled;
+
+/* rudeness levels */
+extern int rp_honour_transient_raise;
+extern int rp_honour_normal_raise;
+extern int rp_honour_transient_map;
+extern int rp_honour_normal_map;
+
+/* Keep track of X11 error messages. */
+extern char *rp_error_msg;
+
+/* Number sets for windows. */
+extern struct numset *rp_window_numset;
+
+
+#endif
diff --git a/src/group.c b/src/group.c
new file mode 100644
index 0000000..6b268f0
--- /dev/null
+++ b/src/group.c
@@ -0,0 +1,272 @@
+#include "ratpoison.h"
+
+static struct numset *group_numset;
+
+void init_groups()
+{
+ rp_group *g;
+
+ group_numset = numset_new();
+ INIT_LIST_HEAD (&rp_groups);
+
+ /* Create the first group in the list (We always need at least
+ one). */
+ g = group_new (numset_request (group_numset));
+ rp_current_group = g;
+ list_add_tail (&g->node, &rp_groups);
+}
+
+rp_group *
+group_new (int number)
+{
+ rp_group *g;
+
+ g = xmalloc (sizeof (rp_group));
+
+ g->number = numset_request (group_numset);
+ g->numset = numset_new();
+ INIT_LIST_HEAD (&g->unmapped_windows);
+ INIT_LIST_HEAD (&g->mapped_windows);
+
+ return g;
+}
+
+void
+group_free (rp_group *g)
+{
+ /* free (g->name); */
+ numset_free (g->numset);
+ numset_release (group_numset, g->number);
+ free (g);
+}
+
+rp_group *
+group_add_new_group ()
+{
+ rp_group *g;
+
+ g = group_new (numset_request (group_numset));
+ list_add_tail (&g->node, &rp_groups);
+
+ return g;
+}
+
+rp_group *
+group_next_group ()
+{
+ return list_next_entry (rp_current_group, &rp_groups, node);
+}
+
+rp_group *
+group_prev_group ()
+{
+ return list_prev_entry (rp_current_group, &rp_groups, node);
+}
+
+rp_window_elem *
+group_find_window (struct list_head *list, rp_window *win)
+{
+ rp_window_elem *cur;
+
+ list_for_each_entry (cur, list, node)
+ {
+ if (cur->win == win)
+ return cur;
+ }
+
+ return NULL;
+}
+
+rp_window *
+group_find_window_by_number (rp_group *g, int num)
+{
+ rp_window_elem *cur;
+
+ list_for_each_entry (cur, &g->mapped_windows, node)
+ {
+ if (cur->number == num)
+ return cur->win;
+ }
+
+ return NULL;
+
+}
+
+void
+group_add_window (rp_group *g, rp_window *w)
+{
+ rp_window_elem *we;
+
+ /* Create our container structure for the window. */
+ we = malloc (sizeof (rp_window_elem));
+ we->win = w;
+ we->number = -1;
+
+ /* Finally, add it to our list. */
+ list_add_tail (&we->node, &g->unmapped_windows);
+}
+
+void
+group_map_window (rp_group *g, rp_window *win)
+{
+ rp_window_elem *we;
+
+ we = group_find_window (&g->unmapped_windows, win);
+
+ if (we)
+ {
+ we->number = numset_request (g->numset);
+ list_move_tail (&we->node, &g->mapped_windows);
+ }
+}
+
+void
+groups_map_window (rp_window *win)
+{
+ rp_group *cur;
+
+ list_for_each_entry (cur, &rp_groups, node)
+ {
+ group_map_window (cur, win);
+ }
+}
+
+void
+group_unmap_window (rp_group *g, rp_window *win)
+{
+ rp_window_elem *we;
+
+ we = group_find_window (&g->mapped_windows, win);
+
+ if (we)
+ {
+ numset_release (g->numset, we->number);
+ list_move_tail (&we->node, &g->unmapped_windows);
+ }
+}
+
+void
+groups_unmap_window (rp_window *win)
+{
+ rp_group *cur;
+
+ list_for_each_entry (cur, &rp_groups, node)
+ {
+ group_unmap_window (cur, win);
+ }
+}
+
+void
+group_del_window (rp_group *g, rp_window *win)
+{
+ rp_window_elem *cur;
+ struct list_head *iter, *tmp;
+
+ /* The assumption is that a window is unmapped before it's deleted. */
+ list_for_each_safe_entry (cur, iter, tmp, &g->unmapped_windows, node)
+ {
+ if (cur->win == win)
+ {
+ numset_release (g->numset, cur->number);
+ list_del (&cur->node);
+ free (cur);
+ }
+ }
+}
+
+/* Remove the window from any groups in resides in. */
+void
+groups_del_window (rp_window *win)
+{
+ rp_group *cur;
+
+ list_for_each_entry (cur, &rp_groups, node)
+ {
+ group_del_window (cur, win);
+ }
+}
+
+rp_window *
+group_last_window (rp_group *g)
+{
+ int last_access = 0;
+ rp_window_elem *most_recent = NULL;
+ rp_window_elem *cur;
+
+ list_for_each_entry (cur, &g->mapped_windows, node)
+ {
+ if (cur->win->last_access >= last_access
+ && cur->win != current_window()
+ && !find_windows_frame (cur->win))
+ {
+ most_recent = cur;
+ last_access = cur->win->last_access;
+ }
+ }
+
+ if (most_recent)
+ return most_recent->win;
+
+ return NULL;
+}
+
+rp_window *
+group_next_window (rp_group *g, rp_window *win)
+{
+ rp_window_elem *cur, *we;
+
+ /* If there is no window, then get the last accessed one. */
+ if (win == NULL)
+ return group_last_window (g);
+
+ /* If we can't find the window, then it's in a different group, so
+ get the last accessed one in this group. */
+ we = group_find_window (&g->mapped_windows, win);
+ if (we == NULL)
+ return group_last_window (g);
+
+ /* The window is in this group, so find the next one in the list
+ that isn't already displayed. */
+ for (cur = list_next_entry (we, &g->mapped_windows, node);
+ cur != we;
+ cur = list_next_entry (cur, &g->mapped_windows, node))
+ {
+ if (!find_windows_frame (cur->win))
+ {
+ return cur->win;
+ }
+ }
+
+ return NULL;
+}
+
+rp_window *
+group_prev_window (rp_group *g, rp_window *win)
+{
+ rp_window_elem *cur, *we;
+
+ /* If there is no window, then get the last accessed one. */
+ if (win == NULL)
+ return group_last_window (g);
+
+ /* If we can't find the window, then it's in a different group, so
+ get the last accessed one in this group. */
+ we = group_find_window (&g->mapped_windows, win);
+ if (we == NULL)
+ return group_last_window (g);
+
+ /* The window is in this group, so find the previous one in the list
+ that isn't already displayed. */
+ for (cur = list_prev_entry (we, &g->mapped_windows, node);
+ cur != we;
+ cur = list_prev_entry (cur, &g->mapped_windows, node))
+ {
+ if (!find_windows_frame (cur->win))
+ {
+ return cur->win;
+ }
+ }
+
+ return NULL;
+
+}
diff --git a/src/group.h b/src/group.h
new file mode 100644
index 0000000..346ffe8
--- /dev/null
+++ b/src/group.h
@@ -0,0 +1,31 @@
+#ifndef GROUP_H
+#define GROUP_H
+
+void init_groups ();
+void group_add_window (rp_group *g, rp_window *w);
+void group_free (rp_group *g);
+rp_group *group_new (int number);
+
+void group_del_window (rp_group *g, rp_window *win);
+void groups_del_window (rp_window *win);
+
+void group_map_window (rp_group *g, rp_window *win);
+void groups_map_window (rp_window *win);
+
+void group_unmap_window (rp_group *g, rp_window *win);
+void groups_unmap_window (rp_window *win);
+
+rp_window *group_prev_window (rp_group *g, rp_window *win);
+rp_window *group_next_window (rp_group *g, rp_window *win);
+
+rp_window *group_last_window (rp_group *g);
+
+rp_group *group_prev_group ();
+rp_group *group_next_group ();
+
+rp_group *group_add_new_group ();
+
+rp_window_elem *group_find_window (struct list_head *list, rp_window *win);
+rp_window *group_find_window_by_number (rp_group *g, int num);
+
+#endif
diff --git a/src/main.c b/src/main.c
index 8ecc045..df919a5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -45,50 +45,6 @@
static void init_screen (rp_screen *s, int screen_num);
-int alarm_signalled = 0;
-int kill_signalled = 0;
-int hup_signalled = 0;
-int chld_signalled = 0;
-int rat_x;
-int rat_y;
-int rat_visible = 1; /* rat is visible by default */
-
-Atom wm_name;
-Atom wm_state;
-Atom wm_change_state;
-Atom wm_protocols;
-Atom wm_delete;
-Atom wm_take_focus;
-Atom wm_colormaps;
-
-Atom rp_command;
-Atom rp_command_request;
-Atom rp_command_result;
-
-int rp_current_screen;
-rp_screen *screens;
-int num_screens;
-Display *dpy;
-
-LIST_HEAD (rp_children);
-struct rp_defaults defaults;
-
-int ignore_badwindow = 0;
-
-char **myargv;
-
-struct rp_key prefix_key;
-
-struct modifier_info rp_modifier_info;
-
-/* rudeness levels */
-int rp_honour_transient_raise = 1;
-int rp_honour_normal_raise = 1;
-int rp_honour_transient_map = 1;
-int rp_honour_normal_map = 1;
-
-char *rp_error_msg = NULL;
-
/* Command line options */
static struct option ratpoison_longopts[] =
{ {"help", no_argument, 0, 'h'},
@@ -605,6 +561,7 @@ main (int argc, char *argv[])
/* Setup ratpoison's internal structures */
init_defaults ();
+ init_groups ();
init_window_stuff ();
/* Get the number of screens */
diff --git a/src/manage.c b/src/manage.c
index 4f7fe14..f6d5657 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -347,7 +347,10 @@ void
unmanage (rp_window *w)
{
numset_release (rp_window_numset, w->number);
+
list_del (&w->node);
+ groups_del_window (w);
+
free_window (w);
#ifdef AUTO_CLOSE
@@ -724,6 +727,9 @@ map_window (rp_window *win)
list_del (&win->node);
insert_into_list (win, &rp_mapped_window);
+ /* Update all groups. */
+ groups_map_window (win);
+
/* The window has never been accessed since it was brought back from
the Withdrawn state. */
win->last_access = 0;
@@ -806,6 +812,9 @@ withdraw_window (rp_window *win)
list_move_tail(&win->node, &rp_unmapped_window);
+ /* Update the groups. */
+ groups_unmap_window (win);
+
ignore_badwindow++;
XRemoveFromSaveSet (dpy, win->w);
diff --git a/src/ratpoison.h b/src/ratpoison.h
index e4d58eb..e1baf21 100644
--- a/src/ratpoison.h
+++ b/src/ratpoison.h
@@ -58,6 +58,7 @@ extern XGCValues gv;
#include "conf.h"
#include "data.h"
+#include "globals.h"
#include "manage.h"
#include "window.h"
#include "bar.h"
@@ -70,6 +71,7 @@ extern XGCValues gv;
#include "split.h"
#include "frame.h"
#include "screen.h"
+#include "group.h"
void clean_up ();
rp_screen *find_screen (Window w);
diff --git a/src/split.c b/src/split.c
index 7b4106b..b64164b 100644
--- a/src/split.c
+++ b/src/split.c
@@ -267,24 +267,27 @@ find_window_for_frame (rp_frame *frame)
{
rp_screen *s = frames_screen (frame);
int last_access = 0;
- rp_window *most_recent = NULL;
- rp_window *cur;
+ rp_window_elem *most_recent = NULL;
+ rp_window_elem *cur;
- list_for_each_entry (cur, &rp_mapped_window, node)
+ list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
{
- if (cur->scr == s
- && cur != current_window()
- && !find_windows_frame (cur)
- && cur->last_access >= last_access
- && window_fits_in_frame (cur, frame)
- && cur->frame_number == EMPTY)
+ if (cur->win->scr == s
+ && cur->win != current_window()
+ && !find_windows_frame (cur->win)
+ && cur->win->last_access >= last_access
+ && window_fits_in_frame (cur->win, frame)
+ && cur->win->frame_number == EMPTY)
{
most_recent = cur;
- last_access = cur->last_access;
+ last_access = cur->win->last_access;
}
}
- return most_recent;
+ if (most_recent)
+ return most_recent->win;
+
+ return NULL;
}
/* Splits the frame in 2. if way is 0 then split vertically otherwise
diff --git a/src/window.c b/src/window.c
index 5c1cfb5..ec7b088 100644
--- a/src/window.c
+++ b/src/window.c
@@ -141,6 +141,9 @@ 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);
+
return new_window;
}
@@ -207,19 +210,15 @@ str_comp (char *s1, char *s2, int len)
return 1;
}
-/* return a window by name */
rp_window *
find_window_name (char *name)
{
- rp_window *w;
+ rp_window_elem *cur;
- list_for_each_entry (w,&rp_mapped_window,node)
+ list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
{
-/* if (w->state == STATE_UNMAPPED) */
-/* continue; */
-
- if (str_comp (name, window_name (w), strlen (name)))
- return w;
+ if (str_comp (name, window_name (cur->win), strlen (name)))
+ return cur->win;
}
/* didn't find it */
@@ -273,23 +272,10 @@ find_window_next (rp_window *w)
rp_window *
find_window_other ()
{
- int last_access = 0;
- rp_window *most_recent = NULL;
- rp_window *cur;
+ return group_last_window (rp_current_group);
+}
- list_for_each_entry (cur, &rp_mapped_window, node)
- {
- if (cur->last_access >= last_access
- && cur != current_window()
- && !find_windows_frame (cur))
- {
- most_recent = cur;
- last_access = cur->last_access;
- }
- }
- return most_recent;
-}
/* Assumes the list is sorted by increasing number. Inserts win into
to Right place to keep the list sorted. */
@@ -542,7 +528,7 @@ print_window_information (rp_window *win)
*/
static void
-format_window_name (char *fmt, rp_window *win, rp_window *other_win,
+format_window_name (char *fmt, rp_window_elem *win_elem, rp_window *other_win,
struct sbuf *buffer)
{
int esc = 0;
@@ -561,44 +547,44 @@ format_window_name (char *fmt, rp_window *win, rp_window *other_win,
switch (*fmt)
{
case 'n':
- snprintf (dbuf, 10, "%d", win->number);
+ snprintf (dbuf, 10, "%d", win_elem->number);
sbuf_concat (buffer, dbuf);
break;
case 's':
- if (win == current_window())
+ if (win_elem->win == current_window())
sbuf_concat (buffer, "*");
- else if (win == other_win)
+ else if (win_elem->win == other_win)
sbuf_concat (buffer, "+");
else
sbuf_concat (buffer, "-");
break;
case 't':
- sbuf_concat (buffer, window_name (win));
+ sbuf_concat (buffer, window_name (win_elem->win));
break;
case 'a':
- if (win->res_name)
- sbuf_concat (buffer, win->res_name);
+ if (win_elem->win->res_name)
+ sbuf_concat (buffer, win_elem->win->res_name);
else
sbuf_concat (buffer, "None");
break;
case 'c':
- if (win->res_class)
- sbuf_concat (buffer, win->res_class);
+ if (win_elem->win->res_class)
+ sbuf_concat (buffer, win_elem->win->res_class);
else
sbuf_concat (buffer, "None");
break;
case 'i':
- snprintf (dbuf, 9, "%ld", (unsigned long)win->w);
+ snprintf (dbuf, 9, "%ld", (unsigned long)win_elem->win->w);
sbuf_concat (buffer, dbuf);
break;
case 'l':
- snprintf (dbuf, 9, "%d", win->last_access);
+ snprintf (dbuf, 9, "%d", win_elem->win->last_access);
sbuf_concat (buffer, dbuf);
break;
@@ -631,7 +617,7 @@ void
get_window_list (char *fmt, char *delim, struct sbuf *buffer,
int *mark_start, int *mark_end)
{
- rp_window *w;
+ rp_window_elem *we;
rp_window *other_window;
if (buffer == NULL) return;
@@ -639,11 +625,12 @@ get_window_list (char *fmt, char *delim, struct sbuf *buffer,
sbuf_clear (buffer);
other_window = find_window_other ();
- list_for_each_entry (w,&rp_mapped_window,node)
+ /* We only loop through the current group to look for windows. */
+ list_for_each_entry (we,&rp_current_group->mapped_windows,node)
{
- PRINT_DEBUG (("%d-%s\n", w->number, window_name (w)));
+ PRINT_DEBUG (("%d-%s\n", we->number, window_name (we->win)));
- if (w == current_window())
+ if (we->win == current_window())
*mark_start = strlen (sbuf_get (buffer));
/* A hack, pad the window with a space at the beginning and end
@@ -651,7 +638,7 @@ get_window_list (char *fmt, char *delim, struct sbuf *buffer,
if (!delim)
sbuf_concat (buffer, " ");
- format_window_name (fmt, w, other_window, buffer);
+ format_window_name (fmt, we, other_window, buffer);
/* A hack, pad the window with a space at the beginning and end
if there is no delimiter. */
@@ -660,10 +647,10 @@ get_window_list (char *fmt, char *delim, struct sbuf *buffer,
/* Only put the delimiter between the windows, and not after the the last
window. */
- if (delim && w->node.next != &rp_mapped_window)
+ if (delim && we->node.next != &rp_current_group->mapped_windows)
sbuf_concat (buffer, delim);
- if (w == current_window())
+ if (we->win == current_window())
{
if(defaults.window_list_style == STYLE_ROW)
{