int get_monitor_dims(int *ret_left_x, int *ret_right_x, int *ret_top_y, int *ret_bottom_y, int i) { Display *display; if (!(display = XOpenDisplay(0))) { return ERR_COULDNT_OPEN_X_DISPLAY; } XRRScreenResources *screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); *ret_left_x = INT_MAX; *ret_right_x = INT_MIN; *ret_top_y = INT_MAX; *ret_bottom_y = INT_MIN; int nmonitors = 0; XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors); /* If the user requests a screen outside of the number of monitors, exit */ if (i >= nmonitors) { return ERR_MONITOR_DNE; } XRRCrtcInfo *screen_info = XRRGetCrtcInfo(display, screen_res, screen_res->crtcs[i]); *ret_left_x = screen_info->x; *ret_right_x = screen_info->x + screen_info->width; *ret_top_y = screen_info->y; *ret_bottom_y = screen_info->y + screen_info->height; return 0; }
int get_monitor_dims_of_focused_screen(int use_anchors, int *ret_left_x, int *ret_right_x, int *ret_top_y, int *ret_bottom_y) { Display *dpy; if (!(dpy = XOpenDisplay(0))) { return ERR_COULDNT_OPEN_X_DISPLAY; } /* Get currently focused window */ Window win = -1; int focus_status; XGetInputFocus(dpy, &win, &focus_status); if (win == PointerRoot || win == None) { return ERR_WIN_NOT_FOUND; } XRRScreenResources *screen_res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy)); XWindowAttributes win_attr; XGetWindowAttributes(dpy, win, &win_attr); int det_x = 0; int det_y = 0; int nmonitors = 0; XRRGetMonitors(dpy, win, 1, &nmonitors); for (int i = 0; i < nmonitors; i++) { XRRCrtcInfo *screen_info = XRRGetCrtcInfo(dpy, screen_res, screen_res->crtcs[i]); /* option flag for using the "anchor" (top left corner) of a window * to determine what screen it belongs to */ if (use_anchors == 1) { det_x = win_attr.x; det_y = win_attr.y; /* Use the center of the window to determine what screen it's on */ } else { det_x = win_attr.x + ((win_attr.width)/2); det_y = win_attr.y + ((win_attr.height)/2); } /* If the window is on the ith screen in the x */ if (det_x >= screen_info->x && det_x < (screen_info->x + screen_info->width)) { /* If the window is on the ith screen in the y */ if (det_y >= screen_info->y && det_y < (screen_info->y + screen_info->height)) { *ret_left_x = screen_info->x; *ret_right_x = screen_info->x + screen_info->width; *ret_top_y = screen_info->y; *ret_bottom_y = screen_info->y + screen_info->height; return 0; } } } /* If the function has not returned yet, then it could not find a screen * on which 'win' resides. */ return ERR_SCREEN_OF_WIN_NOT_FOUND; }
/** Returns an int of 0 if it succeeds in finding the screen number of a * given Window or an int representing the error it ran into. * win the Window we are trying to find the screen of. * *dpy pointer to the Display we will be searching on. * *return_screen_num pointer to an int where the function will fill in the * screen number that 'win' belongs to, if it can be found. * This function will return 0 if it was able to find the screen 'win' belongs * to. If it cannot, then it will return the correct * error code for window-not-found. */ int get_screen_number_of_win(Window win, Display *dpy, int use_anchors, \ int *return_screen_num) { XRRScreenResources *screen_res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy)); XWindowAttributes win_attr; XGetWindowAttributes(dpy, win, &win_attr); int det_x = 0; int det_y = 0; int nmonitors = 0; XRRGetMonitors(dpy, win, 1, &nmonitors); for (int i = 0; i < nmonitors; i++) { XRRCrtcInfo *screen_info = XRRGetCrtcInfo(dpy, screen_res, screen_res->crtcs[i]); /* option flag for using the "anchor" (top left corner) of a window * to determine what screen it belongs to */ if (use_anchors == 1) { det_x = win_attr.x; det_y = win_attr.y; /* Use the center of the window to determine what screen it's on */ } else { det_x = win_attr.x + ((win_attr.width)/2); det_y = win_attr.y + ((win_attr.height)/2); } /* If the window is on the ith screen in the x */ if (det_x >= screen_info->x && det_x < (screen_info->x + screen_info->width)) { /* If the window is on the ith screen in the y */ if (det_y >= screen_info->y && det_y < (screen_info->y + screen_info->height)) { *return_screen_num = i; return 0; } } } /* If the function has not returned yet, then it could not find a screen * on which 'win' resides. */ return ERR_SCREEN_OF_WIN_NOT_FOUND; }
int get_full_display_dims(int *ret_left_x, int *ret_right_x, int *ret_top_y, int *ret_bottom_y) { Display *display; if (!(display = XOpenDisplay(0))) { return ERR_COULDNT_OPEN_X_DISPLAY; } XRRScreenResources *screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); *ret_left_x = INT_MAX; *ret_right_x = INT_MIN; *ret_top_y = INT_MAX; *ret_bottom_y = INT_MIN; int nmonitors = 0; XRRGetMonitors(display, DefaultRootWindow(display), 1, &nmonitors); for (int i = 0; i < nmonitors; i++) { XRRCrtcInfo *screen_info = XRRGetCrtcInfo(display, screen_res, screen_res->crtcs[i]); fprintf(stdout, "%d %d %d %d\n", screen_info->x, screen_info->y, screen_info->width, screen_info->height); if (screen_info->x < *ret_left_x) { *ret_left_x = screen_info->x; } if (((long) (screen_info->x + screen_info->width)) > *ret_right_x) { *ret_right_x = screen_info->x + screen_info->width; } if (screen_info->y < *ret_top_y) { *ret_top_y = screen_info->y; } if (((long) (screen_info->y + screen_info->height)) > *ret_bottom_y) { *ret_bottom_y = screen_info->y + screen_info->height; } } return 0; }
static gboolean init_randr15 (GdkScreen *screen, gboolean *changed) { #ifdef HAVE_RANDR15 GdkDisplay *display = gdk_screen_get_display (screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; gboolean randr12_compat = FALSE; XRRMonitorInfo *rr_monitors; int num_rr_monitors; int old_primary; if (!x11_display->have_randr15) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; rr_monitors = XRRGetMonitors (x11_screen->xdisplay, x11_screen->xroot_window, True, &num_rr_monitors); if (!rr_monitors) return FALSE; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } for (i = 0; i < num_rr_monitors; i++) { RROutput output = rr_monitors[i].outputs[0]; XRROutputInfo *output_info; GdkX11Monitor *monitor; GdkRectangle geometry; GdkRectangle newgeo; char *name; int refresh_rate = 0; gdk_x11_display_error_trap_push (display); output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); if (gdk_x11_display_error_trap_pop (display)) continue; if (output_info == NULL) continue; /* Non RandR1.2+ X driver have output name "default" */ randr12_compat |= !g_strcmp0 (output_info->name, "default"); if (output_info->connection == RR_Disconnected) { XRRFreeOutputInfo (output_info); continue; } if (first_output == None) first_output = output; if (output_info->crtc) { XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); int j; for (j = 0; j < resources->nmode; j++) { XRRModeInfo *xmode = &resources->modes[j]; if (xmode->id == crtc->mode) { if (xmode->hTotal != 0 && xmode->vTotal != 0) refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal * xmode->vTotal); break; } } XRRFreeCrtcInfo (crtc); } monitor = find_monitor_by_output (x11_display, output); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (GDK_TYPE_X11_MONITOR, "display", display, NULL); monitor->output = output; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); name = g_strndup (output_info->name, output_info->nameLen); newgeo.x = rr_monitors[i].x / x11_screen->window_scale; newgeo.y = rr_monitors[i].y / x11_screen->window_scale; newgeo.width = rr_monitors[i].width / x11_screen->window_scale; newgeo.height = rr_monitors[i].height / x11_screen->window_scale; if (newgeo.x != geometry.x || newgeo.y != geometry.y || newgeo.width != geometry.width || newgeo.height != geometry.height || rr_monitors[i].mwidth != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || rr_monitors[i].mheight != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor)))) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), rr_monitors[i].mwidth, rr_monitors[i].mheight); gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), translate_subpixel_order (output_info->subpixel_order)); gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); gdk_monitor_set_model (GDK_MONITOR (monitor), name); g_free (name); if (rr_monitors[i].primary) primary_output = monitor->output; XRRFreeOutputInfo (output_info); } XRRFreeMonitors (rr_monitors); XRRFreeScreenResources (resources); /* non RandR 1.2+ X driver doesn't return any usable multihead data */ if (randr12_compat) { for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->remove) gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); } g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len); return FALSE; } for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (display, GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } old_primary = x11_display->primary_monitor; x11_display->primary_monitor = 0; for (i = 0; i < x11_display->monitors->len; ++i) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->output == primary_output) { x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (monitor->output == first_output) x11_display->primary_monitor = i; } if (x11_display->primary_monitor != old_primary) *changed = TRUE; return x11_display->monitors->len > 0; #endif return FALSE; }