diff options
author | sabetts <sabetts> | 2004-11-19 02:09:42 +0000 |
---|---|---|
committer | sabetts <sabetts> | 2004-11-19 02:09:42 +0000 |
commit | 4bbc65a39c7fb6c4b14dcb9c6bc22ba29ad148ba (patch) | |
tree | 02aed8e089c3b8409156f7f0cd6590d55e4c1545 /src | |
parent | 3597d7d9eaff4d51b8825b9eea443ce7db86c733 (diff) | |
download | ratpoison-4bbc65a39c7fb6c4b14dcb9c6bc22ba29ad148ba.zip |
* src/actions.c (set_vars): add maxundos
(push_frame_undo): new function
(pop_frame_undo): likewise
(initialize_default_keybindings): add binding for "undo"
(initialize_default_keybindings): add def alias for maxundos
(cmd_other): call set_active_window_force instead of
set_active_window
(cmd_v_split): push the frame set
(cmd_h_split): likewise
(cmd_only): likewise
(cmd_remove): likewise
(cmd_shrink): likewise
(cmd_tmpwm): likewise
(cmd_license): update copyright. Add build date and time.
(cmd_fselect): simplify code that returns the frame selected.
(fdump): new function
(cmd_fdump): call fdump to dump the screen's frame set.
(frestore): new function
(cmd_frestore): call frestore to restore the screen's frame set.
(cmd_sfdump): new function
(cmd_sdump): likewise
(set_maxundos): likewise
(cmd_cnext): likewise
(cmd_cprev): likewise
(cmd_inext): likewise
(cmd_iprev): likewise
(cmd_cother): likewise
(cmd_iother): likewise
(cmd_undo): likewise
(cmd_prompt): likewise
(cmd_describekey): likewise
(cmd_dedicate): likewise
* src/main.c (init_defaults): init maxundos to 20
(clean_up): free the undo history lists
* src/window.h (set_active_window_body): new function
(set_active_window_force): likewise
* src/window.c (set_active_window): new function
(set_active_window_force): likewise
(set_active_window_body): renamed from set_active_window
(set_active_window_body): Add code to handle dedicated frames.
* src/screen.h (screen_dump): new prototype
* src/screen.c (screen_dump): new function
* src/linkedlist.h (list_last): new macro
* src/group.h (group_last_window_by_class_complement): new prototype
(group_last_window_by_class): likewise
* src/group.c (group_last_window_by_class): new function
(group_last_window_by_class_complement): likewise
* src/globals.h (rp_frame_undos): new extern.
(rp_num_frame_undos): likewise
* src/globals.c (rp_frame_undos): new list.
(rp_num_frame_undos): new global
* src/frame.c (frame_new): init f->dedicated to 0.
* src/data.h (struct rp_frame): add dedicated member.
(struct rp_defaults): add maxundos member.
(struct rp_frame_undo): new struct.
* src/actions.c: new commands, cnext, cother, cprev,
Diffstat (limited to 'src')
-rw-r--r-- | src/actions.c | 481 | ||||
-rw-r--r-- | src/actions.h | 14 | ||||
-rw-r--r-- | src/data.h | 18 | ||||
-rw-r--r-- | src/frame.c | 1 | ||||
-rw-r--r-- | src/globals.c | 5 | ||||
-rw-r--r-- | src/globals.h | 2 | ||||
-rw-r--r-- | src/group.c | 55 | ||||
-rw-r--r-- | src/group.h | 2 | ||||
-rw-r--r-- | src/linkedlist.h | 9 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/screen.c | 21 | ||||
-rw-r--r-- | src/screen.h | 2 | ||||
-rw-r--r-- | src/window.c | 66 | ||||
-rw-r--r-- | src/window.h | 2 |
14 files changed, 666 insertions, 22 deletions
diff --git a/src/actions.c b/src/actions.c index e334de1..fee6e77 100644 --- a/src/actions.c +++ b/src/actions.c @@ -120,6 +120,19 @@ static user_command user_commands[] = {"vsplit", cmd_v_split, arg_STRING}, {"warp", cmd_warp, arg_STRING}, {"windows", cmd_windows, arg_VOID}, + {"cnext", cmd_cnext, arg_VOID}, + {"cother", cmd_cother, arg_VOID}, + {"cprev", cmd_cprev, arg_VOID}, + {"dedicate", cmd_dedicate, arg_VOID}, + {"describekey", cmd_describekey, arg_STRING}, + {"focusprev", cmd_prev_frame, arg_VOID}, + {"inext", cmd_inext, arg_VOID}, + {"iother", cmd_iother, arg_VOID}, + {"iprev", cmd_iprev, arg_VOID}, + {"prompt", cmd_prompt, arg_STRING}, + {"sdump", cmd_sdump, arg_VOID}, + {"sfdump", cmd_sfdump, arg_VOID}, + {"undo", cmd_undo, arg_STRING}, /*@end (tag required for genrpbindings) */ /* Commands to help debug ratpoison. */ @@ -161,8 +174,10 @@ static char * set_bgcolor (char *data); static char * set_barpadding (char *data); static char * set_winliststyle (char *data); static char * set_framesels (char *data); +static char * set_maxundos (char *data); static struct set_var set_vars[] = { {"resizeunit", set_resizeunit}, + {"maxundos", set_maxundos}, {"wingravity", set_wingravity}, {"transgravity", set_transgravity}, {"maxsizegravity", set_maxsizegravity}, @@ -192,6 +207,35 @@ static alias_t *alias_list; static int alias_list_size; static int alias_list_last; +static char *frestore (char *data, rp_screen *s); +static char *fdump (rp_screen *screen); + +static void +push_frame_undo(rp_screen *screen) +{ + rp_frame_undo *cur; + if (rp_num_frame_undos > defaults.maxundos) + { + /* Delete the oldest node */ + list_last (cur, &rp_frame_undos, node); + pop_frame_undo (cur); + } + cur = xmalloc (sizeof(rp_frame_undo)); + cur->frames = fdump (screen); + cur->screen = screen; + list_add (&cur->node, &rp_frame_undos); + rp_num_frame_undos++; /* increment counter */ +} + +void +pop_frame_undo (rp_frame_undo *u) +{ + if (!u) return; + if (u->frames) free (u->frames); + list_del (&(u->node)); + rp_num_frame_undos--; /* decrement counter */ +} + rp_action* find_keybinding_by_action (char *action, rp_keymap *map) { @@ -483,6 +527,7 @@ initialize_default_keybindings (void) add_keybinding (XK_r, 0, "resize", map); add_keybinding (XK_r, RP_CONTROL_MASK, "resize", map); add_keybinding (XK_question, 0, "help " ROOT_KEYMAP, map); + add_keybinding (XK_underscore, RP_CONTROL_MASK, "undo", map); add_alias ("unbind", "definekey " ROOT_KEYMAP); add_alias ("bind", "definekey " ROOT_KEYMAP); @@ -504,6 +549,7 @@ initialize_default_keybindings (void) add_alias ("defbarpadding", "set barpadding"); add_alias ("defwinliststyle", "set winliststyle"); add_alias ("defframesels", "set framesels"); + add_alias ("defmaxundos", "set maxundos"); } void @@ -922,7 +968,7 @@ cmd_other (int interactive, char *data) if (!w) message (MESSAGE_NO_OTHER_WINDOW); else - set_active_window (w); + set_active_window_force (w); return NULL; } @@ -1674,6 +1720,7 @@ cmd_v_split (int interactive, char *data) rp_frame *frame; int pixels; + push_frame_undo (current_screen()); /* fdump to stack */ frame = current_frame(); /* Default to dividing the frame in half. */ @@ -1696,6 +1743,7 @@ cmd_h_split (int interactive, char *data) rp_frame *frame; int pixels; + push_frame_undo (current_screen()); /* fdump to stack */ frame = current_frame(); /* Default to dividing the frame in half. */ @@ -1715,6 +1763,7 @@ cmd_h_split (int interactive, char *data) char * cmd_only (int interactive, char *data) { + push_frame_undo (current_screen()); /* fdump to stack */ remove_all_splits(); maximize (current_window()); @@ -1727,6 +1776,8 @@ cmd_remove (int interactive, char *data) rp_screen *s = current_screen(); rp_frame *frame; + push_frame_undo (current_screen()); /* fdump to stack */ + if (num_frames(s) <= 1) { message (" remove: cannot remove only frame "); @@ -1748,6 +1799,7 @@ cmd_remove (int interactive, char *data) char * cmd_shrink (int interactive, char *data) { + push_frame_undo (current_screen()); /* fdump to stack */ resize_shrink_to_window (current_frame()); return NULL; } @@ -2036,9 +2088,9 @@ cmd_license (int interactive, char *data) int y = 10; int i; int max_width = 0; - char *license_text[] = { PACKAGE " " VERSION, + char *license_text[] = { PACKAGE " " VERSION, "(built " __DATE__ " " __TIME__ ")", "", - "Copyright (C) 2000, 2001 Shawn Betts", + "Copyright (C) 2000-2004 Shawn Betts", "", "ratpoison is free software; you can redistribute it and/or modify ", "it under the terms of the GNU General Public License as published by ", @@ -3418,6 +3470,7 @@ cmd_tmpwm (int interactive, char *data) int pid; int i; + push_frame_undo (current_screen()); /* fdump to stack */ if (data == NULL) { message (" tmpwm: one argument required "); @@ -3642,17 +3695,8 @@ cmd_fselect (int interactive, char *data) frame = find_frame_number (fnum); if (frame) { - char *s; - struct sbuf *sb; - - /* Return the frame number that was selected. */ - sb = sbuf_new(0); - sbuf_printf (sb, "%d", fnum); - s = sbuf_get(sb); - free (sb); - set_active_frame (frame); - return s; + return xsprintf("%d", frame->number); } else { @@ -3661,8 +3705,8 @@ cmd_fselect (int interactive, char *data) } } -char * -cmd_fdump (int interactively, char *data) +static char * +fdump (rp_screen *screen) { struct sbuf *s; char *tmp; @@ -3671,7 +3715,7 @@ cmd_fdump (int interactively, char *data) s = sbuf_new (0); /* FIXME: Oooh, gross! there's a trailing comma, yuk! */ - list_for_each_entry (cur, ¤t_screen()->frames, node) + list_for_each_entry (cur, &(screen->frames), node) { char *tmp; @@ -3687,9 +3731,33 @@ cmd_fdump (int interactively, char *data) } char * -cmd_frestore (int interactively, char *data) +cmd_fdump (int interactively, char *data) +{ + if (!data) + { + return fdump (current_screen()); + } + else + { + /* assert (NULL != data); */ + int snum; + if (1 != sscanf (data, "%d", &snum) + || snum < 0 + || num_screens <= snum) + { + message (" fdump: invalid argument "); + return NULL; + } + else + { + return fdump (&screens[snum]); + } + } +} + +static char * +frestore (char *data, rp_screen *s) { - rp_screen *s = current_screen(); char *token; char *dup; rp_frame *new, *cur; @@ -3791,6 +3859,13 @@ cmd_frestore (int interactively, char *data) } char * +cmd_frestore (int interactively, char *data) +{ + push_frame_undo (current_screen()); /* fdump to stack */ + return frestore (data, current_screen()); +} + +char * cmd_verbexec (int interactive, char *data) { char msg[100]="Running "; @@ -4517,3 +4592,373 @@ cmd_set (int interactive, char *data) free (rest); return NULL; } + +char * +cmd_sfdump (int interactively, char *data) +{ + struct sbuf *s; + char *tmp, *tmp2; + rp_frame *cur; + + s = sbuf_new (0); + + register int i; + for (i=0; i<num_screens; i++) + { + tmp2 = xsprintf (" %d,", (rp_have_xinerama)?(screens[i].xine_screen_num):(screens[i].screen_num)); + + /* FIXME: Oooh, gross! there's a trailing comma, yuk! */ + list_for_each_entry (cur, &(screens[i].frames), node) + { + char *tmp; + + tmp = frame_dump (cur); + sbuf_concat (s, tmp); + sbuf_concat (s, tmp2); + free (tmp); + } + + free (tmp2); + } + tmp = sbuf_get (s); + free (s); + return tmp; +} + +char * +cmd_sdump (int interactive, char *data) +{ + /* assert(!data); */ + struct sbuf *s; + char *tmp; + register int i; + + s = sbuf_new (0); + for (i=0; i<num_screens; ++i) + { + tmp = screen_dump (&screens[i]); + sbuf_concat (s, tmp); + if (i + 1 != num_screens) /* No trailing comma. */ + sbuf_concat (s, ","); + free (tmp); + } + + tmp = sbuf_get (s); + free (s); + return tmp; +} + +static char * +set_maxundos (char *data) +{ + int tmp; + rp_frame_undo *cur; + + if (!data) + return xsprintf ("%d", defaults.maxundos); + + if (1 != sscanf (data, "%d", &tmp) || tmp < 0) + { + message (" defmaxundos: invalid argument "); + return NULL; + } + + defaults.maxundos = tmp; + + /* Delete any superfluous undos */ + while (rp_num_frame_undos > defaults.maxundos) + { + /* Delete the oldest node */ + list_last (cur, &rp_frame_undos, node); + pop_frame_undo (cur); + } + + return NULL; +} + +char * +cmd_cnext (int interactive, char *data) +{ + rp_window *cur, *last, *win; + + cur = current_window(); + if (!cur || !cur->res_class) /* Can't be done. */ + return cmd_next (interactive, data); + + /* CUR !in cycle list, so LAST marks last node. */ + last = group_prev_window (rp_current_group, cur); + + if (last) + for (win = group_next_window (rp_current_group, cur); + win; + win = group_next_window (rp_current_group, win)) + { + if (win->res_class + && strcmp (cur->res_class, win->res_class)) + { + set_active_window_force (win); + return NULL; + } + + if (win == last) break; + } + + message (MESSAGE_NO_OTHER_WINDOW); + return NULL; +} + +char * +cmd_cprev (int interactive, char *data) +{ + rp_window *cur, *last, *win; + + cur = current_window(); + if (!cur || !cur->res_class) /* Can't be done. */ + return cmd_next (interactive, data); + + /* CUR !in cycle list, so LAST marks last node. */ + last = group_next_window (rp_current_group, cur); + + if (last) + for (win = group_prev_window (rp_current_group, cur); + win; + win = group_prev_window (rp_current_group, win)) + { + if (win->res_class + && strcmp (cur->res_class, win->res_class)) + { + set_active_window_force (win); + return NULL; + } + + if (win == last) break; + } + + message (MESSAGE_NO_OTHER_WINDOW); + return NULL; +} + +char * +cmd_inext (int interactive, char *data) +{ + rp_window *cur, *last, *win; + + cur = current_window(); + if (!cur || !cur->res_class) /* Can't be done. */ + return cmd_next (interactive, data); + + /* CUR !in cycle list, so LAST marks last node. */ + last = group_prev_window (rp_current_group, cur); + + if (last) + for (win = group_next_window (rp_current_group, cur); + win; + win = group_next_window (rp_current_group, win)) + { + if (win->res_class + && !strcmp (cur->res_class, win->res_class)) + { + set_active_window_force (win); + return NULL; + } + + if (win == last) break; + } + + message (MESSAGE_NO_OTHER_WINDOW); + return NULL; +} + +char * +cmd_iprev (int interactive, char *data) +{ + rp_window *cur, *last, *win; + + cur = current_window(); + if (!cur || !cur->res_class) /* Can't be done. */ + return cmd_next (interactive, data); + + /* CUR !in cycle list, so LAST marks last node. */ + last = group_next_window (rp_current_group, cur); + + if (last) + for (win = group_prev_window (rp_current_group, cur); + win; + win = group_prev_window (rp_current_group, win)) + { + if (win->res_class + && !strcmp (cur->res_class, win->res_class)) + { + set_active_window_force (win); + return NULL; + } + + if (win == last) break; + } + + message (MESSAGE_NO_OTHER_WINDOW); + return NULL; +} + +char * +cmd_cother (int interactive, char *data) +{ + rp_window *cur, *w; + + cur = current_window(); + w = group_last_window_by_class (rp_current_group, cur->res_class); + + if (!w) + message (MESSAGE_NO_OTHER_WINDOW); + else + set_active_window_force (w); + + return NULL; +} + +char * +cmd_iother (int interactive, char *data) +{ + rp_window *cur, *w; + + cur = current_window(); + w = group_last_window_by_class_complement (rp_current_group, cur->res_class); + + if (!w) + message (MESSAGE_NO_OTHER_WINDOW); + else + set_active_window_force (w); + + return NULL; +} + +char * +cmd_undo (int interactive, char *data) +{ + rp_frame_undo *cur; + + list_first (cur, &rp_frame_undos, node); + if (!cur) + { + message (" No more undo information available "); + return NULL; + } + else + { + char *ret; + + ret = frestore (cur->frames, cur->screen); + /* Delete the newest node */ + pop_frame_undo (cur); + return ret; + } +} + +char * +cmd_prompt (int interactive, char *data) +{ + char *query, *ret, *prefix; + + if (interactive) return NULL; + + if (NULL == data) + ret = get_input(MESSAGE_PROMPT_COMMAND, trivial_completions); + else + { + prefix = strchr (data, ':'); + if (prefix) + { + prefix++; /* Don't return the colon. */ + query = xmalloc (prefix - data + 1); + strncpy (query, data, prefix - data); + query[prefix - data] = 0; /* null terminate */ + ret = get_more_input (query, prefix, trivial_completions); + free (query); + } + else + { + ret = get_input (data, trivial_completions); + } + } + return ret; +} + +char * +cmd_describekey (int interactive, char *data) +{ + char *keysym_name; + rp_action *key_action; + KeySym keysym; /* Key pressed */ + unsigned int mod; /* Modifiers */ + int rat_grabbed = 0; + rp_keymap *map; + + if (data == NULL) + { + message (" readkey: keymap expected "); + return NULL; + } + + map = find_keymap (data); + if (map == NULL) + { + marked_message_printf (0, 0, " readkey: Unknown keymap '%s' ", data); + return NULL; + } + + XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime); + + /* Change the mouse icon to indicate to the user we are waiting for + more keystrokes */ + if (defaults.wait_for_key_cursor) + { + grab_rat(); + rat_grabbed = 1; + } + + read_key (&keysym, &mod, NULL, 0); + XUngrabKeyboard (dpy, CurrentTime); + + if (rat_grabbed) + ungrab_rat(); + + if ((key_action = find_keybinding (keysym, x11_mask_to_rp_mask (mod), map))) + { + char *result; + result = cmd_echo (1, key_action->data); + + /* Gobble the result. */ + if (result) + free (result); + } + else + { + /* No key match, notify user. */ + keysym_name = keysym_to_string (keysym, x11_mask_to_rp_mask (mod)); + marked_message_printf (0, 0, " %s unbound key ", keysym_name); + free (keysym_name); + } + + return NULL; +} + +char * +cmd_dedicate (int interactive, char *data) +{ + rp_frame *f; + + f = current_frame(); + if (!f) return NULL; + + if (data) + /* Whatever you set it to. */ + f->dedicated = atoi(data); + else + /* Just toggle it, rather than on or off. */ + f->dedicated = !(f->dedicated); + + marked_message_printf (0, 0, " Consider this frame %s. ", (f->dedicated)?"chaste":"promiscuous"); + + return NULL; +} + diff --git a/src/actions.h b/src/actions.h index 8f2df78..84237a7 100644 --- a/src/actions.h +++ b/src/actions.h @@ -129,6 +129,20 @@ char *cmd_ratwarp (int interactive, char *data); char *cmd_ratclick (int interactive, char *data); char *cmd_ratrelwarp (int interactive, char *data); char *cmd_rathold (int interactive, char *data); +char *cmd_cnext (int interactive, char *data); +char *cmd_cother (int interactive, char *data); +char *cmd_cprev (int interactive, char *data); +char *cmd_dedicate (int interactive, char *data); +char *cmd_describekey (int interactive, char *data); +char *cmd_inext (int interactive, char *data); +char *cmd_iother (int interactive, char *data); +char *cmd_iprev (int interactive, char *data); +char *cmd_prompt (int interactive, char *data); +char *cmd_sdump (int interactive, char *data); +char *cmd_sfdump (int interactively, char *data); +char *cmd_undo (int interactive, char *data); +void pop_frame_undo (rp_frame_undo *u); + rp_keymap *find_keymap (char *name); void initialize_default_keybindings (void); @@ -50,7 +50,11 @@ struct rp_frame /* For determining the last frame. */ int last_access; - + + /* Boolean that is set when a frame is + `dedicated' (a.k.a. glued) to one window. */ + unsigned int dedicated; + struct list_head node; }; @@ -237,6 +241,9 @@ struct rp_defaults int history_size; char *frame_selectors; + + /* How many frame sets to remember when undoing. */ + int maxundos; }; /* Information about a child process. */ @@ -325,4 +332,13 @@ struct rp_hook_db_entry struct list_head *hook; }; +typedef struct rp_frame_undo rp_frame_undo; +struct rp_frame_undo +{ + char *frames; + rp_screen *screen; + struct list_head node; +}; + + #endif /* _RATPOISON_DATA_H */ diff --git a/src/frame.c b/src/frame.c index 18352c1..6a06f8f 100644 --- a/src/frame.c +++ b/src/frame.c @@ -115,6 +115,7 @@ frame_new (rp_screen *s) f = xmalloc (sizeof (rp_frame)); f->number = numset_request (s->frames_numset); f->last_access = 0; + f->dedicated = 0; return f; } diff --git a/src/globals.c b/src/globals.c index f23eb9c..d57721e 100644 --- a/src/globals.c +++ b/src/globals.c @@ -87,7 +87,7 @@ struct rp_hook_db_entry rp_hook_db[]= {"quit", &rp_quit_hook}, {"restart", &rp_restart_hook}, {NULL, NULL}}; - + void set_rp_window_focus (rp_window *win) { @@ -103,3 +103,6 @@ set_window_focus (Window window) XSetInputFocus (dpy, window, RevertToPointerRoot, CurrentTime); } + +LIST_HEAD (rp_frame_undos); +int rp_num_frame_undos = 0; diff --git a/src/globals.h b/src/globals.h index 063abc3..6dd0136 100644 --- a/src/globals.h +++ b/src/globals.h @@ -146,4 +146,6 @@ extern int xine_screen_count; extern struct numset *rp_frame_numset; +extern struct list_head rp_frame_undos; +extern int rp_num_frame_undos; #endif diff --git a/src/group.c b/src/group.c index 883e7d8..43fab12 100644 --- a/src/group.c +++ b/src/group.c @@ -508,3 +508,58 @@ group_delete_group (rp_group *g) } } +/* Used by :cother / :iother */ +rp_window * +group_last_window_by_class (rp_group *g, char *class) +{ + int last_access = 0; + rp_window_elem *most_recent = NULL; + rp_window_elem *cur; + rp_screen *s = current_screen(); + + 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) + && (cur->win->scr == s || rp_have_xinerama) + && strcmp(class, cur->win->res_class)) + { + most_recent = cur; + last_access = cur->win->last_access; + } + } + + if (most_recent) + return most_recent->win; + + return NULL; +} + +/* Used by :cother / :iother */ +rp_window * +group_last_window_by_class_complement (rp_group *g, char *class) +{ + int last_access = 0; + rp_window_elem *most_recent = NULL; + rp_window_elem *cur; + rp_screen *s = current_screen(); + + 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) + && (cur->win->scr == s || rp_have_xinerama) + && !strcmp(class, cur->win->res_class)) + { + most_recent = cur; + last_access = cur->win->last_access; + } + } + + if (most_recent) + return most_recent->win; + + return NULL; +} diff --git a/src/group.h b/src/group.h index 7678bbb..c314f20 100644 --- a/src/group.h +++ b/src/group.h @@ -39,4 +39,6 @@ void groups_merge (rp_group *from, rp_group *to); void set_current_group (rp_group *g); +rp_window *group_last_window_by_class (rp_group *g, char *class); +rp_window *group_last_window_by_class_complement (rp_group *g, char *class); #endif diff --git a/src/linkedlist.h b/src/linkedlist.h index fc1b8db..a056093 100644 --- a/src/linkedlist.h +++ b/src/linkedlist.h @@ -57,6 +57,14 @@ void __list_add(struct list_head *new, struct list_head *next); void prefetch(const void *x); +/* Return the last element in the list. */ +#define list_last(last, head, member) \ +{ \ + last = list_entry((head)->prev, typeof(*last), member); \ + if (&last->member == (head)) \ + last = NULL; \ +} + /** * container_of - cast a member of a structure out to the containing structure @@ -180,3 +188,4 @@ void prefetch(const void *x); if (&first->member == (head)) \ first = NULL; \ } + @@ -499,6 +499,7 @@ init_defaults () defaults.history_size = 20; defaults.frame_selectors = xstrdup (""); + defaults.maxundos = 20; } int @@ -705,6 +706,15 @@ clean_up () } free (screens); + /* Delete the undo histories */ + while (rp_num_frame_undos > 0) + { + /* Delete the oldest node */ + rp_frame_undo *cur; + list_last (cur, &rp_frame_undos, node); + pop_frame_undo (cur); + } + /* Free the global frame numset shared by all screens. */ free (rp_frame_numset); diff --git a/src/screen.c b/src/screen.c index 56aa96e..cf88895 100644 --- a/src/screen.c +++ b/src/screen.c @@ -354,3 +354,24 @@ is_rp_window_for_screen(Window w, rp_screen *s) } } +char * +screen_dump (rp_screen *screen) +{ + char *tmp; + struct sbuf *s; + + s = sbuf_new (0); + sbuf_printf (s, "%d %d %d %d %d %d", + (rp_have_xinerama)?screen->xine_screen_num:screen->screen_num, + screen->left, + screen->top, + screen->width, + screen->height, + (current_screen() == screen)?1:0 /* is current? */ + ); + + /* Extract the string and return it, and don't forget to free s. */ + tmp = sbuf_get (s); + free (s); + return tmp; +} diff --git a/src/screen.h b/src/screen.h index fdc37af..b7c4fc1 100644 --- a/src/screen.h +++ b/src/screen.h @@ -39,4 +39,6 @@ void init_screens (int screen_arg, int screen_num); int is_rp_window_for_screen (Window w, rp_screen *s); int is_a_root_window (int w); +char *screen_dump (rp_screen *screen); + #endif diff --git a/src/window.c b/src/window.c index 68e5963..5ba5454 100644 --- a/src/window.c +++ b/src/window.c @@ -455,11 +455,21 @@ is_transient_ancestor (rp_window *win, rp_window *transient_for) #endif /* In the current frame, set the active window to win. win will have focus. */ +void set_active_window (rp_window *win) +{ + set_active_window_body(win, 0); +} + +void set_active_window_force (rp_window *win) +{ + set_active_window_body(win, 1); +} + void -set_active_window (rp_window *win) +set_active_window_body (rp_window *win, int force) { rp_window *last_win; - rp_frame *frame; + rp_frame *frame, *last_frame = NULL; if (win == NULL) return; @@ -474,6 +484,54 @@ set_active_window (rp_window *win) { frame = screen_get_frame (win->scr, win->scr->current_frame); } + + if (frame->dedicated && !force) + { + /* Try to find a non-dedicated frame. */ + rp_frame *cur; + rp_screen *scr; + int done; + + scr = (rp_have_xinerama)?&screens[rp_current_screen]:win->scr; + done = 0; + + /* Try the only / current screen... */ + for (cur = list_next_entry (frame, &scr->frames, node); + cur != frame && !done; + cur = list_next_entry (cur, &scr->frames, node)) + { + if (!cur->dedicated) + { + set_active_frame (cur); + last_frame = frame; + frame = cur; + done = 1; + } + } + + /* If we have Xinerama, we can check *all* screens... */ + if (rp_have_xinerama && !done) + { + int i; + + for (i=0; i<num_screens && !done; i++) + { + if (scr == &screens[i]) continue; + list_for_each_entry (cur,&screens[i].frames,node) + { + if (!cur->dedicated) + { + set_active_frame (cur); + last_frame = frame; + frame = cur; + done = 1; /* Break outer loop. */ + break; /* Break inner loop. */ + } + } + } + } + } + last_win = set_frames_window (frame, win); if (last_win) PRINT_DEBUG (("last window: %s\n", window_name (last_win))); @@ -502,6 +560,10 @@ set_active_window (rp_window *win) XSync (dpy, False); + /* If we switched frame, go back to the old one. */ + if (last_frame) + set_active_frame (last_frame); + /* Call the switch window hook */ hook_run (&rp_switch_win_hook); } diff --git a/src/window.h b/src/window.h index 874de05..f0ec828 100644 --- a/src/window.h +++ b/src/window.h @@ -65,4 +65,6 @@ void free_window_stuff (); rp_frame *win_get_frame (rp_window *win); +void set_active_window_force (rp_window *win); +void set_active_window_body (rp_window *win, int force); #endif /* ! _RATPOISON_LIST_H */ |