diff options
Diffstat (limited to 'src/split.c')
-rw-r--r-- | src/split.c | 420 |
1 files changed, 265 insertions, 155 deletions
diff --git a/src/split.c b/src/split.c index d79903b..5c00572 100644 --- a/src/split.c +++ b/src/split.c @@ -23,6 +23,111 @@ #include "ratpoison.h" +rp_window_frame *rp_window_frame_sentinel; +rp_window_frame *rp_current_frame; + +static void +delete_frame_from_list (rp_window_frame *frame) +{ + frame->next->prev = frame->prev; + frame->prev->next = frame->next; +} + +/* Create a full screen frame */ +static void +create_initial_frame () +{ + screen_info *s; + + s = current_screen(); + rp_current_frame = xmalloc (sizeof (rp_window_frame)); + + rp_current_frame = xmalloc (sizeof (rp_window_frame)); + rp_current_frame->x = PADDING_LEFT; + rp_current_frame->y = PADDING_TOP; + + /* FIXME: what about multiple screens? */ + rp_current_frame->width = DisplayWidth (dpy, 0) - PADDING_RIGHT - PADDING_LEFT; + rp_current_frame->height = DisplayHeight (dpy, 0) - PADDING_BOTTOM - PADDING_TOP; + + rp_window_frame_sentinel->next = rp_current_frame; + rp_window_frame_sentinel->prev = rp_current_frame; + rp_current_frame->next = rp_window_frame_sentinel; + rp_current_frame->prev = rp_window_frame_sentinel; + + rp_current_frame->win = NULL; +} + +void +init_frame_list () +{ + rp_window_frame_sentinel = xmalloc (sizeof (rp_window_frame)); + + rp_window_frame_sentinel->next = rp_window_frame_sentinel; + rp_window_frame_sentinel->prev = rp_window_frame_sentinel; + + create_initial_frame(); +} + +/* Return the frame that contains the window. */ +rp_window_frame * +find_windows_frame (rp_window *win) +{ + rp_window_frame *cur; + + for (cur = rp_window_frame_sentinel->next; + cur != rp_window_frame_sentinel; + cur = cur->next) + { + if (cur->win == win) return cur; + } + + return NULL; +} + +rp_window_frame * +find_frame_next (rp_window_frame *frame) +{ + rp_window_frame *cur; + + if (frame == NULL) return NULL; + + cur = frame; + if (cur->next == rp_window_frame_sentinel) + { + cur = cur->next; + if (cur->next == frame) return NULL; + } + + return cur->next; +} + +rp_window_frame * +find_frame_prev (rp_window_frame *frame) +{ + rp_window_frame *cur; + + if (frame == NULL) return NULL; + + cur = frame; + if (cur->prev == rp_window_frame_sentinel) + { + cur = cur->prev; + if (cur->prev == frame) return NULL; + } + + return cur->prev; +} + +rp_window * +current_window () +{ + if (rp_current_frame) return rp_current_frame->win; + + PRINT_ERROR ("BUG: There should always be a current frame\n"); + return NULL; +} + static int window_fits_in_frame (rp_window *win, rp_window_frame *frame) { @@ -54,8 +159,8 @@ find_window_for_frame (rp_window_frame *frame) cur != rp_mapped_window_sentinel; cur = cur->next) { - if (cur != rp_current_window - && !cur->frame + if (cur != current_window() + && !find_windows_frame (cur) && cur->last_access >= last_access && window_fits_in_frame (cur, frame)) { @@ -67,109 +172,110 @@ find_window_for_frame (rp_window_frame *frame) return most_recent; } -/* Splits the window in 2. if way is != 0 then split it horizontally - otherwise split it vertically. */ -static int -split_window (rp_window *win, int way) +static void +update_frame_indicator () +{ + XMoveWindow (dpy, current_screen()->frame_window, + rp_current_frame->x + rp_current_frame->width / 2 - 5, + rp_current_frame->y + rp_current_frame->height / 2 - 5); +} + +/* Splits the frame in 2. if way is 0 then split vertically otherwise + split it horizontally. */ +static void +split_frame (rp_window_frame *frame, int way) { - rp_window *other_window; - rp_window_frame *frame1, *frame2; + rp_window *win; + rp_window_frame *new_frame; - frame1 = xmalloc (sizeof (rp_window_frame)); - frame2 = xmalloc (sizeof (rp_window_frame)); + /* You can't split a frame unless it has a window in it. */ + if (!frame->win) return; - if (!win->frame) - { - frame1->x = PADDING_LEFT; - frame1->y = PADDING_TOP; - frame1->width = win->scr->root_attr.width - - PADDING_RIGHT - PADDING_LEFT; - frame1->height = win->scr->root_attr.height - - PADDING_BOTTOM - PADDING_TOP; - } - else - { - frame1->x = win->frame->x; - frame1->y = win->frame->y; - frame1->width = win->frame->width; - frame1->height = win->frame->height; - } + new_frame = xmalloc (sizeof (rp_window_frame)); + + /* append the new frame to the list */ + new_frame->prev = rp_window_frame_sentinel->prev; + rp_window_frame_sentinel->prev->next = new_frame; + rp_window_frame_sentinel->prev = new_frame; + new_frame->next = rp_window_frame_sentinel; if (way) { - frame2->x = frame1->x; - frame2->y = frame1->y + frame1->height / 2; - frame2->width = frame1->width; - frame2->height = frame1->height / 2 + frame1->height % 2; + new_frame->x = frame->x; + new_frame->y = frame->y + frame->height / 2; + new_frame->width = frame->width; + new_frame->height = frame->height / 2 + frame->height % 2; - frame1->height /= 2; + frame->height /= 2; } else { - frame2->x = frame1->x + frame1->width / 2; - frame2->y = frame1->y; - frame2->width = frame1->width / 2 + frame1->width % 2; - frame2->height = frame1->height; + new_frame->x = frame->x + frame->width / 2; + new_frame->y = frame->y; + new_frame->width = frame->width / 2 + frame->width % 2; + new_frame->height = frame->height; - frame1->width /= 2; + frame->width /= 2; } - - other_window = find_window_for_frame (frame2); - if (other_window) + + win = find_window_for_frame (new_frame); + if (win) { - PRINT_DEBUG ("Split the window!\n"); + PRINT_DEBUG ("Found a window for the frame!\n"); - if (win->frame) free (win->frame); - win->frame = frame1; - other_window->frame = frame2; + new_frame->win = win; maximize (win); - maximize (other_window); - XRaiseWindow (dpy, other_window->w); XRaiseWindow (dpy, win->w); - - return 1; } else { - PRINT_DEBUG ("Failed to split.\n"); + PRINT_DEBUG ("No window fits the frame.\n"); - free (frame1); - free (frame2); - - return 0; + new_frame->win = NULL; } + + /* resize the existing frame */ + maximize (frame->win); + XRaiseWindow (dpy, frame->win->w); + + update_frame_indicator(); } /* Splits the window vertically in 2. */ -int -v_split_window (rp_window *win) +void +v_split_frame (rp_window_frame *frame) { - return split_window (win, 0); + split_frame (frame, 0); } /* Splits the window horizontally in 2. */ -int -h_split_window (rp_window *win) +void +h_split_frame (rp_window_frame *frame) { - return split_window (win, 1); + split_frame (frame, 1); } void -remove_all_frames () +remove_all_splits () { - rp_window *cur; + rp_window *cur_window; + rp_window_frame *cur; - for (cur = rp_mapped_window_sentinel->next; - cur != rp_mapped_window_sentinel; - cur = cur->next) + cur_window = current_window(); + + while (rp_window_frame_sentinel->next != rp_window_frame_sentinel) { - if (cur->frame) - { - free (cur->frame); - cur->frame = NULL; - } + cur = rp_window_frame_sentinel->next; + delete_frame_from_list (cur); + free (cur); } + + create_initial_frame (); + rp_current_frame->win = cur_window; + + maximize (cur_window); + XRaiseWindow (dpy, cur_window->w); } static int @@ -204,16 +310,13 @@ static int total_frame_area () { int area = 0; - rp_window *cur; + rp_window_frame *cur; - for (cur = rp_mapped_window_sentinel->next; - cur != rp_mapped_window_sentinel; + for (cur = rp_window_frame_sentinel->next; + cur != rp_window_frame_sentinel; cur = cur->next) { - if (cur->frame) - { - area += cur->frame->width * cur->frame->height; - } + area += cur->width * cur->height; } return area; @@ -223,16 +326,13 @@ static int num_frames () { int count = 0; - rp_window *cur; + rp_window_frame *cur; - for (cur = rp_mapped_window_sentinel->next; - cur != rp_mapped_window_sentinel; + for (cur = rp_window_frame_sentinel->next; + cur != rp_window_frame_sentinel; cur = cur->next) { - if (cur->frame) - { - count++; - } + count++; } return count; @@ -254,17 +354,15 @@ frames_overlap (rp_window_frame *f1, rp_window_frame *f2) /* Return 1 if w's frame overlaps any other window's frame */ static int -frame_overlaps (rp_window *w) +frame_overlaps (rp_window_frame *frame) { - rp_window *cur; + rp_window_frame *cur; - for (cur = rp_mapped_window_sentinel->next; - cur != rp_mapped_window_sentinel; + for (cur = rp_window_frame_sentinel->next; + cur != rp_window_frame_sentinel; cur = cur->next) { - if (cur != w - && cur->frame - && frames_overlap (cur->frame, w->frame)) + if (cur != frame && frames_overlap (cur, frame)) { return 1; } @@ -273,105 +371,117 @@ frame_overlaps (rp_window *w) } void -remove_frame (rp_window *w) +remove_frame (rp_window_frame *frame) { int area; - rp_window *cur; - rp_window_frame *frame; + rp_window_frame *cur; - if (w->frame == NULL) return; + if (frame == NULL) return; area = total_frame_area(); PRINT_DEBUG ("Total Area: %d\n", area); - frame = w->frame; - w->frame = NULL; + delete_frame_from_list (frame); /* If there is 1 frame then we have no split screen, so get rid of the remaining window frame. */ if (num_frames() <= 1) { - remove_all_frames(); + remove_all_splits (); free (frame); return; } - for (cur = rp_mapped_window_sentinel->next; - cur != rp_mapped_window_sentinel; + for (cur = rp_window_frame_sentinel->next; + cur != rp_window_frame_sentinel; cur = cur->next) { - if (cur->frame) - { - rp_window_frame tmp_frame; - int fits = 0; + rp_window_frame tmp_frame; + int fits = 0; - /* Backup the frame */ - memcpy (&tmp_frame, cur->frame, sizeof (rp_window_frame)); + /* Backup the frame */ + memcpy (&tmp_frame, cur, sizeof (rp_window_frame)); - if (frame_is_below (frame, cur->frame) - || frame_is_above (frame, cur->frame)) - { - if (frame_is_below (frame, cur->frame)) - cur->frame->y = frame->y; - cur->frame->height += frame->height; - } + if (frame_is_below (frame, cur) + || frame_is_above (frame, cur)) + { + if (frame_is_below (frame, cur)) + cur->y = frame->y; + cur->height += frame->height; + } - PRINT_DEBUG ("New Total Area: %d\n", total_frame_area()); + PRINT_DEBUG ("New Total Area: %d\n", total_frame_area()); - if (total_frame_area() > area || frame_overlaps (cur)) - { - PRINT_DEBUG ("Didn't fit vertically\n"); + if (total_frame_area() > area || frame_overlaps (cur)) + { + PRINT_DEBUG ("Didn't fit vertically\n"); - /* Restore the current window's frame */ - memcpy (cur->frame, &tmp_frame, sizeof (rp_window_frame)); - } - else - { - PRINT_DEBUG ("It fit vertically!!\n"); + /* Restore the current window's frame */ + memcpy (cur, &tmp_frame, sizeof (rp_window_frame)); + } + else + { + PRINT_DEBUG ("It fit vertically!!\n"); - /* update the frame backup */ - memcpy (&tmp_frame, cur->frame, sizeof (rp_window_frame)); - fits = 1; - } + /* update the frame backup */ + memcpy (&tmp_frame, cur, sizeof (rp_window_frame)); + fits = 1; + } - if (frame_is_left (frame, cur->frame) - || frame_is_right (frame, cur->frame)) - { - if (frame_is_right (frame, cur->frame)) - cur->frame->x = frame->x; - cur->frame->width += frame->width; - } + if (frame_is_left (frame, cur) + || frame_is_right (frame, cur)) + { + if (frame_is_right (frame, cur)) + cur->x = frame->x; + cur->width += frame->width; + } - PRINT_DEBUG ("New Total Area: %d\n", total_frame_area()); + PRINT_DEBUG ("New Total Area: %d\n", total_frame_area()); - if (total_frame_area() > area || frame_overlaps (cur)) - { - PRINT_DEBUG ("Didn't fit horizontally\n"); + if (total_frame_area() > area || frame_overlaps (cur)) + { + PRINT_DEBUG ("Didn't fit horizontally\n"); - /* Restore the current window's frame */ - memcpy (cur->frame, &tmp_frame, sizeof (rp_window_frame)); - } - else - { - PRINT_DEBUG ("It fit horizontally!!\n"); - fits = 1; - } + /* Restore the current window's frame */ + memcpy (cur, &tmp_frame, sizeof (rp_window_frame)); + } + else + { + PRINT_DEBUG ("It fit horizontally!!\n"); + fits = 1; + } - if (fits) - { - /* The current frame fits into the new space so keep its - new frame parameters and maximize the window to fit - the new frame size. */ - maximize (cur); - XRaiseWindow (dpy, cur->w); - } - else + if (fits) + { + /* 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) { - memcpy (cur->frame, &tmp_frame, sizeof (rp_window_frame)); + maximize (cur->win); + XRaiseWindow (dpy, cur->win->w); } - + } + else + { + memcpy (cur, &tmp_frame, sizeof (rp_window_frame)); } } free (frame); } + +void +set_active_frame (rp_window_frame *frame) +{ + give_window_focus (frame->win); + rp_current_frame = frame; + + update_frame_indicator(); + + if( !frame->win ) + { + XSetInputFocus (dpy, current_screen()->frame_window, + RevertToPointerRoot, CurrentTime); + } +} |