xserver: Branch 'wonderland-dev'

Deron Johnson deronj at kemper.freedesktop.org
Mon Jun 4 20:10:37 PDT 2007


 hw/vfb/protocol.h    |  615 ++++++++++++++++++++++++++++++
 hw/vfb/remwin.h      |  190 +++++++++
 hw/vfb/rle.c         |  235 +++++++++++
 hw/vfb/rwcomm.h      |   98 ++++
 hw/vfb/rwcommsock.c  |  457 ++++++++++++++++++++++
 hw/vfb/rwcommsock.h  |   55 ++
 hw/vfb/rwin.c        | 1029 +++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/vfb/takecontrol.c |  275 +++++++++++++
 8 files changed, 2954 insertions(+)

New commits:
diff-tree fe201a8f9a4cd8390a84660f68b78d2e4de622dd (from 9789f35cc5ca147c6c4b4bfc810d44fdbdbe5705)
Author: Deron <dj at dj-laptop.(none)>
Date:   Mon Jun 4 20:10:38 2007 -0700

    Add more files to branch.

diff --git a/hw/vfb/protocol.h b/hw/vfb/protocol.h
new file mode 100644
index 0000000..122fb76
--- /dev/null
+++ b/hw/vfb/protocol.h
@@ -0,0 +1,615 @@
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+/*
+** Client-to-Server Messages
+*/
+
+#define CLIENT_MESSAGE_TYPE_INVALID     	0
+#define CLIENT_MESSAGE_TYPE_KEY			1
+#define CLIENT_MESSAGE_TYPE_POINTER		2
+#define CLIENT_MESSAGE_TYPE_TAKE_CONTROL	3
+#define CLIENT_MESSAGE_TYPE_SET_WINDOW_TITLES	4
+#define CLIENT_MESSAGE_TYPE_MOVE_WINDOW		5
+#define CLIENT_MESSAGE_TYPE_RESIZE_WINDOW	6
+#define CLIENT_MESSAGE_TYPE_DESTROY_WINDOW	7
+#define CLIENT_MESSAGE_TYPE_HELLO	        8
+
+typedef struct keyeventmessage_struct {
+    CARD8 	msgType;			
+    CARD8       isPressed;
+    CARD16      pad;
+    CARD32      keysym;
+    CARD32      clientId;
+} KeyEventMessage;
+
+#define KEY_EVENT_MESSAGE_SIZE sizeof(KeyEventMessage)
+
+#define KEY_EVENT_MESSAGE_GET_ISPRESSED(pBuf) \
+    ((KeyEventMessage*)(pBuf))->isPressed
+
+#define KEY_EVENT_MESSAGE_GET_KEYSYM(pBuf) \
+    ((KeyEventMessage*)(pBuf))->keysym
+
+#define KEY_EVENT_MESSAGE_GET_CLIENTID(pBuf) \
+    ((KeyEventMessage*)(pBuf))->clientId
+
+typedef struct pointereventmessage_struct {
+    CARD8 	msgType;
+    CARD8       mask;
+    CARD16      x;
+    CARD16      y;
+    CARD16      pad;
+    CARD32      wid;
+    CARD32      clientId;
+} PointerEventMessage;
+
+#define POINTER_EVENT_MESSAGE_SIZE sizeof(PointerEventMessage)
+
+#define POINTER_EVENT_MESSAGE_GET_MASK(pBuf) \
+    ((PointerEventMessage *)(pBuf))->mask
+
+#define POINTER_EVENT_MESSAGE_GET_X(pBuf) \
+    ((PointerEventMessage*)(pBuf))->x
+
+#define POINTER_EVENT_MESSAGE_GET_Y(pBuf) \
+    ((PointerEventMessage*)(pBuf))->y
+
+#define POINTER_EVENT_MESSAGE_GET_WID(pBuf) \
+    ((PointerEventMessage*)(pBuf))->wid
+
+#define POINTER_EVENT_MESSAGE_GET_CLIENTID(pBuf) \
+    ((PointerEventMessage*)(pBuf))->clientId
+
+typedef struct takecontrolmessage_struct {
+    CARD8 	msgType;			
+    CARD8       steal;
+    CARD16      pad;
+    CARD32      clientId;
+} TakeControlMessage;
+
+#define TAKE_CONTROL_MESSAGE_SIZE sizeof(TakeControlMessage)
+
+#define TAKE_CONTROL_MESSAGE_GET_STEAL(pBuf) \
+    ((((TakeControlMessage*)(pBuf))->steal == 1) ? TRUE : FALSE)
+
+#define TAKE_CONTROL_MESSAGE_GET_CLIENTID(pBuf) \
+    ((TakeControlMessage*)(pBuf))->clientId
+
+/* Same structure used for both server and client messages */
+
+typedef struct setwindowtitlesmessage_struct {
+    CARD8 	msgType;
+    CARD8       pad;
+    CARD16      strLen;
+    /* Followed by strLen bytes */
+} SetWindowTitlesMessage;
+
+#define SET_WINDOW_TITLES_MESSAGE_SIZE sizeof(SetWindowTitlesMessage)
+
+#define SET_WINDOW_TITLES_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((SetWindowTitlesMessage *)(pBuf))->msgType = (mType)
+
+#define SET_WINDOW_TITLES_MESSAGE_GET_STRLEN(pBuf) \
+    ((((SetWindowTitlesMessage*)(pBuf))->strLen))
+
+#define SET_WINDOW_TITLES_MESSAGE_SET_STRLEN(pBuf, len) \
+    ((SetWindowTitlesMessage *)(pBuf))->strLen = (len)
+
+/* Same structure used for both server and client messages */
+
+typedef struct movewindowmessage_struct {
+    CARD8 	msgType;
+    CARD8       pad;
+    CARD16      x;
+    CARD32      clientId;
+    CARD32      wid;
+    CARD16      y;
+} MoveWindowMessage;
+
+#define MOVE_WINDOW_MESSAGE_SIZE sizeof(MoveWindowMessage)
+
+#define MOVE_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((MoveWindowMessage *)(pBuf))->msgType = (mType)
+
+#define MOVE_WINDOW_MESSAGE_GET_X(pBuf) \
+    ((((MoveWindowMessage*)(pBuf))->x))
+
+#define MOVE_WINDOW_MESSAGE_SET_X(pBuf, xval) \
+    ((MoveWindowMessage *)(pBuf))->x = (xval)
+
+#define MOVE_WINDOW_MESSAGE_GET_CLIENT_ID(pBuf) \
+    ((((MoveWindowMessage*)(pBuf))->clientId))
+
+#define MOVE_WINDOW_MESSAGE_SET_CLIENT_ID(pBuf, cid) \
+    ((MoveWindowMessage *)(pBuf))->clientId = (cid)
+
+#define MOVE_WINDOW_MESSAGE_GET_WID(pBuf) \
+    ((((MoveWindowMessage*)(pBuf))->wid))
+
+#define MOVE_WINDOW_MESSAGE_SET_WID(pBuf, widval) \
+    ((MoveWindowMessage *)(pBuf))->wid = (widval)
+
+#define MOVE_WINDOW_MESSAGE_GET_Y(pBuf) \
+    ((((MoveWindowMessage*)(pBuf))->y))
+
+#define MOVE_WINDOW_MESSAGE_SET_Y(pBuf, yval) \
+    ((MoveWindowMessage *)(pBuf))->y = (yval)
+
+/* Same structure used for both server and client messages */
+
+typedef struct resizewindowmessage_struct {
+    CARD8 	msgType;
+    CARD8       pad1;
+    CARD16      pad2;
+    CARD32      clientId;
+    CARD32      wid;
+    CARD32      width;
+    CARD32      height;
+} ResizeWindowMessage;
+
+#define RESIZE_WINDOW_MESSAGE_SIZE sizeof(ResizeWindowMessage)
+
+#define RESIZE_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((ResizeWindowMessage *)(pBuf))->msgType = (mType)
+
+#define RESIZE_WINDOW_MESSAGE_GET_CLIENT_ID(pBuf) \
+    ((((ResizeWindowMessage*)(pBuf))->clientId))
+
+#define RESIZE_WINDOW_MESSAGE_SET_CLIENT_ID(pBuf, cid) \
+    ((ResizeWindowMessage *)(pBuf))->CLIENT_ID = (cid)
+
+#define RESIZE_WINDOW_MESSAGE_GET_WID(pBuf) \
+    ((((ResizeWindowMessage*)(pBuf))->wid))
+
+#define RESIZE_WINDOW_MESSAGE_SET_WID(pBuf, widval) \
+    ((ResizeWindowMessage *)(pBuf))->wid = (widval)
+
+#define RESIZE_WINDOW_MESSAGE_GET_WIDTH(pBuf) \
+    ((((ResizeWindowMessage*)(pBuf))->width))
+
+#define RESIZE_WINDOW_MESSAGE_SET_WIDTH(pBuf, w) \
+    ((ResizeWindowMessage *)(pBuf))->width = (w)
+
+#define RESIZE_WINDOW_MESSAGE_GET_HEIGHT(pBuf) \
+    ((((ResizeWindowMessage*)(pBuf))->height))
+
+#define RESIZE_WINDOW_MESSAGE_SET_HEIGHT(pBuf, h) \
+    ((ResizeWindowMessage *)(pBuf))->height = (h)
+
+typedef struct hellomessage_struct {
+    CARD8 	msgType;
+} HelloMessage;
+
+#define MOVE_WINDOW_MESSAGE_SIZE sizeof(MoveWindowMessage)
+
+/*
+** Server to Client Messages
+*/
+
+#define SERVER_MESSAGE_TYPE_CREATE_WINDOW    		0
+#define SERVER_MESSAGE_TYPE_DESTROY_WINDOW   		1
+#define SERVER_MESSAGE_TYPE_SHOW_WINDOW      		2
+#define SERVER_MESSAGE_TYPE_CONFIGURE_WINDOW 		3
+#define SERVER_MESSAGE_TYPE_POSITION_WINDOW  		4
+#define SERVER_MESSAGE_TYPE_WINDOW_SET_DECORATED  	5
+#define SERVER_MESSAGE_TYPE_WINDOW_SET_BORDER_WIDTH  	6
+#define SERVER_MESSAGE_TYPE_BEEP	 		7
+#define SERVER_MESSAGE_TYPE_DISPLAY_PIXELS	 	8
+#define SERVER_MESSAGE_TYPE_COPY_AREA    	 	9
+#define SERVER_MESSAGE_TYPE_CONTROLLER_STATUS	 	10
+#define SERVER_MESSAGE_TYPE_DISPLAY_CURSOR 		11
+#define SERVER_MESSAGE_TYPE_MOVE_CURSOR                 12
+#define SERVER_MESSAGE_TYPE_SHOW_CURSOR                 13
+#define SERVER_MESSAGE_TYPE_SET_WINDOW_TITLES           14
+#define SERVER_MESSAGE_TYPE_WELCOME                 	15
+#define SERVER_MESSAGE_TYPE_PING                 	16
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	decorated;		
+    CARD16 	borderWidth;
+    CARD32 	wid;
+    CARD16 	x;
+    CARD16 	y;
+    CARD32 	wAndBorder;  /* Includes 2 * bw */
+    CARD32 	hAndBorder;  /* Includes 2 * bw */
+} CreateWindowMessage;
+
+#define CREATE_WINDOW_MESSAGE_SIZE sizeof(CreateWindowMessage)
+
+#define CREATE_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((CreateWindowMessage *)(pBuf))->msgType = (mType)
+
+#define CREATE_WINDOW_MESSAGE_SET_DECORATED(pBuf, decor) \
+    ((CreateWindowMessage *)(pBuf))->decorated = (decor)
+
+#define CREATE_WINDOW_MESSAGE_SET_BORDER_WIDTH(pBuf, bw) \
+    ((CreateWindowMessage *)(pBuf))->borderWidth = (bw)
+
+#define CREATE_WINDOW_MESSAGE_SET_WID(pBuf, windowId) \
+    ((CreateWindowMessage *)(pBuf))->wid = (windowId)
+
+#define CREATE_WINDOW_MESSAGE_SET_X(pBuf, xval) \
+    ((CreateWindowMessage *)(pBuf))->x = (xval)
+
+#define CREATE_WINDOW_MESSAGE_SET_Y(pBuf, yval) \
+    ((CreateWindowMessage *)(pBuf))->y = (yval)
+
+#define CREATE_WINDOW_MESSAGE_SET_WANDBORDER(pBuf, wandb) \
+    ((CreateWindowMessage *)(pBuf))->wAndBorder = (wandb)
+
+#define CREATE_WINDOW_MESSAGE_SET_HANDBORDER(pBuf, handb) \
+    ((CreateWindowMessage *)(pBuf))->hAndBorder = (handb)
+
+/* Same structure used for both server and client messages */
+
+typedef struct {
+    CARD8 	msgType;			
+    CARD8 	pad1;		
+    CARD16 	pad2;
+    CARD32 	wid;
+} DestroyWindowMessage;
+
+#define DESTROY_WINDOW_MESSAGE_SIZE sizeof(DestroyWindowMessage)
+
+#define DESTROY_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((DestroyWindowMessage *)(pBuf))->msgType = (mType)
+
+#define DESTROY_WINDOW_MESSAGE_GET_WID(pBuf) \
+    ((((DestroyWindowMessage*)(pBuf))->wid))
+
+#define DESTROY_WINDOW_MESSAGE_SET_WID(pBuf, windowId) \
+    ((DestroyWindowMessage *)(pBuf))->wid = (windowId)
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	show;		
+    CARD16 	pad;
+    CARD32 	wid;
+} ShowWindowMessage;
+
+#define SHOW_WINDOW_MESSAGE_SIZE sizeof(ShowWindowMessage)
+
+#define SHOW_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((ShowWindowMessage *)(pBuf))->msgType = (mType)
+
+#define SHOW_WINDOW_MESSAGE_SET_WID(pBuf, windowId) \
+    ((ShowWindowMessage *)(pBuf))->wid = (windowId)
+
+#define SHOW_WINDOW_MESSAGE_SET_SHOW(pBuf, showit) \
+    ((ShowWindowMessage *)(pBuf))->show = (showit)
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	pad1;
+    CARD16	pad2;
+    CARD32      clientId;
+    CARD32 	wid;
+    CARD16 	x;
+    CARD16 	y;
+    CARD32 	wAndBorder;    /* Includes 2 * bw */
+    CARD32 	hAndBorder;    /* Includes 2 * bw */
+    CARD32 	sibid;
+} ConfigureWindowMessage;
+
+#define CONFIGURE_WINDOW_MESSAGE_SIZE sizeof(ConfigureWindowMessage)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((ConfigureWindowMessage *)(pBuf))->msgType = (mType)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_CLIENT_ID(pBuf, cid) \
+    ((ConfigureWindowMessage *)(pBuf))->clientId = (clientId)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_WID(pBuf, windowId) \
+    ((ConfigureWindowMessage *)(pBuf))->wid = (windowId)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_X(pBuf, xval) \
+    ((ConfigureWindowMessage *)(pBuf))->x = (xval)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_Y(pBuf, yval) \
+    ((ConfigureWindowMessage *)(pBuf))->y = (yval)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_WANDBORDER(pBuf, wandb) \
+    ((ConfigureWindowMessage *)(pBuf))->wAndBorder = (wandb)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_HANDBORDER(pBuf, handb) \
+    ((ConfigureWindowMessage *)(pBuf))->hAndBorder = (handb)
+
+#define CONFIGURE_WINDOW_MESSAGE_SET_SIBID(pBuf, siblingId) \
+    ((ConfigureWindowMessage *)(pBuf))->sibid = (siblingId)
+
+typedef struct  {
+    CARD8 	msgType;
+    CARD8 	pad1;
+    CARD16 	pad2;
+    CARD32      clientId;
+    CARD32 	wid;
+    CARD16 	x;
+    CARD16 	y;
+} PositionWindowMessage;
+
+#define POSITION_WINDOW_MESSAGE_SIZE sizeof(PositionWindowMessage)
+
+#define POSITION_WINDOW_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((PositionWindowMessage *)(pBuf))->msgType = (mType)
+
+#define POSITION_WINDOW_MESSAGE_SET_CLIENT_ID(pBuf, cid) \
+    ((PositionWindowMessage *)(pBuf))->clientId = (clientId)
+
+#define POSITION_WINDOW_MESSAGE_SET_WID(pBuf, windowId) \
+    ((PositionWindowMessage *)(pBuf))->wid = (windowId)
+
+#define POSITION_WINDOW_MESSAGE_SET_X(pBuf, xval) \
+    ((PositionWindowMessage *)(pBuf))->x = (xval)
+
+#define POSITION_WINDOW_MESSAGE_SET_Y(pBuf, yval) \
+    ((PositionWindowMessage *)(pBuf))->y = (yval)
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	decorated;
+    CARD16 	pad;
+    CARD32 	wid;
+} WindowSetDecoratedMessage;
+
+#define WINDOW_SET_DECORATED_MESSAGE_SIZE sizeof(WindowSetDecoratedMessage)
+
+#define WINDOW_SET_DECORATED_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((WindowSetDecoratedMessage *)(pBuf))->msgType = (mType)
+
+#define WINDOW_SET_DECORATED_MESSAGE_SET_DECORATED(pBuf, decor) \
+    ((WindowSetDecoratedMessage *)(pBuf))->decorated = (decor)
+
+#define WINDOW_SET_DECORATED_MESSAGE_SET_WID(pBuf, windowId) \
+    ((WindowSetDecoratedMessage *)(pBuf))->wid = (windowId)
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	pad;
+    CARD16 	borderWidth;
+    CARD32 	wid;
+} WindowSetBorderWidthMessage;
+
+#define WINDOW_SET_BORDER_WIDTH_MESSAGE_SIZE sizeof(WindowSetBorderWidthMessage)
+
+#define WINDOW_SET_BORDER_WIDTH_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((WindowSetBorderWidthMessage *)(pBuf))->msgType = (mType)
+
+#define WINDOW_SET_BORDER_WIDTH_MESSAGE_SET_BORDER_WIDTH(pBuf, bw) \
+    ((WindowSetBorderWidthMessage *)(pBuf))->borderWidth = (bw)
+
+#define WINDOW_SET_BORDER_WIDTH_MESSAGE_SET_WID(pBuf, windowId) \
+    ((WindowSetBorderWidthMessage *)(pBuf))->wid = (windowId)
+
+typedef struct {
+    CARD8 	msgType;
+} BeepMessage;
+
+#define BEEP_MESSAGE_SIZE sizeof(BeepMessage)
+
+#define BEEP_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((BeepMessage *)(pBuf))->msgType = (mType)
+
+#define DISPLAY_PIXELS_ENCODING_UNCODED    0
+#define DISPLAY_PIXELS_ENCODING_RLE24      1
+
+/* 
+** Note: Don't use xRectangle because x and y are constrained
+** to fit in shorts because they are clipped to the screen.
+*/
+
+typedef struct {
+    CARD16    x;
+    CARD16    y;
+    CARD16    width;
+    CARD16    height;
+
+    /* How pixels which follow are encoded */
+    CARD32    encodingType;
+
+} DirtyAreaRectRec, *DirtyAreaRectPtr;
+    
+#define DIRTY_AREA_RECT_SIZE sizeof(DirtyAreaRectRec)
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	pad;
+    CARD16      numDirty;
+    CARD32 	wid;
+} DisplayPixelsMessage;
+
+#define DISPLAY_PIXELS_MESSAGE_SIZE sizeof(DisplayPixelsMessage)
+
+#define DISPLAY_PIXELS_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((DisplayPixelsMessage *)(pBuf))->msgType = (mType)
+
+#define DISPLAY_PIXELS_MESSAGE_SET_NUM_DIRTY(pBuf, n) \
+    ((DisplayPixelsMessage *)(pBuf))->numDirty = (n)
+
+#define DISPLAY_PIXELS_MESSAGE_SET_WID(pBuf, windowId) \
+    ((DisplayPixelsMessage *)(pBuf))->wid = (windowId)
+
+typedef struct {
+    CARD8 	msgType;
+    CARD8 	pad1;		
+    CARD16 	pad2;
+    CARD32 	wid;
+    CARD32 	srcx;
+    CARD32 	srcy;
+    CARD32 	width;
+    CARD32 	height;
+    CARD32 	dstx;
+    CARD32 	dsty;
+} CopyAreaMessage;
+
+#define COPY_AREA_MESSAGE_SIZE sizeof(CopyAreaMessage)
+
+#define COPY_AREA_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((CopyAreaMessage *)(pBuf))->msgType = (mType)
+
+#define COPY_AREA_MESSAGE_SET_WID(pBuf, windowId) \
+    ((CopyAreaMessage *)(pBuf))->wid = (windowId)
+
+#define COPY_AREA_MESSAGE_SET_SRCX(pBuf, sx) \
+    ((CopyAreaMessage *)(pBuf))->srcx = (sx)
+
+#define COPY_AREA_MESSAGE_SET_SRCY(pBuf, sy) \
+    ((CopyAreaMessage *)(pBuf))->srcy = (sy)
+
+#define COPY_AREA_MESSAGE_SET_WIDTH(pBuf, w) \
+    ((CopyAreaMessage *)(pBuf))->width = (w)
+
+#define COPY_AREA_MESSAGE_SET_HEIGHT(pBuf, h) \
+    ((CopyAreaMessage *)(pBuf))->height = (h)
+
+#define COPY_AREA_MESSAGE_SET_DSTX(pBuf, dx) \
+    ((CopyAreaMessage *)(pBuf))->dstx = (dx)
+
+#define COPY_AREA_MESSAGE_SET_DSTY(pBuf, dy) \
+    ((CopyAreaMessage *)(pBuf))->dsty = (dy)
+
+typedef struct controllerstatusmessage_struct {
+    CARD8 	msgType;			
+    CARD8       status;
+    CARD16      pad;
+    CARD32      clientId;
+} ControllerStatusMessage;
+
+/* The attempt of the specified client to take control has been refused */
+#define CONTROLLER_STATUS_REFUSED        0
+
+/* The specified client has lost control */
+#define CONTROLLER_STATUS_LOST           1
+
+/* The specified client has gained control */
+#define CONTROLLER_STATUS_GAINED         2
+
+#define CONTROLLER_STATUS_MESSAGE_SIZE sizeof(ControllerStatusMessage)
+
+#define CONTROLLER_STATUS_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((ControllerStatusMessage *)(pBuf))->msgType = (mType)
+
+#define CONTROLLER_STATUS_MESSAGE_SET_STATUS(pBuf, stat) \
+    ((ControllerStatusMessage*)(pBuf))->status = (stat)
+
+#define CONTROLLER_STATUS_MESSAGE_SET_CLIENTID(pBuf, cid) \
+    ((ControllerStatusMessage*)(pBuf))->clientId = (cid)
+
+typedef struct displaycursormessage_struct {
+
+    CARD8 	msgType;			
+    CARD8       pad1;
+    CARD16      pad2;
+    CARD16      width;
+    CARD16      height;
+    CARD16      xhot;
+    CARD16      yhot;
+
+    /* Followed by (width * height) 32-bit pixels */
+
+} DisplayCursorMessage;
+
+#define DISPLAY_CURSOR_MESSAGE_SIZE sizeof(DisplayCursorMessage)
+
+#define DISPLAY_CURSOR_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((DisplayCursorMessage *)(pBuf))->msgType = (mType)
+
+#define DISPLAY_CURSOR_MESSAGE_SET_WIDTH(pBuf, w) \
+    ((DisplayCursorMessage *)(pBuf))->width = (w)
+
+#define DISPLAY_CURSOR_MESSAGE_SET_HEIGHT(pBuf, h) \
+    ((DisplayCursorMessage *)(pBuf))->height = (h)
+
+#define DISPLAY_CURSOR_MESSAGE_SET_XHOT(pBuf, xh) \
+    ((DisplayCursorMessage *)(pBuf))->xhot = (xh)
+
+#define DISPLAY_CURSOR_MESSAGE_SET_YHOT(pBuf, yh) \
+    ((DisplayCursorMessage *)(pBuf))->yhot = (yh)
+
+typedef struct movecursormessage_struct {
+    CARD8 	msgType;			
+    CARD8       pad1;
+    CARD16      pad2;
+    CARD32      wid;
+    CARD32      x;
+    CARD32      y;
+} MoveCursorMessage;
+
+#define MOVE_CURSOR_MESSAGE_SIZE sizeof(MoveCursorMessage)
+
+#define MOVE_CURSOR_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((MoveCursorMessage *)(pBuf))->msgType = (mType)
+
+#define MOVE_CURSOR_MESSAGE_SET_WID(pBuf, windowId) \
+    ((MoveCursorMessage *)(pBuf))->wid = (windowId)
+
+#define MOVE_CURSOR_MESSAGE_SET_X(pBuf, cx) \
+    ((MoveCursorMessage *)(pBuf))->x = (cx)
+
+#define MOVE_CURSOR_MESSAGE_SET_Y(pBuf, cy) \
+    ((MoveCursorMessage *)(pBuf))->y = (cy)
+
+typedef struct showcursormessage_struct {
+    CARD8 	msgType;			
+    CARD8       show;
+} ShowCursorMessage;
+
+#define SHOW_CURSOR_MESSAGE_SIZE sizeof(ShowCursorMessage)
+
+#define SHOW_CURSOR_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((ShowCursorMessage *)(pBuf))->msgType = (mType)
+
+#define SHOW_CURSOR_MESSAGE_SET_SHOW(pBuf, showit) \
+    ((ShowCursorMessage *)(pBuf))->show = (showit)
+
+typedef struct welcomessage_struct {
+    CARD8 	msgType;			
+    CARD8       pad1;
+    CARD16      pad2;
+    CARD32      clientId;
+} WelcomeMessage;
+
+#define WELCOME_MESSAGE_SIZE sizeof(WelcomeMessage)
+
+#define WELCOME_MESSAGE_SET_TYPE(pBuf, mType) \
+    ((WelcomeMessage *)(pBuf))->msgType = (mType)
+
+#define WELCOME_MESSAGE_SET_CLIENT_ID(pBuf, cid) \
+    ((WelcomeMessage *)(pBuf))->clientId = (cid)
+
+#endif /* PROTOCOL_H */
diff --git a/hw/vfb/remwin.h b/hw/vfb/remwin.h
new file mode 100644
index 0000000..f545d25
--- /dev/null
+++ b/hw/vfb/remwin.h
@@ -0,0 +1,190 @@
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+#ifndef REMWIN_H
+#define REMWIN_H
+
+#include "scrnintstr.h"
+#include "regionstr.h"
+#include "rwcomm.h"
+#include "gcstruct.h"
+
+/* Don't send any pixel buffers larger than 16KB */
+#define PIXEL_BUF_MAX_NUM_BYTES (1024*16)
+#define PIXEL_BUF_MAX_NUM_PIXELS (PIXEL_BUF_MAX_NUM_BYTES/4)
+
+/* 
+** The RLE algorithm used never creates more pixels than
+** is in the original buffer, so the max number of pixels
+** provides an upper bound on the maximum number of runs.
+*/
+#define RLE_BUF_MAX_NUM_BYTES PIXEL_BUF_MAX_NUM_BYTES
+#define RLE_BUF_MAX_NUM_PIXELS (RLE_BUF_MAX_NUM_BYTES/4)
+
+typedef struct remwin_scr_priv_rec {
+    RwcommPtr                   pComm;
+    OsTimerPtr                  outputTimer;
+    CloseScreenProcPtr		CloseScreen;
+    ScreenWakeupHandlerProcPtr 	WakeupHandler;
+    CreateWindowProcPtr		CreateWindow;
+    RealizeWindowProcPtr	RealizeWindow;
+    UnrealizeWindowProcPtr	UnrealizeWindow;
+    DestroyWindowProcPtr	DestroyWindow;
+    PositionWindowProcPtr	PositionWindow;
+    ResizeWindowProcPtr		ResizeWindow;
+    ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+    CreateGCProcPtr             CreateGC;
+    DisplayCursorProcPtr        DisplayCursor;
+    SetCursorPositionProcPtr    SetCursorPosition;
+
+    unsigned char *pPixelBuf;
+    unsigned char *pRleBuf;
+
+    /* List of managed o(top-level, drawable) windows */
+    WindowPtr   pManagedWindows;
+
+    /* 
+    ** Which client currently has interactive control.
+    ** -1 indicates no one has control.
+    */
+    int controller;
+
+    /* Which pointer buttons the controller has pressed */
+    int controllerButtonMask;
+    
+    /* The currently displayed cursor */
+    CursorPtr pCursor;
+
+    /* 
+    ** The managed window the cursor is in. 
+    ** NULL if cursor isn't shown 
+    */
+    WindowPtr pCursorWin;
+
+    /* The cursor position (relative to pCursorWin) */
+    int cursorX;
+    int cursorY;
+
+    /* The window manager client */
+    ClientPtr pWmClient;
+
+    /* 
+    ** When this is -1 window moves and resizes are programmatic.
+    ** (i.e. invoked by the application). When this is not -1
+    ** window moves and resizes are being made by the user.
+    */
+    int configuringClient;
+
+    /* True when any windows may have unsent dirty pixels */
+    Bool windowsAreDirty;
+
+} RemwinScreenPrivRec, *RemwinScreenPrivPtr;
+
+#define REMWIN_GET_SCRPRIV(pScreen) \
+    ((RemwinScreenPrivPtr)((pScreen)->devPrivates[remwinScreenIndex].ptr))
+
+#define REMWIN_GET_WINPRIV(pWin) \
+    ((RemwinWindowPrivPtr)(pWin)->devPrivates[remwinWinIndex].ptr);
+
+/* DELETE: no longer used 
+#define REMWIN_SET_WINPRIV(pWin, pWinPriv) \
+    (pWin)->devPrivates[remwinWinIndex].ptr = (pointer)pWinPriv;
+*/
+
+typedef struct remwin_window_priv_rec *RemwinWindowPrivPtr;
+
+typedef struct remwin_window_priv_rec {
+
+    /* 
+    ** The window has been dirtied. That is, there are updates to send
+    ** to the client. (One or both of the regions has been updated).
+    */
+    Bool dirty;
+
+    /* Whether the window has been mapped */
+    Bool mapped;
+
+    /* The area of the window that has been dirtied */
+    RegionRec dirtyReg;
+
+    /* The link to the next window (not winpriv!) */
+    WindowPtr pWinNext;
+
+} RemwinWindowPrivRec;
+
+#define REMWIN_GET_GCPRIV(pGC) \
+    ((RemwinGCPrivPtr)(pGC)->devPrivates[remwinGCIndex].ptr);
+
+/* DELETE: no longer used 
+#define REMWIN_SET_GCPRIV(pGC, pGCPriv) \
+    (pWin)->devPrivates[remwinGCIndex].ptr = (pointer)pGCPriv;
+*/
+
+typedef struct remwin_gc_priv_rec *RemwinGCPrivPtr;
+
+typedef struct remwin_gc_priv_rec {
+    GCOps	    *wrapOps;	    /* wrapped ops */
+    GCFuncs	    *wrapFuncs;	    /* wrapped funcs */
+} RemwinGCPrivRec;
+
+extern RemwinScreenPrivRec remwinScreenPriv;
+
+extern void rwoutTimerCreate (ScreenPtr pScreen);
+extern void rwoutTimerDestroy (ScreenPtr pScreen);
+
+extern void rwinHandler (ScreenPtr pScreen);
+
+/* Maximum pixel output rate is 30 fps */
+#define MAX_OUTPUT_RATE 30.0
+#define TIMER_MS ((int)((1/MAX_OUTPUT_RATE) * 1000.0))
+
+extern Bool rwoutInitScreen (ScreenPtr pScreen);
+
+extern void rwTakeControlInit (ScreenPtr pScreen);
+extern void rwTakeControl (ScreenPtr pScreen, int clientId, Bool steal);
+
+extern int remwinScreenIndex;
+
+extern Bool rwoutSetWindowTitlesWrite (ScreenPtr pScreen, int strLen, char *buf);
+
+extern void rwoutBeep (int percent, DeviceIntPtr pDevice,
+		       pointer ctrl, int unused);
+
+extern void rwoutSyncClientOnConnect (ScreenPtr pScreen, RwcommClientPtr pCommClient);
+
+extern Bool rlePixelsWrite (ScreenPtr pScreen, WindowPtr pWin, int x, int y, int w, int h);
+
+extern Bool vfbRemoteWindow;
+
+#endif /* REMWIN_H */
diff --git a/hw/vfb/rle.c b/hw/vfb/rle.c
new file mode 100644
index 0000000..e8c81a0
--- /dev/null
+++ b/hw/vfb/rle.c
@@ -0,0 +1,235 @@
+#undef VERBOSE
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+/* TODO: prune these */
+#include <unistd.h>
+#include "regionstr.h"
+#include "damage.h"
+#include "windowstr.h"
+#include "remwin.h"
+#include "rwcomm.h"
+#include "misc.h"
+#include "protocol.h"
+#include "cursorstr.h"
+#include "servermd.h"
+#include "rwcommsock.h"
+
+extern Bool rwRleVerifyPixels;
+
+#define RGB_MASK 0x00ffffff
+
+#define ROUNDUP(fval) (int)((fval)+1)
+
+#define MIN(a, b) (((a)>(b))?(b):(a))
+
+#define MAX_COUNT 255
+
+#define NEXT_PIXEL(pixel) { \
+    if (linesLeftInChunk <= 0) { \
+	/* End of chunk */ \
+	(pixel) = -1; \
+        /*ErrorF("y,x,ll at end of chunk = %d, %d, %d\n", y, x, linesLeftInChunk);*/ \
+    } else {\
+        (pixel) = *(pPixel++) & RGB_MASK; \
+        /* Advance pointers */ \
+        if (++x >= xLimit) { \
+	    y++; \
+	    linesLeftInChunk--; \
+            pLine += w; \
+	    pPixel = pLine; \
+	    x = xStart;\
+        } \
+    } \
+}
+
+#ifdef VERBOSE
+
+static int maxVerboseRuns = 120;
+static int numRunsOutput = 0;
+
+#define OUTPUT_PIXEL(count, pixel) { \
+    /* \
+    if (numRunsOutput++ < maxVerboseRuns) { \
+        ErrorF("numRuns = %d, count = %d, pixel = 0x%x\n", numRunsOutput, count, pixel); \
+    } \
+    */ \
+    if (pDst >= pDstLimit) { \
+	FatalError("Buffer overflow, pDst = 0x%x, 0x%x\n", (int)pDst, (int)pDstLimit); \
+    } \
+    *pDst++ = ((count) << 24) | (pixel); \
+    bytesInChunk += 4; \
+}
+#else
+#define OUTPUT_PIXEL(count, pixel) { \
+    *pDst++ = ((count) << 24) | (pixel); \
+    bytesInChunk += 4; \
+}
+#endif /* VERBOSE */
+
+Bool
+rlePixelsWrite (ScreenPtr pScreen, WindowPtr pWin, int x, int y, int w, int h)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    RwcommPtr pComm = pScrPriv->pComm;
+    char buf[DIRTY_AREA_RECT_SIZE];
+    DirtyAreaRectPtr pDirty = (DirtyAreaRectPtr) &buf[0];
+    int *pSrc, *pDst, *pLine, *pPixel, *pChunkHeight, *pNumOutBytes;
+    int linesLeft, xStart, xLimit, chunkHeight;
+    int numChunks, linesLeftInChunk;
+    int count, a, b;
+    int bytesInChunk;
+    int i, n;
+
+    /* TODO: for debug */
+    int *pDstLimit;
+
+    chunkHeight = RLE_BUF_MAX_NUM_PIXELS / w;
+    numChunks = ROUNDUP((float)h / chunkHeight);
+#ifdef VERBOSE
+    ErrorF("chunkHeight = %d\n", chunkHeight);
+    ErrorF("numChunks = %d\n", numChunks);
+#endif /* VERBOSE */
+    
+    /* Prepare rectangle description */
+    pDirty->x = x;
+    pDirty->y = y;
+    pDirty->width = w;
+    /* TODO: HACK: notify the client of verification via negative numChunks */
+    if (rwRleVerifyPixels) {
+	pDirty->height = -numChunks;
+    } else {
+	pDirty->height = numChunks;
+    }
+    pDirty->encodingType = DISPLAY_PIXELS_ENCODING_RLE24;
+#ifdef VERBOSE
+    ErrorF("x = %d\n", x);
+    ErrorF("y = %d\n", y);
+    ErrorF("y = %d\n", h);
+    ErrorF("w = %d\n", w);
+#endif /* VERBOSE */
+
+    swaps(&pDirty->x, n);
+    swaps(&pDirty->y, n);
+    swaps(&pDirty->width, n);
+    swaps(&pDirty->height, n);
+    swapl(&pDirty->encodingType, a);
+
+    /* Send it off */
+    if (!RWCOMM_BUFFER_WRITE(pComm, buf, DIRTY_AREA_RECT_SIZE)) {    
+	return FALSE;
+    }
+
+    /* Lazy allocation of pixel buffer*/
+    if (pScrPriv->pPixelBuf == NULL) {
+	pScrPriv->pPixelBuf = (unsigned char *) 
+	    xalloc(PIXEL_BUF_MAX_NUM_BYTES);
+    }
+    pSrc = (int *) pScrPriv->pPixelBuf;
+
+    /* Lazy allocation of rle output buffer*/
+    if (pScrPriv->pRleBuf == NULL) {
+	pScrPriv->pRleBuf = (unsigned char *) 
+	    xalloc(RLE_BUF_MAX_NUM_BYTES + 10);
+    }
+
+    linesLeft = h;
+    xStart = x;
+    xLimit = x + w;
+
+    pChunkHeight = (int *) buf;
+    for (i = 0; i < numChunks; i++) {
+	
+	/* ErrorF("Filling chunk %d\n", i); */
+
+	/* This is a fresh chunk; start at the beginning of the buffer */
+	pDst = (int *) pScrPriv->pRleBuf;
+	pDstLimit = (int *) ((char *)pDst + RLE_BUF_MAX_NUM_BYTES + 10);
+
+	/* Clamp chunk height and send it */
+	chunkHeight = MIN(linesLeft, chunkHeight);
+	*pChunkHeight = chunkHeight;
+	swapl(pChunkHeight, n);
+	if (!RWCOMM_BUFFER_WRITE(pComm, buf, 4)) { 
+	    return FALSE;
+	}
+
+	/* Fetch chunk from frame buffer */
+	(*pScreen->GetImage)((DrawablePtr)pWin, x, y, w, chunkHeight, 
+			     ZPixmap, ~0, (char *) pSrc);
+	pLine = pSrc;
+	pPixel = pLine;
+    
+	linesLeftInChunk = chunkHeight;
+	bytesInChunk = 0;
+	count = 1;
+	NEXT_PIXEL(a);
+	NEXT_PIXEL(b);
+
+	while (b >= 0) {
+	    if (a == b) {
+		if (count == MAX_COUNT) {
+		    OUTPUT_PIXEL(count, a);
+		    count = 1;
+		} else {
+		    count++;
+		}	
+	    } else {
+		OUTPUT_PIXEL(count, a);
+		a = b;
+		count = 1;
+	    }
+	    NEXT_PIXEL(b);
+	}
+	OUTPUT_PIXEL(count, a);
+		    
+	/* 
+	** Now send the number of bytes in the chunk followed by 
+	** the chunk data.
+	*/
+	pNumOutBytes = (int *) buf;
+	*pNumOutBytes = bytesInChunk;
+	swapl(pNumOutBytes, n);
+	if (!RWCOMM_BUFFER_WRITE(pComm, buf, 4)) { 
+	    return FALSE;
+	}
+	if (!RWCOMM_BUFFER_WRITE(pComm, (char *)pScrPriv->pRleBuf, bytesInChunk)) { 
+	    return FALSE;
+	}
+
+	linesLeft -= chunkHeight;
+    }
+
+    return TRUE;
+}
diff --git a/hw/vfb/rwcomm.h b/hw/vfb/rwcomm.h
new file mode 100644
index 0000000..f65c84f
--- /dev/null
+++ b/hw/vfb/rwcomm.h
@@ -0,0 +1,98 @@
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+#ifndef RWCOMM_H
+#define RWCOMM_H
+
+#define RWCOMM_DESTROY(pComm) \
+    (pComm)->funcs.destroy(pComm)
+
+#define RWCOMM_CONNECT(pComm) \
+    (pComm)->funcs.connect(pComm)
+
+#define RWCOMM_DISCONNECT(pComm) \
+    (pComm)->funcs.disconnect(pComm)
+
+#define RWCOMM_IS_CONNECTED(pComm) \
+    (pComm)->funcs.isConnected(pComm)
+
+#define RWCOMM_BUFFER_WRITE(pComm, pBuf, bufLen) \
+    (pComm)->funcs.bufferWrite((pComm), (pBuf), (bufLen))
+
+#define RWCOMM_BUFFER_WRITE_TO_CLIENT(pComm, clientId, pBuf, bufLen) \
+    (pComm)->funcs.bufferWriteToClient((pComm), (clientId), (pBuf), (bufLen))
+
+#define RWCOMM_NEXT_MESSAGE_TYPE_READ(pComm) \
+    (pComm)->funcs.nextMessageTypeRead(pComm)
+
+#define RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf, readLen) \
+    (pComm)->funcs.nextMessageBufferRead((pComm), (buf), (readLen))
+
+#define RWCOMM_CLIENT_MESSAGE_POLL(pComm, pReadMask) \
+    (pComm)->funcs.clientMessagePoll((pComm), (pReadmask))
+
+typedef struct rwcomm_rec *RwcommPtr;
+
+typedef void (*RwcommFuncPtrDestroy)(RwcommPtr pComm);
+typedef void (*RwcommFuncPtrConnect)(RwcommPtr pComm);
+typedef void (*RwcommFuncPtrDisconnect)(RwcommPtr pComm);
+typedef Bool (*RwcommFuncPtrIsConnected)(RwcommPtr pComm);
+typedef Bool (*RwcommFuncPtrBufferWrite)(RwcommPtr pComm, 
+					 char *buf, int bufLen);
+typedef Bool (*RwcommFuncPtrBufferWriteToClient)(RwcommPtr pComm, 
+					 int clientId, char *buf, int bufLen);
+typedef int (*RwcommFuncPtrNextMessageTypeRead)(RwcommPtr pComm);
+typedef int (*RwcommFuncPtrNextMessageBufferRead)(RwcommPtr pComm,
+						  char *buf, int readLen);
+typedef void (*RwcommFuncPtrClientMessagePoll)(RwcommPtr pComm, fd_set *pReadMask);
+
+typedef struct rwcomm_funcptr_rec {
+    RwcommFuncPtrDestroy		destroy;
+    RwcommFuncPtrConnect		connect;
+    RwcommFuncPtrDisconnect		disconnect;
+    RwcommFuncPtrIsConnected            isConnected;
+    RwcommFuncPtrBufferWrite            bufferWrite;
+    RwcommFuncPtrBufferWriteToClient    bufferWriteToClient;
+    RwcommFuncPtrNextMessageTypeRead    nextMessageTypeRead;
+    RwcommFuncPtrNextMessageBufferRead  nextMessageBufferRead;
+    RwcommFuncPtrClientMessagePoll      clientMessagePoll;
+} RwcommFuncPtrRec, *RwcommFuncPtrPtr;
+
+typedef struct rwcomm_rec {
+    RwcommFuncPtrRec funcs;
+} RwcommRec;
+
+typedef pointer RwcommClientPtr;
+
+#endif /* RWCOMM_H */
diff --git a/hw/vfb/rwcommsock.c b/hw/vfb/rwcommsock.c
new file mode 100644
index 0000000..dacb107
--- /dev/null
+++ b/hw/vfb/rwcommsock.c
@@ -0,0 +1,457 @@
+#undef VERBOSE
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+#include <unistd.h>
+#include <errno.h>
+#include <X11/Xproto.h>
+#include "dix-config.h"
+#include "remwin.h"
+#include "rwcomm.h"
+#include "rwcommsock.h"
+#include "protocol.h"
+#include "opaque.h"
+#include <arpa/inet.h>
+#include <fcntl.h>
+
+static void rwcommsockDisconnect (RwcommPtr pComm);
+static int WriteFully (int sock, char *pbuf, int bufLen);
+static int ReadFully (int sock, char *pbuf, int bufLen);
+
+/*
+** Disconnect all activate connections and free the comm module.
+*/
+
+static void
+rwcommsockDestroy (RwcommPtr pComm) 
+{
+    rwcommsockDisconnect(pComm);
+    xfree(pComm);
+}
+
+/* TODO: notyet
+static Bool firstClient = TRUE;
+*/
+
+/*
+** Called when a new client connection is received.
+*/
+
+static void
+rwcommsockConnect (RwcommPtr pComm)
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    ScreenPtr pScreen = pCommsock->pScreen;
+
+    pCommsock->isConnected = TRUE;
+
+    rwoutTimerCreate(pScreen);
+
+    rwTakeControlInit(pScreen);
+
+    // TODO: DS: clientptr is an opaque handle to the client's sessionid
+    rwoutSyncClientOnConnect(pScreen, NULL);
+
+    /* TODO: notyet
+    if (firstClient) {
+	// By this time we know that composite has been enabled and
+	// it is safe to discard frame buffer memory
+	ErrorF("Discarding fb memory");
+	ddxGiveUp();
+	firstClient = FALSE;
+    }
+    */
+}
+
+/*
+** Disconnect all connections.
+*/
+
+static void
+rwcommsockDisconnect (RwcommPtr pComm) 
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+
+    FD_CLR(pCommsock->socket, &pCommsock->fdSetPoll);
+    RemoveEnabledDevice(pCommsock->socket);
+    close(pCommsock->socket);
+
+    if (pCommsock->sockServer > 0) {
+    	if (close(pCommsock->sockServer)) {
+	    ErrorF("rwcommsockDisconnect failed\n");
+	    return;
+	}
+    }
+
+    pCommsock->isConnected = FALSE;
+    rwoutTimerDestroy(pCommsock->pScreen);
+
+    ErrorF("Client disconnected\n");
+}
+
+static Bool
+rwcommsockIsConnected (RwcommPtr pComm) 
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    return pCommsock->isConnected;
+}
+
+/* 
+** Broadcast buffer to all clients 
+*/
+
+static Bool
+rwcommsockBufferWrite (RwcommPtr pComm, char *pbuf, int bufLen) 
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    int ret;
+
+    ret = WriteFully(pCommsock->socket, pbuf, bufLen);
+    if (ret < 0) {
+	ErrorF("rwcommsockBufferWrite: IO error\n");
+	rwcommsockDestroy((RwcommPtr)pCommsock);
+	return FALSE;
+    }
+
+#ifdef VERBOSE
+    { int i;
+
+      bufLen = (bufLen > 50) ? 50 : bufLen;
+
+      ErrorF("Broadcast: ");
+      for (i = 0; i < bufLen; i++) {
+	  ErrorF("0x%x ", ((int)buf[i]) & 0xff);
+      }
+      ErrorF("\n");
+    }
+#endif /* VERBOSE */
+
+    return TRUE;
+}
+
+/* 
+** Unicast buffer to specified client.
+*/
+
+static Bool
+rwcommsockBufferWriteToClient (RwcommPtr pComm, int clientId, char *buf, int bufLen) 
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    int ret;
+
+    /* 
+    ** Note: we can't do unicast in the socket implementation. We can
+    ** only do broadcast. So clients will need to ignore this if necessary.
+    */
+    ret = WriteFully(pCommsock->socket, buf, bufLen);
+    if (ret <= 0) {
+	ErrorF("rwcommsockBufferWriteToClient: IO error\n");
+	rwcommsockDestroy((RwcommPtr)pCommsock);
+	return FALSE;
+    }
+
+#ifdef VERBOSE
+    { int i;
+      
+      bufLen = (bufLen > 50) ? 50 : bufLen;
+
+      ErrorF("Unicast to client %d: ", clientId);
+      for (i = 0; i < bufLen; i++) {
+	  ErrorF("0x%x ", ((int)buf[i]) & 0xff);
+      }
+      ErrorF("\n");
+    }
+#endif /* VERBOSE */
+
+    return TRUE;
+}
+
+static int
+rwcommsockNextMessageTypeRead (RwcommPtr pComm) 
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    char msgType;
+    int ret;
+
+    ret = ReadFully(pCommsock->socket, &msgType, 1);
+    if (ret <= 0) {
+	if (ret != 0) {
+	    ErrorF("rwcommsockNextMessageTypeRead: IO error\n");
+	}
+	rwcommsockDestroy((RwcommPtr)pCommsock);
+	return CLIENT_MESSAGE_TYPE_INVALID;
+    }
+
+    return (int) msgType;
+}
+
+static Bool
+rwcommsockNextMessageBufferRead (RwcommPtr pComm, char *pbuf, int readLen) 
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    int ret;
+
+    ret = ReadFully(pCommsock->socket, pbuf, readLen);
+    if (ret <= 0) {
+	if (ret != 0) {
+	    ErrorF("rwcommsockNextMessageBufferRead: IO error\n");
+	}
+	rwcommsockDestroy((RwcommPtr)pCommsock);
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+rwcommsockClientMessagePoll (RwcommPtr pComm, fd_set *pReadMask)
+{
+    RwcommsockPtr pCommsock = (RwcommsockPtr) pComm;
+    int numFdsSet;
+    fd_set tempFds;
+    struct timeval waittime;
+
+    memcpy((char *)&tempFds, (char *)&pCommsock->fdSetPoll, sizeof(fd_set));
+    waittime.tv_usec = 0;
+    waittime.tv_sec = 0;
+    numFdsSet = select(pCommsock->fdMax + 1, &tempFds, NULL, NULL, &waittime);
+    if (numFdsSet <= 0) {
+	if (numFdsSet == 0) return;
+	if (errno != EINTR) {
+	    ErrorF("rwcommsockClientMessagePoll: select error\n");
+	}
+	return;
+    }
+
+    /* 
+    ** We only listen for a single connection. Only accept a new connection
+    ** if we aren't already connected.
+    */
+    if (!pCommsock->isConnected &&
+	pCommsock->sockServer != -1 && 
+	FD_ISSET(pCommsock->sockServer, pReadMask)) {
+
+	int newSocket;
+	struct sockaddr_in addrDummy;
+	socklen_t lenDummy = sizeof(struct sockaddr_in);
+
+	if ((newSocket = accept(pCommsock->sockServer,
+				(struct sockaddr *)&addrDummy, &lenDummy)) < 0) {
+	    perror("rwcommsockClientMessagePoll: accept");
+	    return;
+	}
+
+	/*
+	if (fcntl(newSocket, F_SETFL, O_NONBLOCK) < 0) {
+	    perror("rwcommsockClientMessagePoll: fcntl");
+	    close(newSocket);
+	    return;
+	}
+	*/
+
+	pCommsock->fdMax = (newSocket > pCommsock->fdMax) ? newSocket :pCommsock->fdMax;
+	FD_SET(newSocket, &pCommsock->fdSetPoll);
+	AddEnabledDevice(newSocket);
+
+	pCommsock->socket = newSocket;
+	RWCOMM_CONNECT((RwcommPtr)pCommsock); 
+
+	ErrorF("New client connected\n");
+
+	numFdsSet--;
+	if (numFdsSet == 0) {
+	    return;
+	}
+    }
+
+    /* Call input handler when the socket has data */
+    if (FD_ISSET(pCommsock->socket, pReadMask) && 
+	FD_ISSET(pCommsock->socket, &pCommsock->fdSetPoll)) {
+	rwinHandler(pCommsock->pScreen);
+    }
+}
+
+/*
+** Create the comm module and accept connections.
+*/
+
+RwcommPtr
+rwcommsockCreate (ScreenPtr pScreen) 
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    RwcommsockPtr pCommsock;
+    struct sockaddr_in sockAddr;
+    int val = 1;
+
+    pCommsock = (RwcommsockPtr) xalloc(sizeof(RwcommsockRec));
+    if (pCommsock == NULL) {
+	return NULL;
+    }
+
+    pCommsock->pScreen = pScreen;
+    pCommsock->sockServer = -1;
+    pCommsock->isConnected = FALSE;
+
+    pCommsock->funcs.destroy = rwcommsockDestroy;
+    pCommsock->funcs.connect = rwcommsockConnect;
+    pCommsock->funcs.disconnect = rwcommsockDisconnect;
+    pCommsock->funcs.isConnected = rwcommsockIsConnected;
+    pCommsock->funcs.bufferWrite = rwcommsockBufferWrite;
+    pCommsock->funcs.bufferWriteToClient = rwcommsockBufferWriteToClient;
+    pCommsock->funcs.nextMessageTypeRead = rwcommsockNextMessageTypeRead;
+    pCommsock->funcs.nextMessageBufferRead = rwcommsockNextMessageBufferRead;
+    pCommsock->funcs.clientMessagePoll = rwcommsockClientMessagePoll;
+
+    pScrPriv->pComm = (RwcommPtr) pCommsock;
+
+    memset(&sockAddr, 0, sizeof(sockAddr));
+    sockAddr.sin_family = AF_INET;
+    sockAddr.sin_port = htons(RWCOMMSOCK_SERVER_PORT + atoi(display));
+    sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    pCommsock->sockServer = socket(AF_INET, SOCK_STREAM, 0);
+    if (pCommsock->sockServer < 0) {
+	xfree(pCommsock);
+	return NULL;
+    }
+
+    if (setsockopt(pCommsock->sockServer, SOL_SOCKET, SO_REUSEADDR, (char *)&val, 4) < 0) {
+	close(pCommsock->sockServer);
+	xfree(pCommsock);
+	return NULL;
+    }
+
+    if (bind(pCommsock->sockServer, 
+	     (struct sockaddr *)&sockAddr, sizeof(struct sockaddr_in)) < 0) {
+	close(pCommsock->sockServer);
+	xfree(pCommsock);
+	return NULL;
+    }
+
+    if (listen(pCommsock->sockServer, 1) < 0) {
+	close(pCommsock->sockServer);
+	xfree(pCommsock);
+	return NULL;
+    }
+
+    FD_ZERO(&pCommsock->fdSetPoll);
+    FD_SET(pCommsock->sockServer, &pCommsock->fdSetPoll);
+    pCommsock->fdMax = pCommsock->sockServer;
+    AddEnabledDevice(pCommsock->sockServer);
+
+    return (RwcommPtr)pCommsock;
+}
+
+static int
+ReadFully (int sock, char *pbuf, int bufLen)
+{
+    int bytes_read;
+
+    errno = 0;
+
+    bytes_read = read(sock, pbuf, bufLen);    
+    while (bytes_read != bufLen) {
+	if (bytes_read > 0) {
+	    bufLen -= bytes_read;
+	    pbuf += bytes_read;
+	} else if (bytes_read == 0) {
+	    /* Read failed because of end of file! */
+	    errno = EPIPE;
+	    return -1;
+	} else if (errno == EWOULDBLOCK ||
+		   errno == EAGAIN) {
+	    int ret;
+	    fd_set r_mask;
+
+	    FD_ZERO(&r_mask);
+	    for (;;) {
+		FD_SET(sock, &r_mask);
+		ret = select(sock + 1, &r_mask, NULL, NULL, NULL);
+		if (ret == -1 && 
+		    errno != EINTR) {
+		    return -1;
+		}
+		if (ret <= 0) {
+		    continue;
+		}
+		if (FD_ISSET(sock, &r_mask)) {
+		    break;
+		}
+	    }
+	    errno = 0;
+	} else {
+	    if (errno != EINTR) {
+		return -1;
+	    }
+	}
+        bytes_read = read(sock, pbuf, bufLen);    
+    }
+
+    return bufLen;
+}
+
+static int
+WriteFully (int sock, char *pbuf, int bufLen)
+{
+    int todo = bufLen;
+    int ret;
+
+    while (bufLen != 0) {
+	ret = write(sock, pbuf, todo);
+	if (ret >= 0) {
+	    pbuf += ret;
+	    bufLen -= ret;
+	    todo = bufLen;
+	} else if (errno == EWOULDBLOCK ||
+		   errno == EAGAIN) {
+	    int nfound;
+	    fd_set w_mask;
+
+	    FD_ZERO(&w_mask);
+	    for (;;) {
+		FD_SET(sock, &w_mask);
+		do {
+		    nfound = select(sock + 1, NULL, &w_mask, NULL, NULL);
+		    if (nfound < 0 && errno != EINTR) {
+			return -1;
+		    }
+		} while (nfound <= 0);
+	    }
+	} else if (errno != EINTR) {
+	    return -1;
+	}
+    }
+
+    return bufLen;
+}
diff --git a/hw/vfb/rwcommsock.h b/hw/vfb/rwcommsock.h
new file mode 100644
index 0000000..0b89afa
--- /dev/null
+++ b/hw/vfb/rwcommsock.h
@@ -0,0 +1,55 @@
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+#ifndef RWCOMMSOCK_H
+#define RWCOMMSOCK_H
+
+/* TODO: rewrite: change this */
+#define RWCOMMSOCK_SERVER_PORT     5900
+
+typedef struct rwcommsock_rec {
+    RwcommFuncPtrRec funcs;
+    ScreenPtr 	pScreen;
+    Bool        isConnected;
+    fd_set	fdSetPoll;        
+    int		fdMax;
+    int		sockServer;
+    int 	socket;
+} RwcommsockRec, *RwcommsockPtr;
+
+extern RwcommPtr rwcommsockCreate (ScreenPtr pScreen);
+extern int ReadExact(int sock, char *buf, int len);
+extern int WriteExact(int sock, char *buf, int len);
+
+#endif /* RWCOMMSOCK_H */
diff --git a/hw/vfb/rwin.c b/hw/vfb/rwin.c
new file mode 100644
index 0000000..e946bba
--- /dev/null
+++ b/hw/vfb/rwin.c
@@ -0,0 +1,1029 @@
+#undef VERBOSE
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+Copyright 1985, 1987, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+******************************************************************/
+
+#include "inputstr.h"
+#define XK_MISCELLANY
+#define XK_LATIN1
+#define XK_LATIN2
+#define XK_LATIN3
+#define XK_LATIN4
+#define XK_LATIN8
+#define XK_LATIN9
+#define XK_CYRILLIC
+#define XK_GREEK
+#define XK_ARMENIAN
+#define XK_CAUCASUS
+#define XK_VIETNAMESE
+#define XK_XKB_KEYS
+#include <X11/keysym.h>
+#include "windowstr.h"
+#include "remwin.h"
+#include "protocol.h"
+#include "lk201kbd.h"
+
+/*
+** Accept the event if its client has been assigned control 
+** or if nobody has control.
+*/
+ 
+#define ACCEPT_EVENT(pScrPriv, clientId) \
+    ((pScrPriv)->controller == clientId || \
+     (pScrPriv)->controller == -1)
+
+/************************************************************************
+** Begin derived from libX11/KeyBind.c
+*/
+
+static void
+UCSConvertCase(register unsigned code,
+                KeySym *lower,
+                KeySym *upper )
+{
+    /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
+    /* NB: Only converts simple one-to-one mappings. */
+
+    /* Tables are used where they take less space than     */
+    /* the code to work out the mappings. Zero values mean */
+    /* undefined code points.                              */
+
+    static unsigned short const IPAExt_upper_mapping[] = { /* part only */
+                            0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
+    0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
+    0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
+    0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
+    0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
+    0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
+    0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
+    0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
+    0x0290, 0x0291, 0x01B7
+    };
+
+    static unsigned short const LatinExtB_upper_mapping[] = { /* first part only */
+    0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
+    0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
+    0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
+    0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
+    0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
+    0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
+    0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
+    0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
+    0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
+    0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
+    };
+
+    static unsigned short const LatinExtB_lower_mapping[] = { /* first part only */
+    0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
+    0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
+    0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
+    0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
+    0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
+    0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
+    0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
+    0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
+    0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
+    0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
+    };
+ 
+    static unsigned short const Greek_upper_mapping[] = {
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, 
+    0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, 
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
+    0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F, 
+    0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+    0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 
+    0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 
+    0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
+    0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 
+    0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 
+    0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 
+    0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
+    0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7, 
+    0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE, 
+    0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6, 
+    0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
+    0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7, 
+    0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
+    };
+
+    static unsigned short const Greek_lower_mapping[] = {
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, 
+    0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
+    0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
+    0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+    0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 
+    0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+    0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+    0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+    0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+    0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+    0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
+    0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
+    0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
+    0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
+    0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
+    0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
+    0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
+    };
+
+    static unsigned short const GreekExt_lower_mapping[] = {
+    0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
+    0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, 
+    0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
+    0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
+    0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 
+    0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 
+    0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 
+    0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 
+    0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
+    0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
+    0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57, 
+    0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57, 
+    0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 
+    0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 
+    0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77, 
+    0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
+    0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 
+    0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 
+    0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, 
+    0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, 
+    0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 
+    0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 
+    0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7, 
+    0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF, 
+    0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7, 
+    0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF, 
+    0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7, 
+    0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF, 
+    0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
+    0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF, 
+    0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7, 
+    0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
+    };
+
+    static unsigned short const GreekExt_upper_mapping[] = {
+    0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 
+    0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 
+    0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
+    0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
+    0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 
+    0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 
+    0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 
+    0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 
+    0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
+    0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
+    0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F, 
+    0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 
+    0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 
+    0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 
+    0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 
+    0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
+    0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 
+    0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 
+    0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 
+    0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 
+    0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 
+    0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 
+    0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7, 
+    0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF, 
+    0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7, 
+    0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF, 
+    0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7, 
+    0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF, 
+    0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7, 
+    0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF, 
+    0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7, 
+    0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
+    };
+
+    *lower = code;
+    *upper = code;
+
+    /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
+    if (code <= 0x00ff) {
+        if (code >= 0x0041 && code <= 0x005a)             /* A-Z */
+            *lower += 0x20;
+        else if (code >= 0x0061 && code <= 0x007a)        /* a-z */
+            *upper -= 0x20;
+        else if ( (code >= 0x00c0 && code <= 0x00d6) ||
+	          (code >= 0x00d8 && code <= 0x00de) )
+            *lower += 0x20;
+        else if ( (code >= 0x00e0 && code <= 0x00f6) ||
+	          (code >= 0x00f8 && code <= 0x00fe) )
+            *upper -= 0x20;
+        else if (code == 0x00ff)      /* y with diaeresis */
+            *upper = 0x0178;
+        else if (code == 0x00b5)      /* micro sign */
+            *upper = 0x039c;
+	return;
+    }
+
+    /* Latin Extended-A, U+0100 to U+017F */
+    if (code >= 0x0100 && code <= 0x017f) {
+        if ( (code >= 0x0100 && code <= 0x012f) ||
+             (code >= 0x0132 && code <= 0x0137) ||
+             (code >= 0x014a && code <= 0x0177) ) {
+            *upper = code & ~1;
+            *lower = code | 1;
+        }
+        else if ( (code >= 0x0139 && code <= 0x0148) ||
+                  (code >= 0x0179 && code <= 0x017e) ) {
+            if (code & 1)
+	        *lower += 1;
+            else
+	        *upper -= 1;
+        }
+        else if (code == 0x0130)
+            *lower = 0x0069;
+        else if (code == 0x0131)
+            *upper = 0x0049;
+        else if (code == 0x0178)
+            *lower = 0x00ff;
+        else if (code == 0x017f)
+            *upper = 0x0053;
+        return;
+    }
+
+    /* Latin Extended-B, U+0180 to U+024F */
+    if (code >= 0x0180 && code <= 0x024f) {
+        if (code >= 0x01cd && code <= 0x01dc) {
+	    if (code & 1)
+	       *lower += 1;
+	    else
+	       *upper -= 1;
+        }
+        else if ( (code >= 0x01de && code <= 0x01ef) ||
+                  (code >= 0x01f4 && code <= 0x01f5) ||
+                  (code >= 0x01f8 && code <= 0x021f) ||
+                  (code >= 0x0222 && code <= 0x0233) ) {
+            *lower |= 1;
+            *upper &= ~1;
+        }
+        else if (code >= 0x0180 && code <= 0x01cc) {
+            *lower = LatinExtB_lower_mapping[code - 0x0180];
+            *upper = LatinExtB_upper_mapping[code - 0x0180];
+        }
+        else if (code == 0x01dd)
+            *upper = 0x018e;
+        else if (code == 0x01f1 || code == 0x01f2) {
+            *lower = 0x01f3;
+            *upper = 0x01f1;
+        }
+        else if (code == 0x01f3)
+            *upper = 0x01f1;
+        else if (code == 0x01f6)
+            *lower = 0x0195;
+        else if (code == 0x01f7)
+            *lower = 0x01bf;
+        else if (code == 0x0220)
+            *lower = 0x019e;
+        return;
+    }
+
+    /* IPA Extensions, U+0250 to U+02AF */
+    if (code >= 0x0253 && code <= 0x0292) {
+        *upper = IPAExt_upper_mapping[code - 0x0253];
+    }
+
+    /* Combining Diacritical Marks, U+0300 to U+036F */
+    if (code == 0x0345) {
+        *upper = 0x0399;
+    }
+
+    /* Greek and Coptic, U+0370 to U+03FF */
+    if (code >= 0x0370 && code <= 0x03ff) {
+        *lower = Greek_lower_mapping[code - 0x0370];
+        *upper = Greek_upper_mapping[code - 0x0370];
+        if (*upper == 0)
+            *upper = code;
+        if (*lower == 0)
+            *lower = code;
+    }
+
+    /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
+    if ( (code >= 0x0400 && code <= 0x04ff) ||
+         (code >= 0x0500 && code <= 0x052f) ) {
+        if (code >= 0x0400 && code <= 0x040f)
+            *lower += 0x50;
+        else if (code >= 0x0410 && code <= 0x042f)
+            *lower += 0x20;
+        else if (code >= 0x0430 && code <= 0x044f)
+            *upper -= 0x20;
+        else if (code >= 0x0450 && code <= 0x045f)
+            *upper -= 0x50;
+        else if ( (code >= 0x0460 && code <= 0x0481) ||
+                  (code >= 0x048a && code <= 0x04bf) ||
+	          (code >= 0x04d0 && code <= 0x04f5) ||
+	          (code >= 0x04f8 && code <= 0x04f9) ||
+                  (code >= 0x0500 && code <= 0x050f) ) {
+            *upper &= ~1;
+            *lower |= 1;
+        }
+        else if (code >= 0x04c1 && code <= 0x04ce) {
+	    if (code & 1)
+	        *lower += 1;
+	    else
+	        *upper -= 1;
+        }
+    }
+
+    /* Armenian, U+0530 to U+058F */
+    if (code >= 0x0530 && code <= 0x058f) {
+        if (code >= 0x0531 && code <= 0x0556)
+            *lower += 0x30;
+        else if (code >=0x0561 && code <= 0x0586)
+            *upper -= 0x30;
+    }
+
+    /* Latin Extended Additional, U+1E00 to U+1EFF */
+    if (code >= 0x1e00 && code <= 0x1eff) {
+        if ( (code >= 0x1e00 && code <= 0x1e95) ||
+             (code >= 0x1ea0 && code <= 0x1ef9) ) {
+            *upper &= ~1;
+            *lower |= 1;
+        }
+        else if (code == 0x1e9b)
+            *upper = 0x1e60;
+    }
+
+    /* Greek Extended, U+1F00 to U+1FFF */
+    if (code >= 0x1f00 && code <= 0x1fff) {
+        *lower = GreekExt_lower_mapping[code - 0x1f00];
+        *upper = GreekExt_upper_mapping[code - 0x1f00];
+        if (*upper == 0)
+            *upper = code;
+        if (*lower == 0)
+            *lower = code;
+    }
+
+    /* Letterlike Symbols, U+2100 to U+214F */
+    if (code >= 0x2100 && code <= 0x214f) {
+        switch (code) {
+        case 0x2126: *lower = 0x03c9; break;
+        case 0x212a: *lower = 0x006b; break;
+        case 0x212b: *lower = 0x00e5; break;
+        }
+    }
+    /* Number Forms, U+2150 to U+218F */
+    else if (code >= 0x2160 && code <= 0x216f)
+        *lower += 0x10;
+    else if (code >= 0x2170 && code <= 0x217f)
+        *upper -= 0x10;
+    /* Enclosed Alphanumerics, U+2460 to U+24FF */
+    else if (code >= 0x24b6 && code <= 0x24cf)
+        *lower += 0x1a;
+    else if (code >= 0x24d0 && code <= 0x24e9)
+        *upper -= 0x1a;
+    /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
+    else if (code >= 0xff21 && code <= 0xff3a)
+        *lower += 0x20;
+    else if (code >= 0xff41 && code <= 0xff5a)
+        *upper -= 0x20;
+    /* Deseret, U+10400 to U+104FF */
+    else if (code >= 0x10400 && code <= 0x10427)
+        *lower += 0x28;
+    else if (code >= 0x10428 && code <= 0x1044f)
+        *upper -= 0x28;
+}
+
+static void
+ConvertCase(KeySym sym, KeySym *lower, KeySym *upper)
+{
+    /* Latin 1 keysym */
+    if (sym < 0x100) {
+        UCSConvertCase(sym, lower, upper);
+	return;
+    }
+
+    /* Unicode keysym */
+    if ((sym & 0xff000000) == 0x01000000) {
+        UCSConvertCase((sym & 0x00ffffff), lower, upper);
+        *upper |= 0x01000000;
+        *lower |= 0x01000000;
+        return;
+    }
+
+    /* Legacy keysym */
+
+    *lower = sym;
+    *upper = sym;
+
+    switch(sym >> 8) {
+    case 1: /* Latin 2 */
+	/* Assume the KeySym is a legal value (ignore discontinuities) */
+	if (sym == XK_Aogonek)
+	    *lower = XK_aogonek;
+	else if (sym >= XK_Lstroke && sym <= XK_Sacute)
+	    *lower += (XK_lstroke - XK_Lstroke);
+	else if (sym >= XK_Scaron && sym <= XK_Zacute)
+	    *lower += (XK_scaron - XK_Scaron);
+	else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
+	    *lower += (XK_zcaron - XK_Zcaron);
+	else if (sym == XK_aogonek)
+	    *upper = XK_Aogonek;
+	else if (sym >= XK_lstroke && sym <= XK_sacute)
+	    *upper -= (XK_lstroke - XK_Lstroke);
+	else if (sym >= XK_scaron && sym <= XK_zacute)
+	    *upper -= (XK_scaron - XK_Scaron);
+	else if (sym >= XK_zcaron && sym <= XK_zabovedot)
+	    *upper -= (XK_zcaron - XK_Zcaron);
+	else if (sym >= XK_Racute && sym <= XK_Tcedilla)
+	    *lower += (XK_racute - XK_Racute);
+	else if (sym >= XK_racute && sym <= XK_tcedilla)
+	    *upper -= (XK_racute - XK_Racute);
+	break;
+    case 2: /* Latin 3 */
+	/* Assume the KeySym is a legal value (ignore discontinuities) */
+	if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
+	    *lower += (XK_hstroke - XK_Hstroke);
+	else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
+	    *lower += (XK_gbreve - XK_Gbreve);
+	else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
+	    *upper -= (XK_hstroke - XK_Hstroke);
+	else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
+	    *upper -= (XK_gbreve - XK_Gbreve);
+	else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
+	    *lower += (XK_cabovedot - XK_Cabovedot);
+	else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
+	    *upper -= (XK_cabovedot - XK_Cabovedot);
+	break;
+    case 3: /* Latin 4 */
+	/* Assume the KeySym is a legal value (ignore discontinuities) */
+	if (sym >= XK_Rcedilla && sym <= XK_Tslash)
+	    *lower += (XK_rcedilla - XK_Rcedilla);
+	else if (sym >= XK_rcedilla && sym <= XK_tslash)
+	    *upper -= (XK_rcedilla - XK_Rcedilla);
+	else if (sym == XK_ENG)
+	    *lower = XK_eng;
+	else if (sym == XK_eng)
+	    *upper = XK_ENG;
+	else if (sym >= XK_Amacron && sym <= XK_Umacron)
+	    *lower += (XK_amacron - XK_Amacron);
+	else if (sym >= XK_amacron && sym <= XK_umacron)
+	    *upper -= (XK_amacron - XK_Amacron);
+	break;
+    case 6: /* Cyrillic */
+	/* Assume the KeySym is a legal value (ignore discontinuities) */
+	if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
+	    *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
+	else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
+	    *upper += (XK_Serbian_DJE - XK_Serbian_dje);
+	else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
+	    *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
+	else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
+	    *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
+        break;
+    case 7: /* Greek */
+	/* Assume the KeySym is a legal value (ignore discontinuities) */
+	if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
+	    *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+	else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
+		 sym != XK_Greek_iotaaccentdieresis &&
+		 sym != XK_Greek_upsilonaccentdieresis)
+	    *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+	else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
+	    *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
+	else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
+		 sym != XK_Greek_finalsmallsigma)
+	    *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
+        break;
+    case 0x13: /* Latin 9 */
+        if (sym == XK_OE)
+            *lower = XK_oe;
+        else if (sym == XK_oe)
+            *upper = XK_OE;
+        else if (sym == XK_Ydiaeresis)
+            *lower = XK_ydiaeresis;
+        break;
+    }
+}
+
+static KeySym
+KeyCodeToKeySym (KeyCode keycode, int col)
+{
+    KeySymsPtr pks = &inputInfo.keyboard->key->curKeySyms;
+    register int per = pks->mapWidth;
+    register KeySym *syms;
+    KeySym lsym, usym;
+
+    if ((col < 0) || ((col >= per) && (col > 3)) ||
+	((int)keycode < pks->minKeyCode) || ((int)keycode > pks->maxKeyCode))
+      return NoSymbol;
+
+    syms = &pks->map[(keycode - pks->minKeyCode) * per];
+    if (col < 4) {
+	if (col > 1) {
+	    while ((per > 2) && (syms[per - 1] == NoSymbol))
+		per--;
+	    if (per < 3)
+		col -= 2;
+	}
+	if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
+	    ConvertCase(syms[col&~1], &lsym, &usym);
+	    if (!(col & 1))
+		return lsym;
+	    else if (usym == lsym)
+		return NoSymbol;
+	    else
+		return usym;
+	}
+    }
+    return syms[col];
+}
+
+static KeyCode
+KeysymToKeycode (KeySym ks)
+{
+    KeySymsPtr pks = &inputInfo.keyboard->key->curKeySyms;
+    register int i, j;
+
+    for (j = 0; j < pks->mapWidth; j++) {
+	for (i = pks->minKeyCode; i <= pks->maxKeyCode; i++) {
+	    if (KeyCodeToKeySym((KeyCode) i, j) == ks)
+		return i;
+	}
+    }
+    return 0;
+}
+
+/*
+** End derived from libX11/KeyBind.c
+************************************************************************/
+
+static void
+injectKeyEvent (ScreenPtr pScreen, Bool isPressed, KeySym keySym)
+{
+    DeviceIntPtr pKeyboard = inputInfo.keyboard;
+    xEvent event;
+
+    event.u.u.detail = KeysymToKeycode(keySym);
+
+    if (isPressed) {
+	event.u.u.type = KeyPress;
+    } else {
+	event.u.u.type = KeyRelease;
+    }
+    event.u.keyButtonPointer.time = GetTimeInMillis();
+    event.u.keyButtonPointer.state = 0;
+
+    (*pKeyboard->public.processInputProc)(&event, pKeyboard, 1);
+}
+
+static void
+injectPointerEvent (ScreenPtr pScreen, int wid, int mask, int x, int y)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    DeviceIntPtr pPointer = inputInfo.pointer;
+    unsigned long when = GetTimeInMillis();
+    xEvent event;
+    int button;
+
+    /* 
+    ** TODO: for now, absolutize event here. This isn't actually correct (because it
+    ** doesn't take into account window position changing after this point but before
+    ** picking, but it will suffice for now.
+    */
+    { 
+	WindowPtr pWin = LookupIDByType(wid, RT_WINDOW);
+	if (pWin == NULL) {
+	    ErrorF("WARNING: cannot find pointer event window %d\n", wid); 
+	    return;
+	}
+	
+	/*
+	ErrorF("Pointer event on window %d, winrel coord xy = %d, %d\n", wid, x, y);
+	*/
+
+	x += pWin->drawable.x;
+	y += pWin->drawable.y;
+
+	/*
+	ErrorF("Pointer event on window %d, scrabs coord xy = %d, %d\n", wid, x, y);
+	*/
+    }    
+
+
+    event.u.u.type = MotionNotify;
+    event.u.keyButtonPointer.rootX = x;
+    event.u.keyButtonPointer.rootY = y;
+    event.u.keyButtonPointer.time = when;;
+    (*inputInfo.pointer->public.processInputProc)(&event, inputInfo.pointer, 1);
+
+    for (button = 0; button < 5; button++) {
+	int buttonMask = 1 << button;
+	int changeMask = mask ^ pScrPriv->controllerButtonMask;
+	if (changeMask & buttonMask) {
+	    if (mask & buttonMask) {
+		event.u.u.type = ButtonPress;
+		event.u.keyButtonPointer.time = when;
+		event.u.u.detail = button + 1;
+	    } else {
+		event.u.u.type = ButtonRelease;
+		event.u.keyButtonPointer.time = when;
+		event.u.u.detail = button + 1;
+	    }
+	    (*pPointer->public.processInputProc)(&event, pPointer, 1);
+	}
+    }
+
+    pScrPriv->controllerButtonMask = mask;
+}
+
+/*
+** The window manager client is the client which has set
+** SubstructureRedirect on the root window. We know this 
+** because the Appshare window manager does this.
+*/
+
+static ClientPtr
+findWindowManagerClient (ScreenPtr pScreen) 
+{
+    WindowPtr pRootWin = WindowTable[pScreen->myNum];
+    OtherClients *pOthClient = wOtherClients(pRootWin);
+
+    while (pOthClient != NULL) {
+	if ((pOthClient->mask & SubstructureRedirectMask)) {
+	    return clients[CLIENT_ID(pOthClient->resource)];
+	}
+    }
+
+    FatalError("Remote Window: Cannot find window manager client");
+}
+
+
+static void
+moveWindow (WindowPtr pWin, int clientId, short x, short y) 
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    int vlist[2];
+    int ret;
+
+    if (pScrPriv->pWmClient == NULL) {
+	pScrPriv->pWmClient = findWindowManagerClient(pScreen);
+    }
+
+    /* Inform clients that an interactive move is occuring */
+    pScrPriv->configuringClient = clientId;
+
+    vlist[0] = x;
+    vlist[1] = y;
+    ret = ConfigureWindow(pWin, (CWX | CWY), (XID *) vlist, pScrPriv->pWmClient);
+    if (ret != Success) {
+	ErrorF("Move window failed, error = %d\n", ret);
+	return;
+    }
+
+    pScrPriv->configuringClient = -1;
+}
+
+static void
+resizeWindow (WindowPtr pWin, int clientId, int w, int h) 
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    int vlist[2];
+    int ret;
+
+    if (pScrPriv->pWmClient == NULL) {
+	pScrPriv->pWmClient = findWindowManagerClient(pScreen);
+    }
+
+    /* Inform clients that an interactive resize is occuring */
+    pScrPriv->configuringClient = clientId;
+
+    vlist[0] = w;
+    vlist[1] = h;
+    ret = ConfigureWindow(pWin, (CWWidth | CWHeight), (XID *) vlist, pScrPriv->pWmClient);
+    if (ret != Success) {
+	ErrorF("Resize window failed, error = %d\n", ret);
+	return;
+    }
+
+    pScrPriv->configuringClient = -1;
+}
+
+static void
+destroyWindow (WindowPtr pWin) 
+{
+    if (pWin->parent != NULL) {
+	FreeResource(pWin->drawable.id, RT_NONE);
+    }
+}
+
+/*
+** Handle client input messages.
+*/
+
+void
+rwinHandler (ScreenPtr pScreen)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    RwcommPtr pComm = pScrPriv->pComm;
+    int msgType;
+    int n;
+
+    msgType = RWCOMM_NEXT_MESSAGE_TYPE_READ(pComm);
+    /*ErrorF("msgType = %d\n", msgType);*/
+
+    switch (msgType) {
+
+    case CLIENT_MESSAGE_TYPE_KEY: {
+	char buf[KEY_EVENT_MESSAGE_SIZE];
+	Bool isPressed;
+	KeySym keySym;
+	int clientId;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf + 1, 
+			     KEY_EVENT_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+	
+	isPressed = KEY_EVENT_MESSAGE_GET_ISPRESSED(buf);
+	keySym = KEY_EVENT_MESSAGE_GET_KEYSYM(buf);
+	clientId = KEY_EVENT_MESSAGE_GET_CLIENTID(buf);
+
+	swapl(&keySym, n);
+	swapl(&clientId, n);
+
+#ifdef VERBOSE
+	ErrorF("KeyEvent: isPressed = %d, keySym = %d, clientId = %d\n", 
+	       isPressed, (int)keySym, clientId);
+#endif
+
+	if (ACCEPT_EVENT(pScrPriv, clientId)) {
+	    injectKeyEvent(pScreen, isPressed, keySym);
+	}
+
+	break;
+    }
+
+    case CLIENT_MESSAGE_TYPE_POINTER: {
+	char buf[POINTER_EVENT_MESSAGE_SIZE];
+	int mask;
+	short x, y;
+	int wid;
+	int clientId;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf + 1,
+			     POINTER_EVENT_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+
+	mask = POINTER_EVENT_MESSAGE_GET_MASK(buf);
+	x = POINTER_EVENT_MESSAGE_GET_X(buf);
+	y = POINTER_EVENT_MESSAGE_GET_Y(buf);
+	wid = POINTER_EVENT_MESSAGE_GET_WID(buf);
+	clientId = POINTER_EVENT_MESSAGE_GET_CLIENTID(buf);
+
+	swaps(&x, n);
+	swaps(&y, n);
+	swapl(&wid, n);
+	swapl(&clientId, n);
+
+#ifdef VERBOSE
+	ErrorF("PointerEvent: mask = 0x%x, x,y = %d, %d, wid = %d, clientId = %d\n", 
+	       mask, x, y, wid, clientId);
+#endif
+
+	if (ACCEPT_EVENT(pScrPriv, clientId)) {
+	    injectPointerEvent(pScreen, wid, mask, x, y);
+	}
+
+	break;
+    }
+
+    case CLIENT_MESSAGE_TYPE_TAKE_CONTROL: {
+	char buf[TAKE_CONTROL_MESSAGE_SIZE];
+	int clientId;
+	Bool steal;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf + 1,
+			     TAKE_CONTROL_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+
+	clientId = TAKE_CONTROL_MESSAGE_GET_CLIENTID(buf);
+	steal = TAKE_CONTROL_MESSAGE_GET_STEAL(buf);
+
+	swapl(&clientId, n);
+
+#ifdef VERBOSE
+	ErrorF("TakeControl: clientId = %d, steal = %d\n", 
+	       clientId, steal);
+#endif
+
+	rwTakeControl(pScreen, clientId, steal);
+
+	break;
+    }
+
+    case CLIENT_MESSAGE_TYPE_SET_WINDOW_TITLES: {
+	char hdrBuf[SET_WINDOW_TITLES_MESSAGE_SIZE];
+	char *buf;
+	short strLen;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, hdrBuf + 1,
+			     SET_WINDOW_TITLES_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+
+	strLen = SET_WINDOW_TITLES_MESSAGE_GET_STRLEN(hdrBuf);
+
+	swaps(&strLen, n);
+
+#ifdef VERBOSE
+	ErrorF("SetWindowTitles: strLen = %d\n", strLen);
+#endif
+
+	buf = xalloc(strLen);
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf, strLen)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+	
+	if (!rwoutSetWindowTitlesWrite(pScreen, strLen, buf)) {
+	    ErrorF("Could not send SetWindowTitles message\n");
+	    return;
+	}
+	
+	xfree(buf);
+
+	break;
+    }
+
+    case CLIENT_MESSAGE_TYPE_MOVE_WINDOW: {
+	char buf[MOVE_WINDOW_MESSAGE_SIZE];
+	int clientId;
+	int wid;
+	int x, y;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf + 1,
+			     MOVE_WINDOW_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+
+	clientId = MOVE_WINDOW_MESSAGE_GET_CLIENT_ID(buf);
+	wid = MOVE_WINDOW_MESSAGE_GET_WID(buf);
+	x = MOVE_WINDOW_MESSAGE_GET_X(buf);
+	y = MOVE_WINDOW_MESSAGE_GET_Y(buf);
+
+	swapl(&clientId, n);
+	swapl(&wid, n);
+	swaps(&x, n);
+	swaps(&y, n);
+
+#ifdef VERBOSE
+	ErrorF("MoveWindow: clientId = %d, wid = %d, xy = %d, %d\n", 
+	       clientId, wid, x, y);
+#endif
+	
+	WindowPtr pWin = LookupIDByType(wid, RT_WINDOW);
+	if (pWin == NULL) {
+	    ErrorF("Could not find window to move, wid = %d\n", wid);
+	    return;
+	}
+
+	moveWindow(pWin, clientId, x, y);
+	break;
+    }
+
+    case CLIENT_MESSAGE_TYPE_RESIZE_WINDOW: {
+	char buf[RESIZE_WINDOW_MESSAGE_SIZE];
+	int clientId;
+	int wid;
+	int w, h;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf + 1,
+			     RESIZE_WINDOW_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+
+	clientId = RESIZE_WINDOW_MESSAGE_GET_CLIENT_ID(buf);
+	wid = RESIZE_WINDOW_MESSAGE_GET_WID(buf);
+	w = RESIZE_WINDOW_MESSAGE_GET_WIDTH(buf);
+	h = RESIZE_WINDOW_MESSAGE_GET_HEIGHT(buf);
+
+	swapl(&clientId, n);
+	swapl(&wid, n);
+	swaps(&w, n);
+	swaps(&h, n);
+
+#ifdef VERBOSE
+	ErrorF("ResizeWindow: clientId = %d, wid = %d, wh = %d, %d\n", 
+	       clientId, wid, w, h);
+#endif
+	
+	WindowPtr pWin = LookupIDByType(wid, RT_WINDOW);
+	if (pWin == NULL) {
+	    ErrorF("Could not find window to resize, wid = %d\n", wid);
+	    return;
+	}
+
+	resizeWindow(pWin, clientId, w, h);
+	break;
+    }
+
+    case CLIENT_MESSAGE_TYPE_DESTROY_WINDOW: {
+	char buf[DESTROY_WINDOW_MESSAGE_SIZE];
+	int wid;
+
+	if (!RWCOMM_NEXT_MESSAGE_BUFFER_READ(pComm, buf + 1,
+		     DESTROY_WINDOW_MESSAGE_SIZE -1)) {
+	    ErrorF("Error reading next message buffer\n");
+	    return;
+	}
+
+	wid = DESTROY_WINDOW_MESSAGE_GET_WID(buf);
+	swapl(&wid, n);
+
+#ifdef VERBOSE
+	ErrorF("DestroyWindow: wid = %d\n", wid);
+#endif
+	
+	WindowPtr pWin = LookupIDByType(wid, RT_WINDOW);
+	if (pWin == NULL) {
+	    ErrorF("Could not find window to destroy, wid = %d\n", wid);
+	    return;
+	}
+
+	destroyWindow(pWin);
+	break;
+    }
+
+    /* TODO */
+    case CLIENT_MESSAGE_TYPE_HELLO: 
+	FatalError("rwinHandler: client message hello is not yet implemented\n");
+	
+    case CLIENT_MESSAGE_TYPE_INVALID:
+	// Client has disconnected
+	ErrorF("Exitting.\n");
+	exit(0);
+        break;
+
+    default:
+	FatalError("rwinHandler: unknown message type %d\n", msgType);
+
+    }
+}
+
diff --git a/hw/vfb/takecontrol.c b/hw/vfb/takecontrol.c
new file mode 100644
index 0000000..adbc5c9
--- /dev/null
+++ b/hw/vfb/takecontrol.c
@@ -0,0 +1,275 @@
+
+/*****************************************************************
+
+Copyright 2007 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+Copyright 1985, 1987, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+******************************************************************/
+
+#include "inputstr.h"
+#include "remwin.h"
+#include "protocol.h"
+
+/*
+** Each time we grant control to a new controller, we need
+** to make sure that if control was granted while the previous
+** controller had any keys or buttons down that we start out the 
+** keyboard state and button state with a clean state.
+
+*/
+
+static void
+initKeyboardState (ScreenPtr pScreen)
+{
+    DeviceIntPtr pKeyboard = inputInfo.keyboard;
+    unsigned long when = GetTimeInMillis();
+    xEvent event;
+    int i, k;
+
+    for (i = 0; i < DOWN_LENGTH; i++) {
+	if (pKeyboard->key->down[i] == 0) {
+	    continue;
+	}
+	for (k = 0; k < 8; k++) {
+	    int mask = 1 << k;
+	    if (pKeyboard->key->down[i] & mask) {
+		event.u.u.type = KeyRelease;
+		event.u.u.detail = (i << 3) | k;
+		event.u.keyButtonPointer.time = when;
+		(*pKeyboard->public.processInputProc)(&event, pKeyboard, 1);
+	    }
+	}
+    }
+}
+
+static void
+initPointerState (ScreenPtr pScreen) 
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    DeviceIntPtr pPointer = inputInfo.pointer;
+    xEvent event;
+    int button;
+
+    for (button = 0; button < 5; button++) {
+	int mask = 1 << button;
+	if (pScrPriv->controllerButtonMask & mask) {
+	    event.u.u.type = ButtonRelease;
+	    event.u.u.detail = button + 1;
+	    event.u.keyButtonPointer.time = GetTimeInMillis();
+	    (*pPointer->public.processInputProc)(&event, pPointer, 1);
+	}
+    }
+}
+
+static void
+rwGrantControl (ScreenPtr pScreen, int clientId)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+
+    /* Are we granting to someone who already has control? */
+    if (pScrPriv->controller == clientId) {
+	return;
+    }
+
+    pScrPriv->controller = clientId;
+
+    initKeyboardState(pScreen);
+    initPointerState(pScreen);
+
+    /* TODO: what else? */
+}
+
+/*
+** Notify everyone that the current controller has lost control
+*/
+
+static Bool
+notifyControlLost (ScreenPtr pScreen)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    RwcommPtr pComm = pScrPriv->pComm;
+    char buf[CONTROLLER_STATUS_MESSAGE_SIZE];
+    int losingClient;
+    int n;
+
+    if (!RWCOMM_IS_CONNECTED(pComm)) {
+	ErrorF("Connection lost.\n");
+	return FALSE;
+    }
+
+    losingClient = pScrPriv->controller;
+    swapl(&losingClient, n);
+
+    CONTROLLER_STATUS_MESSAGE_SET_TYPE(buf, SERVER_MESSAGE_TYPE_CONTROLLER_STATUS);
+    CONTROLLER_STATUS_MESSAGE_SET_STATUS(buf, CONTROLLER_STATUS_LOST);
+    CONTROLLER_STATUS_MESSAGE_SET_CLIENTID(buf, losingClient);
+
+    if (!RWCOMM_BUFFER_WRITE(pComm, buf, CONTROLLER_STATUS_MESSAGE_SIZE)) {
+	ErrorF("Write to connection failed.\n");
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+** Notify everyone that the current controller has gained control
+*/
+
+static Bool
+notifyControlGained (ScreenPtr pScreen)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    RwcommPtr pComm = pScrPriv->pComm;
+    char buf[CONTROLLER_STATUS_MESSAGE_SIZE];
+    int gainingClient;
+    int n;
+
+    if (!RWCOMM_IS_CONNECTED(pComm)) {
+	ErrorF("Connection lost.\n");
+	return FALSE;
+    }
+
+    gainingClient = pScrPriv->controller;
+    swapl(&gainingClient, n);
+
+    CONTROLLER_STATUS_MESSAGE_SET_TYPE(buf, SERVER_MESSAGE_TYPE_CONTROLLER_STATUS);
+    CONTROLLER_STATUS_MESSAGE_SET_STATUS(buf, CONTROLLER_STATUS_GAINED);
+    CONTROLLER_STATUS_MESSAGE_SET_CLIENTID(buf, gainingClient);
+
+    if (!RWCOMM_BUFFER_WRITE(pComm, buf, CONTROLLER_STATUS_MESSAGE_SIZE)) {
+	ErrorF("Write to connection failed.\n");
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+** Notify the given client that its request for control is refused.
+*/
+
+static Bool
+notifyControlRefused (ScreenPtr pScreen, int clientId) 
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+    RwcommPtr pComm = pScrPriv->pComm;
+    char buf[CONTROLLER_STATUS_MESSAGE_SIZE];
+    int refusedClient;
+    int n;
+
+    if (!RWCOMM_IS_CONNECTED(pComm)) {
+	ErrorF("Connection lost.\n");
+	return FALSE;
+    }
+
+    refusedClient = pScrPriv->controller;
+    swapl(&refusedClient, n);
+
+    CONTROLLER_STATUS_MESSAGE_SET_TYPE(buf, SERVER_MESSAGE_TYPE_CONTROLLER_STATUS);
+    CONTROLLER_STATUS_MESSAGE_SET_STATUS(buf, CONTROLLER_STATUS_REFUSED);
+    CONTROLLER_STATUS_MESSAGE_SET_CLIENTID(buf, refusedClient);
+
+    if (!RWCOMM_BUFFER_WRITE_TO_CLIENT(pComm, clientId, 
+			  buf, CONTROLLER_STATUS_MESSAGE_SIZE)) {
+	ErrorF("Write to connection failed.\n");
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+void
+rwTakeControl (ScreenPtr pScreen, int clientId, Bool steal)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+
+    /* If client already has control do nothing */
+    if (pScrPriv->controller == clientId) {
+	return;
+    }
+
+    if (pScrPriv->controller == -1 || steal) {
+
+	/* Nobody has control or client is stealing -- Grant control */
+
+	if (!notifyControlLost(pScreen)) {
+	    ErrorF("Cannot notify clients that control is lost.\n");
+	    return;
+	}
+
+	rwGrantControl(pScreen, clientId);
+	
+	if (!notifyControlGained(pScreen)) {
+	    ErrorF("Cannot notify clients that control is gained.\n");
+	    return;
+	}
+
+    } else {
+	if (!notifyControlRefused(pScreen, clientId)) {
+	    ErrorF("Cannot notify client %d that control is refused.\n", 
+		   clientId);
+	    return;
+	}
+    }
+}
+
+void
+rwTakeControlInit (ScreenPtr pScreen)
+{
+    RemwinScreenPrivPtr pScrPriv = REMWIN_GET_SCRPRIV(pScreen);
+
+    pScrPriv->controller = -1;
+    pScrPriv->controllerButtonMask = 0;
+    pScrPriv->configuringClient = -1;
+}
+


More information about the xorg-commit mailing list