summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsabetts <sabetts>2004-02-27 08:28:16 +0000
committersabetts <sabetts>2004-02-27 08:28:16 +0000
commitfab11adc940f3258dc53c823903f242d9c65da91 (patch)
treeb1057b031c67173189c0c60dbf93fe2b2f8c1210
parenta5c30aed8f3d73ac39e997a11068d12b82eab42e (diff)
downloadratpoison-fab11adc940f3258dc53c823903f242d9c65da91.zip
* src/window.c (give_window_focus): save the mouse position before
checking if win is NULL. (give_window_focus): set rp_current_screen to xine_screen_num of the window's screen. (set_active_window): when using xinerama get the frame from the current screen. * src/split.c (set_frames_window): update the window's scr attribute to point to the frame's screen. (find_window_for_frame): when xinerama is being used search all windows. (set_active_frame): update rp_current_screen to point to the frame's screen. * src/screen.h (init_screens): new prototype (is_rp_window_for_screen): likewise * src/screen.c: include string.h and X11/cursorfont.h (init_screens): new function (is_rp_window_for_screen): new function. (init_screen): fill in xine_screen_num when using xinerama. * src/ratpoison.h: include xinerama.h * src/manage.c (current_screen): use xine_screen_num to find the current screen. (scanwins): use is_rp_window_for_screen to skip over ratpoison windows. (scanwins): when using xinerama only manage windows inside the viewable area. * src/main.c (main): call init_xinerama and init_screens. Move screen initing code to these functions. (init_rat_cursor): move to screen.c (init_screen): likewise (find_screen): likewise (clean_up): call free_xinerama * src/group.c (group_last_window): only check windows in the current screen, unless xinerama is being used in which case all windows are accessible. (group_next_window): likewise (group_prev_window): likewise * src/globals.h: new globals rp_have_xinerama, xine_screen_num. * src/events.c (new_window): when using xinerama, the new window's screen is the current screen. (key_press): when using xinerama, use the current screen. * src/data.h (struct rp_screen): remove root_attr and add left, top, width, height. All dependant code updated. Add xine_screen_num. * src/actions.c (cmd_remove): show the frame indicator in the new current frame after removing the frame. * src/Makefile.am (ratpoison_SOURCES): add xinerama.c and xinerama.h
-rw-r--r--ChangeLog59
-rw-r--r--configure.in7
-rw-r--r--src/Makefile.am6
-rw-r--r--src/actions.c23
-rw-r--r--src/bar.c12
-rw-r--r--src/data.h9
-rw-r--r--src/events.c23
-rw-r--r--src/globals.h3
-rw-r--r--src/group.c6
-rw-r--r--src/main.c139
-rw-r--r--src/manage.c23
-rw-r--r--src/ratpoison.h1
-rw-r--r--src/screen.c219
-rw-r--r--src/screen.h4
-rw-r--r--src/split.c24
-rw-r--r--src/window.c28
16 files changed, 394 insertions, 192 deletions
diff --git a/ChangeLog b/ChangeLog
index c1ad8b1..7c9fd21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,62 @@
+2004-02-27 Shawn Betts <sabetts@vcn.bc.ca>
+
+ * src/window.c (give_window_focus): save the mouse position before
+ checking if win is NULL.
+ (give_window_focus): set rp_current_screen to xine_screen_num of
+ the window's screen.
+ (set_active_window): when using xinerama get the frame from the
+ current screen.
+
+ * src/split.c (set_frames_window): update the window's scr
+ attribute to point to the frame's screen.
+ (find_window_for_frame): when xinerama is being used search all
+ windows.
+ (set_active_frame): update rp_current_screen to point to the
+ frame's screen.
+
+ * src/screen.h (init_screens): new prototype
+ (is_rp_window_for_screen): likewise
+
+ * src/screen.c: include string.h and X11/cursorfont.h
+ (init_screens): new function
+ (is_rp_window_for_screen): new function.
+ (init_screen): fill in xine_screen_num when using xinerama.
+
+ * src/ratpoison.h: include xinerama.h
+
+ * src/manage.c (current_screen): use xine_screen_num to find the
+ current screen.
+ (scanwins): use is_rp_window_for_screen to skip over ratpoison windows.
+ (scanwins): when using xinerama only manage windows inside the viewable area.
+
+ * src/main.c (main): call init_xinerama and init_screens. Move
+ screen initing code to these functions.
+ (init_rat_cursor): move to screen.c
+ (init_screen): likewise
+ (find_screen): likewise
+ (clean_up): call free_xinerama
+
+
+ * src/group.c (group_last_window): only check windows in the
+ current screen, unless xinerama is being used in which case all
+ windows are accessible.
+ (group_next_window): likewise
+ (group_prev_window): likewise
+
+ * src/globals.h: new globals rp_have_xinerama, xine_screen_num.
+
+ * src/events.c (new_window): when using xinerama, the new window's
+ screen is the current screen.
+ (key_press): when using xinerama, use the current screen.
+
+ * src/data.h (struct rp_screen): remove root_attr and add left,
+ top, width, height. All dependant code updated. Add xine_screen_num.
+
+ * src/actions.c (cmd_remove): show the frame indicator in the new
+ current frame after removing the frame.
+
+ * src/Makefile.am (ratpoison_SOURCES): add xinerama.c and xinerama.h
+
2004-02-26 Shawn Betts <sabetts@vcn.bc.ca>
* src/split.c (hide_frame_indicator): unmap all 'current frame'
diff --git a/configure.in b/configure.in
index 6d58f3a..2ec5025 100644
--- a/configure.in
+++ b/configure.in
@@ -17,7 +17,7 @@ dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
dnl
-dnl $Id: configure.in,v 1.39 2003/11/03 03:17:59 sabetts Exp $
+dnl $Id: configure.in,v 1.40 2004/02/27 08:28:16 sabetts Exp $
AC_INIT(src/main.c)
AM_INIT_AUTOMAKE(ratpoison, 1.3.0-cvs)
@@ -87,6 +87,11 @@ CFLAGS="$CFLAGS $X_CFLAGS"
AC_CHECK_LIB(X11, XOpenDisplay,,
AC_MSG_ERROR([*** Can't find libX11]))
+AC_CHECK_HEADERS([X11/extensions/Xinerama.h])
+AC_CHECK_LIB(Xext, XMissingExtension, [LIBS="-lXext $LIBS"],, $CFLAGS $LDFLAGS)
+AC_CHECK_LIB(Xinerama, XineramaQueryScreens, [LIBS="-lXinerama $LIBS"],, $CFLAGS $LDFLAGS)
+
+
dnl Check for electric fence library
dnl AC_CHECK_LIB(efence,malloc,,)
diff --git a/src/Makefile.am b/src/Makefile.am
index 3cd61b6..c295497 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,7 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
-## $Id: Makefile.am,v 1.19 2003/07/17 05:41:41 sabetts Exp $
+## $Id: Makefile.am,v 1.20 2004/02/27 08:28:17 sabetts Exp $
bin_PROGRAMS = ratpoison
@@ -66,4 +66,6 @@ ratpoison_SOURCES = actions.c \
split.c \
split.h \
window.c \
- window.h \ No newline at end of file
+ window.h \
+ xinerama.c \
+ xinerama.h
diff --git a/src/actions.c b/src/actions.c
index 98cf640..59221e0 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -1660,6 +1660,7 @@ cmd_remove (int interactive, char *data)
{
remove_frame (current_frame());
set_active_frame (frame);
+ show_frame_indicator();
}
return NULL;
@@ -1792,7 +1793,7 @@ cmd_banish (int interactive, char *data)
s = current_screen ();
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->root_attr.width - 2, s->root_attr.height - 2);
+ XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2);
return NULL;
}
@@ -1854,8 +1855,8 @@ cmd_license (int interactive, char *data)
}
/* Offset the text so its in the center. */
- x = (s->root_attr.width - max_width) / 2;
- y = (s->root_attr.height - i * FONT_HEIGHT (defaults.font)) / 2;
+ x = s->left + (s->width - max_width) / 2;
+ y = s->top + (s->height - i * FONT_HEIGHT (defaults.font)) / 2;
if (x < 0) x = 0;
if (y < 0) y = 0;
@@ -1967,7 +1968,7 @@ cmd_help (int interactive, char *data)
y += FONT_HEIGHT (defaults.font);
/* Make sure the next line fits entirely within the window. */
- if (y + FONT_HEIGHT (defaults.font) >= s->root_attr.height)
+ if (y + FONT_HEIGHT (defaults.font) >= (s->top + s->height))
{
if (drawing_keys)
{
@@ -2354,8 +2355,8 @@ cmd_defpadding (int interactive, char *data)
frame->width += bk_pos - l;
}
- if (bk_pos + bk_len == current_screen()->root_attr.width - defaults.padding_right)
- frame->width = current_screen()->root_attr.width - r - frame->x;
+ if ((bk_pos + bk_len) == (current_screen()->left + current_screen()->width - defaults.padding_right))
+ frame->width = current_screen()->left + current_screen()->width - r - frame->x;
/* Resize vertically. */
bk_pos = frame->y;
@@ -2367,8 +2368,8 @@ cmd_defpadding (int interactive, char *data)
frame->height += bk_pos - t;
}
- if (bk_pos + bk_len == current_screen()->root_attr.height - defaults.padding_bottom)
- frame->height = current_screen()->root_attr.height - b - frame->y;
+ if ((bk_pos + bk_len) == (current_screen()->top + current_screen()->height - defaults.padding_bottom))
+ frame->height = current_screen()->top + current_screen()->height - b - frame->y;
maximize_all_windows_in_frame (frame);
}
@@ -2747,8 +2748,8 @@ cmd_info (int interactive, char *data)
if (current_window() == NULL)
{
marked_message_printf (0, 0, " (%d, %d) No window ",
- current_screen()->root_attr.width,
- current_screen()->root_attr.height);
+ current_screen()->width,
+ current_screen()->height);
}
else
{
@@ -3325,7 +3326,7 @@ cmd_fselect (int interactive, char *data)
height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2);
/* Create and map the window. */
- wins[i] = XCreateWindow (dpy, s->root, cur->x, cur->y, width, height, 1,
+ wins[i] = XCreateWindow (dpy, s->root, s->left + cur->x, s->top + cur->y, width, height, 1,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBorderPixel | CWBackPixel,
&attr);
diff --git a/src/bar.c b/src/bar.c
index 5dedac9..cb7d45d 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -96,17 +96,17 @@ bar_x (rp_screen *s, int width)
case NorthWestGravity:
case WestGravity:
case SouthWestGravity:
- x = 0;
+ x = s->left;
break;
case NorthGravity:
case CenterGravity:
case SouthGravity:
- x = (s->root_attr.width - width - defaults.bar_border_width * 2) / 2;
+ x = s->left + (s->width - width - defaults.bar_border_width * 2) / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
- x = s->root_attr.width - width - defaults.bar_border_width * 2;
+ x = s->left + s->width - width - defaults.bar_border_width * 2;
break;
}
@@ -123,18 +123,18 @@ bar_y (rp_screen *s, int height)
case NorthEastGravity:
case NorthGravity:
case NorthWestGravity:
- y = 0;
+ y = s->top;
break;
case EastGravity:
case CenterGravity:
case WestGravity:
- y = (s->root_attr.height - height
+ y = s->top + (s->height - height
- defaults.bar_border_width * 2) / 2;
break;
case SouthEastGravity:
case SouthGravity:
case SouthWestGravity:
- y = (s->root_attr.height - height
+ y = s->top + (s->height - height
- defaults.bar_border_width * 2);
break;
}
diff --git a/src/data.h b/src/data.h
index 5cfd550..5969ae4 100644
--- a/src/data.h
+++ b/src/data.h
@@ -50,7 +50,7 @@ struct rp_frame
/* For determining the last frame. */
int last_access;
-
+
struct list_head node;
};
@@ -137,14 +137,17 @@ struct rp_group
struct rp_screen
{
GC normal_gc;
- XWindowAttributes root_attr;
Window root, bar_window, key_window, input_window, frame_window, help_window;
int bar_is_raised;
int screen_num; /* Our screen number as dictated my X */
+ int xine_screen_num; /* Our screen number for the Xinerama extension */
Colormap def_cmap;
Cursor rat;
unsigned long fg_color, bg_color; /* The pixel color. */
-
+
+ /* Here to abstract over the Xinerama vs X screens difference */
+ int left, top, width, height;
+
char *display_string;
/* A list of frames that may or may not contain windows. There should
diff --git a/src/events.c b/src/events.c
index 97de6af..2498be2 100644
--- a/src/events.c
+++ b/src/events.c
@@ -50,9 +50,22 @@ new_window (XCreateWindowEvent *e)
if (e->override_redirect)
return;
- s = find_screen (e->parent);
win = find_window (e->window);
+ /* In Xinerama mode, all windows have the same root, so check
+ * all Xinerama screens
+ */
+ if (rp_have_xinerama)
+ {
+ /* New windows belong to the current screen */
+ s = &screens[rp_current_screen];
+ }
+ else
+ {
+ s = find_screen (e->parent);
+ }
+ if (is_rp_window_for_screen(e->window, s)) return;
+
if (s && win == NULL
&& e->window != s->key_window
&& e->window != s->bar_window
@@ -376,10 +389,13 @@ key_press (XEvent *ev)
unsigned int modifier;
KeySym ks;
- s = find_screen (ev->xkey.root);
+ if (rp_have_xinerama)
+ s = current_screen();
+ else
+ s = find_screen (ev->xkey.root);
#ifdef HIDE_MOUSE
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->root_attr.width - 2, s->root_attr.height - 2);
+ XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2);
#endif
if (!s) return;
@@ -825,3 +841,4 @@ listen_for_events ()
}
}
}
+
diff --git a/src/globals.h b/src/globals.h
index 2e5ac29..4a4ed46 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -141,4 +141,7 @@ extern struct rp_hook_db_entry rp_hook_db[];
void set_rp_window_focus (rp_window *win);
void set_window_focus (Window window);
+extern int rp_have_xinerama;
+extern int xine_screen_count;
+
#endif
diff --git a/src/group.c b/src/group.c
index c4815ec..3e637aa 100644
--- a/src/group.c
+++ b/src/group.c
@@ -331,7 +331,7 @@ group_last_window (rp_group *g)
if (cur->win->last_access >= last_access
&& cur->win != current_window()
&& !find_windows_frame (cur->win)
- && cur->win->scr == s)
+ && (cur->win->scr == s || rp_have_xinerama))
{
most_recent = cur;
last_access = cur->win->last_access;
@@ -365,7 +365,7 @@ group_next_window (rp_group *g, rp_window *win)
cur != we;
cur = list_next_entry (cur, &g->mapped_windows, node))
{
- if (!find_windows_frame (cur->win) && cur->win->scr == current_screen())
+ if (!find_windows_frame (cur->win) && (cur->win->scr == current_screen() || rp_have_xinerama))
{
return cur->win;
}
@@ -395,7 +395,7 @@ group_prev_window (rp_group *g, rp_window *win)
cur != we;
cur = list_prev_entry (cur, &g->mapped_windows, node))
{
- if (!find_windows_frame (cur->win) && cur->win->scr == current_screen())
+ if (!find_windows_frame (cur->win) && (cur->win->scr == current_screen() || rp_have_xinerama))
{
return cur->win;
}
diff --git a/src/main.c b/src/main.c
index b2daf7a..aace543 100644
--- a/src/main.c
+++ b/src/main.c
@@ -44,8 +44,6 @@
# define WAIT_ANY -1
#endif
-static void init_screen (rp_screen *s, int screen_num);
-
/* Command line options */
static struct option ratpoison_longopts[] =
{ {"help", no_argument, 0, 'h'},
@@ -614,38 +612,8 @@ main (int argc, char *argv[])
init_defaults ();
init_groups ();
init_window_stuff ();
-
- /* Get the number of screens */
- num_screens = ScreenCount (dpy);
-
- /* make sure the screen specified is valid. */
- if (screen_arg)
- {
- if (screen_num < 0 || screen_num >= num_screens)
- {
- fprintf (stderr, "%d is an invalid screen for the display\n", screen_num);
- exit (EXIT_FAILURE);
- }
-
- /* we're only going to use one screen. */
- num_screens = 1;
- }
-
- /* Initialize the screens */
- screens = (rp_screen *)xmalloc (sizeof (rp_screen) * num_screens);
- PRINT_DEBUG (("%d screens.\n", num_screens));
-
- if (screen_arg)
- {
- init_screen (&screens[0], screen_num);
- }
- else
- {
- for (i=0; i<num_screens; i++)
- {
- init_screen (&screens[i], i);
- }
- }
+ init_xinerama ();
+ init_screens (screen_arg, screen_num);
init_frame_lists ();
update_modifier_map ();
@@ -687,96 +655,6 @@ main (int argc, char *argv[])
}
static void
-init_rat_cursor (rp_screen *s)
-{
- s->rat = XCreateFontCursor( dpy, XC_icon );
-}
-
-static void
-init_screen (rp_screen *s, int screen_num)
-{
- XGCValues gv;
-
- /* Select on some events on the root window, if this fails, then
- there is already a WM running and the X Error handler will catch
- it, terminating ratpoison. */
- XSelectInput(dpy, RootWindow (dpy, screen_num),
- PropertyChangeMask | ColormapChangeMask
- | SubstructureRedirectMask | SubstructureNotifyMask );
- XSync (dpy, False);
-
- /* Create the numset for the frames. */
- s->frames_numset = numset_new ();
-
- /* Build the display string for each screen */
- s->display_string = xmalloc (strlen(DisplayString (dpy)) + 21);
- sprintf (s->display_string, "DISPLAY=%s", DisplayString (dpy));
- if (strrchr (DisplayString (dpy), ':'))
- {
- char *dot;
-
- dot = strrchr(s->display_string, '.');
- if (dot)
- sprintf(dot, ".%i", screen_num);
- }
-
- PRINT_DEBUG (("%s\n", s->display_string));
-
- s->screen_num = screen_num;
- s->root = RootWindow (dpy, screen_num);
- s->def_cmap = DefaultColormap (dpy, screen_num);
- XGetWindowAttributes (dpy, s->root, &s->root_attr);
-
- init_rat_cursor (s);
-
- s->fg_color = BlackPixel (dpy, s->screen_num);
- s->bg_color = WhitePixel (dpy, s->screen_num);
-
- /* Setup the GC for drawing the font. */
- gv.foreground = s->fg_color;
- gv.background = s->bg_color;
- gv.function = GXcopy;
- gv.line_width = 1;
- gv.subwindow_mode = IncludeInferiors;
- gv.font = defaults.font->fid;
- s->normal_gc = XCreateGC(dpy, s->root,
- GCForeground | GCBackground | GCFunction
- | GCLineWidth | GCSubwindowMode | GCFont,
- &gv);
-
- /* Create the program bar window. */
- s->bar_is_raised = 0;
- s->bar_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1,
- defaults.bar_border_width,
- s->fg_color, s->bg_color);
-
- /* Setup the window that will receive all keystrokes once the prefix
- key has been pressed. */
- s->key_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, 0,
- WhitePixel (dpy, s->screen_num),
- BlackPixel (dpy, s->screen_num));
- XSelectInput (dpy, s->key_window, KeyPressMask | KeyReleaseMask);
- XMapWindow (dpy, s->key_window);
-
- /* Create the input window. */
- s->input_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1,
- defaults.bar_border_width,
- s->fg_color, s->bg_color);
- XSelectInput (dpy, s->input_window, KeyPressMask | KeyReleaseMask);
-
- /* Create the frame indicator window */
- s->frame_window = XCreateSimpleWindow (dpy, s->root, 1, 1, 1, 1, defaults.bar_border_width,
- s->fg_color, s->bg_color);
-
- /* Create the help window */
- s->help_window = XCreateSimpleWindow (dpy, s->root, 0, 0, s->root_attr.width,
- s->root_attr.height, 0, s->fg_color, s->bg_color);
- XSelectInput (dpy, s->help_window, KeyPressMask);
-
- XSync (dpy, 0);
-}
-
-static void
free_screen (rp_screen *s)
{
rp_frame *frame;
@@ -824,6 +702,8 @@ clean_up ()
}
free (screens);
+ free_xinerama();
+
XFreeFont (dpy, defaults.font);
free (defaults.window_fmt);
@@ -831,14 +711,3 @@ clean_up ()
XCloseDisplay (dpy);
}
-/* Given a root window, return the rp_screen struct */
-rp_screen *
-find_screen (Window w)
-{
- int i;
-
- for (i=0; i<num_screens; i++)
- if (screens[i].root == w) return &screens[i];
-
- return NULL;
- }
diff --git a/src/manage.c b/src/manage.c
index 2330721..e85bfe8 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -129,7 +129,7 @@ current_screen ()
for (i=0; i<num_screens; i++)
{
- if (screens[i].screen_num == rp_current_screen)
+ if (screens[i].xine_screen_num == rp_current_screen)
return &screens[i];
}
@@ -385,14 +385,19 @@ scanwins(rp_screen *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
- || wins[i] == s->frame_window
- || wins[i] == s->help_window
+ if (is_rp_window_for_screen(wins[i], s)
|| attr.override_redirect == True
|| unmanaged_window (wins[i])) continue;
+ /* FIXME - with this code, windows which are entirely off-screen
+ * when RP starts won't ever be managed when Xinerama is enabled.
+ */
+ if (rp_have_xinerama
+ && ((attr.x > s->left + s->width)
+ || (attr.x < s->left)
+ || (attr.y > s->top + s->height)
+ || (attr.y < s->top))) continue;
+
win = add_to_window_list (s, wins[i]);
PRINT_DEBUG (("map_state: %s\n",
@@ -671,7 +676,7 @@ maximize (rp_window *win)
/* Actually do the maximizing. */
- XMoveResizeWindow (dpy, win->w, win->x, win->y, win->width, win->height);
+ XMoveResizeWindow (dpy, win->w, win->scr->left + win->x, win->scr->top + win->y, win->width, win->height);
XSetWindowBorderWidth (dpy, win->w, win->border);
XSync (dpy, False);
@@ -696,7 +701,7 @@ force_maximize (rp_window *win)
problem. */
if (win->hints->flags & PResizeInc)
{
- XMoveResizeWindow (dpy, win->w, win->x, win->y,
+ XMoveResizeWindow (dpy, win->w, win->scr->left + win->x, win->scr->top + win->y,
win->width + win->hints->width_inc,
win->height + win->hints->height_inc);
}
@@ -708,7 +713,7 @@ force_maximize (rp_window *win)
XSync (dpy, False);
/* Resize the window to its proper maximum size. */
- XMoveResizeWindow (dpy, win->w, win->x, win->y, win->width, win->height);
+ XMoveResizeWindow (dpy, win->w, win->scr->left + win->x, win->scr->top + win->y, win->width, win->height);
XSetWindowBorderWidth (dpy, win->w, win->border);
XSync (dpy, False);
diff --git a/src/ratpoison.h b/src/ratpoison.h
index 0a9719e..eb34dcf 100644
--- a/src/ratpoison.h
+++ b/src/ratpoison.h
@@ -84,6 +84,7 @@ extern XGCValues gv;
#endif /* HAVE_READLINE_HISTORY_H */
#include "completions.h"
#include "hook.h"
+#include "xinerama.h"
void clean_up ();
rp_screen *find_screen (Window w);
diff --git a/src/screen.c b/src/screen.c
index dec512a..f46e3ca 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -19,23 +19,27 @@
*/
#include "ratpoison.h"
+#include <string.h>
+#include <X11/cursorfont.h>
+
+static void init_screen (rp_screen *s, int screen_num);
int
screen_width (rp_screen *s)
{
- return DisplayWidth (dpy, s->screen_num) - defaults.padding_right - defaults.padding_left;
+ return s->width - defaults.padding_right - defaults.padding_left;
}
int
screen_height (rp_screen *s)
{
- return DisplayHeight (dpy, s->screen_num) - defaults.padding_bottom - defaults.padding_top;
+ return s->height - defaults.padding_bottom - defaults.padding_top;
}
int
screen_left (rp_screen *s)
{
- return defaults.padding_left;
+ return s->left + defaults.padding_left;
}
int
@@ -47,7 +51,7 @@ screen_right (rp_screen *s)
int
screen_top (rp_screen *s)
{
- return defaults.padding_top;
+ return s->top + defaults.padding_top;
}
int
@@ -116,3 +120,210 @@ screen_get_frame (rp_screen *s, int frame_num)
return NULL;
}
+
+/* Given a root window, return the rp_screen struct */
+rp_screen *
+find_screen (Window w)
+{
+ int i;
+
+ for (i=0; i<num_screens; i++)
+ if (screens[i].root == w) return &screens[i];
+
+ return NULL;
+ }
+
+void
+init_screens (int screen_arg, int screen_num)
+{
+ int i;
+
+ /* Get the number of screens */
+ if (rp_have_xinerama)
+ num_screens = xine_screen_count;
+ else
+ num_screens = ScreenCount (dpy);
+
+ /* make sure the screen specified is valid. */
+ if (screen_arg)
+ {
+ /* Using just a single Xinerama screen doesn't really make sense. So we
+ * disable Xinerama in this case.
+ */
+ if (rp_have_xinerama)
+ {
+ fprintf (stderr, "Warning: selecting a specific Xinerama screen is not implemented.\n");
+ rp_have_xinerama = 0;
+ screen_num = 0;
+ num_screens = ScreenCount(dpy);
+ }
+
+ if (screen_num < 0 || screen_num >= num_screens)
+ {
+ fprintf (stderr, "%d is an invalid screen for the display\n", screen_num);
+ exit (EXIT_FAILURE);
+ }
+
+ /* we're only going to use one screen. */
+ num_screens = 1;
+ }
+
+ /* Initialize the screens */
+ screens = (rp_screen *)xmalloc (sizeof (rp_screen) * num_screens);
+ PRINT_DEBUG (("%d screens.\n", num_screens));
+
+ if (screen_arg)
+ {
+ init_screen (&screens[0], screen_num);
+ }
+ else
+ {
+ for (i=0; i<num_screens; i++)
+ {
+ init_screen (&screens[i], i);
+ }
+ }
+
+}
+
+static void
+init_rat_cursor (rp_screen *s)
+{
+ s->rat = XCreateFontCursor( dpy, XC_icon );
+}
+
+static void
+init_screen (rp_screen *s, int screen_num)
+{
+ XGCValues gv;
+ int xine_screen_num;
+
+ /* We use screen_num below to refer to the real X screen number, but
+ * if we're using Xinerama, it will only be the Xinerama logical screen
+ * number. So we shuffle it away and replace it with the real one now,
+ * to cause confusion. -- CP
+ */
+ if (rp_have_xinerama)
+ {
+ xine_screen_num = screen_num;
+ screen_num = DefaultScreen(dpy);
+ xinerama_get_screen_info(xine_screen_num,
+ &s->left, &s->top, &s->width, &s->height);
+ }
+ else
+ {
+ xine_screen_num = screen_num;
+ s->left = 0;
+ s->top = 0;
+ s->width = DisplayWidth(dpy, screen_num);
+ s->height = DisplayHeight(dpy, screen_num);
+ }
+
+ /* Select on some events on the root window, if this fails, then
+ there is already a WM running and the X Error handler will catch
+ it, terminating ratpoison. */
+ XSelectInput(dpy, RootWindow (dpy, screen_num),
+ PropertyChangeMask | ColormapChangeMask
+ | SubstructureRedirectMask | SubstructureNotifyMask );
+ XSync (dpy, False);
+
+ /* Create the numset for the frames. */
+ s->frames_numset = numset_new ();
+
+ /* Build the display string for each screen */
+ s->display_string = xmalloc (strlen(DisplayString (dpy)) + 21);
+ sprintf (s->display_string, "DISPLAY=%s", DisplayString (dpy));
+ if (strrchr (DisplayString (dpy), ':'))
+ {
+ char *dot;
+
+ dot = strrchr(s->display_string, '.');
+ if (dot)
+ sprintf(dot, ".%i", screen_num);
+ }
+
+ PRINT_DEBUG (("%s\n", s->display_string));
+
+ s->screen_num = screen_num;
+ s->xine_screen_num = xine_screen_num;
+ s->root = RootWindow (dpy, screen_num);
+ s->def_cmap = DefaultColormap (dpy, screen_num);
+
+ init_rat_cursor (s);
+
+ s->fg_color = BlackPixel (dpy, s->screen_num);
+ s->bg_color = WhitePixel (dpy, s->screen_num);
+
+ /* Setup the GC for drawing the font. */
+ gv.foreground = s->fg_color;
+ gv.background = s->bg_color;
+ gv.function = GXcopy;
+ gv.line_width = 1;
+ gv.subwindow_mode = IncludeInferiors;
+ gv.font = defaults.font->fid;
+ s->normal_gc = XCreateGC(dpy, s->root,
+ GCForeground | GCBackground | GCFunction
+ | GCLineWidth | GCSubwindowMode | GCFont,
+ &gv);
+
+ /* Create the program bar window. */
+ s->bar_is_raised = 0;
+ s->bar_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1,
+ defaults.bar_border_width,
+ s->fg_color, s->bg_color);
+
+ /* Setup the window that will receive all keystrokes once the prefix
+ key has been pressed. */
+ s->key_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, 0,
+ WhitePixel (dpy, s->screen_num),
+ BlackPixel (dpy, s->screen_num));
+ XSelectInput (dpy, s->key_window, KeyPressMask | KeyReleaseMask);
+ XMapWindow (dpy, s->key_window);
+
+ /* Create the input window. */
+ s->input_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1,
+ defaults.bar_border_width,
+ s->fg_color, s->bg_color);
+ XSelectInput (dpy, s->input_window, KeyPressMask | KeyReleaseMask);
+
+ /* Create the frame indicator window */
+ s->frame_window = XCreateSimpleWindow (dpy, s->root, 1, 1, 1, 1, defaults.bar_border_width,
+ s->fg_color, s->bg_color);
+
+ /* Create the help window */
+ s->help_window = XCreateSimpleWindow (dpy, s->root, s->left, s->top, s->width,
+ s->height, 0, s->fg_color, s->bg_color);
+ XSelectInput (dpy, s->help_window, KeyPressMask);
+
+ XSync (dpy, 0);
+}
+
+static int
+is_rp_window_for_given_screen (Window w, rp_screen *s)
+{
+ if (w != s->key_window &&
+ w != s->bar_window &&
+ w != s->input_window &&
+ w != s->frame_window &&
+ w != s->help_window)
+ return 0;
+ return 1;
+}
+
+int
+is_rp_window_for_screen(Window w, rp_screen *s)
+{
+ int i;
+
+ if (rp_have_xinerama)
+ {
+ for (i=0; i<num_screens; i++)
+ if (is_rp_window_for_given_screen(w, &screens[i])) return 1;
+ return 0;
+ }
+ else
+ {
+ return is_rp_window_for_given_screen(w, s);
+ }
+}
+
diff --git a/src/screen.h b/src/screen.h
index 35ccdd7..7d41901 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -33,4 +33,8 @@ void screen_restore_frameset (rp_screen *s, struct list_head *head);
void frameset_free (struct list_head *head);
rp_frame *screen_get_frame (rp_screen *s, int frame_num);
+void init_screens (int screen_arg, int screen_num);
+
+int is_rp_window_for_screen (Window w, rp_screen *s);
+
#endif
diff --git a/src/split.c b/src/split.c
index 2dcd6ed..787c587 100644
--- a/src/split.c
+++ b/src/split.c
@@ -29,6 +29,8 @@
#define VERTICALLY 0
#define HORIZONTALLY 1
+static rp_screen *frames_screen(rp_frame *);
+
static void
update_last_access (rp_frame *frame)
{
@@ -81,8 +83,8 @@ cleanup_frame (rp_frame *frame)
#ifdef MAXSIZE_WINDOWS_ARE_TRANSIENTS
if (!win->transient
&& !(win->hints->flags & PMaxSize
- && win->hints->max_width < win->scr->root_attr.width
- && win->hints->max_height < win->scr->root_attr.height))
+ && win->hints->max_width < win->scr->width
+ && win->hints->max_height < win->scr->height))
#else
if (!win->transient)
#endif
@@ -99,6 +101,11 @@ set_frames_window (rp_frame *frame, rp_window *win)
{
frame->win_number = win->number;
win->frame_number = frame->number;
+
+ /* We need to make sure that win and frame are on the same screen,
+ * since with Xinerama, windows can move from one screen to another.
+ */
+ win->scr = frames_screen(frame);
}
else
{
@@ -272,7 +279,7 @@ find_window_for_frame (rp_frame *frame)
list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
{
- if (cur->win->scr == s
+ if ((cur->win->scr == s || rp_have_xinerama)
&& cur->win != current_window()
&& !find_windows_frame (cur->win)
&& cur->win->last_access >= last_access
@@ -840,7 +847,7 @@ set_active_frame (rp_frame *frame)
s->current_frame = frame->number;
/* If frame->win == NULL, then rp_current_screen is not updated. */
- rp_current_screen = s->screen_num;
+ rp_current_screen = s->xine_screen_num;
update_bar (s);
@@ -913,9 +920,14 @@ show_frame_message (char *msg)
width = defaults.bar_x_padding * 2 + XTextWidth (defaults.font, msg, strlen (msg));
height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2);
+ /* We don't want another frame indicator to be displayed on another
+ * screen at the same time, so we hide it before bringing it back again.
+ */
+ hide_frame_indicator ();
+
XMoveResizeWindow (dpy, s->frame_window,
- frame->x + frame->width / 2 - width / 2,
- frame->y + frame->height / 2 - height / 2,
+ s->left + frame->x + frame->width / 2 - width / 2,
+ s->top + frame->y + frame->height / 2 - height / 2,
width, height);
XMapRaised (dpy, s->frame_window);
diff --git a/src/window.c b/src/window.c
index 1ac063c..c39142a 100644
--- a/src/window.c
+++ b/src/window.c
@@ -320,6 +320,11 @@ give_window_focus (rp_window *win, rp_window *last_win)
we can track which window was last accessed. */
static int counter = 1;
+ /* Warp the cursor to the window's saved position if last_win and
+ win are different windows. */
+ if (last_win != NULL && win != last_win)
+ save_mouse_position (last_win);
+
if (win == NULL) return;
counter++;
@@ -327,11 +332,6 @@ give_window_focus (rp_window *win, rp_window *last_win)
unhide_window (win);
- /* Warp the cursor to the window's saved position if last_win and
- win are different windows. */
- if (last_win != NULL && win != last_win)
- save_mouse_position (last_win);
-
if (defaults.warp)
{
PRINT_DEBUG (("Warp pointer\n"));
@@ -344,7 +344,7 @@ give_window_focus (rp_window *win, rp_window *last_win)
XInstallColormap (dpy, win->colormap);
/* Finally, give the window focus */
- rp_current_screen = win->scr->screen_num;
+ rp_current_screen = win->scr->xine_screen_num;
set_rp_window_focus (win);
XSync (dpy, False);
@@ -464,7 +464,17 @@ set_active_window (rp_window *win)
if (win == NULL) return;
- frame = screen_get_frame (win->scr, win->scr->current_frame);
+ /* With Xinerama, we can move a window over to the current screen; otherwise
+ * we have to switch to the screen that the window belongs to.
+ */
+ if (rp_have_xinerama)
+ {
+ frame = screen_get_frame (current_screen(), current_screen()->current_frame);
+ }
+ else
+ {
+ frame = screen_get_frame (win->scr, win->scr->current_frame);
+ }
last_win = set_frames_window (frame, win);
if (last_win) PRINT_DEBUG (("last window: %s\n", window_name (last_win)));
@@ -481,8 +491,8 @@ set_active_window (rp_window *win)
#ifdef MAXSIZE_WINDOWS_ARE_TRANSIENTS
if (!win->transient
&& !(win->hints->flags & PMaxSize
- && (win->hints->max_width < win->scr->root_attr.width
- || win->hints->max_height < win->scr->root_attr.height)))
+ && (win->hints->max_width < win->scr->width
+ || win->hints->max_height < win->scr->height)))
#else
if (!win->transient)
#endif