From eac6dda17283fe9f312d0c8576f4370f82fc5c0a Mon Sep 17 00:00:00 2001 From: sabetts Date: Mon, 31 Mar 2003 07:06:22 +0000 Subject: * src/split.c (current_window): call screen_get_frame. (split_frame): call screen_get_frame to get appropriate structure. (split_frame): call find_window_number to get appropriate structure. (remove_all_splits): call screen_get_frame to get appropriate structure. (resize_frame): make sure all frames that will be resized are big enough for the resize. (resize_frame): return int (resize_shrink_to_window): call find_window_number to get the appropriate structure. (resize_frame_right): return int (resize_frame_left): likewise (resize_frame_top): likewise (resize_frame_bottom): likewise (resize_frame_horizontally): backup the frameset and restore it if the resize fails. Do not allow a frame to be resized too small or too big. (resize_frame_vertically): likewise (remove_frame): call find_window_number to get the appropriate structure. (set_active_frame): likewise (blank_frame): likewise (show_frame_message): call screen_get_frame to get the appropriate structure. * src/screen.c (screen_width): new function (and prototype) (screen_height): likewise (screen_left): likewise (screen_right): likewise (screen_top): likewise (screen_bottom): likewise (screen_copy_frameset): likewise (screen_restore_frameset): likewise (frameset_free): likewise (screen_get_frame): likewise * src/split.c (maximize_frame): call screen_width and screen_height to get the size for the frame. * src/ratpoison.h: include screen.h * src/manage.c (move_window): * src/frame.h (frame_copy): new prototype (frame_dump): likewise * src/frame.c (frame_copy): new function (frame_dump): likewise * src/events.c (unmap_notify): compare frame numbers, not pointers. (client_msg): call screen_get_frame when blanking the frame. * src/data.h (EMPTY): new define (struct rp_window_frame): replace the win field with win_number. Dependant code updated. (struct rp_window): replace frame with frame_number. Dependant code updated. (struct screen_info): replace rp_current_frame with current_frame and change type to int. Dependant code updated. * src/Makefile.am (ratpoison_SOURCES): added screen.h and screen.c --- ChangeLog | 66 ++++++++++++++ src/Makefile.am | 4 +- src/actions.c | 92 +++++++++++++------- src/data.h | 15 +++- src/events.c | 12 ++- src/frame.c | 41 +++++++++ src/frame.h | 2 + src/manage.c | 34 ++++---- src/ratpoison.h | 1 + src/screen.c | 118 +++++++++++++++++++++++++ src/screen.h | 36 ++++++++ src/split.c | 264 ++++++++++++++++++++++++++++++++++++-------------------- src/window.c | 18 +++- src/window.h | 2 + 14 files changed, 557 insertions(+), 148 deletions(-) create mode 100644 src/screen.c create mode 100644 src/screen.h diff --git a/ChangeLog b/ChangeLog index f8fbd8c..30c15de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,69 @@ +2003-03-30 Shawn Betts + + * src/split.c (current_window): call screen_get_frame. + (split_frame): call screen_get_frame to get appropriate structure. + (split_frame): call find_window_number to get appropriate + structure. + (remove_all_splits): call screen_get_frame to get appropriate + structure. + (resize_frame): make sure all frames that will be resized are big + enough for the resize. + (resize_frame): return int + (resize_shrink_to_window): call find_window_number to get the + appropriate structure. + (resize_frame_right): return int + (resize_frame_left): likewise + (resize_frame_top): likewise + (resize_frame_bottom): likewise + (resize_frame_horizontally): backup the frameset and restore it if + the resize fails. Do not allow a frame to be resized too small or + too big. + (resize_frame_vertically): likewise + (remove_frame): call find_window_number to get the appropriate + structure. + (set_active_frame): likewise + (blank_frame): likewise + (show_frame_message): call screen_get_frame to get the appropriate + structure. + + * src/screen.c (screen_width): new function (and prototype) + (screen_height): likewise + (screen_left): likewise + (screen_right): likewise + (screen_top): likewise + (screen_bottom): likewise + (screen_copy_frameset): likewise + (screen_restore_frameset): likewise + (frameset_free): likewise + (screen_get_frame): likewise + + * src/split.c (maximize_frame): call screen_width and + screen_height to get the size for the frame. + + * src/ratpoison.h: include screen.h + + * src/manage.c (move_window): + + * src/frame.h (frame_copy): new prototype + (frame_dump): likewise + + * src/frame.c (frame_copy): new function + (frame_dump): likewise + + * src/events.c (unmap_notify): compare frame numbers, not + pointers. + (client_msg): call screen_get_frame when blanking the frame. + + * src/data.h (EMPTY): new define + (struct rp_window_frame): replace the win field with + win_number. Dependant code updated. + (struct rp_window): replace frame with frame_number. Dependant + code updated. + (struct screen_info): replace rp_current_frame with current_frame + and change type to int. Dependant code updated. + + * src/Makefile.am (ratpoison_SOURCES): added screen.h and screen.c + 2003-03-25 Shawn Betts * src/split.h (show_frame_message): new prototype diff --git a/src/Makefile.am b/src/Makefile.am index 798564b..5a10925 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.13 2003/03/07 11:43:26 sabetts Exp $ +## $Id: Makefile.am,v 1.14 2003/03/31 07:06:23 sabetts Exp $ bin_PROGRAMS = ratpoison @@ -47,6 +47,8 @@ ratpoison_SOURCES = actions.c \ ratpoison.h \ sbuf.c \ sbuf.h \ + screen.h \ + screen.c \ split.c \ split.h \ window.c \ diff --git a/src/actions.c b/src/actions.c index 8e18bf2..661e8f2 100644 --- a/src/actions.c +++ b/src/actions.c @@ -674,9 +674,9 @@ cmd_prev_frame (int interactive, void *data) { rp_window_frame *frame; - frame = find_frame_prev (current_screen()->rp_current_frame); + frame = find_frame_prev (screen_get_frame (current_screen(), current_screen()->current_frame)); if (!frame) - message (MESSAGE_NO_OTHER_WINDOW); + message (MESSAGE_NO_OTHER_FRAME); else set_active_frame (frame); @@ -716,7 +716,7 @@ cmd_next_frame (int interactive, void *data) { rp_window_frame *frame; - frame = find_frame_next (current_screen()->rp_current_frame); + frame = find_frame_next (screen_get_frame (current_screen(), current_screen()->current_frame)); if (!frame) message (MESSAGE_NO_OTHER_FRAME); else @@ -778,7 +778,7 @@ cmd_select (int interactive, void *data) { if (strlen (str) == 1 && str[0] == '-') { - blank_frame (current_screen()->rp_current_frame); + blank_frame (screen_get_frame (current_screen(), current_screen()->current_frame)); } /* else if ((w = find_window_name (str))) */ /* { */ @@ -1333,17 +1333,19 @@ read_split (const char *str, int max) char * cmd_h_split (int interactive, void *data) { + rp_window_frame *frame; int pixels; + frame = screen_get_frame (current_screen(), current_screen()->current_frame); + /* Default to dividing the frame in half. */ if (data == NULL) - pixels = current_screen()->rp_current_frame->height / 2; + pixels = frame->height / 2; else - pixels = read_split (data, current_screen()->rp_current_frame->height); - + pixels = read_split (data, frame->height); if (pixels > 0) - h_split_frame (current_screen()->rp_current_frame, pixels); + h_split_frame (frame, pixels); else message (" hsplit: invalid argument "); @@ -1353,16 +1355,19 @@ cmd_h_split (int interactive, void *data) char * cmd_v_split (int interactive, void *data) { + rp_window_frame *frame; int pixels; + frame = screen_get_frame (current_screen(), current_screen()->current_frame); + /* Default to dividing the frame in half. */ if (data == NULL) - pixels = current_screen()->rp_current_frame->width / 2; + pixels = frame->width / 2; else - pixels = read_split (data, current_screen()->rp_current_frame->width); + pixels = read_split (data, frame->width); if (pixels > 0) - v_split_frame (current_screen()->rp_current_frame, pixels); + v_split_frame (frame, pixels); else message (" vsplit: invalid argument "); @@ -1390,11 +1395,11 @@ cmd_remove (int interactive, void *data) return NULL; } - frame = find_frame_next (s->rp_current_frame); + frame = find_frame_next (screen_get_frame (s, s->current_frame)); if (frame) { - remove_frame (current_screen()->rp_current_frame); + remove_frame (screen_get_frame (s, s->current_frame)); set_active_frame (frame); } @@ -1406,7 +1411,7 @@ cmd_shrink (int interactive, void *data) { screen_info *s = current_screen (); - resize_shrink_to_window (s->rp_current_frame); + resize_shrink_to_window (screen_get_frame (s, s->current_frame)); return NULL; } @@ -1424,6 +1429,7 @@ cmd_resize (int interactive, void *data) unsigned int mod; KeySym c; Window fwin; + struct list_head *bk; /* If we haven't got at least 2 frames, there isn't anything to scale. */ @@ -1432,26 +1438,46 @@ cmd_resize (int interactive, void *data) XGetInputFocus (dpy, &fwin, &revert); XSetInputFocus (dpy, s->key_window, RevertToPointerRoot, CurrentTime); + /* Save the frameset in case the user aborts. */ + bk = screen_copy_frameset (s); + while (1) { show_frame_message (" Resize frame "); nbytes = read_key (&c, &mod, buffer, sizeof (buffer), 1); if (c == RESIZE_VGROW_KEY && mod == RESIZE_VGROW_MODIFIER) - resize_frame_vertically (s->rp_current_frame, defaults.frame_resize_unit); + resize_frame_vertically (screen_get_frame (s, s->current_frame), defaults.frame_resize_unit); else if (c == RESIZE_VSHRINK_KEY && mod == RESIZE_VSHRINK_MODIFIER) - resize_frame_vertically (s->rp_current_frame, -defaults.frame_resize_unit); + resize_frame_vertically (screen_get_frame (s, s->current_frame), -defaults.frame_resize_unit); else if (c == RESIZE_HGROW_KEY && mod == RESIZE_HGROW_MODIFIER) - resize_frame_horizontally (s->rp_current_frame, defaults.frame_resize_unit); + resize_frame_horizontally (screen_get_frame (s, s->current_frame), defaults.frame_resize_unit); else if (c == RESIZE_HSHRINK_KEY && mod == RESIZE_HSHRINK_MODIFIER) - resize_frame_horizontally (s->rp_current_frame, -defaults.frame_resize_unit); + resize_frame_horizontally (screen_get_frame (s, s->current_frame), -defaults.frame_resize_unit); else if (c == RESIZE_SHRINK_TO_WINDOW_KEY && mod == RESIZE_SHRINK_TO_WINDOW_MODIFIER) - resize_shrink_to_window (s->rp_current_frame); + resize_shrink_to_window (screen_get_frame (s, s->current_frame)); + else if (c == INPUT_ABORT_KEY && mod == INPUT_ABORT_MODIFIER) + { + rp_window_frame *cur; + + screen_restore_frameset (s, bk); + list_for_each_entry (cur, &s->rp_window_frames, node) + { + maximize_all_windows_in_frame (cur); + } + break; + } else if (c == RESIZE_END_KEY && mod == RESIZE_END_MODIFIER) - break; + { + frameset_free (bk); + break; + } } + /* It is our responsibility to free this. */ + free (bk); + hide_frame_indicator (); XSetInputFocus (dpy, fwin, RevertToPointerRoot, CurrentTime); } @@ -1465,8 +1491,8 @@ cmd_resize (int interactive, void *data) return NULL; } - resize_frame_horizontally (s->rp_current_frame, xdelta); - resize_frame_vertically (s->rp_current_frame, ydelta); + resize_frame_horizontally (screen_get_frame (s, s->current_frame), xdelta); + resize_frame_vertically (screen_get_frame (s, s->current_frame), ydelta); } return NULL; @@ -2104,7 +2130,7 @@ cmd_defborder (int interactive, void *data) /* Update all the visible windows. */ list_for_each_entry (win,&rp_mapped_window,node) { - if (win->frame) + if (win_get_frame (win)) maximize (win); } @@ -2462,7 +2488,7 @@ cmd_focusup (int interactive, void *data) { rp_window_frame *frame; - if ((frame = find_frame_up (current_screen()->rp_current_frame))) + if ((frame = find_frame_up (screen_get_frame (current_screen(), current_screen()->current_frame)))) set_active_frame (frame); return NULL; @@ -2473,7 +2499,7 @@ cmd_focusdown (int interactive, void *data) { rp_window_frame *frame; - if ((frame = find_frame_down (current_screen()->rp_current_frame))) + if ((frame = find_frame_down (screen_get_frame (current_screen(), current_screen()->current_frame)))) set_active_frame (frame); return NULL; @@ -2484,7 +2510,7 @@ cmd_focusleft (int interactive, void *data) { rp_window_frame *frame; - if ((frame = find_frame_left (current_screen()->rp_current_frame))) + if ((frame = find_frame_left (screen_get_frame (current_screen(), current_screen()->current_frame)))) set_active_frame (frame); return NULL; @@ -2495,7 +2521,7 @@ cmd_focusright (int interactive, void *data) { rp_window_frame *frame; - if ((frame = find_frame_right (current_screen()->rp_current_frame))) + if ((frame = find_frame_right (screen_get_frame (current_screen(), current_screen()->current_frame)))) set_active_frame (frame); return NULL; @@ -2707,7 +2733,7 @@ cmd_nextscreen (int interactive, void *data) if (new_screen >= num_screens) new_screen = 0; - set_active_frame (screens[new_screen].rp_current_frame); + set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame)); return NULL; } @@ -2728,7 +2754,7 @@ cmd_prevscreen (int interactive, void *data) if (new_screen < 0) new_screen = num_screens - 1; - set_active_frame (screens[new_screen].rp_current_frame); + set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame)); return NULL; } @@ -2797,7 +2823,7 @@ cmd_tmpwm (int interactive, void *data) /* Remove the window from the frame. */ frame = find_windows_frame (win); if (frame) cleanup_frame (frame); - if (frame == win->scr->rp_current_frame) set_active_frame (frame); + if (frame->number == win->scr->current_frame) set_active_frame (frame); /* put the window in the unmapped list. */ numset_release (rp_window_numset, win->number); @@ -2949,3 +2975,9 @@ cmd_fselect (int interactive, void *data) return NULL; } + +char * +cmd_restore (int interactively, void *data) +{ + return NULL; +} diff --git a/src/data.h b/src/data.h index e87d63e..c7bba0f 100644 --- a/src/data.h +++ b/src/data.h @@ -32,6 +32,11 @@ #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 + typedef struct rp_window rp_window; typedef struct screen_info screen_info; @@ -42,7 +47,9 @@ struct rp_window_frame { int number; int x, y, width, height; - rp_window *win; + + /* The number of the window that is focused in this frame. */ + int win_number; /* For determining the last frame. */ int last_access; @@ -88,7 +95,7 @@ struct rp_window /* A window can be visible inside a frame but not the frame's current window. This keeps track of what frame the window was mapped into. */ - rp_window_frame *frame; + int frame_number; struct list_head node; }; @@ -113,9 +120,9 @@ struct screen_info /* Keep track of which numbers have been given to frames. */ struct numset *frames_numset; - /* Pointer to the currently focused frame. One for each screen so + /* The number of the currently focused frame. One for each screen so when you switch screens the focus doesn't get frobbed. */ - rp_window_frame *rp_current_frame; + int current_frame; }; struct rp_action diff --git a/src/events.c b/src/events.c index b656f16..e73661f 100644 --- a/src/events.c +++ b/src/events.c @@ -94,7 +94,7 @@ unmap_notify (XEvent *ev) window. */ frame = find_windows_frame (win); if (frame) cleanup_frame (frame); - if (frame == win->scr->rp_current_frame) set_active_frame (frame); + if (frame->number == win->scr->current_frame) set_active_frame (frame); withdraw_window (win); break; @@ -180,8 +180,12 @@ destroy_window (XDestroyWindowEvent *ev) have been cleaned up with an unmap notify event, but just in case... */ frame = find_windows_frame (win); - if (frame) cleanup_frame (frame); - if (frame == win->scr->rp_current_frame) set_active_frame (frame); + if (frame) + { + cleanup_frame (frame); + if (frame->number == win->scr->current_frame) + set_active_frame (frame); + } unmanage (win); @@ -319,7 +323,7 @@ client_msg (XClientMessageEvent *ev) if (w) set_active_window (w); else - blank_frame (win->scr->rp_current_frame); + blank_frame (screen_get_frame (win->scr, win->scr->current_frame)); } } else diff --git a/src/frame.c b/src/frame.c index 6faf26e..6ac0277 100644 --- a/src/frame.c +++ b/src/frame.c @@ -124,3 +124,44 @@ frame_free (screen_info *s, rp_window_frame *f) numset_release (s->frames_numset, f->number); free (f); } + + +rp_window_frame * +frame_copy (rp_window_frame *frame) +{ + rp_window_frame *copy; + + copy = xmalloc (sizeof (rp_window_frame)); + + copy->number = frame->number; + copy->x = frame->x; + copy->y = frame->y; + copy->width = frame->width; + copy->height = frame->height; + copy->win_number = frame->win_number; + copy->last_access = frame->last_access; + + return copy; +} + +char * +frame_dump (rp_window_frame *frame) +{ + char *tmp; + struct sbuf *s; + + s = sbuf_new (0); + sbuf_printf (s, "%d %d %d %d %d %d %d", + frame->number, + frame->x, + frame->y, + frame->width, + frame->height, + frame->win_number, + frame->last_access); + + /* 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/frame.h b/src/frame.h index f2e1e4b..256bea3 100644 --- a/src/frame.h +++ b/src/frame.h @@ -38,5 +38,7 @@ int frame_left (rp_window_frame *frame); rp_window_frame *frame_new (screen_info *s); void frame_free (screen_info *s, rp_window_frame *f); +rp_window_frame *frame_copy (rp_window_frame *frame); +char *frame_dump (rp_window_frame *frame); #endif diff --git a/src/manage.c b/src/manage.c index 7a19934..93fe869 100644 --- a/src/manage.c +++ b/src/manage.c @@ -397,26 +397,30 @@ get_state (rp_window *win) static void move_window (rp_window *win) { - if (win->frame == NULL) + rp_window_frame *frame; + + if (win->frame_number == EMPTY) return; + frame = win_get_frame (win); + /* X coord. */ switch (win->gravity) { case NorthWestGravity: case WestGravity: case SouthWestGravity: - win->x = win->frame->x; + win->x = frame->x; break; case NorthGravity: case CenterGravity: case SouthGravity: - win->x = win->frame->x + (win->frame->width - win->border * 2) / 2 - win->width / 2; + win->x = frame->x + (frame->width - win->border * 2) / 2 - win->width / 2; break; case NorthEastGravity: case EastGravity: case SouthEastGravity: - win->x = win->frame->x + win->frame->width - win->width - win->border; + win->x = frame->x + frame->width - win->width - win->border; break; } @@ -426,17 +430,17 @@ move_window (rp_window *win) case NorthEastGravity: case NorthGravity: case NorthWestGravity: - win->y = win->frame->y; + win->y = frame->y; break; case EastGravity: case CenterGravity: case WestGravity: - win->y = win->frame->y + (win->frame->height - win->border * 2) / 2 - win->height / 2; + win->y = frame->y + (frame->height - win->border * 2) / 2 - win->height / 2; break; case SouthEastGravity: case SouthGravity: case SouthWestGravity: - win->y = win->frame->y + win->frame->height - win->height - win->border; + win->y = frame->y + frame->height - win->height - win->border; break; } } @@ -449,15 +453,15 @@ maximize_transient (rp_window *win) rp_window_frame *frame; int maxx, maxy; + frame = win_get_frame (win); + /* We can't maximize a window if it has no frame. */ - if (win->frame == NULL) + if (frame == NULL) return; /* Set the window's border */ win->border = defaults.window_border_width; - frame = win->frame; - /* Always use the window's current width and height for transients. */ maxx = win->width; @@ -507,15 +511,15 @@ maximize_normal (rp_window *win) rp_window_frame *frame; int maxx, maxy; + frame = win_get_frame (win); + /* We can't maximize a window if it has no frame. */ - if (win->frame == NULL) + if (frame == NULL) return; /* Set the window's border */ win->border = defaults.window_border_width; - frame = win->frame; - /* Honour the window's maximum size */ if (win->hints->flags & PMaxSize) { @@ -670,7 +674,7 @@ hide_window (rp_window *win) if (win == NULL) return; /* An unmapped window is not inside a frame. */ - win->frame = NULL; + win->frame_number = EMPTY; /* Ignore the unmap_notify event. */ XSelectInput(dpy, win->w, WIN_EVENTS&~(StructureNotifyMask)); @@ -748,7 +752,7 @@ hide_others (rp_window *win) { if (find_windows_frame (cur) || cur->state != NormalState - || cur->frame != frame) + || cur->frame_number != frame->number) continue; hide_window (cur); diff --git a/src/ratpoison.h b/src/ratpoison.h index 4a5dde7..cc1420f 100644 --- a/src/ratpoison.h +++ b/src/ratpoison.h @@ -69,6 +69,7 @@ extern XGCValues gv; #include "sbuf.h" #include "split.h" #include "frame.h" +#include "screen.h" void clean_up (); screen_info *find_screen (Window w); diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..aa7b1df --- /dev/null +++ b/src/screen.c @@ -0,0 +1,118 @@ +/* Copyright (C) 2000-2003 Shawn Betts + * + * This file is part of ratpoison. + * + * ratpoison is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ratpoison is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +#include "ratpoison.h" + +int +screen_width (screen_info *s) +{ + return DisplayWidth (dpy, s->screen_num) - defaults.padding_right - defaults.padding_left; +} + +int +screen_height (screen_info *s) +{ + return DisplayHeight (dpy, s->screen_num) - defaults.padding_bottom - defaults.padding_top; +} + +int +screen_left (screen_info *s) +{ + return defaults.padding_left; +} + +int +screen_right (screen_info *s) +{ + return screen_left (s) + screen_width (s); +} + +int +screen_top (screen_info *s) +{ + return defaults.padding_top; +} + +int +screen_bottom (screen_info *s) +{ + return screen_top (s) + screen_height (s); +} + +/* Returns a pointer to a list of frames. */ +struct list_head * +screen_copy_frameset (screen_info *s) +{ + struct list_head *head; + rp_window_frame *cur; + + /* Init our new list. */ + head = xmalloc (sizeof (struct list_head)); + INIT_LIST_HEAD (head); + + /* Copy each frame to our new list. */ + list_for_each_entry (cur, &s->rp_window_frames, node) + { + list_add_tail (&(frame_copy (cur))->node, head); + } + + return head; +} + +/* Set head as the frameset, deleting the existing one. */ +void +screen_restore_frameset (screen_info *s, struct list_head *head) +{ + frameset_free (&s->rp_window_frames); + INIT_LIST_HEAD (&s->rp_window_frames); + + /* Hook in our new frameset. */ + list_splice (head, &s->rp_window_frames); +} + +/* Given a list of frames, free them, but don't remove their numbers + from the numset. */ +void +frameset_free (struct list_head *head) +{ + rp_window_frame *frame; + struct list_head *iter, *tmp; + + list_for_each_safe_entry (frame, iter, tmp, head, node) + { + /* FIXME: what if rp_window_frames has memory inside its struct + that needs to be freed? */ + free (frame); + } +} + +rp_window_frame * +screen_get_frame (screen_info *s, int frame_num) +{ + rp_window_frame *cur; + + list_for_each_entry (cur, &s->rp_window_frames, node) + { + if (cur->number == frame_num) + return cur; + } + + return NULL; +} diff --git a/src/screen.h b/src/screen.h new file mode 100644 index 0000000..5b0bbc2 --- /dev/null +++ b/src/screen.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2000-2003 Shawn Betts + * + * This file is part of ratpoison. + * + * ratpoison is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ratpoison is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +#ifndef SCREEN_H +#define SCREEN_H + +int screen_bottom (screen_info *s); +int screen_top (screen_info *s); +int screen_right (screen_info *s); +int screen_left (screen_info *s); +int screen_height (screen_info *s); +int screen_width (screen_info *s); + +struct list_head *screen_copy_frameset (screen_info *s); +void screen_restore_frameset (screen_info *s, struct list_head *head); +void frameset_free (struct list_head *head); +rp_window_frame *screen_get_frame (screen_info *s, int frame_num); + +#endif diff --git a/src/split.c b/src/split.c index b0d6ff1..7db350a 100644 --- a/src/split.c +++ b/src/split.c @@ -85,14 +85,20 @@ cleanup_frame (rp_window_frame *frame) rp_window * set_frames_window (rp_window_frame *frame, rp_window *win) { - rp_window *last_win; + int last_win; - last_win = frame->win; - frame->win = win; + last_win = frame->win_number; if (win) - win->frame = frame; + { + frame->win_number = win->number; + win->frame_number = frame->number; + } + else + { + frame->win_number = EMPTY; + } - return last_win; + return find_window_number (last_win); } static screen_info * @@ -120,7 +126,7 @@ maximize_all_windows_in_frame (rp_window_frame *frame) list_for_each_entry (win, &rp_mapped_window, node) { - if (win->frame == frame) + if (win->frame_number == frame->number) { maximize (win); } @@ -136,22 +142,24 @@ maximize_frame (rp_window_frame *frame) frame->x = defaults.padding_left; frame->y = defaults.padding_top; - frame->width = DisplayWidth (dpy, s->screen_num) - defaults.padding_right - defaults.padding_left; - frame->height = DisplayHeight (dpy, s->screen_num) - defaults.padding_bottom - defaults.padding_top; + frame->width = screen_width (s); + frame->height = screen_height (s); } /* Create a full screen frame */ static void create_initial_frame (screen_info *screen) { - screen->rp_current_frame = frame_new (screen); + rp_window_frame *frame; - list_add_tail (&screen->rp_current_frame->node, &screen->rp_window_frames); + frame = frame_new (screen); + screen->current_frame = frame->number; + list_add_tail (&frame->node, &screen->rp_window_frames); - update_last_access (screen->rp_current_frame); + update_last_access (frame); - maximize_frame (screen->rp_current_frame); - set_frames_window (screen->rp_current_frame, NULL); + maximize_frame (frame); + set_frames_window (frame, NULL); } void @@ -179,7 +187,7 @@ find_last_frame (screen_info *s) list_for_each_entry (cur, &s->rp_window_frames, node) { - if (cur != s->rp_current_frame + if (cur->number != s->current_frame && cur->last_access > last_access) { last_access = cur->last_access; @@ -201,7 +209,7 @@ find_windows_frame (rp_window *win) list_for_each_entry (cur, &s->rp_window_frames, node) { - if (cur->win == win) return cur; + if (cur->win_number == win->number) return cur; } return NULL; @@ -224,7 +232,8 @@ find_frame_prev (rp_window_frame *frame) rp_window * current_window () { - return screens[rp_current_screen].rp_current_frame->win; + return find_window_number (screen_get_frame (&screens[rp_current_screen], + screens[rp_current_screen].current_frame)->win_number); } static int @@ -262,7 +271,7 @@ find_window_for_frame (rp_window_frame *frame) && !find_windows_frame (cur) && cur->last_access >= last_access && window_fits_in_frame (cur, frame) - && !cur->frame) + && cur->frame_number == EMPTY) { most_recent = cur; last_access = cur->last_access; @@ -286,14 +295,8 @@ split_frame (rp_window_frame *frame, int way, int pixels) /* Make our new frame. */ new_frame = frame_new (s); - /* It seems intuitive to make the last frame the newly created - frame. */ - update_last_access (new_frame); - - /* TODO: don't put the new frame at the end of the list, put it - after the existing frame. Then cycling frames cycles in the order - they were created. */ - list_add (&new_frame->node, &s->rp_current_frame->node); + /* Add the frame to the frameset. */ + list_add (&new_frame->node, &(screen_get_frame (s, s->current_frame)->node)); set_frames_window (new_frame, NULL); @@ -335,10 +338,10 @@ split_frame (rp_window_frame *frame, int way, int pixels) } /* resize the existing frame */ - if (frame->win) + if (frame->win_number != EMPTY) { maximize_all_windows_in_frame (frame); - XRaiseWindow (dpy, frame->win->w); + XRaiseWindow (dpy, find_window_number (frame->win_number)->w); } show_frame_indicator(); @@ -371,14 +374,14 @@ remove_all_splits () /* Hide all the windows not in the current frame. */ list_for_each_entry (win, &rp_mapped_window, node) { - if (win->frame != s->rp_current_frame) + if (win->frame_number != s->current_frame) hide_window (win); } /* Delete all the frames except the current one. */ list_for_each_safe_entry (frame, iter, tmp, &s->rp_window_frames, node) { - if (frame != s->rp_current_frame) + if (frame->number != s->current_frame) { list_del (&frame->node); frame_free (s, frame); @@ -386,30 +389,35 @@ remove_all_splits () } /* Maximize the frame and the windows in the frame. */ - maximize_frame (s->rp_current_frame); - maximize_all_windows_in_frame (s->rp_current_frame); + maximize_frame (screen_get_frame (s, s->current_frame)); + maximize_all_windows_in_frame (screen_get_frame (s, s->current_frame)); } /* Shrink the size of the frame to fit it's current window. */ void resize_shrink_to_window (rp_window_frame *frame) { - if (frame->win == NULL) return; + rp_window *win; + + if (frame->win_number == EMPTY) return; - resize_frame_horizontally (frame, frame->win->width + frame->win->border*2 - frame->width); - resize_frame_vertically (frame, frame->win->height + frame->win->border*2 - frame->height); + win = find_window_number (frame->win_number); + + resize_frame_horizontally (frame, win->width + win->border*2 - frame->width); + resize_frame_vertically (frame, win->height + win->border*2 - frame->height); } /* resize_frame is a generic frame resizer that can resize vertically, horizontally, to the right, to the left, etc. It all depends on the - functions passed to it. */ -static void + functions passed to it. Returns -1 if the resize failed, 0 for + success. */ +static int resize_frame (rp_window_frame *frame, rp_window_frame *pusher, int diff, int (*c1)(rp_window_frame *), int (c2)(rp_window_frame *), int (*c3)(rp_window_frame *), int (c4)(rp_window_frame *), void (*resize1)(rp_window_frame *, int), void (*resize2)(rp_window_frame *, int), - void (*resize3)(rp_window_frame *, rp_window_frame *, int)) + int (*resize3)(rp_window_frame *, rp_window_frame *, int)) { screen_info *s = frames_screen (frame); rp_window_frame *cur; @@ -423,6 +431,10 @@ resize_frame (rp_window_frame *frame, rp_window_frame *pusher, int diff, moved then this frame is affected by the resize. */ if ((*c1)(cur) == (*c3)(frame)) { + /* If the frame can't get any smaller, then fail. */ + if (diff > 0 + && abs ((*c3)(cur) - (*c1)(cur)) - diff <= defaults.window_border_width * 2) + return -1; /* Test for this circumstance: --+ | |+-+ @@ -451,7 +463,9 @@ resize_frame (rp_window_frame *frame, rp_window_frame *pusher, int diff, || ((*c4)(cur) > (*c2)(frame) && (*c4)(cur) <= (*c4)(frame))) { - resize3 (cur, frame, -diff); + /* Attempt to resize cur. */ + if (resize3 (cur, frame, -diff) == -1) + return -1; } } } @@ -459,47 +473,49 @@ resize_frame (rp_window_frame *frame, rp_window_frame *pusher, int diff, /* Finally, resize the frame and the windows inside. */ (*resize1) (frame, diff); maximize_all_windows_in_frame (frame); + + return 0; } -static void resize_frame_bottom (rp_window_frame *frame, rp_window_frame *pusher, int diff); -static void resize_frame_top (rp_window_frame *frame, rp_window_frame *pusher, int diff); -static void resize_frame_left (rp_window_frame *frame, rp_window_frame *pusher, int diff); -static void resize_frame_right (rp_window_frame *frame, rp_window_frame *pusher, int diff); +static int resize_frame_bottom (rp_window_frame *frame, rp_window_frame *pusher, int diff); +static int resize_frame_top (rp_window_frame *frame, rp_window_frame *pusher, int diff); +static int resize_frame_left (rp_window_frame *frame, rp_window_frame *pusher, int diff); +static int resize_frame_right (rp_window_frame *frame, rp_window_frame *pusher, int diff); /* Resize frame by moving it's right side. */ -static void +static int resize_frame_right (rp_window_frame *frame, rp_window_frame *pusher, int diff) { - resize_frame (frame, pusher, diff, - frame_left, frame_top, frame_right, frame_bottom, - frame_resize_right, frame_resize_left, resize_frame_left); + return resize_frame (frame, pusher, diff, + frame_left, frame_top, frame_right, frame_bottom, + frame_resize_right, frame_resize_left, resize_frame_left); } /* Resize frame by moving it's left side. */ -static void +static int resize_frame_left (rp_window_frame *frame, rp_window_frame *pusher, int diff) { - resize_frame (frame, pusher, diff, - frame_right, frame_top, frame_left, frame_bottom, - frame_resize_left, frame_resize_right, resize_frame_right); + return resize_frame (frame, pusher, diff, + frame_right, frame_top, frame_left, frame_bottom, + frame_resize_left, frame_resize_right, resize_frame_right); } /* Resize frame by moving it's top side. */ -static void +static int resize_frame_top (rp_window_frame *frame, rp_window_frame *pusher, int diff) { - resize_frame (frame, pusher, diff, - frame_bottom, frame_left, frame_top, frame_right, - frame_resize_up, frame_resize_down, resize_frame_bottom); + return resize_frame (frame, pusher, diff, + frame_bottom, frame_left, frame_top, frame_right, + frame_resize_up, frame_resize_down, resize_frame_bottom); } /* Resize frame by moving it's bottom side. */ -static void +static int resize_frame_bottom (rp_window_frame *frame, rp_window_frame *pusher, int diff) { - resize_frame (frame, pusher, diff, - frame_top, frame_left, frame_bottom, frame_right, - frame_resize_down, frame_resize_up, resize_frame_top); + return resize_frame (frame, pusher, diff, + frame_top, frame_left, frame_bottom, frame_right, + frame_resize_down, frame_resize_up, resize_frame_top); } /* Resize frame diff pixels by expanding it to the right. If the frame @@ -507,19 +523,45 @@ resize_frame_bottom (rp_window_frame *frame, rp_window_frame *pusher, int diff) void resize_frame_horizontally (rp_window_frame *frame, int diff) { + int (*resize_fn)(rp_window_frame *, rp_window_frame*, int); + struct list_head *l; screen_info *s = frames_screen (frame); if (num_frames (s) < 2 || diff == 0) return; - if (frame_right (frame) < DisplayWidth (dpy, s->screen_num) - defaults.padding_right - defaults.padding_left) + if (frame_width (frame) + diff <= defaults.window_border_width * 2) + return; + + /* Find out which resize function to use. */ + if (frame_right (frame) < screen_right (s)) + { + resize_fn = resize_frame_right; + } + else if (frame_left (frame) > screen_left (s)) + { + resize_fn = resize_frame_left; + } + else + { + return; + } + + /* Copy the frameset. If the resize fails, then we restore the + original one. */ + l = screen_copy_frameset (s); + + if ((*resize_fn) (frame, NULL, diff) == -1) { - resize_frame_right (frame, NULL, diff); + screen_restore_frameset (s, l); } - else if (frame_left (frame) > defaults.padding_left) + else { - resize_frame_left (frame, NULL, diff); + frameset_free (l); } + + /* It's our responsibility to free this. */ + free (l); } /* Resize frame diff pixels by expanding it down. If the frame is @@ -527,19 +569,45 @@ resize_frame_horizontally (rp_window_frame *frame, int diff) void resize_frame_vertically (rp_window_frame *frame, int diff) { + int (*resize_fn)(rp_window_frame *, rp_window_frame*, int); + struct list_head *l; screen_info *s = frames_screen (frame); if (num_frames (s) < 2 || diff == 0) return; - if (frame_bottom (frame) < DisplayHeight (dpy, s->screen_num) - defaults.padding_bottom - defaults.padding_top) + if (frame_height (frame) + diff <= defaults.window_border_width * 2) + return; + + /* Find out which resize function to use. */ + if (frame_bottom (frame) < screen_bottom (s)) + { + resize_fn = resize_frame_bottom; + } + else if (frame_top (frame) > screen_top (s)) + { + resize_fn = resize_frame_top; + } + else + { + return; + } + + /* Copy the frameset. If the resize fails, then we restore the + original one. */ + l = screen_copy_frameset (s); + + if ((*resize_fn) (frame, NULL, diff) == -1) { - resize_frame_bottom (frame, NULL, diff); + screen_restore_frameset (s, l); } - else if (frame_top (frame) > defaults.padding_top) + else { - resize_frame_top (frame, NULL, diff); + frameset_free (l); } + + /* It's our responsibility to free this. */ + free (l); } static int @@ -623,6 +691,7 @@ remove_frame (rp_window_frame *frame) screen_info *s; int area; rp_window_frame *cur; + rp_window *win; if (frame == NULL) return; @@ -632,22 +701,23 @@ remove_frame (rp_window_frame *frame) PRINT_DEBUG (("Total Area: %d\n", area)); list_del (&frame->node); - hide_window (frame->win); - hide_others (frame->win); + win = find_window_number (frame->win_number); + hide_window (win); + hide_others (win); list_for_each_entry (cur, &s->rp_window_frames, node) { rp_window_frame tmp_frame; int fits = 0; - if (cur->win) - { - PRINT_DEBUG (("Trying frame containing window '%s'\n", window_name (cur->win))); - } - else - { - PRINT_DEBUG (("Trying some empty frame\n")); - } +/* if (cur->win_number != EMPTY) */ +/* { */ +/* PRINT_DEBUG (("Trying frame containing window '%s'\n", window_name (cur->win))); */ +/* } */ +/* else */ +/* { */ +/* PRINT_DEBUG (("Trying some empty frame\n")); */ +/* } */ /* Backup the frame */ memcpy (&tmp_frame, cur, sizeof (rp_window_frame)); @@ -716,10 +786,11 @@ remove_frame (rp_window_frame *frame) /* The current frame fits into the new space so keep its new frame parameters and maximize the window to fit the new frame size. */ - if (cur->win) + if (cur->win_number != EMPTY) { + win = find_window_number (cur->win_number); maximize_all_windows_in_frame (cur); - XRaiseWindow (dpy, cur->win->w); + XRaiseWindow (dpy, win->w); } } else @@ -738,18 +809,23 @@ set_active_frame (rp_window_frame *frame) { screen_info *old_s = current_screen(); screen_info *s = frames_screen (frame); - rp_window_frame *old = current_screen()->rp_current_frame; + int old = current_screen()->current_frame; + rp_window *win, *old_win; + + win = find_window_number (frame->win_number); + old_win = find_window_number (screen_get_frame (current_screen(), + current_screen()->current_frame)->win_number); /* Make the switch */ - give_window_focus (frame->win, old->win); + give_window_focus (win, old_win); update_last_access (frame); - s->rp_current_frame = frame; + s->current_frame = frame->number; /* If frame->win == NULL, then rp_current_screen is not updated. */ rp_current_screen = s->screen_num; /* Possibly show the frame indicator. */ - if ((old != s->rp_current_frame && num_frames(s) > 1) + if ((old != s->current_frame && num_frames(s) > 1) || s != old_s) { show_frame_indicator(); @@ -757,7 +833,7 @@ set_active_frame (rp_window_frame *frame) /* If the frame has no window to give focus to, give the key window focus. */ - if( !frame->win ) + if(frame->win_number == EMPTY) { XSetInputFocus (dpy, s->key_window, RevertToPointerRoot, CurrentTime); @@ -767,10 +843,13 @@ set_active_frame (rp_window_frame *frame) void blank_frame (rp_window_frame *frame) { - if (frame->win == NULL) return; + rp_window *win; + + if (frame->win_number == EMPTY) return; - hide_window (frame->win); - hide_others (frame->win); + win = find_window_number (frame->number); + hide_window (win); + hide_others (win); set_frames_window (frame, NULL); @@ -797,18 +876,19 @@ show_frame_message (char *msg) { screen_info *s = current_screen (); int width, height; + rp_window_frame *frame; + + frame = screen_get_frame (s, s->current_frame); width = defaults.bar_x_padding * 2 + XTextWidth (defaults.font, msg, strlen (msg)); height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2); - XMoveResizeWindow (dpy, current_screen()->frame_window, - current_screen()->rp_current_frame->x - + current_screen()->rp_current_frame->width / 2 - width / 2, - current_screen()->rp_current_frame->y - + current_screen()->rp_current_frame->height / 2 - height / 2, + XMoveResizeWindow (dpy, s->frame_window, + frame->x + frame->width / 2 - width / 2, + frame->y + frame->height / 2 - height / 2, width, height); - XMapRaised (dpy, current_screen()->frame_window); + XMapRaised (dpy, s->frame_window); XClearWindow (dpy, s->frame_window); XSync (dpy, False); diff --git a/src/window.c b/src/window.c index 87ad967..a3042ab 100644 --- a/src/window.c +++ b/src/window.c @@ -178,7 +178,10 @@ find_window (Window w) void set_current_window (rp_window *win) { - set_frames_window (current_screen()->rp_current_frame, win); + rp_window_frame *frame; + + frame = screen_get_frame (current_screen(), current_screen()->current_frame); + set_frames_window (frame, win); } rp_window * @@ -475,10 +478,12 @@ void set_active_window (rp_window *win) { rp_window *last_win; + rp_window_frame *frame; if (win == NULL) return; - last_win = set_frames_window (win->scr->rp_current_frame, win); + frame = screen_get_frame (win->scr, win->scr->current_frame); + last_win = set_frames_window (frame, win); if (last_win) PRINT_DEBUG (("last window: %s\n", window_name (last_win))); PRINT_DEBUG (("new window: %s\n", window_name (win))); @@ -683,3 +688,12 @@ free_window_stuff () { numset_free (rp_window_numset); } + +rp_window_frame * +win_get_frame (rp_window *win) +{ + if (win->frame_number != EMPTY) + return screen_get_frame (win->scr, win->frame_number); + else + return NULL; +} diff --git a/src/window.h b/src/window.h index f15c26b..1ecf16b 100644 --- a/src/window.h +++ b/src/window.h @@ -63,4 +63,6 @@ void get_window_list (char *fmt, char *delim, struct sbuf *buffer, void init_window_stuff (); void free_window_stuff (); +rp_window_frame *win_get_frame (rp_window *win); + #endif /* ! _RATPOISON_LIST_H */ -- cgit v1.2.3