/* Copyright 2021 Dakshinamurthy Karra (dakshinamurthy.karra@jaliansystems.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "intern.h" /* get_focus_point -- get the focus point to select monitor {{{ */ static void get_focus_point(Display *display, int *x_ret, int *y_ret) { int revert_to; XWindowAttributes attr; Window wid ; FUNCTION_START(); *x_ret = *y_ret = 0; XGetInputFocus(display, &wid, &revert_to); if (wid != None && XGetWindowAttributes(display, wid, &attr) != 0) { int x, y; Window unused_child; /* The coordinates in attr are relative to the parent window. If * the parent window is the root window, then the coordinates are * correct. If the parent window isn't the root window --- which * is likely --- then we translate them. */ Window parent; Window root; Window* children; unsigned int nchildren; XQueryTree(display, wid, &root, &parent, &children, &nchildren); if (children != NULL) { XFree(children); } if (parent == attr.root) { x = attr.x; y = attr.y; } else { XTranslateCoordinates(display, wid, attr.root, attr.x, attr.y, &x, &y, &unused_child); } if (x_ret != NULL) { *x_ret = x; } if (y_ret != NULL) { *y_ret = y; } } DEBUG_MSG(Dvalue, "FocusPoint { x = %d, y = %d }", *x_ret, *y_ret); FUNCTION_END(); } /* }}} */ /* osd_init_monitor -- Initialize multihead if xinerama or xrandr available {{{ */ struct monitor { int number ; int x, y; unsigned width, height; int primary ; }; static struct monitor* get_monitors(Display *display, int *n, int use_xrandr, int use_xinerama) { FUNCTION_START(); struct monitor* r = NULL; *n = 0; #ifdef DEBUG char* used ; #endif #ifdef HAVE_LIBXRANDR if(use_xrandr) { XRRMonitorInfo *monitors = XRRGetMonitors(display, DefaultRootWindow(display), True, n); if(monitors != NULL) { r = calloc(*n, sizeof(struct monitor)); for(int i = 0; i < *n; i++) { r[i].number = i; r[i].primary = monitors[i].primary; r[i].x = monitors[i].x; r[i].y = monitors[i].y; r[i].width = monitors[i].width; r[i].height = monitors[i].height; } XRRFreeMonitors(monitors); #ifdef HAVE_LIBXINERAMA use_xinerama = 0; #endif #ifdef DEBUG used = "Xrandr"; #endif } } #endif #ifdef HAVE_LIBXINERAMA if(use_xinerama) { int dummy_a, dummy_b; XineramaScreenInfo *screeninfo = NULL; if (XineramaQueryExtension(display, &dummy_a, &dummy_b) && (screeninfo = XineramaQueryScreens(display, n)) && XineramaIsActive(display)) { r = calloc(*n, sizeof(struct monitor)); for(int i = 0; i < *n; i++) { r[i].number = i; r[i].primary = 1; /* All monitors are promary */ r[i].x = screeninfo[i].x_org; r[i].y = screeninfo[i].y_org; r[i].width = screeninfo[i].width; r[i].height = screeninfo[i].height; } } if (screeninfo) XFree(screeninfo); #ifdef DEBUG used = "Xinerama" ; #endif } #endif if(r == NULL) { DEBUG_MSG(Dvalue, "GetMonitors { }"); } else { DEBUG_MSG(Dvalue, "GetMonitors { driver: %s, monitors: %d }", used, *n); } FUNCTION_END(); return r; } int osd_init_monitor(Display *display, int screen, int default_monitor, int use_xrandr, int use_xinerama, unsigned int *width, unsigned int *height, int *xpos, int *ypos) { FUNCTION_START(); int monitor = default_monitor; int n; int i; struct monitor *monitors; int focus_x = 0, focus_y = 0; *width = XDisplayWidth(display, screen); *height = XDisplayHeight(display, screen); *xpos = 0; *ypos = 0; monitors = get_monitors(display, &n, use_xrandr, use_xinerama); if(monitors == NULL || n <= 0) return 0; if(monitor > n && monitor != ACTIVE && monitor != PRIMARY) { free(monitors); FUNCTION_END(); fail(-1, "Invalid monitor selection"); } if(monitor == -1 || monitor == ACTIVE) { monitor = 0; get_focus_point(display, &focus_x, &focus_y); for (i = 0; i < n; i++) { if (focus_x >= monitors[i].x && focus_x < monitors[i].x + monitors[i].width && focus_y >= monitors[i].y && focus_y < monitors[i].y + monitors[i].height) { monitor = i; break; } } } else if (monitor == PRIMARY) { monitor = 0; for (i = 0; i < n; i++) { if (monitors[i].primary) { monitor = i; break; } } } *width = monitors[monitor].width; *height = monitors[monitor].height; *xpos = monitors[monitor].x; *ypos = monitors[monitor].y; FUNCTION_END(); return 0; } /* {{{ vim: foldmethod=marker tabstop=2 shiftwidth=2 expandtab }}} */