diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/actions.c | 132 | ||||
-rw-r--r-- | src/bar.c | 6 | ||||
-rw-r--r-- | src/data.h | 17 | ||||
-rw-r--r-- | src/events.c | 75 | ||||
-rw-r--r-- | src/list.c | 130 | ||||
-rw-r--r-- | src/list.h | 4 | ||||
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/manage.c | 45 | ||||
-rw-r--r-- | src/split.c | 420 | ||||
-rw-r--r-- | src/split.h | 14 |
10 files changed, 459 insertions, 394 deletions
diff --git a/src/actions.c b/src/actions.c index 537fbfc..ced4c8e 100644 --- a/src/actions.c +++ b/src/actions.c @@ -1,5 +1,4 @@ -/* ratpoison actions - * Copyright (C) 2000, 2001 Shawn Betts +/* Copyright (C) 2000, 2001 Shawn Betts * * This file is part of ratpoison. * @@ -326,7 +325,7 @@ cmd_generate (void *data) /* ev1.xkey.send_event = */ ev1.xkey.display = dpy; /* ev1.xkey.root = */ - ev1.xkey.window = rp_current_window->w; + ev1.xkey.window = current_window()->w; /* ev1.xkey.subwindow = */ /* ev1.xkey.time = ev.xkey.time; */ /* ev1.xkey.x == */ @@ -337,7 +336,7 @@ cmd_generate (void *data) ev1.xkey.state = prefix_key.state; ev1.xkey.keycode = XKeysymToKeycode (dpy, prefix_key.sym); - XSendEvent (dpy, rp_current_window->w, False, KeyPressMask, &ev1); + XSendEvent (dpy, current_window()->w, False, KeyPressMask, &ev1); /* XTestFakeKeyEvent (dpy, XKeysymToKeycode (dpy, 't'), True, 0); */ @@ -349,11 +348,19 @@ cmd_prev (void *data) { rp_window *w; - if (!rp_current_window) - message (MESSAGE_NO_MANAGED_WINDOWS); - else + /* If the current frame is empty find the last accessed window and + put it in the frame */ + if (!current_window()) + { + set_active_window (find_window_other()); + if (!current_window()) + message (MESSAGE_NO_MANAGED_WINDOWS); + + return; + } + else { - w = find_window_prev (rp_current_window); + w = find_window_prev (current_window()); if (!w) message (MESSAGE_NO_OTHER_WINDOW); @@ -365,19 +372,13 @@ cmd_prev (void *data) void cmd_prev_frame (void *data) { - rp_window *w; - - if (!rp_current_window) - message (MESSAGE_NO_MANAGED_WINDOWS); - else - { - w = find_window_prev_with_frame (rp_current_window); + rp_window_frame *frame; - if (!w) - message (MESSAGE_NO_OTHER_WINDOW); - else - set_active_window (w); - } + frame = find_frame_prev (rp_current_frame); + if (!frame) + message (MESSAGE_NO_OTHER_WINDOW); + else + set_active_frame (frame); } void @@ -385,11 +386,19 @@ cmd_next (void *data) { rp_window *w; - if (!rp_current_window) - message (MESSAGE_NO_MANAGED_WINDOWS); + /* If the current frame is empty find the last accessed window and + put it in the frame */ + if (!current_window()) + { + set_active_window (find_window_other()); + if (!current_window()) + message (MESSAGE_NO_MANAGED_WINDOWS); + + return; + } else { - w = find_window_next (rp_current_window); + w = find_window_next (current_window()); if (!w) message (MESSAGE_NO_OTHER_WINDOW); @@ -401,19 +410,14 @@ cmd_next (void *data) void cmd_next_frame (void *data) { - rp_window *w; + rp_window_frame *frame; - if (!rp_current_window) - message (MESSAGE_NO_MANAGED_WINDOWS); - else - { - w = find_window_next_with_frame (rp_current_window); + frame = find_frame_next (rp_current_frame); + if (!frame) + message (MESSAGE_NO_OTHER_WINDOW); + else + set_active_frame (frame); - if (!w) - message (MESSAGE_NO_OTHER_WINDOW); - else - set_active_window (w); - } } void @@ -462,13 +466,13 @@ cmd_select (void *data) if (strlen (str) > 0) { if ((w = find_window_name (str))) - set_active_window (w); + goto_window (w); /* try by number */ if ((n = string_to_window_number (str)) >= 0) { if ((w = find_window_number (n))) - set_active_window (w); + goto_window (w); else /* show the window list as feedback */ show_bar (current_screen ()); @@ -477,7 +481,7 @@ cmd_select (void *data) /* try by name */ { if ((w = find_window_name (str))) - set_active_window (w); + goto_window (w); else /* we need to format a string that includes the str */ message (" no window by that name "); @@ -492,7 +496,7 @@ cmd_rename (void *data) { char *winname; - if (rp_current_window == NULL) return; + if (current_window() == NULL) return; if (data == NULL) winname = get_input (MESSAGE_PROMPT_NEW_WINDOW_NAME); @@ -501,15 +505,15 @@ cmd_rename (void *data) if (*winname) { - free (rp_current_window->name); - rp_current_window->name = xmalloc (sizeof (char) * strlen (winname) + 1); + free (current_window()->name); + current_window()->name = xmalloc (sizeof (char) * strlen (winname) + 1); - strcpy (rp_current_window->name, winname); + strcpy (current_window()->name, winname); - rp_current_window->named = 1; + current_window()->named = 1; /* Update the program bar. */ - update_window_names (rp_current_window->scr); + update_window_names (current_window()->scr); } free (winname); @@ -522,25 +526,25 @@ cmd_delete (void *data) XEvent ev; int status; - if (rp_current_window == NULL) return; + if (current_window() == NULL) return; ev.xclient.type = ClientMessage; - ev.xclient.window = rp_current_window->w; + ev.xclient.window = current_window()->w; ev.xclient.message_type = wm_protocols; ev.xclient.format = 32; ev.xclient.data.l[0] = wm_delete; ev.xclient.data.l[1] = CurrentTime; - status = XSendEvent(dpy, rp_current_window->w, False, 0, &ev); + status = XSendEvent(dpy, current_window()->w, False, 0, &ev); if (status == 0) fprintf(stderr, "ratpoison: delete window failed\n"); } void cmd_kill (void *data) { - if (rp_current_window == NULL) return; + if (current_window() == NULL) return; - XKillClient(dpy, rp_current_window->w); + XKillClient(dpy, current_window()->w); } void @@ -736,9 +740,9 @@ cmd_abort (void *data) /* XEvent ev; */ /* ev = *rp_current_event; */ -/* ev.xkey.window = rp_current_window->w; */ +/* ev.xkey.window = current_window()->w; */ /* ev.xkey.state = MODIFIER_PREFIX; */ -/* XSendEvent (dpy, rp_current_window->w, False, KeyPressMask, &ev); */ +/* XSendEvent (dpy, current_window()->w, False, KeyPressMask, &ev); */ /* XSync (dpy, False); */ /* } */ @@ -746,7 +750,7 @@ cmd_abort (void *data) void cmd_maximize (void *data) { - force_maximize (rp_current_window); + force_maximize (current_window()); } /* Reassign the prefix key. */ @@ -813,41 +817,35 @@ cmd_echo (void *data) void cmd_h_split (void *data) { - h_split_window (rp_current_window); + h_split_frame (find_windows_frame (current_window())); } void cmd_v_split (void *data) { - v_split_window (rp_current_window); + v_split_frame (find_windows_frame (current_window())); } void cmd_only (void *data) { - if (!rp_current_window) return; + if (!current_window()) return; - remove_all_frames(); - maximize (rp_current_window); + remove_all_splits(); + maximize (current_window()); } void cmd_remove (void *data) { - rp_window *win; - - if (!rp_current_window) return; + rp_window_frame *frame; - remove_frame (rp_current_window); + frame = find_frame_next (rp_current_frame); - win = find_window_next_with_frame (rp_current_window); - if (win) + if (frame) { - set_active_window (win); - } - else - { - set_active_window (find_window_other()); + remove_frame (rp_current_frame); + set_active_frame (frame); } } @@ -114,7 +114,7 @@ update_window_names (screen_info *s) { PRINT_DEBUG ("%d-%s\n", w->number, w->name); - if (w == rp_current_window) + if (w == current_window()) mark_start = strlen (sbuf_get (bar_buffer)); sbuf_concat (bar_buffer, " "); @@ -122,7 +122,7 @@ update_window_names (screen_info *s) sprintf (dbuf, "%d", w->number); sbuf_concat (bar_buffer, dbuf); - if (w == rp_current_window) + if (w == current_window()) sbuf_concat (bar_buffer, "*"); else if (w == other_window) sbuf_concat (bar_buffer, "+"); @@ -133,7 +133,7 @@ update_window_names (screen_info *s) sbuf_concat (bar_buffer, " "); - if (w == rp_current_window) + if (w == current_window()) mark_end = strlen (sbuf_get (bar_buffer)); } @@ -40,6 +40,9 @@ typedef struct rp_window_frame rp_window_frame; struct rp_window_frame { int x, y, width, height; + rp_window *win; + + rp_window_frame *prev, *next; }; @@ -69,9 +72,6 @@ struct rp_window /* Saved mouse position */ int mouse_x, mouse_y; - /* Frame for split screen */ - rp_window_frame *frame; - rp_window *next, *prev; }; @@ -80,7 +80,7 @@ struct screen_info GC normal_gc; XFontStruct *font; /* The font we want to use. */ XWindowAttributes root_attr; - Window root, bar_window, key_window, input_window; + Window root, bar_window, key_window, input_window, frame_window; int bar_is_raised; int screen_num; /* Our screen number as dictated my X */ Colormap def_cmap; @@ -121,9 +121,12 @@ extern rp_window *rp_mapped_window_sentinel; assigned to them and are not visible/active. */ extern rp_window *rp_unmapped_window_sentinel; -/* Pointer to the currently focused window. Points to an element in - the mapped window list. NULL if there are no mapped windows. */ -extern rp_window *rp_current_window; +/* A list of frames that may or may not contain windows. There should + always be one in the list. */ +extern rp_window_frame *rp_window_frame_sentinel; + +/* Pointer to the currently focused frame. */ +extern rp_window_frame *rp_current_frame; extern screen_info *screens; extern int num_screens; diff --git a/src/events.c b/src/events.c index cbf6cd7..b0c9a1b 100644 --- a/src/events.c +++ b/src/events.c @@ -48,13 +48,19 @@ new_window (XCreateWindowEvent *e) win = find_window (e->window); if (s && !win && e->window != s->key_window && e->window != s->bar_window - && e->window != s->input_window) + && e->window != s->input_window && e->window != s->frame_window) { win = add_to_window_list (s, e->window); update_window_information (win); } } +static void +cleanup_frame (rp_window_frame *frame) +{ + frame->win = find_window_other (); +} + void unmap_notify (XEvent *ev) { @@ -68,6 +74,7 @@ unmap_notify (XEvent *ev) if (s && win) { + rp_window_frame *frame; long data[2] = { WithdrawnState, None }; /* Give back the window number. the window will get another one, @@ -78,52 +85,8 @@ unmap_notify (XEvent *ev) ignore_badwindow++; - if (win->frame) - { - rp_window *new_window; - - PRINT_DEBUG ("unmapping framed window.\n"); - - new_window = find_window_for_frame (win->frame); - if (new_window) - { - PRINT_DEBUG ("Found a window to fit the frame.\n"); - - new_window->frame = xmalloc (sizeof (rp_window_frame)); - memcpy (new_window->frame, win->frame, sizeof (rp_window_frame)); - maximize (new_window); - XRaiseWindow (dpy, new_window->w); - - if (win == rp_current_window) - { - set_active_window (new_window); - } - } - else - { - PRINT_DEBUG ("No window to fit the frame.\n"); - - /* We coudn't find a window to occupy the frame, so get - rid of it. */ - remove_frame (win); - new_window = find_window_next_with_frame (rp_current_window); - if (new_window) - { - set_active_window (new_window); - } - else - { - set_active_window (find_window_other()); - } - } - - free (win->frame); - win->frame = NULL; - } - else if (rp_current_window == win) - { - cmd_other (NULL); - } + frame = find_windows_frame (win); + if (frame) cleanup_frame (frame); remove_from_list (win); append_to_list (win, rp_unmapped_window_sentinel); @@ -136,6 +99,8 @@ unmap_notify (XEvent *ev) XSync(dpy, False); + if (win == current_window()) cmd_other (NULL); + ignore_badwindow--; update_window_names (s); @@ -213,11 +178,15 @@ destroy_window (XDestroyWindowEvent *ev) if (win) { - if (win == rp_current_window) + rp_window_frame *frame; + + frame = find_windows_frame (win); + if (frame) cleanup_frame (frame); + + if (win == current_window()) { PRINT_DEBUG ("Destroying the current window.\n"); - rp_current_window = NULL; set_active_window (find_window_other ()); unmanage (win); } @@ -409,11 +378,11 @@ key_press (XEvent *ev) } else { - if (rp_current_window) + if (current_window()) { ignore_badwindow++; - ev->xkey.window = rp_current_window->w; - XSendEvent (dpy, rp_current_window->w, False, KeyPressMask, ev); + ev->xkey.window = current_window()->w; + XSendEvent (dpy, current_window()->w, False, KeyPressMask, ev); XSync (dpy, False); ignore_badwindow--; } @@ -557,7 +526,7 @@ colormap_notify (XEvent *ev) XGetWindowAttributes (dpy, win->w, &attr); win->colormap = attr.colormap; - if (win == rp_current_window) + if (win == current_window()) { XInstallColormap (dpy, win->colormap); } @@ -28,7 +28,6 @@ rp_window *rp_unmapped_window_sentinel; rp_window *rp_mapped_window_sentinel; -rp_window *rp_current_window; /* Get the mouse position relative to the root of the specified window */ static void @@ -46,7 +45,6 @@ free_window (rp_window *w) { if (w == NULL) return; - if (w->frame) free (w->frame); free (w->name); XFree (w->hints); @@ -73,7 +71,6 @@ add_to_window_list (screen_info *s, Window w) new_window->colormap = DefaultColormap (dpy, s->screen_num); new_window->transient = XGetTransientForHint (dpy, new_window->w, &new_window->transient_for); PRINT_DEBUG ("transient %d\n", new_window->transient); - new_window->frame = NULL; get_mouse_root_position (new_window, &new_window->mouse_x, &new_window->mouse_y); @@ -120,12 +117,10 @@ find_window (Window w) return win; } - - void set_current_window (rp_window *win) { - rp_current_window = win; + rp_current_frame->win = win; } void @@ -139,8 +134,6 @@ init_window_list () rp_unmapped_window_sentinel->next = rp_unmapped_window_sentinel; rp_unmapped_window_sentinel->prev = rp_unmapped_window_sentinel; - - rp_current_window = NULL; } rp_window * @@ -208,31 +201,7 @@ find_window_prev (rp_window *w) { if (cur == rp_mapped_window_sentinel) continue; - if (!cur->frame) - { - return cur; - } - } - - return NULL; -} - -/* Return the next window that is contained in a frame. Assumes window - is in the mapped window list. */ -rp_window* -find_window_prev_with_frame (rp_window *w) -{ - rp_window *cur; - - if (!w) return NULL; - - for (cur = w->prev; - cur != w; - cur = cur->prev) - { - if (cur == rp_mapped_window_sentinel) continue; - - if (cur->frame) + if (!find_windows_frame (cur)) { return cur; } @@ -256,31 +225,7 @@ find_window_next (rp_window *w) { if (cur == rp_mapped_window_sentinel) continue; - if (!cur->frame) - { - return cur; - } - } - - return NULL; -} - -/* Return the next window that is contained in a frame. Assumes window - is in the mapped window list. */ -rp_window* -find_window_next_with_frame (rp_window *w) -{ - rp_window *cur; - - if (!w) return NULL; - - for (cur = w->next; - cur != w; - cur = cur->next) - { - if (cur == rp_mapped_window_sentinel) continue; - - if (cur->frame) + if (!find_windows_frame (cur)) { return cur; } @@ -289,7 +234,6 @@ find_window_next_with_frame (rp_window *w) return NULL; } - rp_window * find_window_other () { @@ -302,8 +246,8 @@ find_window_other () cur = cur->next) { if (cur->last_access >= last_access - && cur != rp_current_window - && !cur->frame) + && cur != current_window() + && !find_windows_frame (cur)) { most_recent = cur; last_access = cur->last_access; @@ -427,53 +371,69 @@ save_mouse_position (rp_window *win) } void -set_active_window (rp_window *rp_w) +give_window_focus (rp_window *win) { static int counter = 1; /* increments every time this function is called. This way we can track which window was last accessed. */ - if (rp_w == NULL) return; - if (rp_w == rp_current_window) return; + if (win == NULL) return; counter++; - rp_w->last_access = counter; + win->last_access = counter; - if (rp_w->scr->bar_is_raised) update_window_names (rp_w->scr); +/* if (win->scr->bar_is_raised) update_window_names (win->scr); */ - if (rp_current_window != NULL) + if (current_window() != NULL) { - save_mouse_position (rp_current_window); + save_mouse_position (current_window()); } - XWarpPointer (dpy, None, rp_w->scr->root, - 0, 0, 0, 0, rp_w->mouse_x, rp_w->mouse_y); + XWarpPointer (dpy, None, win->scr->root, + 0, 0, 0, 0, win->mouse_x, win->mouse_y); XSync (dpy, False); - XSetInputFocus (dpy, rp_w->w, + XSetInputFocus (dpy, win->w, RevertToPointerRoot, CurrentTime); /* Swap colormaps */ - if (rp_current_window != NULL) + if (current_window() != NULL) { - XUninstallColormap (dpy, rp_current_window->colormap); + XUninstallColormap (dpy, current_window()->colormap); } - XInstallColormap (dpy, rp_w->colormap); + XInstallColormap (dpy, win->colormap); +} - /* If the new window doesn't have a frame then it inherits the frame - of the current window */ - if (!rp_w->frame && rp_current_window) - { - rp_w->frame = rp_current_window->frame; - rp_current_window->frame = NULL; - } +void +set_active_window (rp_window *win) +{ + if (win == NULL) return; - rp_current_window = rp_w; + give_window_focus (win); + rp_current_frame->win = win; /* Make sure the window comes up full screen */ - maximize (rp_current_window); - XRaiseWindow (dpy, rp_w->w); + maximize (current_window()); + XRaiseWindow (dpy, win->w); /* Make sure the program bar is always on the top */ - update_window_names (rp_w->scr); + update_window_names (win->scr); +} + +/* Go to the window, switching frames if the window is already in a + frame. */ +void +goto_window (rp_window *win) +{ + rp_window_frame *frame; + + frame = find_windows_frame (win); + if (frame) + { + set_active_frame (frame); + } + else + { + set_active_window (win); + } } @@ -31,7 +31,9 @@ void last_window (); rp_window *find_window_in_list (Window w, rp_window *sentinel); rp_window *find_window (Window w); void maximize_current_window (); -void set_active_window (rp_window *rp_w); +void give_window_focus (rp_window *rp_w); +void set_active_window (rp_window *win); +void goto_window (rp_window *win); void set_current_window (rp_window *win); /* int goto_window_name (char *name); */ rp_window *find_window_other (); @@ -402,6 +402,7 @@ main (int argc, char *argv[]) init_numbers (); init_window_list (); + init_frame_list (); initialize_default_keybindings (); init_modifier_map (); @@ -499,6 +500,15 @@ init_screen (screen_info *s, int screen_num) 1, 1, 1, fg_color.pixel, bg_color.pixel); XSelectInput (dpy, s->input_window, KeyPressMask ); + s->frame_window = XCreateSimpleWindow (dpy, s->root, + s->root_attr.width / 2 - 5, + s->root_attr.height / 2 - 5, + 10, 10, 1, + fg_color.pixel, bg_color.pixel); + XSelectInput (dpy, s->frame_window, KeyPressMask ); + XMapRaised (dpy, s->frame_window); + + XSync (dpy, 0); scanwins (s); diff --git a/src/manage.c b/src/manage.c index afa4730..1e52fe3 100644 --- a/src/manage.c +++ b/src/manage.c @@ -65,8 +65,8 @@ ungrab_prefix_key (Window w) screen_info* current_screen () { - if (rp_current_window) - return rp_current_window->scr; + if (current_window()) + return current_window()->scr; else return &screens[0]; } @@ -230,7 +230,10 @@ scanwins(screen_info *s) for (i = 0; i < nwins; i++) { XGetWindowAttributes(dpy, wins[i], &attr); - if (wins[i] == s->bar_window || wins[i] == s->key_window || wins[i] == s->input_window) continue; + if (wins[i] == s->bar_window + || wins[i] == s->key_window + || wins[i] == s->input_window + || wins[i] == s->frame_window) continue; if (attr.override_redirect != True && !unmanaged_window (wins[i])) { @@ -290,11 +293,14 @@ set_state (rp_window *win, int state) static void maximize_transient (rp_window *win) { + rp_window_frame *frame; int maxx, maxy; /* Set the window's border */ win->border = WINDOW_BORDER_WIDTH; + frame = find_windows_frame (win); + /* Honour the window's maximum size */ if (win->hints->flags & PMaxSize) { @@ -330,12 +336,12 @@ maximize_transient (rp_window *win) PRINT_DEBUG ("maxsize: %d %d\n", maxx, maxy); /* Fit the window inside its frame (if it has one) */ - if (win->frame) + if (frame) { - win->x = win->frame->x - win->width / 2 - + (win->frame->width - win->border * 2) / 2; - win->y = win->frame->y - win->height / 2 - + (win->frame->height - win->border * 2) / 2; + win->x = frame->x - win->width / 2 + + (frame->width - win->border * 2) / 2; + win->y = frame->y - win->height / 2 + + (frame->height - win->border * 2) / 2; } else { @@ -354,6 +360,7 @@ maximize_transient (rp_window *win) static void maximize_normal (rp_window *win) { + rp_window_frame *frame; int maxx, maxy; int off_x = 0; @@ -362,6 +369,8 @@ maximize_normal (rp_window *win) /* Set the window's border */ win->border = WINDOW_BORDER_WIDTH; + frame = find_windows_frame (win); + /* Honour the window's maximum size */ if (win->hints->flags & PMaxSize) { @@ -377,15 +386,13 @@ maximize_normal (rp_window *win) } /* Fit the window inside its frame (if it has one) */ - if (win->frame) + if (frame) { PRINT_DEBUG ("frame width=%d height=%d\n", - win->frame->width, win->frame->height); + frame->width, frame->height); - if (maxx > win->frame->width) maxx = win->frame->width - - win->border * 2; - if (maxy > win->frame->height) maxy = win->frame->height - - win->border * 2; + if (maxx > frame->width) maxx = frame->width - win->border * 2; + if (maxy > frame->height) maxy = frame->height - win->border * 2; } /* Make sure we maximize to the nearest Resize Increment specified @@ -411,10 +418,10 @@ maximize_normal (rp_window *win) PRINT_DEBUG ("maxsize: %d %d\n", maxx, maxy); /* Fit the window inside its frame (if it has one) */ - if (win->frame) + if (frame) { - win->x = win->frame->x; - win->y = win->frame->y; + win->x = frame->x; + win->y = frame->y; } else { @@ -431,7 +438,7 @@ maximize_normal (rp_window *win) void maximize (rp_window *win) { - if (!win) win = rp_current_window; + if (!win) win = current_window(); if (!win) return; /* Handle maximizing transient windows differently */ @@ -455,7 +462,7 @@ maximize (rp_window *win) void force_maximize (rp_window *win) { - if (!win) win = rp_current_window; + if (!win) win = current_window(); if (!win) return; maximize_normal(win); 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); + } +} diff --git a/src/split.h b/src/split.h index 4e70e24..2fa1557 100644 --- a/src/split.h +++ b/src/split.h @@ -22,10 +22,16 @@ #ifndef SPLIT_H #define SPLIT_H -int h_split_window (rp_window *w); -int v_split_window (rp_window *w); -void remove_all_frames (); -void remove_frame (rp_window *w); +void h_split_frame (rp_window_frame *frame); +void v_split_frame (rp_window_frame *frame); +void remove_all_splits (); +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); +rp_window_frame *find_frame_next (rp_window_frame *frame); +rp_window_frame *find_frame_prev (rp_window_frame *frame); +rp_window *current_window (); +void init_frame_list (); +void set_active_frame (rp_window_frame *frame); #endif |