From b0839d05a60e59dfa2722e13586a4857a295d4fd Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Sat, 12 Nov 2016 17:58:24 +0100 Subject: Add xrandr support Drop deprecated xinerama support and replace it with xrandr. Signed-off-by: Mathieu OTHACEHE --- configure.ac | 21 ++- src/Makefile.am | 8 +- src/actions.c | 337 ++++++++++++++++++++++-------------------- src/bar.c | 8 +- src/communications.c | 11 +- src/communications.h | 2 +- src/data.h | 21 ++- src/events.c | 82 ++++------- src/format.c | 10 +- src/globals.c | 31 ++-- src/globals.h | 13 +- src/group.c | 18 +-- src/input.c | 10 +- src/linkedlist.c | 139 ++++++++++++++++++ src/linkedlist.h | 6 + src/main.c | 98 +++---------- src/manage.c | 22 +-- src/ratpoison.h | 2 +- src/screen.c | 404 +++++++++++++++++++++++++++++++++++---------------- src/screen.h | 21 ++- src/split.c | 105 +++++++------ src/split.h | 2 +- src/window.c | 60 ++++---- src/window.h | 1 + src/xinerama.c | 104 ------------- src/xinerama.h | 28 ---- src/xrandr.c | 204 ++++++++++++++++++++++++++ src/xrandr.h | 32 ++++ 28 files changed, 1091 insertions(+), 709 deletions(-) delete mode 100644 src/xinerama.c delete mode 100644 src/xinerama.h create mode 100644 src/xrandr.c create mode 100644 src/xrandr.h diff --git a/configure.ac b/configure.ac index 7c2bc83..7e101e7 100644 --- a/configure.ac +++ b/configure.ac @@ -156,13 +156,6 @@ AC_SUBST(HISTORY_LIBS) AC_CHECK_LIB(X11, XOpenDisplay, [X_LIBS="-lX11 $X_LIBS"], AC_MSG_ERROR([*** Can't find libX11]),$X_LIBS $X_EXTRA_LIBS) -mysavedCPPFLAGS="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS $X_CFLAGS" -AC_CHECK_HEADERS([X11/extensions/Xinerama.h], [], [], [ -#include -]) -CPPFLAGS="$mysavedCPPFLAGS" - mysavedCPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $X_CFLAGS" AC_CHECK_HEADERS([X11/XKBlib.h], [], [], [ @@ -171,7 +164,19 @@ AC_CHECK_HEADERS([X11/XKBlib.h], [], [], [ CPPFLAGS="$mysavedCPPFLAGS" AC_CHECK_LIB(Xext, XMissingExtension, [X_LIBS="-lXext $X_LIBS"],,$X_LIBS $X_EXTRA_LIBS) -AC_CHECK_LIB(Xinerama, XineramaQueryScreens, [X_LIBS="-lXinerama $X_LIBS"; AC_DEFINE(HAVE_LIBXINERAMA,1,[Xinerama])],,$X_LIBS $X_EXTRA_LIBS) + +AC_ARG_WITH([xrandr], +[AS_HELP_STRING([--without-xrandr], [Build without xrandr support, even if available])], +[], +[with_xrandr=yes]) + +compile_xrandr=no +AS_IF([test "$with_xrandr" != no], +[AC_CHECK_LIB(Xrandr, XRRGetScreenResources, [compile_xrandr=yes X_LIBS="-lXrandr $X_LIBS" AC_DEFINE(HAVE_LIBXRANDR, 1, [Xrandr])],,$X_LIBS $X_EXTRA_LIBS)] +[]) + +AM_CONDITIONAL(HAVE_LIBXRANDR, test "$compile_xrandr" = yes) + AC_CHECK_LIB(Xtst, XTestFakeButtonEvent, [X_LIBS="-lXtst $X_LIBS"; AC_DEFINE(HAVE_LIBXTST,1,[Xtst])],,$X_LIBS $X_EXTRA_LIBS) AC_CHECK_LIB([X11], [XkbKeycodeToKeysym], [AC_DEFINE(HAVE_XKBKEYCODETOKEYSYM, 1, diff --git a/src/Makefile.am b/src/Makefile.am index 3ba6de3..0daf587 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,6 +70,8 @@ ratpoison_SOURCES = actions.c \ split.c \ split.h \ window.c \ - window.h \ - xinerama.c \ - xinerama.h + window.h + +if HAVE_LIBXRANDR +ratpoison_SOURCES += xrandr.c xrandr.h +endif diff --git a/src/actions.c b/src/actions.c index 3aef26b..acfb466 100644 --- a/src/actions.c +++ b/src/actions.c @@ -477,7 +477,7 @@ push_frame_undo(rp_screen *screen) static rp_frame_undo * pop_frame_list (struct list_head *undo_list, struct list_head *redo_list) { - rp_screen *screen = current_screen(); + rp_screen *screen = rp_current_screen; rp_frame_undo *first, *new; /* Is there something to restore? */ @@ -1038,9 +1038,9 @@ parse_keydesc (char *keydesc, struct rp_key *key) static void grab_rat (void) { - XGrabPointer (dpy, current_screen()->root, True, 0, + XGrabPointer (dpy, rp_current_screen->root, True, 0, GrabModeAsync, GrabModeAsync, - None, current_screen()->rat, CurrentTime); + None, rp_current_screen->rat, CurrentTime); } static void @@ -1282,7 +1282,7 @@ cmd_other (int interactive UNUSED, struct cmdarg **args UNUSED) rp_window *w; /* w = find_window_other (); */ - w = group_last_window (rp_current_group, current_screen()); + w = group_last_window (rp_current_group, rp_current_screen); if (!w) return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW); @@ -1410,7 +1410,7 @@ cmd_select (int interactive, struct cmdarg **args) if (interactive) { /* show the window list as feedback */ - show_bar (current_screen (), defaults.window_fmt); + show_bar (rp_current_screen, defaults.window_fmt); ret = cmdret_new (RET_SUCCESS, NULL); } else @@ -1458,7 +1458,7 @@ cmd_rename (int interactive UNUSED, struct cmdarg **args) hook_run (&rp_title_changed_hook); /* Update the program bar. */ - update_window_names (current_screen(), defaults.window_fmt); + update_window_names (rp_current_screen, defaults.window_fmt); return cmdret_new (RET_SUCCESS, NULL); } @@ -1791,45 +1791,48 @@ read_frame (struct sbuf *s, struct cmdarg **arg) int keysym_bufsize = sizeof (keysym_buf); unsigned int mod; Window *wins; - int i, j; - rp_frame *cur; + int i; + rp_frame *cur_frame; + rp_screen *cur_screen; int frames; if (s == NULL) { frames = 0; - for (j=0; jfg_color; - attr.background_pixel = screen->bg_color; + attr.border_pixel = rp_glob_screen.fg_color; + attr.background_pixel = rp_glob_screen.bg_color; attr.override_redirect = True; - list_for_each_entry (cur, &screen->frames, node) + list_for_each_entry (cur_frame, &cur_screen->frames, node) { int width, height; char *num; /* Create the string to be displayed in the window and determine the height and width of the window. */ - /* num = xsprintf (" %d ", cur->number); */ - num = frame_selector (cur->number); - width = defaults.bar_x_padding * 2 + rp_text_width (screen, num, -1); - height = (FONT_HEIGHT (screen) + defaults.bar_y_padding * 2); + /* num = xsprintf (" %d ", cur_frame->number); */ + num = frame_selector (cur_frame->number); + width = defaults.bar_x_padding * 2 + rp_text_width (cur_screen, num, -1); + height = (FONT_HEIGHT (cur_screen) + defaults.bar_y_padding * 2); /* Create and map the window. */ - wins[i] = XCreateWindow (dpy, screen->root, screen->left + cur->x, screen->top + cur->y, width, height, 1, + wins[i] = XCreateWindow (dpy, cur_screen->root, cur_screen->left + cur_frame->x, cur_screen->top + cur_frame->y, width, height, 1, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect | CWBorderPixel | CWBackPixel, &attr); @@ -1837,9 +1840,9 @@ read_frame (struct sbuf *s, struct cmdarg **arg) XClearWindow (dpy, wins[i]); /* Display the frame's number inside the window. */ - rp_draw_string (screen, wins[i], STYLE_NORMAL, + rp_draw_string (cur_screen, wins[i], STYLE_NORMAL, defaults.bar_x_padding, - defaults.bar_y_padding + FONT_ASCENT(screen), + defaults.bar_y_padding + FONT_ASCENT(cur_screen), num, -1); free (num); @@ -2684,7 +2687,7 @@ spawn(char *cmd, int raw, rp_frame *frame) { /* Some process setup to make sure the spawned process runs in its own session. */ - putenv(current_screen()->display_string); + putenv(rp_current_screen->display_string); #ifdef HAVE_SETSID if (setsid() == -1) #endif @@ -2725,7 +2728,7 @@ spawn(char *cmd, int raw, rp_frame *frame) child->terminated = 0; child->frame = frame; child->group = rp_current_group; - child->screen = current_screen(); + child->screen = rp_current_screen; child->window_mapped = 0; list_add (&child->node, &rp_children); @@ -2833,7 +2836,7 @@ cmd_windows (int interactive, struct cmdarg **args) if (interactive) { - s = current_screen (); + s = rp_current_screen; /* This is a yukky hack. If the bar already hidden then show the bar. This handles the case when msgwait is 0 (the bar sticks) and the user uses this command to toggle the bar on and @@ -2961,7 +2964,7 @@ cmd_v_split (int interactive UNUSED, struct cmdarg **args) rp_frame *frame; int pixels; - push_frame_undo (current_screen()); /* fdump to stack */ + push_frame_undo (rp_current_screen); /* fdump to stack */ frame = current_frame(); /* Default to dividing the frame in half. */ @@ -2989,7 +2992,7 @@ cmd_h_split (int interactive UNUSED, struct cmdarg **args) rp_frame *frame; int pixels; - push_frame_undo (current_screen()); /* fdump to stack */ + push_frame_undo (rp_current_screen); /* fdump to stack */ frame = current_frame(); /* Default to dividing the frame in half. */ @@ -3013,7 +3016,7 @@ cmd_h_split (int interactive UNUSED, struct cmdarg **args) cmdret * cmd_only (int interactive UNUSED, struct cmdarg **args UNUSED) { - push_frame_undo (current_screen()); /* fdump to stack */ + push_frame_undo (rp_current_screen); /* fdump to stack */ remove_all_splits(); maximize (current_window()); @@ -3023,10 +3026,10 @@ cmd_only (int interactive UNUSED, struct cmdarg **args UNUSED) cmdret * cmd_remove (int interactive UNUSED, struct cmdarg **args UNUSED) { - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; rp_frame *frame; - push_frame_undo (current_screen()); /* fdump to stack */ + push_frame_undo (rp_current_screen); /* fdump to stack */ if (num_frames(s) <= 1) { @@ -3048,7 +3051,7 @@ cmd_remove (int interactive UNUSED, struct cmdarg **args UNUSED) cmdret * cmd_shrink (int interactive UNUSED, struct cmdarg **args UNUSED) { - push_frame_undo (current_screen()); /* fdump to stack */ + push_frame_undo (rp_current_screen); /* fdump to stack */ resize_shrink_to_window (current_frame()); return cmdret_new (RET_SUCCESS, NULL); } @@ -3090,7 +3093,7 @@ static resize_binding resize_bindings[] = cmdret * cmd_resize (int interactive, struct cmdarg **args) { - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; /* If the user calls resize with arguments, treat it like the non-interactive version. */ @@ -3198,7 +3201,7 @@ cmd_banish (int interactive UNUSED, struct cmdarg **args UNUSED) { rp_screen *s; - s = current_screen (); + s = rp_current_screen; XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2); return cmdret_new (RET_SUCCESS, NULL); @@ -3207,7 +3210,7 @@ cmd_banish (int interactive UNUSED, struct cmdarg **args UNUSED) cmdret * cmd_banishrel (int interactive UNUSED, struct cmdarg **args UNUSED) { - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; rp_window *w = current_window(); rp_frame *f = current_frame(); @@ -3227,7 +3230,7 @@ cmd_ratinfo (int interactive UNUSED, struct cmdarg **args UNUSED) int mouse_x, mouse_y, root_x, root_y; unsigned int mask; - s = current_screen(); + s = rp_current_screen; XQueryPointer (dpy, s->root, &root_win, &child_win, &mouse_x, &mouse_y, &root_x, &root_y, &mask); return cmdret_new (RET_SUCCESS, "%d %d", mouse_x, mouse_y); @@ -3243,7 +3246,7 @@ cmd_ratrelinfo (int interactive UNUSED, struct cmdarg **args UNUSED) int mouse_x, mouse_y, root_x, root_y; unsigned int mask; - s = current_screen(); + s = rp_current_screen; rpw = current_window(); f = current_frame(); @@ -3264,7 +3267,7 @@ cmd_ratwarp (int interactive UNUSED, struct cmdarg **args) { rp_screen *s; - s = current_screen (); + s = rp_current_screen; XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, ARG(0,number), ARG(1,number)); return cmdret_new (RET_SUCCESS, NULL); } @@ -3340,7 +3343,7 @@ cmd_curframe (int interactive, struct cmdarg **args UNUSED) cmdret * cmd_license (int interactive UNUSED, struct cmdarg **args UNUSED) { - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; int x = 10; int y = 10; int i; @@ -3416,7 +3419,7 @@ cmd_license (int interactive UNUSED, struct cmdarg **args UNUSED) } /* The help window overlaps the bar, so redraw it. */ - if (current_screen()->bar_is_raised) + if (rp_current_screen->bar_is_raised) redraw_last_message(); return cmdret_new (RET_SUCCESS, NULL); @@ -3434,7 +3437,7 @@ cmd_help (int interactive, struct cmdarg **args) if (interactive) { - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; int i, old_i; int x = 10; int y = 0; @@ -3551,7 +3554,7 @@ cmd_help (int interactive, struct cmdarg **args) } /* The help window overlaps the bar, so redraw it. */ - if (current_screen()->bar_is_raised) + if (rp_current_screen->bar_is_raised) redraw_last_message(); return cmdret_new (RET_SUCCESS, NULL); @@ -3745,8 +3748,8 @@ update_gc (rp_screen *s) { XGCValues gcv; - gcv.foreground = s->fg_color; - gcv.background = s->bg_color; + gcv.foreground = rp_glob_screen.fg_color; + gcv.background = rp_glob_screen.bg_color; gcv.function = GXcopy; gcv.line_width = 1; gcv.subwindow_mode = IncludeInferiors; @@ -3755,8 +3758,8 @@ update_gc (rp_screen *s) GCForeground | GCBackground | GCFunction | GCLineWidth | GCSubwindowMode, &gcv); - gcv.foreground = s->bg_color; - gcv.background = s->fg_color; + gcv.foreground = rp_glob_screen.bg_color; + gcv.background = rp_glob_screen.fg_color; XFreeGC (dpy, s->inverse_gc); s->inverse_gc = XCreateGC(dpy, s->root, GCForeground | GCBackground @@ -3769,10 +3772,11 @@ static void update_all_gcs (void) { int i; + rp_screen *cur; - for (i=0; iframes),node) + list_for_each_entry (frame,&(rp_current_screen->frames),node) { int bk_pos, bk_len; @@ -3899,8 +3903,8 @@ set_padding (struct cmdarg **args) frame->width += bk_pos - l; } - 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; + if ((bk_pos + bk_len) == (rp_current_screen->left + rp_current_screen->width - defaults.padding_right)) + frame->width = rp_current_screen->left + rp_current_screen->width - r - frame->x; /* Resize vertically. */ bk_pos = frame->y; @@ -3912,8 +3916,8 @@ set_padding (struct cmdarg **args) frame->height += bk_pos - t; } - 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; + if ((bk_pos + bk_len) == (rp_current_screen->top + rp_current_screen->height - defaults.padding_bottom)) + frame->height = rp_current_screen->top + rp_current_screen->height - b - frame->y; maximize_all_windows_in_frame (frame); } @@ -3952,7 +3956,7 @@ set_border (struct cmdarg **args) static cmdret * set_barborder (struct cmdarg **args) { - int i; + rp_screen *cur; if (args[0] == NULL) return cmdret_new (RET_SUCCESS, "%d", defaults.bar_border_width); @@ -3963,11 +3967,11 @@ set_barborder (struct cmdarg **args) defaults.bar_border_width = ARG(0,number); /* Update the frame and bar windows. */ - for (i=0; ibar_window, defaults.bar_border_width); + XSetWindowBorderWidth (dpy, cur->frame_window, defaults.bar_border_width); + XSetWindowBorderWidth (dpy, cur->input_window, defaults.bar_border_width); } return cmdret_new (RET_SUCCESS, NULL); @@ -4108,28 +4112,28 @@ set_framefmt (struct cmdarg **args) static cmdret * set_fgcolor (struct cmdarg **args) { - int i; XColor color, junk; + rp_screen *cur; if (args[0] == NULL) return cmdret_new (RET_SUCCESS, "%s", defaults.fgcolor_string); - for (i=0; idef_cmap, ARG_STRING(0), &color, &junk)) return cmdret_new (RET_FAILURE, "set fgcolor: unknown color"); - screens[i].fg_color = color.pixel; - update_gc (&screens[i]); - XSetWindowBorder (dpy, screens[i].bar_window, color.pixel); - XSetWindowBorder (dpy, screens[i].input_window, color.pixel); - XSetWindowBorder (dpy, screens[i].frame_window, color.pixel); - XSetWindowBorder (dpy, screens[i].help_window, color.pixel); + rp_glob_screen.fg_color = color.pixel; + update_gc (cur); + XSetWindowBorder (dpy, cur->bar_window, color.pixel); + XSetWindowBorder (dpy, cur->input_window, color.pixel); + XSetWindowBorder (dpy, cur->frame_window, color.pixel); + XSetWindowBorder (dpy, cur->help_window, color.pixel); #ifdef USE_XFT_FONT - if (!XftColorAllocName (dpy, DefaultVisual (dpy, screens[i].screen_num), - DefaultColormap (dpy, screens[i].screen_num), - ARG_STRING(0), &screens[i].xft_fg_color)) + if (!XftColorAllocName (dpy, DefaultVisual (dpy, cur->screen_num), + DefaultColormap (dpy, cur->screen_num), + ARG_STRING(0), &cur->xft_fg_color)) return cmdret_new (RET_FAILURE, "set fgcolor: unknown color"); #endif @@ -4143,28 +4147,29 @@ set_fgcolor (struct cmdarg **args) static cmdret * set_bgcolor (struct cmdarg **args) { - int i; XColor color, junk; + rp_screen *cur; if (args[0] == NULL) return cmdret_new (RET_SUCCESS, "%s", defaults.bgcolor_string); - for (i=0; idef_cmap, ARG_STRING(0), &color, &junk)) return cmdret_new (RET_FAILURE, "set bgcolor: unknown color"); - screens[i].bg_color = color.pixel; - update_gc (&screens[i]); - XSetWindowBackground (dpy, screens[i].bar_window, color.pixel); - XSetWindowBackground (dpy, screens[i].input_window, color.pixel); - XSetWindowBackground (dpy, screens[i].frame_window, color.pixel); - XSetWindowBackground (dpy, screens[i].help_window, color.pixel); + rp_glob_screen.bg_color = color.pixel; + update_gc (cur); + XSetWindowBackground (dpy, cur->bar_window, color.pixel); + XSetWindowBackground (dpy, cur->input_window, color.pixel); + XSetWindowBackground (dpy, cur->frame_window, color.pixel); + XSetWindowBackground (dpy, cur->help_window, color.pixel); #ifdef USE_XFT_FONT - if (!XftColorAllocName (dpy, DefaultVisual (dpy, screens[i].screen_num), - DefaultColormap (dpy, screens[i].screen_num), - ARG_STRING(0), &screens[i].xft_bg_color)) + if (!XftColorAllocName (dpy, DefaultVisual (dpy, cur->screen_num), + DefaultColormap (dpy, cur->screen_num), + ARG_STRING(0), &cur->xft_bg_color)) return cmdret_new (RET_FAILURE, "set fgcolor: unknown color"); #endif @@ -4178,20 +4183,20 @@ set_bgcolor (struct cmdarg **args) static cmdret * set_fwcolor (struct cmdarg **args) { - int i; XColor color, junk; rp_window *win = current_window(); + rp_screen *cur; if (args[0] == NULL) return cmdret_new (RET_SUCCESS, "%s", defaults.fwcolor_string); - for (i=0; idef_cmap, ARG_STRING(0), &color, &junk)) return cmdret_new (RET_FAILURE, "set fwcolor: unknown color"); - screens[i].fw_color = color.pixel; - update_gc (&screens[i]); + rp_glob_screen.fw_color = color.pixel; + update_gc (cur); free (defaults.fwcolor_string); defaults.fwcolor_string = xstrdup (ARG_STRING(0)); @@ -4199,7 +4204,7 @@ set_fwcolor (struct cmdarg **args) /* Update current window. */ if (win != NULL) - XSetWindowBorder (dpy, win->w, win->scr->fw_color); + XSetWindowBorder (dpy, win->w, rp_glob_screen.fw_color); return cmdret_new (RET_SUCCESS, NULL); } @@ -4207,20 +4212,20 @@ set_fwcolor (struct cmdarg **args) static cmdret * set_bwcolor (struct cmdarg **args) { - int i; XColor color, junk; - rp_window *win, *cur = current_window(); + rp_window *win, *cur_win = current_window(); + rp_screen *cur_screen; if (args[0] == NULL) return cmdret_new (RET_SUCCESS, "%s", defaults.bwcolor_string); - for (i=0; idef_cmap, ARG_STRING(0), &color, &junk)) return cmdret_new (RET_FAILURE, "set bwcolor: unknown color"); - screens[i].bw_color = color.pixel; - update_gc (&screens[i]); + rp_glob_screen.bw_color = color.pixel; + update_gc (cur_screen); free (defaults.bwcolor_string); defaults.bwcolor_string = xstrdup (ARG_STRING(0)); @@ -4229,8 +4234,8 @@ set_bwcolor (struct cmdarg **args) /* Update all the visible windows. */ list_for_each_entry (win,&rp_mapped_window,node) { - if (win != cur) - XSetWindowBorder (dpy, win->w, win->scr->bw_color); + if (win != cur_win) + XSetWindowBorder (dpy, win->w, rp_glob_screen.bw_color); } @@ -4490,7 +4495,7 @@ cmd_swap (int interactive UNUSED, struct cmdarg **args) dest_frame = ARG(0, frame); src_frame = args[1] ? ARG (1, frame) : current_frame(); - if (!rp_have_xinerama) + if (!rp_have_xrandr) { s = frames_screen(src_frame); if (screen_find_frame_by_frame(s, dest_frame) == NULL) @@ -4622,17 +4627,18 @@ cmd_unalias (int interactive UNUSED, struct cmdarg **args) cmdret * cmd_nextscreen (int interactive UNUSED, struct cmdarg **args UNUSED) { - int new_screen; + rp_screen *new_screen; + rp_frame *new_frame; + + new_screen = screen_next (); /* No need to go through the motions when we don't have to. */ - if (num_screens <= 1) + if (screen_count() <= 1 || new_screen == rp_current_screen) return cmdret_new (RET_FAILURE, "nextscreen: no other screen"); - new_screen = rp_current_screen + 1; - if (new_screen >= num_screens) - new_screen = 0; + new_frame = screen_get_frame (new_screen, new_screen->current_frame); - set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame), 1); + set_active_frame (new_frame, 1); return cmdret_new (RET_SUCCESS, NULL); } @@ -4640,17 +4646,18 @@ cmd_nextscreen (int interactive UNUSED, struct cmdarg **args UNUSED) cmdret * cmd_prevscreen (int interactive UNUSED, struct cmdarg **args UNUSED) { - int new_screen; + rp_screen *new_screen; + rp_frame *new_frame; + + new_screen = screen_prev (); /* No need to go through the motions when we don't have to. */ - if (num_screens <= 1) + if (screen_count () <= 1 || new_screen == rp_current_screen) return cmdret_new (RET_SUCCESS, "prevscreen: no other screen"); - new_screen = rp_current_screen - 1; - if (new_screen < 0) - new_screen = num_screens - 1; + new_frame = screen_get_frame (new_screen, new_screen->current_frame); - set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame), 1); + set_active_frame (new_frame, 1); return cmdret_new (RET_SUCCESS, NULL); } @@ -4659,15 +4666,23 @@ cmdret * cmd_sselect(int interactive UNUSED, struct cmdarg **args) { int new_screen; + rp_frame *new_frame; + rp_screen *screen; new_screen = ARG(0,number); if (new_screen < 0) return cmdret_new (RET_FAILURE, "sselect: out of range"); - if (new_screen < num_screens) - set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame), 1); + if (new_screen < screen_count ()) + { + screen = screen_at (new_screen); + new_frame = screen_get_frame (screen, screen->current_frame); + set_active_frame (new_frame, 1); + } else - return cmdret_new (RET_FAILURE, "sselect: out of range"); + { + return cmdret_new (RET_FAILURE, "sselect: out of range"); + } return cmdret_new (RET_SUCCESS, NULL); } @@ -4854,20 +4869,21 @@ cmd_tmpwm (int interactive UNUSED, struct cmdarg **args) { struct list_head *tmp, *iter; rp_window *win = NULL; + rp_screen *cur_screen; int child; int status; int pid; - int i; int (*old_handler)(Display *, XErrorEvent *); - push_frame_undo (current_screen()); /* fdump to stack */ + push_frame_undo (rp_current_screen); /* fdump to stack */ /* Release event selection on the root windows, so the new WM can have it. */ - for (i=0; iscreen_num), 0); + deactivate_screen (cur_screen); } /* Ungrab all our keys. */ @@ -4888,6 +4904,7 @@ cmd_tmpwm (int interactive UNUSED, struct cmdarg **args) /* Disable our SIGCHLD handler */ set_sig_handler (SIGCHLD, SIG_DFL); + /* Launch the new WM and wait for it to terminate. */ pid = spawn (ARG_STRING(0), 0, NULL); PRINT_DEBUG (("spawn pid: %d\n", pid)); @@ -4895,8 +4912,10 @@ cmd_tmpwm (int interactive UNUSED, struct cmdarg **args) { child = waitpid (pid, &status, 0); } while (child != -1 && child != pid); + /* Enable our SIGCHLD handler */ set_sig_handler (SIGCHLD, chld_handler); + /* Some processes may have quit while our sigchld handler was disabled, so check for them. */ check_child_procs(); @@ -4908,26 +4927,33 @@ cmd_tmpwm (int interactive UNUSED, struct cmdarg **args) old_handler = XSetErrorHandler (tmpwm_error_handler); do { tmpwm_error_raised = 0; - for (i=0; iscreen_num), + PropertyChangeMask | ColormapChangeMask + | SubstructureRedirectMask | SubstructureNotifyMask + | StructureNotifyMask); XSync (dpy, False); - } + } + if (tmpwm_error_raised) sleep(1); } while (tmpwm_error_raised); + XSetErrorHandler (old_handler); - for (i=0; ikey_window); + set_window_focus (rp_current_screen->key_window); /* And we're back in ratpoison. */ return cmdret_new (RET_SUCCESS, NULL); @@ -4988,7 +5014,7 @@ cmd_fdump (int interactively UNUSED, struct cmdarg **args) char *dump; if (args[0] == NULL) - screen = current_screen (); + screen = rp_current_screen; else { int snum; @@ -4996,10 +5022,10 @@ cmd_fdump (int interactively UNUSED, struct cmdarg **args) if (snum < 0) return cmdret_new (RET_FAILURE, "fdump: invalid negative screen number"); - else if (num_screens <= snum) + else if (snum >= screen_count ()) return cmdret_new (RET_FAILURE, "fdump: unknown screen"); else - screen = &screens[snum]; + screen = screen_at (snum); } dump = fdump (screen); @@ -5105,8 +5131,8 @@ frestore (char *data, rp_screen *s) cmdret * cmd_frestore (int interactively UNUSED, struct cmdarg **args) { - push_frame_undo (current_screen()); /* fdump to stack */ - return frestore (ARG_STRING(0), current_screen()); + push_frame_undo (rp_current_screen); /* fdump to stack */ + return frestore (ARG_STRING(0), rp_current_screen); } cmdret * @@ -5212,7 +5238,7 @@ cmd_gnumber (int interactive UNUSED, struct cmdarg **args) group_resort_group (g); /* Update the group list. */ - update_group_names (current_screen()); + update_group_names (rp_current_screen); } return cmdret_new (RET_SUCCESS, NULL); @@ -5226,7 +5252,7 @@ cmd_grename (int interactive UNUSED, struct cmdarg **args) group_rename (rp_current_group, ARG_STRING(0)); /* Update the group list. */ - update_group_names (current_screen()); + update_group_names (rp_current_screen); return cmdret_new (RET_SUCCESS, NULL); } @@ -5256,7 +5282,7 @@ cmd_groups (int interactive, struct cmdarg **args UNUSED) if (interactive) { - s = current_screen (); + s = rp_current_screen; /* This is a yukky hack. If the bar already hidden then show the bar. This handles the case when msgwait is 0 (the bar sticks) and the user uses this command to toggle the bar on and @@ -5571,28 +5597,29 @@ cmd_sfdump (int interactively UNUSED, struct cmdarg **args UNUSED) char screen_suffix[16]; cmdret *ret; struct sbuf *dump; - rp_frame *cur; - int i; + rp_frame *cur_frame; + rp_screen *cur_screen; dump = sbuf_new (0); - for (i = 0; i < num_screens; i++) + list_for_each_entry (cur_screen, &rp_screens, node) { snprintf (screen_suffix, sizeof (screen_suffix), " %d,", - rp_have_xinerama ? - screens[i].xine_screen_num : - screens[i].screen_num); + rp_have_xrandr ? + cur_screen->xrandr.output : + cur_screen->screen_num); - list_for_each_entry (cur, &(screens[i].frames), node) + list_for_each_entry (cur_frame, &(cur_screen->frames), node) { char *frameset; - frameset = frame_dump (cur, &screens[i]); + frameset = frame_dump (cur_frame, cur_screen); sbuf_concat (dump, frameset); sbuf_concat (dump, screen_suffix); free (frameset); } } + sbuf_chop (dump); ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (dump)); sbuf_free (dump); @@ -5602,14 +5629,16 @@ cmd_sfdump (int interactively UNUSED, struct cmdarg **args UNUSED) cmdret * cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) { - struct sbuf *buffer[num_screens]; char *copy, *ptr, *token; long screen; int out_of_screen = 0; int restored = 0; + int s_count = screen_count (); + struct sbuf *buffer[s_count]; + rp_screen *cur_screen; int i; - for (i = 0; i < num_screens; i++) + for (i = 0; i < s_count; i++) buffer[i] = sbuf_new (0); copy = xstrdup (ARG_STRING (0)); @@ -5632,7 +5661,7 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) screen = string_to_positive_int (ptr); /* check that specified screen number is valid */ - if (screen >= 0 && screen < num_screens) + if (screen >= 0 && screen < s_count) { /* clobber screen number here, frestore() doesn't need it */ *ptr = '\0'; @@ -5650,13 +5679,13 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) free (copy); /* now restore the frames for each screen */ - for (i = 0; i < num_screens; i++) + list_for_each_entry (cur_screen, &rp_screens, node) { cmdret * ret; - push_frame_undo (&screens[i]); /* fdump to stack */ + push_frame_undo (cur_screen); /* fdump to stack */ /* FIXME: store RET_SUCCESS || RET_FAILURE for each screen and output it later */ - ret = frestore (sbuf_get (buffer[i]), &screens[i]); + ret = frestore (sbuf_get (buffer[i]), cur_screen); cmdret_free (ret); sbuf_free (buffer[i]); } @@ -5675,12 +5704,12 @@ cmd_sdump (int interactive UNUSED, struct cmdarg **args UNUSED) cmdret *ret; struct sbuf *s; char *tmp; - int i; + rp_screen *cur_screen; s = sbuf_new (0); - for (i = 0; i < num_screens; ++i) + list_for_each_entry (cur_screen, &rp_screens, node) { - tmp = screen_dump (&screens[i]); + tmp = screen_dump (cur_screen); sbuf_concat (s, tmp); sbuf_concat (s, ","); free (tmp); diff --git a/src/bar.c b/src/bar.c index 0f429b8..afe6f9f 100644 --- a/src/bar.c +++ b/src/bar.c @@ -292,7 +292,7 @@ count_lines (char* msg, int len) static int max_line_length (char* msg) { - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; size_t i; size_t start; int ret = 0; @@ -512,7 +512,7 @@ static void get_mark_box (char *msg, size_t mark_start, size_t mark_end, int *x, int *y, int *width, int *height) { - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; int start, end; int mark_end_is_new_line = 0; int start_line; @@ -578,7 +578,7 @@ draw_box (rp_screen *s, int x, int y, int width, int height) GC lgc; unsigned long mask; - lgv.foreground = s->fg_color; + lgv.foreground = rp_glob_screen.fg_color; mask = GCForeground; lgc = XCreateGC(dpy, s->root, mask, &lgv); @@ -621,7 +621,7 @@ marked_message (char *msg, int mark_start, int mark_end) static void marked_message_internal (char *msg, int mark_start, int mark_end) { - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; int num_lines; int width; int height; diff --git a/src/communications.c b/src/communications.c index 76f3b98..c484a28 100644 --- a/src/communications.c +++ b/src/communications.c @@ -105,7 +105,7 @@ receive_command_result (Window w) } int -send_command (unsigned char interactive, unsigned char *cmd, int screen_num) +send_command (unsigned char interactive, unsigned char *cmd) { Window w, root; int done = 0, return_status = RET_FAILURE; @@ -114,14 +114,7 @@ send_command (unsigned char interactive, unsigned char *cmd, int screen_num) s = sbuf_new(0); sbuf_printf(s, "%c%s", interactive, cmd); - - /* If the user specified a specific screen, then send the event to - that screen. */ - if (screen_num >= 0) - root = RootWindow (dpy, screen_num); - else - root = DefaultRootWindow (dpy); - + root = RootWindow (dpy, DefaultScreen (dpy)); w = XCreateSimpleWindow (dpy, root, 0, 0, 1, 1, 0, 0, 0); /* Select first to avoid race condition */ diff --git a/src/communications.h b/src/communications.h index 6cdd33c..ae958fa 100644 --- a/src/communications.h +++ b/src/communications.h @@ -22,6 +22,6 @@ #ifndef _RATPOISON_COMMUNICATIONS_H #define _RATPOISON_COMMUNICATIONS_H 1 -int send_command (unsigned char interactive, unsigned char *cmd, int screen_num); +int send_command (unsigned char interactive, unsigned char *cmd); #endif /* ! _RATPOISON_COMMUNICATIONS_H */ diff --git a/src/data.h b/src/data.h index 85a0324..a8651c6 100644 --- a/src/data.h +++ b/src/data.h @@ -35,6 +35,7 @@ typedef struct rp_window rp_window; typedef struct rp_screen rp_screen; +typedef struct rp_global_screen rp_global_screen; typedef struct rp_action rp_action; typedef struct rp_keymap rp_keymap; typedef struct rp_frame rp_frame; @@ -149,18 +150,29 @@ struct rp_group struct list_head node; }; +struct rp_global_screen +{ + unsigned long fg_color, bg_color, fw_color, bw_color; /* The pixel color. */ +}; + +struct xrandr_info { + int output; + int crtc; + struct sbuf* name; +}; + struct rp_screen { GC normal_gc, inverse_gc; 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, fw_color, bw_color; /* The pixel color. */ - /* Here to abstract over the Xinerama vs X screens difference */ + struct xrandr_info xrandr; + + /* Here to abstract over the Xrandr vs X screens difference */ int left, top, width, height; char *display_string; @@ -176,6 +188,9 @@ struct rp_screen when you switch screens the focus doesn't get frobbed. */ int current_frame; + /* This structure can exist in a list. */ + struct list_head node; + #ifdef USE_XFT_FONT XftFont *xft_font; XftColor xft_fg_color, xft_bg_color; diff --git a/src/events.c b/src/events.c index 814e1ef..496752e 100644 --- a/src/events.c +++ b/src/events.c @@ -79,18 +79,9 @@ new_window (XCreateWindowEvent *e) 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); - } + /* New windows belong to the current screen */ + s = rp_current_screen; + if (is_rp_window_for_screen(e->window, s)) return; if (s && win == NULL @@ -137,7 +128,7 @@ unmap_notify (XEvent *ev) { cleanup_frame (frame); if (frame->number == win->scr->current_frame - && current_screen() == win->scr) + && rp_current_screen == win->scr) set_active_frame (frame, 0); /* Since we may have switched windows, call the hook. */ if (frame->win_number != EMPTY) @@ -234,7 +225,7 @@ destroy_window (XDestroyWindowEvent *ev) { cleanup_frame (frame); if (frame->number == win->scr->current_frame - && current_screen() == win->scr) + && rp_current_screen == win->scr) set_active_frame (frame, 0); /* Since we may have switched windows, call the hook. */ if (frame->win_number != EMPTY) @@ -442,11 +433,7 @@ key_press (XEvent *ev) unsigned int modifier; KeySym ks; - if (rp_have_xinerama) - s = current_screen(); - else - s = find_screen (ev->xkey.root); - + s = rp_current_screen; if (!s) return; #ifdef HIDE_MOUSE @@ -671,7 +658,7 @@ colormap_notify (XEvent *ev) win->colormap = attr.colormap; if (win == current_window() - && !current_screen()->bar_is_raised) + && !rp_current_screen->bar_is_raised) { XInstallColormap (dpy, win->colormap); } @@ -715,18 +702,6 @@ mapping_notify (XMappingEvent *ev) grab_keys_all_wins(); } -static void -configure_notify (XConfigureEvent *ev) -{ - rp_screen *s; - - s = find_screen(ev->window); - if (s != NULL) - /* This is a root window of a screen, - * look if its width or height changed: */ - screen_update(s,ev->width,ev->height); -} - /* This is called whan an application has requested the selection. Copied from rxvt. */ static void @@ -797,6 +772,11 @@ selection_clear (void) static void delegate_event (XEvent *ev) { + +#ifdef HAVE_LIBXRANDR + xrandr_notify (ev); +#endif + switch (ev->type) { case ConfigureRequest: @@ -867,11 +847,6 @@ delegate_event (XEvent *ev) selection_clear(); break; - case ConfigureNotify: - PRINT_DEBUG (("--- Handling ConfigureNotify ---\n")); - configure_notify( &ev->xconfigure ); - break; - case MapNotify: case Expose: case MotionNotify: @@ -894,14 +869,18 @@ handle_signals (void) /* An alarm means we need to hide the popup windows. */ if (alarm_signalled > 0) { - int i; + rp_screen *cur; PRINT_DEBUG (("Alarm received.\n")); /* Only hide the bar if it times out. */ if (defaults.bar_timeout > 0) - for (i=0; idisplay_string); + putenv (rp_current_screen->display_string); unhide_all_windows(); XSync(dpy, False); - for (i=0; i 0) diff --git a/src/format.c b/src/format.c index 0706f21..caf8781 100644 --- a/src/format.c +++ b/src/format.c @@ -41,7 +41,7 @@ RP_FMT(incheight); RP_FMT(incwidth); RP_FMT(gravity); RP_FMT(screen); -RP_FMT(xinescreen); +RP_FMT(xrandrscreen); RP_FMT(transient); RP_FMT(maxsize); RP_FMT(pid); @@ -72,7 +72,7 @@ struct fmt_item fmt_items[] = { { 'M', fmt_maxsize }, { 'w', fmt_width }, { 'W', fmt_incwidth }, - { 'x', fmt_xinescreen }, + { 'x', fmt_xrandrscreen}, { 0, NULL } }; @@ -218,7 +218,7 @@ fmt_status (rp_window_elem *win_elem, struct sbuf *buf) { rp_window *other_window; - other_window = find_window_other (current_screen()); + other_window = find_window_other (rp_current_screen); if (win_elem->win == other_window) sbuf_copy (buf, "+"); else if (win_elem->win == current_window()) @@ -282,9 +282,9 @@ fmt_screen (rp_window_elem *elem, struct sbuf *buf) } static void -fmt_xinescreen (rp_window_elem *elem, struct sbuf *buf) +fmt_xrandrscreen (rp_window_elem *elem, struct sbuf *buf) { - sbuf_printf_concat (buf, "%d", elem->win->scr->xine_screen_num); + sbuf_printf_concat (buf, "%d", elem->win->scr->xrandr.output); } static void diff --git a/src/globals.c b/src/globals.c index 1481a5c..23aee95 100644 --- a/src/globals.c +++ b/src/globals.c @@ -59,11 +59,14 @@ Atom _net_wm_window_type; Atom _net_wm_window_type_dialog; Atom _net_wm_name; -int rp_current_screen; -rp_screen *screens; -int num_screens; +LIST_HEAD (rp_screens); +rp_screen *rp_current_screen; +rp_global_screen rp_glob_screen; + Display *dpy; +int rp_have_xrandr; + rp_group *rp_current_group; LIST_HEAD (rp_groups); LIST_HEAD (rp_children); @@ -94,11 +97,17 @@ rp_xselection selection; static void x_export_selection (void) { + rp_screen *screen; + + list_first(screen, &rp_screens, node); + if (!screen) + return; + /* Hang the selections off screen 0's key window. */ - XSetSelectionOwner(dpy, XA_PRIMARY, screens[0].key_window, CurrentTime); - if (XGetSelectionOwner(dpy, XA_PRIMARY) != screens[0].key_window) + XSetSelectionOwner (dpy, XA_PRIMARY, screen->key_window, CurrentTime); + if (XGetSelectionOwner (dpy, XA_PRIMARY) != screen->key_window) PRINT_ERROR(("can't get primary selection")); - XChangeProperty(dpy, screens[0].root, XA_CUT_BUFFER0, xa_string, 8, + XChangeProperty(dpy, screen->root, XA_CUT_BUFFER0, xa_string, 8, PropModeReplace, (unsigned char*)selection.text, selection.len); } @@ -162,10 +171,10 @@ get_primary_selection(void) struct sbuf *s = sbuf_new(0); for (nread = 0, bytes_after = 1; bytes_after > 0; nread += ct.nitems) { - if ((XGetWindowProperty(dpy, current_screen()->input_window, rp_selection, (nread / 4), 4096, - True, AnyPropertyType, &ct.encoding, - &ct.format, &ct.nitems, &bytes_after, - &ct.value) != Success)) { + if ((XGetWindowProperty (dpy, rp_current_screen->input_window, rp_selection, (nread / 4), 4096, + True, AnyPropertyType, &ct.encoding, + &ct.format, &ct.nitems, &bytes_after, + &ct.value) != Success)) { XFree(ct.value); sbuf_free(s); return NULL; @@ -185,7 +194,7 @@ get_selection (void) { Atom property; XEvent ev; - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; int loops = 1000; /* Just insert our text, if we own the selection. */ diff --git a/src/globals.h b/src/globals.h index 1fb7e0f..f3a70d4 100644 --- a/src/globals.h +++ b/src/globals.h @@ -79,6 +79,9 @@ /* The list of groups. */ extern struct list_head rp_groups; +/* Whether or not we support xrandr */ +int rp_have_xrandr; + extern rp_group *rp_current_group; /* Each child process is stored in this list. spawn, creates a new @@ -104,9 +107,10 @@ extern struct list_head rp_mapped_window; assigned to them and are not visible/active. */ extern struct list_head rp_unmapped_window; -extern int rp_current_screen; -extern rp_screen *screens; -extern int num_screens; +/* The list of screens. */ +extern struct list_head rp_screens; +extern rp_screen *rp_current_screen; +extern rp_global_screen rp_glob_screen; extern XEvent rp_current_event; @@ -193,8 +197,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; +extern int rp_have_xrandr; extern struct numset *rp_frame_numset; diff --git a/src/group.c b/src/group.c index 02d2073..10d65fc 100644 --- a/src/group.c +++ b/src/group.c @@ -494,7 +494,7 @@ group_last_window (rp_group *g, rp_screen *s) if (cur->win->last_access >= last_access && cur->win != current_window() && !find_windows_frame (cur->win) - && (cur->win->scr == s || rp_have_xinerama)) + && (cur->win->scr == s || rp_have_xrandr)) { most_recent = cur; last_access = cur->win->last_access; @@ -514,7 +514,7 @@ group_next_window (rp_group *g, rp_window *win) /* If there is no window, then get the last accessed one. */ if (win == NULL) - return group_last_window (g, current_screen()); + return group_last_window (g, rp_current_screen); /* If we can't find the window, then it's in a different group, so get the last accessed one in this group. */ @@ -528,7 +528,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 == win->scr || rp_have_xinerama)) + if (!find_windows_frame (cur->win) && (cur->win->scr == win->scr || rp_have_xrandr)) { return cur->win; } @@ -544,7 +544,7 @@ group_prev_window (rp_group *g, rp_window *win) /* If there is no window, then get the last accessed one. */ if (win == NULL) - return group_last_window (g, current_screen()); + return group_last_window (g, rp_current_screen); /* If we can't find the window, then it's in a different group, so get the last accessed one in this group. */ @@ -558,7 +558,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 == win->scr || rp_have_xinerama)) + if (!find_windows_frame (cur->win) && (cur->win->scr == win->scr || rp_have_xrandr)) { return cur->win; } @@ -676,14 +676,14 @@ group_last_window_by_class (rp_group *g, char *class) int last_access = 0; rp_window_elem *most_recent = NULL; rp_window_elem *cur; - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; list_for_each_entry (cur, &g->mapped_windows, node) { if (cur->win->last_access >= last_access && cur->win != current_window() && !find_windows_frame (cur->win) - && (cur->win->scr == s || rp_have_xinerama) + && (cur->win->scr == s || rp_have_xrandr) && strcmp(class, cur->win->res_class)) { most_recent = cur; @@ -704,14 +704,14 @@ group_last_window_by_class_complement (rp_group *g, char *class) int last_access = 0; rp_window_elem *most_recent = NULL; rp_window_elem *cur; - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; list_for_each_entry (cur, &g->mapped_windows, node) { if (cur->win->last_access >= last_access && cur->win != current_window() && !find_windows_frame (cur->win) - && (cur->win->scr == s || rp_have_xinerama) + && (cur->win->scr == s || rp_have_xrandr) && !strcmp(class, cur->win->res_class)) { most_recent = cur; diff --git a/src/input.c b/src/input.c index 51443e8..8566e32 100644 --- a/src/input.c +++ b/src/input.c @@ -446,7 +446,7 @@ read_single_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int int nbytes; XGetInputFocus (dpy, &focus, &revert); - set_window_focus (current_screen()->key_window); + set_window_focus (rp_current_screen->key_window); nbytes = read_key (keysym, modifiers, keysym_name, len); set_window_focus (focus); @@ -515,7 +515,7 @@ update_input_window (rp_screen *s, rp_input_line *line) line->length); gcv.function = GXxor; - gcv.foreground = s->fg_color ^ s->bg_color; + gcv.foreground = rp_glob_screen.fg_color ^ rp_glob_screen.bg_color; lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gcv); /* Draw a cheap-o cursor - MkIII */ @@ -537,12 +537,12 @@ ring_bell (void) GC lgc; XGCValues gcv; XWindowAttributes attr; - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; XGetWindowAttributes (dpy, s->input_window, &attr); gcv.function = GXxor; - gcv.foreground = s->fg_color ^ s->bg_color; + gcv.foreground = rp_glob_screen.fg_color ^ rp_glob_screen.bg_color; lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gcv); XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); @@ -570,7 +570,7 @@ get_more_input (char *prompt, char *preinput, int history_id, { /* Emacs 21 uses a 513 byte string to store the keysym name. */ char keysym_buf[513]; - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; KeySym ch; unsigned int modifier; rp_input_line *line; diff --git a/src/linkedlist.c b/src/linkedlist.c index adedf8a..99cabc0 100644 --- a/src/linkedlist.c +++ b/src/linkedlist.c @@ -196,3 +196,142 @@ list_size (struct list_head *list) return i; } + +#define MAX_LIST_LENGTH_BITS 20 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) + +/* + * Returns a list organized in an intermediate format suited + * to chaining of merge() calls: null-terminated, no reserved or + * sentinel head node, "prev" links not maintained. + */ +static struct list_head * +merge(void *priv, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b), + struct list_head *a, struct list_head *b) +{ + struct list_head head, *tail = &head; + + while (a && b) { + /* if equal, take 'a' -- important for sort stability */ + if ((*cmp) (priv, a, b) <= 0) { + tail->next = a; + a = a->next; + } else { + tail->next = b; + b = b->next; + } + tail = tail->next; + } + tail->next = a?:b; + return head.next; +} + +/* + * Combine final list merge with restoration of standard doubly-linked + * list structure. This approach duplicates code from merge(), but + * runs faster than the tidier alternatives of either a separate final + * prev-link restoration pass, or maintaining the prev links + * throughout. + */ +static void +merge_and_restore_back_links(void *priv, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b), + struct list_head *head, + struct list_head *a, struct list_head *b) +{ + struct list_head *tail = head; + unsigned int count = 0; + + while (a && b) { + /* if equal, take 'a' -- important for sort stability */ + if ((*cmp) (priv, a, b) <= 0) { + tail->next = a; + a->prev = tail; + a = a->next; + } else { + tail->next = b; + b->prev = tail; + b = b->next; + } + tail = tail->next; + } + tail->next = a ? : b; + + do { + /* + * In worst cases this loop may run many iterations. + * Continue callbacks to the client even though no + * element comparison is needed, so the client's cmp() + * routine can invoke cond_resched() periodically. + */ + if (!(++count)) + (*cmp) (priv, tail->next, tail->next); + + tail->next->prev = tail; + tail = tail->next; + } while (tail->next); + + tail->next = head; + head->prev = tail; +} + +/** + * list_sort - sort a list + * @priv: private data, opaque to list_sort(), passed to @cmp + * @head: the list to sort + * @cmp: the elements comparison function + * + * This function implements "merge sort", which has O(nlog(n)) + * complexity. + * + * The comparison function @cmp must return a negative value if @a + * should sort before @b, and a positive value if @a should sort after + * @b. If @a and @b are equivalent, and their original relative + * ordering is to be preserved, @cmp must return 0. + */ +void +list_sort(void *priv, struct list_head *head, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b)) +{ + struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists + -- last slot is a sentinel */ + int lev; /* index into part[] */ + int max_lev = 0; + struct list_head *list; + + if (list_empty (head)) + return; + + memset(part, 0, sizeof(part)); + + head->prev->next = NULL; + list = head->next; + + while (list) { + struct list_head *cur = list; + list = list->next; + cur->next = NULL; + + for (lev = 0; part[lev]; lev++) { + cur = merge (priv, cmp, part[lev], cur); + part[lev] = NULL; + } + if (lev > max_lev) { + if (lev >= ARRAY_SIZE(part)-1) { + lev--; + } + max_lev = lev; + } + part[lev] = cur; + } + + for (lev = 0; lev < max_lev; lev++) + if (part[lev]) + list = merge (priv, cmp, part[lev], list); + + merge_and_restore_back_links (priv, cmp, head, part[max_lev], list); +} diff --git a/src/linkedlist.h b/src/linkedlist.h index 42fee3d..6a3da7c 100644 --- a/src/linkedlist.h +++ b/src/linkedlist.h @@ -25,6 +25,8 @@ #ifndef _RATPOISON_LINKLIST_H #define _RATPOISON_LINKLIST_H +#include + /* * Simple doubly linked list implementation. * @@ -214,3 +216,7 @@ void __list_add(struct list_head *new, if (&first->member == (head)) \ first = NULL; \ } + +void list_sort(void *priv, struct list_head *head, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b)); diff --git a/src/main.c b/src/main.c index 3ca8ee6..3f5eb28 100644 --- a/src/main.c +++ b/src/main.c @@ -59,7 +59,6 @@ static struct option ratpoison_longopts[] = {"version", no_argument, 0, 'v'}, {"command", required_argument, 0, 'c'}, {"display", required_argument, 0, 'd'}, - {"screen", required_argument, 0, 's'}, {"file", required_argument, 0, 'f'}, {0, 0, 0, 0} }; @@ -338,7 +337,6 @@ print_help (void) printf ("-h, --help Display this help screen\n"); printf ("-v, --version Display the version\n"); printf ("-d, --display Set the X display to use\n"); - printf ("-s, --screen Only use the specified screen\n"); printf ("-c, --command Send ratpoison a colon-command\n"); printf ("-i, --interactive Execute commands in interactive mode\n"); printf ("-f, --file Specify an alternative configuration file\n\n"); @@ -588,12 +586,10 @@ init_defaults (void) int main (int argc, char *argv[]) { - int i; int c; char **cmd = NULL; int cmd_count = 0; - int screen_arg = 0; - int screen_num = 0; + rp_screen *cur; char *display = NULL; unsigned char interactive = 0; char *alt_rcfile = NULL; @@ -639,10 +635,6 @@ main (int argc, char *argv[]) case 'd': display = optarg; break; - case 's': - screen_arg = 1; - screen_num = strtol (optarg, NULL, 10); - break; case 'i': interactive = 1; break; @@ -686,13 +678,11 @@ main (int argc, char *argv[]) if (cmd_count > 0) { - int j, screen, exit_status = EXIT_SUCCESS; - - screen = screen_arg ? screen_num : -1; + int j, exit_status = EXIT_SUCCESS; for (j = 0; j < cmd_count; j++) { - if (!send_command (interactive, (unsigned char *)cmd[j], screen)) + if (!send_command (interactive, (unsigned char *)cmd[j])) exit_status = EXIT_FAILURE; free (cmd[j]); } @@ -736,8 +726,13 @@ main (int argc, char *argv[]) init_xkb (); init_groups (); init_window_stuff (); - init_xinerama (); - init_screens (screen_arg, screen_num); + +#ifdef HAVE_LIBXRANDR + init_xrandr (); + rp_have_xrandr = 1; +#endif + + init_screens (); init_frame_lists (); update_modifier_map (); @@ -745,19 +740,11 @@ main (int argc, char *argv[]) initialize_default_keybindings (); history_load (); - /* Scan for windows */ - if (screen_arg) - { - rp_current_screen = screen_num; - scanwins (&screens[0]); - } - else + list_for_each_entry (cur, &rp_screens, node) { - rp_current_screen = 0; - for (i=0; ikey_window); + set_window_focus (rp_current_screen->key_window); listen_for_events (); return EXIT_SUCCESS; } -static void -free_screen (rp_screen *s) -{ - rp_frame *frame; - struct list_head *iter, *tmp; - - /* Relinquish our hold on the root window. */ - XSelectInput(dpy, RootWindow (dpy, s->screen_num), 0); - - list_for_each_safe_entry (frame, iter, tmp, &s->frames, node) - { - frame_free (s, frame); - } - - deactivate_screen(s); - - XDestroyWindow (dpy, s->bar_window); - XDestroyWindow (dpy, s->key_window); - XDestroyWindow (dpy, s->input_window); - XDestroyWindow (dpy, s->frame_window); - XDestroyWindow (dpy, s->help_window); - -#ifdef USE_XFT_FONT - if (s->xft_font) - { - XftColorFree (dpy, DefaultVisual (dpy, s->screen_num), - DefaultColormap (dpy, s->screen_num), &s->xft_fg_color); - XftColorFree (dpy, DefaultVisual (dpy, s->screen_num), - DefaultColormap (dpy, s->screen_num), &s->xft_bg_color); - XftFontClose (dpy, s->xft_font); - } -#endif - - XFreeCursor (dpy, s->rat); - XFreeColormap (dpy, s->def_cmap); - XFreeGC (dpy, s->normal_gc); - XFreeGC (dpy, s->inverse_gc); - - free (s->display_string); -} - void clean_up (void) { - int i; + rp_screen *cur; + struct list_head *iter, *tmp; history_save (); @@ -831,11 +778,14 @@ clean_up (void) free_window_stuff (); free_groups (); - for (i=0; inode); + screen_free (cur); + free (cur); } - free (screens); + + screen_free_final (); /* Delete the undo histories */ while (list_size (&rp_frame_undos) > 0) @@ -849,8 +799,6 @@ clean_up (void) /* Free the global frame numset shared by all screens. */ numset_free (rp_frame_numset); - free_xinerama(); - #ifndef USE_XFT_FONT XFreeFontSet (dpy, defaults.font); #endif diff --git a/src/manage.c b/src/manage.c index 412fc29..2faab71 100644 --- a/src/manage.c +++ b/src/manage.c @@ -154,21 +154,6 @@ grab_keys_all_wins (void) } } -rp_screen* -current_screen (void) -{ - int i; - - for (i=0; ileft, s->top, s->left + s->width, s->top + s->height));} - if (rp_have_xinerama + if (rp_have_xrandr && ((attr.x > s->left + s->width) || (attr.x < s->left) || (attr.y > s->top + s->height) @@ -901,7 +883,7 @@ hide_window (rp_window *win) XSelectInput (dpy, win->w, WIN_EVENTS); /* Ensure that the window doesn't have the focused border color. This is needed by remove_frame and possibly others. */ - XSetWindowBorder (dpy, win->w, win->scr->bw_color); + XSetWindowBorder (dpy, win->w, rp_glob_screen.bw_color); set_state (win, IconicState); } diff --git a/src/ratpoison.h b/src/ratpoison.h index 5ff7c44..c98dd40 100644 --- a/src/ratpoison.h +++ b/src/ratpoison.h @@ -78,7 +78,7 @@ extern XGCValues gv; #include "history.h" #include "completions.h" #include "hook.h" -#include "xinerama.h" +#include "xrandr.h" #include "format.h" void clean_up (void); diff --git a/src/screen.c b/src/screen.c index 0afdee0..d3a4d87 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,4 +1,5 @@ /* Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts + * Copyright (C) 2016 Mathieu OTHACEHE * * This file is part of ratpoison. * @@ -22,7 +23,7 @@ #include #include -static void init_screen (rp_screen *s, int screen_num); +static void init_screen (rp_screen *s); int screen_width (rp_screen *s) @@ -153,79 +154,119 @@ screen_find_frame_by_frame (rp_screen *s, rp_frame *f) rp_screen * find_screen (Window w) { - int i; + rp_screen *cur; - for (i=0; iroot == w) + return cur; + } - return NULL; - } + return NULL; +} /* Return 1 if w is a root window of any of the screens. */ int is_a_root_window (unsigned int w) { - int i; - for (i=0; iroot == w) + return 1; + } + + return 0; +} + +rp_screen * +screen_at(int index) +{ + int i = 0; + rp_screen *cur; + + list_for_each_entry (cur, &rp_screens, node) + { + if (index == i) + return cur; + + i++; + } + + return NULL; +} + +static int +screen_cmp_left (void *priv, struct list_head *a, struct list_head *b) +{ + rp_screen *sc_a = container_of (a, typeof(*sc_a), node); + rp_screen *sc_b = container_of (b, typeof(*sc_b), node); + + if (sc_a->left < sc_b->left) + return -1; + else if (sc_a->left > sc_b->left) + return 1; return 0; } void -init_screens (int screen_arg, int screen_num) +screen_sort(void) { - int i; + return list_sort (NULL, &rp_screens, screen_cmp_left); +} - /* Get the number of screens */ - if (rp_have_xinerama) - num_screens = xine_screen_count; - else - num_screens = ScreenCount (dpy); +static void +init_global_screen (rp_global_screen *s) +{ + int screen_num; - /* 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); - } + screen_num = DefaultScreen (dpy); + s->fg_color = BlackPixel (dpy, screen_num); + s->bg_color = WhitePixel (dpy, screen_num); + s->fw_color = BlackPixel (dpy, screen_num); + s->bw_color = BlackPixel (dpy, screen_num); +} - if (screen_num < 0 || screen_num >= num_screens) - { - fprintf (stderr, "%d is an invalid screen for the display\n", screen_num); - exit (EXIT_FAILURE); - } +void +init_screens () +{ + int i; + int screen_count; + int *rr_outputs = NULL; + rp_screen *screen; - /* we're only going to use one screen. */ - num_screens = 1; - } + /* Get the number of screens */ + if (rp_have_xrandr) { +#ifdef HAVE_LIBXRANDR + rr_outputs = xrandr_query_screen (&screen_count); +#endif + } else { + screen_count = ScreenCount (dpy); + } /* Create our global frame numset */ rp_frame_numset = numset_new(); - /* Initialize the screens */ - screens = xmalloc (sizeof (rp_screen) * num_screens); - PRINT_DEBUG (("%d screens.\n", num_screens)); + init_global_screen (&rp_glob_screen); - if (screen_arg) + for (i = 0; i < screen_count; i++) { - init_screen (&screens[0], screen_num); - } - else - { - for (i=0; inode, &rp_screens); + +#ifdef HAVE_LIBXRANDR + if (rp_have_xrandr) + xrandr_fill_screen (rr_outputs[i], screen); +#endif + init_screen (screen); } + screen_sort (); + + if (rr_outputs) + free (rr_outputs); } static void @@ -235,41 +276,30 @@ init_rat_cursor (rp_screen *s) } static void -init_screen (rp_screen *s, int screen_num) +init_screen (rp_screen *s) { XGCValues gcv; struct sbuf *buf; - int xine_screen_num; char *colon; + int 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 + screen_num = DefaultScreen (dpy); + + if (!rp_have_xrandr) { - xine_screen_num = screen_num; s->left = 0; s->top = 0; - s->width = DisplayWidth(dpy, screen_num); - s->height = DisplayHeight(dpy, screen_num); + 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 - | StructureNotifyMask); + XSelectInput (dpy, RootWindow (dpy, screen_num), + PropertyChangeMask | ColormapChangeMask + | SubstructureRedirectMask | SubstructureNotifyMask + | StructureNotifyMask); XSync (dpy, False); /* Set the numset for the frames to our global numset. */ @@ -295,21 +325,15 @@ init_screen (rp_screen *s, int screen_num) PRINT_DEBUG (("display string: %s\n", s->display_string)); - s->screen_num = screen_num; - s->xine_screen_num = xine_screen_num; s->root = RootWindow (dpy, screen_num); + s->screen_num = 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); - s->fw_color = BlackPixel (dpy, s->screen_num); - s->bw_color = BlackPixel (dpy, s->screen_num); - /* Setup the GC for drawing the font. */ - gcv.foreground = s->fg_color; - gcv.background = s->bg_color; + gcv.foreground = rp_glob_screen.fg_color; + gcv.background = rp_glob_screen.bg_color; gcv.function = GXcopy; gcv.line_width = 1; gcv.subwindow_mode = IncludeInferiors; @@ -317,8 +341,8 @@ init_screen (rp_screen *s, int screen_num) GCForeground | GCBackground | GCFunction | GCLineWidth | GCSubwindowMode, &gcv); - gcv.foreground = s->bg_color; - gcv.background = s->fg_color; + gcv.foreground = rp_glob_screen.bg_color; + gcv.background = rp_glob_screen.fg_color; s->inverse_gc = XCreateGC(dpy, s->root, GCForeground | GCBackground | GCFunction | GCLineWidth | GCSubwindowMode, @@ -328,28 +352,28 @@ init_screen (rp_screen *s, int screen_num) 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); + rp_glob_screen.fg_color, rp_glob_screen.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)); + WhitePixel (dpy, screen_num), + BlackPixel (dpy, screen_num)); XSelectInput (dpy, s->key_window, KeyPressMask | KeyReleaseMask); /* 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); + rp_glob_screen.fg_color, rp_glob_screen.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); + rp_glob_screen.fg_color, rp_glob_screen.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); + s->height, 0, rp_glob_screen.fg_color, rp_glob_screen.bg_color); XSelectInput (dpy, s->help_window, KeyPressMask); activate_screen(s); @@ -391,13 +415,13 @@ activate_screen (rp_screen *s) { /* Add netwm support. FIXME: I think this is busted. */ XChangeProperty (dpy, RootWindow (dpy, s->screen_num), - _net_supported, XA_ATOM, 32, PropModeReplace, - (unsigned char*)&_net_wm_pid, 1); + _net_supported, XA_ATOM, 32, PropModeReplace, + (unsigned char*)&_net_wm_pid, 1); /* set window manager name */ XChangeProperty (dpy, RootWindow (dpy, s->screen_num), - _net_wm_name, xa_utf8_string, 8, PropModeReplace, - (unsigned char*)"ratpoison", 9); + _net_wm_name, xa_utf8_string, 8, PropModeReplace, + (unsigned char*)"ratpoison", 9); XMapWindow (dpy, s->key_window); } @@ -409,9 +433,9 @@ deactivate_screen (rp_screen *s) /* delete everything so noone sees them while we are not there */ XDeleteProperty (dpy, RootWindow (dpy, s->screen_num), - _net_supported); + _net_supported); XDeleteProperty (dpy, RootWindow (dpy, s->screen_num), - _net_wm_name); + _net_wm_name); } static int @@ -429,18 +453,15 @@ is_rp_window_for_given_screen (Window w, rp_screen *s) int is_rp_window_for_screen(Window w, rp_screen *s) { - int i; + rp_screen *cur; - if (rp_have_xinerama) - { - for (i=0; ixine_screen_num:screen->screen_num, - screen->left, - screen->top, - screen->width, - screen->height, - (current_screen() == screen)?1:0 /* is current? */ - ); + if (rp_have_xrandr) + sbuf_printf(s, "%s ", sbuf_get (screen->xrandr.name)); + + sbuf_printf_concat (s, "%d %d %d %d %d %d", + (rp_have_xrandr) ? screen->xrandr.output : screen->screen_num, + screen->left, + screen->top, + screen->width, + screen->height, + (rp_current_screen == screen)?1:0 /* is current? */ + ); /* Extract the string and return it, and don't forget to free s. */ tmp = sbuf_get (s); @@ -465,27 +489,67 @@ screen_dump (rp_screen *screen) return tmp; } +int +screen_count (void) +{ + return list_size (&rp_screens); +} + +rp_screen * +screen_next (void) +{ + return list_next_entry (rp_current_screen, &rp_screens, node); +} + +rp_screen * +screen_prev (void) +{ + return list_prev_entry (rp_current_screen, &rp_screens, node); +} + +static void +screen_remove_current (rp_screen *s) +{ + rp_screen *new_screen; + rp_frame *new_frame; + rp_window *cur_win; + int cur_frame; + + cur_win = current_window (); + new_screen = screen_next (); + + cur_frame = new_screen->current_frame; + new_frame = screen_get_frame (new_screen, cur_frame); + + set_active_frame (new_frame, 1); + + hide_window (cur_win); +} + void -screen_update (rp_screen *s, int width, int height) +screen_update (rp_screen *s, int left, int top, int width, int height) { rp_frame *f; - int oldwidth,oldheight; + int oldwidth, oldheight; PRINT_DEBUG (("screen_update(%d,%d)\n", width, height)); - if (rp_have_xinerama) - { - /* TODO: how to do this with xinerama? */ - return; - } - if (s->width == width && s->height == height) + if (s->width == width && + s->height == height && + s->left == left && + s->top == top) /* nothing to do */ return; - oldwidth = s->width; oldheight = s->height; - s->width = width; s->height = height; + oldwidth = s->width; + oldheight = s->height; - XResizeWindow (dpy, s->help_window, width, height); + s->left = left; + s->top = top; + s->width = width; + s->height = height; + + XMoveResizeWindow (dpy, s->help_window, s->left, s->top, s->width, s->height); list_for_each_entry (f, &s->frames, node) { @@ -496,3 +560,99 @@ screen_update (rp_screen *s, int width, int height) maximize_all_windows_in_frame (f); } } + +rp_screen * +screen_add (int rr_output) +{ + rp_screen *screen; + + screen = xmalloc (sizeof(*screen)); + list_add (&screen->node, &rp_screens); + + if (!rp_current_screen) + rp_current_screen = screen; + + change_windows_screen (NULL, screen); + +#ifdef HAVE_LIBXRANDR + xrandr_fill_screen (rr_output, screen); +#endif + init_screen (screen); + init_frame_list (screen); + + return screen; +} + +void +screen_del (rp_screen *s) +{ + /* + * The deleted screen cannot be the current screen anymore, + * focus the next one. + */ + if (s == rp_current_screen) { + screen_remove_current (s); + } else { + rp_frame *cur_frame; + rp_window *cur_win; + + cur_frame = screen_get_frame (s, s->current_frame); + cur_win = find_window_number (cur_frame->win_number); + hide_window (cur_win); + } + + change_windows_screen (s, rp_current_screen); + screen_free (s); + + list_del (&s->node); + free (s); +} + +void +screen_free (rp_screen *s) +{ + rp_frame *frame; + struct list_head *iter, *tmp; + + list_for_each_safe_entry (frame, iter, tmp, &s->frames, node) + { + frame_free (s, frame); + } + + deactivate_screen(s); + + XDestroyWindow (dpy, s->bar_window); + XDestroyWindow (dpy, s->key_window); + XDestroyWindow (dpy, s->input_window); + XDestroyWindow (dpy, s->frame_window); + XDestroyWindow (dpy, s->help_window); + +#ifdef USE_XFT_FONT + if (s->xft_font) + { + XftColorFree (dpy, DefaultVisual (dpy, s->screen_num), + DefaultColormap (dpy, s->screen_num), &s->xft_fg_color); + XftColorFree (dpy, DefaultVisual (dpy, s->screen_num), + DefaultColormap (dpy, s->screen_num), &s->xft_bg_color); + XftFontClose (dpy, s->xft_font); + } +#endif + + XFreeCursor (dpy, s->rat); + XFreeColormap (dpy, s->def_cmap); + XFreeGC (dpy, s->normal_gc); + XFreeGC (dpy, s->inverse_gc); + + free (s->display_string); + + if (rp_have_xrandr) + free (s->xrandr.name); +} + +void +screen_free_final (void) +{ + /* Relinquish our hold on the root window. */ + XSelectInput(dpy, RootWindow (dpy, DefaultScreen (dpy)), 0); + +} diff --git a/src/screen.h b/src/screen.h index 6bad555..eef6c42 100644 --- a/src/screen.h +++ b/src/screen.h @@ -35,7 +35,7 @@ void frameset_free (struct list_head *head); rp_frame *screen_get_frame (rp_screen *s, int frame_num); rp_frame *screen_find_frame_by_frame (rp_screen *s, rp_frame *f); -void init_screens (int screen_arg, int screen_num); +void init_screens (); void activate_screen (rp_screen *s); void deactivate_screen (rp_screen *s); @@ -44,5 +44,22 @@ int is_a_root_window (unsigned int w); char *screen_dump (rp_screen *screen); -void screen_update (rp_screen *s, int width, int height); +void screen_update (rp_screen *s, int left, int top, int width, int height); + +int screen_count (void); + +rp_screen *screen_next(void); +rp_screen *screen_prev(void); + +rp_screen *screen_at (int index); + +rp_screen *screen_by_output(int rr_output); +rp_screen *screen_by_crtc(int rr_crtc); +void screen_sort(void); + +rp_screen *screen_add(int rr_output); +void screen_del(rp_screen *s); +void screen_free (rp_screen *s); +void screen_free_final(void); + #endif diff --git a/src/split.c b/src/split.c index b36b99e..5f74777 100644 --- a/src/split.c +++ b/src/split.c @@ -41,24 +41,10 @@ update_last_access (rp_frame *frame) rp_frame * current_frame (void) { - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; return screen_get_frame (s, s->current_frame); } -int -num_frames (rp_screen *s) -{ - int count = 0; - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - count++; - } - - return count; -} - void cleanup_frame (rp_frame *frame) { @@ -95,7 +81,7 @@ set_frames_window (rp_frame *frame, rp_window *win) 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. + * since with Xrandr, windows can move from one screen to another. */ win->scr = frames_screen(frame); } @@ -110,15 +96,17 @@ set_frames_window (rp_frame *frame, rp_window *win) rp_screen * frames_screen (rp_frame *frame) { - int i; - rp_frame *cur; + rp_frame *cur_frame; + rp_screen *cur_screen; - for (i=0; iframes, node) + { + if (frame == cur_frame) + return cur_screen; + } + } /* This SHOULD be impossible to get to. FIXME: It'll crash higher up if we return NULL. */ @@ -171,10 +159,12 @@ create_initial_frame (rp_screen *screen) void init_frame_lists (void) { - int i; + rp_screen *cur; - for (i=0; iframes, node) + list_for_each_entry (cur_frame, &cur_screen->frames, node) { - if (cur->number != current_screen()->current_frame - && cur->last_access > last_access) + if (cur_frame->number != rp_current_screen->current_frame && + cur_frame->last_access > last_access) { - last_access = cur->last_access; - last = cur; + last_access = cur_frame->last_access; + last = cur_frame; } } } @@ -227,6 +215,12 @@ find_windows_frame (rp_window *win) return NULL; } +int +num_frames (rp_screen *s) +{ + return list_size (&s->frames); +} + rp_frame * find_frame_next (rp_frame *frame) { @@ -277,7 +271,7 @@ find_window_for_frame (rp_frame *frame) list_for_each_entry (cur, &rp_current_group->mapped_windows, node) { - if ((cur->win->scr == s || rp_have_xinerama) + if ((cur->win->scr == s || rp_have_xrandr) && cur->win != current_window() && !find_windows_frame (cur->win) && cur->win->last_access >= last_access @@ -382,7 +376,7 @@ void remove_all_splits (void) { struct list_head *tmp, *iter; - rp_screen *s = current_screen(); + rp_screen *s = rp_current_screen; rp_frame *frame; rp_window *win; @@ -822,9 +816,9 @@ remove_frame (rp_frame *frame) void set_active_frame (rp_frame *frame, int force_indicator) { - rp_screen *old_s = current_screen(); + rp_screen *old_s = rp_current_screen; rp_screen *s = frames_screen (frame); - int old = current_screen()->current_frame; + int old = rp_current_screen->current_frame; rp_window *win, *old_win; rp_frame *old_frame; @@ -845,7 +839,7 @@ set_active_frame (rp_frame *frame, int force_indicator) s->current_frame = frame->number; /* If frame->win == NULL, then rp_current_screen is not updated. */ - rp_current_screen = s->xine_screen_num; + rp_current_screen = s; update_bar (s); @@ -926,15 +920,18 @@ blank_frame (rp_frame *frame) void hide_frame_indicator (void) { - int i; - for (i=0; iframe_window); + } } void show_frame_indicator (int force) { - if (num_frames (current_screen()) > 1 || force) + if (num_frames (rp_current_screen) > 1 || force) { hide_frame_indicator (); show_frame_message (defaults.frame_fmt); @@ -945,7 +942,7 @@ show_frame_indicator (int force) void show_frame_message (char *msg) { - rp_screen *s = current_screen (); + rp_screen *s = rp_current_screen; int width, height; rp_frame *frame; rp_window *win; @@ -1072,17 +1069,15 @@ find_frame_right (rp_frame *frame) rp_frame * find_frame_number (int num) { - int i; - rp_frame *cur; + rp_frame *cur_frame; + rp_screen *cur_screen; - for (i=0; iframes, node) + list_for_each_entry (cur_frame, &cur_screen->frames, node) { - if (cur->number == num) - return cur; + if (cur_frame->number == num) + return cur_frame; } } diff --git a/src/split.h b/src/split.h index 87bb660..f125df6 100644 --- a/src/split.h +++ b/src/split.h @@ -22,7 +22,6 @@ #ifndef SPLIT_H #define SPLIT_H -int num_frames (rp_screen *s); rp_window *set_frames_window (rp_frame *frame, rp_window *win); void cleanup_frame (rp_frame *frame); void maximize_all_windows_in_frame (rp_frame *frame); @@ -35,6 +34,7 @@ void resize_frame_vertically (rp_frame *frame, int diff); void remove_frame (rp_frame *frame); rp_window *find_window_for_frame (rp_frame *frame); rp_frame *find_windows_frame (rp_window *win); +int num_frames (rp_screen *s); rp_frame *find_frame_next (rp_frame *frame); rp_frame *find_frame_prev (rp_frame *frame); rp_window *current_window (void); diff --git a/src/window.c b/src/window.c index 7d31a87..b7609ca 100644 --- a/src/window.c +++ b/src/window.c @@ -412,7 +412,7 @@ give_window_focus (rp_window *win, rp_window *last_win) if (last_win != NULL && win != last_win) { save_mouse_position (last_win); - XSetWindowBorder (dpy, last_win->w, last_win->scr->bw_color); + XSetWindowBorder (dpy, last_win->w, rp_glob_screen.bw_color); } if (win == NULL) return; @@ -432,10 +432,10 @@ give_window_focus (rp_window *win, rp_window *last_win) if (last_win != NULL) XUninstallColormap (dpy, last_win->colormap); XInstallColormap (dpy, win->colormap); - XSetWindowBorder (dpy, win->w, win->scr->fw_color); + XSetWindowBorder (dpy, win->w, rp_glob_screen.fw_color); /* Finally, give the window focus */ - rp_current_screen = win->scr->xine_screen_num; + rp_current_screen = win->scr; set_rp_window_focus (win); XSync (dpy, False); @@ -456,31 +456,17 @@ static rp_frame * find_frame_non_dedicated(rp_screen *current_screen, rp_frame *current_frame) { rp_frame *cur; + rp_screen *screen; - /* Try the only / current screen... */ - for (cur = list_next_entry (current_frame, ¤t_screen->frames, node); - cur != current_frame; - cur = list_next_entry (cur, ¤t_screen->frames, node)) - { - if (!cur->dedicated) - return cur; - } - - /* If we have Xinerama, we can check *all* screens... */ - if (rp_have_xinerama) + list_for_each_entry (screen, &rp_screens, node) { - int i; + if (current_screen == screen) + continue; - for (i = 0; i < num_screens; i++) + list_for_each_entry (cur, &screen->frames, node) { - if (current_screen == &screens[i]) - continue; - - list_for_each_entry (cur, &screens[i].frames, node) - { - if (!cur->dedicated) - return cur; - } + if (!cur->dedicated) + return cur; } } @@ -492,36 +478,30 @@ set_active_window_body (rp_window *win, int force) { rp_window *last_win; rp_frame *frame = NULL, *last_frame = NULL; - rp_screen *screen; if (win == NULL) return; PRINT_DEBUG (("intended_frame_number: %d\n", win->intended_frame_number)); - /* 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. - */ - screen = rp_have_xinerama ? current_screen () : win->scr; - /* use the intended frame if we can. */ if (win->intended_frame_number >= 0) { - frame = screen_get_frame (screen, win->intended_frame_number); + frame = screen_get_frame (rp_current_screen, win->intended_frame_number); win->intended_frame_number = -1; if (frame != current_frame ()) last_frame = current_frame (); } if (frame == NULL) - frame = screen_get_frame (screen, screen->current_frame); + frame = screen_get_frame (rp_current_screen, rp_current_screen->current_frame); if (frame->dedicated && !force) { /* Try to find a non-dedicated frame. */ rp_frame *non_dedicated; - non_dedicated = find_frame_non_dedicated (screen, frame); + non_dedicated = find_frame_non_dedicated (rp_current_screen, frame); if (non_dedicated != NULL) { last_frame = frame; @@ -594,7 +574,7 @@ get_window_list (char *fmt, char *delim, struct sbuf *buffer, if (buffer == NULL) return; sbuf_clear (buffer); - find_window_other (current_screen()); + find_window_other (rp_current_screen); /* We only loop through the current group to look for windows. */ list_for_each_entry (we,&rp_current_group->mapped_windows,node) @@ -671,3 +651,15 @@ win_get_frame (rp_window *win) else return NULL; } + +void +change_windows_screen (rp_screen *old_screen, rp_screen *new_screen) +{ + rp_window *win; + + list_for_each_entry (win, &rp_mapped_window, node) + { + if (win->scr == old_screen) + win->scr = new_screen; + } +} diff --git a/src/window.h b/src/window.h index fdd246c..4ec8ec8 100644 --- a/src/window.h +++ b/src/window.h @@ -61,5 +61,6 @@ void set_active_window_force (rp_window *win); void set_active_window_body (rp_window *win, int force); struct rp_child_info *get_child_info (Window w); +void change_windows_screen (rp_screen *s, rp_screen *new_screen); #endif /* ! _RATPOISON_LIST_H */ diff --git a/src/xinerama.c b/src/xinerama.c deleted file mode 100644 index a8bceb2..0000000 --- a/src/xinerama.c +++ /dev/null @@ -1,104 +0,0 @@ -/* functions for grabbing information about Xinerama screens - * Copyright (C) 2003 Cameron Patrick - * - * This file is part of ratpoison. - * - * ratpoison is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * ratpoison is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -#include "ratpoison.h" - -#ifdef HAVE_X11_EXTENSIONS_XINERAMA_H -# include -# define XINERAMA -#endif - -int rp_have_xinerama = 0; -int xine_screen_count; - -#ifdef XINERAMA -static XineramaScreenInfo *xine_screens = NULL; -#endif - -void -init_xinerama(void) -{ -#ifdef XINERAMA - int evbase, errbase, major, minor; - - rp_have_xinerama = 0; - - if (xine_screens) XFree(xine_screens); - - if (!XineramaQueryExtension(dpy, &evbase, &errbase)) { - return; - } - - if (XineramaQueryVersion(dpy, &major, &minor) == 0) { - return; - } - - if (major != 1) { - fprintf (stderr, "Warning: Xinerama version %d.%d not supported\n", major, minor); - return; - } - - if (!XineramaIsActive(dpy)) { - return; - } - - xine_screens = XineramaQueryScreens(dpy, &xine_screen_count); - if (xine_screens == NULL) { - return; - } - if (xine_screen_count < 2) { - XFree (xine_screens); - xine_screens = NULL; - return; - } - - rp_have_xinerama = 1; -#else - rp_have_xinerama = 0; -#endif -} - -#ifdef XINERAMA -void xinerama_get_screen_info(int sc, int *x, int *y, int *w, int *h) -{ - if ((sc < xine_screen_count) && (sc >= 0)) { - *x = xine_screens[sc].x_org; - *y = xine_screens[sc].y_org; - *w = xine_screens[sc].width; - *h = xine_screens[sc].height; - } -} -#else -void xinerama_get_screen_info(int sc UNUSED, int *x UNUSED, int *y UNUSED, int *w UNUSED, int *h UNUSED) -{ -} -#endif - -void -free_xinerama(void) -{ -#ifdef XINERAMA - if (xine_screens) { - XFree(xine_screens); - } - rp_have_xinerama = 0; -#endif -} diff --git a/src/xinerama.h b/src/xinerama.h deleted file mode 100644 index 233ec46..0000000 --- a/src/xinerama.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2003 Cameron Patrick - * - * This file is part of ratpoison. - * - * ratpoison is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * ratpoison is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -#ifndef XINERAMA_H -#define XINERAMA_H - -void init_xinerama(void); -void free_xinerama(void); -void xinerama_get_screen_info(int sc, int *x, int *y, int *w, int *h); - -#endif diff --git a/src/xrandr.c b/src/xrandr.c new file mode 100644 index 0000000..f2ea804 --- /dev/null +++ b/src/xrandr.c @@ -0,0 +1,204 @@ +/* functions for grabbing information about xrandr screens + * Copyright (C) 2016 Mathieu OTHACEHE + * + * This file is part of ratpoison. + * + * ratpoison is free software; you can redistribute it and/or moify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ratpoison is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +#include "ratpoison.h" + +#include + +static int xrandr_evbase; + +#define XRANDR_MAJOR 1 +#define XRANDR_MINOR 2 + +void +init_xrandr (void) +{ + int errbase, major, minor; + + if (!XRRQueryExtension (dpy, &xrandr_evbase, &errbase)) { + return; + } + + if (XRRQueryVersion (dpy, &major, &minor) == 0) { + return; + } + + if (major != XRANDR_MAJOR || + (major == XRANDR_MAJOR && minor < XRANDR_MINOR)) { + PRINT_ERROR (("Xrandr version %d.%d is not supported\n", major, minor)); + return; + } + + XRRSelectInput (dpy, RootWindow (dpy, DefaultScreen(dpy)), + RRCrtcChangeNotifyMask | RROutputChangeNotifyMask); +} + +int * +xrandr_query_screen (int *screen_count) +{ + XRRScreenResources *res; + XRROutputInfo *outinfo; + int *output_array; + int count = 0; + int i; + + res = XRRGetScreenResources (dpy, RootWindow (dpy, DefaultScreen (dpy))); + output_array = xmalloc (res->noutput * sizeof(int)); + + for (i = 0; i < res->noutput; i++) { + outinfo = XRRGetOutputInfo (dpy, res, res->outputs[i]); + if (!outinfo->crtc) + continue; + + output_array[count] = res->outputs[i]; + count++; + + XRRFreeOutputInfo (outinfo); + } + + *screen_count = count; + XRRFreeScreenResources (res); + + return output_array; +} + +static rp_screen * +xrandr_screen_output (int rr_output) +{ + rp_screen *cur; + + list_for_each_entry (cur, &rp_screens, node) + { + if (cur->xrandr.output == rr_output) + return cur; + } + + return NULL; +} + +static rp_screen * +xrandr_screen_crtc (int rr_crtc) +{ + rp_screen *cur; + + list_for_each_entry (cur, &rp_screens, node) + { + if (cur->xrandr.crtc == rr_crtc) + return cur; + } + + return NULL; +} + +void +xrandr_fill_screen (int rr_output, rp_screen *screen) +{ + XRRScreenResources *res; + XRROutputInfo *outinfo; + XRRCrtcInfo *crtinfo; + + res = XRRGetScreenResourcesCurrent (dpy, RootWindow (dpy, DefaultScreen (dpy))); + outinfo = XRRGetOutputInfo (dpy, res, rr_output); + if (!outinfo->crtc) + goto free_res; + + crtinfo = XRRGetCrtcInfo (dpy, res, outinfo->crtc); + if (!crtinfo) + goto free_out; + + screen->xrandr.name = sbuf_new (0); + sbuf_concat (screen->xrandr.name, outinfo->name); + + screen->xrandr.output = rr_output; + screen->xrandr.crtc = outinfo->crtc; + + screen->left = crtinfo->x; + screen->top = crtinfo->y; + screen->width = crtinfo->width; + screen->height = crtinfo->height; + + XRRFreeCrtcInfo (crtinfo); + free_out: + XRRFreeOutputInfo (outinfo); + free_res: + XRRFreeScreenResources (res); +} + +static void +xrandr_output_change (XRROutputChangeNotifyEvent *ev) +{ + XRRScreenResources *res; + XRROutputInfo *outinfo; + rp_screen *screen; + + res = XRRGetScreenResourcesCurrent (dpy, RootWindow (dpy, DefaultScreen (dpy))); + outinfo = XRRGetOutputInfo (dpy, res, ev->output); + + screen = xrandr_screen_output (ev->output); + if (!screen && outinfo->crtc) { + screen_add (ev->output); + screen_sort (); + } else if (screen && !outinfo->crtc) { + screen_del (screen); + } + + XRRFreeOutputInfo (outinfo); + XRRFreeScreenResources (res); +} + +static void +xrandr_crtc_change (XRRCrtcChangeNotifyEvent *ev) +{ + rp_screen *screen; + + if (!ev->crtc || !ev->width || !ev->height) + return; + + screen = xrandr_screen_crtc (ev->crtc); + if (screen) + screen_update (screen, ev->x, ev->y, ev->width, ev->height); +} + +void +xrandr_notify (XEvent *ev) +{ + int ev_code = xrandr_evbase + RRNotify; + XRRNotifyEvent *n_event; + XRROutputChangeNotifyEvent *o_event; + XRRCrtcChangeNotifyEvent *c_event; + + if (ev->type != ev_code) + return; + + n_event = (XRRNotifyEvent *)ev; + switch (n_event->subtype) { + case RRNotify_OutputChange: + o_event = (XRROutputChangeNotifyEvent *)ev; + xrandr_output_change (o_event); + break; + case RRNotify_CrtcChange: + c_event = (XRRCrtcChangeNotifyEvent *)ev; + xrandr_crtc_change (c_event); + break; + default: + break; + } +} diff --git a/src/xrandr.h b/src/xrandr.h new file mode 100644 index 0000000..d765789 --- /dev/null +++ b/src/xrandr.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 Mathieu OTHACEHE + * + * This file is part of ratpoison. + * + * ratpoison is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * ratpoison is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +#ifndef XRANDR_H +#define XRANDR_H + +#include "ratpoison.h" + +void init_xrandr(void); +int *xrandr_query_screen(int *screen_count); +void xrandr_fill_screen(int rr_output, rp_screen *screen); +void xrandr_notify(XEvent *ev); + +#endif -- cgit v1.2.3 From 59b867127c52335b218f3bc82e29692c9f28e2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Mon, 21 Nov 2016 19:54:14 +0100 Subject: libXext isn't used --- configure.ac | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7e101e7..033b2c3 100644 --- a/configure.ac +++ b/configure.ac @@ -163,8 +163,6 @@ AC_CHECK_HEADERS([X11/XKBlib.h], [], [], [ ]) CPPFLAGS="$mysavedCPPFLAGS" -AC_CHECK_LIB(Xext, XMissingExtension, [X_LIBS="-lXext $X_LIBS"],,$X_LIBS $X_EXTRA_LIBS) - AC_ARG_WITH([xrandr], [AS_HELP_STRING([--without-xrandr], [Build without xrandr support, even if available])], [], -- cgit v1.2.3 From 9e5ee1e7b10670470de538a8c4faf7b4461354fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Mon, 21 Nov 2016 19:59:45 +0100 Subject: autotools: detect precisely Xrandr support Bail out if xrandr support can't be found but the user explicitely requested it. --- configure.ac | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 033b2c3..feacaac 100644 --- a/configure.ac +++ b/configure.ac @@ -101,6 +101,14 @@ AS_CASE([$enable_mdoc], AC_MSG_RESULT([$manpage_format]) AC_SUBST([manpage_format]) +AC_MSG_CHECKING([Xrandr support]) +AC_ARG_WITH([xrandr], + [AS_HELP_STRING([--without-xrandr], + [Build without Xrandr support, default is to use if available])], + [with_xrandr=$withval], + [with_xrandr=check]) +AC_MSG_RESULT([$with_xrandr]) + dnl Checks for programs. AC_PROG_CC AM_MISSING_PROG([MANDOC], [mandoc]) @@ -163,24 +171,32 @@ AC_CHECK_HEADERS([X11/XKBlib.h], [], [], [ ]) CPPFLAGS="$mysavedCPPFLAGS" -AC_ARG_WITH([xrandr], -[AS_HELP_STRING([--without-xrandr], [Build without xrandr support, even if available])], -[], -[with_xrandr=yes]) - -compile_xrandr=no -AS_IF([test "$with_xrandr" != no], -[AC_CHECK_LIB(Xrandr, XRRGetScreenResources, [compile_xrandr=yes X_LIBS="-lXrandr $X_LIBS" AC_DEFINE(HAVE_LIBXRANDR, 1, [Xrandr])],,$X_LIBS $X_EXTRA_LIBS)] -[]) - -AM_CONDITIONAL(HAVE_LIBXRANDR, test "$compile_xrandr" = yes) - AC_CHECK_LIB(Xtst, XTestFakeButtonEvent, [X_LIBS="-lXtst $X_LIBS"; AC_DEFINE(HAVE_LIBXTST,1,[Xtst])],,$X_LIBS $X_EXTRA_LIBS) AC_CHECK_LIB([X11], [XkbKeycodeToKeysym], [AC_DEFINE(HAVE_XKBKEYCODETOKEYSYM, 1, [Define to 1 if you have the `XkbKeycodeToKeysym' function.])], [], [$X_LIBS $X_EXTRA_LIBS]) +mysavedCPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $X_CFLAGS" +AC_CHECK_HEADERS([X11/extensions/Xrandr.h], [], [], [ +#include +]) +CPPFLAGS="$mysavedCPPFLAGS" + +AC_CHECK_LIB(Xrandr, XRRGetScreenResources, + [X_LIBS="-lXrandr $X_LIBS" + AC_DEFINE(HAVE_LIBXRANDR, 1, [Xrandr])], + [], [$X_LIBS $X_EXTRA_LIBS]) + +compile_xrandr=no +AS_CASE(["$with_xrandr:$ac_cv_header_X11_extensions_Xrandr_h:$ac_cv_lib_Xrandr_XRRGetScreenResources"], + [yes:no:*], [AC_MSG_ERROR([*** Can't enable Xrandr support, header Xrandr.h not found.])], + [yes:*:no], [AC_MSG_ERROR([*** Can't enable Xrandr support, libXrandr not found.])], + [yes:yes:yes|check:yes:yes], [compile_xrandr=yes]) + +AM_CONDITIONAL(HAVE_LIBXRANDR, [test "$compile_xrandr" = yes]) + AC_SUBST(X_LIBS) AC_SUBST(X_EXTRA_LIBS) AC_SUBST(X_CFLAGS) -- cgit v1.2.3 From 28d7a4967d6c550ee9d03180e08691519b9b4bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Mon, 21 Nov 2016 20:03:39 +0100 Subject: Replace extra definition with a declaration --- src/globals.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/globals.h b/src/globals.h index f3a70d4..dd21c9b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -80,7 +80,7 @@ extern struct list_head rp_groups; /* Whether or not we support xrandr */ -int rp_have_xrandr; +extern int rp_have_xrandr; extern rp_group *rp_current_group; @@ -197,8 +197,6 @@ 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_xrandr; - extern struct numset *rp_frame_numset; extern struct list_head rp_frame_undos; -- cgit v1.2.3 From f34153a2f385818c3820b37c20cde4e1054ccce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Mon, 21 Nov 2016 20:04:37 +0100 Subject: Only use xrandr if Xrandr init succeeds --- src/main.c | 1 - src/xrandr.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 3f5eb28..f5b5972 100644 --- a/src/main.c +++ b/src/main.c @@ -729,7 +729,6 @@ main (int argc, char *argv[]) #ifdef HAVE_LIBXRANDR init_xrandr (); - rp_have_xrandr = 1; #endif init_screens (); diff --git a/src/xrandr.c b/src/xrandr.c index f2ea804..f36105a 100644 --- a/src/xrandr.c +++ b/src/xrandr.c @@ -49,6 +49,8 @@ init_xrandr (void) XRRSelectInput (dpy, RootWindow (dpy, DefaultScreen(dpy)), RRCrtcChangeNotifyMask | RROutputChangeNotifyMask); + + rp_have_xrandr = 1; } int * -- cgit v1.2.3 From 638b0ed001b595f1303239092ffddaa9c29078e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Tue, 22 Nov 2016 01:12:08 +0100 Subject: Style nits, typo and non-existing functions. --- src/actions.c | 2 +- src/data.h | 2 +- src/screen.c | 11 +++++------ src/screen.h | 4 +--- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/actions.c b/src/actions.c index acfb466..bcefe0b 100644 --- a/src/actions.c +++ b/src/actions.c @@ -4952,7 +4952,7 @@ cmd_tmpwm (int interactive UNUSED, struct cmdarg **args) that are unmapped or destroyed. */ list_for_each_entry (cur_screen, &rp_screens, node) { - sync_wins (cur_screen); + sync_wins (cur_screen); } /* At this point, new windows have the top level keys grabbed but diff --git a/src/data.h b/src/data.h index a8651c6..1e640e7 100644 --- a/src/data.h +++ b/src/data.h @@ -166,7 +166,7 @@ struct rp_screen GC normal_gc, inverse_gc; 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 screen_num; /* Our screen number as dictated by X */ Colormap def_cmap; Cursor rat; diff --git a/src/screen.c b/src/screen.c index d3a4d87..7224f57 100644 --- a/src/screen.c +++ b/src/screen.c @@ -181,7 +181,7 @@ is_a_root_window (unsigned int w) } rp_screen * -screen_at(int index) +screen_at (int index) { int i = 0; rp_screen *cur; @@ -212,7 +212,7 @@ screen_cmp_left (void *priv, struct list_head *a, struct list_head *b) } void -screen_sort(void) +screen_sort (void) { return list_sort (NULL, &rp_screens, screen_cmp_left); } @@ -230,7 +230,7 @@ init_global_screen (rp_global_screen *s) } void -init_screens () +init_screens (void) { int i; int screen_count; @@ -265,14 +265,13 @@ init_screens () screen_sort (); - if (rr_outputs) - free (rr_outputs); + free (rr_outputs); } static void init_rat_cursor (rp_screen *s) { - s->rat = XCreateFontCursor( dpy, XC_icon ); + s->rat = XCreateFontCursor (dpy, XC_icon); } static void diff --git a/src/screen.h b/src/screen.h index eef6c42..7d85951 100644 --- a/src/screen.h +++ b/src/screen.h @@ -35,7 +35,7 @@ void frameset_free (struct list_head *head); rp_frame *screen_get_frame (rp_screen *s, int frame_num); rp_frame *screen_find_frame_by_frame (rp_screen *s, rp_frame *f); -void init_screens (); +void init_screens (void); void activate_screen (rp_screen *s); void deactivate_screen (rp_screen *s); @@ -53,8 +53,6 @@ rp_screen *screen_prev(void); rp_screen *screen_at (int index); -rp_screen *screen_by_output(int rr_output); -rp_screen *screen_by_crtc(int rr_crtc); void screen_sort(void); rp_screen *screen_add(int rr_output); -- cgit v1.2.3 From b5c1e280cca0965eca0767534ee6514834b524e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Tue, 22 Nov 2016 01:15:33 +0100 Subject: Temporarily mark sfrestore as broken --- src/actions.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/actions.c b/src/actions.c index bcefe0b..606116c 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5638,6 +5638,8 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) rp_screen *cur_screen; int i; + return cmdret_new (RET_FAILURE, "FIXME: sfrestore is currently broken"); + for (i = 0; i < s_count; i++) buffer[i] = sbuf_new (0); -- cgit v1.2.3 From b7b1ccf24ce930d4f31f040fdc220aba15a01993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Tue, 22 Nov 2016 01:44:13 +0100 Subject: autotools: xkb is an external package -> --with[out]-xkb --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index feacaac..3f31f3c 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ AC_SUBST(XFT_CFLAGS) AC_SUBST(XFT_LIBS) AC_ARG_WITH([xkb], - [AS_HELP_STRING([--disable-xkb], [Don't build XKB support for keyboard input.])], + [AS_HELP_STRING([--without-xkb], [Don't build XKB support for keyboard input.])], [xkb=$withval], [xkb=yes]) AS_IF([test "X$xkb" = "Xyes"], -- cgit v1.2.3 From 02b2628422648c7f3f0f82441256fe15b623a723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Tue, 22 Nov 2016 02:03:39 +0100 Subject: Use a different tarball name for xrandr support. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3f31f3c..ef44eb3 100644 --- a/configure.ac +++ b/configure.ac @@ -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 -AC_INIT([ratpoison], [1.4.9-beta], [ratpoison-devel@nongnu.org]) +AC_INIT([ratpoison], [1.4.9-xrandr1], [ratpoison-devel@nongnu.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/main.c]) -- cgit v1.2.3 From 47c2bee92a15b4eb953e5b2b63f08d38ab245ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 09:24:58 +0100 Subject: Sprinkle more debug in xrandr code. --- src/screen.c | 3 ++- src/xrandr.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/screen.c b/src/screen.c index 7224f57..115aeca 100644 --- a/src/screen.c +++ b/src/screen.c @@ -531,7 +531,8 @@ screen_update (rp_screen *s, int left, int top, int width, int height) rp_frame *f; int oldwidth, oldheight; - PRINT_DEBUG (("screen_update(%d,%d)\n", width, height)); + PRINT_DEBUG (("screen_update (left=%d, top=%d, width=%d, height=%d)\n", + left, top, width, height)); if (s->width == width && s->height == height && diff --git a/src/xrandr.c b/src/xrandr.c index f36105a..a8cef61 100644 --- a/src/xrandr.c +++ b/src/xrandr.c @@ -155,10 +155,16 @@ xrandr_output_change (XRROutputChangeNotifyEvent *ev) outinfo = XRRGetOutputInfo (dpy, res, ev->output); screen = xrandr_screen_output (ev->output); + if (!screen && outinfo->crtc) { - screen_add (ev->output); + screen = screen_add (ev->output); screen_sort (); + PRINT_DEBUG (("%s: Added screen %s with crtc %lu\n", __func__, + sbuf_get (screen->xrandr.name), + (unsigned long)outinfo->crtc)); } else if (screen && !outinfo->crtc) { + PRINT_DEBUG (("%s: Removing screen %s\n", __func__, + sbuf_get (screen->xrandr.name))); screen_del (screen); } @@ -166,6 +172,25 @@ xrandr_output_change (XRROutputChangeNotifyEvent *ev) XRRFreeScreenResources (res); } +static const char * +xrandr_rotation_string (Rotation r) +{ + static char buf[64]; + +#define CASE(c) case c : return #c + switch (r) + { + CASE(RR_Rotate_0); + CASE(RR_Rotate_90); + CASE(RR_Rotate_180); + CASE(RR_Rotate_270); +#undef CASE + default: + snprintf(buf, sizeof buf, "Unknown rotation %hu", (unsigned short)r); + return buf; + } +} + static void xrandr_crtc_change (XRRCrtcChangeNotifyEvent *ev) { @@ -175,8 +200,17 @@ xrandr_crtc_change (XRRCrtcChangeNotifyEvent *ev) return; screen = xrandr_screen_crtc (ev->crtc); - if (screen) - screen_update (screen, ev->x, ev->y, ev->width, ev->height); + + PRINT_DEBUG (("%s: crtc %s, rotation %s " + "ev->x %d, ev->y %d, ev->width %d, ev->height %d\n", + __func__, screen ? "found" : "not found", + xrandr_rotation_string (ev->rotation), + ev->x, ev->y, ev->width, ev->height)); + + if (!screen) + return; + + screen_update (screen, ev->x, ev->y, ev->width, ev->height); } void @@ -189,18 +223,25 @@ xrandr_notify (XEvent *ev) if (ev->type != ev_code) return; + PRINT_DEBUG (("--- Handling RRNotify ---\n")); n_event = (XRRNotifyEvent *)ev; switch (n_event->subtype) { case RRNotify_OutputChange: + PRINT_DEBUG (("--- XRROutputChangeNotifyEvent ---\n")); o_event = (XRROutputChangeNotifyEvent *)ev; xrandr_output_change (o_event); break; case RRNotify_CrtcChange: + PRINT_DEBUG (("--- XRRCrtcChangeNotifyEvent ---\n")); c_event = (XRRCrtcChangeNotifyEvent *)ev; xrandr_crtc_change (c_event); break; + case RRNotify_OutputProperty: + PRINT_DEBUG (("--- RRNotify_OutputProperty ---\n")); + break; default: + PRINT_DEBUG (("--- Unknown subtype %d ---\n", n_event->subtype)); break; } } -- cgit v1.2.3 From f6f6cd87e6175b203445e1245fb1fa282416ebca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 09:29:35 +0100 Subject: Reinstate code that should stay: we may not have xrandr --- src/events.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/events.c b/src/events.c index 496752e..d881049 100644 --- a/src/events.c +++ b/src/events.c @@ -702,7 +702,19 @@ mapping_notify (XMappingEvent *ev) grab_keys_all_wins(); } -/* This is called whan an application has requested the +static void +configure_notify (XConfigureEvent *ev) +{ + rp_screen *s; + + s = find_screen(ev->window); + if (s != NULL) + /* This is a root window of a screen, + * look if its width or height changed: */ + screen_update (s, ev->x, ev->y, ev->width, ev->height); +} + +/* This is called when an application has requested the selection. Copied from rxvt. */ static void selection_request (XSelectionRequestEvent *rq) @@ -847,6 +859,13 @@ delegate_event (XEvent *ev) selection_clear(); break; + case ConfigureNotify: + PRINT_DEBUG (("--- Handling ConfigureNotify ---\n")); +#ifdef notdef + configure_notify (&ev->xconfigure); +#endif + break; + case MapNotify: case Expose: case MotionNotify: -- cgit v1.2.3 From f4e9c732dacdb40d2c4123e1a096bc48404f3b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 09:33:47 +0100 Subject: Kill superflous var. --- src/xrandr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xrandr.c b/src/xrandr.c index a8cef61..1425178 100644 --- a/src/xrandr.c +++ b/src/xrandr.c @@ -216,13 +216,13 @@ xrandr_crtc_change (XRRCrtcChangeNotifyEvent *ev) void xrandr_notify (XEvent *ev) { - int ev_code = xrandr_evbase + RRNotify; XRRNotifyEvent *n_event; XRROutputChangeNotifyEvent *o_event; XRRCrtcChangeNotifyEvent *c_event; - if (ev->type != ev_code) + if (ev->type != xrandr_evbase + RRNotify) return; + PRINT_DEBUG (("--- Handling RRNotify ---\n")); n_event = (XRRNotifyEvent *)ev; -- cgit v1.2.3 From c1deb5c9ea2712cb1faed32a5905914517c04024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 09:36:32 +0100 Subject: Keep on handling ConfigureNotify if we don't have xrandr --- src/events.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/events.c b/src/events.c index d881049..b31a194 100644 --- a/src/events.c +++ b/src/events.c @@ -786,7 +786,8 @@ delegate_event (XEvent *ev) { #ifdef HAVE_LIBXRANDR - xrandr_notify (ev); + if (rp_have_xrandr) + xrandr_notify (ev); #endif switch (ev->type) @@ -860,10 +861,11 @@ delegate_event (XEvent *ev) break; case ConfigureNotify: - PRINT_DEBUG (("--- Handling ConfigureNotify ---\n")); -#ifdef notdef - configure_notify (&ev->xconfigure); -#endif + if (!rp_have_xrandr) + { + PRINT_DEBUG (("--- Handling ConfigureNotify ---\n")); + configure_notify (&ev->xconfigure); + } break; case MapNotify: -- cgit v1.2.3 From 0e31e477e5eedff5a87d01b39dc75d381f55e43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 09:47:34 +0100 Subject: Only call xrandr_fill_screen is xrandr is available --- src/screen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/screen.c b/src/screen.c index 115aeca..ea00262 100644 --- a/src/screen.c +++ b/src/screen.c @@ -575,7 +575,8 @@ screen_add (int rr_output) change_windows_screen (NULL, screen); #ifdef HAVE_LIBXRANDR - xrandr_fill_screen (rr_output, screen); + if (rp_have_xrandr) + xrandr_fill_screen (rr_output, screen); #endif init_screen (screen); init_frame_list (screen); -- cgit v1.2.3 From bba8ecc0f678b50f521ca06c69a88b7c9f0dc15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 09:55:43 +0100 Subject: define HAVE_XRANDR/link with libXrandr when we actually want to --- configure.ac | 13 +++++++------ src/Makefile.am | 2 +- src/events.c | 2 +- src/main.c | 2 +- src/screen.c | 6 +++--- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index ef44eb3..63ee565 100644 --- a/configure.ac +++ b/configure.ac @@ -184,18 +184,19 @@ AC_CHECK_HEADERS([X11/extensions/Xrandr.h], [], [], [ ]) CPPFLAGS="$mysavedCPPFLAGS" -AC_CHECK_LIB(Xrandr, XRRGetScreenResources, - [X_LIBS="-lXrandr $X_LIBS" - AC_DEFINE(HAVE_LIBXRANDR, 1, [Xrandr])], - [], [$X_LIBS $X_EXTRA_LIBS]) +# XXX Find out why ":" is so important below, with no argument +# half of config.h ends up #undef'd +AC_CHECK_LIB(Xrandr, XRRGetScreenResources, [: nothing], [], [$X_LIBS $X_EXTRA_LIBS]) compile_xrandr=no AS_CASE(["$with_xrandr:$ac_cv_header_X11_extensions_Xrandr_h:$ac_cv_lib_Xrandr_XRRGetScreenResources"], [yes:no:*], [AC_MSG_ERROR([*** Can't enable Xrandr support, header Xrandr.h not found.])], [yes:*:no], [AC_MSG_ERROR([*** Can't enable Xrandr support, libXrandr not found.])], - [yes:yes:yes|check:yes:yes], [compile_xrandr=yes]) + [yes:yes:yes|check:yes:yes], [X_LIBS="-lXrandr $X_LIBS" + AC_DEFINE(HAVE_XRANDR, 1, [Xrandr]) + compile_xrandr=yes]) -AM_CONDITIONAL(HAVE_LIBXRANDR, [test "$compile_xrandr" = yes]) +AM_CONDITIONAL(HAVE_XRANDR, [test "$compile_xrandr" = yes]) AC_SUBST(X_LIBS) AC_SUBST(X_EXTRA_LIBS) diff --git a/src/Makefile.am b/src/Makefile.am index 0daf587..bc27439 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,6 @@ ratpoison_SOURCES = actions.c \ window.c \ window.h -if HAVE_LIBXRANDR +if HAVE_XRANDR ratpoison_SOURCES += xrandr.c xrandr.h endif diff --git a/src/events.c b/src/events.c index b31a194..5e1013a 100644 --- a/src/events.c +++ b/src/events.c @@ -785,7 +785,7 @@ static void delegate_event (XEvent *ev) { -#ifdef HAVE_LIBXRANDR +#ifdef HAVE_XRANDR if (rp_have_xrandr) xrandr_notify (ev); #endif diff --git a/src/main.c b/src/main.c index f5b5972..ca5ebc8 100644 --- a/src/main.c +++ b/src/main.c @@ -727,7 +727,7 @@ main (int argc, char *argv[]) init_groups (); init_window_stuff (); -#ifdef HAVE_LIBXRANDR +#ifdef HAVE_XRANDR init_xrandr (); #endif diff --git a/src/screen.c b/src/screen.c index ea00262..240b876 100644 --- a/src/screen.c +++ b/src/screen.c @@ -239,7 +239,7 @@ init_screens (void) /* Get the number of screens */ if (rp_have_xrandr) { -#ifdef HAVE_LIBXRANDR +#ifdef HAVE_XRANDR rr_outputs = xrandr_query_screen (&screen_count); #endif } else { @@ -256,7 +256,7 @@ init_screens (void) screen = xmalloc (sizeof(*screen)); list_add (&screen->node, &rp_screens); -#ifdef HAVE_LIBXRANDR +#ifdef HAVE_XRANDR if (rp_have_xrandr) xrandr_fill_screen (rr_outputs[i], screen); #endif @@ -574,7 +574,7 @@ screen_add (int rr_output) change_windows_screen (NULL, screen); -#ifdef HAVE_LIBXRANDR +#ifdef HAVE_XRANDR if (rp_have_xrandr) xrandr_fill_screen (rr_output, screen); #endif -- cgit v1.2.3 From d3897ebdbf7e181d178e257c556346adb2be7258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Wed, 23 Nov 2016 10:22:47 +0100 Subject: Fix rotations when using xrandr --- src/xrandr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/xrandr.c b/src/xrandr.c index 1425178..2534099 100644 --- a/src/xrandr.c +++ b/src/xrandr.c @@ -210,7 +210,10 @@ xrandr_crtc_change (XRRCrtcChangeNotifyEvent *ev) if (!screen) return; - screen_update (screen, ev->x, ev->y, ev->width, ev->height); + if (ev->rotation == RR_Rotate_90 || ev->rotation == RR_Rotate_270) + screen_update (screen, ev->x, ev->y, ev->height, ev->width); + else + screen_update (screen, ev->x, ev->y, ev->width, ev->height); } void -- cgit v1.2.3 From 2f6586fbdb50ab2319d9fb1ab7fe01624366c69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 24 Nov 2016 07:22:21 +0100 Subject: Tweak previous. Use nicer names that the long ac_cv_* variables. Also, the reason why the third parameter of AC_CHECK_LIB was significant is that, if using the default (empty), the macro adds -lXrandr to LIBS. Later, LIBS is used for compile tests, which fail if libXrandr is not in the default search path of ld(1), for example in /usr/X11R6/lib... --- configure.ac | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 63ee565..a55591e 100644 --- a/configure.ac +++ b/configure.ac @@ -179,21 +179,19 @@ AC_CHECK_LIB([X11], [XkbKeycodeToKeysym], mysavedCPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $X_CFLAGS" -AC_CHECK_HEADERS([X11/extensions/Xrandr.h], [], [], [ +AC_CHECK_HEADERS([X11/extensions/Xrandr.h], [xrandr_h=yes], [xrandr_h=no], [ #include ]) CPPFLAGS="$mysavedCPPFLAGS" -# XXX Find out why ":" is so important below, with no argument -# half of config.h ends up #undef'd -AC_CHECK_LIB(Xrandr, XRRGetScreenResources, [: nothing], [], [$X_LIBS $X_EXTRA_LIBS]) +AC_CHECK_LIB(Xrandr, XRRGetScreenResources, [libxrandr=yes], [libxrandr=no], [$X_LIBS $X_EXTRA_LIBS]) compile_xrandr=no -AS_CASE(["$with_xrandr:$ac_cv_header_X11_extensions_Xrandr_h:$ac_cv_lib_Xrandr_XRRGetScreenResources"], +AS_CASE(["$with_xrandr:$xrandr_h:$libxrandr"], [yes:no:*], [AC_MSG_ERROR([*** Can't enable Xrandr support, header Xrandr.h not found.])], [yes:*:no], [AC_MSG_ERROR([*** Can't enable Xrandr support, libXrandr not found.])], [yes:yes:yes|check:yes:yes], [X_LIBS="-lXrandr $X_LIBS" - AC_DEFINE(HAVE_XRANDR, 1, [Xrandr]) + AC_DEFINE(HAVE_XRANDR, 1, [Define to 1 if you want Xrandr support.]) compile_xrandr=yes]) AM_CONDITIONAL(HAVE_XRANDR, [test "$compile_xrandr" = yes]) -- cgit v1.2.3 From 55a5ed452a7e1b6c581164e2dad15d528198eb40 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Thu, 24 Nov 2016 10:34:48 +0100 Subject: Kill gcc unused function warning The xrandr_rotation_string function is used only if DEBUG is enabled. --- src/xrandr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xrandr.c b/src/xrandr.c index 2534099..f1f3ef5 100644 --- a/src/xrandr.c +++ b/src/xrandr.c @@ -172,6 +172,7 @@ xrandr_output_change (XRROutputChangeNotifyEvent *ev) XRRFreeScreenResources (res); } +#ifdef DEBUG static const char * xrandr_rotation_string (Rotation r) { @@ -190,6 +191,7 @@ xrandr_rotation_string (Rotation r) return buf; } } +#endif static void xrandr_crtc_change (XRRCrtcChangeNotifyEvent *ev) -- cgit v1.2.3 From 8e1316eba8d734b2f167a5a39fa93f7ecffa9c6a Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Tue, 29 Nov 2016 20:00:49 +0100 Subject: Assign a number to each screen using a numset A number is added to rp_screen to identify every screen. The screen numbers are affected at ratpoison start, when screens are sorted. On screen addition, a new number is requested. On screen deletion, the screen number is released. --- src/data.h | 6 ++++++ src/screen.c | 21 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/data.h b/src/data.h index 1e640e7..8019ec8 100644 --- a/src/data.h +++ b/src/data.h @@ -153,6 +153,9 @@ struct rp_group struct rp_global_screen { unsigned long fg_color, bg_color, fw_color, bw_color; /* The pixel color. */ + + /* This numset is responsible for giving out numbers for each screen */ + struct numset *numset; }; struct xrandr_info { @@ -170,6 +173,9 @@ struct rp_screen Colormap def_cmap; Cursor rat; + /* Screen number, handled by rp_global_screen numset */ + int number; + struct xrandr_info xrandr; /* Here to abstract over the Xrandr vs X screens difference */ diff --git a/src/screen.c b/src/screen.c index 240b876..e629419 100644 --- a/src/screen.c +++ b/src/screen.c @@ -217,12 +217,25 @@ screen_sort (void) return list_sort (NULL, &rp_screens, screen_cmp_left); } +static void +screen_set_numbers (void) +{ + rp_screen *cur; + + list_for_each_entry (cur, &rp_screens, node) + { + cur->number = numset_request (rp_glob_screen.numset); + } +} + static void init_global_screen (rp_global_screen *s) { int screen_num; screen_num = DefaultScreen (dpy); + + s->numset = numset_new (); s->fg_color = BlackPixel (dpy, screen_num); s->bg_color = WhitePixel (dpy, screen_num); s->fw_color = BlackPixel (dpy, screen_num); @@ -264,6 +277,7 @@ init_screens (void) } screen_sort (); + screen_set_numbers (); free (rr_outputs); } @@ -474,7 +488,7 @@ screen_dump (rp_screen *screen) sbuf_printf(s, "%s ", sbuf_get (screen->xrandr.name)); sbuf_printf_concat (s, "%d %d %d %d %d %d", - (rp_have_xrandr) ? screen->xrandr.output : screen->screen_num, + screen->number, screen->left, screen->top, screen->width, @@ -569,6 +583,8 @@ screen_add (int rr_output) screen = xmalloc (sizeof(*screen)); list_add (&screen->node, &rp_screens); + screen->number = numset_request (rp_glob_screen.numset); + if (!rp_current_screen) rp_current_screen = screen; @@ -602,6 +618,8 @@ screen_del (rp_screen *s) hide_window (cur_win); } + numset_release (rp_glob_screen.numset, s->number); + change_windows_screen (s, rp_current_screen); screen_free (s); @@ -656,4 +674,5 @@ screen_free_final (void) /* Relinquish our hold on the root window. */ XSelectInput(dpy, RootWindow (dpy, DefaultScreen (dpy)), 0); + numset_free (rp_glob_screen.numset); } -- cgit v1.2.3 From 2b1bf78cbd1e85f86439ed083a919ffc2080fba7 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Tue, 29 Nov 2016 20:00:50 +0100 Subject: Fix fdump and sselect Use screen numset in fdump and sselect. --- src/actions.c | 20 +++++++------------- src/screen.c | 10 +++++----- src/screen.h | 2 +- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/actions.c b/src/actions.c index 606116c..8d89a2d 100644 --- a/src/actions.c +++ b/src/actions.c @@ -4673,16 +4673,12 @@ cmd_sselect(int interactive UNUSED, struct cmdarg **args) if (new_screen < 0) return cmdret_new (RET_FAILURE, "sselect: out of range"); - if (new_screen < screen_count ()) - { - screen = screen_at (new_screen); - new_frame = screen_get_frame (screen, screen->current_frame); - set_active_frame (new_frame, 1); - } - else - { - return cmdret_new (RET_FAILURE, "sselect: out of range"); - } + screen = screen_number (new_screen); + if (!screen) + return cmdret_new (RET_FAILURE, "sselect: screen not found"); + + new_frame = screen_get_frame (screen, screen->current_frame); + set_active_frame (new_frame, 1); return cmdret_new (RET_SUCCESS, NULL); } @@ -5022,10 +5018,8 @@ cmd_fdump (int interactively UNUSED, struct cmdarg **args) if (snum < 0) return cmdret_new (RET_FAILURE, "fdump: invalid negative screen number"); - else if (snum >= screen_count ()) - return cmdret_new (RET_FAILURE, "fdump: unknown screen"); else - screen = screen_at (snum); + screen = screen_number (snum); } dump = fdump (screen); diff --git a/src/screen.c b/src/screen.c index e629419..3c49409 100644 --- a/src/screen.c +++ b/src/screen.c @@ -181,17 +181,17 @@ is_a_root_window (unsigned int w) } rp_screen * -screen_at (int index) +screen_number (int number) { - int i = 0; rp_screen *cur; + if (number < 0) + return NULL; + list_for_each_entry (cur, &rp_screens, node) { - if (index == i) + if (cur->number == number) return cur; - - i++; } return NULL; diff --git a/src/screen.h b/src/screen.h index 7d85951..0d5f68d 100644 --- a/src/screen.h +++ b/src/screen.h @@ -51,7 +51,7 @@ int screen_count (void); rp_screen *screen_next(void); rp_screen *screen_prev(void); -rp_screen *screen_at (int index); +rp_screen *screen_number (int number); void screen_sort(void); -- cgit v1.2.3 From e8e9267e52b30d6a30c4ef5f1b39f524e5c16645 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Tue, 29 Nov 2016 20:00:51 +0100 Subject: Fix sfdump Use screen numset in sfdump --- src/actions.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/actions.c b/src/actions.c index 8d89a2d..e4c1c4e 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5599,9 +5599,7 @@ cmd_sfdump (int interactively UNUSED, struct cmdarg **args UNUSED) list_for_each_entry (cur_screen, &rp_screens, node) { snprintf (screen_suffix, sizeof (screen_suffix), " %d,", - rp_have_xrandr ? - cur_screen->xrandr.output : - cur_screen->screen_num); + cur_screen->number); list_for_each_entry (cur_frame, &(cur_screen->frames), node) { -- cgit v1.2.3 From 565a004a183992418e6b64900044055dcd210d3a Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Tue, 29 Nov 2016 20:00:52 +0100 Subject: Fix sfrestore Use screen numset in sfrestore --- src/actions.c | 67 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/actions.c b/src/actions.c index e4c1c4e..7f3f541 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5622,18 +5622,21 @@ cmdret * cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) { char *copy, *ptr, *token; - long screen; + int snum; int out_of_screen = 0; - int restored = 0; int s_count = screen_count (); - struct sbuf *buffer[s_count]; - rp_screen *cur_screen; - int i; - return cmdret_new (RET_FAILURE, "FIXME: sfrestore is currently broken"); + struct sf_data { + rp_screen *screen; + struct sbuf *frames; + int ret_restore; + } sf_data[s_count]; + + int sf_index = 0; + int i; for (i = 0; i < s_count; i++) - buffer[i] = sbuf_new (0); + sf_data[i].frames = sbuf_new (0); copy = xstrdup (ARG_STRING (0)); @@ -5646,22 +5649,25 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) while (token != NULL) { + rp_screen *screen; + /* search for end of frameset */ ptr = token; while (*ptr != ')') ptr++; ptr++; - screen = string_to_positive_int (ptr); - - /* check that specified screen number is valid */ - if (screen >= 0 && screen < s_count) + snum = string_to_positive_int (ptr); + screen = screen_number(snum); + if (screen) { /* clobber screen number here, frestore() doesn't need it */ *ptr = '\0'; - sbuf_concat (buffer[screen], token); - sbuf_concat (buffer[screen], ","); - restored++; + sbuf_concat (sf_data[sf_index].frames, token); + sbuf_concat (sf_data[sf_index].frames, ","); + + sf_data[sf_index].screen = screen; + sf_index++; } else out_of_screen++; @@ -5673,23 +5679,42 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) free (copy); /* now restore the frames for each screen */ - list_for_each_entry (cur_screen, &rp_screens, node) + for (i = 0; i < sf_index; i++) { cmdret * ret; + rp_screen *cur_screen; + struct sbuf *cur_frames; + + cur_screen = sf_data[i].screen; + cur_frames = sf_data[i].frames; + push_frame_undo (cur_screen); /* fdump to stack */ - /* FIXME: store RET_SUCCESS || RET_FAILURE for each screen and output - it later */ - ret = frestore (sbuf_get (buffer[i]), cur_screen); + + ret = frestore (sbuf_get (cur_frames), cur_screen); + sf_data[i].ret_restore = ret->success; + cmdret_free (ret); - sbuf_free (buffer[i]); + sbuf_free (cur_frames); + } + + for (i = 0; i < sf_index; i++) + { + int ret; + + ret = sf_data[i].ret_restore; + if (ret != RET_SUCCESS) + { + return cmdret_new (ret, "Failed to restore frames for screen %d", + sf_data[i].screen->xrandr.output); + } } if (!out_of_screen) - return cmdret_new (RET_SUCCESS, "Restored %i Frame(s)", restored); + return cmdret_new (RET_SUCCESS, "Restored %i Frame(s)", sf_index); else return cmdret_new (RET_SUCCESS, "Restored %i Frame(s), %i Frame(s) out of Screen(s)", - restored, out_of_screen); + sf_index, out_of_screen); } cmdret * -- cgit v1.2.3 From 97ffa32dbeec660aae323aacf2a19b2ad7d144e0 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Tue, 29 Nov 2016 20:00:53 +0100 Subject: Add height dimension to screen sorting Screen are only sorted according to their width offset from origin ("left" in screen struct). Also sort screen that share a same width offset according to their height offset ("top" in screen struct). --- src/screen.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/screen.c b/src/screen.c index 3c49409..ddc03cb 100644 --- a/src/screen.c +++ b/src/screen.c @@ -198,15 +198,26 @@ screen_number (int number) } static int -screen_cmp_left (void *priv, struct list_head *a, struct list_head *b) +screen_cmp (void *priv, struct list_head *a, struct list_head *b) { rp_screen *sc_a = container_of (a, typeof(*sc_a), node); rp_screen *sc_b = container_of (b, typeof(*sc_b), node); if (sc_a->left < sc_b->left) - return -1; + { + return -1; + } else if (sc_a->left > sc_b->left) - return 1; + { + return 1; + } + else if (sc_a->left == sc_b->left) + { + if (sc_a->top < sc_b->top) + return -1; + else + return 1; + } return 0; } @@ -214,7 +225,7 @@ screen_cmp_left (void *priv, struct list_head *a, struct list_head *b) void screen_sort (void) { - return list_sort (NULL, &rp_screens, screen_cmp_left); + return list_sort (NULL, &rp_screens, screen_cmp); } static void -- cgit v1.2.3 From 3a784b57107d6bf1d65e6b01f744e91c2ec790c6 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Tue, 29 Nov 2016 20:00:54 +0100 Subject: Kill gcc uninitialized warning It is useless to initialize screen_count, but it prevents a gcc warning. --- src/screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screen.c b/src/screen.c index ddc03cb..7593f49 100644 --- a/src/screen.c +++ b/src/screen.c @@ -257,7 +257,7 @@ void init_screens (void) { int i; - int screen_count; + int screen_count = 0; int *rr_outputs = NULL; rp_screen *screen; -- cgit v1.2.3 From 3d24fae3ad1c59f7baa6dd90dd53bda39dbddf06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 22:12:29 +0100 Subject: Tighten screen sorting: comparing a screen with itself should return 0 --- src/screen.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/screen.c b/src/screen.c index 7593f49..9c7f1e6 100644 --- a/src/screen.c +++ b/src/screen.c @@ -204,20 +204,14 @@ screen_cmp (void *priv, struct list_head *a, struct list_head *b) rp_screen *sc_b = container_of (b, typeof(*sc_b), node); if (sc_a->left < sc_b->left) - { - return -1; - } - else if (sc_a->left > sc_b->left) - { - return 1; - } - else if (sc_a->left == sc_b->left) - { - if (sc_a->top < sc_b->top) - return -1; - else - return 1; - } + return -1; + if (sc_a->left > sc_b->left) + return 1; + + if (sc_a->top > sc_b->top) + return -1; + if (sc_a->top < sc_b->top) + return 1; return 0; } -- cgit v1.2.3 From 2d80ee07168cc3da3caea2837764042f7c25f118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 22:15:05 +0100 Subject: fdump: don't segfault if screen is not found --- src/actions.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/actions.c b/src/actions.c index 7f3f541..325ef78 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5019,7 +5019,11 @@ cmd_fdump (int interactively UNUSED, struct cmdarg **args) if (snum < 0) return cmdret_new (RET_FAILURE, "fdump: invalid negative screen number"); else - screen = screen_number (snum); + { + screen = screen_number (snum); + if (!screen) + return cmdret_new (RET_FAILURE, "fdump: screen %d not found", snum); + } } dump = fdump (screen); -- cgit v1.2.3 From 97035c0713a6cf5dfb704377724b113d96a776cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 22:16:36 +0100 Subject: Callers shouldn't pass a negative number to screen_number() --- src/screen.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/screen.c b/src/screen.c index 9c7f1e6..77ce41d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -185,9 +185,6 @@ screen_number (int number) { rp_screen *cur; - if (number < 0) - return NULL; - list_for_each_entry (cur, &rp_screens, node) { if (cur->number == number) -- cgit v1.2.3 From 61bfec557731c2bd4def6ead5c9bf1802a3249ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 22:17:53 +0100 Subject: sselect: print the screen number in case of failure --- src/actions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions.c b/src/actions.c index 325ef78..d59cafe 100644 --- a/src/actions.c +++ b/src/actions.c @@ -4675,7 +4675,7 @@ cmd_sselect(int interactive UNUSED, struct cmdarg **args) screen = screen_number (new_screen); if (!screen) - return cmdret_new (RET_FAILURE, "sselect: screen not found"); + return cmdret_new (RET_FAILURE, "sselect: screen %d not found", new_screen); new_frame = screen_get_frame (screen, screen->current_frame); set_active_frame (new_frame, 1); -- cgit v1.2.3 From 53f3fb0e9ead37acd3e16a8779b2e99944674e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 22:33:53 +0100 Subject: sfrestore: partial fix for frame allocation/deallocation There is still a problem with allocation of screens vs frames. A screen can have multiple frames (for now this triggers a segfault). --- src/actions.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/actions.c b/src/actions.c index d59cafe..73bc282 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5662,7 +5662,7 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) ptr++; snum = string_to_positive_int (ptr); - screen = screen_number(snum); + screen = screen_number (snum); if (screen) { /* clobber screen number here, frestore() doesn't need it */ @@ -5698,9 +5698,11 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) sf_data[i].ret_restore = ret->success; cmdret_free (ret); - sbuf_free (cur_frames); } + for (i = 0; i < s_count; i++) + sbuf_free (sf_data[i].frames); + for (i = 0; i < sf_index; i++) { int ret; -- cgit v1.2.3 From f32bfb18f15244e1f2bd65064edbc6dbd167031b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 22:39:34 +0100 Subject: sfrestore: in case of error, mention the screen number, not its xrandr id --- src/actions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions.c b/src/actions.c index 73bc282..63f7245 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5711,7 +5711,7 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) if (ret != RET_SUCCESS) { return cmdret_new (ret, "Failed to restore frames for screen %d", - sf_data[i].screen->xrandr.output); + sf_data[i].screen->number); } } -- cgit v1.2.3 From 110e3829bf79da7153143f99d301c41cd4c4c777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 23:08:55 +0100 Subject: Fix and simplify sfrestore Use a scratch buffer for each screen, this simplifies a lot allocations and iterations, and allows restoring screens that contain more than one frame. --- src/actions.c | 71 ++++++++++++++++++++--------------------------------------- src/data.h | 3 +++ src/screen.c | 2 ++ 3 files changed, 29 insertions(+), 47 deletions(-) diff --git a/src/actions.c b/src/actions.c index 63f7245..1134631 100644 --- a/src/actions.c +++ b/src/actions.c @@ -5626,21 +5626,14 @@ cmdret * cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) { char *copy, *ptr, *token; - int snum; - int out_of_screen = 0; - int s_count = screen_count (); - - struct sf_data { - rp_screen *screen; - struct sbuf *frames; - int ret_restore; - } sf_data[s_count]; - - int sf_index = 0; - int i; + rp_screen *screen; + int out_of_screen = 0, restored = 0; - for (i = 0; i < s_count; i++) - sf_data[i].frames = sbuf_new (0); + list_for_each_entry (screen, &rp_screens, node) + { + sbuf_free (screen->scratch_buffer); + screen->scratch_buffer = sbuf_new (0); + } copy = xstrdup (ARG_STRING (0)); @@ -5653,7 +5646,7 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) while (token != NULL) { - rp_screen *screen; + int snum; /* search for end of frameset */ ptr = token; @@ -5667,11 +5660,8 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) { /* clobber screen number here, frestore() doesn't need it */ *ptr = '\0'; - sbuf_concat (sf_data[sf_index].frames, token); - sbuf_concat (sf_data[sf_index].frames, ","); - - sf_data[sf_index].screen = screen; - sf_index++; + sbuf_concat (screen->scratch_buffer, token); + sbuf_concat (screen->scratch_buffer, ","); } else out_of_screen++; @@ -5683,44 +5673,31 @@ cmd_sfrestore (int interactively UNUSED, struct cmdarg **args) free (copy); /* now restore the frames for each screen */ - for (i = 0; i < sf_index; i++) + list_for_each_entry (screen, &rp_screens, node) { - cmdret * ret; - rp_screen *cur_screen; - struct sbuf *cur_frames; - - cur_screen = sf_data[i].screen; - cur_frames = sf_data[i].frames; + cmdret *ret; - push_frame_undo (cur_screen); /* fdump to stack */ + if (strlen (sbuf_get (screen->scratch_buffer)) == 0) + continue; - ret = frestore (sbuf_get (cur_frames), cur_screen); - sf_data[i].ret_restore = ret->success; + push_frame_undo (screen); /* fdump to stack */ + /* XXX save the failure of each frestore and display it in case of error */ + ret = frestore (sbuf_get (screen->scratch_buffer), screen); + if (ret->success) + restored++; cmdret_free (ret); - } - - for (i = 0; i < s_count; i++) - sbuf_free (sf_data[i].frames); - for (i = 0; i < sf_index; i++) - { - int ret; - - ret = sf_data[i].ret_restore; - if (ret != RET_SUCCESS) - { - return cmdret_new (ret, "Failed to restore frames for screen %d", - sf_data[i].screen->number); - } + sbuf_free (screen->scratch_buffer); + screen->scratch_buffer = NULL; } if (!out_of_screen) - return cmdret_new (RET_SUCCESS, "Restored %i Frame(s)", sf_index); + return cmdret_new (RET_SUCCESS, "screens restored: %d", restored); else return cmdret_new (RET_SUCCESS, - "Restored %i Frame(s), %i Frame(s) out of Screen(s)", - sf_index, out_of_screen); + "screens restored: %d, frames out of screen: %d", + restored, out_of_screen); } cmdret * diff --git a/src/data.h b/src/data.h index 8019ec8..eb662ce 100644 --- a/src/data.h +++ b/src/data.h @@ -197,6 +197,9 @@ struct rp_screen /* This structure can exist in a list. */ struct list_head node; + /* Used by sfrestore */ + struct sbuf *scratch_buffer; + #ifdef USE_XFT_FONT XftFont *xft_font; XftColor xft_fg_color, xft_bg_color; diff --git a/src/screen.c b/src/screen.c index 77ce41d..fedddfa 100644 --- a/src/screen.c +++ b/src/screen.c @@ -320,6 +320,8 @@ init_screen (rp_screen *s) /* Set the numset for the frames to our global numset. */ s->frames_numset = rp_frame_numset; + s->scratch_buffer = NULL; + /* Build the display string for each screen */ buf = sbuf_new (0); sbuf_printf (buf, "DISPLAY=%s", DisplayString (dpy)); -- cgit v1.2.3 From 4d12ba27413510a4d0128cb20e47aaa173fa266a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 1 Dec 2016 23:40:23 +0100 Subject: Bump to ratpoison-1.4.9-xrandr2 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a55591e..6c12560 100644 --- a/configure.ac +++ b/configure.ac @@ -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 -AC_INIT([ratpoison], [1.4.9-xrandr1], [ratpoison-devel@nongnu.org]) +AC_INIT([ratpoison], [1.4.9-xrandr2], [ratpoison-devel@nongnu.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/main.c]) -- cgit v1.2.3 From 94fcf440050defa49d9f726302a62d327d377e84 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:52 +0100 Subject: Remove useless argument from is_rp_window_for_screen function The screen argument is useless as this function operates on all screens. To find if a window belong to a specific ratpoison screen, function is_rp_window_for_given_screen may be used. --- src/events.c | 2 +- src/manage.c | 2 +- src/screen.c | 2 +- src/screen.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/events.c b/src/events.c index 5e1013a..e462d4f 100644 --- a/src/events.c +++ b/src/events.c @@ -82,7 +82,7 @@ new_window (XCreateWindowEvent *e) /* New windows belong to the current screen */ s = rp_current_screen; - if (is_rp_window_for_screen(e->window, s)) return; + if (is_rp_window_for_screen(e->window)) return; if (s && win == NULL && e->window != s->key_window diff --git a/src/manage.c b/src/manage.c index 2faab71..8b62a30 100644 --- a/src/manage.c +++ b/src/manage.c @@ -460,7 +460,7 @@ scanwins(rp_screen *s) for (i = 0; i < nwins; i++) { XGetWindowAttributes(dpy, wins[i], &attr); - if (is_rp_window_for_screen(wins[i], s) + if (is_rp_window_for_screen(wins[i]) || attr.override_redirect == True || unmanaged_window (wins[i])) continue; diff --git a/src/screen.c b/src/screen.c index fedddfa..b9bb696 100644 --- a/src/screen.c +++ b/src/screen.c @@ -468,7 +468,7 @@ is_rp_window_for_given_screen (Window w, rp_screen *s) } int -is_rp_window_for_screen(Window w, rp_screen *s) +is_rp_window_for_screen(Window w) { rp_screen *cur; diff --git a/src/screen.h b/src/screen.h index 0d5f68d..2072d36 100644 --- a/src/screen.h +++ b/src/screen.h @@ -39,7 +39,7 @@ void init_screens (void); void activate_screen (rp_screen *s); void deactivate_screen (rp_screen *s); -int is_rp_window_for_screen (Window w, rp_screen *s); +int is_rp_window_for_screen (Window w); int is_a_root_window (unsigned int w); char *screen_dump (rp_screen *screen); -- cgit v1.2.3 From 61516d64eb81d872d4e4d2a4ed50dbcb5d950557 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:53 +0100 Subject: Move function declaration to the right header find_screen is defined in screen.c so it makes more sense to declare it in screen.h --- src/ratpoison.h | 1 - src/screen.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ratpoison.h b/src/ratpoison.h index c98dd40..981a882 100644 --- a/src/ratpoison.h +++ b/src/ratpoison.h @@ -82,7 +82,6 @@ extern XGCValues gv; #include "format.h" void clean_up (void); -rp_screen *find_screen (Window w); void set_close_on_exec (int fd); const char *get_homedir (void); diff --git a/src/screen.h b/src/screen.h index 2072d36..67d8ab4 100644 --- a/src/screen.h +++ b/src/screen.h @@ -35,6 +35,7 @@ void frameset_free (struct list_head *head); rp_frame *screen_get_frame (rp_screen *s, int frame_num); rp_frame *screen_find_frame_by_frame (rp_screen *s, rp_frame *f); +rp_screen *find_screen (Window w); void init_screens (void); void activate_screen (rp_screen *s); void deactivate_screen (rp_screen *s); -- cgit v1.2.3 From f7c9339d236a9742b15700457787b7f6e64fb7c4 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:54 +0100 Subject: Add primary screen detection The user may specify that a screen is primary with xrandr. Save this information in ratpoison for future use. The use of XRRGetOutputPrimary forces us to bump xrandr supported revision from >=1.2 to >=1.3. --- src/data.h | 1 + src/xrandr.c | 15 ++++++++++++++- src/xrandr.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/data.h b/src/data.h index eb662ce..08f1667 100644 --- a/src/data.h +++ b/src/data.h @@ -161,6 +161,7 @@ struct rp_global_screen struct xrandr_info { int output; int crtc; + int primary; struct sbuf* name; }; diff --git a/src/xrandr.c b/src/xrandr.c index f1f3ef5..de0cde3 100644 --- a/src/xrandr.c +++ b/src/xrandr.c @@ -26,7 +26,7 @@ static int xrandr_evbase; #define XRANDR_MAJOR 1 -#define XRANDR_MINOR 2 +#define XRANDR_MINOR 3 void init_xrandr (void) @@ -110,12 +110,19 @@ xrandr_screen_crtc (int rr_crtc) return NULL; } +int +xrandr_is_primary (rp_screen *screen) +{ + return screen->xrandr.primary; +} + void xrandr_fill_screen (int rr_output, rp_screen *screen) { XRRScreenResources *res; XRROutputInfo *outinfo; XRRCrtcInfo *crtinfo; + RROutput primary; res = XRRGetScreenResourcesCurrent (dpy, RootWindow (dpy, DefaultScreen (dpy))); outinfo = XRRGetOutputInfo (dpy, res, rr_output); @@ -126,6 +133,12 @@ xrandr_fill_screen (int rr_output, rp_screen *screen) if (!crtinfo) goto free_out; + primary = XRRGetOutputPrimary (dpy, RootWindow (dpy, DefaultScreen (dpy))); + if (rr_output == primary) + screen->xrandr.primary = 1; + else + screen->xrandr.primary = 0; + screen->xrandr.name = sbuf_new (0); sbuf_concat (screen->xrandr.name, outinfo->name); diff --git a/src/xrandr.h b/src/xrandr.h index d765789..25ff830 100644 --- a/src/xrandr.h +++ b/src/xrandr.h @@ -26,6 +26,7 @@ void init_xrandr(void); int *xrandr_query_screen(int *screen_count); +int xrandr_is_primary (rp_screen *screen); void xrandr_fill_screen(int rr_output, rp_screen *screen); void xrandr_notify(XEvent *ev); -- cgit v1.2.3 From d8fab39242f683f84027402d8b174ff68a581811 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:56 +0100 Subject: Add a function to find a screen matching a given XWindowAttributes It allows to find the screen associated to a Window, using it's x and y position. --- src/screen.c | 18 ++++++++++++++++++ src/screen.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/screen.c b/src/screen.c index b9bb696..7bbc133 100644 --- a/src/screen.c +++ b/src/screen.c @@ -165,6 +165,24 @@ find_screen (Window w) return NULL; } +/* Given a window attr, return the rp_screen struct */ +rp_screen * +find_screen_by_attr (XWindowAttributes attr) +{ + rp_screen *cur; + + list_for_each_entry (cur, &rp_screens, node) + { + if (attr.x >= cur->left && + attr.x <= cur->left + cur->width && + attr.y >= cur->top && + attr.y <= cur->top + cur->height) + return cur; + } + + return NULL; +} + /* Return 1 if w is a root window of any of the screens. */ int is_a_root_window (unsigned int w) diff --git a/src/screen.h b/src/screen.h index 67d8ab4..69bc032 100644 --- a/src/screen.h +++ b/src/screen.h @@ -36,6 +36,8 @@ rp_frame *screen_get_frame (rp_screen *s, int frame_num); rp_frame *screen_find_frame_by_frame (rp_screen *s, rp_frame *f); rp_screen *find_screen (Window w); +rp_screen *find_screen_by_attr (XWindowAttributes w); + void init_screens (void); void activate_screen (rp_screen *s); void deactivate_screen (rp_screen *s); -- cgit v1.2.3 From 2afbce75d61319e5fbbc7c8a1a4844870ef6a9e7 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:57 +0100 Subject: Simplify scanwins function Use find_screen_by_attr function, remove screen argument and a useless debug message. --- src/main.c | 3 ++- src/manage.c | 25 +++++++++++-------------- src/manage.h | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main.c b/src/main.c index ca5ebc8..cce4f94 100644 --- a/src/main.c +++ b/src/main.c @@ -743,9 +743,10 @@ main (int argc, char *argv[]) { if (!rp_current_screen) rp_current_screen = cur; - scanwins (cur); } + scanwins (); + if (read_startup_files (alt_rcfile) == -1) return EXIT_FAILURE; diff --git a/src/manage.c b/src/manage.c index 8b62a30..2c12f09 100644 --- a/src/manage.c +++ b/src/manage.c @@ -447,37 +447,34 @@ unmanage (rp_window *w) /* When starting up scan existing windows and start managing them. */ void -scanwins(rp_screen *s) +scanwins () { rp_window *win; XWindowAttributes attr; unsigned int i, nwins; Window dw1, dw2, *wins; - XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins); + XQueryTree(dpy, rp_glob_screen.root, &dw1, &dw2, &wins, &nwins); PRINT_DEBUG (("windows: %d\n", nwins)); for (i = 0; i < nwins; i++) { + rp_screen *screen; + XGetWindowAttributes(dpy, wins[i], &attr); if (is_rp_window_for_screen(wins[i]) || attr.override_redirect == True || unmanaged_window (wins[i])) continue; - { - XWindowAttributes root_attr; - - XGetWindowAttributes (dpy, s->root, &root_attr); - PRINT_DEBUG (("attrs: %d %d %d %d %d %d\n", root_attr.x, root_attr.y, - s->left, s->top, s->left + s->width, s->top + s->height));} - if (rp_have_xrandr - && ((attr.x > s->left + s->width) - || (attr.x < s->left) - || (attr.y > s->top + s->height) - || (attr.y < s->top))) continue; + screen = find_screen_by_attr (attr); + if (!screen) + { + PRINT_ERROR (("Unable to find a screen by window attributes\n")); + continue; + } - win = add_to_window_list (s, wins[i]); + win = add_to_window_list (screen, wins[i]); PRINT_DEBUG (("map_state: %s\n", attr.map_state == IsViewable ? "IsViewable": diff --git a/src/manage.h b/src/manage.h index 6d5f1f5..22bb169 100644 --- a/src/manage.h +++ b/src/manage.h @@ -29,7 +29,7 @@ char *list_unmanaged_windows (void); void add_unmanaged_window (char *name); int unmanaged_window (Window w); rp_screen* current_screen (void); -void scanwins(rp_screen *s); +void scanwins (); void unmanage (rp_window *w); int update_window_name (rp_window *win); void update_normal_hints (rp_window *win); -- cgit v1.2.3 From 25ec4e4ad39fc1074d1ac7949103b70ea4790cb9 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:58 +0100 Subject: Select xrandr primary screen at startup if possible If xrandr support is enabled and a screen is marked primary, use it as current screen at startup. Otherwise, use the first screen in sorted screen list as current screen at startup. --- src/main.c | 7 ------- src/screen.c | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index cce4f94..76af702 100644 --- a/src/main.c +++ b/src/main.c @@ -589,7 +589,6 @@ main (int argc, char *argv[]) int c; char **cmd = NULL; int cmd_count = 0; - rp_screen *cur; char *display = NULL; unsigned char interactive = 0; char *alt_rcfile = NULL; @@ -739,12 +738,6 @@ main (int argc, char *argv[]) initialize_default_keybindings (); history_load (); - list_for_each_entry (cur, &rp_screens, node) - { - if (!rp_current_screen) - rp_current_screen = cur; - } - scanwins (); if (read_startup_files (alt_rcfile) == -1) diff --git a/src/screen.c b/src/screen.c index 7bbc133..1f720de 100644 --- a/src/screen.c +++ b/src/screen.c @@ -248,6 +248,32 @@ screen_set_numbers (void) } } +static void +screen_select_primary (void) +{ + rp_screen *cur; + + /* By default, take the first screen as current screen */ + list_first(cur, &rp_screens, node); + if (!rp_current_screen) + rp_current_screen = cur; + +#ifdef HAVE_XRANDR + if (!rp_have_xrandr) + return; + + list_for_each_entry (cur, &rp_screens, node) + { + if (xrandr_is_primary(cur)) { + rp_current_screen = cur; + PRINT_DEBUG(("Xrandr primary screen %d detected\n", + rp_current_screen->number)); + break; + } + } +#endif +} + static void init_global_screen (rp_global_screen *s) { @@ -298,6 +324,7 @@ init_screens (void) screen_sort (); screen_set_numbers (); + screen_select_primary (); free (rr_outputs); } -- cgit v1.2.3 From 18ec858a4935a217bb41f01a546b2c7a8c25a72b Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 7 Dec 2016 10:03:55 +0100 Subject: Store RootWindow in global_screen structure Every screen stores a copy of xrandr RootWindow even if they all share the same RootWindow. This patch stores the RootWindow in a global location for all screens. Further work is required to remove RootWindow from per screen structure. --- src/data.h | 1 + src/screen.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/data.h b/src/data.h index 08f1667..3975955 100644 --- a/src/data.h +++ b/src/data.h @@ -152,6 +152,7 @@ struct rp_group struct rp_global_screen { + Window root; unsigned long fg_color, bg_color, fw_color, bw_color; /* The pixel color. */ /* This numset is responsible for giving out numbers for each screen */ diff --git a/src/screen.c b/src/screen.c index 1f720de..095040c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -280,6 +280,7 @@ init_global_screen (rp_global_screen *s) int screen_num; screen_num = DefaultScreen (dpy); + s->root = RootWindow (dpy, screen_num); s->numset = numset_new (); s->fg_color = BlackPixel (dpy, screen_num); -- cgit v1.2.3 From 597ab87c290016fec5c1d333915c9e1dfdde1627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Thu, 8 Dec 2016 20:36:33 +0100 Subject: Bump to xrandr3. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6c12560..43e2a6a 100644 --- a/configure.ac +++ b/configure.ac @@ -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 -AC_INIT([ratpoison], [1.4.9-xrandr2], [ratpoison-devel@nongnu.org]) +AC_INIT([ratpoison], [1.4.9-xrandr3], [ratpoison-devel@nongnu.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/main.c]) -- cgit v1.2.3 From 8637e3d69e744fa6efca981d830e344d3ab122dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 9 Dec 2016 16:30:52 +0100 Subject: Adapt function name --- src/events.c | 2 +- src/manage.c | 2 +- src/screen.c | 2 +- src/screen.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/events.c b/src/events.c index e462d4f..e87bce2 100644 --- a/src/events.c +++ b/src/events.c @@ -82,7 +82,7 @@ new_window (XCreateWindowEvent *e) /* New windows belong to the current screen */ s = rp_current_screen; - if (is_rp_window_for_screen(e->window)) return; + if (is_rp_window (e->window)) return; if (s && win == NULL && e->window != s->key_window diff --git a/src/manage.c b/src/manage.c index 2c12f09..0c1877d 100644 --- a/src/manage.c +++ b/src/manage.c @@ -462,7 +462,7 @@ scanwins () rp_screen *screen; XGetWindowAttributes(dpy, wins[i], &attr); - if (is_rp_window_for_screen(wins[i]) + if (is_rp_window (wins[i]) || attr.override_redirect == True || unmanaged_window (wins[i])) continue; diff --git a/src/screen.c b/src/screen.c index 095040c..8b624c7 100644 --- a/src/screen.c +++ b/src/screen.c @@ -514,7 +514,7 @@ is_rp_window_for_given_screen (Window w, rp_screen *s) } int -is_rp_window_for_screen(Window w) +is_rp_window (Window w) { rp_screen *cur; diff --git a/src/screen.h b/src/screen.h index 69bc032..fdc0748 100644 --- a/src/screen.h +++ b/src/screen.h @@ -42,7 +42,7 @@ void init_screens (void); void activate_screen (rp_screen *s); void deactivate_screen (rp_screen *s); -int is_rp_window_for_screen (Window w); +int is_rp_window (Window w); int is_a_root_window (unsigned int w); char *screen_dump (rp_screen *screen); -- cgit v1.2.3 From 7ce2f7e14abee30a84181bc991becc06bcc70ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 9 Dec 2016 16:38:28 +0100 Subject: no parameter -> void; C and C++ differ here --- src/manage.c | 2 +- src/manage.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/manage.c b/src/manage.c index 0c1877d..4296480 100644 --- a/src/manage.c +++ b/src/manage.c @@ -447,7 +447,7 @@ unmanage (rp_window *w) /* When starting up scan existing windows and start managing them. */ void -scanwins () +scanwins (void) { rp_window *win; XWindowAttributes attr; diff --git a/src/manage.h b/src/manage.h index 22bb169..130ca65 100644 --- a/src/manage.h +++ b/src/manage.h @@ -29,7 +29,7 @@ char *list_unmanaged_windows (void); void add_unmanaged_window (char *name); int unmanaged_window (Window w); rp_screen* current_screen (void); -void scanwins (); +void scanwins (void); void unmanage (rp_window *w); int update_window_name (rp_window *win); void update_normal_hints (rp_window *win); -- cgit v1.2.3 From 3fabca8d30161ade3c77dfec575708aa1ed7fcdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 9 Dec 2016 16:40:39 +0100 Subject: Dead decl --- src/manage.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/manage.h b/src/manage.h index 130ca65..e83a5f2 100644 --- a/src/manage.h +++ b/src/manage.h @@ -28,7 +28,6 @@ void clear_unmanaged_list (void); char *list_unmanaged_windows (void); void add_unmanaged_window (char *name); int unmanaged_window (Window w); -rp_screen* current_screen (void); void scanwins (void); void unmanage (rp_window *w); int update_window_name (rp_window *win); -- cgit v1.2.3 From ec084368bf4a6975ed96ac1bc7e51dd1d86dfc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 9 Dec 2016 16:42:34 +0100 Subject: Yet another function that doesn't take arguments any more --- src/screen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/screen.c b/src/screen.c index 8b624c7..ca7bb2f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -571,7 +571,7 @@ screen_prev (void) } static void -screen_remove_current (rp_screen *s) +screen_remove_current (void) { rp_screen *new_screen; rp_frame *new_frame; @@ -658,7 +658,7 @@ screen_del (rp_screen *s) * focus the next one. */ if (s == rp_current_screen) { - screen_remove_current (s); + screen_remove_current (); } else { rp_frame *cur_frame; rp_window *cur_win; -- cgit v1.2.3 From 3cce1aa561ba3510495787370350a92f147da63f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 9 Dec 2016 16:43:22 +0100 Subject: Unused param --- src/screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screen.c b/src/screen.c index ca7bb2f..d8f580f 100644 --- a/src/screen.c +++ b/src/screen.c @@ -213,7 +213,7 @@ screen_number (int number) } static int -screen_cmp (void *priv, struct list_head *a, struct list_head *b) +screen_cmp (void *priv UNUSED, struct list_head *a, struct list_head *b) { rp_screen *sc_a = container_of (a, typeof(*sc_a), node); rp_screen *sc_b = container_of (b, typeof(*sc_b), node); -- cgit v1.2.3 From 31d4ca8f900d0d8db2a3ac6123c3c445cfa6346a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Courr=C3=A8ges-Anglas?= Date: Fri, 9 Dec 2016 16:43:47 +0100 Subject: Bump to xrandr4 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 43e2a6a..3b4af55 100644 --- a/configure.ac +++ b/configure.ac @@ -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 -AC_INIT([ratpoison], [1.4.9-xrandr3], [ratpoison-devel@nongnu.org]) +AC_INIT([ratpoison], [1.4.9-xrandr4], [ratpoison-devel@nongnu.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/main.c]) -- cgit v1.2.3 From 5318f014451620f32a264d01f620562e973f3a64 Mon Sep 17 00:00:00 2001 From: Joseph Mingrone Date: Sun, 11 Dec 2016 19:03:29 -0400 Subject: Update screen-aware focus* commands after changes to support XRandR This is an update to Pedro Silva's patch, so that it applies against the xrandr branch. That patch introduced four new functions, frame_*_abs, which report a frame's left, right, top, and bottom coordinates offset by it's screen arrangement. This allows the use of the focus* commands as additional screen navigation tools, and has the added benefit of making the find_frame_* functions clearer. --- doc/ratpoison.texi | 4 +++- src/frame.c | 27 +++++++++++++++++++++++++++ src/frame.h | 4 ++++ src/split.c | 44 ++++++++++++++++++++++++-------------------- 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/doc/ratpoison.texi b/doc/ratpoison.texi index da9da16..8876db1 100644 --- a/doc/ratpoison.texi +++ b/doc/ratpoison.texi @@ -904,7 +904,9 @@ window.'' ratpoison means there's no other window to switch to in the current screen. If you want to switch to the other xterm you can switch to it by name (use @command{select} or @kbd{C-t '}), by number, or you can use @command{nextscreen}, @command{prevscreen}, and -@command{sselect}. +@command{sselect}. Note, however, that the commands +@command{focusright}, @command{focusleft}, @command{focusup}, and +@command{focusdown} do work across screens. @deffn Command nextscreen This jumps you to the next X11 screen. @command{nextscreen} is diff --git a/src/frame.c b/src/frame.c index c42e2ab..95e4952 100644 --- a/src/frame.c +++ b/src/frame.c @@ -47,6 +47,33 @@ frame_bottom (rp_frame *frame) return frame->y + frame->height; } + +int +frame_left_abs (rp_frame *frame) +{ + rp_screen *s = frames_screen (frame); + return s->left + frame->x; +} + +int +frame_top_abs (rp_frame *frame) +{ + rp_screen *s = frames_screen (frame); + return s->top + frame->y; +} + +int +frame_right_abs (rp_frame *frame) +{ + return frame_left_abs (frame) + frame->width; +} + +int +frame_bottom_abs (rp_frame *frame) +{ + return frame_top_abs (frame) + frame->height; +} + int frame_width(rp_frame *frame) { diff --git a/src/frame.h b/src/frame.h index 611ecc0..f78f86c 100644 --- a/src/frame.h +++ b/src/frame.h @@ -35,6 +35,10 @@ int frame_bottom (rp_frame *frame); int frame_right (rp_frame *frame); int frame_top (rp_frame *frame); int frame_left (rp_frame *frame); +int frame_bottom_abs (rp_frame *frame); +int frame_right_abs (rp_frame *frame); +int frame_top_abs (rp_frame *frame); +int frame_left_abs (rp_frame *frame); rp_frame *frame_new (rp_screen *s); void frame_free (rp_screen *s, rp_frame *f); diff --git a/src/split.c b/src/split.c index 5f74777..7042a55 100644 --- a/src/split.c +++ b/src/split.c @@ -997,15 +997,16 @@ show_frame_message (char *msg) rp_frame * find_frame_up (rp_frame *frame) { - rp_screen *s = frames_screen (frame); + rp_screen *s; rp_frame *cur; - list_for_each_entry (cur, &s->frames, node) + list_for_each_entry (s, &rp_screens, node) { - if (frame->y == cur->y + cur->height) + list_for_each_entry (cur, &s->frames, node) { - if (frame->x >= cur->x && frame->x < cur->x + cur->width) - return cur; + if (frame_top_abs (frame) == frame_bottom_abs (cur)) + if (frame_right_abs (frame) >= frame_left_abs (cur) && frame_left_abs (frame) <= frame_right_abs (cur)) + return cur; } } @@ -1015,15 +1016,16 @@ find_frame_up (rp_frame *frame) rp_frame * find_frame_down (rp_frame *frame) { - rp_screen *s = frames_screen (frame); + rp_screen *s; rp_frame *cur; - list_for_each_entry (cur, &s->frames, node) + list_for_each_entry (s, &rp_screens, node) { - if (frame->y + frame->height == cur->y) + list_for_each_entry (cur, &s->frames, node) { - if (frame->x >= cur->x && frame->x < cur->x + cur->width) - return cur; + if (frame_bottom_abs (frame) == frame_top_abs (cur)) + if (frame_right_abs (frame) >= frame_left_abs (cur) && frame_left_abs (frame) <= frame_right_abs (cur)) + return cur; } } @@ -1033,15 +1035,16 @@ find_frame_down (rp_frame *frame) rp_frame * find_frame_left (rp_frame *frame) { - rp_screen *s = frames_screen (frame); + rp_screen *s; rp_frame *cur; - list_for_each_entry (cur, &s->frames, node) + list_for_each_entry (s, &rp_screens, node) { - if (frame->x == cur->x + cur->width) + list_for_each_entry (cur, &s->frames, node) { - if (frame->y >= cur->y && frame->y < cur->y + cur->height) - return cur; + if (frame_left_abs (frame) == frame_right_abs (cur)) + if (frame_top_abs (frame) >= frame_top_abs (cur) && frame_top_abs (frame) < frame_bottom_abs (cur)) + return cur; } } @@ -1051,15 +1054,16 @@ find_frame_left (rp_frame *frame) rp_frame * find_frame_right (rp_frame *frame) { - rp_screen *s = frames_screen (frame); + rp_screen *s; rp_frame *cur; - list_for_each_entry (cur, &s->frames, node) + list_for_each_entry (s, &rp_screens, node) { - if (frame->x + frame->width == cur->x) + list_for_each_entry (cur, &s->frames, node) { - if (frame->y >= cur->y && frame->y < cur->y + cur->height) - return cur; + if (frame_right_abs (frame) == frame_left_abs (cur)) + if (frame_top_abs (frame) >= frame_top_abs (cur) && frame_top_abs (frame) < frame_bottom_abs (cur)) + return cur; } } -- cgit v1.2.3 From cc68614a5c1c83421668556cf732c341c8da83f9 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 14 Dec 2016 19:53:59 +0100 Subject: Add a hide_screen_windows function This function is useful to find the windows displayed on a specific screen and hide them. --- src/manage.c | 14 ++++++++++++++ src/manage.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/manage.c b/src/manage.c index 4296480..f2a15f5 100644 --- a/src/manage.c +++ b/src/manage.c @@ -978,3 +978,17 @@ hide_others (rp_window *win) hide_window (cur); } } + +/* Hide any window displayed on the given screen */ +void +hide_screen_windows (rp_screen *s) +{ + rp_frame *cur_frame; + rp_window *cur_win; + + list_for_each_entry (cur_frame, &s->frames, node) + { + cur_win = find_window_number (cur_frame->win_number); + hide_window (cur_win); + } +} diff --git a/src/manage.h b/src/manage.h index e83a5f2..6788485 100644 --- a/src/manage.h +++ b/src/manage.h @@ -55,5 +55,6 @@ void unhide_all_windows (void); void unhide_window_below (rp_window *win); void withdraw_window (rp_window *win); void hide_others (rp_window *win); +void hide_screen_windows (rp_screen *s); #endif /* ! _RATPOISION_MANAGE_H */ -- cgit v1.2.3 From 399bdf758d11bc812ff958bfacba9720f3d95d84 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 14 Dec 2016 19:54:00 +0100 Subject: Fix frozen state when a new screen appears after all screens have been removed Handle correctly the fact that the deleted screen could be the last one. If a screen is plugged, and no other screens are present, give focus to it's key window. --- src/screen.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/screen.c b/src/screen.c index d8f580f..cfcf2f8 100644 --- a/src/screen.c +++ b/src/screen.c @@ -635,11 +635,6 @@ screen_add (int rr_output) screen->number = numset_request (rp_glob_screen.numset); - if (!rp_current_screen) - rp_current_screen = screen; - - change_windows_screen (NULL, screen); - #ifdef HAVE_XRANDR if (rp_have_xrandr) xrandr_fill_screen (rr_output, screen); @@ -647,30 +642,42 @@ screen_add (int rr_output) init_screen (screen); init_frame_list (screen); + if (screen_count () == 1) + { + rp_current_screen = screen; + change_windows_screen (NULL, rp_current_screen); + set_window_focus (rp_current_screen->key_window); + } + return screen; } void screen_del (rp_screen *s) { - /* - * The deleted screen cannot be the current screen anymore, - * focus the next one. - */ - if (s == rp_current_screen) { - screen_remove_current (); - } else { - rp_frame *cur_frame; - rp_window *cur_win; + if (screen_count () == 1) + { + hide_screen_windows (s); + rp_current_screen = NULL; + } + else if (s == rp_current_screen) + { + /* + * The deleted screen cannot be the current screen anymore, + * focus the next one. + */ + screen_remove_current (); + } + else + { + hide_screen_windows (s); + } - cur_frame = screen_get_frame (s, s->current_frame); - cur_win = find_window_number (cur_frame->win_number); - hide_window (cur_win); - } + /* Affect window's screen backpointer to the new current screen */ + change_windows_screen (s, rp_current_screen); numset_release (rp_glob_screen.numset, s->number); - change_windows_screen (s, rp_current_screen); screen_free (s); list_del (&s->node); -- cgit v1.2.3 From 2bda8bc2933dc3be318fbb7d1e290cd6ff4b1262 Mon Sep 17 00:00:00 2001 From: Mathieu OTHACEHE Date: Wed, 28 Dec 2016 14:41:25 +0100 Subject: screen: rewrite screen_del conditions Rewrite screen_del conditional imbrications for a better readability. No functional changes here. --- src/screen.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/screen.c b/src/screen.c index cfcf2f8..2c36a6b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -655,18 +655,21 @@ screen_add (int rr_output) void screen_del (rp_screen *s) { - if (screen_count () == 1) - { - hide_screen_windows (s); - rp_current_screen = NULL; - } - else if (s == rp_current_screen) + if (s == rp_current_screen) { - /* - * The deleted screen cannot be the current screen anymore, - * focus the next one. - */ - screen_remove_current (); + if (screen_count () == 1) + { + hide_screen_windows (s); + rp_current_screen = NULL; + } + else + { + /* + * The deleted screen cannot be the current screen anymore, + * focus the next one. + */ + screen_remove_current (); + } } else { -- cgit v1.2.3