BOOL vncClient::SendUpdate(rfb::SimpleUpdateTracker &update) { // If there is nothing to send then exit if (update.is_empty()) { vnclog.Print(LL_INTERR, "no data to send\n"); return FALSE; } // Get the update info from the tracker rfb::UpdateInfo update_info; update.get_update(update_info); update.clear(); // Find out how many rectangles in total will be updated // This includes copyrects and changed rectangles split // up by codings such as CoRRE. int updates = 0; updates += update_info.copied.size(); rfb::RectVector::const_iterator i; for (i=update_info.changed.begin(); i != update_info.changed.end(); i++) { updates += m_encodemgr.GetNumCodedRects(*i); } // If there are no updates then return if (updates == 0) { vnclog.Print(LL_INTERR, "no data to send2\n"); return FALSE; } // Otherwise, send <number of rectangles> header rfbFramebufferUpdateMsg header; header.nRects = Swap16IfLE(updates); if (!SendRFBMsg(rfbFramebufferUpdate, (BYTE *) &header, sz_rfbFramebufferUpdateMsg)) return FALSE; // Send the copyrect rectangles if (!update_info.copied.empty()) { rfb::Point to_src_delta = update_info.copy_delta.negate(); for (i=update_info.copied.begin(); i!=update_info.copied.end(); i++) { rfb::Point src = (*i).tl.translate(to_src_delta); if (!SendCopyRect(*i, src)) return FALSE; } } // Encode & send the actual rectangles if (!SendRectangles(update_info.changed)) return FALSE; return TRUE; }
bool vncDesktopThread::handle_display_change(HANDLE& threadHandle, rfb::Region2D& rgncache, rfb::SimpleUpdateTracker& clipped_updates, rfb::ClippedUpdateTracker& updates) { if ((m_desktop->m_displaychanged || //WM_DISPLAYCHANGE !vncService::InputDesktopSelected() || //handle logon and screensaver desktops m_desktop->m_SWtoDesktop || //switch from SW to full desktop or visa versa m_desktop->m_hookswitch|| //hook change request m_desktop->asked_display!=m_desktop->m_buffer.GetDisplay() //monitor change request ) ) { // We need to wait until viewer has send if he support Size changes if (!m_server->All_clients_initialalized()) { Sleep(30); vnclog.Print(LL_INTERR, VNCLOG("Wait for viewer init \n")); } //logging if (m_desktop->m_displaychanged) vnclog.Print(LL_INTERR, VNCLOG("++++Screensize changed \n")); if (m_desktop->m_SWtoDesktop) vnclog.Print(LL_INTERR, VNCLOG("m_SWtoDesktop \n")); if (m_desktop->m_hookswitch) vnclog.Print(LL_INTERR, VNCLOG("m_hookswitch \n")); if (m_desktop->asked_display!=m_desktop->m_buffer.GetDisplay()) vnclog.Print(LL_INTERR, VNCLOG("desktop switch %i %i \n"),m_desktop->asked_display,m_desktop->m_buffer.GetDisplay()); if (!m_server->IsThereFileTransBusy()) if (!vncService::InputDesktopSelected()) vnclog.Print(LL_INTERR, VNCLOG("++++InputDesktopSelected \n")); BOOL screensize_changed=false; BOOL monitor_changed=false; rfbServerInitMsg oldscrinfo; //******************************************************* // Lock Buffers from here //******************************************************* { if (XRichCursorEnabled) m_server->UpdateCursorShape(); /// We lock all buffers,,and also back the client thread update mechanism omni_mutex_lock l(m_desktop->m_update_lock); #ifdef _DEBUG char szText[256]; sprintf(szText," ++++++ Mutex lock display changes\n"); OutputDebugString(szText); #endif // We remove all queue updates from the tracker m_server->Clear_Update_Tracker(); // Also clear the current updates rgncache.clear(); // Also clear the copy_rect updates clipped_updates.clear(); // TESTTESTTEST // Are all updates cleared....old updates could generate bounding errors // any other queues to clear ? Yep cursor positions m_desktop->m_cursorpos.tl.x=0; m_desktop->m_cursorpos.tl.y=0; m_desktop->m_cursorpos.br.x=0; m_desktop->m_cursorpos.br.y=0; //keep a copy of the old screen size, so we can check for changes later on oldscrinfo = m_desktop->m_scrinfo; if (m_desktop->asked_display!=m_desktop->m_buffer.GetDisplay()) { m_desktop->Checkmonitors(); m_desktop->asked_display=m_desktop->m_buffer.GetDisplay(); int old_monitor=m_desktop->current_monitor; m_desktop->current_monitor=1; if (m_desktop->asked_display==2 && m_desktop->nr_monitors>1) m_desktop->current_monitor=2; if (m_desktop->asked_display==3 && m_desktop->nr_monitors>1) m_desktop->current_monitor=3; vnclog.Print(LL_INTERR, VNCLOG("OLd Current mon %i %i \n"),old_monitor,m_desktop->current_monitor); if ( old_monitor!=m_desktop->current_monitor) monitor_changed=true; } //******************************************************* // Reinitialize buffers,color, etc // monitor change, for non driver, use another buffer //******************************************************* if (!m_server->IsThereFileTransBusy()) if (m_desktop->m_displaychanged || !vncService::InputDesktopSelected() || m_desktop->m_hookswitch || (monitor_changed && !m_desktop->m_videodriver)) { // Attempt to close the old hooks // shutdown(true) driver is reinstalled without shutdown,(shutdown need a 640x480x8 switch) vnclog.Print(LL_INTERR, VNCLOG("m_desktop->Shutdown")); monitor_changed=false; if (!m_desktop->Shutdown()) { vnclog.Print(LL_INTERR, VNCLOG("Shutdown KillAuthClients\n")); m_server->KillAuthClients(); return false; } bool fHookDriverWanted = (FALSE != m_desktop->m_hookdriver); Sleep(1000); vnclog.Print(LL_INTERR, VNCLOG("m_desktop->Startup")); if (m_desktop->Startup() != 0) { vnclog.Print(LL_INTERR, VNCLOG("Startup KillAuthClients\n")); m_server->KillAuthClients(); SetEvent(m_desktop->restart_event); return false; } if (m_desktop->m_videodriver) { if (!XRichCursorEnabled) m_desktop->m_videodriver->HardwareCursor(); else m_desktop->m_videodriver->NoHardwareCursor(); } m_server->SetScreenOffset(m_desktop->m_ScreenOffsetx,m_desktop->m_ScreenOffsety,m_desktop->nr_monitors); // sf@2003 - After a new Startup(), we check if the required video driver // is actually available. If not, we force hookdll // No need for m_hookswitch again because the driver is NOT available anyway. // All the following cases are now handled: // 1. Desktop thread starts with "Video Driver" checked and no video driver available... // -> HookDll forced (handled by the first InitHookSettings() after initial Startup() call // 2. Desktop Thread starts without "Video Driver" checked but available driver // then the user checks "Video Driver" -> Video Driver used // 3. Desktop thread starts with "Video Driver" and available driver used // Then driver is switched off (-> hookDll) // Then the driver is switched on again (-> hook driver used again) // 4. Desktop thread starts without "Video Driver" checked and no driver available // then the users checks "Video Driver" if (fHookDriverWanted && m_desktop->m_videodriver == NULL) { vnclog.Print(LL_INTERR, VNCLOG("m_videodriver == NULL \n")); m_desktop->SethookMechanism(true, false); // InitHookSettings() would work as well; } stop_hookwatch=true; vnclog.Print(LL_INTERR, VNCLOG("threadHandle \n")); if (threadHandle) { WaitForSingleObject( threadHandle, INFINITE ); CloseHandle(threadHandle); stop_hookwatch=false; threadHandle=NULL; } vnclog.Print(LL_INTERR, VNCLOG("threadHandle2 \n")); } //******************************************************* // end reinit //******************************************************* if ((m_desktop->m_scrinfo.framebufferWidth != oldscrinfo.framebufferWidth) || (m_desktop->m_scrinfo.framebufferHeight != oldscrinfo.framebufferHeight || m_desktop->m_SWtoDesktop==TRUE )) { screensize_changed=true; vnclog.Print(LL_INTINFO, VNCLOG("SCR: new screen format %dx%dx%d\n"), m_desktop->m_scrinfo.framebufferWidth, m_desktop->m_scrinfo.framebufferHeight, m_desktop->m_scrinfo.format.bitsPerPixel); } m_desktop->m_displaychanged = FALSE; m_desktop->m_hookswitch = FALSE; m_desktop->Hookdll_Changed = m_desktop->On_Off_hookdll; // Set the hooks again if necessary ! m_desktop->m_SWtoDesktop=FALSE; //**************************************************************************** //************* SCREEN SIZE CHANGED //**************************************************************************** if (screensize_changed) { vnclog.Print(LL_INTERR, VNCLOG("Size changed\n")); POINT CursorPos; m_desktop->SWinit(); m_desktop->GetQuarterSize(); GetCursorPos(&CursorPos); CursorPos.x=g_dpi.UnscaleX(CursorPos.x); CursorPos.y=g_dpi.UnscaleY(CursorPos.y); CursorPos.x -= m_desktop->m_ScreenOffsetx; CursorPos.y -= m_desktop->m_ScreenOffsety; m_desktop->m_cursorpos.tl = CursorPos; m_desktop->m_cursorpos.br = rfb::Point(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)).translate(CursorPos); m_server->SetSWOffset(m_desktop->m_SWOffsetx,m_desktop->m_SWOffsety); // Adjust the UpdateTracker clip region updates.set_clip_region(m_desktop->m_Cliprect); m_desktop->m_buffer.ClearCache(); } if (monitor_changed) { // we are using the driver, so a monitor change is a view change, like a special kind of single window // m_desktop->current_monitor is the new monitor we want to see // monitor size mymonitor[m_desktop->current_monitor-1] // m_SWOffset is used by the encoders to send the correct coordinates to the viewer // Cliprect, buffer coordinates m_desktop->m_SWOffsetx=m_desktop->mymonitor[m_desktop->current_monitor-1].offsetx-m_desktop->mymonitor[2].offsetx; m_desktop->m_SWOffsety=m_desktop->mymonitor[m_desktop->current_monitor-1].offsety-m_desktop->mymonitor[2].offsety; m_server->SetSWOffset(m_desktop->m_SWOffsetx,m_desktop->m_SWOffsety); m_desktop->m_Cliprect.tl.x=m_desktop->mymonitor[m_desktop->current_monitor-1].offsetx-m_desktop->mymonitor[2].offsetx; m_desktop->m_Cliprect.tl.y=m_desktop->mymonitor[m_desktop->current_monitor-1].offsety-m_desktop->mymonitor[2].offsety; m_desktop->m_Cliprect.br.x=m_desktop->mymonitor[m_desktop->current_monitor-1].offsetx+ m_desktop->mymonitor[m_desktop->current_monitor-1].Width-m_desktop->mymonitor[2].offsetx; m_desktop->m_Cliprect.br.y=m_desktop->mymonitor[m_desktop->current_monitor-1].offsety+ m_desktop->mymonitor[m_desktop->current_monitor-1].Height-m_desktop->mymonitor[2].offsety; vnclog.Print(LL_INTERR, VNCLOG("***********###############************ %i %i %i %i %i %i\n"),m_desktop->m_SWOffsetx,m_desktop->m_SWOffsety ,m_desktop->m_Cliprect.tl.x,m_desktop->m_Cliprect.tl.y,m_desktop->m_Cliprect.br.x,m_desktop->m_Cliprect.br.y); rgncache.assign_union(rfb::Region2D(m_desktop->m_Cliprect)); updates.set_clip_region(m_desktop->m_Cliprect); m_desktop->m_buffer.ClearCache(); m_desktop->m_buffer.BlackBack(); } m_desktop->m_buffer.ClearCache(); m_desktop->m_buffer.BlackBack(); InvalidateRect(NULL,NULL,TRUE); rgncache.assign_union(rfb::Region2D(m_desktop->m_Cliprect)); if (memcmp(&m_desktop->m_scrinfo.format, &oldscrinfo.format, sizeof(rfbPixelFormat)) != 0) { vnclog.Print(LL_INTERR, VNCLOG("Format changed\n")); m_server->UpdatePalette(false); // changed no lock ok m_server->UpdateLocalFormat(false); // changed no lock ok } if (screensize_changed) { screensize_changed=false; m_server->SetNewSWSize(m_desktop->m_scrinfo.framebufferWidth,m_desktop->m_scrinfo.framebufferHeight,FALSE);//changed no lock ok m_server->SetScreenOffset(m_desktop->m_ScreenOffsetx,m_desktop->m_ScreenOffsety,m_desktop->nr_monitors);// no lock ok } if (monitor_changed) { monitor_changed=false; m_server->SetNewSWSize(m_desktop->mymonitor[m_desktop->current_monitor-1].Width,m_desktop->mymonitor[m_desktop->current_monitor-1].Height,TRUE); //changed no lock ok } #ifdef _DEBUG //char szText[256]; sprintf(szText," ++++++ Mutex unlock display changes\n"); OutputDebugString(szText); #endif }// end lock } return true; }