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

Reply via email to