⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncdesktop.cpp

📁 Web VNC samples delphi
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				for (int x=0; x<cliplen; x++)
				{
					if (cliptext[x] != '\x0d')
					{
						unixtext[unixpos] = cliptext[x];
						unixpos++;
					}
				}
				unixtext[unixpos] = 0;

				// Free the clip text
				free(cliptext);
				cliptext = NULL;

				// Now send the unix text to the server
				_this->m_server->UpdateClipText(unixtext);

				free(unixtext);
			}
		}

		_this->m_initialClipBoardSeen = TRUE;

		if (_this->m_hnextviewer != NULL)
		{
			// Pass the message to the next window in clipboard viewer chain.  
			return SendMessage(_this->m_hnextviewer, WM_DRAWCLIPBOARD, 0,0); 
		}

		return 0;

	default:
		return DefWindowProc(hwnd, iMsg, wParam, lParam);
	}
}

BOOL vncDesktop::CheckUpdates()
{
#ifndef _DEBUG
	try
	{
#endif
		// Re-install polling timer if necessary
		if (m_server->PollingCycleChanged())
		{
			SetPollingTimer();
			m_server->PollingCycleChanged(false);
		}

		// Update the state of blank screen timer
		UpdateBlankScreenTimer();

		// Has the display resolution or desktop changed?
		if (m_displaychanged || !vncService::InputDesktopSelected() || !inConsoleSession())
		{
			vnclog.Print(LL_STATE, VNCLOG("display resolution or desktop changed.\n"));

			rfbServerInitMsg oldscrinfo = m_scrinfo;
			m_displaychanged = FALSE;

			// Attempt to close the old hooks
			if (!Shutdown())
			{
				vnclog.Print(LL_INTERR, VNCLOG("failed to close desktop server.\n"));
				m_server->KillAuthClients();
				return FALSE;
			}

			// Now attempt to re-install them!
			ChangeResNow();

			if (!Startup())
			{
				vnclog.Print(LL_INTERR, VNCLOG("failed to re-start desktop server.\n"));
				m_server->KillAuthClients();
				return FALSE;
			}

			// Check if the screen info has changed
			vnclog.Print(LL_INTINFO,
						VNCLOG("SCR: old screen format %dx%dx%d\n"),
						oldscrinfo.framebufferWidth,
						oldscrinfo.framebufferHeight,
						oldscrinfo.format.bitsPerPixel);
			vnclog.Print(LL_INTINFO,
						VNCLOG("SCR: new screen format %dx%dx%d\n"),
						m_scrinfo.framebufferWidth,
						m_scrinfo.framebufferHeight,
						m_scrinfo.format.bitsPerPixel);
			if (memcmp(&m_scrinfo, &oldscrinfo, sizeof(oldscrinfo)) != 0)
			{
				vnclog.Print(LL_INTINFO, VNCLOG("screen format has changed.\n"));
			}

			// Call this regardless of screen format change
			m_server->UpdateLocalFormat();

			// Add a full screen update to all the clients
			m_changed_rgn.AddRect(m_bmrect);
			m_server->UpdatePalette();
		}

		// TRIGGER THE UPDATE

		RECT rect = m_server->GetSharedRect();
		RECT new_rect = GetSourceRect();
		IntersectRect(&new_rect, &new_rect, &m_bmrect);

		// Update screen size if required
		if (!EqualRect(&new_rect, &rect))
		{
			m_server->SetSharedRect(new_rect);
			bool sendnewfb = false;

			if (rect.right - rect.left != new_rect.right - new_rect.left ||
				rect.bottom - rect.top != new_rect.bottom - new_rect.top)
				sendnewfb = true;

			// FIXME: We should not send NewFBSize if a client
			//        did not send framebuffer update request.
			m_server->SetNewFBSize(sendnewfb);

			m_changed_rgn.Clear();

			if (sendnewfb && m_server->WindowShared())
			{
				if (new_rect.right - new_rect.left == 0 &&
					new_rect.bottom - new_rect.top == 0)
				{
// window is minimized
					return TRUE;
				}
				else
				{
// window is restored
// window is resized
					m_changed_rgn.AddRect(new_rect);
				}
			}
			else
			{
				return TRUE;
			}
		}

		// If we have clients full region requests
		if (m_server->FullRgnRequested())
		{
			// Capture screen to main buffer
			CaptureScreen(rect, m_mainbuff);
			// If we have a video driver - reset counter
			if ( m_videodriver != NULL && m_videodriver->IsActive())
			{
				m_videodriver->ResetCounter();
			}
		}

// DEBUG: Continue auditing the code from this point.

		// If we have incremental update requests
		if (1 || m_server->IncrRgnRequested())
		{
			vncRegion rgn;

			// Use either a mirror video driver, or perform polling
			if (m_videodriver != NULL && m_videodriver->IsActive())
			{
				// FIXME: If there were no incremental update requests
				//        for some time, we will loose updates.
// IMPORTANT: Mirage outputs the regions re (0, 0)
// so we have to offset them re virtual display

// TODOTODO
					BOOL bCursorShape = FALSE;

					m_videodriver->HandleDriverChanges(
						this,
						m_changed_rgn,
						m_bmrect.left,
						m_bmrect.top,
						bCursorShape);
			}
			else
			{
				if (GetPollingFlag())
				{
					SetPollingFlag(false);
					PerformPolling();
				}
			}

			// Check for moved windows
// PrimaryDisplayOnlyShared: check if any problems when
// dragging from another display
			if ((m_server->FullScreen() || m_server->PrimaryDisplayOnlyShared()) &&
				!(m_videodriver && m_videodriver->IsHandlingScreen2ScreenBlt()))
			{
				CalcCopyRects();
			}

			if (m_copyrect_set)
			{
				// Send copyrect to all clients
				m_server->CopyRect(m_copyrect_rect, m_copyrect_src);
				m_copyrect_set = false;

// IMPORTANT: this order: CopyRectToBuffer, CaptureScreen, GetChangedRegion
				// Copy old window rect to back buffer
				CopyRectToBuffer(m_copyrect_rect, m_copyrect_src);

				// Copy new window rect to main buffer
				CaptureScreen(m_copyrect_rect, m_mainbuff);

				// Get changed pixels to rg
				GetChangedRegion(rgn, m_copyrect_rect);

				RECT rect;
				rect.left= m_copyrect_src.x;
				rect.top = m_copyrect_src.y;
				rect.right = rect.left + (m_copyrect_rect.right - m_copyrect_rect.left);
				rect.bottom = rect.top + (m_copyrect_rect.bottom - m_copyrect_rect.top);
				// Refresh old window rect
				m_changed_rgn.AddRect(rect);
				// Don't refresh new window rect
				m_changed_rgn.SubtractRect(m_copyrect_rect);
			} 

			// Get only desktop area
			vncRegion temprgn;
			temprgn.Clear();
			temprgn.AddRect(rect);
			m_changed_rgn.Intersect(temprgn);

			// Get list of rectangles for checking
			rectlist rectsToScan;
			m_changed_rgn.Rectangles(rectsToScan);

			// Capture and check them
			CheckRects(rgn, rectsToScan);

			// Update the mouse
			m_server->UpdateMouse();

			// Send changed region data to all clients
			m_server->UpdateRegion(rgn);

      // Save changes to region
      m_last_changed_rgn.Clear();
      m_last_changed_rgn.Combine(m_changed_rgn);

			// Clear changed region
			m_changed_rgn.Clear();
		}

		// Trigger an update to be sent
		if (m_server->FullRgnRequested() || m_server->IncrRgnRequested())
		{
			m_server->TriggerUpdate();
		}

#ifndef _DEBUG
	}
	catch (...)
	{
		vnclog.Print(LL_INTERR, VNCLOG("vncDesktop::CheckUpdates caught an exception.\n"));
		m_server->KillAuthClients();
		return FALSE;
	}
#endif

	return TRUE;
}

void
vncDesktop::SetPollingTimer()
{
	const UINT driverCycle = 30;
	const UINT minPollingCycle = 5;

	UINT msec;
	if (m_videodriver != NULL) {
		msec = driverCycle;
	} else {
		msec = m_server->GetPollingCycle() / 16;
		if (msec < minPollingCycle) {
			msec = minPollingCycle;
		}
	}
	m_timer_polling = SetTimer(Window(), TIMER_POLL, msec, NULL);
}

inline void vncDesktop::CheckRects(vncRegion &rgn, rectlist &rects)
{
#ifndef _DEBUG
	try
	{
#endif
		rectlist::iterator i;

		for (i = rects.begin(); i != rects.end(); i++)
		{
			// Copy data to the main buffer
			// FIXME: Maybe call CaptureScreen() just once?
			//        Check what would be more efficient.
			CaptureScreen(*i, m_mainbuff);

// Check for changes in the rectangle
			GetChangedRegion(rgn, *i);
		}
#ifndef _DEBUG
	}
	catch (...)
	{
		vnclog.Print(LL_INTERR, VNCLOG("vncDesktop::CheckRects caught an exception.\n"));
		throw;
	}
#endif
}

// This notably improves performance when using Visual C++ 6.0 compiler
#pragma function(memcpy, memcmp)

static const int BLOCK_SIZE = 32;

// created for troubleshoot purposes;
// when GetChangedRegion_Normal et al are suspected for bugs/need changes.
// the code below is as simple and clear as possible
void vncDesktop::GetChangedRegion_Dummy(vncRegion &rgn, const RECT &rect)
{
	rgn.AddRect(rect);

	// Copy the changes to the back buffer
	const int c2rect_re_vd_top = rect.top - m_bmrect.top;
	const int c3rect_re_vd_left = rect.left - m_bmrect.left;
	_ASSERTE(c2rect_re_vd_top >= 0);
	_ASSERTE(c3rect_re_vd_left >= 0);

	const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;
	const int offset = c2rect_re_vd_top * m_bytesPerRow + c3rect_re_vd_left * bytesPerPixel;

	unsigned char *o_ptr = m_backbuff + offset;
	unsigned char *n_ptr = m_mainbuff + offset;
	const int bytes_in_row = (rect.right - rect.left) * bytesPerPixel;
	for (int y = rect.top; y < rect.bottom; y++)
	{
		memcpy(o_ptr, n_ptr, bytes_in_row);
		n_ptr += m_bytesPerRow;
		o_ptr += m_bytesPerRow;
	}
}

void vncDesktop::GetChangedRegion_Normal(vncRegion &rgn, const RECT &rect)
{
	const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;
	const int bytes_per_scanline = (rect.right - rect.left) * bytesPerPixel;

	const int crect_re_vd_left = rect.left - m_bmrect.left;
	const int crect_re_vd_top = rect.top - m_bmrect.top;
	_ASSERTE(crect_re_vd_left >= 0);
	_ASSERTE(crect_re_vd_top >= 0);

	const int offset = crect_re_vd_top * m_bytesPerRow + crect_re_vd_left * bytesPerPixel;
	unsigned char *o_ptr = m_backbuff + offset;
	unsigned char *n_ptr = m_mainbuff + offset;

	RECT new_rect = rect;

	// Fast processing for small rectangles
	if (rect.right - rect.left <= BLOCK_SIZE &&
		rect.bottom - rect.top <= BLOCK_SIZE)
	{
		for (int y = rect.top; y < rect.bottom; y++)
		{
			if (memcmp(o_ptr, n_ptr, bytes_per_scanline) != 0)
			{
				new_rect.top = y;
				UpdateChangedSubRect(rgn, new_rect);
				break;
			}
			o_ptr += m_bytesPerRow;
			n_ptr += m_bytesPerRow;
		}
		return;
	}

// Process bigger rectangles
	BOOL bTop4Move = TRUE;
	for (int y = rect.top; y < rect.bottom; y++)
	{
		if (memcmp(o_ptr, n_ptr, bytes_per_scanline) != 0)
		{
			if (bTop4Move)
			{
				new_rect.top = y;
				bTop4Move = FALSE;
			}
			// Skip a number of lines after a non-matched one
			int n = BLOCK_SIZE / 2 - 1;
			y += n;
			o_ptr += n * m_bytesPerRow;
			n_ptr += n * m_bytesPerRow;
		}
		else
		{
			if (!bTop4Move)
			{
				new_rect.bottom = y;
				UpdateChangedRect(rgn, new_rect);
				bTop4Move = TRUE;
			}
		}
		o_ptr += m_bytesPerRow;
		n_ptr += m_bytesPerRow;
	}
	if (!bTop4Move)
	{
		new_rect.bottom = rect.bottom;
		UpdateChangedRect(rgn, new_rect);
	}
}

void vncDesktop::UpdateChangedRect(vncRegion &rgn, const RECT &rect)
{
	// Pass small rectangles directly to UpdateChangedSubRect
	if (rect.right - rect.left <= BLOCK_SIZE &&
		rect.bottom - rect.top <= BLOCK_SIZE)
	{
		UpdateChangedSubRect(rgn, rect);
		return;
	}

	const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;

	RECT new_rect;
	int x, y, ay;

	const int crect_re_vd_left = rect.left - m_bmrect.left;
	const int crect_re_vd_top = rect.top - m_bmrect.top;
	_ASSERTE(crect_re_vd_left >= 0);
	_ASSERTE(crect_re_vd_top >= 0);

	// Scan down the rectangle
	const int offset = crect_re_vd_top * m_bytesPerRow + crect_re_vd_left * bytesPerPixel;
	unsigned char *o_topleft_ptr = m_backbuff + offset;
	unsigned char *n_topleft_ptr = m_mainbuff + offset;

	for (y = rect.top; y < rect.bottom; y += BLOCK_SIZE)
	{
		// Work out way down the bitmap
		unsigned char *o_row_ptr = o_topleft_ptr;
		unsigned char *n_row_ptr = n_topleft_ptr;

		const int blockbottom = Min(y + BLOCK_SIZE, rect.bottom);
		new_rect.bottom = blockbottom;

		BOOL bLeft4Move = TRUE;

		for (x = rect.left; x < rect.right; x += BLOCK_SIZE)
		{
			// Work our way across the row
			unsigned char *n_block_ptr = n_row_ptr;
			unsigned char *o_block_ptr = o_row_ptr;

			const UINT blockright = Min(x + BLOCK_SIZE, rect.right);
			const UINT bytesPerBlockRow = (blockright-x) * bytesPerPixel;

			// Scan this block
			for (ay = y; ay < blockbottom; ay++)
			{
				if (memcmp(n_block_ptr, o_block_ptr, bytesPerBlockRow) != 0)
					break;
				n_block_ptr += m_bytesPerRow;
				o_block_ptr += m_bytesPerRow;
			}
			if (ay < blockbottom)
			{
				// There were changes, so this block will need to be updated
				if (bLeft4Move)
				{
					new_rect.left = x;
					bLeft4Move = FALSE;
					new_rect.top = ay;
				}
				else if (ay < new_rect.top)
				{
					new_rect.top = ay;
				}
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -