Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}