From eeeb0d672a91fa6e02aea13fde33cfee289a7069 Mon Sep 17 00:00:00 2001 From: Vlad Glagolev Date: Sat, 11 Aug 2018 17:37:28 -0700 Subject: jgmenu: added xrandr support --- wm-addons/jgmenu/CONFIGURE | 4 +- wm-addons/jgmenu/DEPENDS | 8 +- wm-addons/jgmenu/HISTORY | 6 ++ wm-addons/jgmenu/PRE_BUILD | 5 ++ wm-addons/jgmenu/at-pointer.patch | 104 ++++++++++++++++++++++++++ wm-addons/jgmenu/xrandr.patch | 150 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 wm-addons/jgmenu/at-pointer.patch create mode 100644 wm-addons/jgmenu/xrandr.patch (limited to 'wm-addons') diff --git a/wm-addons/jgmenu/CONFIGURE b/wm-addons/jgmenu/CONFIGURE index 7ae3323c6d..13a78b1465 100755 --- a/wm-addons/jgmenu/CONFIGURE +++ b/wm-addons/jgmenu/CONFIGURE @@ -1 +1,3 @@ -config_query JGMENU_SINGLE_WINDOW "Re-enable single window mode option?" n +config_query JGMENU_SINGLE_WINDOW "Re-enable single window mode option?" n && + +config_query JGMENU_XRANDR "Use modern Xrandr extension instead of Xinerama?" n diff --git a/wm-addons/jgmenu/DEPENDS b/wm-addons/jgmenu/DEPENDS index 855583f8af..0f50a37421 100755 --- a/wm-addons/jgmenu/DEPENDS +++ b/wm-addons/jgmenu/DEPENDS @@ -1,6 +1,12 @@ depends libpng && depends libx11 && -depends libxinerama && + +if [ ${JGMENU_XRANDR} == y ]; then + depends libxrandr +else + depends libxinerama +fi && + depends pango && depends cairo && depends librsvg2 && diff --git a/wm-addons/jgmenu/HISTORY b/wm-addons/jgmenu/HISTORY index 29a8658601..ede90b5ec4 100644 --- a/wm-addons/jgmenu/HISTORY +++ b/wm-addons/jgmenu/HISTORY @@ -1,3 +1,9 @@ +2018-08-11 Vlad Glagolev + * CONFIGURE, DEPENDS: added xrandr option + * PRE_BUILD: apply patches + * at-pointer.patch, xrandr.patch: added, official patches for optional + xrandr support + 2018-04-06 Vlad Glagolev * CONFIGURE: added, for single window mode option * PRE_BUILD: added, to apply patch diff --git a/wm-addons/jgmenu/PRE_BUILD b/wm-addons/jgmenu/PRE_BUILD index 064396da95..2af9ca2483 100755 --- a/wm-addons/jgmenu/PRE_BUILD +++ b/wm-addons/jgmenu/PRE_BUILD @@ -1,6 +1,11 @@ default_pre_build && cd "${SOURCE_DIRECTORY}" && +if [ ${JGMENU_XRANDR} == y ]; then + patch -p1 < "${SPELL_DIRECTORY}/at-pointer.patch" && + patch -p1 < "${SPELL_DIRECTORY}/xrandr.patch" +fi && + if [ ${JGMENU_SINGLE_WINDOW} == y ]; then patch -p1 < "${SPELL_DIRECTORY}/single_window.patch" fi diff --git a/wm-addons/jgmenu/at-pointer.patch b/wm-addons/jgmenu/at-pointer.patch new file mode 100644 index 0000000000..aed6c7f5a1 --- /dev/null +++ b/wm-addons/jgmenu/at-pointer.patch @@ -0,0 +1,104 @@ +From 1e0bae4e0bacbb0570ac2181055ce628748d35ee Mon Sep 17 00:00:00 2001 +From: Johan Malm +Date: Thu, 17 May 2018 18:28:36 +0100 +Subject: [PATCH] multi-monitor: launch correctly 'at-pointer' (issue #56) + +Update screen dimensions before launching when in at_pointer mode in +order to use the correct x0, y0, width and height. +--- + geometry.c | 12 ++++++++---- + geometry.h | 1 + + jgmenu.c | 1 + + x11-ui.c | 15 +++++++++++++++ + 4 files changed, 25 insertions(+), 4 deletions(-) + +diff --git a/geometry.c b/geometry.c +index 55aa737..541ac2e 100644 +--- a/geometry.c ++++ b/geometry.c +@@ -133,6 +133,13 @@ static void geo_update(void) + update_sub_window(); + } + ++void geo_update_monitor_coords(void) ++{ ++ ui_get_screen_res(&screen_x0, &screen_y0, &screen_width, ++ &screen_height, config.monitor); ++ geo_update(); ++} ++ + void geo_init(void) + { + /* +@@ -155,10 +162,7 @@ void geo_init(void) + item_margin_x = 4; + item_margin_y = 4; + +- ui_get_screen_res(&screen_x0, &screen_y0, &screen_width, +- &screen_height, config.monitor); +- +- geo_update(); ++ geo_update_monitor_coords(); + } + + int geo_get_item_coordinates(struct area *a) +diff --git a/geometry.h b/geometry.h +index f0647f9..ce57adf 100644 +--- a/geometry.h ++++ b/geometry.h +@@ -47,6 +47,7 @@ + #include "x11-ui.h" + #include "align.h" + ++void geo_update_monitor_coords(void); + void geo_init(void); + int geo_get_item_coordinates(struct area *a); + struct point geo_get_max_itemarea_that_fits(void); +diff --git a/jgmenu.c b/jgmenu.c +index 7b75cec..9b41ea4 100644 +--- a/jgmenu.c ++++ b/jgmenu.c +@@ -809,6 +809,7 @@ void launch_menu_at_pointer(void) + struct point pos; + struct area wa; + ++ geo_update_monitor_coords(); + XQueryPointer(ui->dpy, DefaultRootWindow(ui->dpy), &dw, &dw, &di, &di, + &pos.x, &pos.y, &du); + +diff --git a/x11-ui.c b/x11-ui.c +index edc6bde..3404f84 100644 +--- a/x11-ui.c ++++ b/x11-ui.c +@@ -131,6 +131,17 @@ void ui_init(void) + ui->root = RootWindow(ui->dpy, ui->screen); + } + ++static void print_screen_info(int n, XineramaScreenInfo *screen_info) ++{ ++ int i; ++ ++ info("%d monitor(s) detected", n); ++ for (i = 0; i < n; i++) ++ printf(" - monitor-%d: x0=%d; y0=%d; w=%d; h=%d\n", ++ i + 1, screen_info[i].x_org, screen_info[i].y_org, ++ screen_info[i].width, screen_info[i].height); ++} ++ + #define INTERSECT(x, y, w, h, r) (MAX(0, MIN((x) + (w), (r).x_org + (r).width) - \ + MAX((x), (r).x_org)) &&\ + MAX(0, MIN((y) + (h), (r).y_org + (r).height) - \ +@@ -146,9 +157,13 @@ void ui_get_screen_res(int *x0, int *y0, int *width, int *height, int monitor) + screen_info = XineramaQueryScreens(ui->dpy, &n); + BUG_ON(!screen_info); + XQueryPointer(ui->dpy, ui->root, &dw, &dw, &x, &y, &di, &di, &du); ++ if (getenv("JGMENU_SCREEN_INFO")) ++ print_screen_info(n, screen_info); + for (i = 0; i < n; i++) + if (INTERSECT(x, y, 1, 1, screen_info[i])) + break; ++ ++ /* handle user specified monitor (from config file) */ + if (monitor) { + if (monitor > n) + die("cannot connect to monitor '%d' (max %d)", monitor, n); diff --git a/wm-addons/jgmenu/xrandr.patch b/wm-addons/jgmenu/xrandr.patch new file mode 100644 index 0000000000..71047a30a8 --- /dev/null +++ b/wm-addons/jgmenu/xrandr.patch @@ -0,0 +1,150 @@ +From f8ccef404fe8436e4473e48cfa66d8389286e234 Mon Sep 17 00:00:00 2001 +From: Johan Malm +Date: Sat, 11 Aug 2018 13:45:35 +0100 +Subject: [PATCH] x11-ui.c: replace xinerama with xrandr (issue #60) + +xinerama has been reported to segfault with some new graphics cards. + +Suggested-by: @vaygr +--- + Makefile.inc | 2 +- + x11-ui.c | 91 +++++++++++++++++++++++++++++++++++----------------- + 2 files changed, 63 insertions(+), 30 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index b33b399..9f362c8 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -23,7 +23,7 @@ jgmenu-ob: CFLAGS += `xml2-config --cflags` + jgmenu-xdg: CFLAGS += `xml2-config --cflags` + jgmenu-lx: CFLAGS += `pkg-config --cflags glib-2.0 libmenu-cache` + +-jgmenu: LIBS += `pkg-config x11 xinerama cairo pango pangocairo librsvg-2.0 --libs` ++jgmenu: LIBS += `pkg-config x11 xrandr cairo pango pangocairo librsvg-2.0 --libs` + jgmenu: LIBS += -pthread -lrt -lpng + jgmenu-ob: LIBS += `xml2-config --libs` + jgmenu-xdg: LIBS += `xml2-config --libs` +diff --git a/x11-ui.c b/x11-ui.c +index 7ed7678..e6df14d 100644 +--- a/x11-ui.c ++++ b/x11-ui.c +@@ -16,7 +16,7 @@ + #include + #include + #include +-#include ++#include + #include /* for usleep */ + + #include "x11-ui.h" +@@ -131,49 +131,82 @@ void ui_init(void) + ui->root = RootWindow(ui->dpy, ui->screen); + } + +-static void print_screen_info(int n, XineramaScreenInfo *screen_info) ++static void print_screen_info(void) + { +- int i; +- +- info("%d monitor(s) detected", n); +- for (i = 0; i < n; i++) +- printf(" - monitor-%d: x0=%d; y0=%d; w=%d; h=%d\n", +- i + 1, screen_info[i].x_org, screen_info[i].y_org, +- screen_info[i].width, screen_info[i].height); ++ int i, n; ++ XRRScreenResources *sr; ++ XRRCrtcInfo *ci = NULL; ++ ++ sr = XRRGetScreenResources(ui->dpy, DefaultRootWindow(ui->dpy)); ++ n = sr->noutput; ++ info("%d xrandr outputs(s) detected", n); ++ for (i = 0; i < n; i++) { ++ ci = XRRGetCrtcInfo(ui->dpy, sr, sr->crtcs[i]); ++ if (!ci->width || !ci->height) ++ printf(" - monitor-%d: not connected\n", i + 1); ++ else ++ printf(" - monitor-%d: x0=%d; y0=%d; w=%d; h=%d\n", ++ i + 1, ci->x, ci->y, ci->width, ci->height); ++ } ++ XRRFreeCrtcInfo(ci); ++ XRRFreeScreenResources(sr); + } + +-#define INTERSECT(x, y, w, h, r) (MAX(0, MIN((x) + (w), (r).x_org + (r).width) - \ +- MAX((x), (r).x_org)) &&\ +- MAX(0, MIN((y) + (h), (r).y_org + (r).height) - \ +- MAX((y), (r).y_org))) ++static int intersect(int x, int y, int w, int h, XRRCrtcInfo *ci) ++{ ++ return MAX(0, MIN(x + w, (int)ci->x + (int)ci->width) - MAX(x, (int)ci->x)) && ++ MAX(0, MIN(y + h, (int)ci->y + (int)ci->height) - MAX(y, (int)ci->y)); ++} + + void ui_get_screen_res(int *x0, int *y0, int *width, int *height, int monitor) + { + int i, n, x, y, di; + unsigned int du; + Window dw; +- XineramaScreenInfo *screen_info; ++ XRRScreenResources *sr; ++ XRRCrtcInfo *ci = NULL; + +- screen_info = XineramaQueryScreens(ui->dpy, &n); +- BUG_ON(!screen_info); +- XQueryPointer(ui->dpy, ui->root, &dw, &dw, &x, &y, &di, &di, &du); + if (getenv("JGMENU_SCREEN_INFO")) +- print_screen_info(n, screen_info); +- for (i = 0; i < n; i++) +- if (INTERSECT(x, y, 1, 1, screen_info[i])) +- break; ++ print_screen_info(); ++ sr = XRRGetScreenResources(ui->dpy, DefaultRootWindow(ui->dpy)); ++ BUG_ON(!sr); ++ n = sr->noutput; + +- /* handle user specified monitor (from config file) */ ++ /* ++ * Global variable config.monitor let's the user specify a monitor. ++ * If not set, we use the current pointer position ++ */ + if (monitor) { + if (monitor > n) +- die("cannot connect to monitor '%d' (max %d)", monitor, n); +- i = monitor - 1; ++ die("cannot connect to monitor '%d'", monitor); ++ ci = XRRGetCrtcInfo(ui->dpy, sr, sr->crtcs[monitor - 1]); ++ if (!ci->width || !ci->height) ++ die("cannot connect to monitor '%d'", monitor); ++ info("using user specified monitor '%d'", monitor); ++ goto monitor_selected; ++ } ++ ++ XQueryPointer(ui->dpy, ui->root, &dw, &dw, &x, &y, &di, &di, &du); ++ for (i = 0; i < n; i++) { ++ ci = XRRGetCrtcInfo(ui->dpy, sr, sr->crtcs[i]); ++ BUG_ON(!ci); ++ if (!ci->width || !ci->height) ++ continue; ++ if (intersect(x, y, 1, 1, ci)) { ++ info("using monitor '%d'", i + 1); ++ break; ++ } + } +- *x0 = screen_info[i].x_org; +- *y0 = screen_info[i].y_org; +- *width = screen_info[i].width; +- *height = screen_info[i].height; +- XFree(screen_info); ++ ++monitor_selected: ++ if (!ci) ++ die("connection could be established to monitor"); ++ *x0 = ci->x; ++ *y0 = ci->y; ++ *width = ci->width; ++ *height = ci->height; ++ XRRFreeCrtcInfo(ci); ++ XRRFreeScreenResources(sr); + } + + void set_wm_class(void) -- cgit v1.2.3