diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/actions.c | 95 | ||||
-rw-r--r-- | src/actions.h | 3 | ||||
-rw-r--r-- | src/conf.h | 24 | ||||
-rw-r--r-- | src/data.h | 1 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/split.c | 254 | ||||
-rw-r--r-- | src/split.h | 4 |
7 files changed, 366 insertions, 16 deletions
diff --git a/src/actions.c b/src/actions.c index 623ca40..17a1db2 100644 --- a/src/actions.c +++ b/src/actions.c @@ -88,6 +88,8 @@ static user_command user_commands[] = {"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}, /*@end (tag required for genrpbindings) */ /* Commands to set default behavior. */ @@ -107,6 +109,7 @@ static user_command user_commands[] = {"deffgcolor", cmd_deffgcolor, arg_STRING}, {"defbgcolor", cmd_defbgcolor, arg_STRING}, {"defbarpadding", cmd_defbarpadding, arg_STRING}, + {"defresizeunit", cmd_defresizeunit, arg_STRING}, /* Commands to help debug ratpoison. */ #ifdef DEBUG @@ -1356,6 +1359,98 @@ cmd_remove (int interactive, void *data) return NULL; } +char * +cmd_shrink (int interactive, void *data) +{ + screen_info *s = current_screen (); + + resize_shrink_to_window (s->rp_current_frame); + return NULL; +} + +char * +cmd_resize (int interactive, void *data) +{ + screen_info *s = current_screen (); + + /* If the user calls resize with arguments, treat it like the + non-interactive version. */ + if (interactive && data == NULL) + { + int nbytes, revert; + char buffer[513]; + unsigned int mod; + KeySym c; + Window fwin; + + /* If we haven't got at least 2 frames, there isn't anything to + scale. */ + if (num_frames (s) < 2) return NULL; + + XGetInputFocus (dpy, &fwin, &revert); + XSetInputFocus (dpy, s->key_window, RevertToPointerRoot, CurrentTime); + + nbytes = read_key (&c, &mod, buffer, sizeof (buffer)); + while (1) + { + if (c == RESIZE_VGROW_KEY && mod == RESIZE_VGROW_MODIFIER) + resize_frame_vertically (s->rp_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); + else if (c == RESIZE_HGROW_KEY && mod == RESIZE_HGROW_MODIFIER) + resize_frame_horizontally (s->rp_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); + else if (c == RESIZE_SHRINK_TO_WINDOW_KEY + && mod == RESIZE_SHRINK_TO_WINDOW_MODIFIER) + resize_shrink_to_window (s->rp_current_frame); + else if (c == RESIZE_END_KEY && mod == RESIZE_END_MODIFIER) + break; + + nbytes = read_key (&c, &mod, buffer, sizeof (buffer)); + } + + XSetInputFocus (dpy, fwin, RevertToPointerRoot, CurrentTime); + } + else + { + int xdelta, ydelta; + + if (sscanf (data, "%d %d", &xdelta, &ydelta) < 2) + { + message (" resize: Two numeric arguments required "); + return NULL; + } + + resize_frame_horizontally (s->rp_current_frame, xdelta); + resize_frame_vertically (s->rp_current_frame, ydelta); + } + + return NULL; +} + +char * +cmd_defresizeunit (int interactive, void *data) +{ + int tmp; + + if (data == NULL && !interactive) + return xsprintf ("%d", defaults.frame_resize_unit); + + if (data == NULL || sscanf (data, "%d", &tmp) < 1) + { + message (" defresizeunit: One argument required "); + return NULL; + } + + if (tmp >= 0) + defaults.frame_resize_unit = tmp; + else + message (" defresizeunit: Bad argument "); + + return NULL; +} + /* banish the rat pointer */ char * cmd_banish (int interactive, void *data) diff --git a/src/actions.h b/src/actions.h index 397e0f4..3446f12 100644 --- a/src/actions.h +++ b/src/actions.h @@ -68,6 +68,8 @@ char * cmd_h_split (int interactive, void *data); char * cmd_v_split (int interactive, void *data); char * cmd_only (int interactive, void *data); char * cmd_remove (int interactive, void *data); +char * cmd_shrink (int interactive, void *data); +char * cmd_resize (int interactive, void *data); char * cmd_banish (int interactive, void *data); char * cmd_curframe (int interactive, void *data); char * cmd_help (int interactive, void *data); @@ -90,6 +92,7 @@ char * cmd_defwinfmt (int interactive, void *data); char * cmd_defwinname (int interactive, void *data); char * cmd_deffgcolor (int interactive, void *data); char * cmd_defbgcolor (int interactive, void *data); +char * cmd_defresizeunit (int interactive, void *data); char * cmd_setenv (int interactive, void *data); char * cmd_getenv (int interactive, void *data); char * cmd_chdir (int interactive, void *data); @@ -40,6 +40,30 @@ #define INPUT_NEXT_HISTORY_KEY XK_n #define INPUT_NEXT_HISTORY_MODIFIER ControlMask +/* Key used to enlarge frame vertically when in resize mode. */ +#define RESIZE_VGROW_KEY XK_n +#define RESIZE_VGROW_MODIFIER ControlMask + +/* Key used to shrink frame vertically when in resize mode. */ +#define RESIZE_VSHRINK_KEY XK_p +#define RESIZE_VSHRINK_MODIFIER ControlMask + +/* Key used to enlarge frame horizontally when in resize mode. */ +#define RESIZE_HGROW_KEY XK_f +#define RESIZE_HGROW_MODIFIER ControlMask + +/* Key used to shrink frame horizontally when in resize mode. */ +#define RESIZE_HSHRINK_KEY XK_b +#define RESIZE_HSHRINK_MODIFIER ControlMask + +/* Key used to shrink frame to fit it's current window. */ +#define RESIZE_SHRINK_TO_WINDOW_KEY XK_s +#define RESIZE_SHRINK_TO_WINDOW_MODIFIER 0 + +/* Key used to exit resize mode. */ +#define RESIZE_END_KEY XK_Return +#define RESIZE_END_MODIFIER 0 + /* Number of history items to store. */ #define INPUT_MAX_HISTORY 50 @@ -144,6 +144,7 @@ struct rp_defaults int bar_border_width; int frame_indicator_timeout; + int frame_resize_unit; int padding_left; int padding_right; @@ -460,6 +460,7 @@ init_defaults () defaults.bar_border_width = 1; defaults.frame_indicator_timeout = 1; + defaults.frame_resize_unit = 10; defaults.padding_left = 0; defaults.padding_right = 0; diff --git a/src/split.c b/src/split.c index b364868..53b596b 100644 --- a/src/split.c +++ b/src/split.c @@ -38,6 +38,22 @@ update_last_access (rp_window_frame *frame) counter++; } +int +num_frames (screen_info *s) +{ + int count = 0; + rp_window_frame *cur; + + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + count++; + } + + return count; +} + rp_window * set_frames_window (rp_window_frame *frame, rp_window *win) { @@ -405,6 +421,228 @@ remove_all_splits () set_frames_window (s->rp_current_frame, cur_window); } +/* 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; + + 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); +} + +/* Resize FRAME vertically by diff pixels. if diff is negative + then shrink the frame, otherwise enlarge it. */ +void +resize_frame_vertically (rp_window_frame *frame, int diff) +{ + screen_info *s = frames_screen (frame); + int found_adjacent_frames = 0; + int max_bound, min_bound; + int orig_y; + rp_window_frame *cur; + + if (num_frames (s) < 2 || diff == 0) + return; + + max_bound = frame->x + frame->width; + min_bound = frame->x; + orig_y = frame->y; + + /* Look for frames below that needs to be resized. */ + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->y == (frame->y + frame->height) + && (cur->x + cur->width) > frame->x + && cur->x < (frame->x + frame->width)) + { + cur->height -= diff; + cur->y += diff; + + if ((cur->x + cur->width) > max_bound) + max_bound = cur->x + cur->width; + + if (cur->x < min_bound) + min_bound = cur->x; + + if (cur->win) + maximize_all_windows_in_frame (cur); + + found_adjacent_frames = 1; + } + } + + /* Found no frames below, look for some above. */ + if (!found_adjacent_frames) + { + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->y == (frame->y - cur->height) + && (cur->x + cur->width) > frame->x + && cur->x < (frame->x + frame->width)) + { + cur->height -= diff; + + if ((cur->x + cur->width) > max_bound) + max_bound = cur->x + cur->width; + + if (cur->x < min_bound) + min_bound = cur->x; + + if (cur->win) + maximize_all_windows_in_frame (cur); + + found_adjacent_frames = 1; + } + } + + /* If we found any frames, move the current frame. */ + if (found_adjacent_frames) + { + frame->y -= diff; + } + } + + /* Resize current frame. */ + if (found_adjacent_frames) + { + frame->height += diff; + + /* If we left any gaps, take care of them too. */ + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->y == orig_y && cur->x >= min_bound + && cur->x + cur->width <= max_bound + && cur != frame) + { + cur->height = frame->height; + cur->y = frame->y; + + if (cur->win) + maximize_all_windows_in_frame (cur); + } + } + + if (frame->win) + { + maximize_all_windows_in_frame (frame); + XRaiseWindow (dpy, frame->win->w); + } + } +} + +/* Resize FRAME horizontally by diff pixels. if diff is negative + then shrink the frame, otherwise enlarge it. */ +void +resize_frame_horizontally (rp_window_frame *frame, int diff) +{ + screen_info *s = frames_screen (frame); + int found_adjacent_frames = 0; + int max_bound, min_bound; + int orig_x; + rp_window_frame *cur; + + if (num_frames (s) < 2 || diff == 0) + return; + + max_bound = frame->y + frame->height; + min_bound = frame->y; + orig_x = frame->x; + + /* Look for frames on the right that needs to be resized. */ + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->x == (frame->x + frame->width) + && (cur->y + cur->height) > frame->y + && cur->y < (frame->y + frame->height)) + { + cur->width -= diff; + cur->x += diff; + + if ((cur->y + cur->height) > max_bound) + max_bound = cur->y + cur->height; + + if (cur->y < min_bound) + min_bound = cur->y; + + if (cur->win) + maximize_all_windows_in_frame (cur); + + found_adjacent_frames = 1; + } + } + + /* Found no frames to the right, look for some to the left. */ + if (!found_adjacent_frames) + { + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->x == (frame->x - cur->width) + && (cur->y + cur->height) > frame->y + && cur->y < (frame->y + frame->height)) + { + cur->width -= diff; + + if ((cur->y + cur->height) > max_bound) + max_bound = cur->y + cur->height; + + if (cur->y < min_bound) + min_bound = cur->y; + + if (cur->win) + maximize_all_windows_in_frame (cur); + + found_adjacent_frames = 1; + } + } + + /* If we found any frames, move the current frame. */ + if (found_adjacent_frames) + { + frame->x -= diff; + } + } + + /* Resize current frame. */ + if (found_adjacent_frames) + { + frame->width += diff; + + /* If we left any gaps, take care of them too. */ + for (cur = s->rp_window_frame_sentinel->next; + cur != s->rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->x == orig_x && cur->y >= min_bound + && cur->y + cur->height <= max_bound + && cur != frame) + { + cur->width = frame->width; + cur->x = frame->x; + + if (cur->win) + maximize_all_windows_in_frame (cur); + } + } + + if (frame->win) + { + maximize_all_windows_in_frame (frame); + XRaiseWindow (dpy, frame->win->w); + } + } +} + static int frame_is_below (rp_window_frame *src, rp_window_frame *frame) { @@ -449,22 +687,6 @@ total_frame_area (screen_info *s) return area; } -static int -num_frames (screen_info *s) -{ - int count = 0; - rp_window_frame *cur; - - for (cur = s->rp_window_frame_sentinel->next; - cur != s->rp_window_frame_sentinel; - cur = cur->next) - { - count++; - } - - return count; -} - /* Return 1 if frames f1 and f2 overlap */ static int frames_overlap (rp_window_frame *f1, rp_window_frame *f2) diff --git a/src/split.h b/src/split.h index 7879329..fe2d853 100644 --- a/src/split.h +++ b/src/split.h @@ -22,11 +22,15 @@ #ifndef SPLIT_H #define SPLIT_H +int num_frames (screen_info *s); rp_window *set_frames_window (rp_window_frame *frame, rp_window *win); void maximize_all_windows_in_frame (rp_window_frame *frame); void h_split_frame (rp_window_frame *frame, int pixels); void v_split_frame (rp_window_frame *frame, int pixels); void remove_all_splits (); +void resize_shrink_to_window (rp_window_frame *frame); +void resize_frame_horizontally (rp_window_frame *frame, int steps); +void resize_frame_vertically (rp_window_frame *frame, int steps); void remove_frame (rp_window_frame *frame); rp_window *find_window_for_frame (rp_window_frame *frame); rp_window_frame *find_windows_frame (rp_window *win); |