
Portions Copyright (C) 1993-1996 Olivetti Research Limited, Cambridge, England.

THERE IS NO WARRANTY FOR THIS SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE
LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THIS SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  NO
GUARANTEE IS MADE THAT THIS SOFTWARE IS FREE OF SOFTWARE VIRUSES.  THE ENTIRE
RISK AS TO THE QUALITY AND PERFORMANCE OF THIS SOFTWARE IS WITH YOU.  SHOULD
THIS SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THIS
SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE THIS SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THIS SOFTWARE TO OPERATE WITH ANY OTHER SYSTEMS), EVEN IF SUCH
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


Notes on the "teleporting aware" window manager tpwm
====================================================

Tpwm is a window manager based on the version of tvtwm in X11R5 contrib.  It
has few changes from the original tvtwm. The changes can be split into two
sorts.


1. Changes which really have nothing to do with teleporting (most of these were
needed simply to get tvtwm to compile on all our architectures):

- Comment out XPM stuff from Imakefile.
- Add XTOOLLIB (-lXt) to LOCAL_LIBRARIES in Imakefile. 
- Remove ssetroot stuff.
- Add #include <stdio.h> in LocPixmap.c
- Use memset not bzero in menus.c.
- Don't use m4 to preprocess "twmrc" files in parse.c.
- Look for files called ".tpwmrc.<screen>" and ".tpwmrc" before usual ones.


2. Changes for extra teleporting features:

- Keep note of change in viewport size by monitoring _ORL_TP_VIEWPORT_SIZE
  property on root window, and adjusting the panner appropriately (events.c
  and vdt.c).
- For sticky windows, keep a note of their position relative to the nearest
  corner so that when the viewport is resized they stay at the some position
  relative to that corner (add_window.c, move.c and events.c).
- Handle (keyboard) mapping notify events by going through all the keysyms of
  keys that should be grabbed and grabbing the new corresponding keycodes.



Just in case it's useful, here's the complete list of diffs from R5 tvtwm:


*************** Imakefile *****************
25,27c25,27
<          XPMLIB       = -lXpm
<         XPM_DEF = -DXPM
<     XLOADIM_DEF = -DXLOADIMAGE=\"/usr/local/bin/xloadimage\"
---
> XCOMM         XPMLIB  = -lXpm
> XCOMM        XPM_DEF = -DXPM
> XCOMM    XLOADIM_DEF = -DXLOADIMAGE=\"/usr/local/bin/xloadimage\"
37c37
< LOCAL_LIBRARIES = $(XMULIB) $(EXTENSIONLIB) $(XPMLIB) $(XLIB)
---
> LOCAL_LIBRARIES = $(XMULIB) $(EXTENSIONLIB) $(XPMLIB) $(XLIB) $(XTOOLLIB)
49c49
< AllTarget(tvtwm ssetroot)
---
> AllTarget(tpwm)
59,60c59
< ComplexProgramTarget(tvtwm)
< NormalProgramTarget(ssetroot,ssetroot.o,,$(LOCAL_LIBRARIES),)
---
> NormalProgramTarget(tpwm,$(OBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
62,64d60
< MakeDirectories(install,$(TWMDIR))
< InstallNonExec(system.twmrc,$(TWMDIR))
< XCOMM InstallNamedProg(ssetroot,xsetroot,$(BINDIR))


*************** LocPixmap.c *****************
39a40
> #include <stdio.h>


*************** add_window.c *****************
843a844,865
>     /*
>      * If window is sticky, record its position relative to nearest corner.
>      */
> 
>     if (tmp_win->sticky) {
>       int centreX, centreY;
> 
>       centreX = tmp_win->frame_x + tmp_win->frame_bw + (tmp_win->frame_width / 2);
>       centreY = tmp_win->frame_y + tmp_win->frame_bw + (tmp_win->frame_height / 2);
> 
>       if (centreX > Scr->MyDisplayWidth / 2) {
>           tmp_win->stickyX = tmp_win->frame_x - Scr->MyDisplayWidth;
>       } else {
>           tmp_win->stickyX = tmp_win->frame_x;
>       }
>       if (centreY > Scr->MyDisplayHeight / 2) {
>           tmp_win->stickyY = tmp_win->frame_y - Scr->MyDisplayHeight;
>       } else {
>           tmp_win->stickyY = tmp_win->frame_y;
>       }
>     }
> 


*************** events.c *****************
108a109,110
> static void HandleMappingNotify();
> 
212a215
>     EventHandler[MappingNotify] = HandleMappingNotify;
304c307
<       case MappingNotify:  return None;
---
>       case MappingNotify:  return DefaultRootWindow(dpy);
736a740,780
>       if (Event.xproperty.atom == _XA_ORL_TP_VIEWPORT_SIZE) {
>           if (GetViewportSize()) {
>               TwmWindow *tmp;
>               XEvent ev;
>               int x = Scr->vdtPositionX, y = Scr->vdtPositionY, moveDesktop = 0;
> 
>               for (tmp = Scr->TwmRoot.next; tmp != NULL; tmp = tmp->next) {
>                   if (tmp->sticky) {
>                       int x = tmp->stickyX, y = tmp->stickyY;
> 
>                       if (x < 0) x += Scr->MyDisplayWidth;
>                       if (y < 0) y += Scr->MyDisplayHeight;
> 
>                       if (!Scr->StickyAbove) {
>                           x += Scr->vdtPositionX;
>                           y += Scr->vdtPositionY;
>                       }
>                           
>                       SetupFrame(tmp, x, y, tmp->frame_width, tmp->frame_height, -1, True);
>                   }
>               }
> 
>               if (x + Scr->MyDisplayWidth > Scr->vdtWidth) {
>                   x = Scr->vdtWidth - Scr->MyDisplayWidth;
>                   moveDesktop = 1;
>               }
>               if (y + Scr->MyDisplayHeight > Scr->vdtHeight) {
>                   y = Scr->vdtHeight - Scr->MyDisplayHeight;
>                   moveDesktop = 1;
>               }
>               if (moveDesktop) {
>                   MoveDesktop(x, y);
>               }
>               else {
>                   ev.xexpose.count = 0;
>                   HandlePannerExpose(&ev);
>               }
>           }
>           return;
>       }
> 
2515a2560,2591
> }
> 
> /***********************************************************************
>  *
>  *  Procedure:
>  *    HandleMappingNotify
>  *
>  ***********************************************************************
>  */
> 
> static void
> HandleMappingNotify ()
> {
>     TwmWindow *tmp_win;
>     FuncKey *tmp;
>     int keycode;
> 
>     if (Event.xmapping.request == MappingKeyboard)
>       XRefreshKeyboardMapping(&Event.xmapping);
> 
>     for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
>     {
>       if ((keycode = XKeysymToKeycode(dpy, tmp->keysym)) != 0)
>           tmp->keycode = keycode;
>     }
> 
>     for (tmp_win = Scr->TwmRoot.next;
>        tmp_win != NULL;
>        tmp_win = tmp_win->next)
>     {
>       GrabKeys(tmp_win);
>     }


*************** menus.c *****************
2860c2860
<               bzero (tmp->cmaps.scoreboard, 
---
>               memset (tmp->cmaps.scoreboard, 0,


*************** move.c *****************
102a103,125
> 
>       /*
>        * If window is sticky, record its position relative to nearest corner.
>        */
> 
>       if (tmp_win->sticky) {
>           int centreX, centreY;
> 
>           centreX = tmp_win->frame_x + tmp_win->frame_bw + (tmp_win->frame_width / 2);
>           centreY = tmp_win->frame_y + tmp_win->frame_bw + (tmp_win->frame_height / 2);
> 
>           if (centreX > Scr->MyDisplayWidth / 2) {
>               tmp_win->stickyX = tmp_win->frame_x - Scr->MyDisplayWidth;
>           } else {
>               tmp_win->stickyX = tmp_win->frame_x;
>           }
>           if (centreY > Scr->MyDisplayHeight / 2) {
>               tmp_win->stickyY = tmp_win->frame_y - Scr->MyDisplayHeight;
>           } else {
>               tmp_win->stickyY = tmp_win->frame_y;
>           }
>       }
> 


*************** parse.c *****************
138,142c138,144
<        *   1.  .tvtwmrc.#
<        *   2.  .tvtwmrc
<        *   3.  .twmrc.#
<        *   4.  .twmrc
<        *   5.  system.twmrc
---
>        *   1.  .tpwmrc.#
>        *   2.  .tpwmrc
>        *   3.  .tvtwmrc.#
>        *   4.  .tvtwmrc
>        *   5.  .twmrc.#
>        *   6.  .twmrc
>        *   7.  system.twmrc
144c146
<       for (twmrc = NULL, i = 0; !twmrc && i < 6; i++) {
---
>       for (twmrc = NULL, i = 0; !twmrc && i < 8; i++) {
150c152
<         case 1:           /* ~/.twmrc.screennum */
---
>         case 1:           /* ~/.tpwmrc.screennum */
155a158,176
>                               (void) sprintf (tmpfilename, "%s/.tpwmrc.%d",
>                                       home, Scr->screen);
>                               break;
>                       }
>               }
>               continue;
> 
>         case 2:                       /* ~/.tpwmrc */
>               if (home) {
>                       tmpfilename[homelen + 8] = '\0';
>               }
>               break;
> 
>         case 3:           /* ~/.tvtwmrc.screennum */
>               if (!filename) {
>                       home = getenv ("HOME");
>                       if (home) {
>                               homelen = strlen (home);
>                               cp = tmpfilename;
163c184
<         case 2:                       /* ~/.tvtwmrc */
---
>         case 4:                       /* ~/.tvtwmrc */
169c190
<         case 3:                       /* ~/.twmrc.screennum */
---
>         case 5:                       /* ~/.twmrc.screennum */
182c203
<         case 4:                       /* ~/.twmrc */
---
>         case 6:                       /* ~/.twmrc */
188c209
<         case 5:                       /* system.twmrc */
---
>         case 7:                       /* system.twmrc */
207c228
<               twmrc = start_m4(raw);
---
> /*            twmrc = start_m4(raw); */


*************** twm.c *****************
968a969
> Atom _XA_ORL_TP_VIEWPORT_SIZE;
979a981
>     _XA_ORL_TP_VIEWPORT_SIZE = XInternAtom(dpy, "_ORL_TP_VIEWPORT_SIZE", False);


*************** twm.h *****************
274a275,276
>     int stickyX, stickyY;     /* if so, position relative to nearest corner
>                                  (-ve means from right/bottom) */
307a310
> #ifndef SYSV
308a312
> #endif
371a376
> extern Atom _XA_ORL_TP_VIEWPORT_SIZE;


*************** vdt.c *****************
705a706,707
> 
>     GetViewportSize();
863a866,902
> }
> 
> 
> /*
>  * GetViewportSize reads the value of the _ORL_TP_VIEWPORT_SIZE property from
>  * the root window. It returns 0 if the property does not exist or is invalid,
>  * 1 if it does exist and the appropriate values in the Scr structure have
>  * been altered.
>  */
> 
> int
> GetViewportSize()
> {
>     Atom actual = None;
>     int actual_format;
>     unsigned long nitems, bytesafter;
>     unsigned char *data = NULL;
>     int scrollPercentX, scrollPercentY;
> 
>     XGetWindowProperty(dpy, Scr->Root, _XA_ORL_TP_VIEWPORT_SIZE, 0, 2, False,
>                     XA_INTEGER, &actual, &actual_format, &nitems, &bytesafter, &data);
> 
>     if ((actual == XA_INTEGER) && (actual_format == 32) && (nitems == 2)) {
>       scrollPercentX = (100 * Scr->vdtScrollDistanceX) / Scr->MyDisplayWidth;
>       scrollPercentY = (100 * Scr->vdtScrollDistanceY) / Scr->MyDisplayHeight;
>       Scr->MyDisplayWidth = (int)((long *)data)[0];
>       Scr->MyDisplayHeight = (int)((long *)data)[1];
>       Scr->vdtScrollDistanceX = (scrollPercentX * Scr->MyDisplayWidth) / 100;
>       Scr->vdtScrollDistanceY = (scrollPercentY * Scr->MyDisplayHeight) / 100;
>       Scr->PannerOutlineWidth = 0;    /* panner outline needs redrawing */
>       XFree(data);
>       return 1;
>     }
> 
>     if (data)
>       XFree(data);
>     return 0;


*************** vdt.h *****************
62a63
> extern int GetViewportSize();
