xresize

changeset 0:8555f3aabbc7

created hg repository for xresize, useful little bugger
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 10 Mar 2011 14:58:46 +0200
parents
children a2c94df7f405
files Makefile xresize.c
diffstat 2 files changed, 274 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Makefile	Thu Mar 10 14:58:46 2011 +0200
     1.3 @@ -0,0 +1,13 @@
     1.4 +obj = xresize.o
     1.5 +bin = xresize
     1.6 +
     1.7 +CC = gcc
     1.8 +CFLAGS = -pedantic -Wall -g -I/usr/X11R6/include -DUSE_XRANDR -DUSE_XF86VM
     1.9 +LDFLAGS = -L/usr/X11R6/lib -lX11 -lXrandr -lXxf86vm
    1.10 +
    1.11 +$(bin): $(obj)
    1.12 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    1.13 +
    1.14 +.PHONY: clean
    1.15 +clean:
    1.16 +	rm -f $(obj) $(bin)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xresize.c	Thu Mar 10 14:58:46 2011 +0200
     2.3 @@ -0,0 +1,261 @@
     2.4 +#include <stdio.h>
     2.5 +#include <stdlib.h>
     2.6 +#include <string.h>
     2.7 +#include <ctype.h>
     2.8 +#include <X11/Xlib.h>
     2.9 +
    2.10 +#ifdef USE_XRANDR
    2.11 +#include <X11/extensions/Xrandr.h>
    2.12 +
    2.13 +char *randr_err_msg[] = {
    2.14 +	"RRSetConfigSuccess",
    2.15 +	"RRSetConfigInvalidConfigTime",
    2.16 +	"RRSetConfigInvalidTime",
    2.17 +	"RRSetConfigFailed"
    2.18 +};
    2.19 +#endif
    2.20 +
    2.21 +#ifdef USE_XF86VM
    2.22 +#include <X11/extensions/xf86vmode.h>
    2.23 +#endif
    2.24 +
    2.25 +int get_size(Display *dpy, int scr, int *xsz, int *ysz);
    2.26 +int set_size(Display *dpy, int scr, int xsz, int ysz);
    2.27 +
    2.28 +const char *usage = "usage: %s [options]\n"
    2.29 +	"options:\n"
    2.30 +	"  -s <w>x<h>   set specified screen size\n"
    2.31 +	"  -f           force size change without current size detection\n"
    2.32 +	"  -h           this usage information\n";
    2.33 +
    2.34 +int use_xrandr = 1;
    2.35 +int use_xf86vm = 1;
    2.36 +
    2.37 +int main(int argc, char **argv)
    2.38 +{
    2.39 +	int i, cur_xres, cur_yres, xres = -1, yres = -1;
    2.40 +	int force = 0;
    2.41 +	Display *dpy;
    2.42 +	int scr;
    2.43 +
    2.44 +	for(i=1; i<argc; i++) {
    2.45 +		if(argv[i][0] == '-' && (argv[i][2] == 0 || argv[i][1] == '-')) {
    2.46 +			char *sep;
    2.47 +
    2.48 +			switch(argv[i][1]) {
    2.49 +			case 's':
    2.50 +				if(!isdigit(argv[++i][0]) || !(sep = strchr(argv[i], 'x')) || !isdigit(*(sep + 1))) {
    2.51 +					fputs("-s must be followed by something like \"640x480\"\n", stderr);
    2.52 +					return EXIT_FAILURE;
    2.53 +				}
    2.54 +				xres = atoi(argv[i]);
    2.55 +				yres = atoi(sep + 1);
    2.56 +				break;
    2.57 +
    2.58 +			case 'f':
    2.59 +				force = 1;
    2.60 +				break;
    2.61 +
    2.62 +			case 'h':
    2.63 +				printf(usage, argv[0]);
    2.64 +				return 0;
    2.65 +
    2.66 +			case '-':
    2.67 +				if(strcmp(argv[i], "--no-xrandr") == 0) {
    2.68 +					use_xrandr = 0;
    2.69 +					break;
    2.70 +				} else if(strcmp(argv[i], "--no-xf86vm") == 0) {
    2.71 +					use_xf86vm = 0;
    2.72 +					break;
    2.73 +				}
    2.74 +				/* fallthrough to invalid arg */
    2.75 +			default:
    2.76 +				fprintf(stderr, "unrecognized option: %s, try -h for usage\n", argv[i]);
    2.77 +				return 1;
    2.78 +			}
    2.79 +		} else {
    2.80 +			fprintf(stderr, "unexpected argument: %s\n", argv[i]);
    2.81 +			return 1;
    2.82 +		}
    2.83 +	}
    2.84 +
    2.85 +	if(!(dpy = XOpenDisplay(0))) {
    2.86 +		fprintf(stderr, "failed to connect to the X server\n");
    2.87 +		return 1;
    2.88 +	}
    2.89 +	scr = DefaultScreen(dpy);
    2.90 +
    2.91 +	if(get_size(dpy, scr, &cur_xres, &cur_yres) == -1) {
    2.92 +		fprintf(stderr, "failed to retreive current screen size\n");
    2.93 +		XCloseDisplay(dpy);
    2.94 +		return 1;
    2.95 +	}
    2.96 +	printf("current size: %dx%d\n", cur_xres, cur_yres);
    2.97 +
    2.98 +	if(xres != -1) {	/* size change requested */
    2.99 +		if(xres != cur_xres || yres != cur_yres || force) {
   2.100 +			if(set_size(dpy, scr, xres, yres) == -1) {
   2.101 +				fprintf(stderr, "set_size failed\n");
   2.102 +				XCloseDisplay(dpy);
   2.103 +				return 1;
   2.104 +			}
   2.105 +			printf("size updated sucessfully\n");
   2.106 +		} else {
   2.107 +			printf("already at requested size! do nothing (use -f to force change).\n");
   2.108 +		}
   2.109 +	}
   2.110 +	XCloseDisplay(dpy);
   2.111 +	return 0;
   2.112 +}
   2.113 +
   2.114 +int get_size(Display *dpy, int scr, int *xsz, int *ysz)
   2.115 +{
   2.116 +	Window root;
   2.117 +	int event_base, error_base;
   2.118 +
   2.119 +	scr = DefaultScreen(dpy);
   2.120 +	root = RootWindow(dpy, scr);
   2.121 +
   2.122 +	/* first try r&r */
   2.123 +#ifdef USE_XRANDR
   2.124 +	if(use_xrandr && XRRQueryExtension(dpy, &event_base, &error_base)) {
   2.125 +		XRRScreenConfiguration *xrr_config;
   2.126 +		XRRScreenSize *ssizes;
   2.127 +		Rotation rot;
   2.128 +		int ssize_count, curr;
   2.129 +
   2.130 +		if(!(xrr_config = XRRGetScreenInfo(dpy, root))) {
   2.131 +			fprintf(stderr, "failed to retrieve screen configuration\n");
   2.132 +			return -1;
   2.133 +		}
   2.134 +		ssizes = XRRConfigSizes(xrr_config, &ssize_count);
   2.135 +		curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
   2.136 +
   2.137 +		*xsz = ssizes[curr].width;
   2.138 +		*ysz = ssizes[curr].height;
   2.139 +
   2.140 +		XRRFreeScreenConfigInfo(xrr_config);
   2.141 +		return 0;
   2.142 +	}
   2.143 +#endif
   2.144 +
   2.145 +	/* then try xf86vm */
   2.146 +#ifdef USE_XF86VM
   2.147 +	if(use_xf86vm && XF86VidModeQueryExtension(dpy, &event_base, &error_base)) {
   2.148 +		XF86VidModeModeLine modeline;
   2.149 +		int dot_clock;
   2.150 +
   2.151 +		if(!XF86VidModeGetModeLine(dpy, scr, &dot_clock, &modeline)) {
   2.152 +			fprintf(stderr, "failed to get current video mode\n");
   2.153 +			return -1;
   2.154 +		}
   2.155 +
   2.156 +		*xsz = modeline.hdisplay;
   2.157 +		*ysz = modeline.vdisplay;
   2.158 +
   2.159 +		if(modeline.privsize) {
   2.160 +			XFree(modeline.private);
   2.161 +		}
   2.162 +		return 0;
   2.163 +	}
   2.164 +#endif
   2.165 +
   2.166 +	fprintf(stderr, "can't get any size information\n");
   2.167 +	return -1;
   2.168 +}
   2.169 +
   2.170 +
   2.171 +int set_size(Display *dpy, int scr, int xsz, int ysz)
   2.172 +{
   2.173 +	int i, event_base, error_base;
   2.174 +	Window root;
   2.175 +
   2.176 +	root = RootWindow(dpy, scr);
   2.177 +
   2.178 +	/* first try r&r */
   2.179 +#ifdef USE_XRANDR
   2.180 +	if(use_xrandr && XRRQueryExtension(dpy, &event_base, &error_base)) {
   2.181 +		Status st;
   2.182 +		XRRScreenConfiguration *xrr_config;
   2.183 +		XRRScreenSize *ssizes;
   2.184 +		Rotation rot;
   2.185 +		int ssize_count, curr;
   2.186 +		Time timestamp, cfg_timestamp;
   2.187 +
   2.188 +		if(!(xrr_config = XRRGetScreenInfo(dpy, root))) {
   2.189 +			fprintf(stderr, "failed to retrieve screen configuration\n");
   2.190 +			return -1;
   2.191 +		}
   2.192 +		ssizes = XRRConfigSizes(xrr_config, &ssize_count);
   2.193 +		curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
   2.194 +		timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);
   2.195 +
   2.196 +		if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {
   2.197 +			XRRFreeScreenConfigInfo(xrr_config);
   2.198 +			return 0;
   2.199 +		}
   2.200 +
   2.201 +		for(i=0; i<ssize_count; i++) {
   2.202 +			if(ssizes[i].width == xsz && ssizes[i].height == ysz) {
   2.203 +				break;
   2.204 +			}
   2.205 +		}
   2.206 +		if(i == ssize_count) {
   2.207 +			fprintf(stderr, "requested size unsuppored by the X server configuration\n");
   2.208 +			XRRFreeScreenConfigInfo(xrr_config);
   2.209 +			return -1;
   2.210 +		}
   2.211 +
   2.212 +		if((st = XRRSetScreenConfig(dpy, xrr_config, root, i, rot, timestamp)) != 0) {
   2.213 +			fprintf(stderr, "failed to set resolution with r-and-r, error: %d (%s)\n", st, randr_err_msg[st]);
   2.214 +			XRRFreeScreenConfigInfo(xrr_config);
   2.215 +#ifdef USE_XF86VM
   2.216 +			printf("retrying with xf86vm...\n");
   2.217 +			goto retry_with_xf86vm;
   2.218 +#endif
   2.219 +			return -1;
   2.220 +		}
   2.221 +
   2.222 +		XRRFreeScreenConfigInfo(xrr_config);
   2.223 +		return 0;
   2.224 +	}
   2.225 +#endif
   2.226 +
   2.227 +	/*try xf86vm */
   2.228 +#ifdef USE_XF86VM
   2.229 +retry_with_xf86vm:
   2.230 +	if(use_xf86vm && XF86VidModeQueryExtension(dpy, &event_base, &error_base)) {
   2.231 +		XF86VidModeModeInfo **modes;
   2.232 +		int mode_count;
   2.233 +
   2.234 +		if(!XF86VidModeGetAllModeLines(dpy, scr, &mode_count, &modes)) {
   2.235 +			fprintf(stderr, "failed to get list of available video modes\n");
   2.236 +			return -1;
   2.237 +		}
   2.238 +
   2.239 +		for(i=0; i<mode_count; i++) {
   2.240 +			if(modes[i]->hdisplay == xsz && modes[i]->vdisplay == ysz) {
   2.241 +				break;
   2.242 +			}
   2.243 +		}
   2.244 +		if(i == mode_count) {
   2.245 +			fprintf(stderr, "requested size unsuppored by the X server configuration\n");
   2.246 +			XFree(modes);
   2.247 +			return -1;
   2.248 +		}
   2.249 +
   2.250 +		if(!XF86VidModeSwitchToMode(dpy, scr, modes[i])) {
   2.251 +			fprintf(stderr, "failed to set requested size with xf86vm\n");
   2.252 +			XFree(modes);
   2.253 +			return -1;
   2.254 +		}
   2.255 +		XF86VidModeSetViewPort(dpy, scr, 0, 0);
   2.256 +
   2.257 +		XFree(modes);
   2.258 +		return 0;
   2.259 +	}
   2.260 +#endif
   2.261 +
   2.262 +	fprintf(stderr, "not possible to change display size\n");
   2.263 +	return -1;
   2.264 +}