Also looks good, ack.

Regards,

Hans


On 11/23/2010 04:56 PM, Arnon Gilboa wrote:
-currently png&  bmp
-using wspice libs cximage.lib&  png.lib
-jpg&  tiff will follow
---
  vdagent/vdagent.cpp    |  214 ++++++++++++++++++++++++++++++++---------------
  vdagent/vdagent.vcproj |   21 +++--
  2 files changed, 159 insertions(+), 76 deletions(-)

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index c210016..1ebf1e4 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -18,25 +18,41 @@
  #include "vdcommon.h"
  #include "desktop_layout.h"
  #include "display_setting.h"
+#include "ximage.h"
  #include<lmcons.h>
+#include<set>

  #define VD_AGENT_LOG_PATH       TEXT("%svdagent.log")
  #define VD_AGENT_WINCLASS_NAME  TEXT("VDAGENT")
  #define VD_INPUT_INTERVAL_MS    20
  #define VD_TIMER_ID             1
  #define VD_CLIPBOARD_TIMEOUT_MS 10000
+#define VD_CLIPBOARD_FORMAT_MAX_TYPES 16

+//FIXME: extract format/type stuff to win_vdagent_common for use by 
windows\platform.cpp as well
  typedef struct VDClipboardFormat {
      uint32_t format;
-    uint32_t type;
+    uint32_t types[VD_CLIPBOARD_FORMAT_MAX_TYPES];
  } VDClipboardFormat;

  VDClipboardFormat clipboard_formats[] = {
-    {CF_UNICODETEXT, VD_AGENT_CLIPBOARD_UTF8_TEXT},
-    {0, 0}};
+    {CF_UNICODETEXT, {VD_AGENT_CLIPBOARD_UTF8_TEXT, 0}},
+    //FIXME: support more image types
+    {CF_DIB, {VD_AGENT_CLIPBOARD_IMAGE_PNG, VD_AGENT_CLIPBOARD_IMAGE_BMP, 0}},
+};

  #define clipboard_formats_count (sizeof(clipboard_formats) / 
sizeof(clipboard_formats[0]))

+typedef struct ImageType {
+    uint32_t type;
+    DWORD cximage_format;
+} ImageType;
+
+static ImageType image_types[] = {
+    {VD_AGENT_CLIPBOARD_IMAGE_PNG, CXIMAGE_FORMAT_PNG},
+    {VD_AGENT_CLIPBOARD_IMAGE_BMP, CXIMAGE_FORMAT_BMP},
+};
+
  class VDAgent {
  public:
      static VDAgent* get();
@@ -61,13 +77,15 @@ private:
      void on_clipboard_release();
      DWORD get_buttons_change(DWORD last_buttons_state, DWORD 
new_buttons_state,
                               DWORD mask, DWORD down_flag, DWORD up_flag);
+    static HGLOBAL utf8_alloc(LPCSTR data, int size);
      static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam, 
LPARAM lparam);
      static VOID CALLBACK read_completion(DWORD err, DWORD bytes, LPOVERLAPPED 
overlap);
      static VOID CALLBACK write_completion(DWORD err, DWORD bytes, 
LPOVERLAPPED overlap);
      static DWORD WINAPI event_thread_proc(LPVOID param);
      static void dispatch_message(VDAgentMessage* msg, uint32_t port);
-    static uint32_t get_clipboard_format(uint32_t type);
-    static uint32_t get_clipboard_type(uint32_t format);
+    uint32_t get_clipboard_format(uint32_t type);
+    uint32_t get_clipboard_type(uint32_t format);
+    DWORD get_cximage_format(uint32_t type);
      enum { owner_none, owner_guest, owner_client };
      void set_clipboard_owner(int new_owner);
      uint8_t* write_lock(DWORD bytes = 0);
@@ -113,6 +131,8 @@ private:
      uint32_t *_client_caps;
      uint32_t _client_caps_size;

+    std::set<uint32_t>  _grab_types;
+
      VDLog* _log;
  };

@@ -162,6 +182,7 @@ VDAgent::VDAgent()
      ZeroMemory(&_input, sizeof(INPUT));
      ZeroMemory(&_pipe_state, sizeof(VDPipeState));
      MUTEX_INIT(_write_mutex);
+
      _singleton = this;
  }

@@ -498,10 +519,7 @@ bool VDAgent::handle_mon_config(VDAgentMonitorsConfig* 
mon_config, uint32_t port

  bool VDAgent::handle_clipboard(VDAgentClipboard* clipboard, uint32_t size)
  {
-    HGLOBAL clip_data;
-    LPVOID clip_buf;
-    int clip_size;
-    int clip_len;
+    HANDLE clip_data;
      UINT format;
      bool ret = false;

@@ -514,40 +532,22 @@ bool VDAgent::handle_clipboard(VDAgentClipboard* 
clipboard, uint32_t size)
          SetEvent(_clipboard_event);
          return false;
      }
-    // Get the required clipboard size
      switch (clipboard->type) {
      case VD_AGENT_CLIPBOARD_UTF8_TEXT:
-        // Received utf8 string is not null-terminated
-        if (!(clip_len = MultiByteToWideChar(CP_UTF8, 0, 
(LPCSTR)clipboard->data, size, NULL, 0))) {
-            return false;
-        }
-        clip_len++;
-        clip_size = clip_len * sizeof(WCHAR);
+        clip_data = utf8_alloc((LPCSTR)clipboard->data, size);
+        break;
+    case VD_AGENT_CLIPBOARD_IMAGE_PNG:
+    case VD_AGENT_CLIPBOARD_IMAGE_BMP: {
+        DWORD cximage_format = get_cximage_format(clipboard->type);
+        ASSERT(cximage_format);
+        CxImage image(clipboard->data, size, cximage_format);
+        clip_data = image.CopyToHandle();
          break;
+    }
      default:
          vd_printf("Unsupported clipboard type %u", clipboard->type);
          return true;
      }
-    // Allocate and lock clipboard memory
-    if (!(clip_data = GlobalAlloc(GMEM_DDESHARE, clip_size))) {
-        return false;
-    }
-    if (!(clip_buf = GlobalLock(clip_data))) {
-        GlobalFree(clip_data);
-        return false;
-    }
-    // Translate data and set clipboard content
-    switch (clipboard->type) {
-    case VD_AGENT_CLIPBOARD_UTF8_TEXT:
-        ret = !!MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)clipboard->data, size, 
(LPWSTR)clip_buf,
-                                    clip_len);
-        ((LPWSTR)clip_buf)[clip_len - 1] = L'\0';
-        break;
-    }
-    GlobalUnlock(clip_data);
-    if (!ret) {
-        return false;
-    }
      format = get_clipboard_format(clipboard->type);
      if (SetClipboardData(format, clip_data)) {
          SetEvent(_clipboard_event);
@@ -563,6 +563,36 @@ bool VDAgent::handle_clipboard(VDAgentClipboard* 
clipboard, uint32_t size)
      return ret;
  }

+HGLOBAL VDAgent::utf8_alloc(LPCSTR data, int size)
+{
+    HGLOBAL handle;
+    LPVOID buf;
+    int len;
+
+    // Received utf8 string is not null-terminated
+    if (!(len = MultiByteToWideChar(CP_UTF8, 0, data, size, NULL, 0))) {
+        return NULL;
+    }
+    len++;
+    // Allocate and lock clipboard memory
+    if (!(handle = GlobalAlloc(GMEM_DDESHARE, len * sizeof(WCHAR)))) {
+        return NULL;
+    }
+    if (!(buf = GlobalLock(handle))) {
+        GlobalFree(handle);
+        return NULL;
+    }
+    // Translate data and set clipboard content
+    if (!(MultiByteToWideChar(CP_UTF8, 0, data, size, (LPWSTR)buf, len))) {
+        GlobalUnlock(handle);
+        GlobalFree(handle);
+        return NULL;
+    }
+    ((LPWSTR)buf)[len - 1] = L'\0';
+    GlobalUnlock(handle);
+    return handle;
+}
+
  void VDAgent::set_display_depth(uint32_t depth)
  {
      size_t display_count;
@@ -798,16 +828,18 @@ bool VDAgent::write_message(uint32_t type, uint32_t size 
= 0, void* data = NULL)

  void VDAgent::on_clipboard_grab()
  {
-    uint32_t* types = new uint32_t[clipboard_formats_count];
+    uint32_t* types = new uint32_t[clipboard_formats_count * 
VD_CLIPBOARD_FORMAT_MAX_TYPES];
      int count = 0;

      if (!VD_AGENT_HAS_CAPABILITY(_client_caps, _client_caps_size,
                                   VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) {
          return;
-    }
-    for (VDClipboardFormat* iter = clipboard_formats; iter->format; iter++) {
-        if (IsClipboardFormatAvailable(iter->format)) {
-            types[count++] = iter->type;
+    }
+    for (int i = 0; i<  clipboard_formats_count; i++) {
+        if (IsClipboardFormatAvailable(clipboard_formats[i].format)) {
+            for (uint32_t* ptype = clipboard_formats[i].types; *ptype; 
ptype++) {
+                types[count++] = *ptype;
+            }
          }
      }
      if (count) {
@@ -865,14 +897,14 @@ void VDAgent::on_clipboard_release()

  bool VDAgent::handle_clipboard_grab(VDAgentClipboardGrab* clipboard_grab, 
uint32_t size)
  {
-    bool has_supported_type = false;
-    uint32_t format;
+    std::set<uint32_t>  grab_formats;

+    _grab_types.clear();
      for (uint32_t i = 0; i<  size / sizeof(clipboard_grab->types[0]); i++) {
-        format = get_clipboard_format(clipboard_grab->types[i]);
+        vd_printf("grab %u", clipboard_grab->types[i]);
+        uint32_t format = get_clipboard_format(clipboard_grab->types[i]);
          //On first supported type, open and empty the clipboard
-        if (format&&  !has_supported_type) {
-            has_supported_type = true;
+        if (format&&  grab_formats.empty()) {
              if (!OpenClipboard(_hwnd)) {
                  return false;
              }
@@ -880,10 +912,13 @@ bool VDAgent::handle_clipboard_grab(VDAgentClipboardGrab* 
clipboard_grab, uint32
          }
          //For all supported type set delayed rendering
          if (format) {
-            SetClipboardData(format, NULL);
+            _grab_types.insert(clipboard_grab->types[i]);
+            if (grab_formats.insert(format).second) {
+                SetClipboardData(format, NULL);
+            }
          }
      }
-    if (!has_supported_type) {
+    if (grab_formats.empty()) {
          vd_printf("No supported clipboard types in client grab");
          return true;
      }
@@ -898,9 +933,10 @@ bool 
VDAgent::handle_clipboard_request(VDAgentClipboardRequest* clipboard_reques
  {
      UINT format;
      HANDLE clip_data;
-    LPVOID clip_buf;
-    int clip_size;
+    uint8_t* new_data = NULL;
+    long new_size;
      size_t len;
+    CxImage image;

      if (_clipboard_owner != owner_guest) {
          vd_printf("Received clipboard request from client while clipboard is not 
owned by guest");
@@ -917,40 +953,60 @@ bool 
VDAgent::handle_clipboard_request(VDAgentClipboardRequest* clipboard_reques
      if (!IsClipboardFormatAvailable(format) || !OpenClipboard(_hwnd)) {
          return false;
      }
-    if (!(clip_data = GetClipboardData(format)) || !(clip_buf = 
GlobalLock(clip_data))) {
+    if (!(clip_data = GetClipboardData(format))) {
          CloseClipboard();
          return false;
      }
      switch (clipboard_request->type) {
      case VD_AGENT_CLIPBOARD_UTF8_TEXT:
-        len = wcslen((wchar_t*)clip_buf);
-        clip_size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)clip_buf, 
(int)len, NULL, 0, NULL, NULL);
+        if (!(new_data = (uint8_t*)GlobalLock(clip_data))) {
+            break;
+        }
+        len = wcslen((LPCWSTR)new_data);
+        new_size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)new_data, 
(int)len, NULL, 0, NULL, NULL);
+        break;
+    case VD_AGENT_CLIPBOARD_IMAGE_PNG:
+    case VD_AGENT_CLIPBOARD_IMAGE_BMP: {
+        DWORD cximage_format = get_cximage_format(clipboard_request->type);
+        ASSERT(cximage_format);
+        if (!image.CreateFromHANDLE(clip_data)) {
+            vd_printf("Image create from handle failed");
+            break;
+        }
+        if (!image.Encode(new_data, new_size, cximage_format)) {
+            vd_printf("Image encode to type %u failed", 
clipboard_request->type);
+            break;
+        }
+        vd_printf("Image encoded to %u bytes", new_size);
          break;
      }
-
-    if (!clip_size) {
-        GlobalUnlock(clip_data);
+    }
+    if (!new_size) {
          CloseClipboard();
          return false;
      }
      _out_msg_pos = 0;
-    _out_msg_size = sizeof(VDAgentMessage) + sizeof(VDAgentClipboard) + 
clip_size;
+    _out_msg_size = sizeof(VDAgentMessage) + sizeof(VDAgentClipboard) + 
new_size;
      _out_msg = (VDAgentMessage*)new uint8_t[_out_msg_size];
      _out_msg->protocol = VD_AGENT_PROTOCOL;
      _out_msg->type = VD_AGENT_CLIPBOARD;
      _out_msg->opaque = 0;
-    _out_msg->size = (uint32_t)(sizeof(VDAgentClipboard) + clip_size);
+    _out_msg->size = (uint32_t)(sizeof(VDAgentClipboard) + new_size);
      VDAgentClipboard* clipboard = (VDAgentClipboard*)_out_msg->data;
      clipboard->type = clipboard_request->type;

      switch (clipboard_request->type) {
      case VD_AGENT_CLIPBOARD_UTF8_TEXT:
-        WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)clip_buf, (int)len, 
(LPSTR)clipboard->data,
-                            clip_size, NULL, NULL);
+        WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)new_data, (int)len, 
(LPSTR)clipboard->data,
+                            new_size, NULL, NULL);
+        GlobalUnlock(clip_data);
+        break;
+    case VD_AGENT_CLIPBOARD_IMAGE_PNG:
+    case VD_AGENT_CLIPBOARD_IMAGE_BMP:
+        memcpy(clipboard->data, new_data, new_size);
+        image.FreeMemory(new_data);
          break;
      }
-
-    GlobalUnlock(clip_data);
      CloseClipboard();
      write_clipboard();
      return true;
@@ -968,9 +1024,11 @@ void VDAgent::handle_clipboard_release()

  uint32_t VDAgent::get_clipboard_format(uint32_t type)
  {
-    for (VDClipboardFormat* iter = clipboard_formats; iter->format&&  
iter->type; iter++) {
-        if (iter->type == type) {
-            return iter->format;
+    for (int i = 0; i<  clipboard_formats_count; i++) {
+        for (uint32_t* ptype = clipboard_formats[i].types; *ptype; ptype++) {
+            if (*ptype == type) {
+                return clipboard_formats[i].format;
+            }
          }
      }
      return 0;
@@ -978,9 +1036,29 @@ uint32_t VDAgent::get_clipboard_format(uint32_t type)

  uint32_t VDAgent::get_clipboard_type(uint32_t format)
  {
-    for (VDClipboardFormat* iter = clipboard_formats; iter->format&&  
iter->type; iter++) {
-        if (iter->format == format) {
-            return iter->type;
+    uint32_t* types = NULL;
+
+    for (int i = 0; i<  clipboard_formats_count&&  !types; i++) {
+        if (clipboard_formats[i].format == format) {
+            types = clipboard_formats[i].types;
+        }
+    }
+    if (!types) {
+        return 0;
+    }
+    for (uint32_t* ptype = types; *ptype; ptype++) {
+        if (_grab_types.find(*ptype) != _grab_types.end()) {
+            return *ptype;
+        }
+    }
+    return 0;
+}
+
+DWORD VDAgent::get_cximage_format(uint32_t type)
+{
+    for (int i = 0; i<  sizeof(image_types) / sizeof(image_types[0]); i++) {
+        if (image_types[i].type == type) {
+            return image_types[i].cximage_format;
          }
      }
      return 0;
diff --git a/vdagent/vdagent.vcproj b/vdagent/vdagent.vcproj
index 0453c12..ee60f42 100644
--- a/vdagent/vdagent.vcproj
+++ b/vdagent/vdagent.vcproj
@@ -44,7 +44,7 @@
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               
AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+                               
AdditionalIncludeDirectories="..\common;&quot;$(SPICE_COMMON_DIR)&quot;;&quot;$(SPICE_LIBS)\include\CxImage&quot;"
                                
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
                                MinimalRebuild="true"
                                BasicRuntimeChecks="3"
@@ -65,8 +65,9 @@
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="Version.lib"
+                               AdditionalDependencies="Version.lib zlibwapiD.lib 
png_d.lib cximage_d.lib"
                                LinkIncremental="2"
+                               
AdditionalLibraryDirectories="&quot;$(SPICE_LIBS)\lib&quot;"
                                GenerateDebugInformation="true"
                                SubSystem="2"
                                RandomizedBaseAddress="1"
@@ -121,7 +122,7 @@
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               
AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+                               
AdditionalIncludeDirectories="..\common;&quot;$(SPICE_COMMON_DIR)&quot;;&quot;$(SPICE_LIBS)\include\CxImage&quot;"
                                
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
                                MinimalRebuild="true"
                                BasicRuntimeChecks="3"
@@ -142,8 +143,10 @@
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="Version.lib"
+                               AdditionalDependencies="Version.lib zlibwapiD.lib 
png_d.lib cximage_d.lib"
                                LinkIncremental="2"
+                               
AdditionalLibraryDirectories="&quot;$(SPICE_LIBS)\lib64&quot;"
+                               IgnoreDefaultLibraryNames=""
                                GenerateDebugInformation="true"
                                SubSystem="2"
                                RandomizedBaseAddress="1"
@@ -197,7 +200,7 @@
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               
AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+                               
AdditionalIncludeDirectories="..\common;&quot;$(SPICE_COMMON_DIR)&quot;;&quot;$(SPICE_LIBS)\include\CxImage&quot;"
                                AdditionalUsingDirectories=""
                                
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
                                RuntimeLibrary="0"
@@ -217,8 +220,9 @@
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="Version.lib"
+                               AdditionalDependencies="Version.lib zlibwapi.lib 
png.lib cximage.lib"
                                LinkIncremental="1"
+                               
AdditionalLibraryDirectories="&quot;$(SPICE_LIBS)\lib&quot;"
                                GenerateDebugInformation="true"
                                SubSystem="2"
                                OptimizeReferences="2"
@@ -275,7 +279,7 @@
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               
AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+                               
AdditionalIncludeDirectories="..\common;&quot;$(SPICE_COMMON_DIR)&quot;;&quot;$(SPICE_LIBS)\include\CxImage&quot;"
                                AdditionalUsingDirectories=""
                                
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
                                RuntimeLibrary="0"
@@ -295,8 +299,9 @@
                        />
                        <Tool
                                Name="VCLinkerTool"
-                               AdditionalDependencies="Version.lib"
+                               AdditionalDependencies="Version.lib zlibwapi.lib 
png.lib cximage.lib"
                                LinkIncremental="1"
+                               
AdditionalLibraryDirectories="&quot;$(SPICE_LIBS)\lib64&quot;"
                                GenerateDebugInformation="true"
                                SubSystem="2"
                                OptimizeReferences="2"
_______________________________________________
Spice-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/spice-devel

Reply via email to