Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 x2x (1.30-7) unstable; urgency=medium
 .
   * merge mods adding options -win-output and -win-transparent
Author: Barak A. Pearlmutter <bap@debian.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2018-07-09

--- x2x-1.30.orig/INSTALL
+++ x2x-1.30/INSTALL
@@ -1,4 +1,5 @@
 Just build/install x2x as any other autotools-based program.
+See README for details installing on Fedora and Ubuntu.
 
 Configuration options:
 
--- x2x-1.30.orig/Makefile.am
+++ x2x-1.30/Makefile.am
@@ -4,9 +4,6 @@
 # BSD-3
 #
 
-AM_CFLAGS = $(X11_CFLAGS) -Wall
-AM_LDFLAGS = $(X11_LIBS)
-
 bin_PROGRAMS = x2x
 
 x2x_SOURCES = x2x.c
@@ -18,8 +15,8 @@ dist_man1_MANS = x2x.1
 
 if WIN32
 
-AM_CFLAGS += -DWIN_2_X
-AM_LDFLAGS += -luser32 -lgdi32 # Ugly hack
+AM_CFLAGS = -DWIN_2_X
+LIBS += -luser32 -lgdi32 # Ugly hack
 x2x_SOURCES += keymap.c winmsg.c x2xwin.rc
 
 .o:.rc
--- x2x-1.30.orig/README
+++ x2x-1.30/README
@@ -32,3 +32,19 @@ Authors
 
 x2x was initially developed in DEC by David Chaiken.
 Current maintainer is Mikhail Gusarov.
+
+== Installing on Fedora, or without building package  ==
+
+1. git clone https://github.com/dottedmag/x2x; cd x2x
+2. ./bootstrap.sh
+3. sudo yum -y install libXext-devel libXtst-devel
+4. ./configure
+5. make && sudo make install
+
+== Installing on Ubuntu or Debian ==
+
+1. git clone https://github.com/dottedmag/x2x; cd x2x
+2. git checkout debian
+3. dpkg-checkbuilddeps (and sudo apt install anything-missing)
+4. fakeroot debian/rules binary
+5. sudo dpkg --install ../x2x_VERSION.deb
--- x2x-1.30.orig/configure.ac
+++ x2x-1.30/configure.ac
@@ -6,7 +6,7 @@ dnl
 
 AC_PREREQ([2.69])
 AC_INIT([x2x],[1.30-rc1],[http://x2x.dottedmag.net/newticket],[x2x],[http://x2x.dottedmag.net])
-AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
 AC_CONFIG_SRCDIR([x2x.c])
 
 # config.h is unused but generating it avoids compiler invocation clutter.
@@ -15,23 +15,24 @@ AC_CONFIG_HEADERS([config.h])
 AC_PROG_CC
 AC_PROG_INSTALL
 
+AX_CFLAGS_WARN_ALL
+
 ## This PKG_CHECK_MODULES can be replaced by the following three
-## AC_CHECK_LIBs and the non-Cygwin setting of AM_LDFLAGS and
+## AC_SEARCH_LIBSs and the non-Cygwin setting of AM_LDFLAGS and
 ## AM_CFLAGS in Makefile.am removed.
 PKG_CHECK_MODULES(X11, xext xtst x11)
-# AC_CHECK_LIB([X11], [XOpenDisplay])
-# AC_CHECK_LIB([Xext], [XextFindDisplay])
-# AC_CHECK_LIB([Xtst], [XTestFakeKeyEvent])
+# AC_SEARCH_LIBS([XOpenDisplay], [X11 x11])
+# AC_SEARCH_LIBS([XextFindDisplay], [Xext xext])
+# AC_SEARCH_LIBS([XTestFakeKeyEvent], [Xtst xtst])
+
+CFLAGS="${X11_CFLAGS} ${CFLAGS}"
+LIBS="${X11_LIBS} ${LIBS}"
 
 AC_ARG_ENABLE([win32],
     AS_HELP_STRING(
         [--enable-win32],
         [enable Win32 support (-fromwin option). Disabled by default]))
 
-AC_SUBST(X11_CFLAGS)
-AC_SUBST(X11_LIBS)
-AC_SUBST(enable_win32)
-
 AM_CONDITIONAL(WIN32, [test x$enable_win32 = xyes])
 
 AC_CONFIG_FILES([Makefile])
--- x2x-1.30.orig/x2x.1
+++ x2x-1.30/x2x.1
@@ -1,4 +1,9 @@
 .nh
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+\" .mso www.tmac
 .TH x2x 1
 .SH NAME
 x2x \- X to X connection
@@ -192,6 +197,36 @@ another window ever obscures it.  This o
 behavior if another application tries to do the same thing.  Useful for
 login scripts.
 .TP
+.B \-win-output
+.IP
+Makes the small window ("trigger window") on the side of the "from" display
+an InputOutput window instead of an InputOnly window. Visibility notification
+events are never generated for InputOnly window, therefore -resurface would
+not work for InputOnly window. Use -win-output together with -resurface.
+.TP
+.B \-win-transparent
+.IP
+Makes the small window ("trigger window") transparent. Use with -win-output option.
+.TP
+.B \-struts
+.IP
+Advertise struts in _NET_WM_STRUT
+    
+Once upon a time, the trigger window was a regular window and could be
+arbitrarily stacked. If obscured it would stop working. Later the
+trigger window became a dock, to be treated specially by the window
+manager. The EWMH spec
+.B suggests
+placing docks over all other
+windows... but some window managers place docks below before unmapping
+them. XMonad is one such window manager. In this case we would like to
+advertise struts - reserved space along screen edges that is not
+normally obscured. However this should not happen if the dock is already
+above all windows. And thus the new '\-struts' settings is born, which
+uses the '_NET_WM_STRUT' property.
+    
+Note that this is a less hacky alternative to '\-resurface'.
+.TP
 .B \-capslockhack
 .IP
 Ugly hack to work-around the situation in which the "to" Xserver doesn't
@@ -244,10 +279,66 @@ Override the title of the control window
 .B \-copyright
 .IP
 Prints the full copyright for the x2x code.
+.TP
+.B \-noscale
+.IP
+This option turns off the mouse scaling.  In some circumstances, the
+remote screen is so different in physical size or resolution that the
+normal mouse scaling applied by x2x distorts the mouse movement so much
+as to be practially unusable.  Note: this is only useful if the remote
+screen is lower resolution than the local screen and also causes the
+remote mouse pointer to warp around when it hits the edges.
+.TP
+.B \-completeregionleft
+.IP
+Describes leftmost coordinate of complete rectangle region in from-display.  If
+from-display is configured with multiple monitors and they have different
+resolution, few regions that does not belongs to any monitor becomes dead space
+that mouse cannot move in.  In the case, the dead space can be mapped to legal
+region of to-display.  If complete region in from-display is specified, X2X
+maps only complete region to to-display and avoid the dead, but legal regions.
+.TP
+.B \-completeregionright
+.IP
+Describes rightmost coordinate of complete rectangle region in from-display.
+.TP
+.B \-completeregionup
+.IP
+Describes uppermost coordinate of complete rectangle region in from-display.
+.TP
+.B \-completeregionlow
+.IP
+Describes lowermost coordinate of complete rectangle region in from-display.
+.SH EXAMPLES
+Calling the system whose keyboard is to be used "primary" and the
+other system "secondary", you need to specify either \-from
+primary-x-display or \-to secondary-x-display.  The x2x program can be
+run on either system.  The easiest way to maintain security is to
+tunnel an X connection over ssh.  Since x2x can be run on either
+computer, it can be invoked in either of the following ways, where we
+assume the local display on each system is :0.
+.TP
+run indirectly on secondary:
+.IP
+primary $ ssh \-X secondary x2x \-to :0 \-east
+.TP
+run indirectly on primary:
+.IP
+secondary $ ssh \-X primary x2x \-from :0 \-west
+.TP
+run directly indirectly on primary:
+.IP
+primary $ ssh \-A secondary env DISPLAY=:0.0 ssh \-X primary x2x \-from :0 \-east
+.SH SEE ALSO
+The
+.URL http://synergy-project.org "synergy program"
+has similar functionality to that of x2x, supports multiple platforms,
+and when I try to use it my X session crashes.
+
+There is a nice
+.URL http://www.linuxjournal.com/content/share-keyboardmouse-between-multiple-computers-x2x "Linux Journal article on x2x" .
 .SH AUTHOR
-David Chaiken
-.br
-(chaiken@pa.dec.com)
+David Chaiken <chaiken@pa.dec.com>
 .br
 Mark Hayter (\-fromwin code, thanks to the WinVNC sources)
 .br
@@ -259,8 +350,9 @@ Current maintaner is Mikhail Gusarov <do
 This software is experimental!  Heaven help you if your network
 connection should go down.  Caveat hacker.  TANSTAAFL.
 
-Nevertheless, bugtracker is at
-http://x2x.dottedmag.net/trac/do/newticket
+The
+.URL http://github.com/dottedmag/x2x "x2x repository and issue tracker"
+has moved to github.
 
 When using the \-fromwin option if the Ctrl-Alt-Del keysequence is used
 while the mouse is forwarded to the X display then the Ctrl and Alt
@@ -273,6 +365,10 @@ and Alt should restore correct operation
 mouse to the Windows display (or using the RightAlt-Home magic key
 sequence).
 
+If you have trouble with some keys not working, try setting the
+keymaps on both systems to be the same using \fBsetxkbmap\fR.
+If that's not enough, make sure that the output of \fBsetxkbmap \-query\fR is identical on both machines.
+
 .SH LAWYERESE
 Copyright (c) 1997
 Digital Equipment Corporation.  All rights reserved.
--- x2x-1.30.orig/x2x.c
+++ x2x-1.30/x2x.c
@@ -235,6 +235,8 @@ typedef struct {
   int     selRevFrom;
   GC      textGC;
   Atom    wmpAtom, wmdwAtom;
+  Atom    netWmWindowTypeAtom, netWmWindowTypeDockAtom;
+  Atom    netWmStrutAtom;
   Cursor  grabCursor;
   Font    fid;
   int     width, height, twidth, theight, tascent;
@@ -362,6 +364,8 @@ static int     doEdge       = EDGE_NONE;
 static Bool    doSel        = True;
 static Bool    doAutoUp     = True;
 static Bool    doResurface  = False;
+static Bool    winTransparent = False;
+static Bool    doInputOnly  = True;
 static PSHADOW shadows      = NULL;
 static int     triggerw     = 2;
 static Bool    doPointerMap = True;
@@ -373,6 +377,12 @@ static Bool    doDpmsMouse  = False;
 static int     logicalOffset= 0;
 static int     nButtons     = 0;
 static KeySym  buttonmap[N_BUTTONS + 1][MAX_BUTTONMAPEVENTS + 1];
+static Bool    noScale      = False;
+static int     compRegLeft  = 0;
+static int     compRegRight = 0;
+static int     compRegUp    = 0;
+static int     compRegLow   = 0;
+static Bool    useStruts    = False;
 
 #ifdef WIN_2_X
 /* These are used to allow pointer comparisons */
@@ -383,6 +393,14 @@ static HWND hWndSave;
 static HINSTANCE m_instance;
 #endif
 
+#ifdef DEBUG_COMPLREG
+#define debug_cmpreg printf
+#else
+void debug_cmpreg(const char *fmt, ...)
+{
+}
+#endif
+
 #ifdef DEBUG
 #define debug printf
 #else
@@ -716,6 +734,12 @@ char **argv;
       doResurface = True;
 
       debug("will resurface the trigger window when obscured\n");
+    } else if (!strcasecmp(argv[arg], "-win-output")) {
+      doInputOnly = False;
+      debug("trigger window will be an InputOutput window\n");
+    } else if (!strcasecmp(argv[arg], "-win-transparent")) {
+      winTransparent = True;
+      debug("trigger window will be transparent\n");
     } else if (!strcasecmp(argv[arg], "-shadow")) {
       if (++arg >= argc) Usage();
       pShadow = (PSHADOW)xmalloc(sizeof(SHADOW));
@@ -731,6 +755,25 @@ char **argv;
       triggerw = atoi(argv[arg]);
     } else if (!strcasecmp(argv[arg], "-copyright")) {
       puts(lawyerese);
+    } else if (!strcasecmp(argv[arg], "-noscale")) {
+      noScale = True;
+    } else if (!strcasecmp(argv[arg], "-completeregionleft")) {
+      if (++arg >= argc) Usage();
+      compRegLeft = atoi(argv[arg]);
+    } else if (!strcasecmp(argv[arg], "-completeregionright")) {
+      if (++arg >= argc) Usage();
+      compRegRight = atoi(argv[arg]);
+    } else if (!strcasecmp(argv[arg], "-completeregionup")) {
+      if (++arg >= argc) Usage();
+      compRegUp = atoi(argv[arg]);
+    } else if (!strcasecmp(argv[arg], "-completeregionlow")) {
+      if (++arg >= argc) Usage();
+      compRegLow = atoi(argv[arg]);
+
+    } else if (!strcasecmp(argv[arg], "-struts")) {
+      useStruts = True;
+
+      debug("will advertise struts in _NET_WM_STRUT\n");
     } else {
       Usage();
     } /* END if... */
@@ -760,6 +803,8 @@ static void Usage()
   printf("       -nosel\n");
   printf("       -noautoup\n");
   printf("       -resurface\n");
+  printf("       -win-output\n");
+  printf("       -win-transparent\n");
   printf("       -capslockhack\n");
   printf("       -nocapslockhack\n");
   printf("       -clipcheck\n");
@@ -768,6 +813,7 @@ static void Usage()
   printf("       -label <LABEL>\n");
   printf("       -title <TITLE>\n");
   printf("       -buttonmap <button#> \"<keysym> ...\"\n");
+  printf("       -struts\n");
 #ifdef WIN_2_X
   printf("       -offset [-]<pixel offset of \"to\">\n");
   printf("WIN_2_X build allows Windows or X as -from display\n");
@@ -1173,14 +1219,35 @@ PDPYINFO pDpyInfo;
         --09/27/99 Greg J. Badros <gjb@cs.washington.edu> */
     /* also, make it an InputOnly window so I don't lose
        screen real estate --09/29/99 gjb */
+    /* make it InputOutput when argument -win-output presents,
+       so to get window visibility change event and make -resurface work */
     trigger = pDpyInfo->trigger =
       XCreateWindow(fromDpy, root,
                     vertical ? triggerw : triggerLoc,
                     vertical ? triggerLoc : triggerw,
                     vertical ? fromWidth - (2*triggerw) : triggerw,
                     vertical ? triggerw : fromHeight - (2*triggerw),
-                    0, 0, InputOnly, 0,
+                    0, 0, doInputOnly?InputOnly:InputOutput, 0,
                     CWOverrideRedirect, &xswa);
+
+    pDpyInfo->netWmWindowTypeAtom = XInternAtom(fromDpy, "_NET_WM_WINDOW_TYPE", True);
+    pDpyInfo->netWmWindowTypeDockAtom = XInternAtom(fromDpy, "_NET_WM_WINDOW_TYPE_DOCK", True);
+    XChangeProperty(fromDpy, trigger, pDpyInfo->netWmWindowTypeAtom,
+                    XA_ATOM, 32, PropModeReplace,
+                    (unsigned char *)&pDpyInfo->netWmWindowTypeDockAtom, 1);
+
+    if (useStruts) {
+      unsigned long struts[4] = { doEdge == EDGE_WEST ? triggerw : 0
+                                , doEdge == EDGE_EAST ? triggerw : 0
+                                , doEdge == EDGE_NORTH ? triggerw : 0
+                                , doEdge == EDGE_SOUTH ? triggerw : 0
+                                };
+      pDpyInfo->netWmStrutAtom = XInternAtom(fromDpy, "_NET_WM_STRUT", True);
+      XChangeProperty(fromDpy, trigger, pDpyInfo->netWmStrutAtom,
+                      XA_CARDINAL, 32, PropModeReplace,
+                      (unsigned char *)&struts, 4);
+    }
+
 #ifdef WIN_2_X
     }
 #endif
@@ -1274,6 +1341,14 @@ PDPYINFO pDpyInfo;
   pDpyInfo->wmdwAtom = XInternAtom(fromDpy, "WM_DELETE_WINDOW", True);
   XSetWMProtocols(fromDpy, trigger, &(pDpyInfo->wmdwAtom), 1);
 
+  /* making the trigger window transparent */
+  if (winTransparent) {
+    u_int32_t cardinal_alpha = (u_int32_t) (0);
+    XChangeProperty(fromDpy, trigger,
+      XInternAtom(fromDpy, "_NET_WM_WINDOW_OPACITY", 0),
+      XA_CARDINAL, 32, PropModeReplace, (u_int8_t*) &cardinal_alpha,1);
+  };
+
   /* mdh - Put in Chaiken's change to make this InputOnly */
   if (doBig) {
     big = pDpyInfo->big =
@@ -1324,13 +1399,42 @@ PDPYINFO pDpyInfo;
     pDpyInfo->yTables[screenNum] = yTable =
       (short *)xmalloc(sizeof(short) * fromHeight);
 
-    /* vertical conversion table */
-    for (counter = 0; counter < fromHeight; ++counter)
-      yTable[counter] = (counter * toHeight) / fromHeight;
-
-    /* horizontal conversion table entries */
-    for (counter = 0; counter < fromWidth; ++counter)
-      xTable[counter] = (counter * toWidth) / fromWidth;
+    debug_cmpreg("fromWidth/Height: %d/%d, toWidth/Height: %d/%d\n",
+		    fromWidth, fromHeight, toWidth, toHeight);
+    if (compRegRight == 0)
+	    compRegRight = fromWidth;
+    if (compRegLow == 0)
+	    compRegLow = fromHeight;
+    if (noScale) {
+        /* TODO:
+            - the fake tables should be built as "starting ignored", 1:1 map
+              region and "ending ignored".  Then the rest of the code would
+              need to be taught to disallow mouse movements in the two ignored
+              areas.  This would stop the mouse wrap-around that the simple
+              tables below result in.
+        */
+
+        /* fake vertical conversion table */
+        for (counter = 0; counter < fromHeight; ++counter)
+          yTable[counter] = counter % (toHeight - 1);
+
+        /* fake horizontal conversion table entries */
+        for (counter = 0; counter < fromWidth; ++counter)
+          xTable[counter] = counter % (toWidth - 1);
+    } else {
+        /* vertical conversion table */
+        for (counter = 0; counter < fromHeight; ++counter)
+          yTable[counter] = (counter < compRegUp || counter > compRegLow) ?
+                   100 :
+                   (counter - compRegUp) * toHeight / (compRegLow - compRegUp);
+
+        /* vertical conversion table */
+        for (counter = 0; counter < fromWidth; ++counter)
+          xTable[counter] = (counter < compRegLeft || counter > compRegRight) ?
+                   100 :
+                   (counter - compRegLeft) * toWidth /
+                   (compRegRight - compRegLeft);
+    }
 
     /* adjustment for boundaries */
     if (vertical) {
@@ -1851,6 +1955,17 @@ XMotionEvent *pEv; /* caution: might be
       DoDPMSForceLevel(pShadow, DPMSModeOn);
     }
 
+#ifdef DEBUG_COMPLREG
+    static unsigned lc;
+
+    if (lc++ % 10 == 0)
+      debug_cmpreg("sj: Call XTestFakeMotionEvent %d/%d to %d/%d\n",
+                      pEv->x_root,
+                      pEv->y_root,
+                      pDpyInfo->xTables[toScreenNum][pEv->x_root],
+                      pDpyInfo->yTables[toScreenNum][pEv->y_root]);
+#endif
+
     XTestFakeMotionEvent(pShadow->dpy, toScreenNum,
                       vert?pDpyInfo->xTables[toScreenNum][pEv->x_root]:toCoord,
                       vert?toCoord:pDpyInfo->yTables[toScreenNum][pEv->y_root],
@@ -1893,6 +2008,15 @@ XCrossingEvent *pEv;
   Display *fromDpy = pDpyInfo->fromDpy;
   XMotionEvent xmev;
 
+  if (pEv->x_root < compRegLeft)
+	  pEv->x_root = compRegLeft;
+  if (pEv->x_root > compRegRight)
+	  pEv->x_root = compRegRight;
+  if (pEv->y_root < compRegUp)
+	  pEv->y_root = compRegUp;
+  if (pEv->y_root > compRegLow)
+	  pEv->y_root = compRegLow;
+
   if ((pEv->mode == NotifyNormal) &&
       (pDpyInfo->mode == X2X_DISCONNECTED) && (dpy == pDpyInfo->fromDpy)) {
     DoConnect(pDpyInfo);
@@ -2467,12 +2591,12 @@ PDPYINFO pDpyInfo;
           if ((keycode = XKeysymToKeycode(pShadow->dpy, pFake->thing))) {
             XTestFakeKeyEvent(pShadow->dpy, keycode, False, 0);
 	    pShadow->flush = True;
-            debug("key 0x%x up\n", pFake->thing);
+            debug("key 0x%lx up\n", (unsigned long)pFake->thing);
           } /* END if */
         } else { /* button goes up */
           XTestFakeButtonEvent(pShadow->dpy, pFake->thing, False, 0);
 	  pShadow->flush = True;
-          debug("button %d up\n", pFake->thing);
+          debug("button %ld up\n", (long)pFake->thing);
         } /* END if/else */
       } /* END for */
 
