winvnc源码阅读笔记(四)---------vncDesktopThread线程
来源:互联网 发布:linux创建多级子目录 编辑:程序博客网 时间:2024/06/03 04:00
此线程的核心函数是run_undetached(),我们从这个函数开始阅读。
该函数的核心功能是:
(1) 该线程调用vncDesktop::Startup()进行所有的初始化工作:
1. 设置象素格式和位图信息
2. 设置各种系统 Hook, 添加系统挂钩,包括屏幕, 键盘,鼠标。
3. 设置一个定时器来处理拉模式(polling mode),每一秒钟执行一次. 这样 TriggerUpdate 例程每秒钟被执行一次.
(2) 设置处理剪切板消息
(3) 创建一个缓存区域对象。所有的区域更新消息都被缓存在该对象中,仅当 TriggerUpdate被触发时,才把这些消息传给所有的客户端。
我们来看代码:
void *
vncDesktopThread::run_undetached(void *arg)
{
if(Q_init() == NULL) //debug by qz,初始化工作。
return NULL;
rfb::SimpleUpdateTracker clipped_updates;
rfb::ClippedUpdateTracker updates(clipped_updates, m_desktop->m_Cliprect);
Q_process_desktop(); //debug by qz,处理桌面信息
while (looping && !fShutdownOrdered)
{
result=WaitForMultipleObjects(6,m_desktop->trigger_events,FALSE,waittime);//debug by qz,等待其中一个事件发送信号,有屏幕更新事件、鼠标更新事件、用户1、2、退出、定时器超时事件等。
//debug by qz,等待100毫秒时间让客户端连接
DWORD status=WaitForSingleObject(m_desktop->restart_event,100);//debug by qz,参数hHandle是一个事件的句柄,第二个参数dwMilliseconds是时间间隔。如果事件是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT。 保证这段函数不被其他线程打断.
if (status==WAIT_TIMEOUT) looping=false;
switch(result)
{
case WAIT_TIMEOUT:
case WAIT_OBJECT_0:
{
waiting_update=0;
ResetEvent(m_desktop->trigger_events[0]);
Q_30fps(); //保持最大30帧每秒
handle_driver_changes(rgncache,updates); //重要,处理驱动视频更新数据
g_update_triggered = FALSE;
Q_execl_hookdll(); //每次开启、关闭钩子库调用都需要被线程加载
//当网络上没有数据在交换(传输),并且server端屏幕没有发生变化时,退出本线程,等待主程序重启该线程,以节省系统开销
if (!m_server->IsThereFileTransBusy())//有数据交换时返回1,无则返回0
handle_display_change(threadHandle, rgncache, clipped_updates, updates);//屏幕有变化时返回1,无则返回0
Q_single_window(updates); //给window发送信号
m_desktop->m_UltraEncoder_used=m_desktop->m_server->IsThereAUltraEncodingClient(); //看是否有ultra编码的客户端
tmp<<"vncDesktopThread---run_undetached:"<<(unsigned long)GetCycleCount()<<"------"<<"beep over"<<endl;
omni_mutex_lock l(m_desktop->m_update_lock); //重要,此处可能消耗32s时间
if (m_desktop->m_server->UpdateWanted()) //这个函数耗时较多,64s-100s之间,重点注意
{
Q_handle_cursorpos(); //处理光标信息
Q_pooling_or_driver(); //轮询或驱动模式
Q_process_mouse_pointer(); //处理鼠标信息
omni_mutex_lock ll(m_desktop->m_update_lock);// 防止任何客户端接触到缓冲区
if (!m_desktop->m_hookdriver && !m_server->SingleWindow()) // 检查窗口的位置
m_desktop->CalcCopyRects(updates);
Q_grab_display(); //捕捉屏幕信息
tmp<<"vncDesktopThread---run_undetached:"<<(unsigned long)GetCycleCount()<<"------"<<"grab display over"<<endl;
// capture=true;
Q_handle_mouse(); //处理鼠标信息,主要是处理客户端的鼠标触发和移动操作
Q_scan_changed_region(clipped_updates);//扫描整个屏幕以确定有哪些区域改变了
updates.add_changed(changedrgn); //增加需要更新的区域,耗时16ms,添加数据到发送缓冲里面
updates.add_cached(cachedrgn);
clipped_updates.get_update(m_server->GetUpdateTracker()); //触发socket发送更新数据,重要.
Q_clear_update_tracker(clipped_updates);
} //end if UpdateWanted
//newtick = timeGetTime();
}//end case
break;
case WAIT_OBJECT_0+1:
ResetEvent(m_desktop->trigger_events[1]);
m_desktop->lock_region_add=true;
rgncache.assign_union(m_desktop->rgnpump);
m_desktop->rgnpump.clear();
m_desktop->lock_region_add=false;
waiting_update++;
break;
case WAIT_OBJECT_0+2:
ResetEvent(m_desktop->trigger_events[2]);
break;
case WAIT_OBJECT_0+3:
if (MyGetCursorInfo)
{
MyCURSORINFO cinfo;
cinfo.cbSize=sizeof(MyCURSORINFO);
MyGetCursorInfo(&cinfo);
m_desktop->SetCursor(cinfo.hCursor);
}
ResetEvent(m_desktop->trigger_events[3]);
break;
case WAIT_OBJECT_0+4:
rgncache.assign_union(m_desktop->m_Cliprect);
ResetEvent(m_desktop->trigger_events[4]);
break;
case WAIT_OBJECT_0+5:
//break to close
looping=false;
ResetEvent(m_desktop->trigger_events[5]);
break;
}//end switch
}//while
stop_hookwatch=true;
if (threadHandle)
{
WaitForSingleObject( threadHandle, 5000 );
CloseHandle(threadHandle);
}
m_desktop->SetClipboardActive(FALSE);
vnclog.Print(LL_INTINFO, VNCLOG("quitting desktop server thread/n"));
// Clear all the hooks and close windows, etc.
m_desktop->SetBlockInputState(false);
m_server->SingleWindow(false);
vnclog.Print(LL_INTINFO, VNCLOG("quitting desktop server thread:SetBlockInputState/n"));
// Clear the shift modifier keys, now that there are no remote clients
vncKeymap::ClearShiftKeys();
vnclog.Print(LL_INTINFO, VNCLOG("quitting desktop server thread:ClearShiftKeys/n"));
// Switch back into our home desktop, under NT (no effect under 9x)
//TAG14
HWND mywin=FindWindow("blackscreen",NULL);
if (mywin)SendMessage(mywin,WM_CLOSE, 0, 0);
g_DesktopThread_running=false;
vnclog.Print(LL_INTINFO, VNCLOG("quitting desktop server thread:g_DesktopThread_running=false/n"));
m_desktop->Shutdown();
vnclog.Print(LL_INTINFO, VNCLOG("quitting desktop server thread:m_desktop->Shutdown/n"));
return NULL;
}
- winvnc源码阅读笔记(四)---------vncDesktopThread线程
- winvnc源码阅读笔记(一)---------线程
- WINVNC源码阅读(四)
- winvnc源码阅读笔记(二)---------vncClientUpdateThread线程
- winvnc源码阅读笔记(三)---------vncClient::SendUpdate线程
- WINVNC源码阅读(一)
- WINVNC源码阅读(二)
- WINVNC源码阅读(三)
- WINVNC源码阅读(五)
- WINVNC源码阅读(六)
- WINVNC源码阅读(七)
- WINVNC源码分析(四)
- WINVNC源码分析(四)-vnchooks
- WINVNC源码分析(四)-vnchooks
- AFNetworking 3.0 源码阅读笔记(四)
- SDWebImage 源码阅读笔记(四)
- libevent源码阅读笔记(四)
- WINVNC源码分析(四)——IO之rdr库
- DataSnap Server 中使用多态
- 数据存取
- LUA函数和C函数的相互调用
- 推荐一个好的文献管理工具吧,各位童鞋好友
- c# 设计
- winvnc源码阅读笔记(四)---------vncDesktopThread线程
- js 点击文本框后弹出选择日期
- c#编程访问网络共享
- 实施IT治理:方法论、模型、全球最佳实践
- event.preventDefault()
- python urllib从远程服务器下载文件到本地
- 登峰造极的人物 God Like
- 深度优先搜索算法(Depth first search)
- Android源码的层次结构分析