From 3b8109daecc1c12359d27896686ff63b7ec03a22 Mon Sep 17 00:00:00 2001 From: Denis Oliver Kropp Date: Thu, 21 Oct 2010 10:25:07 +0200 Subject: new update mechanism --- src/Main.cxx | 129 +++++++++++++++++++------ src/Options.cxx | 42 ++++++++ src/SourceWin32.cxx | 269 +++++++++++++++++++++++++++++++++------------------- src/classes.h | 3 + 4 files changed, 314 insertions(+), 129 deletions(-) diff --git a/src/Main.cxx b/src/Main.cxx index 20e7d2c..0fb9fc0 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -3,23 +3,37 @@ namespace PluggIt { D_DEBUG_DOMAIN( PluggIt_Main, "PluggIt/Main", "PluggIt Main" ); D_DEBUG_DOMAIN( PluggIt_View, "PluggIt/View", "PluggIt View" ); +#define NOTRCSOURCEMASK 0x20 +#define HK_REMOTEAPP DIKS_CUSTOM97 + + class Main extends View, Runnable { class Config { public DFBDimension m_size; public DFBPoint m_offset; public DFBDimension m_resolution; + public DFBLocation m_destination; public DFBSurfacePixelFormat m_format; public std::string m_title; public bool m_interactive; - public bool m_updating; - public bool m_use_driver; + public bool m_always_all; + public long m_interval_all; + public long m_interval_hot; + public long m_focus_timeout; public Config() : m_format(DSPF_UNKNOWN), m_interactive(false), - m_updating(false) + m_always_all(false), + m_interval_all(400), + m_interval_hot(100), + m_focus_timeout(0) { + m_destination.x = 0.0f; + m_destination.y = 0.0f; + m_destination.w = 1.0f; + m_destination.h = 1.0f; } }; @@ -43,21 +57,29 @@ class Main extends View, Runnable private bool m_view_visible; private DFBSurfacePixelFormat m_view_format; + private u8 m_opacity; + + private IDiVine *m_divine; + public Main() : m_source(NULL), - m_view_visible(false) + m_view_visible(false), + m_opacity(255) { D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ ); m_options.addOption( new Options::OptionDimension( "-s", "--size", "x", "Size of view", m_config.m_size ) ); m_options.addOption( new Options::OptionPoint ( "-o", "--offset", ",", "Offset of view", m_config.m_offset ) ); m_options.addOption( new Options::OptionDimension( "-r", "--resolution", "x", "Resolution of view", m_config.m_resolution ) ); + m_options.addOption( new Options::OptionLocation ( "-d", "--destination", ",-x", "Destination location", m_config.m_destination ) ); m_options.addOption( new Options::OptionFormat ( "-f", "--format", "", "Pixel format of view", m_config.m_format ) ); m_options.addOption( new Options::OptionString ( "-t", "--title", "", "Title of window to show", m_config.m_title ) ); m_options.addOption( new Options::OptionBool ( "-i", "--interactive", "", "Use interactive window picking", m_config.m_interactive ) ); - m_options.addOption( new Options::OptionBool ( "-u", "--updating", "", "Update continuously", m_config.m_updating ) ); - m_options.addOption( new Options::OptionBool ( "-d", "--driver", "", "Use driver mode", m_config.m_use_driver ) ); + m_options.addOption( new Options::OptionBool ( "-a", "--all", "", "Always all", m_config.m_always_all ) ); + m_options.addOption( new Options::OptionLong ( "-A", "--inter-all", "", "Interval all", m_config.m_interval_all ) ); + m_options.addOption( new Options::OptionLong ( "-H", "--inter-hot", "", "Interval hot", m_config.m_interval_hot ) ); + m_options.addOption( new Options::OptionLong ( "-F", "--focus", "", "Focus timeout", m_config.m_focus_timeout ) ); } public void main( int argc, char *argv[] ) { @@ -71,7 +93,29 @@ class Main extends View, Runnable return; initDFB(); - initSource(); + + + DiVineCreate( &m_divine ); + +#ifdef __WIN32__ + SourceWin32::Config config( m_config.m_interactive ? + SourceWin32::Config::WINDOW_SELECTION_INTERACTIVE : + (m_config.m_title.size() > 0 ? + SourceWin32::Config::WINDOW_SELECTION_TITLE : + SourceWin32::Config::WINDOW_SELECTION_NONE), m_config.m_title, + m_config.m_always_all, m_config.m_interval_all, m_config.m_interval_hot ); + + m_source = new SourceWin32( this, config ); +#else + SourceX11::Config config( m_config.m_interactive ? + SourceX11::Config::WINDOW_SELECTION_INTERACTIVE : + (m_config.m_title.size() > 0 ? + SourceX11::Config::WINDOW_SELECTION_TITLE : + SourceX11::Config::WINDOW_SELECTION_NONE), m_config.m_title ); + + m_source = new SourceX11( this, config ); +#endif + Thread *thread = new Thread( this, "Main" ); @@ -115,7 +159,19 @@ class Main extends View, Runnable up = true; case DWET_KEYDOWN: - key = CKeySend::MapDfbKeyEventToVK( event->key_symbol ); + if (event->key_symbol == DIKS_0 && !up) { + m_opacity = (m_opacity == 255 ? 0 : 255); + m_window.SetOpacity( m_opacity ); + } + else + key = CKeySend::MapDfbKeyEventToVK( event->key_symbol ); + break; + + case DWET_LOSTFOCUS: + if (m_config.m_focus_timeout) { + sleep( m_config.m_focus_timeout ); + hk_SendKey( HK_REMOTEAPP, 0, 0, 1 ); + } break; default: @@ -143,29 +199,6 @@ class Main extends View, Runnable m_events = m_dfb.CreateEventBuffer(); } - private void initSource() { - D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ ); - -#ifdef __WIN32__ - SourceWin32::Config config( m_config.m_interactive ? - SourceWin32::Config::WINDOW_SELECTION_INTERACTIVE : - (m_config.m_title.size() > 0 ? - SourceWin32::Config::WINDOW_SELECTION_TITLE : - SourceWin32::Config::WINDOW_SELECTION_NONE), m_config.m_title, - m_config.m_updating, m_config.m_use_driver ); - - m_source = new SourceWin32( this, config ); -#else - SourceX11::Config config( m_config.m_interactive ? - SourceX11::Config::WINDOW_SELECTION_INTERACTIVE : - (m_config.m_title.size() > 0 ? - SourceX11::Config::WINDOW_SELECTION_TITLE : - SourceX11::Config::WINDOW_SELECTION_NONE), m_config.m_title ); - - m_source = new SourceX11( this, config ); -#endif - } - private void run() { try { m_source->MainLoop(); @@ -271,6 +304,14 @@ class Main extends View, Runnable m_view_format = m_surface.GetPixelFormat(); m_window.AttachEventBuffer( m_events ); + + + DFBWindowGeometry geometry; + + geometry.mode = DWGM_LOCATION; + geometry.location = m_config.m_destination; + + m_window.SetDstGeometry( &geometry ); } m_view_size = size; @@ -466,6 +507,32 @@ class Main extends View, Runnable m_view_visible = true; } } + + void + hk_SendKey( int keyname, + int src, + int sys, + int cmd ) + { + if (m_divine) { + DFBResult ret; + DFBInputEvent event; + + src |= NOTRCSOURCEMASK; + + event.clazz = DFEC_INPUT; + event.type = DIET_KEYPRESS; + event.key_code = (((unsigned int)src & 0xff) << 24) | (((unsigned int)sys & 0xff) << 16) | ((unsigned int)cmd & 0xffff); + event.key_symbol = (DFBInputDeviceKeySymbol)keyname; + event.flags = (DFBInputEventFlags)(DIEF_KEYCODE | DIEF_KEYSYMBOL); + + ret = m_divine->SendEvent( m_divine, &event ); + if (ret) + D_DERROR( (DirectResult) ret, "IDiVine::SendEvent() failed!\n" ); + } + else + D_ERROR( "IDiVine interface is null!\n" ); + } }; } diff --git a/src/Options.cxx b/src/Options.cxx index 27e8924..f68b0f3 100644 --- a/src/Options.cxx +++ b/src/Options.cxx @@ -196,6 +196,48 @@ class Options } }; + public class OptionRectangle extends Option { + private DFBRectangle &m_value; + + public OptionRectangle( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + DFBRectangle &value ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + } + + public virtual bool Parse( const char *arg ) { + if (sscanf( arg, "%d,%d-%dx%d", &m_value.x, &m_value.y, &m_value.w, &m_value.h ) != 4) { + D_ERROR( "Option/Rectangle: Invalid argument to '%s' or '%s'!\n", m_short_name, m_long_name ); + return false; + } + + return true; + } + }; + + public class OptionLocation extends Option { + private DFBLocation &m_value; + + public OptionLocation( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + DFBLocation &value ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + } + + public virtual bool Parse( const char *arg ) { + if (sscanf( arg, "%f,%f-%fx%f", &m_value.x, &m_value.y, &m_value.w, &m_value.h ) != 4) { + D_ERROR( "Option/Location: Invalid argument to '%s' or '%s'!\n", m_short_name, m_long_name ); + return false; + } + + return true; + } + }; + private vector m_options; diff --git a/src/SourceWin32.cxx b/src/SourceWin32.cxx index 1007e35..fd9a13c 100644 --- a/src/SourceWin32.cxx +++ b/src/SourceWin32.cxx @@ -3,17 +3,6 @@ namespace PluggIt { D_DEBUG_DOMAIN( PluggIt_SourceWin32, "PluggIt/SourceWin32", "PluggIt Source Win32" ); -#include "ScreenHooks.h" - -// Constants -const UINT RFB_SCREEN_UPDATE = RegisterWindowMessage("WinVNC.Update.DrawRect"); -const UINT RFB_COPYRECT_UPDATE = RegisterWindowMessage("WinVNC.Update.CopyRect"); -const UINT RFB_MOUSE_UPDATE = RegisterWindowMessage("WinVNC.Update.Mouse"); -const char szDesktopSink[] = "WinVNC desktop sink"; - -typedef BOOL (*SetHooksFn)(DWORD thread_id,UINT UpdateMsg,UINT CopyMsg,UINT MouseMsg,BOOL ddihook); - - class SourceWin32 extends Source, Runnable { private HINSTANCE m_hInstance; @@ -40,16 +29,10 @@ class SourceWin32 extends Source, Runnable private Updates m_updates; - private VIDEODRIVER m_driver; - private bool m_using_driver; - private pthread_mutex_t m_lock; private pthread_cond_t m_cond; - SetHooksFn SetHooks; - - public class Config extends Source::Config { friend class SourceWin32; @@ -61,23 +44,34 @@ class SourceWin32 extends Source, Runnable private WindowSelection m_selection; private std::string m_title; - private bool m_updating; - private bool m_use_driver; + private bool m_always_all; + private int m_interval_all; + private int m_interval_hot; public Config( WindowSelection selection, const std::string &title = std::string(), - bool updating = false, bool use_driver = true ) + bool always_all = false, int interval_all = 400, + int interval_hot = 100 ) { - m_selection = selection; - m_title = title; - m_updating = updating; - m_use_driver = use_driver; + m_selection = selection; + m_title = title; + m_always_all = always_all; + m_interval_all = interval_all; + m_interval_hot = interval_hot; } }; - public SourceWin32( View *view, const Config &config ) : Source( view, config ), m_updates(16) { + private const Config &m_config_win32; + + + public SourceWin32( View *view, const Config &config ) + : + Source( view, config ), + m_updates(16), + m_config_win32( config ) + { D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p )\n", __FUNCTION__, view ); m_hInstance = GetModuleHandle( NULL ); @@ -119,7 +113,24 @@ class SourceWin32 extends Source, Runnable m_size.w = rect.right - rect.left; m_size.h = rect.bottom - rect.top; - queueUpdate( 0, 0, m_size.w - 1, m_size.h - 1 ); + +#define RECT_WIDTH 32 +#define RECT_HEIGHT 32 + + for (int y=0; y m_size.w - 1) + region.x2 = m_size.w - 1; + + if (region.y2 > m_size.h - 1) + region.y2 = m_size.h - 1; + + m_all_rects.push_back( DFBRectangle(region) ); + } + } + std::string t = getWindowTitle( m_window ); @@ -127,10 +138,6 @@ class SourceWin32 extends Source, Runnable D_INFO( "Source/Win32: Window %d,%d-%ux%u, name '%s'\n", m_position.x, m_position.y, m_size.w, m_size.h, t.c_str() ); - if (config.m_use_driver) - m_driver.VIDEODRIVER_start( m_position.x, m_position.y, m_size.w, m_size.h ); - - m_using_driver = m_driver.mypchangebuf != NULL; m_view->config( m_size ); @@ -219,45 +226,18 @@ class SourceWin32 extends Source, Runnable D_DEBUG_AT( PluggIt_SourceWin32, " -> %4d,%4d-%4dx%4d (%d regions, %d rectangles)\n", DFB_RECTANGLE_VALS_FROM_REGION( &bounding ), m_updates.num_regions(), rects.size() ); + /* + * (4) Update TV + */ + m_view->update( rects, (void*)((char*) m_pixels2 + m_pitch2 * (m_size.h - 1)), - m_pitch2 ); + m_updates.reset(); pthread_mutex_unlock( &m_lock ); - - - for (unsigned int i=0; iupdate( rects, (void*)((char*) m_pixels + m_pitch * (m_size.h - 1)), - m_pitch ); } } -/**********************************************************************************************************************/ - - private void queueUpdate( int x1, int y1, int x2, int y2 ) { - D_DEBUG_AT( PluggIt_SourceWin32, "%s( %d,%d-%dx%d )\n", __FUNCTION__, x1, y1, x2 - x1 + 1, y2 - y1 + 1 ); - - pthread_mutex_lock( &m_lock ); - - DFBRegion damage( x1, y1, x2, y2 ); - - m_updates.addRegion( damage ); - - pthread_cond_signal( &m_cond ); - - pthread_mutex_unlock( &m_lock ); - } - /**********************************************************************************************************************/ private static std::string getWindowTitle( HWND window ) { @@ -270,9 +250,6 @@ class SourceWin32 extends Source, Runnable return buf; } - -/**********************************************************************************************************************/ - class EnumContext { public const std::string &title; public HWND window; @@ -446,54 +423,150 @@ class SourceWin32 extends Source, Runnable /**********************************************************************************************************************/ - public virtual int MainLoop() { + private bool diffRect( const DFBRectangle_C &rect ) { + D_DEBUG_AT( PluggIt_SourceWin32, "(2) comparing %4d,%4d-%4dx%4d\n", + DFB_RECTANGLE_VALS( &rect ) ); - HMODULE hModule; - char szCurrentDir[MAX_PATH]; + DFBRegion region( rect ); - if (GetModuleFileName(NULL, szCurrentDir, MAX_PATH)) { - char* p = strrchr(szCurrentDir, '\\'); - if (p == NULL) return 0; - *p = '\0'; - strcat (szCurrentDir,"\\vnchooks.dll"); - } + for (int y = region.y1; y <= region.y2; y++) { + const u64 *p1 = (const u64*)( (const u8*)m_pixels + (m_size.h - 1 - y) * m_pitch ); + const u64 *p2 = (const u64*)( (const u8*)m_pixels2 + (m_size.h - 1 - y) * m_pitch2 ); - hModule = LoadLibrary( szCurrentDir ); - if (!hModule) - throw new Exception( "Failed to load vnchooks.dll!" ); + for (int x = region.x1/2; x <= region.x2/2; x++) { + if (p1[x] != p2[x]) + return true; + } + } - SetHooks = (SetHooksFn) GetProcAddress( hModule, "SetHooks" ); + return false; + } + private vector m_all_rects; + private vector m_hot_rects; - if (!SetHooks( - GetCurrentThreadId(), - RFB_SCREEN_UPDATE, - RFB_COPYRECT_UPDATE, - RFB_MOUSE_UPDATE, false - )) - throw new Exception( "Failed to set hooks!" ); + public virtual int MainLoop() { + long long last_all = 0; + while (true) { + bool all = true; + const vector *copy_rects; - MSG msg; + if (m_config_win32.m_always_all) { + usleep( m_config_win32.m_interval_all * 1000 ); - printf( " -> RFB_SCREEN_UPDATE = %u\n", RFB_SCREEN_UPDATE ); - printf( " -> RFB_COPYRECT_UPDATE = %u\n", RFB_COPYRECT_UPDATE ); + copy_rects = &m_all_rects; + } + else { + long long this_time = direct_clock_get_abs_millis(); - while (WaitMessage()/*GetMessage( &msg, 0, 0, 0 )*/) { - printf( " -> Dispatching event (id %u)...\n", msg.message ); + if (this_time - last_all >= m_config_win32.m_interval_all) { + last_all = this_time; - if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) { - if (msg.message == RFB_SCREEN_UPDATE) { - queueUpdate( (SHORT)LOWORD(msg.wParam), - (SHORT)HIWORD(msg.wParam), - (SHORT)LOWORD(msg.lParam) - 1, - (SHORT)HIWORD(msg.lParam) - 1 ); + copy_rects = &m_all_rects; } else { - TranslateMessage( &msg ); - DispatchMessage( &msg ); + if (m_hot_rects.empty()) { + usleep( 20000 ); + continue; + } + else + usleep( m_config_win32.m_interval_hot * 1000 ); + + copy_rects = &m_hot_rects; + + all = false; } } + + /* + * (1) Copy from desktop to bitmap + */ + if (all) { + D_DEBUG_AT( PluggIt_SourceWin32, "(1) copying all %4d,%4d-%4dx%4d\n", + 0, 0, m_size.w, m_size.h ); + + BitBlt( m_bitmap_dc, + 0, + 0, + m_size.w, + m_size.h, + m_window_dc, + 0, + 0, + SRCCOPY ); + } + else { + Updates copy( 32 ); + + for (unsigned int i=0; isize(); i++) { + copy.addRegion( DFBRegion(copy_rects->at(i)) ); + } + + vector rects; + + copy.GetRectangles( rects ); + + + for (unsigned int i=0; i diff_rects; + + for (unsigned int i=0; isize(); i++) { + if (diffRect( copy_rects->at(i) )) { + diff_rects.push_back( copy_rects->at(i) ); + } + } + + /* + * (3) Copy from bitmap to bitmap2 + */ + pthread_mutex_lock( &m_lock ); + + for (unsigned int i=0; i EXIT!\n" ); diff --git a/src/classes.h b/src/classes.h index 8f81e90..2d8228b 100644 --- a/src/classes.h +++ b/src/classes.h @@ -28,6 +28,9 @@ extern "C" { #include #include + + +#include } -- cgit