This is a daemon program to sync Xrandr rotation with the synaptics device.
Signed-off-by: Takashi Iwai <[email protected]> --- tools/Makefile.am | 5 +- tools/synxrrd.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 1 deletions(-) create mode 100644 tools/synxrrd.c diff --git a/tools/Makefile.am b/tools/Makefile.am index 2ad48f6..1111576 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -bin_PROGRAMS = synclient syndaemon +bin_PROGRAMS = synclient syndaemon synxrrd AM_CPPFLAGS = -I$(top_srcdir)/include -I$(sdkdir) AM_CFLAGS = $(XI_CFLAGS) @@ -30,3 +30,6 @@ syndaemon_SOURCES = syndaemon.c syndaemon_CFLAGS = $(AM_CFLAGS) $(XTST_CFLAGS) syndaemon_LDFLAGS = $(AM_LDFLAGS) $(XTST_LIBS) +synxrrd_SOURCES = synxrrd.c +synxrrd_LDFLAGS = -lXrandr $(XLIB_LIBS) $(XI_LIBS) + diff --git a/tools/synxrrd.c b/tools/synxrrd.c new file mode 100644 index 0000000..9f00e5b --- /dev/null +++ b/tools/synxrrd.c @@ -0,0 +1,186 @@ +/* + * synxrrd.c + * Copyright (C) 2010 Takashi Iwai <[email protected]> + */ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xrandr.h> + +#define progname "synxrrd" + +static int verbose; +static const char *laptop_name; + +static int is_laptop(const char *name) +{ + if (laptop_name) { + if (!strcmp(name, laptop_name)) + return 1; + } else { + if (strstr(name, "LVDS") || + strstr(name, "Lvds") || + strstr(name, "LVDs")) + return 1; + if (strstr(name, "LCD")) + return 1; + } + return 0; +} + +static int current_rotation = -1; /* unknown */ + +static int (*xerror_saved)(Display *, XErrorEvent *); +static int xerror_code; + +static int xerror_ignore(Display *dpy, XErrorEvent *err) +{ + xerror_code = err->error_code; + return 0; +} + +extern int (*_XErrorFunction)(Display *, XErrorEvent *); +extern int _XDefaultError(Display *dpy, XErrorEvent *event); + +static void xerror_save(void) +{ + xerror_code = 0; + xerror_saved = _XErrorFunction; + _XErrorFunction = xerror_ignore; +} + +static int xerror_restore(void) +{ + _XErrorFunction = xerror_saved; + return xerror_code; +} + +static void notify_synaptics(XRRCrtcInfo *cres) +{ + int rotation; + char buf[256]; + + if (cres->rotation & 8) + rotation = 3; + else if (cres->rotation & 4) + rotation = 2; + else if (cres->rotation & 2) + rotation = 1; + else + rotation = 0; + if (current_rotation == rotation) + return; + current_rotation = rotation; + if (verbose) + fprintf(stderr, "%s: notified rotation %d\n", + progname, current_rotation); + sprintf(buf, "synclient Orientation=%d", current_rotation); + system(buf); +} + +static void update_screen(Display *dpy, Window root) +{ + XRRScreenResources *res; + int i; + + res = XRRGetScreenResources(dpy, root); + if (!res) + return; + for (i = 0; i < res->noutput; i++) { + XRROutputInfo *info; + + info = XRRGetOutputInfo(dpy, res, res->outputs[i]); + if (!info) + continue; + if (is_laptop(info->name)) { + RRCrtc crtc = info->crtc; + XRRCrtcInfo *cres; + + XRRFreeOutputInfo(info); + cres = XRRGetCrtcInfo(dpy, res, crtc); + if (!cres) + continue; + notify_synaptics(cres); + XRRFreeCrtcInfo(cres); + break; + } + XRRFreeOutputInfo(info); + } + XRRFreeScreenResources(res); +} + +static void synxrr_daemon(Display *dpy, Window root) +{ + int event_base, error_base; + + XRRQueryExtension(dpy, &event_base, &error_base); + + XRRSelectInput(dpy, root, RRScreenChangeNotifyMask); + + for (;;) { + XEvent event; + + XNextEvent(dpy, &event); + xerror_save(); + XRRUpdateConfiguration(&event); + switch (event.type - event_base) { + case RRScreenChangeNotify: + update_screen(dpy, root); + break; + } + xerror_restore(); + } +} + +static void usage(void) +{ + fprintf(stderr, "usage: %s [options]\n", progname); + fprintf(stderr, " options\n"); + fprintf(stderr, " -d display set X display name\n"); + fprintf(stderr, " -l name xrandr output name for laptop display\n"); + fprintf(stderr, " -v verbose mode\n"); +} + +int main(int argc, char **argv) +{ + Display *dpy; + Window root; + const char *display_name = NULL; + const char *device_name; + int c; + + while ((c = getopt(argc, argv, "d:l:v")) != -1) { + switch (c) { + case 'd': + display_name = optarg; + break; + case 'l': + laptop_name = optarg; + break; + case 'v': + verbose++; + break; + default: + usage(); + return 1; + } + } + + device_name = argv[optind]; + + dpy = XOpenDisplay(display_name); + if (!dpy) { + perror("open display"); + return 1; + } + + root = DefaultRootWindow(dpy); + update_screen(dpy, root); + synxrr_daemon(dpy, root); + + return 0; +} -- 1.7.3.1 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
