~ubuntu-branches/ubuntu/hardy/x2x/hardy

« back to all changes in this revision

Viewing changes to x2x.c

  • Committer: Bazaar Package Importer
  • Author(s): Adrian Bridgett
  • Date: 2001-01-09 18:48:27 UTC
  • Revision ID: james.westby@ubuntu.com-20010109184827-89db0zo4beunb8w0
Tags: 1.27-5.1
* NMU
* use debhelper rather than cpbs - it's more standard and gives us FHS
* compile with "-g -O2" as per policy
* merge in patch from Tor Slettnes <tor@slett.net> to map buttons and not
  send any which the remote end can't handle (closes: #80629, #56252)
* patches downloaded from http://www.eax.com/other/x2x-1.27-1.28.patch:
  - unofficial x2x-1.28 patch from Adam Sulmcki <adam@cfar.umd.edu>
    which adds an error handler (closes: #56252).  NB: I have only applied
    the cleanup parts of the patch since #80629 fixes the problem better.
    I've left the patch in debian/errorhandler.diff in case it's needed in
    future.
  - from Greg J. Badros <gjb@cs.washington.edu>:
    -  fix for the feedback loop which can arise
    -  save some screen estate
* patch from Ben Harris <bjh21@cam.ac.uk> to change title of window
  (closes: #54045)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * x2x: Uses the XTEST extension to forward keystrokes from a window on
3
 
 *      one display to another display.  Useful for desks
4
 
 *      with multiple keyboards.
 
2
 * x2x: Uses the XTEST extension to forward mouse movements and keystrokes
 
3
 *      from a window on one display to another display.  Useful for
 
4
 *      desks with multiple keyboards.
5
5
 *
6
6
 * Copyright (c) 1997
7
7
 * Digital Equipment Corporation.  All rights reserved.
37
37
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
38
38
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
39
 */
 
40
 
 
41
/*
 
42
 * Modified on 3 Oct 1998 by Charles Briscoe-Smith:
 
43
 *   added options -north and -south
 
44
 */
 
45
 
40
46
#include <stdio.h>
41
47
#include <stdlib.h>
42
48
#include <string.h>
 
49
#include <unistd.h>
43
50
#include <X11/Xlib.h>
44
51
#include <X11/Xresource.h>
45
52
#include <X11/Xutil.h>
46
53
#include <X11/cursorfont.h>
47
54
#include <X11/Xatom.h> /* for selection */
 
55
#include <X11/extensions/XTest.h>
48
56
#include <sys/types.h> /* for select */
49
57
#include <sys/time.h> /* for select */
50
 
#include "format.h"
51
58
 
52
59
/*#define DEBUG*/
53
60
 
 
61
#ifndef MIN
 
62
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
 
63
#endif
 
64
#ifndef MAX
 
65
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
 
66
#endif
 
67
 
54
68
/**********
55
69
 * definitions for edge
56
70
 **********/
57
71
#define EDGE_NONE   0 /* don't transfer between edges of screens */
58
 
#define EDGE_EAST   1 /* from display is on the east side of to display */
59
 
#define EDGE_WEST   2 /* from display is on the west side of to display */
 
72
#define EDGE_NORTH  1 /* from display is on the north side of to display */
 
73
#define EDGE_SOUTH  2 /* from display is on the south side of to display */
 
74
#define EDGE_EAST   3 /* from display is on the east side of to display */
 
75
#define EDGE_WEST   4 /* from display is on the west side of to display */
60
76
 
61
77
/**********
62
78
 * functions
92
108
static void    Usage();
93
109
 
94
110
/**********
95
 
 * text formatting instructions
96
 
 **********/
97
 
#define toDpyFormatLength (sizeof(toDpyFormat) / sizeof(Format))
98
 
static Format toDpyFormat[] = {
99
 
  FormatMeasureText,
100
 
  FormatSetLeft,      0,
101
 
  FormatSetTop,       0,
102
 
  FormatAddHalfTextX, 1,
103
 
  FormatAddHalfTextY, 3,
104
 
  FormatString, (Format)"unknown",
105
 
  FormatAddHalfTextX, 1,
106
 
  FormatAddHalfTextY, 1
107
 
  };
108
 
/* indexes of values to be filled in at runtime */
109
 
#define toDpyLeftIndex    2
110
 
#define toDpyTopIndex     4
111
 
#define toDpyStringIndex 10 
112
 
 
113
 
/**********
114
111
 * stuff for selection forwarding
115
112
 **********/
116
113
typedef struct _dpyxtra {
135
132
 
136
133
#define N_BUTTONS   5
137
134
 
 
135
#define MAX_BUTTONMAPEVENTS 20
 
136
 
138
137
#define GETDPYXTRA(DPY,PDPYINFO)\
139
138
   (((DPY) == (PDPYINFO)->fromDpy) ?\
140
139
    &((PDPYINFO)->fromDpyXtra) : &((PDPYINFO)->toDpyXtra))
161
160
  GC      textGC;
162
161
  Atom    wmpAtom, wmdwAtom;
163
162
  Cursor  grabCursor;
164
 
  XFS     *font;
165
 
  int     twidth, theight;
166
 
  int     lastFromX;
 
163
  Font    fid;
 
164
  int     width, height, twidth, theight, tascent;
 
165
  Bool    vertical;
 
166
  int     lastFromCoord;
167
167
  int     unreasonableDelta;
168
168
  
169
169
  /* stuff on "to" display */
180
180
  int     nScreens;
181
181
  short   **xTables; /* precalculated conversion tables */
182
182
  short   **yTables;
183
 
  int     fromXConn, fromXDisc; /* location of cursor after conn/disc ops */
184
 
  int     fromXIncr, fromXDecr; /* location of cursor after incr/decr ops */
 
183
  int     fromConnCoord; /* location of cursor after conn/disc ops */
 
184
  int     fromDiscCoord;
 
185
  int     fromIncrCoord; /* location of cursor after incr/decr ops */
 
186
  int     fromDecrCoord;
185
187
 
186
188
  /* selection forwarding info */
187
189
  DPYXTRA fromDpyXtra;
218
220
static char    *toDpyName   = NULL;
219
221
static char    *defaultFN   = "-*-times-bold-r-*-*-*-180-*-*-*-*-*-*";
220
222
static char    *fontName    = "-*-times-bold-r-*-*-*-180-*-*-*-*-*-*";
 
223
static char    *label       = NULL;
221
224
static char    *pingStr     = "PING"; /* atom for ping request */
222
225
static char    *geomStr     = NULL;
223
226
static Bool    waitDpy      = False;
232
235
static Bool    doPointerMap = True;
233
236
static PSTICKY stickies     = NULL;
234
237
static Bool    doBtnBlock   = False;
 
238
static int     nButtons     = 0;
 
239
static KeySym  buttonmap[N_BUTTONS + 1][MAX_BUTTONMAPEVENTS + 1];
235
240
 
236
241
/**********
237
242
 * main
238
243
 **********/
239
 
main(argc, argv)
240
 
int  argc;
241
 
char **argv;
 
244
int main(int argc, char **argv)
242
245
{
243
246
  Display *fromDpy;
244
247
  PSHADOW pShadow;
253
256
    exit(1);
254
257
  }
255
258
 
256
 
  /* no OS independent wat to stop Xlib from complaining via stderr,
 
259
  /* no OS independent way to stop Xlib from complaining via stderr,
257
260
     but can always pipe stdout/stderr to /dev/null */
258
261
  /* convert to real name: */
259
262
  while ((fromDpy = XOpenDisplay(fromDpyName)) == NULL) {
326
329
  extern  char *lawyerese;
327
330
  PSTICKY pNewSticky;
328
331
  KeySym  keysym;
 
332
  int     button;
 
333
  int     eventno;
 
334
  char    *keyname, *argptr;
329
335
 
330
336
#ifdef DEBUG
331
337
  printf ("programStr = %s\n", programStr);
332
338
#endif  
333
339
 
 
340
  /* Clear button map */
 
341
  for (button = 0; button <= N_BUTTONS; button++)
 
342
      buttonmap[button][0] = NoSymbol;
 
343
 
334
344
  for (arg = 1; arg < argc; ++arg) {
335
345
    if (!strcasecmp(argv[arg], "-from")) {
336
346
      if (++arg >= argc) Usage();
353
363
#ifdef DEBUG
354
364
      printf ("fontName = %s\n", fontName);
355
365
#endif
 
366
    } else if (!strcasecmp(argv[arg], "-label")) {
 
367
      if (++arg >= argc) Usage();
 
368
      label = argv[arg];
 
369
 
 
370
#ifdef DEBUG
 
371
      printf ("label = %s\n", label);
 
372
#endif
356
373
    } else if (!strcasecmp(argv[arg], "-geometry")) {
357
374
      if (++arg >= argc) Usage();
358
375
      geomStr = argv[arg];
384
401
#ifdef DEBUG
385
402
      printf("will not do pointer mapping\n");
386
403
#endif
 
404
    } else if (!strcasecmp(argv[arg], "-north")) {
 
405
      doEdge = EDGE_NORTH;
 
406
#ifdef DEBUG
 
407
      printf("\"from\" is on the north side of \"to\"\n");
 
408
#endif
 
409
    } else if (!strcasecmp(argv[arg], "-south")) {
 
410
      doEdge = EDGE_SOUTH;
 
411
#ifdef DEBUG
 
412
      printf("\"from\" is on the south side of \"to\"\n");
 
413
#endif
387
414
    } else if (!strcasecmp(argv[arg], "-east")) {
388
415
      doEdge = EDGE_EAST;
389
416
#ifdef DEBUG
422
449
      } else {
423
450
        printf("x2x: warning: can't translate %s\n", argv[arg]);
424
451
      }
 
452
    } else if (!strcasecmp(argv[arg], "-buttonmap")) {
 
453
        if (++arg >= argc) Usage();
 
454
        button = atoi(argv[arg]);
 
455
 
 
456
        if ((button < 1) || (button > N_BUTTONS))
 
457
            printf("x2x: warning: invalid button %d\n", button);
 
458
        else if (++arg >= argc)
 
459
            Usage();
 
460
        else
 
461
        {
 
462
#ifdef DEBUG
 
463
            printf("will map button %d to keysyms '%s'\n", button, argv[arg]);
 
464
#endif
 
465
            argptr  = argv[arg];
 
466
            eventno = 0;
 
467
            while ((keyname = strtok(argptr, " \t\n\r")) != NULL)
 
468
            {
 
469
                if ((keysym = XStringToKeysym(keyname)) == NoSymbol)
 
470
                    printf("x2x: warning: can't translate %s\n", keyname);
 
471
                else if (eventno + 1 >= MAX_BUTTONMAPEVENTS)
 
472
                    printf("x2x: warning: too many keys mapped to button %d\n",
 
473
                           button);
 
474
                else
 
475
                    buttonmap[button][eventno++] = keysym;
 
476
                argptr = NULL;
 
477
            }
 
478
            buttonmap[button][eventno] = NoSymbol;
 
479
        }
425
480
    } else if (!strcasecmp(argv[arg], "-resurface")) {
426
481
      doResurface = True;
427
482
#ifdef DEBUG
458
513
  printf("       -big\n");
459
514
  printf("       -buttonblock\n");
460
515
  printf("       -nomouse\n");
 
516
  printf("       -nopointermap\n");
 
517
  printf("       -north\n");
 
518
  printf("       -south\n");
461
519
  printf("       -east\n");
462
520
  printf("       -west\n");
463
521
  printf("       -nosel\n");
465
523
  printf("       -resurface\n");
466
524
  printf("       -shadow <DISPLAY>\n");
467
525
  printf("       -sticky <sticky key>\n");
 
526
  printf("       -label <LABEL>\n");
 
527
  printf("       -buttonmap <button#> \"<keysym> ...\"\n");
468
528
  exit(4);
469
529
 
470
530
} /* END Usage */
510
570
  toConn   = XConnectionNumber(toDpy);
511
571
 
512
572
  while (True) { /* FOREVER */
513
 
    if (fromPending = XPending(fromDpy))
 
573
    if ((fromPending = XPending(fromDpy)))
514
574
      if (ProcessEvent(fromDpy, &dpyInfo)) /* done! */
515
575
        break;
516
576
 
534
594
PDPYINFO pDpyInfo;
535
595
{
536
596
  Display   *fromDpy, *toDpy;
537
 
  Screen    *fromScreen, *toScreen;
 
597
  Screen    *fromScreen;
538
598
  long      black, white;
539
599
  int       fromHeight, fromWidth, toHeight, toWidth;
540
600
  Pixmap    nullPixmap;
544
604
  int       *heights, *widths;
545
605
  int       counter;
546
606
  int       nScreens, screenNum;
547
 
  int       twidth, theight; /* text dimensions */
 
607
  int       twidth, theight, tascent; /* text dimensions */
548
608
  int       xoff, yoff; /* window offsets */
549
609
  unsigned int width, height; /* window width, height */
550
610
  int       geomMask;           /* mask returned by parse */
556
616
  int       eventMask;
557
617
  GC        textGC;
558
618
  char      *windowName;  
559
 
  XFS       *font;
 
619
  Font      fid;
560
620
  PSHADOW   pShadow;
561
621
  int       triggerLoc;
 
622
  Bool      vertical;
562
623
 
563
624
  /* cache commonly used variables */
564
625
  fromDpy = pDpyInfo->fromDpy;
574
635
  /* values also in dpyinfo */
575
636
  root       = pDpyInfo->root      = XDefaultRootWindow(fromDpy); 
576
637
  nScreens   = pDpyInfo->nScreens  = XScreenCount(toDpy);
 
638
  vertical   = pDpyInfo->vertical  = (doEdge == EDGE_NORTH
 
639
                                      || doEdge == EDGE_SOUTH);
577
640
 
578
641
  /* other dpyinfo values */
579
642
  pDpyInfo->mode        = X2X_DISCONNECTED;
580
 
  pDpyInfo->unreasonableDelta = fromWidth / 2;
 
643
  pDpyInfo->unreasonableDelta = (vertical ? fromHeight : fromWidth) / 2;
581
644
  pDpyInfo->pFakeThings = NULL;
582
645
 
583
646
  /* window init structures */
586
649
  eventMask = KeyPressMask | KeyReleaseMask;
587
650
 
588
651
  /* cursor locations for moving between screens */
589
 
  pDpyInfo->fromXIncr = triggerw;
590
 
  pDpyInfo->fromXDecr = fromWidth - triggerw - 1;
 
652
  pDpyInfo->fromIncrCoord = triggerw;
 
653
  pDpyInfo->fromDecrCoord = (vertical ? fromHeight : fromWidth) - triggerw - 1;
591
654
  if (doEdge) { /* edge triggers x2x */
592
655
    nullPixmap = XCreatePixmap(fromDpy, root, 1, 1, 1);
593
656
    eventMask |= EnterWindowMask;
594
657
    pDpyInfo->grabCursor = 
595
658
      XCreatePixmapCursor(fromDpy, nullPixmap, nullPixmap,
596
659
                          &dummyColor, &dummyColor, 0, 0);
597
 
    if (doEdge == EDGE_EAST) {
598
 
      /* trigger window location */
 
660
    /* trigger window location */
 
661
    if (doEdge == EDGE_NORTH) {
 
662
      triggerLoc = 0;
 
663
      pDpyInfo->fromConnCoord = fromHeight - triggerw - 1;
 
664
      pDpyInfo->fromDiscCoord = triggerw;
 
665
    } else if (doEdge == EDGE_SOUTH) {
 
666
      triggerLoc = fromHeight - triggerw;
 
667
      pDpyInfo->fromConnCoord = 1;
 
668
      pDpyInfo->fromDiscCoord = triggerLoc - 1;
 
669
    } else if (doEdge == EDGE_EAST) {
599
670
      triggerLoc = fromWidth - triggerw;
600
 
      toHeight = XHeightOfScreen(XScreenOfDisplay(toDpy, 0));
601
 
      pDpyInfo->fromXConn = 1;
602
 
      pDpyInfo->fromXDisc = fromWidth - triggerw - 1;
603
 
    } else {
604
 
      /* trigger window location */
 
671
      pDpyInfo->fromConnCoord = 1;
 
672
      pDpyInfo->fromDiscCoord = triggerLoc - 1;
 
673
    } else /* doEdge == EDGE_WEST */ {
605
674
      triggerLoc = 0;
606
 
      toHeight = XHeightOfScreen(XScreenOfDisplay(toDpy, nScreens - 1));
607
 
      toWidth  = XWidthOfScreen(XScreenOfDisplay(toDpy, nScreens - 1));
608
 
      pDpyInfo->fromXConn = fromWidth - triggerw - 1;
609
 
      pDpyInfo->fromXDisc = triggerw;
 
675
      pDpyInfo->fromConnCoord = fromWidth - triggerw - 1;
 
676
      pDpyInfo->fromDiscCoord = triggerw;
610
677
    } /* END if doEdge == ... */
611
678
 
612
679
    xswa.background_pixel = black;
613
680
    /* fromWidth - 1 doesn't seem to work for some reason */
 
681
    /* Use triggerw offsets so that if an x2x is running
 
682
       along the left edge and along the north edge, both with
 
683
       -resurface, we don't get a feedback loop of them each
 
684
       fighting to be on top.
 
685
        --09/27/99 Greg J. Badros <gjb@cs.washington.edu> */
 
686
    /* also, make it an InputOnly window so I don't lose 
 
687
       screen real estate --09/29/99 gjb */
614
688
    trigger = pDpyInfo->trigger = 
615
 
      XCreateWindow(fromDpy, root, triggerLoc, 0, triggerw, fromHeight,
616
 
                    0, 0, InputOutput, 0, 
617
 
                    CWBackPixel | CWOverrideRedirect, &xswa);
618
 
    font = NULL;
 
689
      XCreateWindow(fromDpy, root,
 
690
                    vertical ? triggerw : triggerLoc,
 
691
                    vertical ? triggerLoc : triggerw,
 
692
                    vertical ? fromWidth - (2*triggerw) : triggerw,
 
693
                    vertical ? triggerw : fromHeight - (2*triggerw),
 
694
                    0, 0, InputOnly, 0, 
 
695
                    CWOverrideRedirect, &xswa);
 
696
    fid = 0;
619
697
 
620
698
  } else { /* normal window for text: do size grovelling */
621
699
    pDpyInfo->grabCursor = XCreateFontCursor(fromDpy, XC_exchange);
622
700
    eventMask |= StructureNotifyMask | ExposureMask;
623
701
    if (doMouse) eventMask |= ButtonPressMask | ButtonReleaseMask;
624
702
 
 
703
    if (label == NULL)
 
704
      label = toDpyName;
625
705
    /* determine size of text */
626
 
    if (((font = XLoadQueryFont(fromDpy, fontName)) != NULL) ||
627
 
        ((font = XLoadQueryFont(fromDpy, defaultFN)) != NULL) ||
628
 
        ((font = XLoadQueryFont(fromDpy, "fixed")) != NULL)) { 
 
706
    if (((fid = XLoadFont(fromDpy, fontName)) != 0) ||
 
707
      ((fid = XLoadFont(fromDpy, defaultFN)) != 0) ||
 
708
      ((fid = XLoadFont(fromDpy, "fixed")) != 0)) {
629
709
      /* have a font */
630
 
      toDpyFormat[toDpyStringIndex] = (Format)toDpyName;
631
 
      formatText(NULL, NULL, NULL, font, 
632
 
                 toDpyFormatLength, toDpyFormat, &twidth, &theight);
 
710
      int ascent, descent, direction;
 
711
      XCharStruct overall;
 
712
 
 
713
      XQueryTextExtents(fromDpy, fid, label, strlen(label),
 
714
                        &direction, &ascent, &descent, &overall);
 
715
      twidth =  - overall.lbearing + overall.rbearing;
 
716
      theight = ascent + descent;
 
717
      tascent = ascent;
633
718
 
634
719
      textGC = pDpyInfo->textGC = XCreateGC(fromDpy, root, 0, NULL);
635
720
      XSetState(fromDpy, textGC, black, white, GXcopy, AllPlanes);
636
 
      XSetFont(fromDpy, textGC, font->fid);
 
721
      XSetFont(fromDpy, textGC, fid);
637
722
 
638
723
    } else { /* should not have to execute this clause: */
639
724
      twidth = theight = 100; /* default window size */
641
726
 
642
727
    /* determine size of window */
643
728
    xoff = yoff = 0;
644
 
    width = twidth;
645
 
    height = theight;
 
729
    width = twidth + 4; /* XXX gap around text -- should be configurable */
 
730
    height = theight + 4;
646
731
    geomMask = XParseGeometry(geomStr, &xoff, &yoff, &width, &height);
647
732
    switch (gravMask = (geomMask & (XNegative | YNegative))) {
648
733
    case (XNegative | YNegative): gravity = SouthEastGravity; break;
711
796
  free(windowName);
712
797
 
713
798
  /* conversion stuff */
714
 
  pDpyInfo->toScreen = (doEdge == EDGE_WEST) ? (nScreens - 1) : 0;
 
799
  pDpyInfo->toScreen = (doEdge == EDGE_WEST || doEdge == EDGE_NORTH)
 
800
                        ? (nScreens - 1) : 0;
715
801
 
716
802
  /* construct table lookup for screen coordinate conversion */
717
803
  pDpyInfo->xTables = (short **)malloc(sizeof(short *) * nScreens);
739
825
      xTable[counter] = (counter * toWidth) / fromWidth;
740
826
 
741
827
    /* adjustment for boundaries */
742
 
    if ((screenNum != 0) || (doEdge == EDGE_EAST))
743
 
      xTable[0] = COORD_DECR;
744
 
    if (((screenNum + 1) < nScreens) || (doEdge == EDGE_WEST)) {
745
 
      xTable[fromWidth - 1] = COORD_INCR;
746
 
      /* work-around for bug: on at least one tested screen, cursor
747
 
         never moved past fromWidth - 2 */
748
 
      xTable[fromWidth - 2] = COORD_INCR;
 
828
    if (vertical) {
 
829
      if ((screenNum != 0) || (doEdge == EDGE_SOUTH))
 
830
        yTable[0] = COORD_DECR;
 
831
      if (((screenNum + 1) < nScreens) || (doEdge == EDGE_NORTH)) {
 
832
        yTable[fromHeight - 1] = COORD_INCR;
 
833
        /* work-around for bug: on at least one tested screen, cursor
 
834
           never moved past fromWidth - 2  (I'll assume this might apply
 
835
           in the vertical case, too. --cpbs) */
 
836
        yTable[fromHeight - 2] = COORD_INCR;
 
837
      }
 
838
    } else {
 
839
      if ((screenNum != 0) || (doEdge == EDGE_EAST))
 
840
        xTable[0] = COORD_DECR;
 
841
      if (((screenNum + 1) < nScreens) || (doEdge == EDGE_WEST)) {
 
842
        xTable[fromWidth - 1] = COORD_INCR;
 
843
        /* work-around for bug: on at least one tested screen, cursor
 
844
           never moved past fromWidth - 2 */
 
845
        xTable[fromWidth - 2] = COORD_INCR;
 
846
      }
749
847
    }
750
848
 
751
849
  } /* END for screenNum */
787
885
  pDpyInfo->eventMask = eventMask; /* save for future munging */
788
886
  if (doSel) XSetSelectionOwner(fromDpy, XA_PRIMARY, trigger, CurrentTime);
789
887
  XMapRaised(fromDpy, trigger);
790
 
  if (pDpyInfo->font = font) { /* paint text */
 
888
  if (pDpyInfo->fid = fid) { /* paint text */
791
889
    /* position text */
792
890
    pDpyInfo->twidth = twidth;
793
891
    pDpyInfo->theight = theight;
794
 
    toDpyFormat[toDpyLeftIndex] = MAX(0,((width - twidth) / 2));
795
 
    toDpyFormat[toDpyTopIndex]  = MAX(0,((height - theight) / 2));
 
892
    pDpyInfo->tascent = tascent;
 
893
    pDpyInfo->width = width;
 
894
    pDpyInfo->height = height;
796
895
 
797
 
    formatText(fromDpy, trigger, &(textGC), font, 
798
 
               toDpyFormatLength, toDpyFormat, NULL, NULL);
 
896
    XDrawImageString(fromDpy, trigger, textGC,
 
897
                     MAX(0,((width - twidth) / 2)),
 
898
                     MAX(0,((height - theight) / 2)) + tascent, label,
 
899
                     strlen(label));
799
900
  } /* END if font */
800
901
 
801
902
  for (pShadow = shadows; pShadow; pShadow = pShadow->pNext)
937
1038
 
938
1039
  int       toScreenNum;
939
1040
  PSHADOW   pShadow;
940
 
  int       toX, fromX, delta;
 
1041
  int       toCoord, fromCoord, delta;
941
1042
  Display   *fromDpy;
942
1043
  Bool      bAbortedDisconnect;
 
1044
  Bool      vert;
 
1045
 
 
1046
  vert = pDpyInfo->vertical;
943
1047
 
944
1048
  /* find the screen */
945
1049
  toScreenNum = pDpyInfo->toScreen;
946
 
  fromX = pEv->x_root;
 
1050
  fromCoord = vert ? pEv->y_root : pEv->x_root;
947
1051
 
948
1052
  /* check to make sure the cursor is still on the from screen */
949
1053
  if (!(pEv->same_screen)) {
950
 
    toX = (pDpyInfo->lastFromX < fromX) ? COORD_DECR : COORD_INCR;
 
1054
    toCoord = (pDpyInfo->lastFromCoord < fromCoord) ? COORD_DECR : COORD_INCR;
951
1055
  } else {
952
 
    toX = pDpyInfo->xTables[toScreenNum][fromX];
 
1056
    toCoord = (vert?pDpyInfo->yTables:pDpyInfo->xTables)[toScreenNum][fromCoord];
953
1057
 
954
1058
    /* sanity check motion: necessary for nondeterminism surrounding warps */
955
 
    delta = pDpyInfo->lastFromX - fromX;
 
1059
    delta = pDpyInfo->lastFromCoord - fromCoord;
956
1060
    if (delta < 0) delta = -delta;
957
1061
    if (delta > pDpyInfo->unreasonableDelta) return False;
958
1062
  }
959
1063
 
960
 
  if (SPECIAL_COORD(toX) != 0) { /* special coordinate */
 
1064
  if (SPECIAL_COORD(toCoord) != 0) { /* special coordinate */
961
1065
    bAbortedDisconnect = False;
962
 
    if (toX == COORD_INCR) {
 
1066
    if (toCoord == COORD_INCR) {
963
1067
      if (toScreenNum != (pDpyInfo->nScreens - 1)) { /* next screen */
964
1068
        toScreenNum = ++(pDpyInfo->toScreen);
965
 
        fromX = pDpyInfo->fromXIncr;
966
 
        toX = pDpyInfo->xTables[toScreenNum][fromX];
 
1069
        fromCoord = pDpyInfo->fromIncrCoord;
 
1070
        toCoord = (vert?pDpyInfo->yTables:pDpyInfo->xTables)[toScreenNum][fromCoord];
967
1071
      } else { /* disconnect! */
968
1072
        if (doBtnBlock &&
969
1073
            (pEv->state & (Button1Mask | Button2Mask | Button3Mask |
971
1075
          bAbortedDisconnect = True;
972
1076
        else {
973
1077
          DoDisconnect(pDpyInfo);
974
 
          fromX = pDpyInfo->fromXDisc;
 
1078
          fromCoord = pDpyInfo->fromDiscCoord;
975
1079
        }
976
 
        toX = pDpyInfo->xTables[toScreenNum][pDpyInfo->fromXConn];
 
1080
        toCoord = (vert?pDpyInfo->yTables:pDpyInfo->xTables)[toScreenNum][pDpyInfo->fromConnCoord];
977
1081
      }
978
1082
    } else { /* DECR */
979
1083
      if (toScreenNum != 0) { /* previous screen */
980
1084
        toScreenNum = --(pDpyInfo->toScreen);
981
 
        fromX = pDpyInfo->fromXDecr;
982
 
        toX = pDpyInfo->xTables[toScreenNum][fromX];
 
1085
        fromCoord = pDpyInfo->fromDecrCoord;
 
1086
        toCoord = (vert?pDpyInfo->yTables:pDpyInfo->xTables)[toScreenNum][fromCoord];
983
1087
      } else { /* disconnect! */
984
1088
        if (doBtnBlock &&
985
1089
            (pEv->state & (Button1Mask | Button2Mask | Button3Mask |
987
1091
          bAbortedDisconnect = True;
988
1092
        else {
989
1093
          DoDisconnect(pDpyInfo);
990
 
          fromX = pDpyInfo->fromXDisc;
 
1094
          fromCoord = pDpyInfo->fromDiscCoord;
991
1095
        }
992
 
        toX = pDpyInfo->xTables[toScreenNum][pDpyInfo->fromXConn];
 
1096
        toCoord = (vert?pDpyInfo->yTables:pDpyInfo->xTables)[toScreenNum][pDpyInfo->fromConnCoord];
993
1097
      }
994
 
    } /* END if toX */
 
1098
    } /* END if toCoord */
995
1099
    if (!bAbortedDisconnect) {
996
1100
      fromDpy = pDpyInfo->fromDpy;
997
1101
      XWarpPointer(fromDpy, None, pDpyInfo->root, 0, 0, 0, 0, 
998
 
                   fromX, pEv->y_root);
 
1102
                   vert ? pEv->x_root : fromCoord,
 
1103
                   vert ? fromCoord : pEv->y_root);
999
1104
      XFlush(fromDpy);
1000
1105
    }
1001
1106
  } /* END if SPECIAL_COORD */
1002
 
  pDpyInfo->lastFromX = fromX;
 
1107
  pDpyInfo->lastFromCoord = fromCoord;
1003
1108
 
1004
1109
  for (pShadow = shadows; pShadow; pShadow = pShadow->pNext) {
1005
 
    XTestFakeMotionEvent(pShadow->dpy, toScreenNum, toX,
1006
 
                         pDpyInfo->yTables[toScreenNum][pEv->y_root], 0);
 
1110
    XTestFakeMotionEvent(pShadow->dpy, toScreenNum,
 
1111
                      vert?pDpyInfo->xTables[toScreenNum][pEv->x_root]:toCoord,
 
1112
                      vert?toCoord:pDpyInfo->yTables[toScreenNum][pEv->y_root],
 
1113
                      0);
1007
1114
    XFlush(pShadow->dpy);
1008
1115
  } /* END for */
1009
1116
    
1017
1124
XExposeEvent *pEv;
1018
1125
{
1019
1126
  XClearWindow(pDpyInfo->fromDpy, pDpyInfo->trigger);
1020
 
  if (pDpyInfo->font)
1021
 
    formatText(pDpyInfo->fromDpy, pDpyInfo->trigger, 
1022
 
               &(pDpyInfo->textGC), pDpyInfo->font, 
1023
 
               toDpyFormatLength, toDpyFormat, NULL, NULL);
 
1127
  if (pDpyInfo->fid)
 
1128
    XDrawImageString(pDpyInfo->fromDpy, pDpyInfo->trigger, pDpyInfo->textGC,
 
1129
                     MAX(0,((pDpyInfo->width - pDpyInfo->twidth) / 2)),
 
1130
                     MAX(0,((pDpyInfo->height - pDpyInfo->theight) / 2)) +
 
1131
                     pDpyInfo->tascent, label, strlen(label));
 
1132
 
1024
1133
  return False;
1025
1134
  
1026
1135
} /* END ProcessExpose */
1036
1145
  if ((pEv->mode == NotifyNormal) &&
1037
1146
      (pDpyInfo->mode == X2X_DISCONNECTED) && (dpy == pDpyInfo->fromDpy)) {
1038
1147
    DoConnect(pDpyInfo);
1039
 
    XWarpPointer(fromDpy, None, pDpyInfo->root, 0, 0, 0, 0, 
1040
 
                 pDpyInfo->fromXConn, pEv->y_root);
1041
 
    xmev.x_root = pDpyInfo->lastFromX = pDpyInfo->fromXConn;
1042
 
    xmev.y_root = pEv->y_root;
 
1148
    if (pDpyInfo->vertical) {
 
1149
      XWarpPointer(fromDpy, None, pDpyInfo->root, 0, 0, 0, 0, 
 
1150
                   pEv->x_root, pDpyInfo->fromConnCoord);
 
1151
      xmev.x_root = pEv->x_root;
 
1152
      xmev.y_root = pDpyInfo->lastFromCoord = pDpyInfo->fromConnCoord;
 
1153
    } else {
 
1154
      XWarpPointer(fromDpy, None, pDpyInfo->root, 0, 0, 0, 0, 
 
1155
                   pDpyInfo->fromConnCoord, pEv->y_root);
 
1156
      xmev.x_root = pDpyInfo->lastFromCoord = pDpyInfo->fromConnCoord;
 
1157
      xmev.y_root = pEv->y_root;
 
1158
    }
1043
1159
    xmev.same_screen = True;
1044
1160
    ProcessMotionNotify(NULL, pDpyInfo, &xmev);
1045
1161
  }  /* END if NotifyNormal... */
1055
1171
  int state;
1056
1172
  PSHADOW   pShadow;
1057
1173
  unsigned int toButton;
1058
 
 
 
1174
  KeySym  keysym;
 
1175
  KeyCode keycode;
 
1176
  int     eventno;
 
1177
   
1059
1178
  switch (pDpyInfo->mode) {
1060
1179
  case X2X_DISCONNECTED:
1061
1180
    pDpyInfo->mode = X2X_AWAIT_RELEASE;
1064
1183
#endif
1065
1184
    break;
1066
1185
  case X2X_CONNECTED:
1067
 
    if (pEv->button <= N_BUTTONS) toButton = pDpyInfo->inverseMap[pEv->button];
1068
 
    for (pShadow = shadows; pShadow; pShadow = pShadow->pNext) {
1069
 
      XTestFakeButtonEvent(pShadow->dpy, toButton, True, 0);
1070
 
#ifdef DEBUG
1071
 
      printf("from button %d down, to button %d down\n", pEv->button,toButton);
1072
 
#endif
1073
 
      XFlush(pShadow->dpy);
1074
 
    } /* END for */
1075
 
    if (doAutoUp)
1076
 
      FakeAction(pDpyInfo, FAKE_BUTTON, toButton, True);
1077
 
    if (doEdge) break;
 
1186
        if ((pEv->button <= N_BUTTONS) &&
 
1187
            (buttonmap[pEv->button][0] != NoSymbol))
 
1188
        {
 
1189
            for (pShadow = shadows; pShadow; pShadow = pShadow->pNext)
 
1190
            {
 
1191
#ifdef DEBUG
 
1192
                printf("Button %d is mapped, sending keys: ", pEv->button);
 
1193
#endif
 
1194
                for (eventno = 0;
 
1195
                     (keysym = buttonmap[pEv->button][eventno]) != NoSymbol;
 
1196
                     eventno++)
 
1197
                {
 
1198
                    if (keycode = XKeysymToKeycode(pShadow->dpy, keysym)) {
 
1199
                        XTestFakeKeyEvent(pShadow->dpy, keycode, True, 0);
 
1200
                        XTestFakeKeyEvent(pShadow->dpy, keycode, False, 0);
 
1201
                        XFlush(pShadow->dpy);
 
1202
#ifdef DEBUG
 
1203
                        printf(" (0x%04X)", keycode);
 
1204
#endif
 
1205
                    }
 
1206
#ifdef DEBUG
 
1207
                    else
 
1208
                        printf(" (no code)");
 
1209
#endif
 
1210
                }
 
1211
#ifdef DEBUG
 
1212
                printf("\n");
 
1213
#endif
 
1214
            }
 
1215
        } else if (pEv->button <= nButtons) {
 
1216
            toButton = pDpyInfo->inverseMap[pEv->button];
 
1217
            for (pShadow = shadows; pShadow; pShadow = pShadow->pNext) {
 
1218
                XTestFakeButtonEvent(pShadow->dpy, toButton, True, 0);
 
1219
#ifdef DEBUG
 
1220
                printf("from button %d down, to button %d down\n", pEv->button,toButton);
 
1221
#endif
 
1222
                XFlush(pShadow->dpy);
 
1223
            } /* END for */
 
1224
            if (doAutoUp)
 
1225
                FakeAction(pDpyInfo, FAKE_BUTTON, toButton, True);
 
1226
        }
 
1227
     if (doEdge) break;
1078
1228
 
1079
1229
    /* check if more than one button pressed */
1080
1230
    state = pEv->state;
1113
1263
 
1114
1264
  if ((pDpyInfo->mode == X2X_CONNECTED) || 
1115
1265
      (pDpyInfo->mode == X2X_CONN_RELEASE)) {
1116
 
    if (pEv->button <= N_BUTTONS) toButton = pDpyInfo->inverseMap[pEv->button];
1117
 
    for (pShadow = shadows; pShadow; pShadow = pShadow->pNext) {
1118
 
      XTestFakeButtonEvent(pShadow->dpy, toButton, False, 0);
 
1266
        if ((pEv->button <= nButtons) &&
 
1267
            (buttonmap[pEv->button][0] == NoSymbol))
 
1268
            // Do not process button release if it was mapped to keys
 
1269
        {
 
1270
            toButton = pDpyInfo->inverseMap[pEv->button];
 
1271
            for (pShadow = shadows; pShadow; pShadow = pShadow->pNext) {
 
1272
                XTestFakeButtonEvent(pShadow->dpy, toButton, False, 0);
1119
1273
#ifdef DEBUG
1120
 
      printf("from button %d up, to button %d up\n", pEv->button, toButton);
 
1274
                printf("from button %d up, to button %d up\n", pEv->button, toButton);
1121
1275
#endif
1122
 
      XFlush(pShadow->dpy);
1123
 
    } /* END for */
1124
 
    if (doAutoUp)
1125
 
      FakeAction(pDpyInfo, FAKE_BUTTON, toButton, False);
 
1276
                XFlush(pShadow->dpy);
 
1277
            } /* END for */
 
1278
            if (doAutoUp)
 
1279
                FakeAction(pDpyInfo, FAKE_BUTTON, toButton, False);
 
1280
        }  
1126
1281
  } /* END if */
1127
1282
 
1128
1283
  if (doEdge) return False;
1145
1300
    if (!state) { /* all buttons up: time to (dis)connect */
1146
1301
      if (pDpyInfo->mode == X2X_AWAIT_RELEASE) { /* connect */
1147
1302
        DoConnect(pDpyInfo);
1148
 
        xmev.x_root = pDpyInfo->lastFromX = pEv->x_root;
1149
 
        xmev.y_root = pEv->y_root;
 
1303
        if (pDpyInfo->vertical) {
 
1304
          xmev.x_root = pEv->x_root;
 
1305
          xmev.y_root = pDpyInfo->lastFromCoord = pEv->y_root;
 
1306
        } else {
 
1307
          xmev.x_root = pDpyInfo->lastFromCoord = pEv->x_root;
 
1308
          xmev.y_root = pEv->y_root;
 
1309
        }
1150
1310
        xmev.same_screen = True;
1151
1311
        ProcessMotionNotify(NULL, pDpyInfo, &xmev);
1152
1312
      } else { /* disconnect */
1204
1364
PDPYINFO pDpyInfo;
1205
1365
XConfigureEvent *pEv;
1206
1366
{
1207
 
  if (pDpyInfo->font) {
 
1367
  if (pDpyInfo->fid) {
1208
1368
    /* reposition text */
1209
 
    toDpyFormat[toDpyLeftIndex] = 
1210
 
      MAX(0,((pEv->width - pDpyInfo->twidth) / 2));
1211
 
    toDpyFormat[toDpyTopIndex]  = 
1212
 
      MAX(0,((pEv->height - pDpyInfo->theight) / 2));
 
1369
    pDpyInfo->width = pEv->width;
 
1370
    pDpyInfo->height = pEv->height;
1213
1371
  } /* END if font */
1214
1372
  return False;
1215
1373
 
1276
1434
PDPYINFO pDpyInfo;
1277
1435
XPropertyEvent *pEv;
1278
1436
{
1279
 
  XSelectionRequestEvent *pSelReq;
1280
1437
  PDPYXTRA pDpyXtra = GETDPYXTRA(dpy, pDpyInfo);
1281
1438
 
1282
1439
#ifdef DEBUG
1535
1692
{
1536
1693
  unsigned int buttCtr;
1537
1694
  unsigned char buttonMap[N_BUTTONS];
1538
 
  int nButtons;
1539
1695
 
1540
1696
  if (dpy == pDpyInfo->toDpy) { /* only care about toDpy */
1541
1697
    /* straightforward mapping */