VNCviewGS/mouse.cc
Stephen Heumann e1288f7e1b Small refactoring to reduce boilerplate code
DoReadTCP automatically disposes the old read buffer handle before doing the read, and then locks the new read buffer handle before returning. This removes the need for most explicit locking/unlocking of the handle. A macro is provided to dispose of the handle earlier (useful in a few cases where it may be big, and another read isn't immediately performed).

Also, set displayInProgress to FALSE in NextRect, rather than in code for each encoding.
2016-05-28 21:59:35 -05:00

320 lines
12 KiB
C++

#if __ORCAC__
#pragma lint -1
#pragma noroot
segment "VNCview GS";
#endif
#include <window.h>
#include <quickdraw.h>
#include <qdaux.h>
#include <desk.h>
#include <memory.h>
#include <resources.h>
#include <tcpip.h>
#include <menu.h>
#include <control.h>
#include <misctool.h>
#include <scrap.h>
#include <stdio.h>
#include <stdlib.h>
#include <event.h>
#include <limits.h>
#include "vncsession.h"
#include "vncview.h"
#include "vncdisplay.h"
#include "colortables.h"
#include "menus.h"
#include "clipboard.h"
#include "desktopsize.h"
#include "mouse.h"
#include "keyboard.h"
#include "copyrect.h"
#include "raw.h"
#include "hextile.h"
unsigned char * cursor = NULL; /* Cursor from server */
/* Send a DoPointerEvent reflecting the status of the mouse to the server */
/* This routine also maintains the appropriate cursor when using local cursor */
void DoPointerEvent (void) {
static struct {
unsigned char messageType;
unsigned char buttonMask;
unsigned int xPos;
unsigned int yPos;
} pointerEventStruct = { 5 /* message type */ };
Point mouseCoords;
unsigned long contentOrigin;
Point * contentOriginPtr = (void *) &contentOrigin;
RegionHndl contentRgnHndl;
unsigned int oldButtonMask;
GrafPortPtr winPtr;
unsigned long key1 = 0x0000; /* Keys to release & re-press, if any */
unsigned long key2 = 0x0000;
if (viewOnlyMode)
return;
mouseCoords = myEvent.where;
SetPort(vncWindow);
/* Check if mouse is in content region of VNC window; don't send mouse
* updates if it isn't.
*/
if (FindWindow(&winPtr, myEvent.where.h, myEvent.where.v) != wInContent ||
winPtr != vncWindow) {
if (cursor && GetCursorAdr() == cursor)
InitCursor();
return;
}
GlobalToLocal(&mouseCoords);
contentOrigin = GetContentOrigin(vncWindow);
mouseCoords.h += contentOriginPtr->h;
mouseCoords.v += contentOriginPtr->v;
mouseCoords.h = SwapBytes2(mouseCoords.h);
mouseCoords.v = SwapBytes2(mouseCoords.v);
/* Set up correct state of mouse buttons */
oldButtonMask = pointerEventStruct.buttonMask;
pointerEventStruct.buttonMask = 0x00;
if ((myEvent.modifiers & btn0State) == 0x00) { /* Mouse button pressed */
if (emulate3ButtonMouse) {
if (myEvent.modifiers & optionKey) {
pointerEventStruct.buttonMask = 0x02;
key1 = 0xFFE9;
}
if (myEvent.modifiers & appleKey) {
pointerEventStruct.buttonMask |= 0x04;
key2 = 0xFFE7;
}
}
/* If no modifiers, just send a normal left click. */
if (pointerEventStruct.buttonMask == 0x00)
pointerEventStruct.buttonMask = 0x01;
}
if ((myEvent.modifiers & btn1State) == 0x00) /* If 2nd (right) */
pointerEventStruct.buttonMask |= 0x04; /* button is pressed */
/* Don't waste bandwidth by sending update if mouse hasn't changed.
* This may occasionally result in an initial mouse update not being
* sent. If this occurs, the user can simply move the mouse slightly
* in order to send it.
*/
if ( (pointerEventStruct.xPos == mouseCoords.h) &&
(pointerEventStruct.yPos == mouseCoords.v) &&
(pointerEventStruct.buttonMask == oldButtonMask) )
return;
pointerEventStruct.xPos = mouseCoords.h;
pointerEventStruct.yPos = mouseCoords.v;
if (key1)
SendKeyEvent(FALSE, key1);
if (key2)
SendKeyEvent(FALSE, key2);
TCPIPWriteTCP(hostIpid, (Pointer) &pointerEventStruct.messageType,
sizeof(pointerEventStruct), TRUE, FALSE);
/* Can't do useful error checking here */
if (key1)
SendKeyEvent(TRUE, key1);
if (key2)
SendKeyEvent(TRUE, key2);
//printf("Sent mouse update: x = %u, y = %u\n", mouseCoords.h, mouseCoords.v);
//printf(" xPos = %x, yPos = %x, buttons = %x\n", pointerEventStruct.xPos, pointerEventStruct.yPos, (int) pointerEventStruct.buttonMask);
/* Note that we don't have to request a display update here. That has
* been or will be done elsewhere when we're ready for it.
*/
if (cursor && GetCursorAdr() != cursor)
SetCursor(cursor);
}
void DoCursor (void) {
unsigned char *cursorPixels;
unsigned char *bitmask;
unsigned char *dataPtr;
/* Elements of the cursor structure (which isn't a C struct) */
unsigned int *cursorHeightPtr, *cursorWidthPtr;
unsigned char *cursorImage, *cursorMask;
unsigned int *hotSpotYPtr, *hotSpotXPtr;
unsigned long bitmaskByte;
unsigned long bitmaskLineBytes, lineWords;
unsigned int line, n, j; /* Loop counters */
unsigned char *maskLine, *imageLine;
unsigned char *oldCursor = cursor; /* So we can free() it later */
unsigned int outBytes640;
unsigned long outBytes320;
bitmaskLineBytes = ((unsigned long)rectWidth + 7) / 8;
if (!DoReadTCP((unsigned long)rectWidth * rectHeight + bitmaskLineBytes * rectHeight))
return; /* Try again later */
cursorPixels = (unsigned char *)(*readBufferHndl);
bitmask = (unsigned char *)(*readBufferHndl) + (unsigned long)rectWidth * rectHeight;
if (hRez == 640)
lineWords = ((unsigned long)rectWidth + 7) / 8 + 1;
else /* hRez == 320 */
lineWords = ((unsigned long)rectWidth + 3) / 4 + 1;
/* Don't overflow loop indices, and don't use really large cursors.
* (Is there a limit to the cursor sizes QuickDraw II can handle?) */
if (lineWords > 16 || rectHeight > 128 || rectWidth == 0 || rectHeight == 0) {
InitCursor();
cursor = NULL;
goto done;
}
cursor = malloc(8 + 4 * lineWords * rectHeight);
/* Sub-optimal error handling */
if (cursor == NULL) {
InitCursor();
goto done;
}
cursorHeightPtr = (unsigned int *)(void *)cursor;
cursorWidthPtr = cursorHeightPtr + 1;
cursorImage = cursor + 4;
cursorMask = cursorImage + lineWords * rectHeight * 2;
hotSpotYPtr = (unsigned int *)(cursorMask + lineWords * rectHeight * 2);
hotSpotXPtr = hotSpotYPtr + 1;
*cursorHeightPtr = rectHeight;
*cursorWidthPtr = lineWords;
*hotSpotYPtr = rectY;
*hotSpotXPtr = rectX;
/* Make cursorImage using translation tables */
/* Make cursorMask from bitmask */
dataPtr = cursorPixels;
if (hRez == 320) {
for (line = 0; line < rectHeight; line++) { /* for each line ... */
maskLine = cursorMask + line * lineWords * 2;
imageLine = cursorImage + line * lineWords * 2;
for (j = 0; j < bitmaskLineBytes; j++) {
bitmaskByte = *(bitmask + line*bitmaskLineBytes + j);
outBytes320 =
(((unsigned)bitmaskByte & 0x80) ) + (((unsigned)bitmaskByte & 0x80) >> 1) +
(((unsigned)bitmaskByte & 0x80) >> 2) + (((unsigned)bitmaskByte & 0x80) >> 3) +
(((unsigned)bitmaskByte & 0x40) >> 3) + (((unsigned)bitmaskByte & 0x40) >> 4) +
(((unsigned)bitmaskByte & 0x40) >> 5) + (((unsigned)bitmaskByte & 0x40) >> 6) +
(((unsigned)bitmaskByte & 0x20) << 10) + (((unsigned)bitmaskByte & 0x20) << 9) +
(((unsigned)bitmaskByte & 0x20) << 8) + (((unsigned)bitmaskByte & 0x20) << 7) +
(((unsigned)bitmaskByte & 0x10) << 7) + (((unsigned)bitmaskByte & 0x10) << 6) +
(((unsigned)bitmaskByte & 0x10) << 5) + (((unsigned)bitmaskByte & 0x10) << 4) +
((bitmaskByte & 0x08) << 20) + ((bitmaskByte & 0x08) << 19) +
((bitmaskByte & 0x08) << 18) + ((bitmaskByte & 0x08) << 17) +
((bitmaskByte & 0x04) << 17) + ((bitmaskByte & 0x04) << 16) +
((bitmaskByte & 0x04) << 15) + ((bitmaskByte & 0x04) << 14) +
((bitmaskByte & 0x02) << 30) + ((bitmaskByte & 0x02) << 29) +
((bitmaskByte & 0x02) << 28) + ((bitmaskByte & 0x02) << 27) +
((bitmaskByte & 0x01) << 27) + ((bitmaskByte & 0x01) << 26) +
((bitmaskByte & 0x01) << 25) + ((bitmaskByte & 0x01) << 24);
*((unsigned long *)maskLine + j) = outBytes320;
}
*((unsigned int *)maskLine + lineWords - 1) = 0;
for (n = 0; n < rectWidth/2; n++) {
*(imageLine + n) = coltab320[*(dataPtr++)] & 0xF0;
*(imageLine + n) += coltab320[*(dataPtr++)] & 0x0F;
*(imageLine + n) ^= 0xFF; /* Reverse color */
*(imageLine + n) &= *(maskLine + n);
}
if (rectWidth & 0x01) {
*(imageLine + n) = coltab320[*(dataPtr++)] & 0xF0;
*(imageLine + n) ^= 0xFF; /* Reverse color */
*(imageLine + n) &= *(maskLine + n);
n++;
}
*(imageLine + n) = 0;
*((unsigned int *)imageLine + lineWords - 1) = 0;
}
}
else { /* hRez == 640 */
for (line = 0; line < rectHeight; line++) { /* for each line ... */
maskLine = cursorMask + line * lineWords * 2;
imageLine = cursorImage + line * lineWords * 2;
for (j = 0; j < bitmaskLineBytes; j++) {
bitmaskByte = *(bitmask + line*bitmaskLineBytes + j);
outBytes640 =
(((unsigned)bitmaskByte & 0x80) ) + (((unsigned)bitmaskByte & 0xC0) >> 1) +
(((unsigned)bitmaskByte & 0x60) >> 2) + (((unsigned)bitmaskByte & 0x30) >> 3) +
(((unsigned)bitmaskByte & 0x10) >> 4) + (((unsigned)bitmaskByte & 0x08) << 12) +
(((unsigned)bitmaskByte & 0x0C) << 11) + (((unsigned)bitmaskByte & 0x06) << 10) +
(((unsigned)bitmaskByte & 0x03) << 9) + (((unsigned)bitmaskByte & 0x01) << 8);
*((unsigned int *)maskLine + j) = outBytes640;
}
*((unsigned int *)maskLine + lineWords - 1) = 0;
for (n = 0; n < rectWidth / 4; n++) {
*(imageLine + n) = coltab640[*(dataPtr++)] & 0xC0;
*(imageLine + n) += coltab640[*(dataPtr++)] & 0x30;
*(imageLine + n) += coltab640[*(dataPtr++)] & 0x0C;
*(imageLine + n) += coltab640[*(dataPtr++)] & 0x03;
*(imageLine + n) ^= 0xFF; /* Reverse color */
*(imageLine + n) &= *(maskLine + n);
}
if (rectWidth & 0x03) {
*(imageLine + n) = 0;
for (j = 0; j < (rectWidth & 0x03); j++) {
*(imageLine + n) += coltab640[*(dataPtr++)] & (0xC0 >> j*2);
}
*(imageLine + n) ^= 0xFF; /* Reverse color */
*(imageLine + n) &= *(maskLine + n);
n++;
}
*(unsigned int *)(imageLine + n) = 0;
*((unsigned int *)imageLine + lineWords - 1) = 0;
}
}
if (GetCursorAdr() == oldCursor)
SetCursor(cursor);
#if 0
/***************/
{
unsigned char * k;
FILE *foo = fopen("out.txt", "a");
fprintf(foo, "Width = %u, Height = %u, Hotspot X = %u, Hotspot Y = %u:\n",
rectWidth, rectHeight, rectX, rectY);
fprintf(foo, "\n");
for (k = cursor; k < cursorImage; k++)
fprintf(foo, "%02X ", *k);
fprintf(foo, "\n");
for (j = 0; j < lineWords * rectHeight * 4; j++) {
fprintf(foo, "%02X", *(cursorImage + j));
if ((j+1) % (lineWords * 2) == 0)
fprintf(foo, "\n");
}
for (k = cursorImage + j; k < cursorImage + j + 4; k = k + 1)
fprintf(foo, "%02X ", *k);
fprintf(foo, "\n");
fclose(foo);
}
/***************/
#endif
done:
free(oldCursor);
NextRect(); /* Prepare for next rect */
}