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; }
// Modif rdv@2002 - v1.1.x - videodriver BOOL vncDesktopThread::handle_driver_changes(rfb::Region2D &rgncache,rfb::UpdateTracker &tracker) { omni_mutex_lock l(m_desktop->m_videodriver_lock); int oldaantal=m_desktop->m_videodriver->oldaantal; int counter=m_desktop->pchanges_buf->counter; // int nr_updates=m_desktop->pchanges_buf->pointrect[0].type; // vnclog.Print(LL_INTERR, VNCLOG("updates, rects %i\n"),oldaantal-counter); if (oldaantal==counter) return FALSE; if (counter<1 || counter >1999) return FALSE; // m_desktop->pchanges_buf->pointrect[0].type=0; if (!m_server->SingleWindow()) m_screen_moved=m_desktop->CalcCopyRects(tracker); else m_screen_moved=true; /// HEITE01E // buffer was overloaded, so we use the bounding rect /* if (nr_updates>2000) { rfb::Rect rect; int x = m_desktop->pchanges_buf->pointrect[0].rect.left; int w = m_desktop->pchanges_buf->pointrect[0].rect.right-m_desktop->pchanges_buf->pointrect[0].rect.left; int y = m_desktop->pchanges_buf->pointrect[0].rect.top; int h = m_desktop->pchanges_buf->pointrect[0].rect.bottom-m_desktop->pchanges_buf->pointrect[0].rect.top; 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); m_desktop->m_videodriver->oldaantal=counter; } return TRUE; }*/ if (m_server->SingleWindow()) m_screen_moved=true; if (oldaantal<counter) { for (int i =oldaantal+1; i<=counter;i++) { copy_bitmaps_to_buffer(i,rgncache,tracker); } } else { int i = 0; for (i =oldaantal+1;i<MAXCHANGES_BUF;i++) { copy_bitmaps_to_buffer(i,rgncache,tracker); } for (i=1;i<=counter;i++) { copy_bitmaps_to_buffer(i,rgncache,tracker); } } // vnclog.Print(LL_INTINFO, VNCLOG("Nr rects %i \n"),rgncache.Numrects()); m_desktop->m_videodriver->oldaantal=counter; // A lot updates left after combining // This generates an overflow // We expand each single update to minimum 32x32 if (rgncache.Numrects()>150) { rfb::Region2D rgntemp; rfb::RectVector rects; rfb::RectVector::iterator i; rgncache.get_rects(rects, 1, 1); for (i = rects.begin(); i != rects.end(); i++) { rfb::Rect rect = *i; rect.tl.x=rect.tl.x/32*32; rect.tl.y=rect.tl.y/32*32; rect.br.x=rect.br.x/32*32+32; rect.br.y=rect.br.y/32*32+32; if (rect.br.x>m_desktop->m_bmrect.br.x) rect.br.x=m_desktop->m_bmrect.br.x; if (rect.br.y>m_desktop->m_bmrect.br.y) rect.br.y=m_desktop->m_bmrect.br.y; rgntemp.assign_union(rect); } //Still to many little updates //Use the bounding rectangle for updates if (rgntemp.Numrects()>50) { Rect brect=rgntemp.get_bounding_rect(); rgncache.clear(); rgncache.assign_union(brect); } else { rgncache.clear(); rgncache.assign_union(rgntemp); } } return TRUE; }