summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog64
-rw-r--r--NEWS5
-rw-r--r--src/actions.c132
-rw-r--r--src/bar.c6
-rw-r--r--src/data.h17
-rw-r--r--src/events.c75
-rw-r--r--src/list.c130
-rw-r--r--src/list.h4
-rw-r--r--src/main.c10
-rw-r--r--src/manage.c45
-rw-r--r--src/split.c420
-rw-r--r--src/split.h14
12 files changed, 527 insertions, 395 deletions
diff --git a/ChangeLog b/ChangeLog
index c06bf42..5f2c57f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,67 @@
+2001-04-06 shawn <sabetts@diggin.lamenet.tmp>
+
+ * src/split.h (h_split_frame): renamed frome h_split_window
+ (v_split_frame): renamed frome v_split_window
+ (split_frame): renamed frome split_window
+ (remove_all_splits): renamed frome remove_all_frames
+ (find_windows_frame): new prototype
+ (find_frame_next): likewise
+ (find_frame_prev): likewise
+ (current_window): likewise
+ (init_frame_list): likewise
+ (set_active_frame): likewise
+
+ * src/split.c (create_initial_frame): new function
+ (init_frame_list): likewise
+ (find_windows_frame): likewise
+ (find_frame_next): likewise
+ (find_frame_prev): likewise
+ (current_window): likewise
+ (update_frame_indicator): likewise
+ (set_active_frame): likewise
+ (split_frame): rename from split_window
+ (v_split_frame): rename from v_split_window
+ (h_split_frame): rename from h_split_window
+ (remove_all_splits): renamed frome remove_all_frames
+ (total_frame_area): traverses rp_window_frame list
+ (num_frames): likewise
+ (frame_overlaps): likewise
+ (remove_frame): likewise
+ (remove_frame): calls delete_frame_from_list
+
+ * src/manage.c (scanwins): skips the frame_window
+ (maximize_transient): finds the window's frame
+ (maximize_normal): likewise
+
+ * src/main.c (main): calls init_frame_list
+ (init_screen): create and map the frame_window
+
+ * src/list.c (give_window_focus): new function
+ (goto_window): likewise
+ (set_active_window): calls give_window_focus
+
+ * src/list.h (give_window_focus): new prototype
+ (goto_window): likewise
+
+ * src/events.c (new_window): the screen's frame_window is not
+ managed
+ (cleanup_frame): new function
+ (unmap_notify): calls cleanup_frame if window exists in a frame
+ (destroy_window): likewise
+
+ * src/data.h (struct screen_info): remove frame field
+ (struct rp_window_frame): new fields win, prev, next
+ (rp_window_frame_sentinel): new global
+
+ * src/actions.c (cmd_prev): jumps to last accessed window if
+ current frame is empty.
+ (cmd_next): likewise
+ (cmd_remove): nothing is done if only 1 frame exists
+
+ * src/data.h (struct screen_info): new field frame_window
+ (rp_current_frame): new global
+ (rp_current_window): removed. All dependant code updated.
+
2001-04-04 Ryan Yeske <rcyeske@cut.hotdog.tmp>
* src/actions.c: add :banish to user_commands.
diff --git a/NEWS b/NEWS
index 4ebc5ae..0692023 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
ratpoison NEWS --- history of user-visible changes. -*- outline -*-
-* Changes since 0.1.0
+* Changes since 0.1.1
+
** Split windows
Well, the day is finally here. You can now split windows in
@@ -24,6 +25,8 @@ A new command, :banish, which will move the rat pointer out of harms
way, has been added. It is bound to 'C-t b' by default. No more
slapping your rat out of the way, as fun as that was.
+* Changes since 0.1.0
+
** Window list changes
A '+' is now drawn between the window number and the window name for
the last accessed window.
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);
}
}
diff --git a/src/bar.c b/src/bar.c
index c713c63..150aa13 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -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));
}
diff --git a/src/data.h b/src/data.h
index d4e6a82..080f7ee 100644
--- a/src/data.h
+++ b/src/data.h
@@ -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);
}
diff --git a/src/list.c b/src/list.c
index 9225d5a..e4c7680 100644
--- a/src/list.c
+++ b/src/list.c
@@ -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);
+ }
}
diff --git a/src/list.h b/src/list.h
index dfacabb..c69ff71 100644
--- a/src/list.h
+++ b/src/list.h
@@ -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 ();
diff --git a/src/main.c b/src/main.c
index fc97004..cd79f69 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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