From 1260891d2199a486e5e8902182abc07f54445d49 Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 3 Jul 2022 16:19:30 +0300 Subject: [PATCH 01/23] add base for better multimonitor support --- Makefile | 2 +- src/display.c | 47 +++++++++++++++++++++++++++++++++++++++++------ src/display.h | 10 ++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 728f74d..2fc7b9a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ PROGRAM = xob MANPAGE = doc/xob.1 SYSCONF = styles.cfg -LIBS = x11 libconfig +LIBS = x11 libconfig xrandr SOURCES = src/conf.c src/display.c src/main.c # Feature: alpha channel (transparency) diff --git a/src/display.c b/src/display.c index c20eedf..6355f87 100644 --- a/src/display.c +++ b/src/display.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -115,18 +116,18 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, *available_length - 2 * *fat_layer); /* Compute position of the top-left corner */ - *topleft_x = fit_in(WidthOfScreen(dc->x.screen) * conf.x.rel - + *topleft_x = fit_in(dc->x.monitor_info.width * conf.x.rel - (size_x(dc->geometry) + 2 * *fat_layer) / 2, 0, - WidthOfScreen(dc->x.screen) - + dc->x.monitor_info.width - (size_x(dc->geometry) + 2 * *fat_layer)) + - conf.x.abs; - *topleft_y = fit_in(HeightOfScreen(dc->x.screen) * conf.y.rel - + conf.x.abs + dc->x.monitor_info.x; + *topleft_y = fit_in(dc->x.monitor_info.height * conf.y.rel - (size_y(dc->geometry) + 2 * *fat_layer) / 2, 0, - HeightOfScreen(dc->x.screen) - + dc->x.monitor_info.width - (size_y(dc->geometry) + 2 * *fat_layer)) + - conf.y.abs; + conf.y.abs + dc->x.monitor_info.y; } /* PUBLIC Returns a new display context from a given configuration. If the @@ -159,6 +160,40 @@ Display_context init(Style conf) window_attributes.border_pixel = 0; window_attributes.override_redirect = True; + /* Get monitors info */ + char *hard_monitor = "eDP-1"; + int num_monitors; + char *monitor_name; + XRRMonitorInfo *monitor_sizes = XRRGetMonitors( + dc.x.display, root, 0, &num_monitors); + int i; + for (i = 0; i < num_monitors; i++) + { + monitor_name = XGetAtomName(dc.x.display, monitor_sizes[i].name); + if (strcmp(hard_monitor, monitor_name) == 0) + break; + } + if (i == num_monitors) + { + /* Fallback monitor if no monitor with provided name found*/ + fprintf(stderr, "Monitor %s is not found. Use FULL mode\n", + monitor_name); + dc.x.monitor_info.x = 0; + dc.x.monitor_info.y = 0; + dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); + dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); + strcpy(dc.x.monitor_info.name, "FULL"); + } + else + { + dc.x.monitor_info.x = monitor_sizes[i].x; + dc.x.monitor_info.y = monitor_sizes[i].y; + dc.x.monitor_info.width = monitor_sizes[i].width; + dc.x.monitor_info.height = monitor_sizes[i].height; + strcpy(dc.x.monitor_info.name, monitor_name); + } + XRRFreeMonitors(monitor_sizes); + compute_geometry(conf, &dc, &topleft_x, &topleft_y, &fat_layer, &available_length); diff --git a/src/display.h b/src/display.h index 0077c05..6cca433 100644 --- a/src/display.h +++ b/src/display.h @@ -27,6 +27,15 @@ typedef enum ALTERNATIVE } Show_mode; +typedef struct +{ + char name[10]; + int x; + int y; + int width; + int height; +} MonitorInfo; + typedef struct { Display *display; @@ -34,6 +43,7 @@ typedef struct Screen *screen; Window window; Bool mapped; + MonitorInfo monitor_info; } X_context; typedef struct From 712bf6e8d991f60aebcbca42cc2642c2da6ab853 Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 3 Jul 2022 19:50:36 +0300 Subject: [PATCH 02/23] add monitor option to conf --- src/conf.c | 18 +++++++++++++++ src/conf.h | 5 +++++ src/display.c | 62 ++++++++++++++++++++++++++++++--------------------- styles.cfg | 1 + 4 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/conf.c b/src/conf.c index 25559a7..2657e0c 100644 --- a/src/conf.c +++ b/src/conf.c @@ -229,6 +229,22 @@ static int config_setting_lookup_orientation(const config_setting_t *setting, return success_status; } +static int config_setting_lookup_monitor(const config_setting_t *setting, + const char *name, char *monitorvalue) +{ + const char *stringvalue; + + if (config_setting_lookup_string(setting, name, &stringvalue)) + { + strncpy(monitorvalue, stringvalue, LNAME_MONITOR); + } + else + { + fprintf(stderr, "Error: No style %s.\n", name); + } + return CONFIG_TRUE; +} + Style parse_style_config(FILE *file, const char *stylename, Style default_style) { config_t config; @@ -243,6 +259,8 @@ Style parse_style_config(FILE *file, const char *stylename, Style default_style) xob_config = config_lookup(&config, stylename); if (xob_config != NULL) { + config_setting_lookup_monitor(xob_config, "monitor", + style.monitor); config_setting_lookup_int(xob_config, "thickness", &style.thickness); config_setting_lookup_int(xob_config, "border", &style.border); diff --git a/src/conf.h b/src/conf.h index fac68e6..240af0c 100644 --- a/src/conf.h +++ b/src/conf.h @@ -20,6 +20,9 @@ #include +#define MONITOR_AUTO "auto" +#define LNAME_MONITOR 12 + typedef struct { unsigned char red; @@ -63,6 +66,7 @@ typedef enum typedef struct { + char monitor[LNAME_MONITOR]; Dim x; Dim y; Dim length; @@ -77,6 +81,7 @@ typedef struct /* clang-format off */ #define DEFAULT_CONFIGURATION (Style) {\ + .monitor = MONITOR_AUTO,\ .x =\ {\ .rel = 1.0,\ diff --git a/src/display.c b/src/display.c index 6355f87..40b475a 100644 --- a/src/display.c +++ b/src/display.c @@ -160,39 +160,51 @@ Display_context init(Style conf) window_attributes.border_pixel = 0; window_attributes.override_redirect = True; - /* Get monitors info */ - char *hard_monitor = "eDP-1"; - int num_monitors; - char *monitor_name; - XRRMonitorInfo *monitor_sizes = XRRGetMonitors( - dc.x.display, root, 0, &num_monitors); - int i; - for (i = 0; i < num_monitors; i++) + if (strcmp(conf.monitor, MONITOR_AUTO) != 0) { - monitor_name = XGetAtomName(dc.x.display, monitor_sizes[i].name); - if (strcmp(hard_monitor, monitor_name) == 0) - break; + /* Get monitors info */ + int num_monitors; + char *monitor_name; + XRRMonitorInfo *monitor_sizes = XRRGetMonitors( + dc.x.display, root, 0, &num_monitors); + int i; + for (i = 0; i < num_monitors; i++) + { + monitor_name = XGetAtomName(dc.x.display, + monitor_sizes[i].name); + if (strcmp(conf.monitor, monitor_name) == 0) + break; + } + if (i == num_monitors) // Monitor name is not found + { + /* Use auto for monitor option if no monitor with + * provided name found*/ + fprintf(stderr, "Monitor %s is not found. Use FULL mode\n", + monitor_name); + dc.x.monitor_info.x = 0; + dc.x.monitor_info.y = 0; + dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); + dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); + strcpy(dc.x.monitor_info.name, MONITOR_AUTO); + } + else + { + dc.x.monitor_info.x = monitor_sizes[i].x; + dc.x.monitor_info.y = monitor_sizes[i].y; + dc.x.monitor_info.width = monitor_sizes[i].width; + dc.x.monitor_info.height = monitor_sizes[i].height; + strcpy(dc.x.monitor_info.name, monitor_name); + } + XRRFreeMonitors(monitor_sizes); } - if (i == num_monitors) + else { - /* Fallback monitor if no monitor with provided name found*/ - fprintf(stderr, "Monitor %s is not found. Use FULL mode\n", - monitor_name); dc.x.monitor_info.x = 0; dc.x.monitor_info.y = 0; dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); - strcpy(dc.x.monitor_info.name, "FULL"); - } - else - { - dc.x.monitor_info.x = monitor_sizes[i].x; - dc.x.monitor_info.y = monitor_sizes[i].y; - dc.x.monitor_info.width = monitor_sizes[i].width; - dc.x.monitor_info.height = monitor_sizes[i].height; - strcpy(dc.x.monitor_info.name, monitor_name); + strcpy(dc.x.monitor_info.name, MONITOR_AUTO); } - XRRFreeMonitors(monitor_sizes); compute_geometry(conf, &dc, &topleft_x, &topleft_y, &fat_layer, &available_length); diff --git a/styles.cfg b/styles.cfg index 5e5c5ca..bda9283 100644 --- a/styles.cfg +++ b/styles.cfg @@ -1,4 +1,5 @@ default = { + monitor = "auto"; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; From 5e4ee3787414151b292c0a8855e00ebb7870217b Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 3 Jul 2022 20:19:20 +0300 Subject: [PATCH 03/23] update doc --- README.md | 3 ++- doc/xob.1 | 27 ++++++++++++++++----------- doc/xob.md | 6 +++++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e70349e..c9d3ab1 100644 --- a/README.md +++ b/README.md @@ -315,9 +315,10 @@ There is no support for panel integration. You can however use absolute position > "How about multiple monitors?" -xob works well under multihead setups. The `x`, `y`, and `length` style options refer to the combined screen surface. By default the bar is vertical near the right edge of the rightmost monitor. In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. +xob works well under multihead setups. The `monitor`, `x`, `y`, and `length` style options refer to the combined screen surface. By default the bar is vertical near the right edge of the rightmost monitor. In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. By default options `x` and `y` use combined metrics for all your monitors, but you can specify a monitor to the bar, for example you can set option `monitor = "HDMI-1"` to show the bar only on `HDMI-1` (use `xrandr` command to get monitors names). horizontal = { + monitor = "auto"; x = {relative = 0.5; offset = 0;}; y = {relative = 1; offset = -48;}; orientation = "horizontal"; diff --git a/doc/xob.1 b/doc/xob.1 index 40a3c84..845f54c 100644 --- a/doc/xob.1 +++ b/doc/xob.1 @@ -169,6 +169,10 @@ In the following, a dot \[lq].\[rq] means \[lq]suboption\[rq]. For instance \[lq]color.normal.fg\[rq] means \[lq]The suboption fg of the suboption normal of option color\[rq]. .TP +\f[B]monitor\f[R] \f[I]\[lq]output_name\[rq]\f[R] (default: auto) +Output monitor for the bar, use \f[I]xrandr\f[R] command to get monitors names. +The option is case-sensitive. +.TP \f[B]orientation\f[R] \f[I]\[lq]horizontal\[rq] | \[lq]vertical\[rq]\f[R] (default: vertical) Orientation of the bar which either fills up from left to right (\[lq]horizontal\[rq]) or bottom to top (\[lq]vertical\[rq]). @@ -301,6 +305,7 @@ backlight = { .nf \f[C] default = { + monitor = \[dq]auto\[dq]; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; @@ -367,17 +372,17 @@ situations. \[lq]How to set up xob with multiple monitors?\[rq] .RE .PP -xob works well under multihead setups but there is no easy way to -configure the position of the bar for now. -For example, in a dual monitor setup with the default configuration, the -horizontal centering is not local to one of the two monitors. -It is global. -The bar might be split in two: one part on each screen. -Stick to a corner or use absolute positioning. -If you want an xob instance to be centered (horizontally) on the -far-right monitor, set \f[I]x.relative\f[R] to 1.0 (anchored on the far -right) and the \f[I]x.offset\f[R] to minus half the width of that -screen. +xob works well under multihead setups, use option \f[I]monitor\f[R] to +specify one. By default xob use \f[I]auto\f[R] for the option. It means +that in a dual monitor setup with the default configuration, +the horizontal centering is not local to one of the two monitors. +It is global. The bar might be split in two: one part on each screen. +If you want an xob instance to be centered (horizontally) on the specific +monitor, set \f[I]monitor\f[R] option to your monitor output, +for example \f[I]monitor = \[lq]HDMI-1\[rq]\f[R] and set options +\f[I]x.relative\f[R] and \f[I]y.relative\f[R] relative to the monitor. +To get monitors output name you can use \f[I]xrandr --listmonitors\f[R] +command in your terminal. .SH CONTRIBUTIONS .PP Feedback and contributions are welcome. diff --git a/doc/xob.md b/doc/xob.md index b6c2f35..496df90 100644 --- a/doc/xob.md +++ b/doc/xob.md @@ -104,6 +104,9 @@ Options can be grouped together inside curly brackets. Some options expect a gro In the following, a dot "." means "suboption". For instance "color.normal.fg" means "The suboption fg of the suboption normal of option color". +**monitor** "output_name" (default: auto) +: Output monitor for the bar, use `xrandr` command to get monitors names. The option is case-sensitive. + **orientation** *"horizontal" | "vertical"* (default: vertical) : Orientation of the bar which either fills up from left to right ("horizontal") or bottom to top ("vertical"). @@ -194,6 +197,7 @@ This example configuration file provides two styles "volume" and "backlight". In ## DEFAULT CONFIGURATION FILE default = { + monitor = "auto"; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; @@ -242,7 +246,7 @@ There is no support for panel integration. You can however use absolute position > "How to set up xob with multiple monitors?" -xob works well under multihead setups but there is no easy way to configure the position of the bar for now. For example, in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. Stick to a corner or use absolute positioning. If you want an xob instance to be centered (horizontally) on the far-right monitor, set *x.relative* to 1.0 (anchored on the far right) and the *x.offset* to minus half the width of that screen. +xob works well under multihead setups, use option `monitor` to specify one. By default xob use `auto` for the option. It means that in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. If you want an xob instance to be centered (horizontally) on the specific monitor, set `monitor` option to your monitor output, for example `monitor = "HDMI-1"` and set options `x.relative` and `y.relative` relative to the monitor. To get monitors output name you can use `xrandr --listmonitors` command int your terminal. # CONTRIBUTIONS From 5f041d09ffa88ea941eb6c41e3e3285bcec7f95c Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 3 Jul 2022 20:33:23 +0300 Subject: [PATCH 04/23] fix relative length of bars for monitors with different resolution --- src/display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/display.c b/src/display.c index 40b475a..37c5b90 100644 --- a/src/display.c +++ b/src/display.c @@ -108,8 +108,8 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, /* Orientation-related dimensions */ *available_length = dc->geometry.orientation == HORIZONTAL - ? WidthOfScreen(dc->x.screen) - : HeightOfScreen(dc->x.screen); + ? dc->x.monitor_info.width + : dc->x.monitor_info.height; dc->geometry.length = fit_in(*available_length * conf.length.rel + conf.length.abs, 0, @@ -177,7 +177,7 @@ Display_context init(Style conf) } if (i == num_monitors) // Monitor name is not found { - /* Use auto for monitor option if no monitor with + /* Use auto for monitor option if no monitors with * provided name found*/ fprintf(stderr, "Monitor %s is not found. Use FULL mode\n", monitor_name); From 4681e57f49754d445a273c8d614bcaa664272116 Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 3 Jul 2022 20:40:46 +0300 Subject: [PATCH 05/23] fix README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c9d3ab1..ddfc899 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ When starting, xob looks for the configuration file in the following order: Consult the man page for detailed information about the configuration file and the available options. The following `styles.cfg` defines a single style called "default" that showcases all the possible options set to the default values. The configuration file may contain additional styles to choose among using the **-s** argument. default = { + monitor = "auto"; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; @@ -315,7 +316,7 @@ There is no support for panel integration. You can however use absolute position > "How about multiple monitors?" -xob works well under multihead setups. The `monitor`, `x`, `y`, and `length` style options refer to the combined screen surface. By default the bar is vertical near the right edge of the rightmost monitor. In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. By default options `x` and `y` use combined metrics for all your monitors, but you can specify a monitor to the bar, for example you can set option `monitor = "HDMI-1"` to show the bar only on `HDMI-1` (use `xrandr` command to get monitors names). +xob works well under multihead setups. The `monitor`, `x`, `y`, and `length` style options refer to the combined screen surface. By default the bar is vertical near the right edge of the rightmost monitor. In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. By default options `x` and `y` refer to the combined screen surface, but you can specify a monitor for the bar, for example you can set option `monitor = "HDMI-1"` to show the bar only on `HDMI-1` (use `xrandr` command to get monitors names). horizontal = { monitor = "auto"; From ad4f058546cba90fa3ad20a7f73d4b6fe1ea7e09 Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 3 Jul 2022 20:42:43 +0300 Subject: [PATCH 06/23] fix doc --- doc/xob.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/xob.md b/doc/xob.md index 496df90..c1e3758 100644 --- a/doc/xob.md +++ b/doc/xob.md @@ -246,7 +246,7 @@ There is no support for panel integration. You can however use absolute position > "How to set up xob with multiple monitors?" -xob works well under multihead setups, use option `monitor` to specify one. By default xob use `auto` for the option. It means that in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. If you want an xob instance to be centered (horizontally) on the specific monitor, set `monitor` option to your monitor output, for example `monitor = "HDMI-1"` and set options `x.relative` and `y.relative` relative to the monitor. To get monitors output name you can use `xrandr --listmonitors` command int your terminal. +xob works well under multihead setups, use option `monitor` to specify one. By default xob use `auto` for the option. It means that in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. If you want an xob instance to be centered (horizontally) on the specific monitor, set `monitor` option to your monitor output, for example `monitor = "HDMI-1"` and set options `x.relative` and `y.relative` relative to the monitor. To get monitors output name you can use `xrandr --listmonitors` command in your terminal. # CONTRIBUTIONS From 0601e3274ee6abec038ad22f21bafbb180a41f2b Mon Sep 17 00:00:00 2001 From: ILLIA Date: Mon, 4 Jul 2022 20:47:00 +0000 Subject: [PATCH 07/23] Update README.md Co-authored-by: Muhammed Zakir <8190126+MuhammedZakir@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddfc899..0d4bff1 100644 --- a/README.md +++ b/README.md @@ -316,7 +316,7 @@ There is no support for panel integration. You can however use absolute position > "How about multiple monitors?" -xob works well under multihead setups. The `monitor`, `x`, `y`, and `length` style options refer to the combined screen surface. By default the bar is vertical near the right edge of the rightmost monitor. In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. By default options `x` and `y` refer to the combined screen surface, but you can specify a monitor for the bar, for example you can set option `monitor = "HDMI-1"` to show the bar only on `HDMI-1` (use `xrandr` command to get monitors names). +xob works well under multihead setups. The default orientation of bar is `vertical` and is positioned at the right edge of the screen surface. By default, `x`, `y`, and `length` style options refer to the combined screen surface, but you can specify a monitor for the bar, for example you can set option `monitor = "HDMI-1"` to show the bar only on `HDMI-1` (use `xrandr` command to get monitors names). In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. horizontal = { monitor = "auto"; From 0e33dd7763547ade5fa7cacf2eeba87a35e4ec81 Mon Sep 17 00:00:00 2001 From: Megtev Date: Tue, 5 Jul 2022 01:49:37 +0300 Subject: [PATCH 08/23] rename auto mode to combined; small cosmetics fixes --- README.md | 4 ++-- doc/xob.1 | 6 +++--- doc/xob.md | 6 +++--- src/conf.h | 4 ++-- src/display.c | 13 +++++++------ styles.cfg | 2 +- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0d4bff1..8504b6e 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ When starting, xob looks for the configuration file in the following order: Consult the man page for detailed information about the configuration file and the available options. The following `styles.cfg` defines a single style called "default" that showcases all the possible options set to the default values. The configuration file may contain additional styles to choose among using the **-s** argument. default = { - monitor = "auto"; + monitor = "combined"; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; @@ -319,7 +319,7 @@ There is no support for panel integration. You can however use absolute position xob works well under multihead setups. The default orientation of bar is `vertical` and is positioned at the right edge of the screen surface. By default, `x`, `y`, and `length` style options refer to the combined screen surface, but you can specify a monitor for the bar, for example you can set option `monitor = "HDMI-1"` to show the bar only on `HDMI-1` (use `xrandr` command to get monitors names). In vertical layouts, you may prefer to switch the bar to horizontal mode as follows to avoid splits. horizontal = { - monitor = "auto"; + monitor = "combined"; x = {relative = 0.5; offset = 0;}; y = {relative = 1; offset = -48;}; orientation = "horizontal"; diff --git a/doc/xob.1 b/doc/xob.1 index 845f54c..7ec1764 100644 --- a/doc/xob.1 +++ b/doc/xob.1 @@ -169,7 +169,7 @@ In the following, a dot \[lq].\[rq] means \[lq]suboption\[rq]. For instance \[lq]color.normal.fg\[rq] means \[lq]The suboption fg of the suboption normal of option color\[rq]. .TP -\f[B]monitor\f[R] \f[I]\[lq]output_name\[rq]\f[R] (default: auto) +\f[B]monitor\f[R] \f[I]\[lq]output_name\[rq]\f[R] (default: combined) Output monitor for the bar, use \f[I]xrandr\f[R] command to get monitors names. The option is case-sensitive. .TP @@ -305,7 +305,7 @@ backlight = { .nf \f[C] default = { - monitor = \[dq]auto\[dq]; + monitor = \[dq]combined\[dq]; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; @@ -373,7 +373,7 @@ situations. .RE .PP xob works well under multihead setups, use option \f[I]monitor\f[R] to -specify one. By default xob use \f[I]auto\f[R] for the option. It means +specify one. By default xob use \f[I]combined\f[R] for the option. It means that in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. diff --git a/doc/xob.md b/doc/xob.md index c1e3758..18f91c7 100644 --- a/doc/xob.md +++ b/doc/xob.md @@ -104,7 +104,7 @@ Options can be grouped together inside curly brackets. Some options expect a gro In the following, a dot "." means "suboption". For instance "color.normal.fg" means "The suboption fg of the suboption normal of option color". -**monitor** "output_name" (default: auto) +**monitor** "output_name" (default: combined) : Output monitor for the bar, use `xrandr` command to get monitors names. The option is case-sensitive. **orientation** *"horizontal" | "vertical"* (default: vertical) @@ -197,7 +197,7 @@ This example configuration file provides two styles "volume" and "backlight". In ## DEFAULT CONFIGURATION FILE default = { - monitor = "auto"; + monitor = "combined"; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; @@ -246,7 +246,7 @@ There is no support for panel integration. You can however use absolute position > "How to set up xob with multiple monitors?" -xob works well under multihead setups, use option `monitor` to specify one. By default xob use `auto` for the option. It means that in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. If you want an xob instance to be centered (horizontally) on the specific monitor, set `monitor` option to your monitor output, for example `monitor = "HDMI-1"` and set options `x.relative` and `y.relative` relative to the monitor. To get monitors output name you can use `xrandr --listmonitors` command in your terminal. +xob works well under multihead setups, use option `monitor` to specify one. By default xob use `combined` for the option. It means that in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors. It is global. The bar might be split in two: one part on each screen. If you want an xob instance to be centered (horizontally) on the specific monitor, set `monitor` option to your monitor output, for example `monitor = "HDMI-1"` and set options `x.relative` and `y.relative` relative to the monitor. To get monitors output name you can use `xrandr --listmonitors` command in your terminal. # CONTRIBUTIONS diff --git a/src/conf.h b/src/conf.h index 240af0c..70fe72d 100644 --- a/src/conf.h +++ b/src/conf.h @@ -20,7 +20,7 @@ #include -#define MONITOR_AUTO "auto" +#define MONITOR_COMBINED "combined" #define LNAME_MONITOR 12 typedef struct @@ -81,7 +81,7 @@ typedef struct /* clang-format off */ #define DEFAULT_CONFIGURATION (Style) {\ - .monitor = MONITOR_AUTO,\ + .monitor = MONITOR_COMBINED,\ .x =\ {\ .rel = 1.0,\ diff --git a/src/display.c b/src/display.c index 37c5b90..e0da221 100644 --- a/src/display.c +++ b/src/display.c @@ -160,7 +160,7 @@ Display_context init(Style conf) window_attributes.border_pixel = 0; window_attributes.override_redirect = True; - if (strcmp(conf.monitor, MONITOR_AUTO) != 0) + if (strcmp(conf.monitor, MONITOR_COMBINED) != 0) { /* Get monitors info */ int num_monitors; @@ -177,15 +177,16 @@ Display_context init(Style conf) } if (i == num_monitors) // Monitor name is not found { - /* Use auto for monitor option if no monitors with + /* Use combined for monitor option if no monitors with * provided name found*/ - fprintf(stderr, "Monitor %s is not found. Use FULL mode\n", - monitor_name); + fprintf(stderr, "Error: monitor %s is not found.\n", + conf.monitor); + fprintf(stderr, "Info: falling back to combined mode.\n"); dc.x.monitor_info.x = 0; dc.x.monitor_info.y = 0; dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); - strcpy(dc.x.monitor_info.name, MONITOR_AUTO); + strcpy(dc.x.monitor_info.name, MONITOR_COMBINED); } else { @@ -203,7 +204,7 @@ Display_context init(Style conf) dc.x.monitor_info.y = 0; dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); - strcpy(dc.x.monitor_info.name, MONITOR_AUTO); + strcpy(dc.x.monitor_info.name, MONITOR_COMBINED); } compute_geometry(conf, &dc, &topleft_x, &topleft_y, &fat_layer, diff --git a/styles.cfg b/styles.cfg index bda9283..77d10bd 100644 --- a/styles.cfg +++ b/styles.cfg @@ -1,5 +1,5 @@ default = { - monitor = "auto"; + monitor = "combined"; x = {relative = 1; offset = -48;}; y = {relative = 0.5; offset = 0;}; length = {relative = 0.3; offset = 0;}; From 8586a590c2f843bb8442450e2fa0a1ccd8077ae5 Mon Sep 17 00:00:00 2001 From: Megtev Date: Fri, 8 Jul 2022 15:21:24 +0300 Subject: [PATCH 09/23] refactor multimonitor code --- src/conf.h | 3 ++ src/display.c | 113 +++++++++++++++++++++++++++++++------------------- src/display.h | 10 +++++ 3 files changed, 83 insertions(+), 43 deletions(-) diff --git a/src/conf.h b/src/conf.h index 70fe72d..937e5c1 100644 --- a/src/conf.h +++ b/src/conf.h @@ -20,7 +20,10 @@ #include +#define MONITOR_RELATIVE_FOCUS "relative_focus" +#define MONITOR_RELATIVE_POINTER "relative_pointer" #define MONITOR_COMBINED "combined" + #define LNAME_MONITOR 12 typedef struct diff --git a/src/display.c b/src/display.c index e0da221..376a6b2 100644 --- a/src/display.c +++ b/src/display.c @@ -130,6 +130,57 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, conf.y.abs + dc->x.monitor_info.y; } +/* Set combined positon */ +static void set_combined_position(Display_context * pdc) +{ + pdc->x.monitor_info.x = 0; + pdc->x.monitor_info.y = 0; + pdc->x.monitor_info.width = WidthOfScreen(pdc->x.screen); + pdc->x.monitor_info.height = HeightOfScreen(pdc->x.screen); + // strcpy(pdc->x.monitor_info.name, MONITOR_COMBINED); +} + +/* Set specified monitor */ +static void set_specified_position(Display_context * pdc, const Style * pconf) +{ + Window root = RootWindow(pdc->x.display, pdc->x.screen_number); + + /* Get monitors info */ + int num_monitors; + char *monitor_name; + XRRMonitorInfo *monitor_sizes = XRRGetMonitors( + pdc->x.display, root, 0, &num_monitors); + + /* Compare monitors output names */ + int i; + for (i = 0; i < num_monitors; i++) + { + monitor_name = XGetAtomName(pdc->x.display, + monitor_sizes[i].name); + if (strcmp(pconf->monitor, monitor_name) == 0) + break; + } + if (i != num_monitors) + { + pdc->x.monitor_info.x = monitor_sizes[i].x; + pdc->x.monitor_info.y = monitor_sizes[i].y; + pdc->x.monitor_info.width = monitor_sizes[i].width; + pdc->x.monitor_info.height = monitor_sizes[i].height; + strcpy(pdc->x.monitor_info.name, monitor_name); + } + else // Monitor name is not found + { + /* Use combined surface for monitor option if no monitors with + * provided name found */ + fprintf(stderr, "Error: monitor %s is not found.\n", + pconf->monitor); + fprintf(stderr, "Info: falling back to combined mode.\n"); + set_combined_position(pdc); + // strcpy(pdc.x.monitor_info.name, MONITOR_COMBINED); + } + XRRFreeMonitors(monitor_sizes); +} + /* PUBLIC Returns a new display context from a given configuration. If the * .x.display field of the returned display context is NULL, display could not * have been opened.*/ @@ -160,51 +211,27 @@ Display_context init(Style conf) window_attributes.border_pixel = 0; window_attributes.override_redirect = True; - if (strcmp(conf.monitor, MONITOR_COMBINED) != 0) - { - /* Get monitors info */ - int num_monitors; - char *monitor_name; - XRRMonitorInfo *monitor_sizes = XRRGetMonitors( - dc.x.display, root, 0, &num_monitors); - int i; - for (i = 0; i < num_monitors; i++) - { - monitor_name = XGetAtomName(dc.x.display, - monitor_sizes[i].name); - if (strcmp(conf.monitor, monitor_name) == 0) - break; - } - if (i == num_monitors) // Monitor name is not found - { - /* Use combined for monitor option if no monitors with - * provided name found*/ - fprintf(stderr, "Error: monitor %s is not found.\n", - conf.monitor); - fprintf(stderr, "Info: falling back to combined mode.\n"); - dc.x.monitor_info.x = 0; - dc.x.monitor_info.y = 0; - dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); - dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); - strcpy(dc.x.monitor_info.name, MONITOR_COMBINED); - } - else - { - dc.x.monitor_info.x = monitor_sizes[i].x; - dc.x.monitor_info.y = monitor_sizes[i].y; - dc.x.monitor_info.width = monitor_sizes[i].width; - dc.x.monitor_info.height = monitor_sizes[i].height; - strcpy(dc.x.monitor_info.name, monitor_name); - } - XRRFreeMonitors(monitor_sizes); - } + /* Get bar position from conf */ + if (strcmp(conf.monitor, MONITOR_RELATIVE_FOCUS) == 0) + dc.x.bar_position = POSITION_RELATIVE_FOCUS; + else if (strcmp(conf.monitor, MONITOR_RELATIVE_POINTER) == 0) + dc.x.bar_position = POSITION_RELATIVE_POINTER; + else if (strcmp(conf.monitor, MONITOR_COMBINED) == 0) + dc.x.bar_position = POSITION_COMBINED; else + dc.x.bar_position = POSITION_SPECIFIED; + + switch (dc.x.bar_position) { - dc.x.monitor_info.x = 0; - dc.x.monitor_info.y = 0; - dc.x.monitor_info.width = WidthOfScreen(dc.x.screen); - dc.x.monitor_info.height = HeightOfScreen(dc.x.screen); - strcpy(dc.x.monitor_info.name, MONITOR_COMBINED); + case POSITION_COMBINED: + set_combined_position(&dc); + break; + case POSITION_SPECIFIED: + set_specified_position(&dc, &conf); + break; + default: + fprintf(stderr, "Error: in switch position\n"); + break; } compute_geometry(conf, &dc, &topleft_x, &topleft_y, &fat_layer, diff --git a/src/display.h b/src/display.h index 6cca433..bd7a447 100644 --- a/src/display.h +++ b/src/display.h @@ -20,6 +20,15 @@ #include "conf.h" #include +#include + +typedef enum +{ + POSITION_RELATIVE_FOCUS, + POSITION_RELATIVE_POINTER, + POSITION_COMBINED, + POSITION_SPECIFIED +} Bar_position; typedef enum { @@ -44,6 +53,7 @@ typedef struct Window window; Bool mapped; MonitorInfo monitor_info; + Bar_position bar_position; } X_context; typedef struct From 9e73e9afa893265ca9ad13d89509184e120264d5 Mon Sep 17 00:00:00 2001 From: Megtev Date: Fri, 8 Jul 2022 18:54:07 +0300 Subject: [PATCH 10/23] add code to support changing bar position depends on focused window --- src/display.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/display.h | 4 +++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/display.c b/src/display.c index 376a6b2..f8d85a8 100644 --- a/src/display.c +++ b/src/display.c @@ -125,7 +125,7 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, *topleft_y = fit_in(dc->x.monitor_info.height * conf.y.rel - (size_y(dc->geometry) + 2 * *fat_layer) / 2, 0, - dc->x.monitor_info.width - + dc->x.monitor_info.height - (size_y(dc->geometry) + 2 * *fat_layer)) + conf.y.abs + dc->x.monitor_info.y; } @@ -181,6 +181,76 @@ static void set_specified_position(Display_context * pdc, const Style * pconf) XRRFreeMonitors(monitor_sizes); } +/* Change position for the bar to focused monitor */ +static void move_to_focused_monitor(const Display_context * pdc) +{ + + int revert_to_window; + int focused_x, focused_y, topleft_x, topleft_y; + int num_monitors; + int fat_layer, i; + + XRRMonitorInfo *monitor_sizes; + Window focused_window, fchild_window; + + XGetInputFocus(pdc->x.display, &focused_window, &revert_to_window); + + /* Get coords of focused window */ + XTranslateCoordinates(pdc->x.display, focused_window, + RootWindow(pdc->x.display, pdc->x.screen_number), + 0, 0, &focused_x, &focused_y, &fchild_window); + + fprintf(stderr, "\ncoords x[%d] y[%d]\n", focused_x, focused_y); + fprintf(stderr, "x_rel[%.2f] x_abs[%d], y_rel[%.2f], y_abs[%d]\n", + pdc->x.x_rel, pdc->x.x_abs, pdc->x.y_rel, pdc->x.y_abs); + + fat_layer = pdc->geometry.padding + pdc->geometry.border + + pdc->geometry.outline; + + monitor_sizes = XRRGetMonitors( + pdc->x.display, RootWindow(pdc->x.display, pdc->x.screen_number), + 0, &num_monitors); + for (i = 0; i < num_monitors; i++) + { + printf("x[%d] y[%d] w[%d] h[%d]\n", monitor_sizes[i].x, + monitor_sizes[i].y, monitor_sizes[i].width, + monitor_sizes[i].height); + + /* Find monitor by coordinates of focused window */ + if (focused_x > monitor_sizes[i].x && + focused_x < monitor_sizes[i].x + monitor_sizes[i].width && + focused_y > monitor_sizes[i].y && + focused_y < monitor_sizes[i].y + monitor_sizes[i].height) + { + topleft_x = fit_in(monitor_sizes[i].width * pdc->x.x_rel - + (size_x(pdc->geometry) + 2 * fat_layer) / 2, + 0, + monitor_sizes[i].width - + (size_x(pdc->geometry) + 2 * fat_layer)) + + pdc->x.x_abs + monitor_sizes[i].x; + + topleft_y = fit_in(monitor_sizes[i].height * pdc->x.y_rel - + (size_y(pdc->geometry) + 2 * fat_layer) / 2, + 0, + monitor_sizes[i].height - + (size_y(pdc->geometry) + 2 * fat_layer)) + + pdc->x.y_abs + monitor_sizes[i].y; + + fprintf(stderr, "Mname[%s]\n", XGetAtomName( + pdc->x.display, monitor_sizes[i].name)); + printf("topleft_x[%d] topleft_y[%d]\n", topleft_x, + topleft_y); + + XMoveWindow(pdc->x.display, pdc->x.window, + topleft_x, topleft_y); + break; + } + } + + XRRFreeMonitors(monitor_sizes); +} + + /* PUBLIC Returns a new display context from a given configuration. If the * .x.display field of the returned display context is NULL, display could not * have been opened.*/ @@ -211,6 +281,12 @@ Display_context init(Style conf) window_attributes.border_pixel = 0; window_attributes.override_redirect = True; + /* Write bar position relative data to X_context */ + dc.x.x_rel = conf.x.rel; + dc.x.x_abs = conf.x.abs; + dc.x.y_rel = conf.y.rel; + dc.x.y_abs = conf.y.abs; + /* Get bar position from conf */ if (strcmp(conf.monitor, MONITOR_RELATIVE_FOCUS) == 0) dc.x.bar_position = POSITION_RELATIVE_FOCUS; @@ -322,6 +398,18 @@ Display_context show(Display_context dc, int value, int cap, colors.bg); } + /* Move the bar for relative positions */ + // switch (dc.x.bar_position) + switch (POSITION_RELATIVE_FOCUS) + { + case POSITION_RELATIVE_FOCUS: + move_to_focused_monitor(&dc); + break; + case POSITION_COMBINED: + case POSITION_SPECIFIED: + break; + } + XFlush(dc.x.display); return newdc; diff --git a/src/display.h b/src/display.h index bd7a447..2bbfdc3 100644 --- a/src/display.h +++ b/src/display.h @@ -54,6 +54,10 @@ typedef struct Bool mapped; MonitorInfo monitor_info; Bar_position bar_position; + double x_rel; + int x_abs; + double y_rel; + int y_abs; } X_context; typedef struct From b399c085b8d320e05f3c717114abdeea78aa86d8 Mon Sep 17 00:00:00 2001 From: Megtev Date: Sat, 9 Jul 2022 01:31:48 +0300 Subject: [PATCH 11/23] fix mistake with max possible height --- src/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/display.c b/src/display.c index e0da221..2f4bef3 100644 --- a/src/display.c +++ b/src/display.c @@ -125,7 +125,7 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, *topleft_y = fit_in(dc->x.monitor_info.height * conf.y.rel - (size_y(dc->geometry) + 2 * *fat_layer) / 2, 0, - dc->x.monitor_info.width - + dc->x.monitor_info.height - (size_y(dc->geometry) + 2 * *fat_layer)) + conf.y.abs + dc->x.monitor_info.y; } From 1322dda0eb73166ea9e1d346aaa23a50dca2c44e Mon Sep 17 00:00:00 2001 From: Megtev Date: Sat, 9 Jul 2022 13:52:17 +0300 Subject: [PATCH 12/23] add code to support changing bar position depends on pointer position --- src/display.c | 100 +++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/src/display.c b/src/display.c index f8d85a8..a552c14 100644 --- a/src/display.c +++ b/src/display.c @@ -181,29 +181,13 @@ static void set_specified_position(Display_context * pdc, const Style * pconf) XRRFreeMonitors(monitor_sizes); } -/* Change position for the bar to focused monitor */ -static void move_to_focused_monitor(const Display_context * pdc) +/* Move the bar to a monitor with provided coords */ +static void move_to_coords_monitor(const Display_context * pdc, int x, int y) { - - int revert_to_window; - int focused_x, focused_y, topleft_x, topleft_y; - int num_monitors; int fat_layer, i; - + int topleft_x, topleft_y; + int num_monitors; XRRMonitorInfo *monitor_sizes; - Window focused_window, fchild_window; - - XGetInputFocus(pdc->x.display, &focused_window, &revert_to_window); - - /* Get coords of focused window */ - XTranslateCoordinates(pdc->x.display, focused_window, - RootWindow(pdc->x.display, pdc->x.screen_number), - 0, 0, &focused_x, &focused_y, &fchild_window); - - fprintf(stderr, "\ncoords x[%d] y[%d]\n", focused_x, focused_y); - fprintf(stderr, "x_rel[%.2f] x_abs[%d], y_rel[%.2f], y_abs[%d]\n", - pdc->x.x_rel, pdc->x.x_abs, pdc->x.y_rel, pdc->x.y_abs); - fat_layer = pdc->geometry.padding + pdc->geometry.border + pdc->geometry.outline; @@ -212,15 +196,11 @@ static void move_to_focused_monitor(const Display_context * pdc) 0, &num_monitors); for (i = 0; i < num_monitors; i++) { - printf("x[%d] y[%d] w[%d] h[%d]\n", monitor_sizes[i].x, - monitor_sizes[i].y, monitor_sizes[i].width, - monitor_sizes[i].height); - /* Find monitor by coordinates of focused window */ - if (focused_x > monitor_sizes[i].x && - focused_x < monitor_sizes[i].x + monitor_sizes[i].width && - focused_y > monitor_sizes[i].y && - focused_y < monitor_sizes[i].y + monitor_sizes[i].height) + if (x > monitor_sizes[i].x && + x < monitor_sizes[i].x + monitor_sizes[i].width && + y > monitor_sizes[i].y && + y < monitor_sizes[i].y + monitor_sizes[i].height) { topleft_x = fit_in(monitor_sizes[i].width * pdc->x.x_rel - (size_x(pdc->geometry) + 2 * fat_layer) / 2, @@ -236,11 +216,6 @@ static void move_to_focused_monitor(const Display_context * pdc) (size_y(pdc->geometry) + 2 * fat_layer)) + pdc->x.y_abs + monitor_sizes[i].y; - fprintf(stderr, "Mname[%s]\n", XGetAtomName( - pdc->x.display, monitor_sizes[i].name)); - printf("topleft_x[%d] topleft_y[%d]\n", topleft_x, - topleft_y); - XMoveWindow(pdc->x.display, pdc->x.window, topleft_x, topleft_y); break; @@ -250,6 +225,38 @@ static void move_to_focused_monitor(const Display_context * pdc) XRRFreeMonitors(monitor_sizes); } +/* Mobe the bar to monitor with focused window */ +static void move_to_focused_monitor(const Display_context * pdc) +{ + int revert_to_window; + int focused_x, focused_y; + + Window focused_window, fchild_window; + + XGetInputFocus(pdc->x.display, &focused_window, &revert_to_window); + + /* Get coords of focused window */ + XTranslateCoordinates(pdc->x.display, focused_window, + RootWindow(pdc->x.display, pdc->x.screen_number), + 0, 0, &focused_x, &focused_y, &fchild_window); + + move_to_coords_monitor(pdc, focused_x, focused_y); +} + +/* Move the bar to monitor with pointer */ +static void move_to_pointer_monitor(const Display_context * pdc) +{ + int pointer_x, pointer_y, win_x, win_y; + unsigned int p_mask; + Window p_root, p_child; + + XQueryPointer(pdc->x.display, + RootWindow(pdc->x.display, pdc->x.screen_number), + &p_root, &p_child, &pointer_x, &pointer_y, &win_x, &win_y, + &p_mask); + + move_to_coords_monitor(pdc, pointer_x, pointer_y); +} /* PUBLIC Returns a new display context from a given configuration. If the * .x.display field of the returned display context is NULL, display could not @@ -355,6 +362,21 @@ Display_context show(Display_context dc, int value, int cap, Colors colors; Colors colors_overflow_proportional; + /* Move the bar for relative positions */ + // switch (dc.x.bar_position) + switch (POSITION_RELATIVE_POINTER) + { + case POSITION_RELATIVE_FOCUS: + move_to_focused_monitor(&dc); + break; + case POSITION_RELATIVE_POINTER: + move_to_pointer_monitor(&dc); + break; + case POSITION_COMBINED: + case POSITION_SPECIFIED: + break; + } + if (!dc.x.mapped) { XMapWindow(dc.x.display, dc.x.window); @@ -398,18 +420,6 @@ Display_context show(Display_context dc, int value, int cap, colors.bg); } - /* Move the bar for relative positions */ - // switch (dc.x.bar_position) - switch (POSITION_RELATIVE_FOCUS) - { - case POSITION_RELATIVE_FOCUS: - move_to_focused_monitor(&dc); - break; - case POSITION_COMBINED: - case POSITION_SPECIFIED: - break; - } - XFlush(dc.x.display); return newdc; From 552766d14af3456d8a8aae891c7651711173c184 Mon Sep 17 00:00:00 2001 From: Megtev Date: Sun, 10 Jul 2022 14:15:57 +0300 Subject: [PATCH 13/23] move bar position related stuff to Geometry_context --- src/display.c | 28 ++++++++++++++-------------- src/display.h | 14 +++++++++----- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/display.c b/src/display.c index a552c14..8381dd0 100644 --- a/src/display.c +++ b/src/display.c @@ -202,19 +202,19 @@ static void move_to_coords_monitor(const Display_context * pdc, int x, int y) y > monitor_sizes[i].y && y < monitor_sizes[i].y + monitor_sizes[i].height) { - topleft_x = fit_in(monitor_sizes[i].width * pdc->x.x_rel - + topleft_x = fit_in(monitor_sizes[i].width * pdc->geometry.x.rel - (size_x(pdc->geometry) + 2 * fat_layer) / 2, 0, monitor_sizes[i].width - (size_x(pdc->geometry) + 2 * fat_layer)) + - pdc->x.x_abs + monitor_sizes[i].x; + pdc->geometry.x.abs + monitor_sizes[i].x; - topleft_y = fit_in(monitor_sizes[i].height * pdc->x.y_rel - + topleft_y = fit_in(monitor_sizes[i].height * pdc->geometry.y.rel - (size_y(pdc->geometry) + 2 * fat_layer) / 2, 0, monitor_sizes[i].height - (size_y(pdc->geometry) + 2 * fat_layer)) + - pdc->x.y_abs + monitor_sizes[i].y; + pdc->geometry.y.abs + monitor_sizes[i].y; XMoveWindow(pdc->x.display, pdc->x.window, topleft_x, topleft_y); @@ -289,22 +289,22 @@ Display_context init(Style conf) window_attributes.override_redirect = True; /* Write bar position relative data to X_context */ - dc.x.x_rel = conf.x.rel; - dc.x.x_abs = conf.x.abs; - dc.x.y_rel = conf.y.rel; - dc.x.y_abs = conf.y.abs; + dc.geometry.x.rel = conf.x.rel; + dc.geometry.x.abs = conf.x.abs; + dc.geometry.y.rel = conf.y.rel; + dc.geometry.y.abs = conf.y.abs; /* Get bar position from conf */ if (strcmp(conf.monitor, MONITOR_RELATIVE_FOCUS) == 0) - dc.x.bar_position = POSITION_RELATIVE_FOCUS; + dc.geometry.bar_position = POSITION_RELATIVE_FOCUS; else if (strcmp(conf.monitor, MONITOR_RELATIVE_POINTER) == 0) - dc.x.bar_position = POSITION_RELATIVE_POINTER; + dc.geometry.bar_position = POSITION_RELATIVE_POINTER; else if (strcmp(conf.monitor, MONITOR_COMBINED) == 0) - dc.x.bar_position = POSITION_COMBINED; + dc.geometry.bar_position = POSITION_COMBINED; else - dc.x.bar_position = POSITION_SPECIFIED; + dc.geometry.bar_position = POSITION_SPECIFIED; - switch (dc.x.bar_position) + switch (dc.geometry.bar_position) { case POSITION_COMBINED: set_combined_position(&dc); @@ -363,7 +363,7 @@ Display_context show(Display_context dc, int value, int cap, Colors colors_overflow_proportional; /* Move the bar for relative positions */ - // switch (dc.x.bar_position) + // switch (dc.geometry.bar_position) switch (POSITION_RELATIVE_POINTER) { case POSITION_RELATIVE_FOCUS: diff --git a/src/display.h b/src/display.h index 2bbfdc3..5fa4bea 100644 --- a/src/display.h +++ b/src/display.h @@ -53,11 +53,6 @@ typedef struct Window window; Bool mapped; MonitorInfo monitor_info; - Bar_position bar_position; - double x_rel; - int x_abs; - double y_rel; - int y_abs; } X_context; typedef struct @@ -67,6 +62,15 @@ typedef struct int padding; int length; int thickness; + struct { + double rel; + int abs; + } x; + struct { + double rel; + int abs; + } y; + Bar_position bar_position; Orientation orientation; } Geometry_context; From 17194106fb467443e1dfb71c8ceca77492a32c17 Mon Sep 17 00:00:00 2001 From: Megtev Date: Mon, 11 Jul 2022 16:14:47 +0300 Subject: [PATCH 14/23] use clang-format; small improvements --- src/conf.c | 3 +- src/conf.h | 2 +- src/display.c | 143 +++++++++++++++++++++++++++++++------------------- src/display.h | 11 +++- 4 files changed, 99 insertions(+), 60 deletions(-) diff --git a/src/conf.c b/src/conf.c index 2657e0c..bb2f0f7 100644 --- a/src/conf.c +++ b/src/conf.c @@ -259,8 +259,7 @@ Style parse_style_config(FILE *file, const char *stylename, Style default_style) xob_config = config_lookup(&config, stylename); if (xob_config != NULL) { - config_setting_lookup_monitor(xob_config, "monitor", - style.monitor); + config_setting_lookup_monitor(xob_config, "monitor", style.monitor); config_setting_lookup_int(xob_config, "thickness", &style.thickness); config_setting_lookup_int(xob_config, "border", &style.border); diff --git a/src/conf.h b/src/conf.h index 937e5c1..985a8ea 100644 --- a/src/conf.h +++ b/src/conf.h @@ -24,7 +24,7 @@ #define MONITOR_RELATIVE_POINTER "relative_pointer" #define MONITOR_COMBINED "combined" -#define LNAME_MONITOR 12 +#define LNAME_MONITOR 17 typedef struct { diff --git a/src/display.c b/src/display.c index 8381dd0..d685cf4 100644 --- a/src/display.c +++ b/src/display.c @@ -103,6 +103,9 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, dc->geometry.padding = conf.padding; dc->geometry.thickness = conf.thickness; dc->geometry.orientation = conf.orientation; + dc->geometry.length_dynamic.rel = conf.length.rel; + dc->geometry.length_dynamic.abs = conf.length.abs; + *fat_layer = dc->geometry.padding + dc->geometry.border + dc->geometry.outline; @@ -131,7 +134,7 @@ void compute_geometry(Style conf, Display_context *dc, int *topleft_x, } /* Set combined positon */ -static void set_combined_position(Display_context * pdc) +static void set_combined_position(Display_context *pdc) { pdc->x.monitor_info.x = 0; pdc->x.monitor_info.y = 0; @@ -140,23 +143,52 @@ static void set_combined_position(Display_context * pdc) // strcpy(pdc->x.monitor_info.name, MONITOR_COMBINED); } +/* Set bar size relative to the first monitor */ +static void set_relative_position(Display_context *pdc) +{ + Window root = RootWindow(pdc->x.display, pdc->x.screen_number); + + /* Get monitors info */ + int num_monitors; + XRRMonitorInfo *monitor_sizes = + XRRGetMonitors(pdc->x.display, root, 0, &num_monitors); + + /* Set monitor_info for the first monitor */ + if (num_monitors != 0) + { + pdc->x.monitor_info.x = monitor_sizes[0].x; + pdc->x.monitor_info.y = monitor_sizes[0].y; + pdc->x.monitor_info.width = monitor_sizes[0].width; + pdc->x.monitor_info.height = monitor_sizes[0].height; + } + else // Monitor name is not found + { + /* Use combined surface for monitor option if no monitors with + * provided name found */ + fprintf(stderr, "Error: Can't get monitors info.\n"); + fprintf(stderr, "Info: falling back to combined mode.\n"); + set_combined_position(pdc); + // strcpy(pdc.x.monitor_info.name, MONITOR_COMBINED); + } + XRRFreeMonitors(monitor_sizes); +} + /* Set specified monitor */ -static void set_specified_position(Display_context * pdc, const Style * pconf) +static void set_specified_position(Display_context *pdc, const Style *pconf) { Window root = RootWindow(pdc->x.display, pdc->x.screen_number); /* Get monitors info */ int num_monitors; char *monitor_name; - XRRMonitorInfo *monitor_sizes = XRRGetMonitors( - pdc->x.display, root, 0, &num_monitors); + XRRMonitorInfo *monitor_sizes = + XRRGetMonitors(pdc->x.display, root, 0, &num_monitors); /* Compare monitors output names */ int i; for (i = 0; i < num_monitors; i++) { - monitor_name = XGetAtomName(pdc->x.display, - monitor_sizes[i].name); + monitor_name = XGetAtomName(pdc->x.display, monitor_sizes[i].name); if (strcmp(pconf->monitor, monitor_name) == 0) break; } @@ -172,8 +204,7 @@ static void set_specified_position(Display_context * pdc, const Style * pconf) { /* Use combined surface for monitor option if no monitors with * provided name found */ - fprintf(stderr, "Error: monitor %s is not found.\n", - pconf->monitor); + fprintf(stderr, "Error: monitor %s is not found.\n", pconf->monitor); fprintf(stderr, "Info: falling back to combined mode.\n"); set_combined_position(pdc); // strcpy(pdc.x.monitor_info.name, MONITOR_COMBINED); @@ -182,42 +213,41 @@ static void set_specified_position(Display_context * pdc, const Style * pconf) } /* Move the bar to a monitor with provided coords */ -static void move_to_coords_monitor(const Display_context * pdc, int x, int y) +static void move_to_coords_monitor(const Display_context *pdc, int x, int y) { int fat_layer, i; int topleft_x, topleft_y; int num_monitors; XRRMonitorInfo *monitor_sizes; - fat_layer = pdc->geometry.padding + pdc->geometry.border + - pdc->geometry.outline; + fat_layer = + pdc->geometry.padding + pdc->geometry.border + pdc->geometry.outline; monitor_sizes = XRRGetMonitors( - pdc->x.display, RootWindow(pdc->x.display, pdc->x.screen_number), - 0, &num_monitors); + pdc->x.display, RootWindow(pdc->x.display, pdc->x.screen_number), 0, + &num_monitors); for (i = 0; i < num_monitors; i++) { /* Find monitor by coordinates of focused window */ if (x > monitor_sizes[i].x && - x < monitor_sizes[i].x + monitor_sizes[i].width && - y > monitor_sizes[i].y && - y < monitor_sizes[i].y + monitor_sizes[i].height) + x < monitor_sizes[i].x + monitor_sizes[i].width && + y > monitor_sizes[i].y && + y < monitor_sizes[i].y + monitor_sizes[i].height) { topleft_x = fit_in(monitor_sizes[i].width * pdc->geometry.x.rel - - (size_x(pdc->geometry) + 2 * fat_layer) / 2, - 0, - monitor_sizes[i].width - - (size_x(pdc->geometry) + 2 * fat_layer)) + - pdc->geometry.x.abs + monitor_sizes[i].x; + (size_x(pdc->geometry) + 2 * fat_layer) / 2, + 0, + monitor_sizes[i].width - + (size_x(pdc->geometry) + 2 * fat_layer)) + + pdc->geometry.x.abs + monitor_sizes[i].x; topleft_y = fit_in(monitor_sizes[i].height * pdc->geometry.y.rel - - (size_y(pdc->geometry) + 2 * fat_layer) / 2, - 0, - monitor_sizes[i].height - - (size_y(pdc->geometry) + 2 * fat_layer)) + - pdc->geometry.y.abs + monitor_sizes[i].y; - - XMoveWindow(pdc->x.display, pdc->x.window, - topleft_x, topleft_y); + (size_y(pdc->geometry) + 2 * fat_layer) / 2, + 0, + monitor_sizes[i].height - + (size_y(pdc->geometry) + 2 * fat_layer)) + + pdc->geometry.y.abs + monitor_sizes[i].y; + + XMoveWindow(pdc->x.display, pdc->x.window, topleft_x, topleft_y); break; } } @@ -226,7 +256,7 @@ static void move_to_coords_monitor(const Display_context * pdc, int x, int y) } /* Mobe the bar to monitor with focused window */ -static void move_to_focused_monitor(const Display_context * pdc) +static void move_to_focused_monitor(const Display_context *pdc) { int revert_to_window; int focused_x, focused_y; @@ -237,23 +267,22 @@ static void move_to_focused_monitor(const Display_context * pdc) /* Get coords of focused window */ XTranslateCoordinates(pdc->x.display, focused_window, - RootWindow(pdc->x.display, pdc->x.screen_number), - 0, 0, &focused_x, &focused_y, &fchild_window); + RootWindow(pdc->x.display, pdc->x.screen_number), 0, + 0, &focused_x, &focused_y, &fchild_window); move_to_coords_monitor(pdc, focused_x, focused_y); } /* Move the bar to monitor with pointer */ -static void move_to_pointer_monitor(const Display_context * pdc) +static void move_to_pointer_monitor(const Display_context *pdc) { int pointer_x, pointer_y, win_x, win_y; unsigned int p_mask; Window p_root, p_child; XQueryPointer(pdc->x.display, - RootWindow(pdc->x.display, pdc->x.screen_number), - &p_root, &p_child, &pointer_x, &pointer_y, &win_x, &win_y, - &p_mask); + RootWindow(pdc->x.display, pdc->x.screen_number), &p_root, + &p_child, &pointer_x, &pointer_y, &win_x, &win_y, &p_mask); move_to_coords_monitor(pdc, pointer_x, pointer_y); } @@ -306,15 +335,19 @@ Display_context init(Style conf) switch (dc.geometry.bar_position) { - case POSITION_COMBINED: - set_combined_position(&dc); - break; - case POSITION_SPECIFIED: - set_specified_position(&dc, &conf); - break; - default: - fprintf(stderr, "Error: in switch position\n"); - break; + case POSITION_RELATIVE_FOCUS: + case POSITION_RELATIVE_POINTER: + set_relative_position(&dc); + break; + case POSITION_COMBINED: + set_combined_position(&dc); + break; + case POSITION_SPECIFIED: + set_specified_position(&dc, &conf); + break; + default: + fprintf(stderr, "Error: in switch position\n"); + break; } compute_geometry(conf, &dc, &topleft_x, &topleft_y, &fat_layer, @@ -364,17 +397,17 @@ Display_context show(Display_context dc, int value, int cap, /* Move the bar for relative positions */ // switch (dc.geometry.bar_position) - switch (POSITION_RELATIVE_POINTER) + switch (dc.geometry.bar_position) { - case POSITION_RELATIVE_FOCUS: - move_to_focused_monitor(&dc); - break; - case POSITION_RELATIVE_POINTER: - move_to_pointer_monitor(&dc); - break; - case POSITION_COMBINED: - case POSITION_SPECIFIED: - break; + case POSITION_RELATIVE_FOCUS: + move_to_focused_monitor(&dc); + break; + case POSITION_RELATIVE_POINTER: + move_to_pointer_monitor(&dc); + break; + case POSITION_COMBINED: + case POSITION_SPECIFIED: + break; } if (!dc.x.mapped) diff --git a/src/display.h b/src/display.h index 5fa4bea..2c06d72 100644 --- a/src/display.h +++ b/src/display.h @@ -61,12 +61,19 @@ typedef struct int border; int padding; int length; + struct + { + double rel; + int abs; + } length_dynamic; int thickness; - struct { + struct + { double rel; int abs; } x; - struct { + struct + { double rel; int abs; } y; From 5161fd0d8eb0140f89a2c5be2e311cccb2c57b71 Mon Sep 17 00:00:00 2001 From: Megtev Date: Mon, 11 Jul 2022 17:05:52 +0300 Subject: [PATCH 15/23] change bar sizes relative to monitor sizes --- src/display.c | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/display.c b/src/display.c index d685cf4..247c65d 100644 --- a/src/display.c +++ b/src/display.c @@ -36,6 +36,7 @@ static int size_x(Geometry_context g) { return g.orientation == HORIZONTAL ? g.length : g.thickness; } + static int size_y(Geometry_context g) { return g.orientation == HORIZONTAL ? g.thickness : g.length; @@ -212,10 +213,10 @@ static void set_specified_position(Display_context *pdc, const Style *pconf) XRRFreeMonitors(monitor_sizes); } -/* Move the bar to a monitor with provided coords */ -static void move_to_coords_monitor(const Display_context *pdc, int x, int y) +/* Move and resize the bar relative to a monitor with provided coords */ +static void move_resize_to_coords_monitor(Display_context *pdc, int x, int y) { - int fat_layer, i; + int fat_layer, available_length, bar_size_x, bar_size_y, i; int topleft_x, topleft_y; int num_monitors; XRRMonitorInfo *monitor_sizes; @@ -233,21 +234,33 @@ static void move_to_coords_monitor(const Display_context *pdc, int x, int y) y > monitor_sizes[i].y && y < monitor_sizes[i].y + monitor_sizes[i].height) { + /* Recalculate bar sizes */ + available_length = pdc->geometry.orientation == HORIZONTAL + ? monitor_sizes[i].width + : monitor_sizes[i].height; + + pdc->geometry.length = + fit_in(available_length * pdc->geometry.length_dynamic.rel + + pdc->geometry.length_dynamic.abs, + 0, available_length - 2 * fat_layer); + + bar_size_x = size_x(pdc->geometry) + 2 * fat_layer; + bar_size_y = size_y(pdc->geometry) + 2 * fat_layer; + + /* Recalculate bar position */ topleft_x = fit_in(monitor_sizes[i].width * pdc->geometry.x.rel - - (size_x(pdc->geometry) + 2 * fat_layer) / 2, - 0, - monitor_sizes[i].width - - (size_x(pdc->geometry) + 2 * fat_layer)) + + bar_size_x / 2, + 0, monitor_sizes[i].width - bar_size_x) + pdc->geometry.x.abs + monitor_sizes[i].x; topleft_y = fit_in(monitor_sizes[i].height * pdc->geometry.y.rel - - (size_y(pdc->geometry) + 2 * fat_layer) / 2, - 0, - monitor_sizes[i].height - - (size_y(pdc->geometry) + 2 * fat_layer)) + + bar_size_y / 2, + 0, monitor_sizes[i].height - bar_size_y) + pdc->geometry.y.abs + monitor_sizes[i].y; - XMoveWindow(pdc->x.display, pdc->x.window, topleft_x, topleft_y); + /* Move and resize bar */ + XMoveResizeWindow(pdc->x.display, pdc->x.window, topleft_x, + topleft_y, bar_size_x, bar_size_y); break; } } @@ -256,7 +269,7 @@ static void move_to_coords_monitor(const Display_context *pdc, int x, int y) } /* Mobe the bar to monitor with focused window */ -static void move_to_focused_monitor(const Display_context *pdc) +static void move_resize_to_focused_monitor(Display_context *pdc) { int revert_to_window; int focused_x, focused_y; @@ -270,11 +283,11 @@ static void move_to_focused_monitor(const Display_context *pdc) RootWindow(pdc->x.display, pdc->x.screen_number), 0, 0, &focused_x, &focused_y, &fchild_window); - move_to_coords_monitor(pdc, focused_x, focused_y); + move_resize_to_coords_monitor(pdc, focused_x, focused_y); } /* Move the bar to monitor with pointer */ -static void move_to_pointer_monitor(const Display_context *pdc) +static void move_resize_to_pointer_monitor(Display_context *pdc) { int pointer_x, pointer_y, win_x, win_y; unsigned int p_mask; @@ -284,7 +297,7 @@ static void move_to_pointer_monitor(const Display_context *pdc) RootWindow(pdc->x.display, pdc->x.screen_number), &p_root, &p_child, &pointer_x, &pointer_y, &win_x, &win_y, &p_mask); - move_to_coords_monitor(pdc, pointer_x, pointer_y); + move_resize_to_coords_monitor(pdc, pointer_x, pointer_y); } /* PUBLIC Returns a new display context from a given configuration. If the @@ -400,10 +413,10 @@ Display_context show(Display_context dc, int value, int cap, switch (dc.geometry.bar_position) { case POSITION_RELATIVE_FOCUS: - move_to_focused_monitor(&dc); + move_resize_to_focused_monitor(&dc); break; case POSITION_RELATIVE_POINTER: - move_to_pointer_monitor(&dc); + move_resize_to_pointer_monitor(&dc); break; case POSITION_COMBINED: case POSITION_SPECIFIED: From 307bb0ecc13319bc04f49cc1012295001d363cc9 Mon Sep 17 00:00:00 2001 From: Megtev Date: Fri, 15 Jul 2022 16:12:03 +0300 Subject: [PATCH 16/23] update doc; delete unnecessary code --- doc/xob.1 | 7 +++++-- doc/xob.md | 5 ++--- src/display.c | 35 ++++------------------------------- 3 files changed, 11 insertions(+), 36 deletions(-) diff --git a/doc/xob.1 b/doc/xob.1 index 7ec1764..ad8f143 100644 --- a/doc/xob.1 +++ b/doc/xob.1 @@ -169,9 +169,12 @@ In the following, a dot \[lq].\[rq] means \[lq]suboption\[rq]. For instance \[lq]color.normal.fg\[rq] means \[lq]The suboption fg of the suboption normal of option color\[rq]. .TP -\f[B]monitor\f[R] \f[I]\[lq]output_name\[rq]\f[R] (default: combined) +\f[B]monitor\f[R] \f[I]\[lq]output_name\[rq] | \[lq]relative_focus\[rq] | \[lq]relative_pointer\[rq] | \[lq]combined\[rq]\f[R] (default: combined) Output monitor for the bar, use \f[I]xrandr\f[R] command to get monitors names. -The option is case-sensitive. +Use \f[I]relative_focus\f[R] to show the bar on the monitor with a focused window. +Use \f[I]relative_pointer\f[R] to show the bar on the monitor with a mouse +pointer. Use \f[I]combined\f[R] to show the bar on the combined surface of all +monitors. The option is case-sensitive. .TP \f[B]orientation\f[R] \f[I]\[lq]horizontal\[rq] | \[lq]vertical\[rq]\f[R] (default: vertical) Orientation of the bar which either fills up from left to right diff --git a/doc/xob.md b/doc/xob.md index 18f91c7..7a4d111 100644 --- a/doc/xob.md +++ b/doc/xob.md @@ -104,8 +104,8 @@ Options can be grouped together inside curly brackets. Some options expect a gro In the following, a dot "." means "suboption". For instance "color.normal.fg" means "The suboption fg of the suboption normal of option color". -**monitor** "output_name" (default: combined) -: Output monitor for the bar, use `xrandr` command to get monitors names. The option is case-sensitive. +**monitor** *"output_name" | "relative_focus" | "relative_pointer" | "combined"* (default: combined) +: Output monitor for the bar, use `xrandr` command to get monitors names. Use "relative_focus" to show the bar on the monitor with a focused window. Use "relative_pointer" to show the bar on the monitor with a mouse pointer. Use "combined" to show the bar on the combined surface of all monitors. The option is case-sensitive. **orientation** *"horizontal" | "vertical"* (default: vertical) : Orientation of the bar which either fills up from left to right ("horizontal") or bottom to top ("vertical"). @@ -159,7 +159,6 @@ Each of the following have three suboptions ".fg", ".bg", and ".border" correspo ## STYLES - All the options described above must be encompassed inside a style specification. A style consists of a group of all or some of the options described above. The name of the style is the name of an option at the root level of the configuration file. When an option is missing from a style, the default values are used instead. A configuration file may specify several styles (at least 1) to choose using the **-s** argument. This example configuration file provides two styles "volume" and "backlight". Instances of xog launched with **-s volume** and **-s backlight** will look according to the corresponding style. diff --git a/src/display.c b/src/display.c index 247c65d..e39f05f 100644 --- a/src/display.c +++ b/src/display.c @@ -144,36 +144,6 @@ static void set_combined_position(Display_context *pdc) // strcpy(pdc->x.monitor_info.name, MONITOR_COMBINED); } -/* Set bar size relative to the first monitor */ -static void set_relative_position(Display_context *pdc) -{ - Window root = RootWindow(pdc->x.display, pdc->x.screen_number); - - /* Get monitors info */ - int num_monitors; - XRRMonitorInfo *monitor_sizes = - XRRGetMonitors(pdc->x.display, root, 0, &num_monitors); - - /* Set monitor_info for the first monitor */ - if (num_monitors != 0) - { - pdc->x.monitor_info.x = monitor_sizes[0].x; - pdc->x.monitor_info.y = monitor_sizes[0].y; - pdc->x.monitor_info.width = monitor_sizes[0].width; - pdc->x.monitor_info.height = monitor_sizes[0].height; - } - else // Monitor name is not found - { - /* Use combined surface for monitor option if no monitors with - * provided name found */ - fprintf(stderr, "Error: Can't get monitors info.\n"); - fprintf(stderr, "Info: falling back to combined mode.\n"); - set_combined_position(pdc); - // strcpy(pdc.x.monitor_info.name, MONITOR_COMBINED); - } - XRRFreeMonitors(monitor_sizes); -} - /* Set specified monitor */ static void set_specified_position(Display_context *pdc, const Style *pconf) { @@ -350,7 +320,10 @@ Display_context init(Style conf) { case POSITION_RELATIVE_FOCUS: case POSITION_RELATIVE_POINTER: - set_relative_position(&dc); + /* Bar position and sizes will be recalculated every time before + * showing, so the code just init position and sizes like for + * combined surface */ + set_combined_position(&dc); break; case POSITION_COMBINED: set_combined_position(&dc); From 6b5cdc12419e55542826e6fa4a6bacba4b793ba9 Mon Sep 17 00:00:00 2001 From: Megtev Date: Fri, 15 Jul 2022 17:42:03 +0300 Subject: [PATCH 17/23] fix if statement that used to determine monitor info by coords; in relative_focus mode move the bar relative to the center of focused window, not top-left corner of the window --- src/display.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/display.c b/src/display.c index e39f05f..60b66d4 100644 --- a/src/display.c +++ b/src/display.c @@ -198,10 +198,10 @@ static void move_resize_to_coords_monitor(Display_context *pdc, int x, int y) &num_monitors); for (i = 0; i < num_monitors; i++) { - /* Find monitor by coordinates of focused window */ - if (x > monitor_sizes[i].x && + /* Find monitor by coords */ + if (x >= monitor_sizes[i].x && x < monitor_sizes[i].x + monitor_sizes[i].width && - y > monitor_sizes[i].y && + y >= monitor_sizes[i].y && y < monitor_sizes[i].y + monitor_sizes[i].height) { /* Recalculate bar sizes */ @@ -243,6 +243,8 @@ static void move_resize_to_focused_monitor(Display_context *pdc) { int revert_to_window; int focused_x, focused_y; + int dummy_x, dummy_y; + unsigned int focused_width, focused_height, focused_border, focused_depth; Window focused_window, fchild_window; @@ -252,8 +254,14 @@ static void move_resize_to_focused_monitor(Display_context *pdc) XTranslateCoordinates(pdc->x.display, focused_window, RootWindow(pdc->x.display, pdc->x.screen_number), 0, 0, &focused_x, &focused_y, &fchild_window); - - move_resize_to_coords_monitor(pdc, focused_x, focused_y); + /* Get focused window width and height to move bar relative to + * the center of focused window */ + XGetGeometry(pdc->x.display, focused_window, &fchild_window, &dummy_x, + &dummy_y, &focused_width, &focused_height, &focused_border, + &focused_depth); + + move_resize_to_coords_monitor(pdc, focused_x + focused_width / 2, + focused_y + focused_height / 2); } /* Move the bar to monitor with pointer */ From bf55c19050f504797ebbc6fc021c9bad78489aea Mon Sep 17 00:00:00 2001 From: Megtev Date: Fri, 15 Jul 2022 19:36:29 +0300 Subject: [PATCH 18/23] draw all elements of the bar separately --- src/display.c | 93 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/src/display.c b/src/display.c index 2f4bef3..c70c617 100644 --- a/src/display.c +++ b/src/display.c @@ -45,34 +45,107 @@ static int size_y(Geometry_context g) static void draw_empty(X_context x, Geometry_context g, Colors colors) { /* Outline */ +#ifdef _DEBUG_ + // fill_rectangle(x, colors.bg, 0, 0, + // 2 * (g.outline + g.border + g.padding) + size_x(g), + // 2 * (g.outline + g.border + g.padding) + size_y(g)); +#endif + /* Left */ + fill_rectangle(x, colors.bg, 0, 0, g.outline, + 2 * (g.outline + g.border + g.padding) + size_y(g)); + + /* Right */ + fill_rectangle( + x, colors.bg, 2 * (g.border + g.padding) + g.outline + size_x(g), 0, + g.outline, 2 * (g.outline + g.border + g.padding) + size_y(g)); + + /* Top */ fill_rectangle(x, colors.bg, 0, 0, 2 * (g.outline + g.border + g.padding) + size_x(g), - 2 * (g.outline + g.border + g.padding) + size_y(g)); + g.outline); + + /* Bottom */ + fill_rectangle( + x, colors.bg, 0, 2 * (g.border + g.padding) + g.outline + size_y(g), + 2 * (g.outline + g.border + g.padding) + size_x(g), g.outline); + /* Border */ +#ifdef _DEBUG_ fill_rectangle(x, colors.border, g.outline, g.outline, 2 * (g.border + g.padding) + size_x(g), 2 * (g.border + g.padding) + size_y(g)); +#endif + /* Left */ + fill_rectangle(x, colors.border, g.outline, g.outline, g.border, + 2 * (g.border + g.padding) + size_y(g)); + + /* Right */ + fill_rectangle(x, colors.border, + g.outline + g.border + 2 * g.padding + size_x(g), g.outline, + g.border, 2 * (g.border + g.padding) + size_y(g)); + + /* Top */ + fill_rectangle(x, colors.border, g.outline, g.outline, + 2 * (g.border + g.padding) + size_x(g), g.border); + + /* Bottom */ + fill_rectangle(x, colors.border, g.outline, + g.outline + g.border + 2 * g.padding + size_y(g), + 2 * (g.border + g.padding) + size_x(g), g.border); + /* Padding */ +#ifdef _DEBUG_ fill_rectangle(x, colors.bg, g.outline + g.border, g.outline + g.border, 2 * g.padding + size_x(g), 2 * g.padding + size_y(g)); +#endif + + /* Left */ + fill_rectangle(x, colors.bg, g.outline + g.border, g.outline + g.border, + g.padding, 2 * g.padding + size_y(g)); + + /* Right */ + fill_rectangle(x, colors.bg, g.outline + g.border + g.padding + size_x(g), + g.outline + g.border, g.padding, 2 * g.padding + size_y(g)); + + /* Top */ + fill_rectangle(x, colors.bg, g.outline + g.border, g.outline + g.border, + 2 * g.padding + size_x(g), g.padding); + + /* Bottom */ + fill_rectangle(x, colors.bg, g.outline + g.border, + g.outline + g.border + g.padding + size_y(g), + 2 * g.padding + size_x(g), g.padding); } /* Draw a given length of filled bar with the given color */ static void draw_content(X_context x, Geometry_context g, int filled_length, - Color color) + Colors colors) { if (g.orientation == HORIZONTAL) { - fill_rectangle(x, color, g.outline + g.border + g.padding, + /* Fill foreground color */ + fill_rectangle(x, colors.fg, g.outline + g.border + g.padding, g.outline + g.border + g.padding, filled_length, g.thickness); + + /* Fill background color */ + fill_rectangle(x, colors.bg, + g.outline + g.border + g.padding + filled_length, + g.outline + g.border + g.padding, + g.length - filled_length, g.thickness); } else { - fill_rectangle(x, color, g.outline + g.border + g.padding, + /* fill foreground color */ + fill_rectangle(x, colors.fg, g.outline + g.border + g.padding, g.outline + g.border + g.padding + g.length - filled_length, g.thickness, filled_length); + + /* Fill background color */ + fill_rectangle(x, colors.bg, g.outline + g.border + g.padding, + g.outline + g.border + g.padding, + g.thickness, g.length - filled_length); } } @@ -165,13 +238,13 @@ Display_context init(Style conf) /* Get monitors info */ int num_monitors; char *monitor_name; - XRRMonitorInfo *monitor_sizes = XRRGetMonitors( - dc.x.display, root, 0, &num_monitors); + XRRMonitorInfo *monitor_sizes = + XRRGetMonitors(dc.x.display, root, 0, &num_monitors); int i; for (i = 0; i < num_monitors; i++) { - monitor_name = XGetAtomName(dc.x.display, - monitor_sizes[i].name); + monitor_name = + XGetAtomName(dc.x.display, monitor_sizes[i].name); if (strcmp(conf.monitor, monitor_name) == 0) break; } @@ -283,14 +356,14 @@ Display_context show(Display_context dc, int value, int cap, /* Content */ draw_content(dc.x, dc.geometry, - fit_in(value, 0, cap) * dc.geometry.length / cap, colors.fg); + fit_in(value, 0, cap) * dc.geometry.length / cap, colors); /* Proportional overflow : draw separator */ if (value > cap && overflow_mode == PROPORTIONAL && cap * dc.geometry.length / value > dc.geometry.padding) { draw_content(dc.x, dc.geometry, cap * dc.geometry.length / value, - colors_overflow_proportional.fg); + colors_overflow_proportional); draw_separator(dc.x, dc.geometry, cap * dc.geometry.length / value, colors.bg); } From f446332e171140bc147ecf91b3a5c414e16bf1cf Mon Sep 17 00:00:00 2001 From: Megtev Date: Mon, 18 Jul 2022 12:28:13 +0300 Subject: [PATCH 19/23] cosmetics fix --- src/display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/display.c b/src/display.c index c70c617..ccde56e 100644 --- a/src/display.c +++ b/src/display.c @@ -144,8 +144,8 @@ static void draw_content(X_context x, Geometry_context g, int filled_length, /* Fill background color */ fill_rectangle(x, colors.bg, g.outline + g.border + g.padding, - g.outline + g.border + g.padding, - g.thickness, g.length - filled_length); + g.outline + g.border + g.padding, g.thickness, + g.length - filled_length); } } From a397499b51b82d921391d071e82bf0cb8c4c5cb6 Mon Sep 17 00:00:00 2001 From: Megtev Date: Mon, 18 Jul 2022 14:35:08 +0300 Subject: [PATCH 20/23] fix overflow mode --- src/display.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/display.c b/src/display.c index 77ff389..6f5c7ce 100644 --- a/src/display.c +++ b/src/display.c @@ -491,7 +491,10 @@ Display_context show(Display_context dc, int value, int cap, if (value <= cap) colors = dc.colorscheme.normal; else + { colors = dc.colorscheme.overflow; + colors_overflow_proportional.bg = colors.fg; + } break; case ALTERNATIVE: @@ -499,17 +502,16 @@ Display_context show(Display_context dc, int value, int cap, if (value <= cap) colors = dc.colorscheme.alt; else + { colors = dc.colorscheme.altoverflow; + colors_overflow_proportional.bg = colors.fg; + } break; } /* Empty bar */ draw_empty(dc.x, dc.geometry, colors); - /* Content */ - draw_content(dc.x, dc.geometry, - fit_in(value, 0, cap) * dc.geometry.length / cap, colors); - /* Proportional overflow : draw separator */ if (value > cap && overflow_mode == PROPORTIONAL && cap * dc.geometry.length / value > dc.geometry.padding) @@ -519,6 +521,10 @@ Display_context show(Display_context dc, int value, int cap, draw_separator(dc.x, dc.geometry, cap * dc.geometry.length / value, colors.bg); } + else // Value is less then cap + /* Content */ + draw_content(dc.x, dc.geometry, + fit_in(value, 0, cap) * dc.geometry.length / cap, colors); XFlush(dc.x.display); From ef69d4deda1b1a8e6f1e36065e1cb99fd9ef6d0a Mon Sep 17 00:00:00 2001 From: Megtev Date: Mon, 18 Jul 2022 17:16:41 +0300 Subject: [PATCH 21/23] perfomance improvements (don't redraw frame everytime) --- src/display.c | 24 +++++++++++++++++++++--- src/display.h | 4 ++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/display.c b/src/display.c index 6f5c7ce..474a49c 100644 --- a/src/display.c +++ b/src/display.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -461,16 +462,19 @@ Display_context show(Display_context dc, int value, int cap, Colors colors; Colors colors_overflow_proportional; + static int_fast8_t current_state = 0x0; + static int_fast8_t last_state = 0x0; /* Move the bar for relative positions */ - // switch (dc.geometry.bar_position) switch (dc.geometry.bar_position) { case POSITION_RELATIVE_FOCUS: move_resize_to_focused_monitor(&dc); + current_state ^= STATE_SIZE; break; case POSITION_RELATIVE_POINTER: move_resize_to_pointer_monitor(&dc); + current_state ^= STATE_SIZE; break; case POSITION_COMBINED: case POSITION_SPECIFIED: @@ -488,29 +492,43 @@ Display_context show(Display_context dc, int value, int cap, { case NORMAL: colors_overflow_proportional = dc.colorscheme.normal; + current_state &= ~STATE_ALT; if (value <= cap) + { colors = dc.colorscheme.normal; + current_state &= ~STATE_OVERFLOW; + } else { colors = dc.colorscheme.overflow; colors_overflow_proportional.bg = colors.fg; + current_state |= STATE_OVERFLOW; } break; case ALTERNATIVE: colors_overflow_proportional = dc.colorscheme.alt; + current_state |= STATE_ALT; if (value <= cap) + { colors = dc.colorscheme.alt; + current_state &= ~STATE_OVERFLOW; + } else { colors = dc.colorscheme.altoverflow; colors_overflow_proportional.bg = colors.fg; + current_state |= STATE_OVERFLOW; } break; } - /* Empty bar */ - draw_empty(dc.x, dc.geometry, colors); + if (!dc.x.mapped || last_state != current_state) + { + /* Empty bar */ + draw_empty(dc.x, dc.geometry, colors); + } + last_state = current_state; /* Proportional overflow : draw separator */ if (value > cap && overflow_mode == PROPORTIONAL && diff --git a/src/display.h b/src/display.h index 2c06d72..a1b20bc 100644 --- a/src/display.h +++ b/src/display.h @@ -22,6 +22,10 @@ #include #include +#define STATE_ALT (0x1) +#define STATE_OVERFLOW (0x1 << 1) +#define STATE_SIZE (0x1 << 2) + typedef enum { POSITION_RELATIVE_FOCUS, From 77fc933dcfe1a5a2d3c7d67170fb2c32db48bccd Mon Sep 17 00:00:00 2001 From: Megtev Date: Tue, 19 Jul 2022 18:05:38 +0300 Subject: [PATCH 22/23] use pointers for display_context in show, hide and display_context_destroy functions --- src/display.c | 72 +++++++++++++++++++++++---------------------------- src/display.h | 9 ++++--- src/main.c | 9 +++---- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/display.c b/src/display.c index 474a49c..9b8a3a5 100644 --- a/src/display.c +++ b/src/display.c @@ -449,31 +449,29 @@ Display_context init(Style conf) } /* PUBLIC Cleans the X memory buffers. */ -void display_context_destroy(Display_context dc) +void display_context_destroy(Display_context *pdc) { - XCloseDisplay(dc.x.display); + XCloseDisplay(pdc->x.display); } /* PUBLIC Show a bar filled at value/cap in normal or alternative mode */ -Display_context show(Display_context dc, int value, int cap, - Overflow_mode overflow_mode, Show_mode show_mode) +void show(Display_context *pdc, int value, int cap, Overflow_mode overflow_mode, + Show_mode show_mode) { - Display_context newdc = dc; - Colors colors; Colors colors_overflow_proportional; static int_fast8_t current_state = 0x0; static int_fast8_t last_state = 0x0; /* Move the bar for relative positions */ - switch (dc.geometry.bar_position) + switch (pdc->geometry.bar_position) { case POSITION_RELATIVE_FOCUS: - move_resize_to_focused_monitor(&dc); + move_resize_to_focused_monitor(pdc); current_state ^= STATE_SIZE; break; case POSITION_RELATIVE_POINTER: - move_resize_to_pointer_monitor(&dc); + move_resize_to_pointer_monitor(pdc); current_state ^= STATE_SIZE; break; case POSITION_COMBINED: @@ -481,85 +479,81 @@ Display_context show(Display_context dc, int value, int cap, break; } - if (!dc.x.mapped) + if (!pdc->x.mapped) { - XMapWindow(dc.x.display, dc.x.window); - XRaiseWindow(dc.x.display, dc.x.window); - newdc.x.mapped = True; + XMapWindow(pdc->x.display, pdc->x.window); + XRaiseWindow(pdc->x.display, pdc->x.window); + pdc->x.mapped = True; + current_state ^= STATE_MAPPED; } switch (show_mode) { case NORMAL: - colors_overflow_proportional = dc.colorscheme.normal; + colors_overflow_proportional = pdc->colorscheme.normal; current_state &= ~STATE_ALT; if (value <= cap) { - colors = dc.colorscheme.normal; + colors = pdc->colorscheme.normal; current_state &= ~STATE_OVERFLOW; } else { - colors = dc.colorscheme.overflow; + colors = pdc->colorscheme.overflow; colors_overflow_proportional.bg = colors.fg; current_state |= STATE_OVERFLOW; } break; case ALTERNATIVE: - colors_overflow_proportional = dc.colorscheme.alt; + colors_overflow_proportional = pdc->colorscheme.alt; current_state |= STATE_ALT; if (value <= cap) { - colors = dc.colorscheme.alt; + colors = pdc->colorscheme.alt; current_state &= ~STATE_OVERFLOW; } else { - colors = dc.colorscheme.altoverflow; + colors = pdc->colorscheme.altoverflow; colors_overflow_proportional.bg = colors.fg; current_state |= STATE_OVERFLOW; } break; } - if (!dc.x.mapped || last_state != current_state) + if (last_state != current_state) { /* Empty bar */ - draw_empty(dc.x, dc.geometry, colors); + draw_empty(pdc->x, pdc->geometry, colors); } last_state = current_state; /* Proportional overflow : draw separator */ if (value > cap && overflow_mode == PROPORTIONAL && - cap * dc.geometry.length / value > dc.geometry.padding) + cap * pdc->geometry.length / value > pdc->geometry.padding) { - draw_content(dc.x, dc.geometry, cap * dc.geometry.length / value, + draw_content(pdc->x, pdc->geometry, cap * pdc->geometry.length / value, colors_overflow_proportional); - draw_separator(dc.x, dc.geometry, cap * dc.geometry.length / value, - colors.bg); + draw_separator(pdc->x, pdc->geometry, + cap * pdc->geometry.length / value, colors.bg); } else // Value is less then cap /* Content */ - draw_content(dc.x, dc.geometry, - fit_in(value, 0, cap) * dc.geometry.length / cap, colors); - - XFlush(dc.x.display); + draw_content(pdc->x, pdc->geometry, + fit_in(value, 0, cap) * pdc->geometry.length / cap, + colors); - return newdc; + XFlush(pdc->x.display); } /* PUBLIC Hide the window */ -Display_context hide(Display_context dc) +void hide(Display_context *pdc) { - Display_context newdc = dc; - - if (dc.x.mapped) + if (pdc->x.mapped) { - XUnmapWindow(dc.x.display, dc.x.window); - newdc.x.mapped = False; - XFlush(dc.x.display); + XUnmapWindow(pdc->x.display, pdc->x.window); + pdc->x.mapped = False; + XFlush(pdc->x.display); } - - return newdc; } diff --git a/src/display.h b/src/display.h index a1b20bc..e3c41a6 100644 --- a/src/display.h +++ b/src/display.h @@ -25,6 +25,7 @@ #define STATE_ALT (0x1) #define STATE_OVERFLOW (0x1 << 1) #define STATE_SIZE (0x1 << 2) +#define STATE_MAPPED (0x1 << 3) typedef enum { @@ -93,10 +94,10 @@ typedef struct } Display_context; Display_context init(Style conf); -Display_context show(Display_context dc, int value, int cap, - Overflow_mode overflow_mode, Show_mode show_mode); -Display_context hide(Display_context dc); -void display_context_destroy(Display_context dc); +void show(Display_context *pdc, int value, int cap, Overflow_mode overflow_mode, + Show_mode show_mode); +void hide(Display_context *pdc); +void display_context_destroy(Display_context *pdc); /* Draw a rectangle with the given size, position and color */ void fill_rectangle(X_context xc, Color c, int x, int y, unsigned int w, diff --git a/src/main.c b/src/main.c index 1a3eb6a..a33bdb7 100644 --- a/src/main.c +++ b/src/main.c @@ -206,7 +206,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); case 0: /* Time to hide the gauge */ - display_context = hide(display_context); + hide(&display_context); displayed = false; break; default: @@ -214,9 +214,8 @@ int main(int argc, char *argv[]) input_value = parse_input(); if (input_value.valid) { - display_context = - show(display_context, input_value.value, cap, - style.overflow, input_value.show_mode); + show(&display_context, input_value.value, cap, + style.overflow, input_value.show_mode); printf("Update: %d/%d %s\n", input_value.value, cap, (input_value.show_mode == ALTERNATIVE) ? "[ALT]" : ""); @@ -233,7 +232,7 @@ int main(int argc, char *argv[]) } /* Clean the memory */ - display_context_destroy(display_context); + display_context_destroy(&display_context); } return EXIT_SUCCESS; } From a714f635a9c97506612487552cd1264a4b1a83a0 Mon Sep 17 00:00:00 2001 From: Megtev Date: Wed, 20 Jul 2022 12:58:01 +0300 Subject: [PATCH 23/23] improve perfomance for relative bars --- src/display.c | 7 ++++--- src/display.h | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/display.c b/src/display.c index 9b8a3a5..4623357 100644 --- a/src/display.c +++ b/src/display.c @@ -463,16 +463,16 @@ void show(Display_context *pdc, int value, int cap, Overflow_mode overflow_mode, static int_fast8_t current_state = 0x0; static int_fast8_t last_state = 0x0; + int old_length = pdc->geometry.length; + /* Move the bar for relative positions */ switch (pdc->geometry.bar_position) { case POSITION_RELATIVE_FOCUS: move_resize_to_focused_monitor(pdc); - current_state ^= STATE_SIZE; break; case POSITION_RELATIVE_POINTER: move_resize_to_pointer_monitor(pdc); - current_state ^= STATE_SIZE; break; case POSITION_COMBINED: case POSITION_SPECIFIED: @@ -522,7 +522,8 @@ void show(Display_context *pdc, int value, int cap, Overflow_mode overflow_mode, break; } - if (last_state != current_state) + /* Redraw empty bar only if needed */ + if (last_state != current_state || old_length != pdc->geometry.length) { /* Empty bar */ draw_empty(pdc->x, pdc->geometry, colors); diff --git a/src/display.h b/src/display.h index e3c41a6..02327a1 100644 --- a/src/display.h +++ b/src/display.h @@ -24,8 +24,7 @@ #define STATE_ALT (0x1) #define STATE_OVERFLOW (0x1 << 1) -#define STATE_SIZE (0x1 << 2) -#define STATE_MAPPED (0x1 << 3) +#define STATE_MAPPED (0x1 << 2) typedef enum {