summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeron <dj@dj-laptop.(none)>2007-06-04 20:10:38 -0700
committerDeron <dj@dj-laptop.(none)>2007-06-04 20:10:38 -0700
commitfe201a8f9a4cd8390a84660f68b78d2e4de622dd (patch)
tree8756e3cd469921802a7d49833cc999ffa8dd7e0b
parent9789f35cc5ca147c6c4b4bfc810d44fdbdbe5705 (diff)
Add more files to branch.
-rw-r--r--hw/vfb/protocol.h615
-rw-r--r--hw/vfb/remwin.h190
-rw-r--r--hw/vfb/rle.c235
-rw-r--r--hw/vfb/rwcomm.h98
-rw-r--r--hw/vfb/rwcommsock.c457
-rw-r--r--hw/vfb/rwcommsock.h55
-rw-r--r--hw/vfb/rwin.c1029
-rw-r--r--hw/vfb/takecontrol.c275
8 files changed, 2954 insertions, 0 deletions
diff --git a/hw/vfb/protocol.h b/hw/vfb/protocol.h
new file mode 100644
index 000000000..122fb7657
--- /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 000000000..f545d25f5
--- /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 000000000..e8c81a0fb
--- /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 000000000..f65c84f3b
--- /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 000000000..dacb10702
--- /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 000000000..0b89afa7c
--- /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 000000000..e946bba92
--- /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 000000000..adbc5c999
--- /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;
+}
+