diff options
author | Arnon Gilboa <agilboa@redhat.com> | 2010-11-24 10:30:40 +0200 |
---|---|---|
committer | Arnon Gilboa <agilboa@redhat.com> | 2010-11-24 10:30:40 +0200 |
commit | dd31c0cbfd76a3154d6b6bd7ba47f30aec175815 (patch) | |
tree | e62222fc34af0810a020302ceb6a24ab177a50e5 /client/windows | |
parent | 32d94860910aabc7212e4059bf095d0bcd99cc1c (diff) | |
download | spice-dd31c0cbfd76a3154d6b6bd7ba47f30aec175815.tar.gz spice-dd31c0cbfd76a3154d6b6bd7ba47f30aec175815.tar.xz spice-dd31c0cbfd76a3154d6b6bd7ba47f30aec175815.zip |
spicec-win: add image copy-paste support
-currently png & bmp
-using wspice libs cximage.lib & png.lib
-jpg & tiff will follow
Diffstat (limited to 'client/windows')
-rw-r--r-- | client/windows/platform.cpp | 204 | ||||
-rw-r--r-- | client/windows/redc.vcproj | 16 |
2 files changed, 151 insertions, 69 deletions
diff --git a/client/windows/platform.cpp b/client/windows/platform.cpp index 1c309b37..16760003 100644 --- a/client/windows/platform.cpp +++ b/client/windows/platform.cpp @@ -32,6 +32,7 @@ #include "playback.h" #include "cursor.h" #include "named_pipe.h" +#include "ximage.h" #include <spice/vd_agent.h> int gdi_handlers = 0; @@ -66,17 +67,33 @@ static HANDLE clipboard_event = NULL; static const int CLIPBOARD_TIMEOUT_MS = 10000; +static const int CLIPBOARD_FORMAT_MAX_TYPES = 16; + typedef struct ClipboardFormat { uint32_t format; - uint32_t type; + uint32_t types[CLIPBOARD_FORMAT_MAX_TYPES]; } ClipboardFormat; static ClipboardFormat 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}, +}; + +static std::set<uint32_t> grab_types;
+ static const unsigned long MODAL_LOOP_TIMER_ID = 1; static const int MODAL_LOOP_DEFAULT_TIMEOUT = 100; static bool modal_loop_active = false; @@ -89,27 +106,45 @@ void Platform::send_quit_request() } static uint32_t get_clipboard_type(uint32_t format) { - ClipboardFormat* iter; + uint32_t* types = NULL; - for (iter = clipboard_formats; iter->type && iter->format != format; iter++); - return iter->type; + for (int i = 0; i < clipboard_formats_count && !types; i++) { + if (clipboard_formats[i].format == format) { + types = clipboard_formats[i].types; + } + } + if (!types) { + return VD_AGENT_CLIPBOARD_NONE; + } + for (uint32_t* ptype = types; *ptype; ptype++) { + if (grab_types.find(*ptype) != grab_types.end()) { + return *ptype; + } + } + return VD_AGENT_CLIPBOARD_NONE; } static uint32_t get_clipboard_format(uint32_t type) { - ClipboardFormat* iter; - - for (iter = clipboard_formats; iter->format && iter->type != type; iter++); - 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; } static int get_available_clipboard_types(uint32_t** types) { int count = 0; - *types = new uint32_t[clipboard_formats_count]; - for (ClipboardFormat* iter = clipboard_formats; iter->format; iter++) { - if (IsClipboardFormatAvailable(iter->format)) { - *types[count++] = iter->type; + *types = new uint32_t[clipboard_formats_count * CLIPBOARD_FORMAT_MAX_TYPES]; + 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) { @@ -119,6 +154,16 @@ static int get_available_clipboard_types(uint32_t** types) return count; } +static DWORD 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; +} + static LRESULT CALLBACK PlatformWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { @@ -881,14 +926,13 @@ void Platform::set_clipboard_owner(int new_owner) bool Platform::on_clipboard_grab(uint32_t *types, uint32_t type_count) { - bool has_supported_type = false; - uint32_t format; + std::set<uint32_t> grab_formats; + grab_types.clear(); for (uint32_t i = 0; i < type_count; i++) { - format = get_clipboard_format(types[i]); + uint32_t format = get_clipboard_format(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(platform_win)) { return false; } @@ -896,10 +940,13 @@ bool Platform::on_clipboard_grab(uint32_t *types, uint32_t type_count) } //For all supported type set delayed rendering if (format) { - SetClipboardData(format, NULL); + grab_types.insert(types[i]); + if (grab_formats.insert(format).second) { + SetClipboardData(format, NULL); + } } } - if (!has_supported_type) { + if (grab_formats.empty()) { LOG_INFO("No supported clipboard types in client grab"); return false; } @@ -914,12 +961,39 @@ void Platform::set_clipboard_listener(ClipboardListener* listener) clipboard_listener = listener ? listener : &default_clipboard_listener; } +static HGLOBAL 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; +} + bool Platform::on_clipboard_notify(uint32_t type, const uint8_t* data, int32_t size) { - HGLOBAL clip_data; - LPVOID clip_buf; - int clip_size; - int clip_len; + HANDLE clip_data; UINT format; bool ret = false; @@ -927,41 +1001,23 @@ bool Platform::on_clipboard_notify(uint32_t type, const uint8_t* data, int32_t s SetEvent(clipboard_event); return true; } - // Get the required clipboard size switch (type) { case VD_AGENT_CLIPBOARD_UTF8_TEXT: - // Received utf8 string is not null-terminated - if (!(clip_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)data, size, NULL, 0))) { - return false; - } - clip_len++; - clip_size = clip_len * sizeof(WCHAR); + clip_data = utf8_alloc((LPCSTR)data, size); + break; + case VD_AGENT_CLIPBOARD_IMAGE_PNG: + case VD_AGENT_CLIPBOARD_IMAGE_BMP: { + DWORD cximage_format = get_cximage_format(type); + ASSERT(cximage_format); + CxImage image((BYTE *)data, size, cximage_format); + clip_data = image.CopyToHandle(); break; + } default: LOG_INFO("Unsupported clipboard type %u", 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 (type) { - case VD_AGENT_CLIPBOARD_UTF8_TEXT: - ret = !!MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)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(type); if (SetClipboardData(format, clip_data)) { SetEvent(clipboard_event); @@ -981,38 +1037,64 @@ bool Platform::on_clipboard_request(uint32_t type) { UINT format = get_clipboard_format(type); HANDLE clip_data; - LPVOID clip_buf; + LPCWSTR clip_buf; + uint8_t* new_data = NULL; + long new_size; + bool ret = false; if (!format || !IsClipboardFormatAvailable(format) || !OpenClipboard(platform_win)) { return false; } - if (!(clip_data = GetClipboardData(format)) || !(clip_buf = GlobalLock(clip_data))) { + if (!(clip_data = GetClipboardData(format))) { CloseClipboard(); return false; } switch (type) { case VD_AGENT_CLIPBOARD_UTF8_TEXT: { + if (!(clip_buf = (LPCWSTR)GlobalLock(clip_data))) { + break; + } size_t len = wcslen((wchar_t*)clip_buf); - int utf8_size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)clip_buf, len, NULL, 0, NULL, NULL); - if (!utf8_size) { + new_size = WideCharToMultiByte(CP_UTF8, 0, clip_buf, len, NULL, 0, NULL, NULL); + if (!new_size) { + GlobalUnlock(clip_data); break; } - uint8_t* utf8_data = new uint8_t[utf8_size]; - if (WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)clip_buf, len, (LPSTR)utf8_data, utf8_size, + new_data = new uint8_t[new_size]; + if (WideCharToMultiByte(CP_UTF8, 0, clip_buf, len, (LPSTR)new_data, new_size, NULL, NULL)) { - clipboard_listener->on_clipboard_notify(type, utf8_data, utf8_size); + clipboard_listener->on_clipboard_notify(type, new_data, new_size); ret = true; } - delete[] (uint8_t *)utf8_data; + delete[] (uint8_t *)new_data; + GlobalUnlock(clip_data); + break; + } + case VD_AGENT_CLIPBOARD_IMAGE_PNG: + case VD_AGENT_CLIPBOARD_IMAGE_BMP: { + DWORD cximage_format = get_cximage_format(type); + ASSERT(cximage_format); + CxImage image;
+ if (!image.CreateFromHANDLE(clip_data)) {
+ LOG_INFO("Image create from handle failed");
+ break;
+ }
+ if (!image.Encode(new_data, new_size, cximage_format)) {
+ LOG_INFO("Image encode to type %u failed", type);
+ break;
+ }
+ LOG_INFO("Image encoded to %u bytes", new_size);
+ clipboard_listener->on_clipboard_notify(type, new_data, new_size); + image.FreeMemory(new_data); + ret = true; break; } default: LOG_INFO("Unsupported clipboard type %u", type); } - GlobalUnlock(clip_data); CloseClipboard(); return ret; } diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj index c75adea1..8181334b 100644 --- a/client/windows/redc.vcproj +++ b/client/windows/redc.vcproj @@ -49,7 +49,7 @@ <Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories=".;..;..\..\common;..\..\..\spice-protocol;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2""
+ AdditionalIncludeDirectories=".;..;..\..\common;"..\..\..\spice-protocol";..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2";"$(SPICE_LIBS)\include\CxImage""
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GUI;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
MinimalRebuild="false"
BasicRuntimeChecks="3"
@@ -72,7 +72,7 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="pixman-1D.lib libeay32MTd.lib ssleay32MTd.lib ws2_32.lib msimg32.lib winmm.lib libcelt_0_5_1D.lib pthreadVC2d.lib version.lib CEGUIBase_Static_d.lib CEGUITGAImageCodec_Static_d.lib CEGUIExpatParser_Static_d.lib freetype2312MT_D.lib libexpatMT_D.lib pcre_D.lib CEGUIFalagardWRBase_Static_d.lib libjpeg-static-mt-debug.lib zlibwapiD.lib"
+ AdditionalDependencies="pixman-1D.lib libeay32MTd.lib ssleay32MTd.lib ws2_32.lib msimg32.lib winmm.lib libcelt_0_5_1D.lib pthreadVC2d.lib version.lib CEGUIBase_Static_d.lib CEGUITGAImageCodec_Static_d.lib CEGUIExpatParser_Static_d.lib freetype2312MT_D.lib libexpatMT_D.lib pcre_D.lib CEGUIFalagardWRBase_Static_d.lib libjpeg-static-mt-debug.lib zlibwapiD.lib png_d.lib cximage_d.lib"
OutputFile="$(OutDir)\spicec.exe"
LinkIncremental="2"
AdditionalLibraryDirectories=""$(SPICE_LIBS)\lib""
@@ -137,7 +137,7 @@ <Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories=".;..;..\..\common;..\..\..\spice-protocol;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2""
+ AdditionalIncludeDirectories=".;..;..\..\common;"..\..\..\spice-protocol";..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2";"$(SPICE_LIBS)\include\CxImage""
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GUI;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
MinimalRebuild="false"
BasicRuntimeChecks="3"
@@ -160,7 +160,7 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="pixman-1D.lib libeay32MTd.lib ssleay32MTd.lib ws2_32.lib msimg32.lib winmm.lib zlibwapiD.lib version.lib pthreadVC2D.lib libjpeg-static-mt-debug.lib libcelt_0_5_1D.lib CEGUIBase_Static_d.lib CEGUIExpatParser_Static_d.lib CEGUIFalagardWRBase_Static_d.lib CEGUITGAImageCodec_Static_d.lib freetype2312MT.lib libexpatMT.lib pcre.lib"
+ AdditionalDependencies="pixman-1D.lib libeay32MTd.lib ssleay32MTd.lib ws2_32.lib msimg32.lib winmm.lib zlibwapiD.lib version.lib pthreadVC2D.lib libjpeg-static-mt-debug.lib libcelt_0_5_1D.lib CEGUIBase_Static_d.lib CEGUIExpatParser_Static_d.lib CEGUIFalagardWRBase_Static_d.lib CEGUITGAImageCodec_Static_d.lib freetype2312MT.lib libexpatMT.lib pcre.lib png_d.lib cximage_d.lib"
OutputFile="$(OutDir)\spicec.exe"
LinkIncremental="2"
AdditionalLibraryDirectories=""$(SPICE_LIBS)\lib64""
@@ -220,7 +220,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=".;..;..\..\..\spice-protocol;..\..\common;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2""
+ AdditionalIncludeDirectories=".;..;"..\..\..\spice-protocol";..\..\common;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2";"$(SPICE_LIBS)\include\CxImage""
PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GUI;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@@ -240,7 +240,7 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="pixman-1.lib libeay32MT.lib ssleay32MT.lib ws2_32.lib msimg32.lib winmm.lib libcelt_0_5_1.lib pthreadVC2.lib version.lib CEGUIBase_Static.lib CEGUITGAImageCodec_Static.lib CEGUIExpatParser_Static.lib freetype2312MT.lib libexpatMT.lib pcre.lib CEGUIFalagardWRBase_Static.lib libjpeg-static-mt.lib zlibwapi.lib"
+ AdditionalDependencies="pixman-1.lib libeay32MT.lib ssleay32MT.lib ws2_32.lib msimg32.lib winmm.lib libcelt_0_5_1.lib pthreadVC2.lib version.lib CEGUIBase_Static.lib CEGUITGAImageCodec_Static.lib CEGUIExpatParser_Static.lib freetype2312MT.lib libexpatMT.lib pcre.lib CEGUIFalagardWRBase_Static.lib libjpeg-static-mt.lib zlibwapi.lib png.lib cximage.lib"
OutputFile="$(OutDir)\spicec.exe"
LinkIncremental="1"
AdditionalLibraryDirectories=""$(SPICE_LIBS)\lib""
@@ -303,7 +303,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=".;..;..\..\..\spice-protocol;..\..\common;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2""
+ AdditionalIncludeDirectories=".;..;"..\..\..\spice-protocol";..\..\common;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2";"$(SPICE_LIBS)\include\CxImage""
PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;USE_GUI;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@@ -323,7 +323,7 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="pixman-1.lib libeay32MT.lib ssleay32MT.lib ws2_32.lib msimg32.lib winmm.lib zlibwapi.lib version.lib pthreadVC2.lib libjpeg-static-mt.lib libcelt_0_5_1.lib CEGUIBase_Static.lib CEGUIExpatParser_Static.lib CEGUIFalagardWRBase_Static.lib CEGUITGAImageCodec_Static.lib freetype2312MT.lib libexpatMT.lib pcre.lib"
+ AdditionalDependencies="pixman-1.lib libeay32MT.lib ssleay32MT.lib ws2_32.lib msimg32.lib winmm.lib zlibwapi.lib version.lib pthreadVC2.lib libjpeg-static-mt.lib libcelt_0_5_1.lib CEGUIBase_Static.lib CEGUIExpatParser_Static.lib CEGUIFalagardWRBase_Static.lib CEGUITGAImageCodec_Static.lib freetype2312MT.lib libexpatMT.lib pcre.lib png.lib cximage.lib"
OutputFile="$(OutDir)\spicec.exe"
LinkIncremental="1"
AdditionalLibraryDirectories=""$(SPICE_LIBS)\lib64""
|