diff options
author | sabetts <sabetts> | 2003-05-16 23:25:06 +0000 |
---|---|---|
committer | sabetts <sabetts> | 2003-05-16 23:25:06 +0000 |
commit | cf843449115562fe44be792e37bd78639414da4e (patch) | |
tree | 0eba8dbd41b3ad9328b600ca35b4d41e34aaec60 | |
parent | bcf85f95069519c29b2263ff5391a4da0442188e (diff) | |
download | ratpoison-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-- | ChangeLog | 43 | ||||
-rw-r--r-- | FAQ | 20 | ||||
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/actions.c | 191 | ||||
-rw-r--r-- | src/actions.h | 5 | ||||
-rw-r--r-- | src/data.h | 134 | ||||
-rw-r--r-- | src/globals.c | 47 | ||||
-rw-r--r-- | src/globals.h | 103 | ||||
-rw-r--r-- | src/group.c | 272 | ||||
-rw-r--r-- | src/group.h | 31 | ||||
-rw-r--r-- | src/main.c | 45 | ||||
-rw-r--r-- | src/manage.c | 9 | ||||
-rw-r--r-- | src/ratpoison.h | 2 | ||||
-rw-r--r-- | src/split.c | 25 | ||||
-rw-r--r-- | src/window.c | 69 |
16 files changed, 726 insertions, 281 deletions
@@ -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 @@ -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? @@ -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); @@ -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 @@ -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) { |