diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 4bc712eda..88386e8a3 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -70,10 +70,10 @@ if(XEXT_FOUND) endif() find_suggested_package(Xcursor) -if(Xcursor_FOUND) +if(XCURSOR_FOUND) add_definitions(-DWITH_XCURSOR) - include_directories(${Xcursor_INCLUDE_DIRS}) - target_link_libraries(xfreerdp ${Xcursor_LIBRARIES}) + include_directories(${XCURSOR_INCLUDE_DIRS}) + target_link_libraries(xfreerdp ${XCURSOR_LIBRARIES}) endif() find_suggested_package(Xv) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index e05db6abc..e0ebab99d 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "xf_gdi.h" diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 633c05630..53499504c 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -20,6 +20,10 @@ #include #include +#ifdef WITH_XCURSOR +#include +#endif + #ifdef WITH_XINERAMA #include #endif @@ -37,9 +41,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -224,6 +230,76 @@ void xf_hw_desktop_resize(rdpUpdate* update) } } +void xf_pointer_position(rdpUpdate* update, POINTER_POSITION_UPDATE* pointer_position) +{ + +} + +void xf_pointer_system(rdpUpdate* update, POINTER_SYSTEM_UPDATE* pointer_system) +{ + +} + +void xf_pointer_color(rdpUpdate* update, POINTER_COLOR_UPDATE* pointer_color) +{ + +} + +void xf_pointer_new(rdpUpdate* update, POINTER_NEW_UPDATE* pointer_new) +{ + xfInfo* xfi; + Cursor cursor; + XcursorImage ci; + POINTER_COLOR_UPDATE* ptrAttr; + + xfi = GET_XFI(update); + ptrAttr = &pointer_new->colorPtrAttr; + + memset(&ci, 0, sizeof(ci)); + ci.version = XCURSOR_IMAGE_VERSION; + ci.size = sizeof(ci); + ci.width = ptrAttr->width; + ci.height = ptrAttr->height; + ci.xhot = ptrAttr->xPos; + ci.yhot = ptrAttr->yPos; + ci.pixels = (XcursorPixel*) malloc(ci.width * ci.height * 4); + memset(ci.pixels, 0, ci.width * ci.height * 4); + + if ((ptrAttr->andMaskData != 0) && (ptrAttr->xorMaskData != 0)) + { + freerdp_alpha_cursor_convert((uint8*) (ci.pixels), ptrAttr->xorMaskData, ptrAttr->andMaskData, + ptrAttr->width, ptrAttr->height, pointer_new->xorBpp, xfi->clrconv); + } + + if (pointer_new->xorBpp > 24) + { + printf("xorBpp:%d\n", pointer_new->xorBpp); + } + + cursor = XcursorImageLoadCursor(xfi->display, &ci); + xfree(ci.pixels); + + pointer_put(xfi->cache->pointer, ptrAttr->cacheIndex, NULL, (void*) cursor); + + if (xfi->remote_app != True) + XDefineCursor(xfi->display, xfi->window->handle, cursor); +} + +void xf_pointer_cached(rdpUpdate* update, POINTER_CACHED_UPDATE* pointer_cached) +{ + xfInfo* xfi; + void* extra; + Cursor cursor; + + xfi = GET_XFI(update); + + pointer_get(xfi->cache->pointer, pointer_cached->cacheIndex, &extra); + cursor = (Cursor) extra; + + if (xfi->remote_app != True) + XDefineCursor(xfi->display, xfi->window->handle, cursor); +} + boolean xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) { xfInfo* xfi = GET_XFI(instance); @@ -549,6 +625,12 @@ boolean xf_post_connect(freerdp* instance) instance->update->DesktopResize = xf_hw_desktop_resize; } + instance->update->PointerPosition = xf_pointer_position; + instance->update->PointerSystem = xf_pointer_system; + instance->update->PointerColor = xf_pointer_color; + instance->update->PointerNew = xf_pointer_new; + instance->update->PointerCached = xf_pointer_cached; + xfi->rail = rail_new(instance->settings); instance->update->rail = (void*) xfi->rail; rail_register_update_callbacks(xfi->rail, instance->update); diff --git a/cmake/FindXcursor.cmake b/cmake/FindXcursor.cmake index c6afd1cf9..0a438225e 100644 --- a/cmake/FindXcursor.cmake +++ b/cmake/FindXcursor.cmake @@ -2,12 +2,12 @@ # Find the Xcursor libraries # # This module defines the following variables: -# Xcursor_FOUND - True if Xcursor_INCLUDE_DIR & Xcursor_LIBRARY are found -# Xcursor_LIBRARIES - Set when Xcursor_LIBRARY is found -# Xcursor_INCLUDE_DIRS - Set when Xcursor_INCLUDE_DIR is found +# XCURSOR_FOUND - True if XCURSOR_INCLUDE_DIR & XCURSOR_LIBRARY are found +# XCURSOR_LIBRARIES - Set when XCURSOR_LIBRARY is found +# XCURSOR_INCLUDE_DIRS - Set when XCURSOR_INCLUDE_DIR is found # -# Xcursor_INCLUDE_DIR - where to find Xcursor.h, etc. -# Xcursor_LIBRARY - the Xcursor library +# XCURSOR_INCLUDE_DIR - where to find Xcursor.h, etc. +# XCURSOR_LIBRARY - the Xcursor library # #============================================================================= @@ -28,22 +28,22 @@ # limitations under the License. #============================================================================= -find_path(Xcursor_INCLUDE_DIR NAMES Xcursor.h +find_path(XCURSOR_INCLUDE_DIR NAMES Xcursor.h PATH_SUFFIXES X11/Xcursor DOC "The Xcursor include directory" ) -find_library(Xcursor_LIBRARY NAMES Xcursor +find_library(XCURSOR_LIBRARY NAMES Xcursor DOC "The Xcursor library" ) include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xcursor DEFAULT_MSG Xcursor_LIBRARY Xcursor_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(XCURSOR DEFAULT_MSG XCURSOR_LIBRARY XCURSOR_INCLUDE_DIR) -if(Xcursor_FOUND) - set( Xcursor_LIBRARIES ${Xcursor_LIBRARY} ) - set( Xcursor_INCLUDE_DIRS ${Xcursor_INCLUDE_DIR} ) +if(XCURSOR_FOUND) + set( XCURSOR_LIBRARIES ${XCURSOR_LIBRARY} ) + set( XCURSOR_INCLUDE_DIRS ${XCURSOR_INCLUDE_DIR} ) endif() -mark_as_advanced(Xcursor_INCLUDE_DIR Xcursor_LIBRARY) +mark_as_advanced(XCURSOR_INCLUDE_DIR XCURSOR_LIBRARY) diff --git a/include/freerdp/common/color.h b/include/freerdp/common/color.h index 1c72903ea..8e199d5a5 100644 --- a/include/freerdp/common/color.h +++ b/include/freerdp/common/color.h @@ -242,6 +242,7 @@ FREERDP_API uint8* freerdp_glyph_convert(int width, int height, uint8* data); FREERDP_API uint8* freerdp_image_invert(uint8* srcData, uint8* dstData, int width, int height, int bpp); FREERDP_API uint8* freerdp_icon_convert(uint8* srcData, uint8* dstData, uint8* mask, int width, int height, int bpp, HCLRCONV clrconv); FREERDP_API uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int srcBpp, int dstBpp, uint32 bgcolor, uint32 fgcolor, HCLRCONV clrconv); +FREERDP_API void freerdp_alpha_cursor_convert(uint8* alphaData, uint8* xorMask, uint8* andMask, int width, int height, int bpp, HCLRCONV clrconv); #ifdef __cplusplus } diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 0d87dace4..85d531da1 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -104,7 +104,8 @@ typedef struct _POINTER_SYSTEM_UPDATE POINTER_SYSTEM_UPDATE; struct _POINTER_COLOR_UPDATE { uint16 cacheIndex; - uint32 hotSpot; + uint16 xPos; + uint16 yPos; uint16 width; uint16 height; uint16 lengthAndMask; diff --git a/libfreerdp-cache/pointer.c b/libfreerdp-cache/pointer.c index 95a1821af..cbcaef54c 100644 --- a/libfreerdp-cache/pointer.c +++ b/libfreerdp-cache/pointer.c @@ -35,7 +35,7 @@ void* pointer_get(rdpPointer* pointer, uint16 index, void** extra) entry = pointer->entries[index].entry; if (extra != NULL) - extra = pointer->entries[index].extra; + *extra = pointer->entries[index].extra; return entry; } diff --git a/libfreerdp-common/color.c b/libfreerdp-common/color.c index 2b6d3c086..540b2fe78 100644 --- a/libfreerdp-common/color.c +++ b/libfreerdp-common/color.c @@ -23,6 +23,67 @@ #include #include +int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp) +{ + int start; + int shift; + uint16 *src16; + uint32 *src32; + int red, green, blue; + + switch (bpp) + { + case 1: + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + return (data[start] & (0x80 >> shift)) != 0; + case 8: + return data[y * width + x]; + case 15: + case 16: + src16 = (uint16*) data; + return src16[y * width + x]; + case 24: + data += y * width * 3; + data += x * 3; + red = data[0]; + green = data[1]; + blue = data[2]; + return RGB24(red, green, blue); + case 32: + src32 = (uint32*) data; + return src32[y * width + x]; + default: + break; + } + + return 0; +} + +void freerdp_set_pixel(uint8* data, int x, int y, int width, int height, int bpp, int pixel) +{ + int start; + int shift; + int *dst32; + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + if (pixel) + data[start] = data[start] | (0x80 >> shift); + else + data[start] = data[start] & ~(0x80 >> shift); + } + else if (bpp == 32) + { + dst32 = (int*) data; + dst32[y * width + x] = pixel; + } +} + uint32 freerdp_color_convert_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) { uint8 red = 0; @@ -779,3 +840,39 @@ uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int src return srcData; } + +void freerdp_alpha_cursor_convert(uint8* alphaData, uint8* xorMask, uint8* andMask, int width, int height, int bpp, HCLRCONV clrconv) +{ + int xpixel; + int apixel; + int i, j, jj; + + for (j = 0; j < height; j++) + { + jj = (bpp == 1) ? j : (height - 1) - j; + for (i = 0; i < width; i++) + { + xpixel = freerdp_get_pixel(xorMask, i, jj, width, height, bpp); + xpixel = freerdp_color_convert(xpixel, bpp, 32, clrconv); + apixel = freerdp_get_pixel(andMask, i, jj, width, height, 1); + + if (apixel != 0) + { + if ((xpixel & 0xffffff) == 0xffffff) + { + /* use pattern (not solid black) for xor area */ + xpixel = (i & 1) == (j & 1); + xpixel = xpixel ? 0xffffff : 0; + xpixel |= 0xff000000; + } + else if (xpixel == 0xff000000) + { + xpixel = 0; + } + } + + freerdp_set_pixel(alphaData, i, j, width, height, 32, xpixel); + } + } +} + diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index 033f79fc7..cf9fea414 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -194,7 +194,8 @@ void update_read_pointer_system(STREAM* s, POINTER_SYSTEM_UPDATE* pointer_system void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { stream_read_uint16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */ - stream_read_uint32(s, pointer_color->hotSpot); /* hotSpot (4 bytes) */ + stream_read_uint16(s, pointer_color->xPos); /* xPos (2 bytes) */ + stream_read_uint16(s, pointer_color->yPos); /* yPos (2 bytes) */ stream_read_uint16(s, pointer_color->width); /* width (2 bytes) */ stream_read_uint16(s, pointer_color->height); /* height (2 bytes) */ stream_read_uint16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */