From 91b1847c0ba49a43af475ae3f02cdef8908be905 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Sat, 6 Oct 2012 07:14:53 -0700 Subject: [PATCH] Tab to 4sp. No actual code changes. --- src/config.cpp | 56 +-- src/config.in.h | 26 +- src/dimensions.h | 12 +- src/grid.cpp | 104 ++-- src/grid.h | 16 +- src/main.cpp | 394 ++++++++-------- src/neighbor.cpp | 450 +++++++++--------- src/neighbor.h | 2 +- src/pos.h | 70 +-- src/position.cpp | 860 +++++++++++++++++----------------- src/position.h | 56 +-- src/viewport-imp-ewmh.cpp | 114 ++--- src/viewport-imp-ewmh.h | 8 +- src/viewport-imp-xinerama.cpp | 412 ++++++++-------- src/viewport-imp-xinerama.h | 8 +- src/viewport.cpp | 72 +-- src/viewport.h | 10 +- src/window.cpp | 736 ++++++++++++++--------------- src/window.h | 24 +- src/x11-util.cpp | 82 ++-- src/x11-util.h | 6 +- 21 files changed, 1759 insertions(+), 1759 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 070af98..aa95a43 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -21,32 +21,32 @@ #include namespace config { - FILE *fout = stdout, *ferr = stderr; - bool debug_enabled = false; - - void _debug(const char* format, ...) { - if (debug_enabled) { - va_list args; - va_start(args, format); - vfprintf(fout, format, args); - va_end(args); - fprintf(fout, "\n"); - } - } - - void _log(const char* format, ...) { - va_list args; - va_start(args, format); - vfprintf(fout, format, args); - va_end(args); - fprintf(fout, "\n"); - } - - void _error(const char* format, ...) { - va_list args; - va_start(args, format); - vfprintf(ferr, format, args); - va_end(args); - fprintf(ferr, "\n"); - } + FILE *fout = stdout, *ferr = stderr; + bool debug_enabled = false; + + void _debug(const char* format, ...) { + if (debug_enabled) { + va_list args; + va_start(args, format); + vfprintf(fout, format, args); + va_end(args); + fprintf(fout, "\n"); + } + } + + void _log(const char* format, ...) { + va_list args; + va_start(args, format); + vfprintf(fout, format, args); + va_end(args); + fprintf(fout, "\n"); + } + + void _error(const char* format, ...) { + va_list args; + va_start(args, format); + vfprintf(ferr, format, args); + va_end(args); + fprintf(ferr, "\n"); + } } diff --git a/src/config.in.h b/src/config.in.h index 8bcc248..9f5f2d7 100644 --- a/src/config.in.h +++ b/src/config.in.h @@ -49,24 +49,24 @@ #cmakedefine USE_XINERAMA namespace config { - static const int - VERSION_MAJOR = @gridmgr_VERSION_MAJOR@, - VERSION_MINOR = @gridmgr_VERSION_MINOR@, - VERSION_PATCH = @gridmgr_VERSION_PATCH@; + static const int + VERSION_MAJOR = @gridmgr_VERSION_MAJOR@, + VERSION_MINOR = @gridmgr_VERSION_MINOR@, + VERSION_PATCH = @gridmgr_VERSION_PATCH@; - static const char VERSION_STRING[] = "@gridmgr_VERSION_MAJOR@.@gridmgr_VERSION_MINOR@.@gridmgr_VERSION_PATCH@"; - static const char BUILD_DATE[] = __TIMESTAMP__; + static const char VERSION_STRING[] = "@gridmgr_VERSION_MAJOR@.@gridmgr_VERSION_MINOR@.@gridmgr_VERSION_PATCH@"; + static const char BUILD_DATE[] = __TIMESTAMP__; - /* DONT USE THESE, use DEBUG()/LOG()/ERROR() instead: */ + /* DONT USE THESE, use DEBUG()/LOG()/ERROR() instead: */ - extern FILE *fout; - extern FILE *ferr; + extern FILE *fout; + extern FILE *ferr; - extern bool debug_enabled; - void _debug(const char* format, ...); + extern bool debug_enabled; + void _debug(const char* format, ...); - void _log(const char* format, ...); - void _error(const char* format, ...); + void _log(const char* format, ...); + void _error(const char* format, ...); } #endif diff --git a/src/dimensions.h b/src/dimensions.h index dd1fa03..acc9b40 100644 --- a/src/dimensions.h +++ b/src/dimensions.h @@ -20,12 +20,12 @@ */ struct Dimensions { - //position of the top left corner of the screen - long x; - long y; - //width,height are 'exterior' size, including any borders/decorations - unsigned long width; - unsigned long height; + //position of the top left corner of the screen + long x; + long y; + //width,height are 'exterior' size, including any borders/decorations + unsigned long width; + unsigned long height; }; #endif diff --git a/src/grid.cpp b/src/grid.cpp index fe45134..b10c261 100644 --- a/src/grid.cpp +++ b/src/grid.cpp @@ -23,67 +23,67 @@ #include "window.h" bool grid::set_active(POS window) { - return window::select_activate(window); + return window::select_activate(window); } bool grid::set_position(POS gridpos, POS monitor) { - // initializes to the currently active window - ActiveWindow win; + // initializes to the currently active window + ActiveWindow win; - // get current window's dimensions - Dimensions cur_window; - if (!win.Size(cur_window)) { - return false; - } + // get current window's dimensions + Dimensions cur_window; + if (!win.Size(cur_window)) { + return false; + } - /* special case: if the active window is fullscreen, the desktop workarea is - wrong (ie the obscured taskbar extents aren't included). get around this - by unfullscreening the window first (if applicable). but return the - window's dimensions from when it was fullscreened/shaded. */ - win.DeFullscreen();// disregard failure + /* special case: if the active window is fullscreen, the desktop workarea is + wrong (ie the obscured taskbar extents aren't included). get around this + by unfullscreening the window first (if applicable). but return the + window's dimensions from when it was fullscreened/shaded. */ + win.DeFullscreen();// disregard failure - Dimensions cur_viewport, next_viewport; - { - ViewportCalc vcalc(cur_window); - // cur_window + monitor -> cur_viewport + next_viewport - if (!vcalc.Viewports(monitor, cur_viewport, next_viewport)) { - return false; - } - } + Dimensions cur_viewport, next_viewport; + { + ViewportCalc vcalc(cur_window); + // cur_window + monitor -> cur_viewport + next_viewport + if (!vcalc.Viewports(monitor, cur_viewport, next_viewport)) { + return false; + } + } - /* using the requested position and current dimensions, - calculate and set new dimensions */ - PositionCalc pcalc(cur_window); + /* using the requested position and current dimensions, + calculate and set new dimensions */ + PositionCalc pcalc(cur_window); - State cur_state, next_state; - if (/* cur_viewport + cur_window -> cur_state */ - !pcalc.CurState(cur_viewport, cur_state) || - /* cur_state + pos -> next_state */ - !pcalc.NextState(cur_state, gridpos, next_state)) { - return false; - } + State cur_state, next_state; + if (/* cur_viewport + cur_window -> cur_state */ + !pcalc.CurState(cur_viewport, cur_state) || + /* cur_state + pos -> next_state */ + !pcalc.NextState(cur_state, gridpos, next_state)) { + return false; + } - Dimensions next_dim; - if (next_state.pos == POS_UNKNOWN && next_state.mode == MODE_UNKNOWN) { - // window doesnt currently have a state, and user didn't specify one - pcalc.ViewportToDim(cur_viewport, next_viewport, next_dim); - } else { - // next_viewport + next_state -> next_dim - if (!pcalc.StateToDim(next_viewport, next_state, next_dim)) { - return false; - } - } + Dimensions next_dim; + if (next_state.pos == POS_UNKNOWN && next_state.mode == MODE_UNKNOWN) { + // window doesnt currently have a state, and user didn't specify one + pcalc.ViewportToDim(cur_viewport, next_viewport, next_dim); + } else { + // next_viewport + next_state -> next_dim + if (!pcalc.StateToDim(next_viewport, next_state, next_dim)) { + return false; + } + } - // move the window to next_dim - if (!win.DeShade() || !win.MoveResize(next_dim)) { - return false; - } + // move the window to next_dim + if (!win.DeShade() || !win.MoveResize(next_dim)) { + return false; + } - if (next_state.pos == POS_CENTER && - next_state.mode == MODE_THREE_COL_L) { - /* if we're going to be filling the screen anyway, just maximize - (do this after MoveResize so that viewport changes are respected) */ - win.Maximize();// disregard failure - } - return true; + if (next_state.pos == POS_CENTER && + next_state.mode == MODE_THREE_COL_L) { + /* if we're going to be filling the screen anyway, just maximize + (do this after MoveResize so that viewport changes are respected) */ + win.Maximize();// disregard failure + } + return true; } diff --git a/src/grid.h b/src/grid.h index de3d83f..7445d99 100644 --- a/src/grid.h +++ b/src/grid.h @@ -22,14 +22,14 @@ #include "pos.h" namespace grid { - /* Selects and makes active the window in the specified direction relative - * to the currently active window. */ - bool set_active(POS window); - - /* Selects the active window and moves/resizes it to the requested - * position/monitor, according to its current state. - * Returns true if successful, false otherwise. */ - bool set_position(POS gridpos, POS monitor); + /* Selects and makes active the window in the specified direction relative + * to the currently active window. */ + bool set_active(POS window); + + /* Selects the active window and moves/resizes it to the requested + * position/monitor, according to its current state. + * Returns true if successful, false otherwise. */ + bool set_position(POS gridpos, POS monitor); } #endif diff --git a/src/main.cpp b/src/main.cpp index 2c1a130..43bcb4d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,220 +28,220 @@ #define TIMESTR_MAX 128 // arbitrarily large static void syntax(char* appname) { - ERROR_RAWDIR(""); - ERROR_RAWDIR("gridmgr v%s (built %s)", - config::VERSION_STRING, - config::BUILD_DATE); - ERROR_RAWDIR(""); - ERROR_RAWDIR("Performs one or more of the following, in this order:"); - ERROR_RAWDIR("- Activate a window adjacent to the current window."); + ERROR_RAWDIR(""); + ERROR_RAWDIR("gridmgr v%s (built %s)", + config::VERSION_STRING, + config::BUILD_DATE); + ERROR_RAWDIR(""); + ERROR_RAWDIR("Performs one or more of the following, in this order:"); + ERROR_RAWDIR("- Activate a window adjacent to the current window."); #ifdef USE_XINERAMA - ERROR_RAWDIR("- Move active window to an adjacent monitor."); + ERROR_RAWDIR("- Move active window to an adjacent monitor."); #endif - ERROR_RAWDIR("- Position active window on a grid layout."); - ERROR_RAWDIR(""); + ERROR_RAWDIR("- Position active window on a grid layout."); + ERROR_RAWDIR(""); #ifdef USE_XINERAMA - ERROR_RAWDIR("Usage: %s [options] [w/m/p] [w/m/p]", appname); + ERROR_RAWDIR("Usage: %s [options] [w/m/p] [w/m/p]", appname); #else - ERROR_RAWDIR("Usage: %s [options] [w/p] [w/p]", appname); + ERROR_RAWDIR("Usage: %s [options] [w/p] [w/p]", appname); #endif - ERROR_RAWDIR(""); - ERROR_RAWDIR("Windows (activate adjacent (w)indow):"); - ERROR_RAWDIR(" -------- --------- --------- "); - ERROR_RAWDIR(" | wuleft | wup | wuright | "); - ERROR_RAWDIR(" |------- + ------- + --------| "); - ERROR_RAWDIR(" | wleft | | wright | "); - ERROR_RAWDIR(" |------- + ------- + --------| "); - ERROR_RAWDIR(" | wdleft | wdown | wdright | "); - ERROR_RAWDIR(" -------- --------- --------- "); + ERROR_RAWDIR(""); + ERROR_RAWDIR("Windows (activate adjacent (w)indow):"); + ERROR_RAWDIR(" -------- --------- --------- "); + ERROR_RAWDIR(" | wuleft | wup | wuright | "); + ERROR_RAWDIR(" |------- + ------- + --------| "); + ERROR_RAWDIR(" | wleft | | wright | "); + ERROR_RAWDIR(" |------- + ------- + --------| "); + ERROR_RAWDIR(" | wdleft | wdown | wdright | "); + ERROR_RAWDIR(" -------- --------- --------- "); #ifdef USE_XINERAMA - ERROR_RAWDIR(""); - ERROR_RAWDIR("Monitors (move window to adjacent (m)onitor):"); - ERROR_RAWDIR(" -------- --------- --------- "); - ERROR_RAWDIR(" | muleft | mup | muright | "); - ERROR_RAWDIR(" |------- + ------- + --------| "); - ERROR_RAWDIR(" | mleft | | mright | "); - ERROR_RAWDIR(" |------- + ------- + --------| "); - ERROR_RAWDIR(" | mdleft | mdown | mdright | "); - ERROR_RAWDIR(" -------- --------- --------- "); + ERROR_RAWDIR(""); + ERROR_RAWDIR("Monitors (move window to adjacent (m)onitor):"); + ERROR_RAWDIR(" -------- --------- --------- "); + ERROR_RAWDIR(" | muleft | mup | muright | "); + ERROR_RAWDIR(" |------- + ------- + --------| "); + ERROR_RAWDIR(" | mleft | | mright | "); + ERROR_RAWDIR(" |------- + ------- + --------| "); + ERROR_RAWDIR(" | mdleft | mdown | mdright | "); + ERROR_RAWDIR(" -------- --------- --------- "); #endif - ERROR_RAWDIR(""); - ERROR_RAWDIR("Positions (position window on (g)rid):"); - ERROR_RAWDIR(" -------- --------- --------- "); - ERROR_RAWDIR(" | guleft | gup | guright | "); - ERROR_RAWDIR(" |------- + ------- + --------| "); - ERROR_RAWDIR(" | gleft | gcenter | gright | "); - ERROR_RAWDIR(" |------- + ------- + --------| "); - ERROR_RAWDIR(" | gdleft | gdown | gdright | "); - ERROR_RAWDIR(" -------- --------- --------- "); - ERROR_RAWDIR(""); - ERROR_RAWDIR("Options:"); - ERROR_RAWDIR(" -h/--help This help text."); - ERROR_RAWDIR(" -v/--verbose Show verbose output."); - ERROR_RAWDIR(" --log Append any output to ."); - ERROR_RAWDIR(""); + ERROR_RAWDIR(""); + ERROR_RAWDIR("Positions (position window on (g)rid):"); + ERROR_RAWDIR(" -------- --------- --------- "); + ERROR_RAWDIR(" | guleft | gup | guright | "); + ERROR_RAWDIR(" |------- + ------- + --------| "); + ERROR_RAWDIR(" | gleft | gcenter | gright | "); + ERROR_RAWDIR(" |------- + ------- + --------| "); + ERROR_RAWDIR(" | gdleft | gdown | gdright | "); + ERROR_RAWDIR(" -------- --------- --------- "); + ERROR_RAWDIR(""); + ERROR_RAWDIR("Options:"); + ERROR_RAWDIR(" -h/--help This help text."); + ERROR_RAWDIR(" -v/--verbose Show verbose output."); + ERROR_RAWDIR(" --log Append any output to ."); + ERROR_RAWDIR(""); } static bool strsub_to_pos(const char* arg, grid::POS& out, bool center_is_valid) { - if (strcmp(arg, "uleft") == 0) { - out = grid::POS_UP_LEFT; - } else if (strcmp(arg, "up") == 0) { - out = grid::POS_UP_CENTER; - } else if (strcmp(arg, "uright") == 0) { - out = grid::POS_UP_RIGHT; - - } else if (strcmp(arg, "left") == 0) { - out = grid::POS_LEFT; - } else if (center_is_valid && strcmp(arg, "center") == 0) { - out = grid::POS_CENTER; - } else if (strcmp(arg, "right") == 0) { - out = grid::POS_RIGHT; - - } else if (strcmp(arg, "dleft") == 0) { - out = grid::POS_DOWN_LEFT; - } else if (strcmp(arg, "down") == 0) { - out = grid::POS_DOWN_CENTER; - } else if (strcmp(arg, "dright") == 0) { - out = grid::POS_DOWN_RIGHT; - - } else { - return false; - } - return true; + if (strcmp(arg, "uleft") == 0) { + out = grid::POS_UP_LEFT; + } else if (strcmp(arg, "up") == 0) { + out = grid::POS_UP_CENTER; + } else if (strcmp(arg, "uright") == 0) { + out = grid::POS_UP_RIGHT; + + } else if (strcmp(arg, "left") == 0) { + out = grid::POS_LEFT; + } else if (center_is_valid && strcmp(arg, "center") == 0) { + out = grid::POS_CENTER; + } else if (strcmp(arg, "right") == 0) { + out = grid::POS_RIGHT; + + } else if (strcmp(arg, "dleft") == 0) { + out = grid::POS_DOWN_LEFT; + } else if (strcmp(arg, "down") == 0) { + out = grid::POS_DOWN_CENTER; + } else if (strcmp(arg, "dright") == 0) { + out = grid::POS_DOWN_RIGHT; + + } else { + return false; + } + return true; } namespace { - enum CMD { CMD_UNKNOWN, CMD_HELP, CMD_POSITION }; - CMD run_cmd = CMD_UNKNOWN; - grid::POS gridpos = grid::POS_CURRENT, - monitor = grid::POS_CURRENT, window = grid::POS_CURRENT; + enum CMD { CMD_UNKNOWN, CMD_HELP, CMD_POSITION }; + CMD run_cmd = CMD_UNKNOWN; + grid::POS gridpos = grid::POS_CURRENT, + monitor = grid::POS_CURRENT, window = grid::POS_CURRENT; } static bool parse_config(int argc, char* argv[]) { - if (argc == 1) { - syntax(argv[0]); - return false; - } - int c; - while (1) { - static struct option long_options[] = { - {"help", 0, NULL, 'h'}, - {"verbose", 0, NULL, 'v'}, - {"log", required_argument, NULL, 'l'}, - {0,0,0,0} - }; - - int option_index = 0; - c = getopt_long(argc, argv, "hvl", - long_options, &option_index); - if (c == -1) {//unknown arg (doesnt match -x/--x format) - if (optind >= argc) { - //at end of successful parse - break; - } - //getopt refuses to continue, so handle position manually: - for (int i = optind; i < argc; ++i) { - const char* arg = argv[i]; - //DEBUG("%d %d %s", argc, i, arg); - grid::POS tmp_pos; - if (arg[0] == 'g' && strsub_to_pos(arg+1, tmp_pos, true)) { - if (gridpos != grid::POS_CURRENT) { - ERROR("%s: Multiple positions specified: '%s'", argv[0], argv[i]); - syntax(argv[0]); - return false; - } - gridpos = tmp_pos; - } else if (arg[0] == 'w' && strsub_to_pos(arg+1, tmp_pos, false)) { - if (window != grid::POS_CURRENT) { - ERROR("%s: Multiple windows specified: '%s'", argv[0], argv[i]); - syntax(argv[0]); - return false; - } - window = tmp_pos; - } else if (arg[0] == 'm' && strsub_to_pos(arg+1, tmp_pos, false)) { - if (monitor != grid::POS_CURRENT) { - ERROR("%s: Multiple monitors specified: '%s'", argv[0], argv[i]); - syntax(argv[0]); - return false; - } - monitor = tmp_pos; - } else { - ERROR("%s: Unknown argument: '%s'", argv[0], argv[i]); - syntax(argv[0]); - return false; - } - run_cmd = CMD_POSITION; - } - break; - } - - switch (c) { - case 'h': - run_cmd = CMD_HELP; - return true; - case 'v': - config::debug_enabled = true; - break; - case 'l': - { - FILE* logfile = fopen(optarg, "a"); - if (logfile == NULL) { - ERROR("Unable to open log file %s: %s", optarg, strerror(errno)); - return false; - } - config::fout = logfile; - config::ferr = logfile; - char now_s[TIMESTR_MAX]; - { - time_t now = time(NULL); - struct tm now_tm; - localtime_r(&now, &now_tm); - if (strftime(now_s, TIMESTR_MAX, "%a, %d %b %Y %T %z", &now_tm) == 0) { - ERROR_DIR("strftime failed"); - return false; - } - } - fprintf(logfile, "--- %s ---\n", now_s); - for (int i = 0; i < argc && argc < 100;) { - fprintf(logfile, "%s", argv[i]); - if (++i < argc) { - fprintf(logfile, " "); - } - } - fprintf(logfile, "\n"); - } - break; - default: - syntax(argv[0]); - return false; - } - } - - return true; + if (argc == 1) { + syntax(argv[0]); + return false; + } + int c; + while (1) { + static struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"log", required_argument, NULL, 'l'}, + {0,0,0,0} + }; + + int option_index = 0; + c = getopt_long(argc, argv, "hvl", + long_options, &option_index); + if (c == -1) {//unknown arg (doesnt match -x/--x format) + if (optind >= argc) { + //at end of successful parse + break; + } + //getopt refuses to continue, so handle position manually: + for (int i = optind; i < argc; ++i) { + const char* arg = argv[i]; + //DEBUG("%d %d %s", argc, i, arg); + grid::POS tmp_pos; + if (arg[0] == 'g' && strsub_to_pos(arg+1, tmp_pos, true)) { + if (gridpos != grid::POS_CURRENT) { + ERROR("%s: Multiple positions specified: '%s'", argv[0], argv[i]); + syntax(argv[0]); + return false; + } + gridpos = tmp_pos; + } else if (arg[0] == 'w' && strsub_to_pos(arg+1, tmp_pos, false)) { + if (window != grid::POS_CURRENT) { + ERROR("%s: Multiple windows specified: '%s'", argv[0], argv[i]); + syntax(argv[0]); + return false; + } + window = tmp_pos; + } else if (arg[0] == 'm' && strsub_to_pos(arg+1, tmp_pos, false)) { + if (monitor != grid::POS_CURRENT) { + ERROR("%s: Multiple monitors specified: '%s'", argv[0], argv[i]); + syntax(argv[0]); + return false; + } + monitor = tmp_pos; + } else { + ERROR("%s: Unknown argument: '%s'", argv[0], argv[i]); + syntax(argv[0]); + return false; + } + run_cmd = CMD_POSITION; + } + break; + } + + switch (c) { + case 'h': + run_cmd = CMD_HELP; + return true; + case 'v': + config::debug_enabled = true; + break; + case 'l': + { + FILE* logfile = fopen(optarg, "a"); + if (logfile == NULL) { + ERROR("Unable to open log file %s: %s", optarg, strerror(errno)); + return false; + } + config::fout = logfile; + config::ferr = logfile; + char now_s[TIMESTR_MAX]; + { + time_t now = time(NULL); + struct tm now_tm; + localtime_r(&now, &now_tm); + if (strftime(now_s, TIMESTR_MAX, "%a, %d %b %Y %T %z", &now_tm) == 0) { + ERROR_DIR("strftime failed"); + return false; + } + } + fprintf(logfile, "--- %s ---\n", now_s); + for (int i = 0; i < argc && argc < 100;) { + fprintf(logfile, "%s", argv[i]); + if (++i < argc) { + fprintf(logfile, " "); + } + } + fprintf(logfile, "\n"); + } + break; + default: + syntax(argv[0]); + return false; + } + } + + return true; } int main(int argc, char* argv[]) { - if (!parse_config(argc, argv)) { - return EXIT_FAILURE; - } - switch (run_cmd) { - case CMD_HELP: - syntax(argv[0]); - return EXIT_SUCCESS; - case CMD_POSITION: - // activate window (if specified) - if (window != grid::POS_CURRENT && !grid::set_active(window)) { - return EXIT_FAILURE; - } - // move window (if specified) - if (gridpos != grid::POS_CURRENT || monitor != grid::POS_CURRENT) { - return grid::set_position(gridpos, monitor) ? - EXIT_SUCCESS : EXIT_FAILURE; - } - return EXIT_SUCCESS; - default: - ERROR("%s: no command specified", argv[0]); - syntax(argv[0]); - return EXIT_FAILURE; - } + if (!parse_config(argc, argv)) { + return EXIT_FAILURE; + } + switch (run_cmd) { + case CMD_HELP: + syntax(argv[0]); + return EXIT_SUCCESS; + case CMD_POSITION: + // activate window (if specified) + if (window != grid::POS_CURRENT && !grid::set_active(window)) { + return EXIT_FAILURE; + } + // move window (if specified) + if (gridpos != grid::POS_CURRENT || monitor != grid::POS_CURRENT) { + return grid::set_position(gridpos, monitor) ? + EXIT_SUCCESS : EXIT_FAILURE; + } + return EXIT_SUCCESS; + default: + ERROR("%s: no command specified", argv[0]); + syntax(argv[0]); + return EXIT_FAILURE; + } } diff --git a/src/neighbor.cpp b/src/neighbor.cpp index 36fc67d..69ebec3 100644 --- a/src/neighbor.cpp +++ b/src/neighbor.cpp @@ -25,256 +25,256 @@ #define DISTANCE(a,b) ((a > b) ? (a - b) : (b - a)) namespace { - class point { - public: - point() : x(0), y(0) { } - point(const Dimensions& d) - : x(MIDPOINT(d.x, d.width)), - y(MIDPOINT(d.y, d.height)) { } + class point { + public: + point() : x(0), y(0) { } + point(const Dimensions& d) + : x(MIDPOINT(d.x, d.width)), + y(MIDPOINT(d.y, d.height)) { } - /* Returns whether 'p' is in the specified direction relative to this - point. Eg POS_UP -> "is p above this?" */ - bool direction(grid::POS dir, const point& p) const { - // note: M_PI_4 == pi/4, from math.h. - if (y == p.y && x == p.x) { - // p is on top of us, avoid getting stuck - return false; - } - //DEBUG("%s: %f vs %f", grid::dir_str(dir), abs_atan(p), (M_PI_4)); - switch (dir) { - case grid::POS_UP_LEFT: - return (y > p.y && x > p.x); - case grid::POS_UP_RIGHT: - return (y > p.y && x < p.x); - case grid::POS_DOWN_LEFT: - return (y < p.y && x > p.x); - case grid::POS_DOWN_RIGHT: - return (y < p.y && x < p.x); + /* Returns whether 'p' is in the specified direction relative to this + point. Eg POS_UP -> "is p above this?" */ + bool direction(grid::POS dir, const point& p) const { + // note: M_PI_4 == pi/4, from math.h. + if (y == p.y && x == p.x) { + // p is on top of us, avoid getting stuck + return false; + } + //DEBUG("%s: %f vs %f", grid::dir_str(dir), abs_atan(p), (M_PI_4)); + switch (dir) { + case grid::POS_UP_LEFT: + return (y > p.y && x > p.x); + case grid::POS_UP_RIGHT: + return (y > p.y && x < p.x); + case grid::POS_DOWN_LEFT: + return (y < p.y && x > p.x); + case grid::POS_DOWN_RIGHT: + return (y < p.y && x < p.x); - case grid::POS_UP_CENTER: - if (y < p.y) { return false; } // p is below us - return abs_atan(p) >= M_PI_4; // p is too far right/left of us - case grid::POS_DOWN_CENTER: - if (y > p.y) { return false; } // p is above us - return abs_atan(p) >= M_PI_4; // p is too far right/left of us + case grid::POS_UP_CENTER: + if (y < p.y) { return false; } // p is below us + return abs_atan(p) >= M_PI_4; // p is too far right/left of us + case grid::POS_DOWN_CENTER: + if (y > p.y) { return false; } // p is above us + return abs_atan(p) >= M_PI_4; // p is too far right/left of us - case grid::POS_LEFT: - if (x < p.x) { return false; } // p is right of us - return abs_atan(p) <= M_PI_4; // p is too far above/below us - case grid::POS_RIGHT: - if (x > p.x) { return false; } // p is left of us - return abs_atan(p) <= M_PI_4; // p is too far above/below us + case grid::POS_LEFT: + if (x < p.x) { return false; } // p is right of us + return abs_atan(p) <= M_PI_4; // p is too far above/below us + case grid::POS_RIGHT: + if (x > p.x) { return false; } // p is left of us + return abs_atan(p) <= M_PI_4; // p is too far above/below us - case grid::POS_CENTER: - case grid::POS_UNKNOWN: - case grid::POS_CURRENT: - ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); - break; - } - return false;//??? - } + case grid::POS_CENTER: + case grid::POS_UNKNOWN: + case grid::POS_CURRENT: + ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); + break; + } + return false;//??? + } - /* Not a true 'distance', more of a weighting where smaller is better. */ - double distance(grid::POS dir, const point& p) const { - long w = DISTANCE(p.x, x), h = DISTANCE(p.y, y); - switch (dir) { - case grid::POS_UP_LEFT: - case grid::POS_UP_RIGHT: - case grid::POS_DOWN_LEFT: - case grid::POS_DOWN_RIGHT: - //use a weighting that favors diagonals (where w == h) - { - double dist = sqrt((w * w) + (h * h)); - //sqrt again to further decrease dist's importance - return sqrt(dist) * DISTANCE(w, h); - } + /* Not a true 'distance', more of a weighting where smaller is better. */ + double distance(grid::POS dir, const point& p) const { + long w = DISTANCE(p.x, x), h = DISTANCE(p.y, y); + switch (dir) { + case grid::POS_UP_LEFT: + case grid::POS_UP_RIGHT: + case grid::POS_DOWN_LEFT: + case grid::POS_DOWN_RIGHT: + //use a weighting that favors diagonals (where w == h) + { + double dist = sqrt((w * w) + (h * h)); + //sqrt again to further decrease dist's importance + return sqrt(dist) * DISTANCE(w, h); + } - case grid::POS_UP_CENTER: - case grid::POS_DOWN_CENTER: - case grid::POS_RIGHT: - case grid::POS_LEFT: - //use actual distance, diagonals are automatically farther - return sqrt((w * w) + (h * h)); + case grid::POS_UP_CENTER: + case grid::POS_DOWN_CENTER: + case grid::POS_RIGHT: + case grid::POS_LEFT: + //use actual distance, diagonals are automatically farther + return sqrt((w * w) + (h * h)); - case grid::POS_CENTER: - case grid::POS_UNKNOWN: - case grid::POS_CURRENT: - ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); - break; - } - return 0;//??? - } + case grid::POS_CENTER: + case grid::POS_UNKNOWN: + case grid::POS_CURRENT: + ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); + break; + } + return 0;//??? + } - void shift_pos(grid::POS dir, long max_x, long max_y) { - switch (dir) { - case grid::POS_UP_LEFT: - // we're looking up left, so move the point down right - y += max_y; - x += max_x; - break; - case grid::POS_DOWN_RIGHT: - // opposite of UP_LEFT - shift_pos(grid::POS_UP_LEFT, -1 * max_x, -1 * max_y); - break; + void shift_pos(grid::POS dir, long max_x, long max_y) { + switch (dir) { + case grid::POS_UP_LEFT: + // we're looking up left, so move the point down right + y += max_y; + x += max_x; + break; + case grid::POS_DOWN_RIGHT: + // opposite of UP_LEFT + shift_pos(grid::POS_UP_LEFT, -1 * max_x, -1 * max_y); + break; - case grid::POS_UP_RIGHT: - // we're looking up right, so move the point down left - y += max_y; - x -= max_x; - break; - case grid::POS_DOWN_LEFT: - // opposite of UP_RIGHT - shift_pos(grid::POS_UP_RIGHT, -1 * max_x, -1 * max_y); - break; + case grid::POS_UP_RIGHT: + // we're looking up right, so move the point down left + y += max_y; + x -= max_x; + break; + case grid::POS_DOWN_LEFT: + // opposite of UP_RIGHT + shift_pos(grid::POS_UP_RIGHT, -1 * max_x, -1 * max_y); + break; - case grid::POS_UP_CENTER: - // we're looking up, so move the point down - y += max_y; - break; - case grid::POS_DOWN_CENTER: - // opposite of UP_CENTER - shift_pos(grid::POS_UP_CENTER, -1 * max_x, -1 * max_y); - break; + case grid::POS_UP_CENTER: + // we're looking up, so move the point down + y += max_y; + break; + case grid::POS_DOWN_CENTER: + // opposite of UP_CENTER + shift_pos(grid::POS_UP_CENTER, -1 * max_x, -1 * max_y); + break; - case grid::POS_LEFT: - // we're looking left, so move the point right - x += max_x; - break; - case grid::POS_RIGHT: - // opposite of LEFT - shift_pos(grid::POS_LEFT, -1 * max_x, -1 * max_y); - break; + case grid::POS_LEFT: + // we're looking left, so move the point right + x += max_x; + break; + case grid::POS_RIGHT: + // opposite of LEFT + shift_pos(grid::POS_LEFT, -1 * max_x, -1 * max_y); + break; - case grid::POS_CENTER: - case grid::POS_UNKNOWN: - case grid::POS_CURRENT: - ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); - break;//??? - } - } + case grid::POS_CENTER: + case grid::POS_UNKNOWN: + case grid::POS_CURRENT: + ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); + break;//??? + } + } - long x; - long y; + long x; + long y; - private: - inline double abs_atan(const point& p2) const { - long denom = DISTANCE(x, p2.x); - if (denom == 0) { - return M_PI_2;// avoid div0 (pi/2, from math.h) - } else { - return atan(DISTANCE(y, p2.y) / (double)denom); - } - } - }; + private: + inline double abs_atan(const point& p2) const { + long denom = DISTANCE(x, p2.x); + if (denom == 0) { + return M_PI_2;// avoid div0 (pi/2, from math.h) + } else { + return atan(DISTANCE(y, p2.y) / (double)denom); + } + } + }; - /* Finds and selects the nearest non-active point in the given direction and - returns true, or returns false if none was found. */ - bool select_nearest_in_direction(grid::POS dir, const std::vector& pts, - size_t active, size_t& select) { - // find nearst point that matches the given direction - double nearest_dist = 0; - long nearest_i = -1; - const point& active_pt = pts[active]; - DEBUG("search %lu for points %s of %ld,%ld:", - pts.size()-1, grid::pos_str(dir), active_pt.x, active_pt.y); - for (size_t i = 0; i < pts.size(); ++i) { - if (i == active) { - DEBUG("skip: %ld,%ld", pts[i].x, pts[i].y); - continue; - } + /* Finds and selects the nearest non-active point in the given direction and + returns true, or returns false if none was found. */ + bool select_nearest_in_direction(grid::POS dir, const std::vector& pts, + size_t active, size_t& select) { + // find nearst point that matches the given direction + double nearest_dist = 0; + long nearest_i = -1; + const point& active_pt = pts[active]; + DEBUG("search %lu for points %s of %ld,%ld:", + pts.size()-1, grid::pos_str(dir), active_pt.x, active_pt.y); + for (size_t i = 0; i < pts.size(); ++i) { + if (i == active) { + DEBUG("skip: %ld,%ld", pts[i].x, pts[i].y); + continue; + } - const point& pt = pts[i]; - if (active_pt.direction(dir, pt)) { - double dist = active_pt.distance(dir, pt); - DEBUG("match!: %ld,%ld (dist %.02f)", pts[i].x, pts[i].y, dist); - if (nearest_i < 0 || dist < nearest_dist) { - nearest_i = i; - nearest_dist = dist; - } - } else { - DEBUG("miss: %ld,%ld", pts[i].x, pts[i].y); - } - } + const point& pt = pts[i]; + if (active_pt.direction(dir, pt)) { + double dist = active_pt.distance(dir, pt); + DEBUG("match!: %ld,%ld (dist %.02f)", pts[i].x, pts[i].y, dist); + if (nearest_i < 0 || dist < nearest_dist) { + nearest_i = i; + nearest_dist = dist; + } + } else { + DEBUG("miss: %ld,%ld", pts[i].x, pts[i].y); + } + } - if (nearest_i >= 0) { - // found! - select = nearest_i; - return true; - } - return false; - } + if (nearest_i >= 0) { + // found! + select = nearest_i; + return true; + } + return false; + } - /* When nothing is found in a given direction, this function determines what - the fallback direction ordering should be */ - grid::POS fallback_direction(grid::POS dir) { - // go clockwise - switch (dir) { - case grid::POS_UP_CENTER: - return grid::POS_UP_RIGHT; - case grid::POS_UP_RIGHT: - return grid::POS_RIGHT; - case grid::POS_RIGHT: - return grid::POS_DOWN_RIGHT; - case grid::POS_DOWN_RIGHT: - return grid::POS_DOWN_CENTER; - case grid::POS_DOWN_CENTER: - return grid::POS_DOWN_LEFT; - case grid::POS_DOWN_LEFT: - return grid::POS_LEFT; - case grid::POS_LEFT: - return grid::POS_UP_LEFT; - case grid::POS_UP_LEFT: - return grid::POS_UP_CENTER; - case grid::POS_CENTER: - case grid::POS_UNKNOWN: - case grid::POS_CURRENT: - ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); - break; - } - return grid::POS_UP_CENTER;//??? - } + /* When nothing is found in a given direction, this function determines what + the fallback direction ordering should be */ + grid::POS fallback_direction(grid::POS dir) { + // go clockwise + switch (dir) { + case grid::POS_UP_CENTER: + return grid::POS_UP_RIGHT; + case grid::POS_UP_RIGHT: + return grid::POS_RIGHT; + case grid::POS_RIGHT: + return grid::POS_DOWN_RIGHT; + case grid::POS_DOWN_RIGHT: + return grid::POS_DOWN_CENTER; + case grid::POS_DOWN_CENTER: + return grid::POS_DOWN_LEFT; + case grid::POS_DOWN_LEFT: + return grid::POS_LEFT; + case grid::POS_LEFT: + return grid::POS_UP_LEFT; + case grid::POS_UP_LEFT: + return grid::POS_UP_CENTER; + case grid::POS_CENTER: + case grid::POS_UNKNOWN: + case grid::POS_CURRENT: + ERROR("Internal error: invalid dir %s", grid::pos_str(dir)); + break; + } + return grid::POS_UP_CENTER;//??? + } } #define MAX_X(dim) (dim.x + dim.width) #define MAX_Y(dim) (dim.y + dim.height) void neighbor::select(grid::POS dir, const dim_list_t& all, size_t active, size_t& select) { - if (all.size() <= 1) { - select = 0; - return; - } - if (dir == grid::POS_CURRENT) { - select = active; - return; - } + if (all.size() <= 1) { + select = 0; + return; + } + if (dir == grid::POS_CURRENT) { + select = active; + return; + } - // dimension -> center point and max window dimensions - size_t bound_x = MAX_X(all[0]), bound_y = MAX_Y(all[0]); - std::vector pts; - pts.reserve(all.size()); - for (dim_list_t::const_iterator iter = all.begin(); - iter != all.end(); ++iter) { - const Dimensions& d = *iter; - size_t d_x = MAX_X(d), d_y = MAX_Y(d); - if (d_x > bound_x) { bound_x = d_x; } - if (d_y > bound_y) { bound_y = d_y; } - pts.push_back(point(d)); - } + // dimension -> center point and max window dimensions + size_t bound_x = MAX_X(all[0]), bound_y = MAX_Y(all[0]); + std::vector pts; + pts.reserve(all.size()); + for (dim_list_t::const_iterator iter = all.begin(); + iter != all.end(); ++iter) { + const Dimensions& d = *iter; + size_t d_x = MAX_X(d), d_y = MAX_Y(d); + if (d_x > bound_x) { bound_x = d_x; } + if (d_y > bound_y) { bound_y = d_y; } + pts.push_back(point(d)); + } - for (size_t i = 0; i < 4; ++i) {//try each of the four directions - if (select_nearest_in_direction(dir, pts, active, select)) { - return; - } - // not found. try shifting active pt for a wraparound search - pts[active].shift_pos(dir, bound_x, bound_y); - if (select_nearest_in_direction(dir, pts, active, select)) { - return; - } - // still not found. undo shift and try next direction - pts[active].shift_pos(dir, -1 * bound_x, -1 * bound_y); - dir = fallback_direction(dir); - } + for (size_t i = 0; i < 4; ++i) {//try each of the four directions + if (select_nearest_in_direction(dir, pts, active, select)) { + return; + } + // not found. try shifting active pt for a wraparound search + pts[active].shift_pos(dir, bound_x, bound_y); + if (select_nearest_in_direction(dir, pts, active, select)) { + return; + } + // still not found. undo shift and try next direction + pts[active].shift_pos(dir, -1 * bound_x, -1 * bound_y); + dir = fallback_direction(dir); + } - // STILL not found. just give up! - select = active; + // STILL not found. just give up! + select = active; } diff --git a/src/neighbor.h b/src/neighbor.h index 26cdb00..823ecc4 100644 --- a/src/neighbor.h +++ b/src/neighbor.h @@ -27,7 +27,7 @@ typedef std::vector dim_list_t; namespace neighbor { - void select(grid::POS dir, const dim_list_t& all, size_t active, size_t& select); + void select(grid::POS dir, const dim_list_t& all, size_t active, size_t& select); } #endif diff --git a/src/pos.h b/src/pos.h index 11bc1e5..477648d 100644 --- a/src/pos.h +++ b/src/pos.h @@ -20,42 +20,42 @@ */ namespace grid { - /* These are the various available positions which may be set. - * CURRENT is "use the current position", useful when only switching monitors */ - enum POS { - POS_UNKNOWN, POS_CURRENT, - POS_UP_LEFT, POS_UP_CENTER, POS_UP_RIGHT, - POS_LEFT, POS_CENTER, POS_RIGHT, - POS_DOWN_LEFT, POS_DOWN_CENTER, POS_DOWN_RIGHT - }; + /* These are the various available positions which may be set. + * CURRENT is "use the current position", useful when only switching monitors */ + enum POS { + POS_UNKNOWN, POS_CURRENT, + POS_UP_LEFT, POS_UP_CENTER, POS_UP_RIGHT, + POS_LEFT, POS_CENTER, POS_RIGHT, + POS_DOWN_LEFT, POS_DOWN_CENTER, POS_DOWN_RIGHT + }; - inline const char* pos_str(POS pos) { - switch (pos) { - case POS_UNKNOWN: - return "UNKNOWN"; - case POS_CURRENT: - return "CURRENT"; - case POS_UP_LEFT: - return "UP_LEFT"; - case POS_UP_CENTER: - return "UP_CENTER"; - case POS_UP_RIGHT: - return "UP_RIGHT"; - case POS_LEFT: - return "LEFT"; - case POS_CENTER: - return "CENTER"; - case POS_RIGHT: - return "RIGHT"; - case POS_DOWN_LEFT: - return "DOWN_LEFT"; - case POS_DOWN_CENTER: - return "DOWN_CENTER"; - case POS_DOWN_RIGHT: - return "DOWN_RIGHT"; - } - return "???"; - } + inline const char* pos_str(POS pos) { + switch (pos) { + case POS_UNKNOWN: + return "UNKNOWN"; + case POS_CURRENT: + return "CURRENT"; + case POS_UP_LEFT: + return "UP_LEFT"; + case POS_UP_CENTER: + return "UP_CENTER"; + case POS_UP_RIGHT: + return "UP_RIGHT"; + case POS_LEFT: + return "LEFT"; + case POS_CENTER: + return "CENTER"; + case POS_RIGHT: + return "RIGHT"; + case POS_DOWN_LEFT: + return "DOWN_LEFT"; + case POS_DOWN_CENTER: + return "DOWN_CENTER"; + case POS_DOWN_RIGHT: + return "DOWN_RIGHT"; + } + return "???"; + } } #endif diff --git a/src/position.cpp b/src/position.cpp index 3f9c0b8..d3691f0 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -22,456 +22,456 @@ #include "position.h" namespace { - inline const char* mode_str(grid::MODE mode) { - switch (mode) { - case grid::MODE_UNKNOWN: - return "UNKNOWN"; - case grid::MODE_TWO_COL: - return "TWO_COL"; - case grid::MODE_THREE_COL_S: - return "THREE_COL_S"; - case grid::MODE_THREE_COL_L: - return "THREE_COL_L"; - default: - break; - } - return "???"; - } + inline const char* mode_str(grid::MODE mode) { + switch (mode) { + case grid::MODE_UNKNOWN: + return "UNKNOWN"; + case grid::MODE_TWO_COL: + return "TWO_COL"; + case grid::MODE_THREE_COL_S: + return "THREE_COL_S"; + case grid::MODE_THREE_COL_L: + return "THREE_COL_L"; + default: + break; + } + return "???"; + } #define MAX(a,b) (((a) > (b)) ? (a) : (b)) - // whether two numbers are 'near' one another, according to a fudge factor. - template - inline bool _near(A a, B b, const char* a_desc, const char* b_desc) { - // fudge factor: the greater of 5px or 5% of the greater number. - double fudge = MAX(5, 0.05 * MAX(a,b)); - bool ret = (a + fudge) >= b && (a - fudge) <= b; - DEBUG("%s(%d) vs %s(%d): %s", - a_desc, (int)a, b_desc, (int)b, - (ret) ? "true" : "false"); - return ret; - } + // whether two numbers are 'near' one another, according to a fudge factor. + template + inline bool _near(A a, B b, const char* a_desc, const char* b_desc) { + // fudge factor: the greater of 5px or 5% of the greater number. + double fudge = MAX(5, 0.05 * MAX(a,b)); + bool ret = (a + fudge) >= b && (a - fudge) <= b; + DEBUG("%s(%d) vs %s(%d): %s", + a_desc, (int)a, b_desc, (int)b, + (ret) ? "true" : "false"); + return ret; + } #define NEAR(a,b) _near(a, b, #a, #b) } /* given window's dimensions, estimate its state (or unknown+unknown) (inverse of StateToDim) */ bool PositionCalc::CurState(const Dimensions& viewport, State& out) const { - //get window x/y relative to viewport x/y - int rel_x = window.x - viewport.x, - rel_y = window.y - viewport.y; - out.pos = grid::POS_UNKNOWN; - out.mode = grid::MODE_UNKNOWN; - if (NEAR(window.width, viewport.width / 2.)) { - if (NEAR(window.height, viewport.height / 2.)) { - if (NEAR(rel_x, 0)) { - if (NEAR(rel_y, 0)) { - // top left quadrant - out.pos = grid::POS_UP_LEFT; - out.mode = grid::MODE_TWO_COL; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom left quadrant - out.pos = grid::POS_DOWN_LEFT; - out.mode = grid::MODE_TWO_COL; - } - } else if (NEAR(rel_x, viewport.width / 2.)) { - if (NEAR(rel_y, 0)) { - // top right quadrant - out.pos = grid::POS_UP_RIGHT; - out.mode = grid::MODE_TWO_COL; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom right quadrant - out.pos = grid::POS_DOWN_RIGHT; - out.mode = grid::MODE_TWO_COL; - } - } - } else if (NEAR(window.height, viewport.height) && - NEAR(rel_y, 0)) { - if (NEAR(rel_x, 0)) { - // left half - out.pos = grid::POS_LEFT; - out.mode = grid::MODE_TWO_COL; - } else if (NEAR(rel_x, viewport.width / 2.)) { - // right half - out.pos = grid::POS_RIGHT; - out.mode = grid::MODE_TWO_COL; - } - } - } else if (NEAR(window.width, viewport.width / 3.)) { - if (NEAR(window.height, viewport.height / 2.)) { - if (NEAR(rel_x, 0)) { - if (NEAR(rel_y, 0)) { - // top left col - out.pos = grid::POS_UP_LEFT; - out.mode = grid::MODE_THREE_COL_S; - } if (NEAR(rel_y, viewport.height / 2.)) { - // bottom left col - out.pos = grid::POS_DOWN_LEFT; - out.mode = grid::MODE_THREE_COL_S; - } - } else if (NEAR(rel_x, viewport.width / 3.)) { - if (NEAR(rel_y, 0)) { - // top center col - out.pos = grid::POS_UP_CENTER; - out.mode = grid::MODE_THREE_COL_S; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom center col - out.pos = grid::POS_DOWN_CENTER; - out.mode = grid::MODE_THREE_COL_S; - } - } else if (NEAR(rel_x, 2 * viewport.width / 3.)) { - if (NEAR(rel_y, 0)) { - // top right col - out.pos = grid::POS_UP_RIGHT; - out.mode = grid::MODE_THREE_COL_S; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom right col - out.pos = grid::POS_DOWN_RIGHT; - out.mode = grid::MODE_THREE_COL_S; - } - } - } else if (NEAR(window.height, viewport.height) && - NEAR(rel_y, 0)) { - if (NEAR(rel_x, 0)) { - // left col - out.pos = grid::POS_LEFT; - out.mode = grid::MODE_THREE_COL_S; - } else if (NEAR(rel_x, viewport.width / 3.)) { - // center col - out.pos = grid::POS_CENTER; - out.mode = grid::MODE_THREE_COL_S; - } else if (NEAR(rel_x, 2 * viewport.width / 3.)) { - // right col - out.pos = grid::POS_RIGHT; - out.mode = grid::MODE_THREE_COL_S; - } - } - } else if (NEAR(window.width, 2 * viewport.width / 3.)) { - if (NEAR(window.height, viewport.height / 2.)) { - if (NEAR(rel_x, 0)) { - if (NEAR(rel_y, 0)) { - // top left two cols - out.pos = grid::POS_UP_LEFT; - out.mode = grid::MODE_THREE_COL_L; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom left two cols - out.pos = grid::POS_DOWN_LEFT; - out.mode = grid::MODE_THREE_COL_L; - } - } else if (NEAR(rel_x, viewport.width / 3.)) { - if (NEAR(rel_y, 0)) { - // top right two cols - out.pos = grid::POS_UP_RIGHT; - out.mode = grid::MODE_THREE_COL_L; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom right two cols - out.pos = grid::POS_DOWN_RIGHT; - out.mode = grid::MODE_THREE_COL_L; - } - } - } else if (NEAR(window.height, viewport.height) && - NEAR(rel_y, 0)) { - if (NEAR(rel_x, 0)) { - // left two cols - out.pos = grid::POS_LEFT; - out.mode = grid::MODE_THREE_COL_L; - } else if (NEAR(rel_x, viewport.width / 3.)) { - // right two cols - out.pos = grid::POS_RIGHT; - out.mode = grid::MODE_THREE_COL_L; - } - } - } else if (NEAR(window.width, viewport.width) && - NEAR(rel_x, 0)) { - if (NEAR(window.height, viewport.height / 2.)) { - if (NEAR(rel_y, 0)) { - // top half - out.pos = grid::POS_UP_CENTER; - out.mode = grid::MODE_THREE_COL_L; - } else if (NEAR(rel_y, viewport.height / 2.)) { - // bottom half - out.pos = grid::POS_DOWN_CENTER; - out.mode = grid::MODE_THREE_COL_L; - } - } else if (NEAR(window.height, viewport.height) && - NEAR(rel_y, 0)) { - // full screen - out.pos = grid::POS_CENTER; - out.mode = grid::MODE_THREE_COL_L; - } - } + //get window x/y relative to viewport x/y + int rel_x = window.x - viewport.x, + rel_y = window.y - viewport.y; + out.pos = grid::POS_UNKNOWN; + out.mode = grid::MODE_UNKNOWN; + if (NEAR(window.width, viewport.width / 2.)) { + if (NEAR(window.height, viewport.height / 2.)) { + if (NEAR(rel_x, 0)) { + if (NEAR(rel_y, 0)) { + // top left quadrant + out.pos = grid::POS_UP_LEFT; + out.mode = grid::MODE_TWO_COL; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom left quadrant + out.pos = grid::POS_DOWN_LEFT; + out.mode = grid::MODE_TWO_COL; + } + } else if (NEAR(rel_x, viewport.width / 2.)) { + if (NEAR(rel_y, 0)) { + // top right quadrant + out.pos = grid::POS_UP_RIGHT; + out.mode = grid::MODE_TWO_COL; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom right quadrant + out.pos = grid::POS_DOWN_RIGHT; + out.mode = grid::MODE_TWO_COL; + } + } + } else if (NEAR(window.height, viewport.height) && + NEAR(rel_y, 0)) { + if (NEAR(rel_x, 0)) { + // left half + out.pos = grid::POS_LEFT; + out.mode = grid::MODE_TWO_COL; + } else if (NEAR(rel_x, viewport.width / 2.)) { + // right half + out.pos = grid::POS_RIGHT; + out.mode = grid::MODE_TWO_COL; + } + } + } else if (NEAR(window.width, viewport.width / 3.)) { + if (NEAR(window.height, viewport.height / 2.)) { + if (NEAR(rel_x, 0)) { + if (NEAR(rel_y, 0)) { + // top left col + out.pos = grid::POS_UP_LEFT; + out.mode = grid::MODE_THREE_COL_S; + } if (NEAR(rel_y, viewport.height / 2.)) { + // bottom left col + out.pos = grid::POS_DOWN_LEFT; + out.mode = grid::MODE_THREE_COL_S; + } + } else if (NEAR(rel_x, viewport.width / 3.)) { + if (NEAR(rel_y, 0)) { + // top center col + out.pos = grid::POS_UP_CENTER; + out.mode = grid::MODE_THREE_COL_S; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom center col + out.pos = grid::POS_DOWN_CENTER; + out.mode = grid::MODE_THREE_COL_S; + } + } else if (NEAR(rel_x, 2 * viewport.width / 3.)) { + if (NEAR(rel_y, 0)) { + // top right col + out.pos = grid::POS_UP_RIGHT; + out.mode = grid::MODE_THREE_COL_S; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom right col + out.pos = grid::POS_DOWN_RIGHT; + out.mode = grid::MODE_THREE_COL_S; + } + } + } else if (NEAR(window.height, viewport.height) && + NEAR(rel_y, 0)) { + if (NEAR(rel_x, 0)) { + // left col + out.pos = grid::POS_LEFT; + out.mode = grid::MODE_THREE_COL_S; + } else if (NEAR(rel_x, viewport.width / 3.)) { + // center col + out.pos = grid::POS_CENTER; + out.mode = grid::MODE_THREE_COL_S; + } else if (NEAR(rel_x, 2 * viewport.width / 3.)) { + // right col + out.pos = grid::POS_RIGHT; + out.mode = grid::MODE_THREE_COL_S; + } + } + } else if (NEAR(window.width, 2 * viewport.width / 3.)) { + if (NEAR(window.height, viewport.height / 2.)) { + if (NEAR(rel_x, 0)) { + if (NEAR(rel_y, 0)) { + // top left two cols + out.pos = grid::POS_UP_LEFT; + out.mode = grid::MODE_THREE_COL_L; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom left two cols + out.pos = grid::POS_DOWN_LEFT; + out.mode = grid::MODE_THREE_COL_L; + } + } else if (NEAR(rel_x, viewport.width / 3.)) { + if (NEAR(rel_y, 0)) { + // top right two cols + out.pos = grid::POS_UP_RIGHT; + out.mode = grid::MODE_THREE_COL_L; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom right two cols + out.pos = grid::POS_DOWN_RIGHT; + out.mode = grid::MODE_THREE_COL_L; + } + } + } else if (NEAR(window.height, viewport.height) && + NEAR(rel_y, 0)) { + if (NEAR(rel_x, 0)) { + // left two cols + out.pos = grid::POS_LEFT; + out.mode = grid::MODE_THREE_COL_L; + } else if (NEAR(rel_x, viewport.width / 3.)) { + // right two cols + out.pos = grid::POS_RIGHT; + out.mode = grid::MODE_THREE_COL_L; + } + } + } else if (NEAR(window.width, viewport.width) && + NEAR(rel_x, 0)) { + if (NEAR(window.height, viewport.height / 2.)) { + if (NEAR(rel_y, 0)) { + // top half + out.pos = grid::POS_UP_CENTER; + out.mode = grid::MODE_THREE_COL_L; + } else if (NEAR(rel_y, viewport.height / 2.)) { + // bottom half + out.pos = grid::POS_DOWN_CENTER; + out.mode = grid::MODE_THREE_COL_L; + } + } else if (NEAR(window.height, viewport.height) && + NEAR(rel_y, 0)) { + // full screen + out.pos = grid::POS_CENTER; + out.mode = grid::MODE_THREE_COL_L; + } + } - DEBUG("%ldx %ldy %luw %luh -> pos=%s mode=%s", - rel_x, rel_y, window.width, window.height, - pos_str(out.pos), mode_str(out.mode)); - return true; + DEBUG("%ldx %ldy %luw %luh -> pos=%s mode=%s", + rel_x, rel_y, window.width, window.height, + pos_str(out.pos), mode_str(out.mode)); + return true; } bool PositionCalc::NextState(const State& cur, grid::POS req_pos, State& out) const { - if (req_pos == grid::POS_UNKNOWN) {// nice to have - ERROR("Position '%s' was requested. Internal error?", pos_str(req_pos)); - return false; - } - if (req_pos == grid::POS_CURRENT) { - out = cur; - } else if (cur.pos == req_pos) { - // position is same, so rotate mode - out.pos = cur.pos; - switch (cur.pos) { - case grid::POS_UP_CENTER: - case grid::POS_CENTER: - case grid::POS_DOWN_CENTER: - // for center col: 3x2L -> 3x2S (-> 3x2L) (no 2x2) - switch (cur.mode) { - case grid::MODE_THREE_COL_L: - out.mode = grid::MODE_THREE_COL_S; - break; - case grid::MODE_THREE_COL_S: - default: - out.mode = grid::MODE_THREE_COL_L; - } - break; - default: - // for everything else: 2x2 -> 3x2L -> 3x2S (-> 2x2) - switch (cur.mode) { - case grid::MODE_UNKNOWN: - case grid::MODE_THREE_COL_L: - out.mode = grid::MODE_THREE_COL_S; - break; - case grid::MODE_TWO_COL: - out.mode = grid::MODE_THREE_COL_L; - break; - case grid::MODE_THREE_COL_S: - default: - out.mode = grid::MODE_TWO_COL; - } - } - } else { - // new position, so start with initial mode - out.pos = req_pos; - switch (req_pos) { - case grid::POS_UP_CENTER: - case grid::POS_CENTER: - case grid::POS_DOWN_CENTER: - // for center col: start with 3x2L - out.mode = grid::MODE_THREE_COL_L; - break; - default: - // for everything else: start with 2x2 - out.mode = grid::MODE_TWO_COL; - } - } - DEBUG("curpos=%s curmode=%s + reqpos=%s -> pos=%s mode=%s", - pos_str(cur.pos), mode_str(cur.mode), pos_str(req_pos), - pos_str(out.pos), mode_str(out.mode)); - return true; + if (req_pos == grid::POS_UNKNOWN) {// nice to have + ERROR("Position '%s' was requested. Internal error?", pos_str(req_pos)); + return false; + } + if (req_pos == grid::POS_CURRENT) { + out = cur; + } else if (cur.pos == req_pos) { + // position is same, so rotate mode + out.pos = cur.pos; + switch (cur.pos) { + case grid::POS_UP_CENTER: + case grid::POS_CENTER: + case grid::POS_DOWN_CENTER: + // for center col: 3x2L -> 3x2S (-> 3x2L) (no 2x2) + switch (cur.mode) { + case grid::MODE_THREE_COL_L: + out.mode = grid::MODE_THREE_COL_S; + break; + case grid::MODE_THREE_COL_S: + default: + out.mode = grid::MODE_THREE_COL_L; + } + break; + default: + // for everything else: 2x2 -> 3x2L -> 3x2S (-> 2x2) + switch (cur.mode) { + case grid::MODE_UNKNOWN: + case grid::MODE_THREE_COL_L: + out.mode = grid::MODE_THREE_COL_S; + break; + case grid::MODE_TWO_COL: + out.mode = grid::MODE_THREE_COL_L; + break; + case grid::MODE_THREE_COL_S: + default: + out.mode = grid::MODE_TWO_COL; + } + } + } else { + // new position, so start with initial mode + out.pos = req_pos; + switch (req_pos) { + case grid::POS_UP_CENTER: + case grid::POS_CENTER: + case grid::POS_DOWN_CENTER: + // for center col: start with 3x2L + out.mode = grid::MODE_THREE_COL_L; + break; + default: + // for everything else: start with 2x2 + out.mode = grid::MODE_TWO_COL; + } + } + DEBUG("curpos=%s curmode=%s + reqpos=%s -> pos=%s mode=%s", + pos_str(cur.pos), mode_str(cur.mode), pos_str(req_pos), + pos_str(out.pos), mode_str(out.mode)); + return true; } /* given window's state, calculate its dimensions. could have some kind of fancy autogeneration here, but there's a very finite number of possible positions (for now?) */ bool PositionCalc::StateToDim(const Dimensions& viewport, const State& state, - Dimensions& out) const { - bool ret = true; - long rel_x = 0, rel_y = 0;//coordinates relative to viewport - switch (state.mode) { - case grid::MODE_TWO_COL: - switch (state.pos) { - case grid::POS_UP_LEFT:// top left quadrant - rel_x = 0; - rel_y = 0; - out.width = viewport.width / 2.; - out.height = viewport.height / 2.; - break; - case grid::POS_UP_CENTER:// invalid, use mode THREE_COL_S/L - return false; - case grid::POS_UP_RIGHT:// top right quadrant - rel_x = viewport.width / 2.; - rel_y = 0; - out.width = viewport.width / 2.; - out.height = viewport.height / 2.; - break; - case grid::POS_LEFT:// left half - rel_x = 0; - rel_y = 0; - out.width = viewport.width / 2.; - out.height = viewport.height; - break; - case grid::POS_CENTER:// invalid, use mode THREE_COL_S/L - return false; - case grid::POS_RIGHT:// right half - rel_x = viewport.width / 2.; - rel_y = 0; - out.width = viewport.width / 2.; - out.height = viewport.height; - break; - case grid::POS_DOWN_LEFT:// bottom left quadrant - rel_x = 0; - rel_y = viewport.height / 2.; - out.width = viewport.width / 2.; - out.height = viewport.height / 2.; - break; - case grid::POS_DOWN_CENTER:// invalid, use mode THREE_COL_S/L - return false; - case grid::POS_DOWN_RIGHT:// bottom right quadrant - rel_x = viewport.width / 2.; - rel_y = viewport.height / 2.; - out.width = viewport.width / 2.; - out.height = viewport.height / 2.; - break; - default: - ret = false; - break; - } - break; - case grid::MODE_THREE_COL_S: - switch (state.pos) { - case grid::POS_UP_LEFT:// top left col - rel_x = 0; - rel_y = 0; - out.width = viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_UP_CENTER:// top center col - rel_x = viewport.width / 3.; - rel_y = 0; - out.width = viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_UP_RIGHT:// top right col - rel_x = 2 * viewport.width / 3.; - rel_y = 0; - out.width = viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_LEFT:// left third - rel_x = 0; - rel_y = 0; - out.width = viewport.width / 3.; - out.height = viewport.height; - break; - case grid::POS_CENTER:// center col - rel_x = viewport.width / 3.; - rel_y = 0; - out.width = viewport.width / 3.; - out.height = viewport.height; - break; - case grid::POS_RIGHT:// right third - rel_x = 2 * viewport.width / 3.; - rel_y = 0; - out.width = viewport.width / 3; - out.height = viewport.height; - break; - case grid::POS_DOWN_LEFT:// bottom left col - rel_x = 0; - rel_y = viewport.height / 2.; - out.width = viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_DOWN_CENTER:// bottom center col - rel_x = viewport.width / 3.; - rel_y = viewport.height / 2.; - out.width = viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_DOWN_RIGHT:// bottom right col - rel_x = 2 * viewport.width / 3.; - rel_y = viewport.height / 2.; - out.width = viewport.width / 3.; - out.height = viewport.height / 2.; - break; - default: - ret = false; - } - break; - case grid::MODE_THREE_COL_L: - switch (state.pos) { - case grid::POS_UP_LEFT:// top left two cols - rel_x = 0; - rel_y = 0; - out.width = 2 * viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_UP_CENTER:// top half - rel_x = 0; - rel_y = 0; - out.width = viewport.width; - out.height = viewport.height / 2.; - break; - case grid::POS_UP_RIGHT:// top right two cols - rel_x = viewport.width / 3.; - rel_y = 0; - out.width = 2 * viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_LEFT:// left two thirds - rel_x = 0; - rel_y = 0; - out.width = 2 * viewport.width / 3.; - out.height = viewport.height; - break; - case grid::POS_CENTER:// full screen - rel_x = 0; - rel_y = 0; - out.width = viewport.width; - out.height = viewport.height; - break; - case grid::POS_RIGHT:// right two thirds - rel_x = viewport.width / 3.; - rel_y = 0; - out.width = 2 * viewport.width / 3.; - out.height = viewport.height; - break; - case grid::POS_DOWN_LEFT:// bottom left two cols - rel_x = 0; - rel_y = viewport.height / 2.; - out.width = 2 * viewport.width / 3.; - out.height = viewport.height / 2.; - break; - case grid::POS_DOWN_CENTER:// bottom half - rel_x = 0; - rel_y = viewport.height / 2.; - out.width = viewport.width; - out.height = viewport.height / 2.; - break; - case grid::POS_DOWN_RIGHT:// bottom right two cols - rel_x = viewport.width / 3.; - rel_y = viewport.height / 2.; - out.width = 2 * viewport.width / 3.; - out.height = viewport.height / 2.; - break; - default: - ret = false; - } - break; - default: - ret = false; - } - if (ret) { - //convert relative pos to absolute: - out.x = rel_x + viewport.x; - out.y = rel_y + viewport.y; - DEBUG("pos=%s mode=%s -> %ldx %ldy %luw %luh", - pos_str(state.pos), mode_str(state.mode), - out.x, out.y, out.width, out.height); - } else { - ERROR("Bad pos=%s + mode=%s", pos_str(state.pos), mode_str(state.mode)); - } - return ret; + Dimensions& out) const { + bool ret = true; + long rel_x = 0, rel_y = 0;//coordinates relative to viewport + switch (state.mode) { + case grid::MODE_TWO_COL: + switch (state.pos) { + case grid::POS_UP_LEFT:// top left quadrant + rel_x = 0; + rel_y = 0; + out.width = viewport.width / 2.; + out.height = viewport.height / 2.; + break; + case grid::POS_UP_CENTER:// invalid, use mode THREE_COL_S/L + return false; + case grid::POS_UP_RIGHT:// top right quadrant + rel_x = viewport.width / 2.; + rel_y = 0; + out.width = viewport.width / 2.; + out.height = viewport.height / 2.; + break; + case grid::POS_LEFT:// left half + rel_x = 0; + rel_y = 0; + out.width = viewport.width / 2.; + out.height = viewport.height; + break; + case grid::POS_CENTER:// invalid, use mode THREE_COL_S/L + return false; + case grid::POS_RIGHT:// right half + rel_x = viewport.width / 2.; + rel_y = 0; + out.width = viewport.width / 2.; + out.height = viewport.height; + break; + case grid::POS_DOWN_LEFT:// bottom left quadrant + rel_x = 0; + rel_y = viewport.height / 2.; + out.width = viewport.width / 2.; + out.height = viewport.height / 2.; + break; + case grid::POS_DOWN_CENTER:// invalid, use mode THREE_COL_S/L + return false; + case grid::POS_DOWN_RIGHT:// bottom right quadrant + rel_x = viewport.width / 2.; + rel_y = viewport.height / 2.; + out.width = viewport.width / 2.; + out.height = viewport.height / 2.; + break; + default: + ret = false; + break; + } + break; + case grid::MODE_THREE_COL_S: + switch (state.pos) { + case grid::POS_UP_LEFT:// top left col + rel_x = 0; + rel_y = 0; + out.width = viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_UP_CENTER:// top center col + rel_x = viewport.width / 3.; + rel_y = 0; + out.width = viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_UP_RIGHT:// top right col + rel_x = 2 * viewport.width / 3.; + rel_y = 0; + out.width = viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_LEFT:// left third + rel_x = 0; + rel_y = 0; + out.width = viewport.width / 3.; + out.height = viewport.height; + break; + case grid::POS_CENTER:// center col + rel_x = viewport.width / 3.; + rel_y = 0; + out.width = viewport.width / 3.; + out.height = viewport.height; + break; + case grid::POS_RIGHT:// right third + rel_x = 2 * viewport.width / 3.; + rel_y = 0; + out.width = viewport.width / 3; + out.height = viewport.height; + break; + case grid::POS_DOWN_LEFT:// bottom left col + rel_x = 0; + rel_y = viewport.height / 2.; + out.width = viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_DOWN_CENTER:// bottom center col + rel_x = viewport.width / 3.; + rel_y = viewport.height / 2.; + out.width = viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_DOWN_RIGHT:// bottom right col + rel_x = 2 * viewport.width / 3.; + rel_y = viewport.height / 2.; + out.width = viewport.width / 3.; + out.height = viewport.height / 2.; + break; + default: + ret = false; + } + break; + case grid::MODE_THREE_COL_L: + switch (state.pos) { + case grid::POS_UP_LEFT:// top left two cols + rel_x = 0; + rel_y = 0; + out.width = 2 * viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_UP_CENTER:// top half + rel_x = 0; + rel_y = 0; + out.width = viewport.width; + out.height = viewport.height / 2.; + break; + case grid::POS_UP_RIGHT:// top right two cols + rel_x = viewport.width / 3.; + rel_y = 0; + out.width = 2 * viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_LEFT:// left two thirds + rel_x = 0; + rel_y = 0; + out.width = 2 * viewport.width / 3.; + out.height = viewport.height; + break; + case grid::POS_CENTER:// full screen + rel_x = 0; + rel_y = 0; + out.width = viewport.width; + out.height = viewport.height; + break; + case grid::POS_RIGHT:// right two thirds + rel_x = viewport.width / 3.; + rel_y = 0; + out.width = 2 * viewport.width / 3.; + out.height = viewport.height; + break; + case grid::POS_DOWN_LEFT:// bottom left two cols + rel_x = 0; + rel_y = viewport.height / 2.; + out.width = 2 * viewport.width / 3.; + out.height = viewport.height / 2.; + break; + case grid::POS_DOWN_CENTER:// bottom half + rel_x = 0; + rel_y = viewport.height / 2.; + out.width = viewport.width; + out.height = viewport.height / 2.; + break; + case grid::POS_DOWN_RIGHT:// bottom right two cols + rel_x = viewport.width / 3.; + rel_y = viewport.height / 2.; + out.width = 2 * viewport.width / 3.; + out.height = viewport.height / 2.; + break; + default: + ret = false; + } + break; + default: + ret = false; + } + if (ret) { + //convert relative pos to absolute: + out.x = rel_x + viewport.x; + out.y = rel_y + viewport.y; + DEBUG("pos=%s mode=%s -> %ldx %ldy %luw %luh", + pos_str(state.pos), mode_str(state.mode), + out.x, out.y, out.width, out.height); + } else { + ERROR("Bad pos=%s + mode=%s", pos_str(state.pos), mode_str(state.mode)); + } + return ret; } void PositionCalc::ViewportToDim(const Dimensions& cur_viewport, - const Dimensions& next_viewport, Dimensions& out) const { - // just do an exact scaling to the new viewport - if (cur_viewport.width == 0 || cur_viewport.height == 0) {//nice to have, avoid div0 - out = next_viewport;//just throw something together and get out - return; - } - const double ratio_x = next_viewport.width / (double)cur_viewport.width, - ratio_y = next_viewport.height / (double)cur_viewport.height; + const Dimensions& next_viewport, Dimensions& out) const { + // just do an exact scaling to the new viewport + if (cur_viewport.width == 0 || cur_viewport.height == 0) {//nice to have, avoid div0 + out = next_viewport;//just throw something together and get out + return; + } + const double ratio_x = next_viewport.width / (double)cur_viewport.width, + ratio_y = next_viewport.height / (double)cur_viewport.height; - // avoid implicit floor to avoid cumulative rounding error: - out.x = round((window.x - cur_viewport.x) * ratio_x + next_viewport.x); - out.y = round((window.y - cur_viewport.y) * ratio_y + next_viewport.y); - out.width = round(window.width * ratio_x); - out.height = round(window.height * ratio_y); + // avoid implicit floor to avoid cumulative rounding error: + out.x = round((window.x - cur_viewport.x) * ratio_x + next_viewport.x); + out.y = round((window.y - cur_viewport.y) * ratio_y + next_viewport.y); + out.width = round(window.width * ratio_x); + out.height = round(window.height * ratio_y); } diff --git a/src/position.h b/src/position.h index d72a7c4..658d91e 100644 --- a/src/position.h +++ b/src/position.h @@ -23,48 +23,48 @@ #include "dimensions.h" namespace grid { - enum MODE { - MODE_UNKNOWN, - MODE_TWO_COL,// 2x2 (not applicable for center col positions) - MODE_THREE_COL_S,// 3x2 small: each position filling 1 column - MODE_THREE_COL_L// 3x2 large: sides filling 2 columns and center filling full width - }; + enum MODE { + MODE_UNKNOWN, + MODE_TWO_COL,// 2x2 (not applicable for center col positions) + MODE_THREE_COL_S,// 3x2 small: each position filling 1 column + MODE_THREE_COL_L// 3x2 large: sides filling 2 columns and center filling full width + }; } struct State { - State() : pos(grid::POS_UNKNOWN), mode(grid::MODE_UNKNOWN) { } + State() : pos(grid::POS_UNKNOWN), mode(grid::MODE_UNKNOWN) { } - grid::POS pos; - grid::MODE mode; + grid::POS pos; + grid::MODE mode; }; class PositionCalc { public: - PositionCalc(const Dimensions& window) - : window(window) { } + PositionCalc(const Dimensions& window) + : window(window) { } - /* Produces an autodetected state of this window using its current - * coordinates. Returns true on success, else false. */ - bool CurState(const Dimensions& viewport, State& cur_state) const; + /* Produces an autodetected state of this window using its current + * coordinates. Returns true on success, else false. */ + bool CurState(const Dimensions& viewport, State& cur_state) const; - /* Given a current state and requested position for the window, calculates - * its next state. Returns true on success, else false. */ - bool NextState(const State& cur_state, grid::POS req_pos, - State& next_state) const; + /* Given a current state and requested position for the window, calculates + * its next state. Returns true on success, else false. */ + bool NextState(const State& cur_state, grid::POS req_pos, + State& next_state) const; - /* Given a state for the window, calculates the dimensions of that position. - * Returns true on success, else false. */ - bool StateToDim(const Dimensions& viewport, const State& state, - Dimensions& out) const; + /* Given a state for the window, calculates the dimensions of that position. + * Returns true on success, else false. */ + bool StateToDim(const Dimensions& viewport, const State& state, + Dimensions& out) const; - /* Special case of StateToDim: Given the current viewport and next viewport - * for a window with no autodetected state, calculates a reasonable location - * in the new viewport. */ - void ViewportToDim(const Dimensions& cur_viewport, - const Dimensions& next_viewport, Dimensions& out) const; + /* Special case of StateToDim: Given the current viewport and next viewport + * for a window with no autodetected state, calculates a reasonable location + * in the new viewport. */ + void ViewportToDim(const Dimensions& cur_viewport, + const Dimensions& next_viewport, Dimensions& out) const; private: - const Dimensions window; + const Dimensions window; }; #endif diff --git a/src/viewport-imp-ewmh.cpp b/src/viewport-imp-ewmh.cpp index 0c72eae..69f8550 100644 --- a/src/viewport-imp-ewmh.cpp +++ b/src/viewport-imp-ewmh.cpp @@ -21,66 +21,66 @@ #include "x11-util.h" bool viewport::ewmh::get_viewports(Display* disp, const Dimensions& /*activewin*/, - dim_list_t& viewports_out, size_t& active_out) { - //get current workspace - unsigned long cur_workspace; - { - unsigned long* cur_ptr; - static Atom curdesk_msg = XInternAtom(disp, "_NET_CURRENT_DESKTOP", False); - if (!(cur_ptr = (unsigned long *)x11_util::get_property(disp, DefaultRootWindow(disp), - XA_CARDINAL, curdesk_msg, NULL))) { - ERROR_DIR("unable to retrieve current desktop"); - return false; - } - cur_workspace = *cur_ptr; - x11_util::free_property(cur_ptr); - } + dim_list_t& viewports_out, size_t& active_out) { + //get current workspace + unsigned long cur_workspace; + { + unsigned long* cur_ptr; + static Atom curdesk_msg = XInternAtom(disp, "_NET_CURRENT_DESKTOP", False); + if (!(cur_ptr = (unsigned long *)x11_util::get_property(disp, DefaultRootWindow(disp), + XA_CARDINAL, curdesk_msg, NULL))) { + ERROR_DIR("unable to retrieve current desktop"); + return false; + } + cur_workspace = *cur_ptr; + x11_util::free_property(cur_ptr); + } - unsigned long* area; - size_t area_count = 0;//number of areas returned, one per workspace. each area contains 4 ulongs. - static Atom workarea_msg = XInternAtom(disp, "_NET_WORKAREA", False); - if (!(area = (unsigned long*)x11_util::get_property(disp, DefaultRootWindow(disp), - XA_CARDINAL, workarea_msg, &area_count))) { - ERROR_DIR("unable to retrieve spanning workarea"); - return false; - } - if (area_count == 0) { - ERROR_DIR("unable to retrieve spanning workarea."); - x11_util::free_property(area); - return false; - } - if (cur_workspace >= (area_count * 4) || area_count % 4 != 0) {//nice to have - ERROR("got invalid workarea count: %d (cur workspace: %d)", - area_count, cur_workspace); - x11_util::free_property(area); - return false; - } + unsigned long* area; + size_t area_count = 0;//number of areas returned, one per workspace. each area contains 4 ulongs. + static Atom workarea_msg = XInternAtom(disp, "_NET_WORKAREA", False); + if (!(area = (unsigned long*)x11_util::get_property(disp, DefaultRootWindow(disp), + XA_CARDINAL, workarea_msg, &area_count))) { + ERROR_DIR("unable to retrieve spanning workarea"); + return false; + } + if (area_count == 0) { + ERROR_DIR("unable to retrieve spanning workarea."); + x11_util::free_property(area); + return false; + } + if (cur_workspace >= (area_count * 4) || area_count % 4 != 0) {//nice to have + ERROR("got invalid workarea count: %d (cur workspace: %d)", + area_count, cur_workspace); + x11_util::free_property(area); + return false; + } - if (config::debug_enabled) { - for (size_t i = 0; i < area_count/4; ++i) { - if (i == cur_workspace) { - DEBUG("active workspace %lu of %lu: %lux %luy %luw %luh", - i+1, area_count/4, - area[i*4], area[i*4+1], area[i*4+2], area[i*4+3]); - } else { - DEBUG("inactive workspace %lu of %lu: %lux %luy %luw %luh", - i+1, area_count/4, - area[i*4], area[i*4+1], area[i*4+2], area[i*4+3]); - } - } - } + if (config::debug_enabled) { + for (size_t i = 0; i < area_count/4; ++i) { + if (i == cur_workspace) { + DEBUG("active workspace %lu of %lu: %lux %luy %luw %luh", + i+1, area_count/4, + area[i*4], area[i*4+1], area[i*4+2], area[i*4+3]); + } else { + DEBUG("inactive workspace %lu of %lu: %lux %luy %luw %luh", + i+1, area_count/4, + area[i*4], area[i*4+1], area[i*4+2], area[i*4+3]); + } + } + } - //set current workspace as viewport - viewports_out.clear();//nice to have - viewports_out.push_back(Dimensions()); - active_out = 0; + //set current workspace as viewport + viewports_out.clear();//nice to have + viewports_out.push_back(Dimensions()); + active_out = 0; - Dimensions& v = viewports_out.back(); - v.x = area[cur_workspace*4]; - v.y = area[(cur_workspace*4)+1]; - v.width = area[(cur_workspace*4)+2]; - v.height = area[(cur_workspace*4)+3]; + Dimensions& v = viewports_out.back(); + v.x = area[cur_workspace*4]; + v.y = area[(cur_workspace*4)+1]; + v.width = area[(cur_workspace*4)+2]; + v.height = area[(cur_workspace*4)+3]; - x11_util::free_property(area); - return true; + x11_util::free_property(area); + return true; } diff --git a/src/viewport-imp-ewmh.h b/src/viewport-imp-ewmh.h index 16ef36f..1b08102 100644 --- a/src/viewport-imp-ewmh.h +++ b/src/viewport-imp-ewmh.h @@ -27,10 +27,10 @@ typedef std::vector dim_list_t; namespace viewport { - namespace ewmh { - bool get_viewports(Display* disp, const Dimensions& activewin, - dim_list_t& viewports_out, size_t& active_out); - } + namespace ewmh { + bool get_viewports(Display* disp, const Dimensions& activewin, + dim_list_t& viewports_out, size_t& active_out); + } } #endif diff --git a/src/viewport-imp-xinerama.cpp b/src/viewport-imp-xinerama.cpp index 75675e2..0640016 100644 --- a/src/viewport-imp-xinerama.cpp +++ b/src/viewport-imp-xinerama.cpp @@ -26,216 +26,216 @@ #define MAX(a,b) (((a) > (b)) ? (a) : (b)) static int INTERSECTION(int a1, int a2, int b1, int b2) { - int ret = (a2 < b1 || b2 < a1) ? 0 : - (a1 >= b1) ? - ((a2 >= b2) ? (b2 - a1) : (a2 - a1)) : - ((a2 >= b2) ? (b2 - b1) : (a2 - b1)); - DEBUG("%d-%d x %d-%d = %d", a1, a2, b1, b2, ret); - return ret; + int ret = (a2 < b1 || b2 < a1) ? 0 : + (a1 >= b1) ? + ((a2 >= b2) ? (b2 - a1) : (a2 - a1)) : + ((a2 >= b2) ? (b2 - b1) : (a2 - b1)); + DEBUG("%d-%d x %d-%d = %d", a1, a2, b1, b2, ret); + return ret; } namespace { - bool get_screens(Display* disp, const Dimensions& activewin, - Dimensions& bounding_box, dim_list_t& viewports, - size_t& active_viewport) { - int screen_count = 0; - XineramaScreenInfo* screens = XineramaQueryScreens(disp, &screen_count); - if (screens == NULL || screen_count == 0) { - DEBUG_DIR("xinerama not loaded or unavailable"); - if (screens != NULL) { - XFree(screens); - } - return false; - } - - //initialize bounding box to something - bounding_box.x = screens[0].x_org; - bounding_box.y = screens[0].y_org; - int bound_max_x = screens[0].x_org + screens[0].width, - bound_max_y = screens[0].y_org + screens[0].height; - - // search for largest overlap between active window and xinerama screen. - // the screen with the most overlap is the 'active screen' - int active_overlap = 0; - - for (int i = 0; i < screen_count; ++i) { - const XineramaScreenInfo& screen = screens[i]; - - // grow bounding box - bounding_box.x = MIN(bounding_box.x, screen.x_org); - bounding_box.y = MIN(bounding_box.y, screen.y_org); - bound_max_x = MAX(bound_max_x, screen.x_org + screen.width); - bound_max_y = MAX(bound_max_y, screen.y_org + screen.height); - - // add viewport - viewports.push_back(Dimensions()); - Dimensions& v = viewports.back(); - v.x = screen.x_org; - v.y = screen.y_org; - v.width = screen.width; - v.height = screen.height; - - // check active overlap - int overlap = - INTERSECTION(screen.x_org, screen.x_org + screen.width, - activewin.x, activewin.x + activewin.width) * - INTERSECTION(screen.y_org, screen.y_org + screen.height, - activewin.y, activewin.y + activewin.height); - - DEBUG("screen %d of %d: %dx %dy %dw %dh (overlap %d)", - i+1, screen_count, - screen.x_org, screen.y_org, screen.width, screen.height, - overlap); - - if (overlap > active_overlap) { - // overlap is bigger, update active counters - active_overlap = overlap; - active_viewport = i; - } - }; - - DEBUG("active screen is %lu of %d", active_viewport+1, screen_count); - - bounding_box.width = bound_max_x - bounding_box.x; - bounding_box.height = bound_max_y - bounding_box.y; - DEBUG("desktop bounding box: %ldx %ldy %ldw %ldh", - bounding_box.x, bounding_box.y, - bounding_box.width, bounding_box.height); - - XFree(screens); - return true; - } - - struct strut { - enum TYPE { - LEFT, RIGHT, TOP, BOTTOM - }; - - strut(TYPE type, size_t width, size_t min, size_t max) - : type(type), width(width), min(min), max(max) { } - - TYPE type; - size_t width, min, max; - }; - - bool get_struts(Display* disp, std::vector& out) { - Window* clients; - size_t client_count = 0; - static Atom clientlist_msg = XInternAtom(disp, "_NET_CLIENT_LIST", False); - if (!(clients = (Window*)x11_util::get_property(disp, DefaultRootWindow(disp), - XA_WINDOW, clientlist_msg, &client_count))) { - ERROR_DIR("unable to retrieve list of clients"); - return false; - } - for (size_t i = 0; i < client_count; ++i) { - unsigned long* xstrut; - size_t xstrut_count = 0;//number of strut values for this client (should always be 12) - static Atom strut_msg = XInternAtom(disp, "_NET_WM_STRUT_PARTIAL", False); - if (!(xstrut = (unsigned long*)x11_util::get_property(disp, clients[i], - XA_CARDINAL, strut_msg, &xstrut_count))) { - //DEBUG("client %lu of %lu lacks struts", i+1, client_count); - continue; - } - if (xstrut_count != 12) {//nice to have - ERROR_DIR("incorrect number of strut values: got %lu, expected 12", xstrut_count); - x11_util::free_property(clients); - x11_util::free_property(xstrut); - return false; - } - - DEBUG("client %lu of %lu struts: left:%lu@%lu-%lu right:%lu@%lu-%lu top:%lu@%lu-%lu bot:%lu@%lu-%lu", - i+1, client_count, - xstrut[0], xstrut[4], xstrut[5], - xstrut[1], xstrut[6], xstrut[7], - xstrut[2], xstrut[8], xstrut[9], - xstrut[3], xstrut[10], xstrut[11]); - - //left - if (xstrut[0] > 0) { - out.push_back(strut(strut::LEFT, xstrut[0], xstrut[4], xstrut[5])); - } - //right - if (xstrut[1] > 0) { - out.push_back(strut(strut::RIGHT, xstrut[1], xstrut[6], xstrut[7])); - } - //top - if (xstrut[2] > 0) { - out.push_back(strut(strut::TOP, xstrut[2], xstrut[8], xstrut[9])); - } - //bot - if (xstrut[3] > 0) { - out.push_back(strut(strut::BOTTOM, xstrut[3], xstrut[10], xstrut[11])); - } - - x11_util::free_property(xstrut); - } - x11_util::free_property(clients); - return true; - } - - void trim_screen(const Dimensions& bound, const std::vector& struts, - Dimensions& screen) { - //for simpler math, operate on things in terms of min/max - long screen_max_x = screen.x + screen.width, - screen_max_y = screen.y + screen.height; - - for (std::vector::const_iterator iter = struts.begin(); - iter != struts.end(); ++iter) { - switch (iter->type) { - case strut::LEFT: - // first check if it intersects our screen's min/max y - if (INTERSECTION(screen.y, screen_max_y, iter->min, iter->max) != 0) { - //then check if the strut (relative to the bounding box) actually exceeds our min x - screen.x = MAX(screen.x, (long)iter->width - bound.x); - } - break; - case strut::RIGHT: - if (INTERSECTION(screen.y, screen_max_y, iter->min, iter->max) != 0) { - long bound_max_x = bound.x + bound.width; - screen_max_x = MIN(screen_max_x, bound_max_x - iter->width); - } - break; - case strut::TOP: - if (INTERSECTION(screen.x, screen_max_x, iter->min, iter->max) != 0) { - screen.y = MAX(screen.y, (long)iter->width - bound.y); - } - break; - case strut::BOTTOM: - if (INTERSECTION(screen.x, screen_max_x, iter->min, iter->max) != 0) { - long bound_max_y = bound.y + bound.height; - screen_max_y = MIN(screen_max_y, bound_max_y - iter->width); - } - break; - } - } - - screen.width = screen_max_x - screen.x; - screen.height = screen_max_y - screen.y; - - DEBUG("trimmed: %ldx %ldy %ldw %ldh", - screen.x, screen.y, screen.width, screen.height); - } + bool get_screens(Display* disp, const Dimensions& activewin, + Dimensions& bounding_box, dim_list_t& viewports, + size_t& active_viewport) { + int screen_count = 0; + XineramaScreenInfo* screens = XineramaQueryScreens(disp, &screen_count); + if (screens == NULL || screen_count == 0) { + DEBUG_DIR("xinerama not loaded or unavailable"); + if (screens != NULL) { + XFree(screens); + } + return false; + } + + //initialize bounding box to something + bounding_box.x = screens[0].x_org; + bounding_box.y = screens[0].y_org; + int bound_max_x = screens[0].x_org + screens[0].width, + bound_max_y = screens[0].y_org + screens[0].height; + + // search for largest overlap between active window and xinerama screen. + // the screen with the most overlap is the 'active screen' + int active_overlap = 0; + + for (int i = 0; i < screen_count; ++i) { + const XineramaScreenInfo& screen = screens[i]; + + // grow bounding box + bounding_box.x = MIN(bounding_box.x, screen.x_org); + bounding_box.y = MIN(bounding_box.y, screen.y_org); + bound_max_x = MAX(bound_max_x, screen.x_org + screen.width); + bound_max_y = MAX(bound_max_y, screen.y_org + screen.height); + + // add viewport + viewports.push_back(Dimensions()); + Dimensions& v = viewports.back(); + v.x = screen.x_org; + v.y = screen.y_org; + v.width = screen.width; + v.height = screen.height; + + // check active overlap + int overlap = + INTERSECTION(screen.x_org, screen.x_org + screen.width, + activewin.x, activewin.x + activewin.width) * + INTERSECTION(screen.y_org, screen.y_org + screen.height, + activewin.y, activewin.y + activewin.height); + + DEBUG("screen %d of %d: %dx %dy %dw %dh (overlap %d)", + i+1, screen_count, + screen.x_org, screen.y_org, screen.width, screen.height, + overlap); + + if (overlap > active_overlap) { + // overlap is bigger, update active counters + active_overlap = overlap; + active_viewport = i; + } + }; + + DEBUG("active screen is %lu of %d", active_viewport+1, screen_count); + + bounding_box.width = bound_max_x - bounding_box.x; + bounding_box.height = bound_max_y - bounding_box.y; + DEBUG("desktop bounding box: %ldx %ldy %ldw %ldh", + bounding_box.x, bounding_box.y, + bounding_box.width, bounding_box.height); + + XFree(screens); + return true; + } + + struct strut { + enum TYPE { + LEFT, RIGHT, TOP, BOTTOM + }; + + strut(TYPE type, size_t width, size_t min, size_t max) + : type(type), width(width), min(min), max(max) { } + + TYPE type; + size_t width, min, max; + }; + + bool get_struts(Display* disp, std::vector& out) { + Window* clients; + size_t client_count = 0; + static Atom clientlist_msg = XInternAtom(disp, "_NET_CLIENT_LIST", False); + if (!(clients = (Window*)x11_util::get_property(disp, DefaultRootWindow(disp), + XA_WINDOW, clientlist_msg, &client_count))) { + ERROR_DIR("unable to retrieve list of clients"); + return false; + } + for (size_t i = 0; i < client_count; ++i) { + unsigned long* xstrut; + size_t xstrut_count = 0;//number of strut values for this client (should always be 12) + static Atom strut_msg = XInternAtom(disp, "_NET_WM_STRUT_PARTIAL", False); + if (!(xstrut = (unsigned long*)x11_util::get_property(disp, clients[i], + XA_CARDINAL, strut_msg, &xstrut_count))) { + //DEBUG("client %lu of %lu lacks struts", i+1, client_count); + continue; + } + if (xstrut_count != 12) {//nice to have + ERROR_DIR("incorrect number of strut values: got %lu, expected 12", xstrut_count); + x11_util::free_property(clients); + x11_util::free_property(xstrut); + return false; + } + + DEBUG("client %lu of %lu struts: left:%lu@%lu-%lu right:%lu@%lu-%lu top:%lu@%lu-%lu bot:%lu@%lu-%lu", + i+1, client_count, + xstrut[0], xstrut[4], xstrut[5], + xstrut[1], xstrut[6], xstrut[7], + xstrut[2], xstrut[8], xstrut[9], + xstrut[3], xstrut[10], xstrut[11]); + + //left + if (xstrut[0] > 0) { + out.push_back(strut(strut::LEFT, xstrut[0], xstrut[4], xstrut[5])); + } + //right + if (xstrut[1] > 0) { + out.push_back(strut(strut::RIGHT, xstrut[1], xstrut[6], xstrut[7])); + } + //top + if (xstrut[2] > 0) { + out.push_back(strut(strut::TOP, xstrut[2], xstrut[8], xstrut[9])); + } + //bot + if (xstrut[3] > 0) { + out.push_back(strut(strut::BOTTOM, xstrut[3], xstrut[10], xstrut[11])); + } + + x11_util::free_property(xstrut); + } + x11_util::free_property(clients); + return true; + } + + void trim_screen(const Dimensions& bound, const std::vector& struts, + Dimensions& screen) { + //for simpler math, operate on things in terms of min/max + long screen_max_x = screen.x + screen.width, + screen_max_y = screen.y + screen.height; + + for (std::vector::const_iterator iter = struts.begin(); + iter != struts.end(); ++iter) { + switch (iter->type) { + case strut::LEFT: + // first check if it intersects our screen's min/max y + if (INTERSECTION(screen.y, screen_max_y, iter->min, iter->max) != 0) { + //then check if the strut (relative to the bounding box) actually exceeds our min x + screen.x = MAX(screen.x, (long)iter->width - bound.x); + } + break; + case strut::RIGHT: + if (INTERSECTION(screen.y, screen_max_y, iter->min, iter->max) != 0) { + long bound_max_x = bound.x + bound.width; + screen_max_x = MIN(screen_max_x, bound_max_x - iter->width); + } + break; + case strut::TOP: + if (INTERSECTION(screen.x, screen_max_x, iter->min, iter->max) != 0) { + screen.y = MAX(screen.y, (long)iter->width - bound.y); + } + break; + case strut::BOTTOM: + if (INTERSECTION(screen.x, screen_max_x, iter->min, iter->max) != 0) { + long bound_max_y = bound.y + bound.height; + screen_max_y = MIN(screen_max_y, bound_max_y - iter->width); + } + break; + } + } + + screen.width = screen_max_x - screen.x; + screen.height = screen_max_y - screen.y; + + DEBUG("trimmed: %ldx %ldy %ldw %ldh", + screen.x, screen.y, screen.width, screen.height); + } } bool viewport::xinerama::get_viewports(Display* disp, const Dimensions& activewin, - dim_list_t& viewports_out, size_t& active_out) { - viewports_out.clear(); - - Dimensions bounding_box; - if (!get_screens(disp, activewin, bounding_box, viewports_out, active_out)) { - return false; - } - - std::vector struts; - if (!get_struts(disp, struts)) { - return false; - } - - // trim struts from viewports - for (dim_list_t::iterator iter = viewports_out.begin(); - iter != viewports_out.end(); ++iter) { - trim_screen(bounding_box, struts, *iter); - } - - return true; + dim_list_t& viewports_out, size_t& active_out) { + viewports_out.clear(); + + Dimensions bounding_box; + if (!get_screens(disp, activewin, bounding_box, viewports_out, active_out)) { + return false; + } + + std::vector struts; + if (!get_struts(disp, struts)) { + return false; + } + + // trim struts from viewports + for (dim_list_t::iterator iter = viewports_out.begin(); + iter != viewports_out.end(); ++iter) { + trim_screen(bounding_box, struts, *iter); + } + + return true; } diff --git a/src/viewport-imp-xinerama.h b/src/viewport-imp-xinerama.h index aa95f18..0813bd0 100644 --- a/src/viewport-imp-xinerama.h +++ b/src/viewport-imp-xinerama.h @@ -33,10 +33,10 @@ typedef std::vector dim_list_t; namespace viewport { - namespace xinerama { - bool get_viewports(Display* disp, const Dimensions& activewin, - dim_list_t& viewports_out, size_t& active_out); - } + namespace xinerama { + bool get_viewports(Display* disp, const Dimensions& activewin, + dim_list_t& viewports_out, size_t& active_out); + } } #endif diff --git a/src/viewport.cpp b/src/viewport.cpp index 1b37702..1661a96 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -28,52 +28,52 @@ #endif namespace { - bool get_all(const Dimensions& activewin, - dim_list_t& viewports, size_t& active) { - Display* disp = XOpenDisplay(NULL); - if (disp == NULL) { - ERROR_DIR("unable to get display"); - return false; - } + bool get_all(const Dimensions& activewin, + dim_list_t& viewports, size_t& active) { + Display* disp = XOpenDisplay(NULL); + if (disp == NULL) { + ERROR_DIR("unable to get display"); + return false; + } #ifdef USE_XINERAMA - //try xinerama, fall back to ewmh if xinerama is unavailable - bool ok = viewport::xinerama::get_viewports(disp, activewin, viewports, active) || - viewport::ewmh::get_viewports(disp, activewin, viewports, active); + //try xinerama, fall back to ewmh if xinerama is unavailable + bool ok = viewport::xinerama::get_viewports(disp, activewin, viewports, active) || + viewport::ewmh::get_viewports(disp, activewin, viewports, active); #else - //xinerama disabled; just do ewmh - bool ok = viewport::ewmh::get_viewports(disp, activewin, viewports, active); + //xinerama disabled; just do ewmh + bool ok = viewport::ewmh::get_viewports(disp, activewin, viewports, active); #endif - if (config::debug_enabled) { - for (size_t i = 0; i < viewports.size(); ++i) { - const Dimensions& v = viewports[i]; - DEBUG("viewport %lu: %dx %dy %luw %luh", - i, v.x, v.y, v.width, v.height); - } - } + if (config::debug_enabled) { + for (size_t i = 0; i < viewports.size(); ++i) { + const Dimensions& v = viewports[i]; + DEBUG("viewport %lu: %dx %dy %luw %luh", + i, v.x, v.y, v.width, v.height); + } + } - XCloseDisplay(disp); - return ok; - } + XCloseDisplay(disp); + return ok; + } } bool ViewportCalc::Viewports(grid::POS monitor, - Dimensions& cur_viewport, Dimensions& next_viewport) const { - dim_list_t viewports; - size_t active, neighbor; - if (!get_all(activewin, viewports, active)) { - return false; - } + Dimensions& cur_viewport, Dimensions& next_viewport) const { + dim_list_t viewports; + size_t active, neighbor; + if (!get_all(activewin, viewports, active)) { + return false; + } - neighbor::select(monitor, viewports, active, neighbor); + neighbor::select(monitor, viewports, active, neighbor); - cur_viewport = viewports[active]; - next_viewport = viewports[neighbor]; + cur_viewport = viewports[active]; + next_viewport = viewports[neighbor]; - DEBUG("cur viewport: %dx %dy %dw %dh", - cur_viewport.x, cur_viewport.y, cur_viewport.width, cur_viewport.height); - DEBUG("next viewport: %dx %dy %dw %dh", - next_viewport.x, next_viewport.y, next_viewport.width, next_viewport.height); - return true; + DEBUG("cur viewport: %dx %dy %dw %dh", + cur_viewport.x, cur_viewport.y, cur_viewport.width, cur_viewport.height); + DEBUG("next viewport: %dx %dy %dw %dh", + next_viewport.x, next_viewport.y, next_viewport.width, next_viewport.height); + return true; } diff --git a/src/viewport.h b/src/viewport.h index d9d9154..7100a08 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -24,14 +24,14 @@ class ViewportCalc { public: - ViewportCalc(const Dimensions& activewin) - : activewin(activewin) { } + ViewportCalc(const Dimensions& activewin) + : activewin(activewin) { } - bool Viewports(grid::POS monitor, - Dimensions& cur_viewport, Dimensions& next_viewport) const; + bool Viewports(grid::POS monitor, + Dimensions& cur_viewport, Dimensions& next_viewport) const; private: - const Dimensions activewin; + const Dimensions activewin; }; #endif diff --git a/src/window.cpp b/src/window.cpp index 71be3d9..0e3646c 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -24,398 +24,398 @@ #define SOURCE_INDICATION 2 //say that we're a pager or taskbar namespace { - int _client_msg(Display* disp, Window win, Atom msg, - unsigned long data0, unsigned long data1, - unsigned long data2, unsigned long data3, - unsigned long data4) { - XEvent event; - long mask = SubstructureRedirectMask | SubstructureNotifyMask; - - event.xclient.type = ClientMessage; - event.xclient.serial = 0; - event.xclient.send_event = True; - event.xclient.message_type = msg; - event.xclient.window = win; - event.xclient.format = 32; - event.xclient.data.l[0] = data0; - event.xclient.data.l[1] = data1; - event.xclient.data.l[2] = data2; - event.xclient.data.l[3] = data3; - event.xclient.data.l[4] = data4; - - DEBUG("send message_type=%s, data=(%lu,%lu,%lu,%lu,%lu)", - XGetAtomName(disp, msg), data0, data1, data2, data3, data4); - - if (XSendEvent(disp, DefaultRootWindow(disp), False, mask, &event)) { - return true; - } else { - ERROR("Cannot send %s event.", msg); - return false; - } - } - - inline void print_window(Display* disp, Window win) { - if (!config::debug_enabled) { return; } - Window root; - int x, y; - unsigned int width, height, border, depth; - if (XGetGeometry(disp, win, &root, &x, &y, &width, - &height, &border, &depth) == 0) { - ERROR_DIR("get geometry failed"); - return; - } - DEBUG(" %dx %dy %uw %uh %ub", x, y, width, height, border); - } - - Window* get_active_window(Display* disp) { - static Atom actwin_msg = XInternAtom(disp, "_NET_ACTIVE_WINDOW", False); - Window* ret = (Window*)x11_util::get_property(disp, DefaultRootWindow(disp), - XA_WINDOW, actwin_msg, NULL); - if (ret == NULL) { - ERROR_DIR("unable to get active window"); - } - return ret; - } - - bool is_dock_window(Display* disp, Window win) { - /* disallow moving/selecting this window if it has type DESKTOP or DOCK. - (avoid messing with the user's desktop components, eg taskbars) */ - bool ret = false; - size_t count = 0; - static Atom wintype_msg = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False); - Atom* types = (Atom*)x11_util::get_property(disp, win, XA_ATOM, wintype_msg, &count); - if (types == NULL) { - ERROR_DIR("couldn't get window types"); - //assume window types are fine, keep going - } else { - static Atom desktop_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DESKTOP", False), - dock_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False); - for (size_t i = 0; i < count; ++i) { - DEBUG("%d type %lu: %d %s", - win, i, types[i], XGetAtomName(disp, types[i])); - if (types[i] == desktop_type || types[i] == dock_type) { - ret = true; - if (!config::debug_enabled) { - break; - } - } - } - x11_util::free_property(types); - } - return ret; - } - - bool is_menu_window(Display* disp, Window win) { - /* also disallow moving/selecting this window if it has SKIP_PAGER or SKIP_TASKBAR. - (avoid messing with auxiliary panels and menus) */ - bool ret = false; - size_t count = 0; - static Atom state_msg = XInternAtom(disp, "_NET_WM_STATE", False); - Atom* states = (Atom*)x11_util::get_property(disp, win, XA_ATOM, state_msg, &count); - if (states == NULL) { - ERROR_DIR("couldn't get window states"); - //assume window states are fine, keep going - } else { - static Atom skip_pager = XInternAtom(disp, "_NET_WM_STATE_SKIP_PAGER", False), - skip_taskbar = XInternAtom(disp, "_NET_WM_STATE_SKIP_TASKBAR", False); - for (size_t i = 0; i < count; ++i) { - DEBUG("%d state %lu: %d %s", - win, i, states[i], XGetAtomName(disp, states[i])); - if (states[i] == skip_pager || states[i] == skip_taskbar) { - ret = true; - if (!config::debug_enabled) { - break; - } - } - } - x11_util::free_property(states); - } - return ret; - } - - bool get_window_size(Display* disp, Window win, - Dimensions* out_exterior = NULL, - unsigned int* out_margin_width = NULL, - unsigned int* out_margin_height = NULL) { - Window root; - unsigned int internal_width, internal_height; - { - /* first, get the interior width/height from this window - (so that we can calculate margins) */ - int x, y; - unsigned int border, depth; - if (XGetGeometry(disp, win, &root, &x, &y, &internal_width, - &internal_height, &border, &depth) == 0) { - ERROR_DIR("get geometry failed"); - return false; - } - } - - if (win == root) { - ERROR_DIR("this window is root! treating this as an error."); - return false; - } - - /* now traverse up the parents until we reach the one JUST BEFORE root, - and get the external width/height and x/y from that. */ - Window just_before_root; - { - int count = 1; - Window parent = win; - Window* children; - unsigned int children_count; - do { - just_before_root = parent; - if (XQueryTree(disp, just_before_root, &root, - &parent, &children, &children_count) == 0) { - ERROR_DIR("get query tree failed"); - return false; - } - if (children != NULL) { - XFree(children); - } - DEBUG("%d window=%lu, parent=%lu, root=%lu", - count, just_before_root, parent, root); - print_window(disp, just_before_root); - } while (++count < 50 && parent != root); - } - - int x, y; - unsigned int external_width, external_height; - { - unsigned int border, depth; - if (XGetGeometry(disp, just_before_root, &root, &x, &y, &external_width, - &external_height, &border, &depth) == 0) { - ERROR_DIR("get geometry failed"); - return false; - } - } - - if (out_exterior != NULL) { - out_exterior->x = x; - out_exterior->y = y; - out_exterior->width = external_width; - out_exterior->height = external_height; - } - - if (out_margin_width != NULL) { - *out_margin_width = external_width - internal_width; - } - if (out_margin_height != NULL) { - *out_margin_height = external_height - internal_height; - } - - DEBUG("size: exterior %uw %uh - interior %uw %uh = margins %dw %dh", - external_width, external_height, - internal_width, internal_height, - external_width - internal_width, - external_height - internal_height); - return true; - } - - bool activate_window(Display* disp, Window curactive, Window newactive) { - static Atom active_msg = XInternAtom(disp, "_NET_ACTIVE_WINDOW", False); - if (!_client_msg(disp, newactive, active_msg, - SOURCE_INDICATION, CurrentTime, curactive, 0, 0)) { - ERROR_DIR("couldn't activate"); - return false; - } - return true; - } - - bool set_window_state(Display* disp, Window win, Atom state1, Atom state2, bool enable) { - /* - this disagrees with docs, which say that we should be using a - _NET_WM_STATE_DISABLE/_ENABLE atom in data[0]. That apparently doesn't - work in practice, but '0'/'1' do. - */ - - int val = (enable) ? 1 : 0;// just to be explicit - static Atom state_msg = XInternAtom(disp, "_NET_WM_STATE", False); - return _client_msg(disp, win, state_msg, - val, state1, state2, SOURCE_INDICATION, 0); - } - - bool maximize_window(Display* disp, Window win, bool enable) { - static Atom max_vert = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_VERT", False), - max_horiz = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - return set_window_state(disp, win, max_vert, max_horiz, enable); - } + int _client_msg(Display* disp, Window win, Atom msg, + unsigned long data0, unsigned long data1, + unsigned long data2, unsigned long data3, + unsigned long data4) { + XEvent event; + long mask = SubstructureRedirectMask | SubstructureNotifyMask; + + event.xclient.type = ClientMessage; + event.xclient.serial = 0; + event.xclient.send_event = True; + event.xclient.message_type = msg; + event.xclient.window = win; + event.xclient.format = 32; + event.xclient.data.l[0] = data0; + event.xclient.data.l[1] = data1; + event.xclient.data.l[2] = data2; + event.xclient.data.l[3] = data3; + event.xclient.data.l[4] = data4; + + DEBUG("send message_type=%s, data=(%lu,%lu,%lu,%lu,%lu)", + XGetAtomName(disp, msg), data0, data1, data2, data3, data4); + + if (XSendEvent(disp, DefaultRootWindow(disp), False, mask, &event)) { + return true; + } else { + ERROR("Cannot send %s event.", msg); + return false; + } + } + + inline void print_window(Display* disp, Window win) { + if (!config::debug_enabled) { return; } + Window root; + int x, y; + unsigned int width, height, border, depth; + if (XGetGeometry(disp, win, &root, &x, &y, &width, + &height, &border, &depth) == 0) { + ERROR_DIR("get geometry failed"); + return; + } + DEBUG(" %dx %dy %uw %uh %ub", x, y, width, height, border); + } + + Window* get_active_window(Display* disp) { + static Atom actwin_msg = XInternAtom(disp, "_NET_ACTIVE_WINDOW", False); + Window* ret = (Window*)x11_util::get_property(disp, DefaultRootWindow(disp), + XA_WINDOW, actwin_msg, NULL); + if (ret == NULL) { + ERROR_DIR("unable to get active window"); + } + return ret; + } + + bool is_dock_window(Display* disp, Window win) { + /* disallow moving/selecting this window if it has type DESKTOP or DOCK. + (avoid messing with the user's desktop components, eg taskbars) */ + bool ret = false; + size_t count = 0; + static Atom wintype_msg = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False); + Atom* types = (Atom*)x11_util::get_property(disp, win, XA_ATOM, wintype_msg, &count); + if (types == NULL) { + ERROR_DIR("couldn't get window types"); + //assume window types are fine, keep going + } else { + static Atom desktop_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DESKTOP", False), + dock_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False); + for (size_t i = 0; i < count; ++i) { + DEBUG("%d type %lu: %d %s", + win, i, types[i], XGetAtomName(disp, types[i])); + if (types[i] == desktop_type || types[i] == dock_type) { + ret = true; + if (!config::debug_enabled) { + break; + } + } + } + x11_util::free_property(types); + } + return ret; + } + + bool is_menu_window(Display* disp, Window win) { + /* also disallow moving/selecting this window if it has SKIP_PAGER or SKIP_TASKBAR. + (avoid messing with auxiliary panels and menus) */ + bool ret = false; + size_t count = 0; + static Atom state_msg = XInternAtom(disp, "_NET_WM_STATE", False); + Atom* states = (Atom*)x11_util::get_property(disp, win, XA_ATOM, state_msg, &count); + if (states == NULL) { + ERROR_DIR("couldn't get window states"); + //assume window states are fine, keep going + } else { + static Atom skip_pager = XInternAtom(disp, "_NET_WM_STATE_SKIP_PAGER", False), + skip_taskbar = XInternAtom(disp, "_NET_WM_STATE_SKIP_TASKBAR", False); + for (size_t i = 0; i < count; ++i) { + DEBUG("%d state %lu: %d %s", + win, i, states[i], XGetAtomName(disp, states[i])); + if (states[i] == skip_pager || states[i] == skip_taskbar) { + ret = true; + if (!config::debug_enabled) { + break; + } + } + } + x11_util::free_property(states); + } + return ret; + } + + bool get_window_size(Display* disp, Window win, + Dimensions* out_exterior = NULL, + unsigned int* out_margin_width = NULL, + unsigned int* out_margin_height = NULL) { + Window root; + unsigned int internal_width, internal_height; + { + /* first, get the interior width/height from this window + (so that we can calculate margins) */ + int x, y; + unsigned int border, depth; + if (XGetGeometry(disp, win, &root, &x, &y, &internal_width, + &internal_height, &border, &depth) == 0) { + ERROR_DIR("get geometry failed"); + return false; + } + } + + if (win == root) { + ERROR_DIR("this window is root! treating this as an error."); + return false; + } + + /* now traverse up the parents until we reach the one JUST BEFORE root, + and get the external width/height and x/y from that. */ + Window just_before_root; + { + int count = 1; + Window parent = win; + Window* children; + unsigned int children_count; + do { + just_before_root = parent; + if (XQueryTree(disp, just_before_root, &root, + &parent, &children, &children_count) == 0) { + ERROR_DIR("get query tree failed"); + return false; + } + if (children != NULL) { + XFree(children); + } + DEBUG("%d window=%lu, parent=%lu, root=%lu", + count, just_before_root, parent, root); + print_window(disp, just_before_root); + } while (++count < 50 && parent != root); + } + + int x, y; + unsigned int external_width, external_height; + { + unsigned int border, depth; + if (XGetGeometry(disp, just_before_root, &root, &x, &y, &external_width, + &external_height, &border, &depth) == 0) { + ERROR_DIR("get geometry failed"); + return false; + } + } + + if (out_exterior != NULL) { + out_exterior->x = x; + out_exterior->y = y; + out_exterior->width = external_width; + out_exterior->height = external_height; + } + + if (out_margin_width != NULL) { + *out_margin_width = external_width - internal_width; + } + if (out_margin_height != NULL) { + *out_margin_height = external_height - internal_height; + } + + DEBUG("size: exterior %uw %uh - interior %uw %uh = margins %dw %dh", + external_width, external_height, + internal_width, internal_height, + external_width - internal_width, + external_height - internal_height); + return true; + } + + bool activate_window(Display* disp, Window curactive, Window newactive) { + static Atom active_msg = XInternAtom(disp, "_NET_ACTIVE_WINDOW", False); + if (!_client_msg(disp, newactive, active_msg, + SOURCE_INDICATION, CurrentTime, curactive, 0, 0)) { + ERROR_DIR("couldn't activate"); + return false; + } + return true; + } + + bool set_window_state(Display* disp, Window win, Atom state1, Atom state2, bool enable) { + /* + this disagrees with docs, which say that we should be using a + _NET_WM_STATE_DISABLE/_ENABLE atom in data[0]. That apparently doesn't + work in practice, but '0'/'1' do. + */ + + int val = (enable) ? 1 : 0;// just to be explicit + static Atom state_msg = XInternAtom(disp, "_NET_WM_STATE", False); + return _client_msg(disp, win, state_msg, + val, state1, state2, SOURCE_INDICATION, 0); + } + + bool maximize_window(Display* disp, Window win, bool enable) { + static Atom max_vert = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_VERT", False), + max_horiz = XInternAtom(disp, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + return set_window_state(disp, win, max_vert, max_horiz, enable); + } } bool window::select_activate(grid::POS dir) { - Display* disp = XOpenDisplay(NULL); - if (disp == NULL) { - ERROR_DIR("unable to get display"); - return false; - } - - std::vector wins; - - { - size_t win_count = 0; - static Atom clientlist_msg = XInternAtom(disp, "_NET_CLIENT_LIST", False); - Window* all_wins = (Window*)x11_util::get_property(disp, DefaultRootWindow(disp), - XA_WINDOW, clientlist_msg, &win_count); - if (all_wins == NULL || win_count == 0) { - ERROR_DIR("unable to get list of windows"); - if (all_wins != NULL) { - x11_util::free_property(all_wins); - } - XCloseDisplay(disp); - return false; - } - // only select normal windows, ignore docks and menus - for (size_t i = 0; i < win_count; ++i) { - if (!is_dock_window(disp, all_wins[i]) && !is_menu_window(disp, all_wins[i])) { - wins.push_back(all_wins[i]); - } - } - x11_util::free_property(all_wins); - } - - size_t active_window = 0; - dim_list_t all_windows; - { - Window* active = get_active_window(disp); - if (active == NULL) { - XCloseDisplay(disp); - return false; - } - for (size_t i = 0; i < wins.size(); ++i) { - if (wins[i] == *active) { - active_window = i; - DEBUG_DIR("ACTIVE:"); - } - all_windows.push_back(Dimensions()); - get_window_size(disp, wins[i], &all_windows.back(), NULL, NULL); - } - x11_util::free_property(active); - } - - size_t next_window; - neighbor::select(dir, all_windows, active_window, next_window); - - bool ok = activate_window(disp, wins[active_window], wins[next_window]); - - XCloseDisplay(disp); - return ok; + Display* disp = XOpenDisplay(NULL); + if (disp == NULL) { + ERROR_DIR("unable to get display"); + return false; + } + + std::vector wins; + + { + size_t win_count = 0; + static Atom clientlist_msg = XInternAtom(disp, "_NET_CLIENT_LIST", False); + Window* all_wins = (Window*)x11_util::get_property(disp, DefaultRootWindow(disp), + XA_WINDOW, clientlist_msg, &win_count); + if (all_wins == NULL || win_count == 0) { + ERROR_DIR("unable to get list of windows"); + if (all_wins != NULL) { + x11_util::free_property(all_wins); + } + XCloseDisplay(disp); + return false; + } + // only select normal windows, ignore docks and menus + for (size_t i = 0; i < win_count; ++i) { + if (!is_dock_window(disp, all_wins[i]) && !is_menu_window(disp, all_wins[i])) { + wins.push_back(all_wins[i]); + } + } + x11_util::free_property(all_wins); + } + + size_t active_window = 0; + dim_list_t all_windows; + { + Window* active = get_active_window(disp); + if (active == NULL) { + XCloseDisplay(disp); + return false; + } + for (size_t i = 0; i < wins.size(); ++i) { + if (wins[i] == *active) { + active_window = i; + DEBUG_DIR("ACTIVE:"); + } + all_windows.push_back(Dimensions()); + get_window_size(disp, wins[i], &all_windows.back(), NULL, NULL); + } + x11_util::free_property(active); + } + + size_t next_window; + neighbor::select(dir, all_windows, active_window, next_window); + + bool ok = activate_window(disp, wins[active_window], wins[next_window]); + + XCloseDisplay(disp); + return ok; } ActiveWindow::~ActiveWindow() { - if (disp != NULL) { - XCloseDisplay(disp); - } - if (win != NULL) { - x11_util::free_property(win); - } + if (disp != NULL) { + XCloseDisplay(disp); + } + if (win != NULL) { + x11_util::free_property(win); + } } bool ActiveWindow::init() { - if (disp == NULL) { - disp = XOpenDisplay(NULL); - if (disp == NULL) { - ERROR_DIR("unable to get display"); - return false; - } - } - - if (win == NULL) { - win = get_active_window(disp); - if (win == NULL) { - return false; - } - } - return true; + if (disp == NULL) { + disp = XOpenDisplay(NULL); + if (disp == NULL) { + ERROR_DIR("unable to get display"); + return false; + } + } + + if (win == NULL) { + win = get_active_window(disp); + if (win == NULL) { + return false; + } + } + return true; } bool ActiveWindow::Size(Dimensions& activewin) { - if (!init()) { - return false; - } + if (!init()) { + return false; + } - if (is_dock_window(disp, *win) || is_menu_window(disp, *win)) { - LOG_DIR("Active window is a desktop or dock. Ignoring move request."); - return false; - } + if (is_dock_window(disp, *win) || is_menu_window(disp, *win)) { + LOG_DIR("Active window is a desktop or dock. Ignoring move request."); + return false; + } - if (!get_window_size(disp, *win, &activewin, NULL, NULL)) { - ERROR_DIR("couldn't get window size"); - return false; - } + if (!get_window_size(disp, *win, &activewin, NULL, NULL)) { + ERROR_DIR("couldn't get window size"); + return false; + } - DEBUG("activewin %dx %dy %luw %luh", - activewin.x, activewin.y, activewin.width, activewin.height); + DEBUG("activewin %dx %dy %luw %luh", + activewin.x, activewin.y, activewin.width, activewin.height); - return true; + return true; } bool ActiveWindow::MoveResize(const Dimensions& activewin) { - if (!init()) { - return false; - } - - unsigned int margin_width, margin_height; - if (!get_window_size(disp, *win, NULL, &margin_width, &margin_height)) { - return false; - } - - //demaximize the window before attempting to move it - if (!maximize_window(disp, *win, false)) { - ERROR_DIR("couldn't demaximize"); - //disregard failure - } - - unsigned long new_interior_width = activewin.width - margin_width, - new_interior_height = activewin.height - margin_height; - - //moveresize uses exterior for position, but interior for width/height - DEBUG("%ldx %ldy %luw %luh - margins %dw %dh = %ldx %ldy %luw %luh", - activewin.x, activewin.y, activewin.width, activewin.height, - margin_width, margin_height, - activewin.x, activewin.y, new_interior_width, new_interior_height); - - if (XMoveResizeWindow(disp, *win, activewin.x, activewin.y, - new_interior_width, new_interior_height) == 0) { - ERROR("MoveResize to %ldx %ldy %luw %luh failed.", - activewin.x, activewin.y, new_interior_width, new_interior_height); - return false; - } - return true; + if (!init()) { + return false; + } + + unsigned int margin_width, margin_height; + if (!get_window_size(disp, *win, NULL, &margin_width, &margin_height)) { + return false; + } + + //demaximize the window before attempting to move it + if (!maximize_window(disp, *win, false)) { + ERROR_DIR("couldn't demaximize"); + //disregard failure + } + + unsigned long new_interior_width = activewin.width - margin_width, + new_interior_height = activewin.height - margin_height; + + //moveresize uses exterior for position, but interior for width/height + DEBUG("%ldx %ldy %luw %luh - margins %dw %dh = %ldx %ldy %luw %luh", + activewin.x, activewin.y, activewin.width, activewin.height, + margin_width, margin_height, + activewin.x, activewin.y, new_interior_width, new_interior_height); + + if (XMoveResizeWindow(disp, *win, activewin.x, activewin.y, + new_interior_width, new_interior_height) == 0) { + ERROR("MoveResize to %ldx %ldy %luw %luh failed.", + activewin.x, activewin.y, new_interior_width, new_interior_height); + return false; + } + return true; } bool ActiveWindow::Maximize() { - if (!init()) { - return false; - } - - if (!maximize_window(disp, *win, true)) { - ERROR_DIR("couldn't maximize"); - return false; - } - return true; + if (!init()) { + return false; + } + + if (!maximize_window(disp, *win, true)) { + ERROR_DIR("couldn't maximize"); + return false; + } + return true; } bool ActiveWindow::DeFullscreen() { - if (!init()) { - return false; - } - - static Atom fs = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False); - if (!set_window_state(disp, *win, fs, 0, false)) { - ERROR_DIR("couldn't defullscreen"); - return false; - } - return true; + if (!init()) { + return false; + } + + static Atom fs = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False); + if (!set_window_state(disp, *win, fs, 0, false)) { + ERROR_DIR("couldn't defullscreen"); + return false; + } + return true; } bool ActiveWindow::DeShade() { - if (!init()) { - return false; - } - - static Atom shade = XInternAtom(disp, "_NET_WM_STATE_SHADED", False); - if (!set_window_state(disp, *win, shade, 0, false)) { - ERROR_DIR("couldn't deshade"); - return false; - } - return true; + if (!init()) { + return false; + } + + static Atom shade = XInternAtom(disp, "_NET_WM_STATE_SHADED", False); + if (!set_window_state(disp, *win, shade, 0, false)) { + ERROR_DIR("couldn't deshade"); + return false; + } + return true; } diff --git a/src/window.h b/src/window.h index d73b6cc..40ebdcd 100644 --- a/src/window.h +++ b/src/window.h @@ -25,28 +25,28 @@ #include "dimensions.h" namespace window { - /* Finds the nearest window in the given direction and activates it. */ - bool select_activate(grid::POS dir); + /* Finds the nearest window in the given direction and activates it. */ + bool select_activate(grid::POS dir); } class ActiveWindow { public: - ActiveWindow() : disp(NULL), win(NULL) { } - virtual ~ActiveWindow(); + ActiveWindow() : disp(NULL), win(NULL) { } + virtual ~ActiveWindow(); - bool Size(Dimensions& activewin); + bool Size(Dimensions& activewin); - bool MoveResize(const Dimensions& activewin); + bool MoveResize(const Dimensions& activewin); - bool Maximize(); - bool DeFullscreen(); - bool DeShade(); + bool Maximize(); + bool DeFullscreen(); + bool DeShade(); private: - bool init(); + bool init(); - Display* disp; - Window* win; + Display* disp; + Window* win; }; #endif diff --git a/src/x11-util.cpp b/src/x11-util.cpp index 980f4b6..234b23f 100644 --- a/src/x11-util.cpp +++ b/src/x11-util.cpp @@ -22,51 +22,51 @@ #define MAX_PROPERTY_VALUE_LEN 4096 unsigned char* x11_util::get_property(Display *disp, Window win, - Atom xa_prop_type, Atom xa_prop_name, size_t* out_count) { - Atom xa_ret_type; - int ret_format; - unsigned long ret_nitems, ret_bytes_after; - unsigned char* ret_prop; + Atom xa_prop_type, Atom xa_prop_name, size_t* out_count) { + Atom xa_ret_type; + int ret_format; + unsigned long ret_nitems, ret_bytes_after; + unsigned char* ret_prop; - /* MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage): - * - * long_length = Specifies the length in 32-bit multiples of the - * data to be retrieved. - */ - if (XGetWindowProperty(disp, win, xa_prop_name, 0, MAX_PROPERTY_VALUE_LEN / 4, false, - xa_prop_type, &xa_ret_type, &ret_format, - &ret_nitems, &ret_bytes_after, &ret_prop) != Success) { - ERROR("Cannot get property %d/%s.", xa_prop_name, XGetAtomName(disp, xa_prop_name)); - return NULL; - } else { - DEBUG("Property %d/%s -> %lu items", xa_prop_name, XGetAtomName(disp, xa_prop_name), ret_nitems); - } + /* MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage): + * + * long_length = Specifies the length in 32-bit multiples of the + * data to be retrieved. + */ + if (XGetWindowProperty(disp, win, xa_prop_name, 0, MAX_PROPERTY_VALUE_LEN / 4, false, + xa_prop_type, &xa_ret_type, &ret_format, + &ret_nitems, &ret_bytes_after, &ret_prop) != Success) { + ERROR("Cannot get property %d/%s.", xa_prop_name, XGetAtomName(disp, xa_prop_name)); + return NULL; + } else { + DEBUG("Property %d/%s -> %lu items", xa_prop_name, XGetAtomName(disp, xa_prop_name), ret_nitems); + } - if (xa_ret_type != xa_prop_type) { - if (xa_ret_type == None) { - // avoid crash on XGetAtomName(None) - char *req = XGetAtomName(disp, xa_prop_type); - //not necessarily an error, can happen if the window in question just lacks the requested property - //DEBUG("Unsupported or invalid request %s: requested type %s, got ", prop_name, req); - XFree(req); - } else { - char *req = XGetAtomName(disp, xa_prop_type), - *got = XGetAtomName(disp, xa_ret_type); - ERROR("Invalid type of property %d/%s: req %s, got %s", - xa_prop_name, XGetAtomName(disp, xa_prop_name), req, got); - XFree(req); - XFree(got); - } - XFree(ret_prop); - return NULL; - } + if (xa_ret_type != xa_prop_type) { + if (xa_ret_type == None) { + // avoid crash on XGetAtomName(None) + char *req = XGetAtomName(disp, xa_prop_type); + //not necessarily an error, can happen if the window in question just lacks the requested property + //DEBUG("Unsupported or invalid request %s: requested type %s, got ", prop_name, req); + XFree(req); + } else { + char *req = XGetAtomName(disp, xa_prop_type), + *got = XGetAtomName(disp, xa_ret_type); + ERROR("Invalid type of property %d/%s: req %s, got %s", + xa_prop_name, XGetAtomName(disp, xa_prop_name), req, got); + XFree(req); + XFree(got); + } + XFree(ret_prop); + return NULL; + } - if (out_count != NULL) { - *out_count = ret_nitems; - } - return ret_prop; + if (out_count != NULL) { + *out_count = ret_nitems; + } + return ret_prop; } void x11_util::free_property(void* prop) { - XFree(prop); + XFree(prop); } diff --git a/src/x11-util.h b/src/x11-util.h index b49a19a..f6dbe1e 100644 --- a/src/x11-util.h +++ b/src/x11-util.h @@ -24,9 +24,9 @@ #include namespace x11_util { - unsigned char* get_property(Display *disp, Window win, - Atom xa_prop_type, Atom xa_prop_name, size_t* out_count); - void free_property(void* prop); + unsigned char* get_property(Display *disp, Window win, + Atom xa_prop_type, Atom xa_prop_name, size_t* out_count); + void free_property(void* prop); } #endif -- 2.45.2