📄 vncdesktopthread.cpp
字号:
if (m_desktop->m_server->PollFullScreen())
{
if (
(
//(lTime - m_lLastUpdateTime > 33) // 30 FPS max // Now Useless with RDV timing above...
// &&
(lTime - m_lLastMouseMoveTime > 100) // 100 ms pause after a Mouse move
)
//||
//!m_desktop->m_server->TurboMode() // Only block FS Polling in Turbo Mode...
)
{
m_lLastUpdateTime = lTime;
if (
(lTime - m_lLastMouseMoveTime > 300) // Restart FS Polling 300ms after last mouse move
//||
//(!m_desktop->m_server->TurboMode())
// ||
// (!m_desktop->RestartDriver)
)
m_desktop->FastDetectChanges(rgncache, m_desktop->GetSize(), 0, true);
}
}
if (m_desktop->m_server->PollForeground())
{
// Get the window rectangle for the currently selected window
HWND hwnd = GetForegroundWindow();
if (hwnd != NULL)
PollWindow(rgncache, hwnd);
}
if (m_desktop->m_server->PollUnderCursor())
{
// Find the mouse position
POINT mousepos;
if (GetCursorPos(&mousepos))
{
// Find the window under the mouse
HWND hwnd = WindowFromPoint(mousepos);
if (hwnd != NULL)
PollWindow(rgncache, hwnd);
}
}
}
//****************************************************************************
//************* driver No polling
//****************************************************************************
else
{
// long lTime = timeGetTime();
if (cursormoved)
{
// if (lTime - m_desktop->m_lLastMouseUpdateTime < 200)
// continue;
m_desktop->m_buffer.SetAccuracy(m_desktop->m_server->TurboMode() ? 2 : 1);
// m_desktop->m_lLastMouseUpdateTime = lTime;
}
else
// 4 is not that bad...but not perfect (especially with tree branchs display)
m_desktop->m_buffer.SetAccuracy(m_desktop->m_server->TurboMode() ? 4 : 2);
}
// PROCESS THE MOUSE POINTER
// Some of the hard work is done in clients, some here
// This code fetches the desktop under the old pointer position
// but the client is responsible for actually encoding and sending
// it when required.
// This code also renders the pointer and saves the rendered position
// Clients include this when rendering updates.
// The code is complicated in this way because we wish to avoid
// rendering parts of the screen the mouse moved through between
// client updates, since in practice they will probably not have changed.
if (cursormoved && !m_desktop->m_hookdriver)
{
if (!m_desktop->m_cursorpos.is_empty())
{
// Cursor position seems to be outsite the bounding
// When you make the screen smaller
// add extra check
rfb::Rect rect;
int x = m_desktop->m_cursorpos.tl.x;
int w = m_desktop->m_cursorpos.br.x-x;
int y = m_desktop->m_cursorpos.tl.y;
int h = m_desktop->m_cursorpos.br.y-y;
if (ClipRect(&x, &y, &w, &h, m_desktop->m_bmrect.tl.x, m_desktop->m_bmrect.tl.y,
m_desktop->m_bmrect.br.x-m_desktop->m_bmrect.tl.x, m_desktop->m_bmrect.br.y-m_desktop->m_bmrect.tl.y))
{
rect.tl.x = x;
rect.br.x = x+w;
rect.tl.y = y;
rect.br.y = y+h;
rgncache = rgncache.union_(rect);
// vnclog.Print(LL_INTINFO, VNCLOG("6 %i %i %i %i "),m_desktop->m_cursorpos.br.x,m_desktop->m_cursorpos.br.y,m_desktop->m_cursorpos.tl.x,m_desktop->m_cursorpos.tl.y);
// vnclog.Print(LL_INTINFO, VNCLOG("6 %i %i %i %i "),rect.br.x,rect.br.y,rect.tl.x,rect.tl.y);
}
}
}
{
// Prevent any clients from accessing the Buffer
omni_mutex_lock l(m_desktop->m_update_lock);
// CHECK FOR COPYRECTS
// This actually just checks where the Foreground window is
if (!m_desktop->m_hookdriver && !m_server->SingleWindow())
m_desktop->CalcCopyRects(updates);
// GRAB THE DISPLAY
// Fetch data from the display to our display cache.
// Update the scaled rects when using server side scaling
// something wrong inithooking again
// We make sure no updates are in the regions
// sf@2002 - Added "&& m_desktop->m_hookdriver"
// Otherwise we're still getting driver updates (from shared memory buffer)
// after a m_hookdriver switching from on to off
// (and m_hookdll from off to on) that causes mouse cursor garbage,
// or missing mouse cursor.
if (m_desktop->VideoBuffer() && m_desktop->m_hookdriver)
{
m_desktop->m_buffer.GrabRegion(rgncache,true);
}
else
{
m_desktop->m_buffer.GrabRegion(rgncache,false);
}
// sf@2002 - v1.1.x - Mouse handling
// If one client, send cursor shapes only when the cursor changes.
// This is Disabled for now.
if( !XRichCursorEnabled==m_desktop->m_server->IsXRichCursorEnabled())
{
XRichCursorEnabled=m_desktop->m_server->IsXRichCursorEnabled();
if (m_desktop->m_videodriver)
{
if (!XRichCursorEnabled) m_desktop->m_videodriver->HardwareCursor();
else m_desktop->m_videodriver->NoHardwareCursor();
}
}
if (m_desktop->m_server->IsXRichCursorEnabled() && !m_desktop->m_UltraEncoder_used)
{
if (m_desktop->m_hcursor != m_desktop->m_hOldcursor || m_desktop->m_buffer.IsShapeCleared())
{
m_desktop->m_hOldcursor = m_desktop->m_hcursor;
m_desktop->m_buffer.SetCursorPending(TRUE);
if (!m_desktop->m_hookdriver) m_desktop->m_buffer.GrabMouse(); // Grab mouse cursor in all cases
m_desktop->m_server->UpdateMouse();
rfb::Rect rect;
int x = m_desktop->m_cursorpos.tl.x;
int w = m_desktop->m_cursorpos.br.x-x;
int y = m_desktop->m_cursorpos.tl.y;
int h = m_desktop->m_cursorpos.br.y-y;
if (ClipRect(&x, &y, &w, &h, m_desktop->m_bmrect.tl.x, m_desktop->m_bmrect.tl.y,
m_desktop->m_bmrect.br.x-m_desktop->m_bmrect.tl.x, m_desktop->m_bmrect.br.y-m_desktop->m_bmrect.tl.y))
{
rect.tl.x = x;
rect.br.x = x+w;
rect.tl.y = y;
rect.br.y = y+h;
rgncache = rgncache.union_(rect);
// vnclog.Print(LL_INTINFO, VNCLOG("7 %i %i %i %i "),m_desktop->m_cursorpos.br.x,m_desktop->m_cursorpos.br.y,m_desktop->m_cursorpos.tl.x,m_desktop->m_cursorpos.tl.y);
// vnclog.Print(LL_INTINFO, VNCLOG("6 %i %i %i %i "),rect.br.x,rect.br.y,rect.tl.x,rect.tl.y);
}
m_server->UpdateCursorShape();
}
}
else if (!m_desktop->m_hookdriver)// If several clients, send them all the mouse updates
{
// Render the mouse
//if (!m_desktop->VideoBuffer())
m_desktop->m_buffer.GrabMouse();
if (cursormoved /*&& !m_desktop->m_buffer.IsCursorUpdatePending()*/)
{
// Inform clients that it has moved
m_desktop->m_server->UpdateMouse();
// Get the buffer to fetch the pointer bitmap
if (!m_desktop->m_cursorpos.is_empty())
{
rfb::Rect rect;
int x = m_desktop->m_cursorpos.tl.x;
int w = m_desktop->m_cursorpos.br.x-x;
int y = m_desktop->m_cursorpos.tl.y;
int h = m_desktop->m_cursorpos.br.y-y;
if (ClipRect(&x, &y, &w, &h, m_desktop->m_bmrect.tl.x, m_desktop->m_bmrect.tl.y,
m_desktop->m_bmrect.br.x-m_desktop->m_bmrect.tl.x, m_desktop->m_bmrect.br.y-m_desktop->m_bmrect.tl.y))
{
rect.tl.x = x;
rect.br.x = x+w;
rect.tl.y = y;
rect.br.y = y+h;
rgncache = rgncache.union_(rect);
//vnclog.Print(LL_INTINFO, VNCLOG("8 %i %i %i %i "),m_desktop->m_cursorpos.br.x,m_desktop->m_cursorpos.br.y,m_desktop->m_cursorpos.tl.x,m_desktop->m_cursorpos.tl.y);
//vnclog.Print(LL_INTINFO, VNCLOG("8 %i %i %i %i "),rect.br.x,rect.br.y,rect.tl.x,rect.tl.y);
}
}
}
}
// SCAN THE CHANGED REGION FOR ACTUAL CHANGES
// The hooks return hints as to areas that may have changed.
// We check the suggested areas, and just send the ones that
// have actually changed.
// Note that we deliberately don't check the copyrect destination
// here, to reduce the overhead & the likelihood of corrupting the
// backbuffer contents.
rfb::Region2D checkrgn;
rfb::Region2D changedrgn;
rfb::Region2D cachedrgn;
//Update the backbuffer for the copyrect region
if (!clipped_updates.get_copied_region().is_empty())
{
rfb::UpdateInfo update_info;
rfb::RectVector::const_iterator i;
clipped_updates.get_update(update_info);
if (!update_info.copied.empty())
{
for (i=update_info.copied.begin(); i!=update_info.copied.end(); i++)
m_desktop->m_buffer.CopyRect(*i, update_info.copy_delta);
}
}
//Remove the copyrect region from the other updates
//checkrgn = rgncache.union_(clipped_updates.get_copied_region());
checkrgn = rgncache.subtract(clipped_updates.get_copied_region());
//make sure the copyrect is checked next update
rgncache = clipped_updates.get_copied_region();
//Check all regions for changed and cached parts
//This is very cpu intensive, only check once for all viewers
if (!checkrgn.is_empty())
m_desktop->m_buffer.CheckRegion(changedrgn,cachedrgn, checkrgn);
updates.add_changed(changedrgn);
updates.add_cached(cachedrgn);
clipped_updates.get_update(m_server->GetUpdateTracker());
} // end mutex lock
// Clear the update tracker and region cache an solid
clipped_updates.clear();
// screen blanking
if (m_desktop->OldPowerOffTimeout!=0)
{
if (!m_server->BlackAlphaBlending())
{
SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 1, NULL, 0);
SendMessage(m_desktop->m_hwnd,WM_SYSCOMMAND,SC_MONITORPOWER,(LPARAM)2);
//call a more administrative function to block input
m_desktop->BlockInput(true);
}
}
}
// Now wait for more messages to be queued
if (!WaitMessage())
{
vnclog.Print(LL_INTERR, VNCLOG("WaitMessage() failed"));
break;
}
}//peek message
else if (msg.message == RFB_SCREEN_UPDATE)
{
// Process an incoming update event
// An area of the screen has changed
// ddihook also use RFB_SCREEN_UPDATE
// to passe the updates
rfb::Rect rect;
rect.tl = rfb::Point((SHORT)LOWORD(msg.wParam), (SHORT)HIWORD(msg.wParam));
rect.br = rfb::Point((SHORT)LOWORD(msg.lParam), (SHORT)HIWORD(msg.lParam));
//Buffer coordinates
rect.tl.x-=m_desktop->m_ScreenOffsetx;
rect.br.x-=m_desktop->m_ScreenOffsetx;
rect.tl.y-=m_desktop->m_ScreenOffsety;
rect.br.y-=m_desktop->m_ScreenOffsety;
// vnclog.Print(LL_INTERR, VNCLOG("REct %i %i %i %i "),rect.tl.x,rect.br.x,rect.tl.y,rect.br.y);
rect = rect.intersect(m_desktop->m_Cliprect);
if (!rect.is_empty())
{
rgncache = rgncache.union_(rect);
}
idle_skip = TRUE;
}
else if (msg.message == RFB_MOUSE_UPDATE)
{
// Process an incoming mouse event
// Save the cursor ID
m_desktop->SetCursor((HCURSOR) msg.wParam);
idle_skip = TRUE;
}
else if (msg.message == RFB_KEY)
{
if(msg.wParam == VK_PAUSE)
{
vncClientList clients = m_server->ClientList();
vncClientList::iterator i;
for(i = clients.begin(); i!=clients.end(); i++)
{
vncClient *client = m_server->GetClient(*i);
client->PauseConnection(!client->IsConnectionPaused());
}
}
}
else if (msg.message == WM_QUIT)
{
break;
}
else if (msg.message == WM_USER)
{
// driver dedected a cursor change
if (MyGetCursorInfo)
{
MyCURSORINFO cinfo;
cinfo.cbSize=sizeof(MyCURSORINFO);
MyGetCursorInfo(&cinfo);
m_desktop->SetCursor(cinfo.hCursor);
}
}
else if (msg.message == WM_USER+2)
{
// Forced idle full screen update
rgncache=rgncache.union_(m_desktop->m_Cliprect);
}
else
{
// Process any other messages normally
TranslateMessage(&msg);
DispatchMessage(&msg);
idle_skip = TRUE;
}
}//while
#ifndef _DEBUG
}
catch(...)
{
vnclog.Print(LL_INTERR, VNCLOG("DesktopThread.CATCH"));
}
#endif
m_desktop->SetClipboardActive(FALSE);
vnclog.Print(LL_INTINFO, VNCLOG("quitting desktop server thread"));
// Clear all the hooks and close windows, etc.
m_desktop->SetDisableInput(false);
m_desktop->Shutdown();
m_server->SingleWindow(false);
// Clear the shift modifier keys, now that there are no remote clients
vncKeymap::ClearShiftKeys();
// Switch back into our home desktop, under NT (no effect under 9x)
vncService::SelectHDESK(home_desktop);
g_DesktopThread_running=false;
HWND mywin=FindWindow("blackscreen",NULL);
if (mywin)PostMessage(mywin,WM_CLOSE, 0, 0);
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -