📄 vncclient.cpp
字号:
// Merge the two
vncRegion dummy;
dummy.AddRect(m_server->GetSharedRect());
region.Intersect(dummy);
m_changed_rgn.Combine(region);
}
}
void
vncClient::CopyRect(RECT &dest, POINT &source)
{
// If copyrect is disabled then just redraw the region!
if (!m_copyrect_use)
{
UpdateRect(dest);
return;
}
{
omni_mutex_lock l(m_regionLock);
// Clip the destination to the screen
RECT destrect;
if (!IntersectRect(&destrect, &dest, &m_server->GetSharedRect()))
return;
// Adjust the source correspondingly
source.x = source.x + (destrect.left - dest.left);
source.y = source.y + (destrect.top - dest.top);
// Work out the source rectangle
RECT srcrect;
// Is this a continuation of an earlier window drag?
if (m_copyrect_set &&
((source.x == m_copyrect_rect.left) && (source.y == m_copyrect_rect.top)))
{
// Yes, so use the old source position
srcrect.left = m_copyrect_src.x;
srcrect.top = m_copyrect_src.y;
}
else
{
// No, so use this source position
srcrect.left = source.x;
srcrect.top = source.y;
}
// And fill out the right & bottom using the dest rect
srcrect.right = destrect.right-destrect.left + srcrect.left;
srcrect.bottom = destrect.bottom-destrect.top + srcrect.top;
// Clip the source to the screen
RECT srcrect2;
if (!IntersectRect(&srcrect2, &srcrect, &m_server->GetSharedRect()))
return;
// Correct the destination rectangle
destrect.left += (srcrect2.left - srcrect.left);
destrect.top += (srcrect2.top - srcrect.top);
destrect.right = srcrect2.right-srcrect2.left + destrect.left;
destrect.bottom = srcrect2.bottom-srcrect2.top + destrect.top;
// Is there an existing CopyRect rectangle?
if (m_copyrect_set)
{
// Yes, so compare their areas!
if (((destrect.right-destrect.left) * (destrect.bottom-destrect.top))
< ((m_copyrect_rect.right-m_copyrect_rect.left) * (m_copyrect_rect.bottom-m_copyrect_rect.top)))
return;
}
// Set the copyrect...
m_copyrect_rect = destrect;
m_copyrect_src.x = srcrect2.left;
m_copyrect_src.y = srcrect2.top;
m_copyrect_set = TRUE;
}
}
void
vncClient::UpdateClipText(LPSTR text)
{
if (!m_protocol_ready) return;
// Don't send the clipboard contents to a view-only client
if (!IsKeyboardEnabled() || !IsPointerEnabled())
return;
// Lock out any update sends and send clip text to the client
omni_mutex_lock l(m_sendUpdateLock);
rfbServerCutTextMsg message;
message.length = Swap32IfLE(strlen(text));
if (!SendRFBMsg(rfbServerCutText, (BYTE *) &message, sizeof(message)))
{
Kill();
return;
}
if (!m_socket->SendQueued(text, strlen(text)))
{
Kill();
return;
}
}
void
vncClient::UpdatePalette()
{
omni_mutex_lock l(m_regionLock);
m_palettechanged = TRUE;
}
// Functions used to set and retrieve the client settings
const char*
vncClient::GetClientName()
{
return (m_client_name != NULL) ? m_client_name : "[unknown]";
}
const char*
vncClient::GetServerName()
{
return (m_server_name != NULL) ? m_server_name : "[unknown]";
}
// Internal methods
BOOL
vncClient::SendRFBMsg(CARD8 type, BYTE *buffer, int buflen)
{
// Set the message type
((rfbServerToClientMsg *)buffer)->type = type;
// Send the message
if (!m_socket->SendQueued((char *) buffer, buflen))
{
vnclog.Print(LL_CONNERR, VNCLOG("failed to send RFB message to client\n"));
Kill();
return FALSE;
}
return TRUE;
}
BOOL vncClient::SendUpdate()
{
#ifndef _DEBUG
try
{
#endif
// First, check if we need to send pending NewFBSize message
if (m_use_NewFBSize && m_fb_size_changed) {
SetNewFBSize(TRUE);
return TRUE;
}
vncRegion toBeSent; // Region to actually be sent
rectlist toBeSentList; // List of rectangles to actually send
vncRegion toBeDone; // Region to check
// Prepare to send cursor position update if necessary
if (m_cursor_pos_changed) {
POINT cursor_pos;
if (!GetCursorPos(&cursor_pos)) {
cursor_pos.x = 0;
cursor_pos.y = 0;
}
RECT shared_rect = m_server->GetSharedRect();
cursor_pos.x -= shared_rect.left;
cursor_pos.y -= shared_rect.top;
if (cursor_pos.x < 0) {
cursor_pos.x = 0;
} else if (cursor_pos.x >= shared_rect.right - shared_rect.left) {
cursor_pos.x = shared_rect.right - shared_rect.left - 1;
}
if (cursor_pos.y < 0) {
cursor_pos.y = 0;
} else if (cursor_pos.y >= shared_rect.bottom - shared_rect.top) {
cursor_pos.y = shared_rect.bottom - shared_rect.top - 1;
}
if (cursor_pos.x == m_cursor_pos.x && cursor_pos.y == m_cursor_pos.y) {
m_cursor_pos_changed = FALSE;
} else {
m_cursor_pos.x = cursor_pos.x;
m_cursor_pos.y = cursor_pos.y;
}
}
toBeSent.Clear();
if (!m_full_rgn.IsEmpty()) {
m_incr_rgn.Clear();
m_copyrect_set = false;
toBeSent.Combine(m_full_rgn);
m_changed_rgn.Clear();
m_full_rgn.Clear();
} else {
if (!m_incr_rgn.IsEmpty()) {
// Get region to send from vncDesktop
toBeSent.Combine(m_changed_rgn);
// Mouse stuff for the case when cursor shape updates are off
if (!m_cursor_update_sent && !m_cursor_update_pending) {
// If the mouse hasn't moved, see if its position is in the rect
// we're sending. If so, make sure the full mouse rect is sent.
if (!m_mousemoved) {
vncRegion tmpMouseRgn;
tmpMouseRgn.AddRect(m_oldmousepos);
tmpMouseRgn.Intersect(toBeSent);
if (!tmpMouseRgn.IsEmpty())
m_mousemoved = TRUE;
}
// If the mouse has moved (or otherwise needs an update):
if (m_mousemoved) {
// Include an update for its previous position
if (IntersectRect(&m_oldmousepos, &m_oldmousepos, &m_server->GetSharedRect()))
toBeSent.AddRect(m_oldmousepos);
// Update the cached mouse position
m_oldmousepos = m_buffer->GrabMouse();
// Include an update for its current position
if (IntersectRect(&m_oldmousepos, &m_oldmousepos, &m_server->GetSharedRect()))
toBeSent.AddRect(m_oldmousepos);
// Indicate the move has been handled
m_mousemoved = FALSE;
}
}
m_changed_rgn.Clear();
}
}
// Get the list of changed rectangles!
int numrects = 0;
if (toBeSent.Rectangles(toBeSentList))
{
// Find out how many rectangles this update will contain
rectlist::iterator i;
int numsubrects;
for (i=toBeSentList.begin(); i != toBeSentList.end(); i++)
{
numsubrects = m_buffer->GetNumCodedRects(*i);
// Skip remaining rectangles if an encoder will use LastRect extension.
if (numsubrects == 0) {
numrects = 0xFFFF;
break;
}
numrects += numsubrects;
}
}
if (numrects != 0xFFFF) {
// Count cursor shape and cursor position updates.
if (m_cursor_update_pending)
numrects++;
if (m_cursor_pos_changed)
numrects++;
// Handle the copyrect region
if (m_copyrect_set)
numrects++;
// If there are no rectangles then return
if (numrects != 0)
m_incr_rgn.Clear();
else
return FALSE;
}
omni_mutex_lock l(m_sendUpdateLock);
// Otherwise, send <number of rectangles> header
rfbFramebufferUpdateMsg header;
header.nRects = Swap16IfLE(numrects);
if (!SendRFBMsg(rfbFramebufferUpdate, (BYTE *) &header, sz_rfbFramebufferUpdateMsg))
return TRUE;
// Send mouse cursor shape update
if (m_cursor_update_pending) {
if (!SendCursorShapeUpdate())
return TRUE;
}
// Send cursor position update
if (m_cursor_pos_changed) {
if (!SendCursorPosUpdate())
return TRUE;
}
// Encode & send the copyrect
if (m_copyrect_set) {
m_copyrect_set = FALSE;
if(!SendCopyRect(m_copyrect_rect, m_copyrect_src))
return TRUE;
}
// Encode & send the actual rectangles
if (!SendRectangles(toBeSentList))
return TRUE;
// Send LastRect marker if needed.
if (numrects == 0xFFFF) {
if (!SendLastRect())
return TRUE;
}
// Both lists should be empty when we exit
_ASSERT(toBeSentList.empty());
#ifndef _DEBUG
}
catch (...)
{
vnclog.Print(LL_INTERR, VNCLOG("vncClient::SendUpdate caught an exception.\n"));
throw;
}
#endif
return TRUE;
}
// Send a set of rectangles
BOOL
vncClient::SendRectangles(rectlist &rects)
{
RECT rect;
// Work through the list of rectangles, sending each one
while(!rects.empty())
{
rect = rects.front();
if (!SendRectangle(rect))
return FALSE;
rects.pop_front();
}
rects.clear();
return TRUE;
}
// Tell the encoder to send a single rectangle
BOOL vncClient::SendRectangle(RECT &rect)
{
RECT sharedRect;
{
omni_mutex_lock l(m_regionLock);
sharedRect = m_server->GetSharedRect();
}
IntersectRect(&rect, &rect, &sharedRect);
// Get the buffer to encode the rectangle
UINT bytes = m_buffer->TranslateRect(
rect,
m_socket,
sharedRect.left,
sharedRect.top);
// Send the encoded data
return m_socket->SendQueued((char *)(m_buffer->GetClientBuffer()), bytes);
}
// Send a single CopyRect message
BOOL vncClient::SendCopyRect(RECT &dest, POINT &source)
{
RECT rc_shr = m_server->GetSharedRect();
// Create the message header
rfbFramebufferUpdateRectHeader copyrecthdr;
copyrecthdr.r.x = Swap16IfLE(dest.left - rc_shr.left);
copyrecthdr.r.y = Swap16IfLE(dest.top - rc_shr.top);
copyrecthdr.r.w = Swap16IfLE(dest.right-dest.left);
copyrecthdr.r.h = Swap16IfLE(dest.bottom-dest.top);
copyrecthdr.encoding = Swap32IfLE(rfbEncodingCopyRect);
// Create the CopyRect-specific section
rfbCopyRect copyrectbody;
copyrectbody.srcX = Swap16IfLE(source.x - rc_shr.left);
copyrectbody.srcY = Swap16IfLE(source.y - rc_shr.top);
// Now send the message;
if (!m_socket->SendQueued((char *)©recthdr, sizeof(copyrecthdr)))
return FALSE;
if (!m_socket->SendQueued((char *)©rectbody, sizeof(copyrectbody)))
return FALSE;
return TRUE;
}
// Send LastRect marker indicating that there are no more rectangles to send
BOOL
vncClient::SendLastRect()
{
// Create the message header
rfbFramebufferUpdateRectHeader hdr;
hdr.r.x = 0;
hdr.r.y = 0;
hdr.r.w = 0;
hdr.r.h = 0;
hdr.encoding = Swap32IfLE(rfbEncodingLastRect);
// Now send the message;
if (!m_socket->SendQueued((char *)&hdr, sizeof(hdr)))
return FALSE;
return TRUE;
}
// Send the encoder-generated palette to the client
// This function only returns FALSE if the SendQueued fails - any other
// error is coped with internally...
BOOL
vncClient::SendPalette()
{
rfbSetColourMapEntriesMsg setcmap;
RGBQUAD *rgbquad;
UINT ncolours = 256;
// Reserve space for the colour data
rgbquad = new RGBQUAD[ncolours];
if (rgbquad == NULL)
return TRUE;
// Get the data
if (!m_buffer->GetRemotePalette(rgbquad, ncolours))
{
delete [] rgbquad;
return TRUE;
}
// Compose the message
omni_mutex_lock l(m_sendUpdateLock);
setcmap.type = rfbSetColourMapEntries;
setcmap.firstColour = Swap16IfLE(0);
setcmap.nColours = Swap16IfLE(ncolours);
if (!m_socket->SendQueued((char *) &setcmap, sz_rfbSetColourMapEntriesMsg))
{
delete [] rgbquad;
return FA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -