📄 clientconnection.cpp
字号:
if (m_connDlg != NULL)
m_connDlg->SetStatus("Interaction capability list received");
}
//
// Read the list of rfbCapabilityInfo structures and enable corresponding
// capabilities in the specified container. The count argument specifies how
// many records to read from the socket.
//
void ClientConnection::ReadCapabilityList(CapsContainer *caps, int count)
{
rfbCapabilityInfo msginfo;
for (int i = 0; i < count; i++) {
ReadExact((char *)&msginfo, sz_rfbCapabilityInfo);
msginfo.code = Swap32IfLE(msginfo.code);
caps->Enable(&msginfo);
}
}
void ClientConnection::SizeWindow(bool centered)
{
// Find how large the desktop work area is
RECT workrect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &workrect, 0);
int workwidth = workrect.right - workrect.left;
int workheight = workrect.bottom - workrect.top;
vnclog.Print(2, _T("Screen work area is %d x %d\n"),
workwidth, workheight);
RECT fullwinrect;
if (m_opts.m_scaling) {
SetRect(&fullwinrect, 0, 0,
m_si.framebufferWidth * m_opts.m_scale_num / m_opts.m_scale_den,
m_si.framebufferHeight * m_opts.m_scale_num / m_opts.m_scale_den);
} else {
SetRect(&fullwinrect, 0, 0,
m_si.framebufferWidth, m_si.framebufferHeight);
}
AdjustWindowRectEx(&fullwinrect,
GetWindowLong(m_hwnd, GWL_STYLE ),
FALSE, GetWindowLong(m_hwnd, GWL_EXSTYLE));
m_fullwinwidth = fullwinrect.right - fullwinrect.left;
m_fullwinheight = fullwinrect.bottom - fullwinrect.top;
AdjustWindowRectEx(&fullwinrect,
GetWindowLong(m_hwndscroll, GWL_STYLE ) & ~WS_HSCROLL &
~WS_VSCROLL & ~WS_BORDER,
FALSE, GetWindowLong(m_hwndscroll, GWL_EXSTYLE));
AdjustWindowRectEx(&fullwinrect,
GetWindowLong(m_hwnd1, GWL_STYLE ),
FALSE, GetWindowLong(m_hwnd1, GWL_EXSTYLE));
if (GetMenuState(GetSystemMenu(m_hwnd1, FALSE),
ID_TOOLBAR, MF_BYCOMMAND) == MF_CHECKED) {
RECT rtb;
GetWindowRect(m_hToolbar, &rtb);
fullwinrect.bottom = fullwinrect.bottom + rtb.bottom - rtb.top - 3;
}
m_winwidth = min(fullwinrect.right - fullwinrect.left, workwidth);
m_winheight = min(fullwinrect.bottom - fullwinrect.top, workheight);
if ((fullwinrect.right - fullwinrect.left > workwidth) &&
(workheight - m_winheight >= 16)) {
m_winheight = m_winheight + 16;
}
if ((fullwinrect.bottom - fullwinrect.top > workheight) &&
(workwidth - m_winwidth >= 16)) {
m_winwidth = m_winwidth + 16;
}
int x,y;
WINDOWPLACEMENT winplace;
winplace.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(m_hwnd1, &winplace);
if (centered) {
x = (workwidth - m_winwidth) / 2;
y = (workheight - m_winheight) / 2;
} else {
// Try to preserve current position if possible
GetWindowPlacement(m_hwnd1, &winplace);
if ((winplace.showCmd == SW_SHOWMAXIMIZED) || (winplace.showCmd == SW_SHOWMINIMIZED)) {
x = winplace.rcNormalPosition.left;
y = winplace.rcNormalPosition.top;
} else {
RECT tmprect;
GetWindowRect(m_hwnd1, &tmprect);
x = tmprect.left;
y = tmprect.top;
}
if (x + m_winwidth > workrect.right)
x = workrect.right - m_winwidth;
if (y + m_winheight > workrect.bottom)
y = workrect.bottom - m_winheight;
}
winplace.rcNormalPosition.top = y;
winplace.rcNormalPosition.left = x;
winplace.rcNormalPosition.right = x + m_winwidth;
winplace.rcNormalPosition.bottom = y + m_winheight;
SetWindowPlacement(m_hwnd1, &winplace);
SetForegroundWindow(m_hwnd1);
PositionChildWindow();
}
void ClientConnection::PositionChildWindow()
{
RECT rparent;
GetClientRect(m_hwnd1, &rparent);
int parentwidth = rparent.right - rparent.left;
int parentheight = rparent.bottom - rparent.top;
if (GetMenuState(GetSystemMenu(m_hwnd1, FALSE),
ID_TOOLBAR, MF_BYCOMMAND) == MF_CHECKED) {
RECT rtb;
GetWindowRect(m_hToolbar, &rtb);
int rtbheight = rtb.bottom - rtb.top - 3;
SetWindowPos(m_hToolbar, HWND_TOP, rparent.left, rparent.top,
parentwidth, rtbheight, SWP_SHOWWINDOW);
parentheight = parentheight - rtbheight;
rparent.top = rparent.top + rtbheight;
} else {
ShowWindow(m_hToolbar, SW_HIDE);
}
SetWindowPos(m_hwndscroll, HWND_TOP, rparent.left - 1, rparent.top - 1,
parentwidth + 2, parentheight + 2, SWP_SHOWWINDOW);
if (!m_opts.m_FitWindow) {
if (InFullScreenMode()) {
ShowScrollBar(m_hwndscroll, SB_HORZ, FALSE);
ShowScrollBar(m_hwndscroll, SB_VERT, FALSE);
} else {
ShowScrollBar(m_hwndscroll, SB_VERT, parentheight < m_fullwinheight);
ShowScrollBar(m_hwndscroll, SB_HORZ, parentwidth < m_fullwinwidth);
GetClientRect(m_hwndscroll, &rparent);
parentwidth = rparent.right - rparent.left;
parentheight = rparent.bottom - rparent.top;
ShowScrollBar(m_hwndscroll, SB_VERT, parentheight < m_fullwinheight);
ShowScrollBar(m_hwndscroll, SB_HORZ, parentwidth < m_fullwinwidth);
GetClientRect(m_hwndscroll, &rparent);
parentwidth = rparent.right - rparent.left;
parentheight = rparent.bottom - rparent.top;
}
} else {
if (!IsIconic(m_hwnd1)) {
ShowScrollBar(m_hwndscroll, SB_HORZ, FALSE);
ShowScrollBar(m_hwndscroll, SB_VERT, FALSE);
GetClientRect(m_hwndscroll, &rparent);
parentwidth = rparent.right - rparent.left;
parentheight = rparent.bottom - rparent.top;
if ((parentwidth < 1) || (parentheight < 1))
return;
RECT fullwinrect;
int den = max(m_si.framebufferWidth * 100 / parentwidth,
m_si.framebufferHeight * 100 / parentheight);
SetRect(&fullwinrect, 0, 0, (m_si.framebufferWidth * 100 + den - 1) / den,
(m_si.framebufferHeight * 100 + den - 1) / den);
while ((fullwinrect.right - fullwinrect.left > parentwidth) ||
(fullwinrect.bottom - fullwinrect.top > parentheight)) {
den++;
SetRect(&fullwinrect, 0, 0, (m_si.framebufferWidth * 100 + den - 1) / den,
(m_si.framebufferHeight * 100 + den - 1) / den);
}
m_opts.m_scale_num = 100;
m_opts.m_scale_den = den;
m_opts.FixScaling();
m_fullwinwidth = fullwinrect.right - fullwinrect.left;
m_fullwinheight = fullwinrect.bottom - fullwinrect.top;
}
}
int x, y;
if (parentwidth > m_fullwinwidth) {
x = (parentwidth - m_fullwinwidth) / 2;
} else {
x = rparent.left;
}
if (parentheight > m_fullwinheight) {
y = (parentheight - m_fullwinheight) / 2;
} else {
y = rparent.top;
}
SetWindowPos(m_hwnd, HWND_TOP, x, y,
min(parentwidth, m_fullwinwidth),
min(parentheight, m_fullwinheight),
SWP_SHOWWINDOW);
m_cliwidth = min( (int)parentwidth, (int)m_fullwinwidth);
m_cliheight = min( (int)parentheight, (int)m_fullwinheight);
m_hScrollMax = m_fullwinwidth;
m_vScrollMax = m_fullwinheight;
int newhpos, newvpos;
if (!m_opts.m_FitWindow) {
newhpos = max(0, min(m_hScrollPos,
m_hScrollMax - max(m_cliwidth, 0)));
newvpos = max(0, min(m_vScrollPos,
m_vScrollMax - max(m_cliheight, 0)));
} else {
newhpos = 0;
newvpos = 0;
}
RECT clichild;
GetClientRect(m_hwnd, &clichild);
ScrollWindowEx(m_hwnd, m_hScrollPos-newhpos, m_vScrollPos-newvpos,
NULL, &clichild, NULL, NULL, SW_INVALIDATE);
m_hScrollPos = newhpos;
m_vScrollPos = newvpos;
if (!m_opts.m_FitWindow) {
UpdateScrollbars();
} else {
InvalidateRect(m_hwnd, NULL, FALSE);
}
UpdateWindow(m_hwnd);
}
void ClientConnection::CreateLocalFramebuffer() {
omni_mutex_lock l(m_bitmapdcMutex);
// Remove old bitmap object if it already exists
bool bitmapExisted = false;
if (m_hBitmap != NULL) {
DeleteObject(m_hBitmap);
bitmapExisted = true;
}
// We create a bitmap which has the same pixel characteristics as
// the local display, in the hope that blitting will be faster.
TempDC hdc(m_hwnd);
m_hBitmap = ::CreateCompatibleBitmap(hdc, m_si.framebufferWidth,
m_si.framebufferHeight);
if (m_hBitmap == NULL)
throw WarningException("Error creating local image of screen.");
// Select this bitmap into the DC with an appropriate palette
ObjectSelector b(m_hBitmapDC, m_hBitmap);
PaletteSelector p(m_hBitmapDC, m_hPalette);
// Put a "please wait" message up initially
RECT rect;
SetRect(&rect, 0,0, m_si.framebufferWidth, m_si.framebufferHeight);
COLORREF bgcol = RGB(0xcc, 0xcc, 0xcc);
FillSolidRect(&rect, bgcol);
if (!bitmapExisted) {
COLORREF oldbgcol = SetBkColor(m_hBitmapDC, bgcol);
COLORREF oldtxtcol = SetTextColor(m_hBitmapDC, RGB(0,0,64));
rect.right = m_si.framebufferWidth / 2;
rect.bottom = m_si.framebufferHeight / 2;
DrawText (m_hBitmapDC, _T("Please wait - initial screen loading"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
SetBkColor(m_hBitmapDC, oldbgcol);
SetTextColor(m_hBitmapDC, oldtxtcol);
}
InvalidateRect(m_hwnd, NULL, FALSE);
}
void ClientConnection::SetupPixelFormat() {
// Have we requested a reduction to 8-bit?
if (m_opts.m_Use8Bit) {
vnclog.Print(2, _T("Requesting 8-bit truecolour\n"));
m_myFormat = vnc8bitFormat;
// We don't support colormaps so we'll ask the server to convert
} else if (!m_si.format.trueColour) {
// We'll just request a standard 16-bit truecolor
vnclog.Print(2, _T("Requesting 16-bit truecolour\n"));
m_myFormat = vnc16bitFormat;
} else {
// Normally we just use the sever's format suggestion
m_myFormat = m_si.format;
// It's silly requesting more bits than our current display has, but
// in fact it doesn't usually amount to much on the network.
// Windows doesn't support 8-bit truecolour.
// If our display is palette-based, we want more than 8 bit anyway,
// unless we're going to start doing palette stuff at the server.
// So the main use would be a 24-bit true-colour desktop being viewed
// on a 16-bit true-colour display, and unless you have lots of images
// and hence lots of raw-encoded stuff, the size of the pixel is not
// going to make much difference.
// We therefore don't bother with any restrictions, but here's the
// start of the code if we wanted to do it.
if (false) {
// Get a DC for the root window
TempDC hrootdc(NULL);
int localBitsPerPixel = GetDeviceCaps(hrootdc, BITSPIXEL);
int localRasterCaps = GetDeviceCaps(hrootdc, RASTERCAPS);
vnclog.Print(2, _T("Memory DC has depth of %d and %s pallete-based.\n"),
localBitsPerPixel, (localRasterCaps & RC_PALETTE) ? "is" : "is not");
// If we're using truecolor, and the server has more bits than we do
if ( (localBitsPerPixel > m_myFormat.depth) &&
! (localRasterCaps & RC_PALETTE)) {
m_myFormat.depth = localBitsPerPixel;
// create a bitmap compatible with the current display
// call GetDIBits twice to get the colour info.
// set colour masks and shifts
}
}
}
// The endian will be set before sending
}
void ClientConnection::SetFormatAndEncodings()
{
// Set pixel format to myFormat
rfbSetPixelFormatMsg spf;
spf.type = rfbSetPixelFormat;
spf.format = m_myFormat;
spf.format.redMax = Swap16IfLE(spf.format.redMax);
spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
spf.format.bigEndian = 0;
WriteExact((char *)&spf, sz_rfbSetPixelFormatMsg);
// The number of bytes required to hold at least one pixel.
m_minPixelBytes = (m_myFormat.bitsPerPixel + 7) >> 3;
// Set encodings
char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]);
int len = 0;
se->type = rfbSetEncodings;
se->nEncodings = 0;
bool useCompressLevel = false;
int i;
// Put the preferred encoding first, and change it if the
// preferred encoding is not actually usable.
for (i = LASTENCODING; i >= rfbEncodingRaw; i--)
{
if (m_opts.m_PreferredEncoding == i) {
if (m_opts.m_UseEnc[i]) {
encs[se->nEncodings++] = Swap32IfLE(i);
if ( i == rfbEncodingZlib ||
i == rfbEncodingTight ||
i == rfbEncodingZlibHex ) {
useCompressLevel = true;
}
} else {
m_opts.m_PreferredEncoding--;
}
}
}
// Now we go through and put in all the other encodings in order.
// We do rather assume that the most recent encoding is the most
// desirable!
for (i = LASTENCODING; i >= rfbEncodingRaw; i--)
{
if ( (m_opts.m_PreferredEncoding != i) &&
(m_opts.m_UseEnc[i]))
{
encs[se->nEncodings++] = Swap32IfLE(i);
if ( i == rfbEncodingZlib ||
i == rfbEncodingTight ||
i == rfbEncodingZlibHex ) {
useCompressLevel = true;
}
}
}
// Request desired compression level if applicable
if ( useCompressLevel && m_opts.m_useCompressLevel &&
m_opts.m_compressLevel >= 0 &&
m_opts.m_compressLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE( rfbEncodingCompressLevel0 +
m_opts.m_compressLevel );
}
// Request cursor shape updates if enabled by user
if (m_opts.m_requestShapeUpdates) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
if (!m_opts.m_ignoreShapeUpdates)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
}
// Request JPEG quality level if JPEG compression was enabled by user
if ( m_opts.m_enableJpegCompression &&
m_opts.m_jpegQualityLevel >= 0 &&
m_opts.m_jpegQualityLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE( rfbEncodingQualityLevel0 +
m_opts.m_jpegQualityLevel );
}
// Notify the server that we support LastRect and NewFBSize encodings
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -