diff --git a/.gitignore b/.gitignore
index 048417b7d..ff66464d9 100755
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,9 @@ external/*
# Documentation
docs/api
client/X11/xfreerdp.1
+client/X11/xfreerdp.1.xml
+client/X11/xfreerdp-channels.1.xml
+client/X11/xfreerdp-examples.1.xml
# Mac OS X
.DS_Store
diff --git a/CMakeLists.txt b/CMakeLists.txt
index edd2e0aa5..a38dd3a19 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -142,7 +142,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
endif()
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
- set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG")
+ set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
@@ -160,10 +160,10 @@ endif()
if(MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gd")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MT")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /O2")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Ob2")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W2")
+ #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MD")
+ #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /O2")
+ #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Ob2")
+ #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W2")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_AMD64_")
else()
@@ -171,6 +171,13 @@ if(MSVC)
endif()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
+
+ if(CMAKE_BUILD_TYPE STREQUAL "Release")
+ else()
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
+ endif()
+
endif()
if(WIN32)
@@ -220,21 +227,24 @@ if(APPLE)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_IOS_EXTERNAL_SSL_PATH})
set_property(GLOBAL PROPERTY XCODE_ATTRIBUTE_SKIP_INSTALL YES)
else()
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
+
+ if(NOT DEFINED CMAKE_OSX_ARCHITECTURES)
+ set(CMAKE_OSX_ARCHITECTURES i386 x86_64)
+ endif()
+
if(IS_DIRECTORY /opt/local/include)
include_directories(/opt/local/include)
link_directories(/opt/local/lib)
endif()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.5")
endif()
+
if(WITH_CLANG)
set(CMAKE_C_COMPILER "clang")
endif()
if (WITH_VERBOSE)
- # Support for automatic reference counting requires non-fragile abi.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v")
-
- # Tell the compiler where to look for the FreeRDP framework
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v")
endif()
endif()
@@ -261,6 +271,7 @@ endif()
if(UNIX OR CYGWIN)
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
+ check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
set(X11_FEATURE_TYPE "RECOMMENDED")
else()
set(X11_FEATURE_TYPE "DISABLED")
@@ -313,6 +324,10 @@ set(NPP_FEATURE_TYPE "OPTIONAL")
set(NPP_FEATURE_PURPOSE "performance")
set(NPP_FEATURE_DESCRIPTION "NVIDIA Performance Primitives library")
+set(JPEG_FEATURE_TYPE "OPTIONAL")
+set(JPEG_FEATURE_PURPOSE "codec")
+set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
+
if(WIN32)
set(X11_FEATURE_TYPE "DISABLED")
set(ZLIB_FEATURE_TYPE "DISABLED")
@@ -329,8 +344,9 @@ if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_FEATURE_TYPE "OPTIONAL")
- set(X11_FEATURE_TYPE "DISABLED")
+ set(X11_FEATURE_TYPE "OPTIONAL")
if(IOS)
+ set(X11_FEATURE_TYPE "DISABLED")
set(ALSA_FEATURE_TYPE "DISABLED")
set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_FEATURE_TYPE "DISABLED")
@@ -353,6 +369,11 @@ endif()
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
+if (${WITH_DIRECTFB})
+ message(WARNING "
+DIRECTFB is orphaned and not maintained see docs/README.directfb for details
+")
+endif()
find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION})
find_feature(OpenSSL ${OPENSSL_FEATURE_TYPE} ${OPENSSL_FEATURE_PURPOSE} ${OPENSSL_FEATURE_DESCRIPTION})
@@ -366,6 +387,8 @@ find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DE
find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION})
find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
+find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
+
if(TARGET_ARCH MATCHES "x86|x64")
if (NOT APPLE)
# Intel Performance Primitives
@@ -394,12 +417,12 @@ set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}")
set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions")
# Include directories
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Configure files
add_definitions("-DHAVE_CONFIG_H")
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
# RPATH configuration
set(CMAKE_SKIP_BUILD_RPATH FALSE)
@@ -424,8 +447,8 @@ if(BUILD_TESTING)
endif()
# WinPR
-set(WINPR_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/winpr/include")
-include_directories(${WINPR_INCLUDE_DIR})
+include_directories("${CMAKE_SOURCE_DIR}/winpr/include")
+include_directories("${CMAKE_BINARY_DIR}/winpr/include")
add_subdirectory(winpr)
@@ -449,7 +472,9 @@ if(WITH_THIRD_PARTY)
endif()
endif()
-add_subdirectory(include)
+if (NOT WITH_WAYK)
+ add_subdirectory(include)
+endif()
add_subdirectory(libfreerdp)
@@ -474,6 +499,8 @@ endif()
SET(CPACK_BINARY_ZIP "ON")
+if(NOT WITH_WAYK)
+
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt")
if(NOT WIN32)
@@ -529,9 +556,12 @@ if(MSVC)
if(MSVC_RUNTIME STREQUAL "dynamic")
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
include(InstallRequiredSystemLibraries)
+
+if(NOT WITH_WAYK)
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT libraries)
+endif()
endif()
set(EXTRA_DATA_DIR "extra/")
@@ -577,3 +607,4 @@ endif()
include(CPack)
+endif()
diff --git a/buildx/client/Mac/cli/Info.plist b/buildx/client/Mac/cli/Info.plist
deleted file mode 100644
index cb6976502..000000000
--- a/buildx/client/Mac/cli/Info.plist
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
-
- CFBundleIconFile
- FreeRDP
- CFBundleIdentifier
- FreeRDP.Mac
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
-
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1
- LSMinimumSystemVersion
-
- NSHumanReadableCopyright
- Copyright © 2012 __MyCompanyName__. All rights reserved.
- NSMainNibFile
- MainMenu
- NSPrincipalClass
- NSApplication
-
-
diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c
index 2d4906ea2..787f208bd 100644
--- a/channels/audin/client/pulse/audin_pulse.c
+++ b/channels/audin/client/pulse/audin_pulse.c
@@ -290,6 +290,17 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length
BYTE* encoded_data;
AudinPulseDevice* pulse = (AudinPulseDevice*) userdata;
+ /* There is a race condition here where we may receive this callback
+ * before the buffer has been set up in the main code. It's probably
+ * possible to fix with additional locking, but it's easier just to
+ * ignore input until the buffer is ready.
+ */
+ if (pulse->buffer == NULL)
+ {
+ /* fprintf(stderr, "%s: ignoring input, pulse buffer not ready.\n", __func__); */
+ return;
+ }
+
pa_stream_peek(stream, &data, &length);
frames = length / pulse->bytes_per_frame;
@@ -373,6 +384,7 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
DEBUG_DVC("");
+ pulse->buffer = NULL;
pulse->receive = receive;
pulse->user_data = user_data;
diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt
index 6aa60777a..fc42466bb 100644
--- a/channels/client/CMakeLists.txt
+++ b/channels/client/CMakeLists.txt
@@ -19,16 +19,16 @@ set(MODULE_NAME "freerdp-channels-client")
set(MODULE_PREFIX "FREERDP_CHANNELS_CLIENT")
set(${MODULE_PREFIX}_SRCS
- tables.c
- tables.h
- addin.c
- addin.h
- init.c
- init.h
- open.c
- open.h
- channels.c
- channels.h)
+ ${CMAKE_CURRENT_BINARY_DIR}/tables.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tables.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/addin.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/addin.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/init.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/init.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/open.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/open.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/channels.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/channels.h)
list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES)
@@ -96,7 +96,7 @@ foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
endforeach()
set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ NULL, NULL, NULL }\n};")
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_SOURCE_DIR}/tables.c)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_BINARY_DIR}/tables.c)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
diff --git a/channels/client/channels.c b/channels/client/channels.c
index a9ea2b0dc..bf886dba4 100644
--- a/channels/client/channels.c
+++ b/channels/client/channels.c
@@ -441,10 +441,14 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c
int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name, void* pInterface)
{
int status = 0;
+ ChannelConnectedEventArgs e;
rdpChannels* channels = (rdpChannels*) context->custom;
freerdp* instance = channels->instance;
- IFCALLRET(instance->OnChannelConnected, status, instance, name, pInterface);
+ EventArgsInit(&e, "freerdp");
+ e.name = name;
+ e.pInterface = pInterface;
+ PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e);
return status;
}
@@ -452,10 +456,14 @@ int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const ch
int freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, const char* name, void* pInterface)
{
int status = 0;
+ ChannelDisconnectedEventArgs e;
rdpChannels* channels = (rdpChannels*) context->custom;
freerdp* instance = channels->instance;
- IFCALLRET(instance->OnChannelDisconnected, status, instance, name, pInterface);
+ EventArgsInit(&e, "freerdp");
+ e.name = name;
+ e.pInterface = pInterface;
+ PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e);
return status;
}
diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c
index 023bbf8e1..426475a64 100644
--- a/channels/cliprdr/client/cliprdr_format.c
+++ b/channels/cliprdr/client/cliprdr_format.c
@@ -87,14 +87,15 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIS
if (!cliprdr->use_long_format_names)
name_length = 32;
- Stream_EnsureRemainingCapacity(body, Stream_Capacity(body) + 4 + name_length);
+ Stream_EnsureRemainingCapacity(body, 4 + name_length);
Stream_Write_UINT32(body, cb_event->formats[i]);
Stream_Write(body, name, name_length);
}
- s = cliprdr_packet_new(CB_FORMAT_LIST, 0, Stream_Capacity(body));
- Stream_Write(s, Stream_Buffer(body), Stream_Capacity(body));
+ Stream_SealLength(body);
+ s = cliprdr_packet_new(CB_FORMAT_LIST, 0, Stream_Length(body));
+ Stream_Write(s, Stream_Buffer(body), Stream_Length(body));
Stream_Free(body, TRUE);
}
@@ -290,16 +291,16 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
{
- /* where is this documented? */
-#if 0
+ /* http://msdn.microsoft.com/en-us/library/hh872154.aspx */
wMessage* event;
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
{
- event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_MONITOR_READY, NULL, NULL);
+ /* In case of an error the clipboard will not be synchronized with the server.
+ * Post this event to restart format negociation and data transfer. */
+ event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event);
}
-#endif
}
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
diff --git a/channels/disp/CMakeLists.txt b/channels/disp/CMakeLists.txt
new file mode 100644
index 000000000..541892d95
--- /dev/null
+++ b/channels/disp/CMakeLists.txt
@@ -0,0 +1,22 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2012 Marc-Andre Moreau
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+define_channel("disp")
+
+if(WITH_CLIENT_CHANNELS)
+ add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
diff --git a/channels/disp/ChannelOptions.cmake b/channels/disp/ChannelOptions.cmake
new file mode 100644
index 000000000..0e254adad
--- /dev/null
+++ b/channels/disp/ChannelOptions.cmake
@@ -0,0 +1,12 @@
+
+set(OPTION_DEFAULT OFF)
+set(OPTION_CLIENT_DEFAULT ON)
+set(OPTION_SERVER_DEFAULT OFF)
+
+define_channel_options(NAME "disp" TYPE "dynamic"
+ DESCRIPTION "Display Update Virtual Channel Extension"
+ SPECIFICATIONS "[MS-RDPEDISP]"
+ DEFAULT ${OPTION_DEFAULT})
+
+define_channel_client_options(${OPTION_CLIENT_DEFAULT})
+define_channel_server_options(${OPTION_SERVER_DEFAULT})
diff --git a/channels/disp/client/CMakeLists.txt b/channels/disp/client/CMakeLists.txt
new file mode 100644
index 000000000..403a15ce4
--- /dev/null
+++ b/channels/disp/client/CMakeLists.txt
@@ -0,0 +1,47 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2013 Marc-Andre Moreau
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+define_channel_client("disp")
+
+set(${MODULE_PREFIX}_SRCS
+ disp_main.c
+ disp_main.h)
+
+include_directories(..)
+
+add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
+
+set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE freerdp
+ MODULES freerdp-common freerdp-utils)
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE winpr
+ MODULES winpr-sysinfo)
+
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+if(NOT STATIC_CHANNELS)
+ install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
+endif()
+
+set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
+
diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c
new file mode 100644
index 000000000..feb971550
--- /dev/null
+++ b/channels/disp/client/disp_main.c
@@ -0,0 +1,341 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Display Update Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "disp_main.h"
+
+struct _DISP_CHANNEL_CALLBACK
+{
+ IWTSVirtualChannelCallback iface;
+
+ IWTSPlugin* plugin;
+ IWTSVirtualChannelManager* channel_mgr;
+ IWTSVirtualChannel* channel;
+};
+typedef struct _DISP_CHANNEL_CALLBACK DISP_CHANNEL_CALLBACK;
+
+struct _DISP_LISTENER_CALLBACK
+{
+ IWTSListenerCallback iface;
+
+ IWTSPlugin* plugin;
+ IWTSVirtualChannelManager* channel_mgr;
+ DISP_CHANNEL_CALLBACK* channel_callback;
+};
+typedef struct _DISP_LISTENER_CALLBACK DISP_LISTENER_CALLBACK;
+
+struct _DISP_PLUGIN
+{
+ IWTSPlugin iface;
+
+ IWTSListener* listener;
+ DISP_LISTENER_CALLBACK* listener_callback;
+
+ UINT32 MaxNumMonitors;
+ UINT32 MaxMonitorWidth;
+ UINT32 MaxMonitorHeight;
+};
+typedef struct _DISP_PLUGIN DISP_PLUGIN;
+
+int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors)
+{
+ int index;
+ int status;
+ wStream* s;
+ UINT32 type;
+ UINT32 length;
+ DISP_PLUGIN* disp;
+ UINT32 MonitorLayoutSize;
+
+ disp = (DISP_PLUGIN*) callback->plugin;
+
+#ifdef DISP_PREVIEW
+ MonitorLayoutSize = 32;
+#else
+ MonitorLayoutSize = 40;
+#endif
+
+ length = 8 + 8 + (NumMonitors * MonitorLayoutSize);
+
+ type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT;
+
+ s = Stream_New(NULL, length);
+
+ Stream_Write_UINT32(s, type); /* Type (4 bytes) */
+ Stream_Write_UINT32(s, length); /* Length (4 bytes) */
+
+ if (NumMonitors > disp->MaxNumMonitors)
+ NumMonitors = disp->MaxNumMonitors;
+
+#ifdef DISP_PREVIEW
+ Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
+#else
+ Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */
+#endif
+
+ Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
+
+ //fprintf(stderr, "NumMonitors: %d\n", NumMonitors);
+
+ for (index = 0; index < NumMonitors; index++)
+ {
+ Monitors[index].Width -= (Monitors[index].Width % 2);
+
+ if (Monitors[index].Width < 200)
+ Monitors[index].Width = 200;
+
+ if (Monitors[index].Width > disp->MaxMonitorWidth)
+ Monitors[index].Width = disp->MaxMonitorWidth;
+
+ if (Monitors[index].Height < 200)
+ Monitors[index].Height = 200;
+
+ if (Monitors[index].Height > disp->MaxMonitorHeight)
+ Monitors[index].Height = disp->MaxMonitorHeight;
+
+ Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].PhysicalHeight); /* PhysicalHeight (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */
+
+#if 0
+ fprintf(stderr, "\t: Flags: 0x%04X\n", Monitors[index].Flags);
+ fprintf(stderr, "\t: Left: %d\n", Monitors[index].Left);
+ fprintf(stderr, "\t: Top: %d\n", Monitors[index].Top);
+ fprintf(stderr, "\t: Width: %d\n", Monitors[index].Width);
+ fprintf(stderr, "\t: Height: %d\n", Monitors[index].Height);
+ fprintf(stderr, "\t: PhysicalWidth: %d\n", Monitors[index].PhysicalWidth);
+ fprintf(stderr, "\t: PhysicalHeight: %d\n", Monitors[index].PhysicalHeight);
+ fprintf(stderr, "\t: Orientation: %d\n", Monitors[index].Orientation);
+#endif
+
+#ifndef DISP_PREVIEW
+ Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */
+#endif
+ }
+
+ Stream_SealLength(s);
+
+ status = callback->channel->Write(callback->channel, Stream_Length(s), Stream_Buffer(s), NULL);
+
+ Stream_Free(s, TRUE);
+
+ return status;
+}
+
+int disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
+{
+ DISP_PLUGIN* disp;
+
+ disp = (DISP_PLUGIN*) callback->plugin;
+
+ Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */
+ Stream_Read_UINT32(s, disp->MaxMonitorWidth); /* MaxMonitorWidth (4 bytes) */
+ Stream_Read_UINT32(s, disp->MaxMonitorHeight); /* MaxMonitorHeight (4 bytes) */
+
+ //fprintf(stderr, "DisplayControlCapsPdu: MaxNumMonitors: %d MaxMonitorWidth: %d MaxMonitorHeight: %d\n",
+ // disp->MaxNumMonitors, disp->MaxMonitorWidth, disp->MaxMonitorHeight);
+
+ return 0;
+}
+
+int disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
+{
+ UINT32 type;
+ UINT32 length;
+
+ Stream_Read_UINT32(s, type); /* Type (4 bytes) */
+ Stream_Read_UINT32(s, length); /* Length (4 bytes) */
+
+ //fprintf(stderr, "Type: %d Length: %d\n", type, length);
+
+ switch (type)
+ {
+ case DISPLAY_CONTROL_PDU_TYPE_CAPS:
+ disp_recv_display_control_caps_pdu(callback, s);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
+{
+ wStream* s;
+ int status = 0;
+ DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback;
+
+ s = Stream_New(pBuffer, cbSize);
+
+ status = disp_recv_pdu(callback, s);
+
+ Stream_Free(s, FALSE);
+
+ return status;
+}
+
+static int disp_on_close(IWTSVirtualChannelCallback* pChannelCallback)
+{
+ DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback;
+
+ if (callback)
+ {
+ free(callback);
+ }
+
+ return 0;
+}
+
+static int disp_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
+ IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
+ IWTSVirtualChannelCallback** ppCallback)
+{
+ DISP_CHANNEL_CALLBACK* callback;
+ DISP_LISTENER_CALLBACK* listener_callback = (DISP_LISTENER_CALLBACK*) pListenerCallback;
+
+ callback = (DISP_CHANNEL_CALLBACK*) malloc(sizeof(DISP_CHANNEL_CALLBACK));
+ ZeroMemory(callback, sizeof(DISP_CHANNEL_CALLBACK));
+
+ callback->iface.OnDataReceived = disp_on_data_received;
+ callback->iface.OnClose = disp_on_close;
+ callback->plugin = listener_callback->plugin;
+ callback->channel_mgr = listener_callback->channel_mgr;
+ callback->channel = pChannel;
+ listener_callback->channel_callback = callback;
+
+ *ppCallback = (IWTSVirtualChannelCallback*) callback;
+
+ return 0;
+}
+
+static int disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
+{
+ int status;
+ DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin;
+
+ disp->listener_callback = (DISP_LISTENER_CALLBACK*) malloc(sizeof(DISP_LISTENER_CALLBACK));
+ ZeroMemory(disp->listener_callback, sizeof(DISP_LISTENER_CALLBACK));
+
+ disp->listener_callback->iface.OnNewChannelConnection = disp_on_new_channel_connection;
+ disp->listener_callback->plugin = pPlugin;
+ disp->listener_callback->channel_mgr = pChannelMgr;
+
+ status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0,
+ (IWTSListenerCallback*) disp->listener_callback, &(disp->listener));
+
+ disp->listener->pInterface = disp->iface.pInterface;
+
+ return status;
+}
+
+static int disp_plugin_terminated(IWTSPlugin* pPlugin)
+{
+ DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin;
+
+ if (disp)
+ {
+ free(disp);
+ }
+
+ return 0;
+}
+
+/**
+ * Channel Client Interface
+ */
+
+int disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors)
+{
+ DISP_PLUGIN* disp = (DISP_PLUGIN*) context->handle;
+ DISP_CHANNEL_CALLBACK* callback = disp->listener_callback->channel_callback;
+
+ disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors);
+
+ return 1;
+}
+
+#ifdef STATIC_CHANNELS
+#define DVCPluginEntry disp_DVCPluginEntry
+#endif
+
+int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
+{
+ int error = 0;
+ DISP_PLUGIN* disp;
+ DispClientContext* context;
+
+ disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp");
+
+ if (disp == NULL)
+ {
+ disp = (DISP_PLUGIN*) malloc(sizeof(DISP_PLUGIN));
+
+ if (disp)
+ {
+ ZeroMemory(disp, sizeof(DISP_PLUGIN));
+
+ disp->iface.Initialize = disp_plugin_initialize;
+ disp->iface.Connected = NULL;
+ disp->iface.Disconnected = NULL;
+ disp->iface.Terminated = disp_plugin_terminated;
+
+ context = (DispClientContext*) malloc(sizeof(DispClientContext));
+
+ context->handle = (void*) disp;
+
+ context->SendMonitorLayout = disp_send_monitor_layout;
+
+ disp->iface.pInterface = (void*) context;
+
+ disp->MaxNumMonitors = 16;
+ disp->MaxMonitorWidth = 8192;
+ disp->MaxMonitorHeight = 8192;
+
+ error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp);
+ }
+ }
+
+ return error;
+}
diff --git a/channels/disp/client/disp_main.h b/channels/disp/client/disp_main.h
new file mode 100644
index 000000000..db1ce10c5
--- /dev/null
+++ b/channels/disp/client/disp_main.h
@@ -0,0 +1,40 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Display Update Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_CHANNEL_DISP_CLIENT_MAIN_H
+#define FREERDP_CHANNEL_DISP_CLIENT_MAIN_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+#include
+
+#define DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
+#define DISPLAY_CONTROL_PDU_TYPE_CAPS 0x00000003
+
+#define DISP_PREVIEW 1
+
+#endif /* FREERDP_CHANNEL_DISP_CLIENT_MAIN_H */
+
diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c
index ac897a669..954247d02 100644
--- a/channels/drdynvc/client/dvcman.c
+++ b/channels/drdynvc/client/dvcman.c
@@ -376,16 +376,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
{
DEBUG_WARN("channel rejected by plugin");
- channel->status = 1;
- ArrayList_Add(dvcman->channels, channel);
+ free(channel);
return 1;
}
}
}
- channel->status = 1;
- ArrayList_Add(dvcman->channels, channel);
-
+ free(channel);
return 1;
}
diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c
index 6e35c1ee9..16bf4bbb0 100644
--- a/channels/parallel/client/parallel_main.c
+++ b/channels/parallel/client/parallel_main.c
@@ -286,6 +286,7 @@ static void parallel_free(DEVICE* device)
MessageQueue_PostQuit(parallel->queue, 0);
WaitForSingleObject(parallel->thread, INFINITE);
+ Stream_Free(parallel->device.data, TRUE);
MessageQueue_Free(parallel->queue);
CloseHandle(parallel->thread);
diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c
index 89e2ffb81..3826b7c3a 100644
--- a/channels/printer/client/printer_main.c
+++ b/channels/printer/client/printer_main.c
@@ -179,13 +179,16 @@ static void* printer_thread_func(void* arg)
{
IRP* irp;
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) arg;
+ HANDLE obj[] = {printer_dev->event, printer_dev->stopEvent};
while (1)
{
- WaitForSingleObject(printer_dev->event, INFINITE);
+ DWORD rc = WaitForMultipleObjects(2, obj, FALSE, INFINITE);
- if (WaitForSingleObject(printer_dev->stopEvent, 0) == WAIT_OBJECT_0)
+ if (rc == WAIT_OBJECT_0 + 1)
break;
+ else if( rc != WAIT_OBJECT_0 )
+ continue;
ResetEvent(printer_dev->event);
diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c
index 854fd46ab..81099e6d8 100644
--- a/channels/rdpei/client/rdpei_main.c
+++ b/channels/rdpei/client/rdpei_main.c
@@ -96,9 +96,10 @@ struct _RDPEI_PLUGIN
RDPINPUT_CONTACT_DATA contacts[MAX_CONTACTS];
RDPINPUT_CONTACT_POINT* contactPoints;
- HANDLE mutex;
HANDLE event;
HANDLE thread;
+
+ CRITICAL_SECTION lock;
};
typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN;
@@ -160,7 +161,7 @@ static void* rdpei_schedule_thread(void* arg)
{
status = WaitForSingleObject(rdpei->event, 20);
- WaitForSingleObject(rdpei->mutex, INFINITE);
+ EnterCriticalSection(&rdpei->lock);
rdpei_add_frame(context);
@@ -170,7 +171,7 @@ static void* rdpei_schedule_thread(void* arg)
if (status == WAIT_OBJECT_0)
ResetEvent(rdpei->event);
- ReleaseMutex(rdpei->mutex);
+ LeaveCriticalSection(&rdpei->lock);
}
return NULL;
@@ -212,14 +213,14 @@ int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
- Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V1); /* protocolVersion (4 bytes) */
+ Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */
Stream_Write_UINT16(s, rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */
Stream_SealLength(s);
if (!rdpei->thread)
{
- rdpei->mutex = CreateMutex(NULL, FALSE, NULL);
+ InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpei_schedule_thread, (void*) rdpei, 0, NULL);
}
@@ -249,6 +250,7 @@ void rdpei_print_contact_flags(UINT32 contactFlags)
int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
int index;
+ int rectSize = 2;
RDPINPUT_CONTACT_DATA* contact;
#ifdef WITH_DEBUG_RDPEI
@@ -264,12 +266,18 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
*/
rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
- Stream_EnsureRemainingCapacity(s, frame->contactCount * 32);
+ Stream_EnsureRemainingCapacity(s, frame->contactCount * 64);
for (index = 0; index < frame->contactCount; index++)
{
contact = &frame->contacts[index];
+ contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT;
+ contact->contactRectLeft = contact->x - rectSize;
+ contact->contactRectTop = contact->y - rectSize;
+ contact->contactRectRight = contact->x + rectSize;
+ contact->contactRectBottom = contact->y + rectSize;
+
#ifdef WITH_DEBUG_RDPEI
printf("contact[%d].contactId: %d\n", index, contact->contactId);
printf("contact[%d].fieldsPresent: %d\n", index, contact->fieldsPresent);
@@ -325,7 +333,7 @@ int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_
wStream* s;
UINT32 pduLength;
- pduLength = 64 + (frame->contactCount * 32);
+ pduLength = 64 + (frame->contactCount * 64);
s = Stream_New(NULL, pduLength);
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
@@ -355,11 +363,13 @@ int rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */
- if (protocolVersion != RDPINPUT_PROTOCOL_V1)
+#if 0
+ if (protocolVersion != RDPINPUT_PROTOCOL_V10)
{
fprintf(stderr, "Unknown [MS-RDPEI] protocolVersion: 0x%08X\n", protocolVersion);
return -1;
}
+#endif
return 0;
}
@@ -533,7 +543,7 @@ int rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contac
RDPINPUT_CONTACT_POINT* contactPoint;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
- WaitForSingleObject(rdpei->mutex, INFINITE);
+ EnterCriticalSection(&rdpei->lock);
contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[contact->contactId];
CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA));
@@ -541,7 +551,7 @@ int rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contac
SetEvent(rdpei->event);
- ReleaseMutex(rdpei->mutex);
+ LeaveCriticalSection(&rdpei->lock);
return 1;
}
diff --git a/channels/rdpei/client/rdpei_main.h b/channels/rdpei/client/rdpei_main.h
index c0d0d2d67..cf4dccee0 100644
--- a/channels/rdpei/client/rdpei_main.h
+++ b/channels/rdpei/client/rdpei_main.h
@@ -35,7 +35,8 @@
/* Protocol Version */
-#define RDPINPUT_PROTOCOL_V1 0x00010000
+#define RDPINPUT_PROTOCOL_V10 0x00010000
+#define RDPINPUT_PROTOCOL_V101 0x00010001
/* Client Ready Flags */
diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c
index df4700e9f..d2ff16a48 100644
--- a/channels/serial/client/serial_main.c
+++ b/channels/serial/client/serial_main.c
@@ -67,7 +67,6 @@ struct _SERIAL_DEVICE
wQueue* queue;
LIST* pending_irps;
- HANDLE in_event;
fd_set read_fds;
fd_set write_fds;
@@ -324,35 +323,31 @@ static void* serial_thread_func(void* arg)
IRP* irp;
DWORD status;
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
+ HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue)};
while (1)
{
- if (WaitForSingleObject(serial->stopEvent, 0) == WAIT_OBJECT_0)
- break;
+ status = WaitForMultipleObjects(2, ev, FALSE, 1);
- if (WaitForSingleObject(Queue_Event(serial->queue), 10) == WAIT_OBJECT_0)
+ if (WAIT_OBJECT_0 == status)
break;
serial->nfds = 1;
FD_ZERO(&serial->read_fds);
FD_ZERO(&serial->write_fds);
- serial->tv.tv_sec = 1;
+ serial->tv.tv_sec = 0;
serial->tv.tv_usec = 0;
serial->select_timeout = 0;
- irp = (IRP*) Queue_Dequeue(serial->queue);
-
- if (irp)
- serial_process_irp(serial, irp);
-
- status = WaitForSingleObject(serial->in_event, 0);
-
- if ((status == WAIT_OBJECT_0) || (status == WAIT_TIMEOUT))
+ if (status == WAIT_OBJECT_0 + 1)
{
- if (serial_check_fds(serial))
- ResetEvent(serial->in_event);
+ if ((irp = (IRP*) Queue_Dequeue(serial->queue)))
+ serial_process_irp(serial, irp);
+ continue;
}
+
+ serial_check_fds(serial);
}
return NULL;
@@ -371,10 +366,18 @@ static void serial_free(DEVICE* device)
DEBUG_SVC("freeing device");
+ /* Stop thread */
SetEvent(serial->stopEvent);
+ WaitForSingleObject(serial->thread, INFINITE);
- /* TODO: free lists */
+ serial_tty_free(serial->tty);
+ /* Clean up resources */
+ Stream_Free(serial->device.data, TRUE);
+ Queue_Free(serial->queue);
+ list_free(serial->pending_irps);
+ CloseHandle(serial->stopEvent);
+ CloseHandle(serial->thread);
free(serial);
}
@@ -387,6 +390,11 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32
DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
tty = serial->tty;
+ if(!tty)
+ {
+ DEBUG_WARN("tty = %p", tty);
+ return;
+ }
switch (abort_io)
{
@@ -423,7 +431,6 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32
Stream_Write_UINT32(irp->output, 0);
irp->Complete(irp);
- SetEvent(serial->in_event);
break;
}
@@ -438,6 +445,11 @@ static void serial_check_for_events(SERIAL_DEVICE* serial)
SERIAL_TTY* tty;
tty = serial->tty;
+ if(!tty)
+ {
+ DEBUG_WARN("tty = %p", tty);
+ return;
+ }
DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
@@ -460,8 +472,6 @@ static void serial_check_for_events(SERIAL_DEVICE* serial)
prev = irp;
irp = (IRP*) list_next(serial->pending_irps, irp);
list_remove(serial->pending_irps, prev);
-
- SetEvent(serial->in_event);
}
}
@@ -485,6 +495,11 @@ void serial_get_timeouts(SERIAL_DEVICE* serial, IRP* irp, UINT32* timeout, UINT3
DEBUG_SVC("length read %u", Length);
tty = serial->tty;
+ if(!tty)
+ {
+ DEBUG_WARN("tty = %p", tty);
+ return;
+ }
*timeout = (tty->read_total_timeout_multiplier * Length) + tty->read_total_timeout_constant;
*interval_timeout = tty->read_interval_timeout;
@@ -499,6 +514,11 @@ static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp)
SERIAL_TTY* tty;
tty = serial->tty;
+ if(!tty)
+ {
+ DEBUG_WARN("tty = %p", tty);
+ return;
+ }
switch (irp->MajorFunction)
{
@@ -537,7 +557,6 @@ static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp)
irp->IoStatus = STATUS_PENDING;
list_enqueue(serial->pending_irps, irp);
- SetEvent(serial->in_event);
}
static void __serial_check_fds(SERIAL_DEVICE* serial)
@@ -550,6 +569,11 @@ static void __serial_check_fds(SERIAL_DEVICE* serial)
ZeroMemory(&serial->tv, sizeof(struct timeval));
tty = serial->tty;
+ if(!tty)
+ {
+ DEBUG_WARN("tty = %p", tty);
+ return;
+ }
/* scan every pending */
irp = list_peek(serial->pending_irps);
@@ -599,10 +623,7 @@ static void __serial_check_fds(SERIAL_DEVICE* serial)
irp = (IRP*) list_next(serial->pending_irps, irp);
if (irp_completed || (prev->IoStatus == STATUS_SUCCESS))
- {
list_remove(serial->pending_irps, prev);
- SetEvent(serial->in_event);
- }
}
}
@@ -615,6 +636,11 @@ static void serial_set_fds(SERIAL_DEVICE* serial)
DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
tty = serial->tty;
+ if(!tty)
+ {
+ DEBUG_WARN("tty = %p", tty);
+ return;
+ }
irp = (IRP*) list_peek(serial->pending_irps);
while (irp)
@@ -692,7 +718,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
name = device->Name;
path = device->Path;
- if (name[0] && path[0])
+ if ((name && name[0]) && (path && path[0]))
{
serial = (SERIAL_DEVICE*) malloc(sizeof(SERIAL_DEVICE));
ZeroMemory(serial, sizeof(SERIAL_DEVICE));
@@ -711,13 +737,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
serial->path = path;
serial->queue = Queue_New(TRUE, -1, -1);
serial->pending_irps = list_new();
- serial->in_event = CreateEvent(NULL, TRUE, FALSE, NULL);
serial->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial);
- serial->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL);
+ serial->thread = CreateThread(NULL, 0,
+ (LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL);
}
return 0;
diff --git a/channels/serial/client/serial_tty.c b/channels/serial/client/serial_tty.c
index 23445b2ca..95bf375fe 100644
--- a/channels/serial/client/serial_tty.c
+++ b/channels/serial/client/serial_tty.c
@@ -412,7 +412,11 @@ BOOL serial_tty_read(SERIAL_TTY* tty, BYTE* buffer, UINT32* Length)
status = read(tty->fd, buffer, *Length);
if (status < 0)
+ {
+ DEBUG_WARN("failed with %zd, errno=[%d] %s\n",
+ status, errno, strerror(errno));
return FALSE;
+ }
tty->event_txempty = status;
*Length = status;
@@ -456,6 +460,9 @@ void serial_tty_free(SERIAL_TTY* tty)
{
DEBUG_SVC("in");
+ if(!tty)
+ return;
+
if (tty->fd >= 0)
{
if (tty->pold_termios)
diff --git a/channels/server/CMakeLists.txt b/channels/server/CMakeLists.txt
index b86cd6df4..aa15ce965 100644
--- a/channels/server/CMakeLists.txt
+++ b/channels/server/CMakeLists.txt
@@ -40,7 +40,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
- MODULES winpr-crt winpr-synch winpr-interlocked)
+ MODULES winpr-crt winpr-synch winpr-interlocked winpr-error)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} PARENT_SCOPE)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c
index fa4dd0b3d..4efff88ff 100644
--- a/channels/smartcard/client/smartcard_main.c
+++ b/channels/smartcard/client/smartcard_main.c
@@ -44,8 +44,7 @@ static void smartcard_free(DEVICE* dev)
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) dev;
SetEvent(smartcard->stopEvent);
- CloseHandle(smartcard->thread);
- CloseHandle(smartcard->irpEvent);
+ WaitForSingleObject(smartcard->thread, INFINITE);
while ((irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList)) != NULL)
irp->Discard(irp);
@@ -55,8 +54,14 @@ static void smartcard_free(DEVICE* dev)
/* Begin TS Client defect workaround. */
while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(smartcard->CompletionIds)) != NULL)
- free(CompletionIdInfo);
+ free(CompletionIdInfo);
+ CloseHandle(smartcard->thread);
+ CloseHandle(smartcard->irpEvent);
+ CloseHandle(smartcard->stopEvent);
+ CloseHandle(smartcard->CompletionIdsMutex);
+
+ Stream_Free(smartcard->device.data, TRUE);
list_free(smartcard->CompletionIds);
/* End TS Client defect workaround. */
@@ -119,13 +124,16 @@ static void smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
static void* smartcard_thread_func(void* arg)
{
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg;
+ HANDLE ev[] = {smartcard->irpEvent, smartcard->stopEvent};
while (1)
{
- WaitForSingleObject(smartcard->irpEvent, INFINITE);
+ DWORD status = WaitForSingleObject(2, ev, FALSE, INFINITE);
- if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
+ if (status == WAIT_OBJECT_0 + 1)
break;
+ else if(status != WAIT_OBJECT_0)
+ continue;
ResetEvent(smartcard->irpEvent);
smartcard_process_irp_list(smartcard);
diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
index 9e2c1674d..9ead22b81 100644
--- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
+++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
@@ -669,7 +669,6 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE *
return FALSE;
}
-
return TRUE;
}
@@ -1133,12 +1132,12 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
{
- DEBUG_DVC("tsmf_gstreamer_decodeEx_VIDEO. Start:(%llu) End:(%llu) Duration:(%llu) Last End:(%llu)",
+ DEBUG_DVC("tsmf_gstreamer_decodeEx_VIDEO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
start_time, end_time, duration, mdecoder->last_sample_end_time);
}
else
{
- DEBUG_DVC("tsmf_gstreamer_decodeEX_AUDIO. Start:(%llu) End:(%llu) Duration:(%llu) Last End:(%llu)",
+ DEBUG_DVC("tsmf_gstreamer_decodeEx_AUDIO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
start_time, end_time, duration, mdecoder->last_sample_end_time);
}
@@ -1176,7 +1175,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
*/
if (start_time > (mdecoder->last_sample_end_time + 10000000) || (end_time + 10000000) < mdecoder->last_sample_end_time)
{
- DEBUG_DVC("tsmf_gstreamer_decodeEx: start_time=[%llu] > last_sample_end_time=[%llu]", start_time, mdecoder->last_sample_end_time);
+ DEBUG_DVC("tsmf_gstreamer_decodeEx: start_time=[%"PRIu64"] > last_sample_end_time=[%"PRIu64"]", start_time, mdecoder->last_sample_end_time);
DEBUG_DVC("tsmf_gstreamer_decodeEx: Stream seek detected - flushing element.");
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
gst_object_unref(mdecoder->pipe);
@@ -1205,7 +1204,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (fout)
{
- fprintf(fout, "%"PRIu64"\n", (long unsigned int) start_time);
+ fprintf(fout, "%"PRIu64"\n", start_time);
fclose(fout);
}
@@ -1231,7 +1230,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (fin)
{
UINT64 AStartTime = 0;
- fscanf(fin, "%"PRIu64, (long unsigned int*) &AStartTime);
+ fscanf(fin, "%"PRIu64, &AStartTime);
fclose(fin);
if (start_time > AStartTime)
{
@@ -1265,7 +1264,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (fin)
{
UINT64 VStartTime = 0;
- fscanf(fin, "%"PRIu64, (long unsigned int*) &VStartTime);
+ fscanf(fin, "%"PRIu64, &VStartTime);
fclose(fin);
if (start_time > VStartTime)
{
@@ -1283,7 +1282,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
pthread_mutex_unlock(&mdecoder->gst_mutex);
DEBUG_WARN("tsmf_gstreamer_decodeEx: gst_buffer_try_new_and_alloc(%d) failed.", data_size);
return FALSE;
- }
+ }
gst_buffer_set_caps(gst_buf, mdecoder->gst_caps);
memcpy(GST_BUFFER_MALLOCDATA(gst_buf), data, data_size);
GST_BUFFER_TIMESTAMP(gst_buf) = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
@@ -1325,20 +1324,21 @@ static void tsmf_gstreamer_change_volume(ITSMFDecoder * decoder, UINT32 newVolum
if (mdecoder->shutdown)
return;
- if (!mdecoder->aVolume)
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
return;
- if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ mdecoder->gstMuted = (BOOL) muted;
+ DEBUG_DVC("tsmf_gstreamer_change_volume: mute=[%d]", mdecoder->gstMuted);
+ mdecoder->gstVolume = (double) newVolume / (double) 10000;
+ DEBUG_DVC("tsmf_gstreamer_change_volume: gst_new_vol=[%f]", mdecoder->gstVolume);
+
+ if (!mdecoder->aVolume)
return;
if (!G_IS_OBJECT(mdecoder->aVolume))
return;
- mdecoder->gstMuted = (BOOL) muted;
- DEBUG_DVC("tsmf_gstreamer_change_volume: mute=[%d]", mdecoder->gstMuted);
g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
- mdecoder->gstVolume = (double) newVolume / (double) 10000;
- DEBUG_DVC("tsmf_gstreamer_change_volume: gst_new_vol=[%f]", mdecoder->gstVolume);
g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
}
@@ -1482,7 +1482,7 @@ static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder * decoder)
GstFormat fmt = GST_FORMAT_TIME;
gint64 pos = 0;
gst_element_query_position (mdecoder->outsink, &fmt, &pos);
- DEBUG_DVC("tsmf_gstreamer_current_pos=[%llu]", pos);
+ DEBUG_DVC("tsmf_gstreamer_current_pos=[%"PRIu64"]", pos);
return pos/100;
}
@@ -1524,13 +1524,14 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int new
{
if (info->noutput > 0)
{
- if (info->outputs[0] == primary_output)
+ if (info->outputs[0] == primary_output || i == 0)
{
mdecoder->xOffset = info->x;
mdecoder->yOffset = info->y;
}
DEBUG_DVC("output %d ID: %lu (x,y): (%d,%d) (w,h): (%d,%d) primary: %d", i, info->outputs[0], info->x, info->y, info->width, info->height, (info->outputs[0] == primary_output));
}
+ XRRFreeCrtcInfo(info);
}
}
}
@@ -1545,7 +1546,12 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int new
if(mdecoder->subwin)
{
XMoveWindow(mdecoder->disp, mdecoder->subwin, anewX, anewY);
- XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
+ if(newWidth > 0 && newHeight > 0) {
+ XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
+ } else {
+ XResizeWindow(mdecoder->disp, mdecoder->subwin, 1, 1);
+ }
+
XSync(mdecoder->disp, FALSE);
XShapeCombineRectangles (mdecoder->disp, mdecoder->subwin, ShapeBounding, 0, 0,(XRectangle*) rectangles, numRectangles, ShapeSet, Unsorted);
XSync(mdecoder->disp, FALSE);
@@ -1599,7 +1605,7 @@ ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
decoder->xOffset = 0;
decoder->yOffset = 0;
decoder->offsetObtained = FALSE;
- decoder->gstVolume = 1.0;
+ decoder->gstVolume = 0.5;
decoder->gstMuted = FALSE;
decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */
pthread_mutex_init(&decoder->gst_mutex, NULL);
diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c
index 59059dbba..03229adb5 100644
--- a/channels/tsmf/client/tsmf_ifman.c
+++ b/channels/tsmf/client/tsmf_ifman.c
@@ -127,8 +127,6 @@ int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
return 0;
}
-static TSMF_PRESENTATION* pexisted = 0;
-
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
{
int status = 0;
@@ -136,15 +134,16 @@ int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
DEBUG_DVC("");
- if (pexisted)
+ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+ if (presentation)
{
+ DEBUG_DVC("Presentation already exists");
ifman->output_pending = FALSE;
return 0;
}
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
- pexisted = presentation;
if (presentation == NULL)
status = 1;
@@ -283,8 +282,8 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
if (presentation)
tsmf_presentation_free(presentation);
-
- pexisted = 0;
+ else
+ DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 4);
Stream_Write_UINT32(ifman->output, 0); /* Result */
diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c
index d1449237e..f31175150 100644
--- a/channels/tsmf/client/tsmf_media.c
+++ b/channels/tsmf/client/tsmf_media.c
@@ -84,6 +84,9 @@ struct _TSMF_PRESENTATION
UINT64 audio_start_time;
UINT64 audio_end_time;
+ UINT32 volume;
+ UINT32 muted;
+
HANDLE mutex;
HANDLE thread;
@@ -282,6 +285,9 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
memcpy(presentation->presentation_id, guid, GUID_SIZE);
presentation->channel_callback = pChannelCallback;
+ presentation->volume = 5000; /* 50% */
+ presentation->muted = 0;
+
presentation->mutex = CreateMutex(NULL, FALSE, NULL);
presentation->stream_list = list_new();
@@ -786,6 +792,9 @@ void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 ne
LIST_ITEM* item;
TSMF_STREAM* stream;
+ presentation->volume = newVolume;
+ presentation->muted = muted;
+
for (item = presentation->stream_list->head; item; item = item->next)
{
stream = (TSMF_STREAM*) item->data;
@@ -964,7 +973,10 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
stream->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
stream->sample_list = Queue_New(TRUE, -1, -1);
+ stream->sample_list->object.fnObjectFree = free;
+
stream->sample_ack_list = Queue_New(TRUE, -1, -1);
+ stream->sample_ack_list->object.fnObjectFree = free;
WaitForSingleObject(presentation->mutex, INFINITE);
list_enqueue(presentation->stream_list, stream);
@@ -1026,6 +1038,7 @@ void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
stream->width = mediatype.Width;
stream->height = mediatype.Height;
stream->decoder = tsmf_load_decoder(name, &mediatype);
+ tsmf_stream_change_volume(stream, stream->presentation->volume, stream->presentation->muted);
}
void tsmf_stream_end(TSMF_STREAM* stream)
diff --git a/channels/urbdrc/client/CMakeLists.txt b/channels/urbdrc/client/CMakeLists.txt
index 53391f100..736097122 100644
--- a/channels/urbdrc/client/CMakeLists.txt
+++ b/channels/urbdrc/client/CMakeLists.txt
@@ -31,6 +31,10 @@ set(${MODULE_PREFIX}_SRCS
include_directories(..)
+find_package(UDev REQUIRED)
+find_package(UUID REQUIRED)
+find_package(DbusGlib REQUIRED)
+
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
@@ -38,9 +42,9 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} libusb-devman)
set(${MODULE_PREFIX}_LIBS
- dbus-glib-1
- udev
- uuid)
+ ${DBUS_GLIB_LIBRARIES}
+ ${UDEV_LIBRARIES}
+ ${UUID_LIBRARIES})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
diff --git a/channels/urbdrc/client/libusb/CMakeLists.txt b/channels/urbdrc/client/libusb/CMakeLists.txt
index 0f66539da..47688b9b0 100644
--- a/channels/urbdrc/client/libusb/CMakeLists.txt
+++ b/channels/urbdrc/client/libusb/CMakeLists.txt
@@ -27,6 +27,8 @@ set(${MODULE_PREFIX}_SRCS
include_directories(..)
+find_package(libusb-1.0 REQUIRED)
+
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
@@ -35,9 +37,10 @@ set(${MODULE_PREFIX}_LIBS
${CMAKE_THREAD_LIBS_INIT})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
- dbus-glib-1
- usb-1.0
- udev)
+ ${DBUS_GLIB_LIBRARIES}
+ ${UUID_LIBRARIES}
+ ${LIBUSB_1_LIBRARIES}
+ )
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
diff --git a/client/Android/FreeRDPCore/jni/android_freerdp.c b/client/Android/FreeRDPCore/jni/android_freerdp.c
index 632ca82c2..f0046dcc5 100644
--- a/client/Android/FreeRDPCore/jni/android_freerdp.c
+++ b/client/Android/FreeRDPCore/jni/android_freerdp.c
@@ -686,7 +686,8 @@ JNIEXPORT void JNICALL jni_freerdp_set_gateway_info(JNIEnv *env, jclass cls, jin
settings->GatewayUsername = strdup(gatewayusername);
settings->GatewayPassword = strdup(gatewaypassword);
settings->GatewayDomain = strdup(gatewaydomain);
- settings->GatewayUsageMethod = TRUE;
+ settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
+ settings->GatewayEnabled = TRUE;
settings->GatewayUseSameCredentials = FALSE;
(*env)->ReleaseStringUTFChars(env, jgatewayhostname, gatewayhostname);
diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java
index 055b48b73..defaf9247 100644
--- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java
+++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java
@@ -248,6 +248,9 @@ public class SessionActivity extends Activity
{
Log.v(TAG, "OnConnectionFailure");
+ // remove pending move events
+ uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
+
if(progressDialog != null)
{
progressDialog.dismiss();
@@ -264,7 +267,10 @@ public class SessionActivity extends Activity
private void OnDisconnected(Context context)
{
Log.v(TAG, "OnDisconnected");
-
+
+ // remove pending move events
+ uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
+
if(progressDialog != null)
{
progressDialog.dismiss();
@@ -434,6 +440,7 @@ public class SessionActivity extends Activity
keyboardMapper = new KeyboardMapper();
keyboardMapper.init(this);
+ keyboardMapper.reset(this);
modifiersKeyboard = new Keyboard(getApplicationContext(), R.xml.modifiers_keyboard);
specialkeysKeyboard = new Keyboard(getApplicationContext(), R.xml.specialkeys_keyboard);
diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java
index 83f6ca562..06b800a80 100644
--- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java
+++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java
@@ -65,7 +65,9 @@ public abstract class ClipboardManagerProxy {
String data = null;
if (clip != null && clip.getItemCount() > 0) {
- data = clip.getItemAt(0).getText().toString();
+ CharSequence cs = clip.getItemAt(0).getText();
+ if (cs != null)
+ data = cs.toString();
}
if (mListener != null) {
mListener.onClipboardChanged(data);
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 2543bb028..e78c37517 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -57,4 +57,4 @@ endif()
if (WITH_DOTNET)
add_subdirectory(DotNetClient)
-endif()
\ No newline at end of file
+endif()
diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt
index 78dfca32b..2344f46a1 100755
--- a/client/Mac/CMakeLists.txt
+++ b/client/Mac/CMakeLists.txt
@@ -1,10 +1,10 @@
+
project(MacFreeRDP-library)
set(MODULE_NAME "MacFreeRDP-library")
set(MODULE_OUTPUT_NAME "MacFreeRDP")
-set(MODULE_PREFIX "FREERDP_CLIENT_MAC-LIB")
+set(MODULE_PREFIX "FREERDP_CLIENT_MAC_LIBRARY")
-# Import frameworks
find_library(FOUNDATION_LIBRARY Foundation)
find_library(COCOA_LIBRARY Cocoa)
find_library(APPKIT_LIBRARY AppKit)
@@ -21,53 +21,57 @@ set(MACOSX_BUNDLE_SHORT_VERSION_STRING 1.1.0)
set(MACOSX_BUNDLE_BUNDLE_VERSION 1.1.0)
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013. All Rights Reserved.")
-set(${MODULE_NAME}_RESOURCES "en.lproj/InfoPlist.strings")
+set(${MODULE_PREFIX}_XIBS PasswordDialog.xib)
-# OS X Interface Builder files
-file(GLOB ${MODULE_NAME}_XIBS *.xib)
+set(${MODULE_PREFIX}_SOURCES "")
-# source files
-file(GLOB ${MODULE_NAME}_SRC *.c *.m)
+set(${MODULE_PREFIX}_OBJECTIVE_SOURCES
+ main.m
+ mf_client.m
+ MRDPCursor.m
+ MRDPView.m
+ PasswordDialog.m)
-# header files
-file(GLOB ${MODULE_NAME}_HEADERS *.h)
+list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES})
+
+set(${MODULE_PREFIX}_HEADERS
+ mfreerdp.h
+ mf_client.h
+ MRDPCursor.h
+ MRDPView.h
+ PasswordDialog.h)
+
+set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings")
# Include XIB file in Xcode resources.
if("${CMAKE_GENERATOR}" MATCHES "Xcode")
message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}")
- set(${MODULE_NAME}_RESOURCES ${${MODULE_NAME}_RESOURCES} ${${MODULE_NAME}_XIBS})
+ set(${MODULE_PREFIX}_RESOURCES ${${MODULE_PREFIX}_RESOURCES} ${${MODULE_PREFIX}_XIBS})
endif()
add_library(${MODULE_NAME}
SHARED
../common/client.c
- ${${MODULE_NAME}_SRC}
- ${${MODULE_NAME}_HEADERS}
- ${${MODULE_NAME}_RESOURCES})
+ ${${MODULE_PREFIX}_SOURCES}
+ ${${MODULE_PREFIX}_HEADERS}
+ ${${MODULE_PREFIX}_RESOURCES})
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAME}")
# configures the framework to always be looked for in the application bundle in the Frameworks sub-folder.
-SET_TARGET_PROPERTIES(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_INSTALL_PATH @executable_path/../Frameworks/)
+set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_INSTALL_PATH @executable_path/../Frameworks/)
set_target_properties(${MODULE_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH}
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
-# Support for automatic reference counting requires non-fragile abi.
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi")
-
-set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)")
-
-set(MODULE_VERSION, 1.1.0)
-
set_target_properties(${MODULE_NAME} PROPERTIES
FRAMEWORK TRUE
MACOSX_FRAMEWORK_IDENTIFIER com.awakecoding.${MODULE_NAME}
FRAMEWORK_VERSION 1.1.0
MACOSX_FRAMEWORK_SHORT_VERSION_STRING 1.1.0
- MACOSX_FRAMEWORK_BUNDLE_VERSION 1.1.0
- INSTALL_NAME_DIR "@executable_path/../../Frameworks"
+ MACOSX_FRAMEWORK_BUNDLE_BUNDLE_VERSION 1.1.0
+ INSTALL_NAME_DIR "@executable_path/../Frameworks"
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
BUILD_WITH_INSTALL_RPATH 1)
@@ -106,15 +110,15 @@ if (${BUILD_SHARED_LIBS})
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Contents/$"
COMMENT "Copying ${LIB} to output directory"
COMMAND install_name_tool -change "$"
- "@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/${MODULE_NAME}"
+ "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/${MODULE_NAME}"
COMMENT Setting install name for ${LIB}
COMMAND "${CMAKE_COMMAND}" -E echo install_name_tool -change "$"
- "@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/${MODULE_NAME}")
+ "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/${MODULE_NAME}")
endforeach()
# Call install_name_tool to reassign the library install names in dependent libraries
@@ -123,8 +127,8 @@ if (${BUILD_SHARED_LIBS})
# message("adding post-build dependency: ${LIB}")
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND install_name_tool -change "$"
- "@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Contents/$"
+ "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Contents/$"
COMMENT Setting install name for ${LIB} in module ${DEST})
endforeach()
endforeach()
@@ -132,7 +136,7 @@ if (${BUILD_SHARED_LIBS})
endif()
# Add post-build NIB file generation in unix makefiles. XCode handles this implicitly.
-if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
+# if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
message(STATUS "Adding post-build NIB file generation event for ${MODULE_NAME}")
# Make sure we can find the 'ibtool' program. If we can NOT find it we
@@ -145,7 +149,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
# Make sure the 'Resources' Directory is correctly created before we build
add_custom_command(TARGET ${MODULE_NAME} PRE_BUILD
- COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.app/Contents/Resources)
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources)
# Compile the .xib files using the 'ibtool' program with the destination being the app package
foreach(xib ${${MODULE_NAME}_XIBS})
@@ -153,22 +157,23 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
add_custom_command (TARGET ${MODULE_NAME} POST_BUILD
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
- --compile ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.app/Contents/Resources/${XIB_WE}.nib ${xib}
+ --compile ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources/${XIB_WE}.nib ${CMAKE_CURRENT_SOURCE_DIR}/${xib}
COMMENT "Compiling ${xib}")
endforeach()
-endif()
+# endif()
# Copy the public header files into the framework
-foreach(HEADER ${${MODULE_NAME}_HEADERS})
+foreach(HEADER ${${MODULE_PREFIX}_HEADERS})
# message("adding post-build dependency: ${LIB}")
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
- COMMAND ditto ${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Headers/
+ COMMAND ditto ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/
COMMENT Copying public header files to ${MODULE_NAME})
endforeach()
# Copy the FreeRDP header files into the framework
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
- COMMAND ditto ${CMAKE_SOURCE_DIR}/include/freerdp ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Headers/freerdp
+ COMMAND ditto ${CMAKE_SOURCE_DIR}/include/freerdp ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/freerdp
+ COMMAND ditto ${CMAKE_SOURCE_DIR}/winpr/include/winpr ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/winpr
COMMENT Copying FreeRDP header files to ${MODULE_NAME})
add_subdirectory(cli)
diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h
index 2cc67c2d4..289dae5ce 100755
--- a/client/Mac/MRDPView.h
+++ b/client/Mac/MRDPView.h
@@ -41,14 +41,11 @@
@interface MRDPView : NSView
{
- CFRunLoopSourceRef run_loop_src_channels;
- CFRunLoopSourceRef run_loop_src_update;
- CFRunLoopSourceRef run_loop_src_input;
-
NSBitmapImageRep* bmiRep;
NSMutableArray* cursors;
NSMutableArray* windows;
NSTimer* pasteboard_timer;
+ NSCursor* currentCursor;
NSRect prevWinPosition;
int titleBarHeight;
freerdp* instance;
@@ -61,7 +58,6 @@
char** argv;
NSPoint savedDragLocation;
- BOOL mouseInClientArea;
BOOL firstCreateWindow;
BOOL isMoveSizeInProgress;
BOOL skipResizeOnce;
@@ -78,6 +74,10 @@
int kdlmeta;
int kdrmeta;
int kdcapslock;
+
+ BOOL initialized;
+
+ NSImageView* imageView;
@public
NSPasteboard* pasteboard_rd; /* for reading from clipboard */
@@ -88,11 +88,11 @@
}
- (int) rdpStart :(rdpContext*) rdp_context;
-- (void) rdpConnectError;
-- (void) rdpRemoteAppError;
+- (void) setCursor: (NSCursor*) cursor;
+
- (void) onPasteboardTimerFired :(NSTimer *) timer;
- (void) releaseResources;
-- (void) setViewSize : (int) width : (int) height;
+- (void) setViewSize : (int) w : (int) h;
@property (assign) int is_connected;
@@ -107,3 +107,9 @@
#define PTR_FLAGS_BUTTON2 0x2000
#define PTR_FLAGS_BUTTON3 0x4000
#define WheelRotationMask 0x01FF
+
+BOOL mac_pre_connect(freerdp* instance);
+BOOL mac_post_connect(freerdp* instance);
+BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain);
+int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
+DWORD mac_client_thread(void* param);
diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m
index fe516b543..d12f2da3a 100644
--- a/client/Mac/MRDPView.m
+++ b/client/Mac/MRDPView.m
@@ -42,6 +42,8 @@
* -
*/
+#include
+
#include "mf_client.h"
#import "mfreerdp.h"
#import "MRDPView.h"
@@ -63,7 +65,6 @@
#import "freerdp/client/file.h"
#import "freerdp/client/cmdline.h"
-
/******************************************
Forward declarations
******************************************/
@@ -75,19 +76,14 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer);
void mf_Pointer_SetNull(rdpContext* context);
void mf_Pointer_SetDefault(rdpContext* context);
// int rdp_connect(void);
-BOOL mac_pre_connect(freerdp* instance);
-BOOL mac_post_connect(freerdp* instance);
-BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain);
void mac_set_bounds(rdpContext* context, rdpBounds* bounds);
void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap);
void mac_begin_paint(rdpContext* context);
void mac_end_paint(rdpContext* context);
void mac_save_state_info(freerdp* instance, rdpContext* context);
-static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info);
-static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info);
-static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info);
-int register_update_fds(freerdp* instance);
-int register_input_fds(freerdp* instance);
+static void update_activity_cb(freerdp* instance);
+static void input_activity_cb(freerdp* instance);
+static void channel_activity_cb(freerdp* instance);
int invoke_draw_rect(rdpContext* context);
int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data);
int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
@@ -101,6 +97,9 @@ void cliprdr_process_text(freerdp* instance, BYTE* data, int len);
void cliprdr_send_supported_format_list(freerdp* instance);
int register_channel_fds(int* fds, int count, freerdp* instance);
+
+DWORD mac_client_thread(void* param);
+
struct cursor
{
rdpPointer* pointer;
@@ -124,57 +123,112 @@ struct rgba_data
- (int) rdpStart:(rdpContext*) rdp_context
{
- int status;
mfContext* mfc;
rdpSettings* settings;
EmbedWindowEventArgs e;
+ [self initializeView];
+
context = rdp_context;
mfc = (mfContext*) rdp_context;
instance = context->instance;
settings = context->settings;
- mfc->view = self;
EventArgsInit(&e, "mfreerdp");
e.embed = TRUE;
e.handle = (void*) self;
PubSub_OnEmbedWindow(context->pubSub, context, &e);
+ [self setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight];
- context->instance->PreConnect = mac_pre_connect;
- context->instance->PostConnect = mac_post_connect;
- context->instance->ReceiveChannelData = mac_receive_channel_data;
- context->instance->Authenticate = mac_authenticate;
-
- // TODO
- // instance->Authenticate = mf_authenticate;
- // instance->VerifyCertificate = mf_verify_certificate;
- // instance->LogonErrorInfo = mf_logon_error_info;
-
- status = freerdp_connect(context->instance);
+ mfc->thread = CreateThread(NULL, 0, mac_client_thread, (void*) context, 0, &mfc->mainThreadId);
- if (!status)
- {
- [self setIs_connected:0];
- [self rdpConnectError];
- return 1;
- }
-
- /* register update message queue with the RunLoop */
- register_update_fds(context->instance);
-
- /* register update message queue with the RunLoop */
- register_input_fds(context->instance);
-
- /* register channel events with the RunLoop */
- register_channels_fds(context->instance);
-
- freerdp_check_fds(context->instance);
-
- [self setIs_connected:1];
-
return 0;
}
+DWORD mac_client_thread(void* param)
+{
+ @autoreleasepool
+ {
+ int status;
+ HANDLE events[4];
+ HANDLE input_event;
+ HANDLE update_event;
+ HANDLE channels_event;
+
+ DWORD nCount;
+ rdpContext* context = (rdpContext*) param;
+ mfContext* mfc = (mfContext*) context;
+ freerdp* instance = context->instance;
+ MRDPView* view = mfc->view;
+
+ status = freerdp_connect(context->instance);
+
+ if (!status)
+ {
+ [view setIs_connected:0];
+ return 0;
+ }
+
+ [view setIs_connected:1];
+
+ nCount = 0;
+
+ events[nCount++] = mfc->stopEvent;
+
+ if (instance->settings->AsyncUpdate)
+ {
+ events[nCount++] = update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
+ }
+
+ if (instance->settings->AsyncInput)
+ {
+ events[nCount++] = input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
+ }
+
+ if (instance->settings->AsyncChannels)
+ {
+ events[nCount++] = channels_event = freerdp_channels_get_event_handle(instance);
+ }
+
+ while (1)
+ {
+ status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
+
+ if (WaitForSingleObject(mfc->stopEvent, 0) == WAIT_OBJECT_0)
+ {
+ break;
+ }
+
+ if (instance->settings->AsyncUpdate)
+ {
+ if (WaitForSingleObject(update_event, 0) == WAIT_OBJECT_0)
+ {
+ update_activity_cb(instance);
+ }
+ }
+
+ if (instance->settings->AsyncInput)
+ {
+ if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
+ {
+ input_activity_cb(instance);
+ }
+ }
+
+ if (instance->settings->AsyncChannels)
+ {
+ if (WaitForSingleObject(channels_event, 0) == WAIT_OBJECT_0)
+ {
+ channel_activity_cb(instance);
+ }
+ }
+ }
+
+ ExitThread(0);
+ return 0;
+ }
+}
+
/************************************************************************
methods we override
************************************************************************/
@@ -185,7 +239,7 @@ struct rgba_data
- (id)initWithFrame:(NSRect)frame
{
- self = [super initWithFrame:frame];
+ self = [super initWithFrame:frame];
if (self)
{
@@ -201,24 +255,50 @@ struct rgba_data
//TODO - Expose this code as a public method, because awakeFromNib
// won't be called if the view is created dynamically
-- (void) awakeFromNib
+- (void) viewDidLoad
{
- // store our window dimensions
- width = [self frame].size.width;
- height = [self frame].size.height;
- titleBarHeight = 22;
-
- [[self window] becomeFirstResponder];
- [[self window] setAcceptsMouseMovedEvents:YES];
-
- cursors = [[NSMutableArray alloc] initWithCapacity:10];
+ [self initializeView];
+}
- // setup a mouse tracking area
- NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
-
- [self addTrackingArea:trackingArea];
-
- mouseInClientArea = YES;
+- (void) initializeView
+{
+ if (!initialized)
+ {
+ // store our window dimensions
+ width = [self frame].size.width;
+ height = [self frame].size.height;
+ titleBarHeight = 22;
+
+ [[self window] becomeFirstResponder];
+ [[self window] setAcceptsMouseMovedEvents:YES];
+
+ cursors = [[NSMutableArray alloc] initWithCapacity:10];
+
+ // setup a mouse tracking area
+ NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
+
+ [self addTrackingArea:trackingArea];
+
+ // Set the default cursor
+ currentCursor = [NSCursor arrowCursor];
+
+ initialized = YES;
+ }
+}
+
+- (void) setCursor: (NSCursor*) cursor
+{
+ self->currentCursor = cursor;
+ [[self window] invalidateCursorRectsForView:self];
+
+ [imageView setImage:[currentCursor image]];
+}
+
+
+// Set the current cursor
+- (void) resetCursorRects
+{
+ [self addCursorRect:[self visibleRect] cursor:currentCursor];
}
/** *********************************************************************
@@ -596,7 +676,8 @@ struct rgba_data
- (void) releaseResources
{
int i;
-
+
+
for (i = 0; i < argc; i++)
{
if (argv[i])
@@ -610,20 +691,6 @@ struct rgba_data
if (pixel_data)
free(pixel_data);
-
- if (run_loop_src_update != 0)
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_update, kCFRunLoopDefaultMode);
-
- if (run_loop_src_input != 0)
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_input, kCFRunLoopDefaultMode);
-
- if (run_loop_src_channels != 0)
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_channels, kCFRunLoopDefaultMode);
-
- freerdp_client_stop(self->context);
-
- freerdp_client_context_free(self->context);
-
}
/** *********************************************************************
@@ -657,94 +724,6 @@ struct rgba_data
instance methods
************************************************************************/
-/** *********************************************************************
- * double check that a mouse event occurred in our client view
- ***********************************************************************/
-
-- (BOOL) eventIsInClientArea :(NSEvent *) event :(int *) xptr :(int *) yptr
-{
- NSPoint loc = [event locationInWindow];
- int x = (int) loc.x;
- int y = (int) loc.y;
-
- if ((x < 0) || (y < 0))
- {
- if (mouseInClientArea)
- {
- // set default cursor before leaving client area
- mouseInClientArea = NO;
- NSCursor *cur = [NSCursor arrowCursor];
- [cur set];
- }
-
- return NO;
- }
-
- if ((x > width) || (y > height))
- {
- if (mouseInClientArea)
- {
- // set default cursor before leaving client area
- mouseInClientArea = NO;
- NSCursor *cur = [NSCursor arrowCursor];
- [cur set];
- }
-
- return NO;
- }
-
- // on Mac origin is at lower left, but we want it on upper left
- y = height - y;
-
- *xptr = x;
- *yptr = y;
- mouseInClientArea = YES;
- return YES;
-}
-
-/** *********************************************************************
- * called when we fail to connect to a RDP server
- ***********************************************************************/
-
-- (void) rdpConnectError
-{
- NSString* message = @"Error connecting to server";
- if (connectErrorCode == AUTHENTICATIONERROR)
- {
- message = [NSString stringWithFormat:@"%@:\n%@", message, @"Authentication failure, check credentials."];
- }
-
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:message];
- [alert beginSheetModalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
- contextInfo:nil];
-}
-
-/** *********************************************************************
- * called when we fail to launch remote app on RDP server
- ***********************************************************************/
-
-- (void) rdpRemoteAppError
-{
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:@"Error starting remote app on specified server"];
- [alert beginSheetModalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
- contextInfo:nil];
-}
-
-/** *********************************************************************
- * just a terminate selector for above call
- ***********************************************************************/
-
-- (void) alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci
-{
- [NSApp terminate:nil];
-}
-
- (void) onPasteboardTimerFired :(NSTimer*) timer
{
int i;
@@ -782,8 +761,17 @@ struct rgba_data
outerRect.size.height = h + heightDiff;
[[self window] setMaxSize:outerRect.size];
[[self window] setMinSize:outerRect.size];
- [[self window] setFrame:outerRect display:YES];
-
+
+ @try
+ {
+ [[self window] setFrame:outerRect display:YES];
+ }
+ @catch (NSException * e) {
+ NSLog(@"Exception: %@", e);
+ }
+ @finally {
+ }
+
// set client area to specified dimensions
innerRect.size.width = w;
innerRect.size.height = h;
@@ -815,9 +803,6 @@ BOOL mac_pre_connect(freerdp* instance)
instance->update->EndPaint = mac_end_paint;
instance->update->SetBounds = mac_set_bounds;
//instance->update->BitmapUpdate = mac_bitmap_update;
-
- mfContext *mfc = (mfContext*) instance->context;
- MRDPView* view = (MRDPView*) mfc->view;
settings = instance->settings;
@@ -868,8 +853,6 @@ BOOL mac_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
- [view setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight];
-
freerdp_channels_pre_connect(instance->context->channels, instance);
return TRUE;
@@ -888,13 +871,7 @@ BOOL mac_pre_connect(freerdp* instance)
BOOL mac_post_connect(freerdp* instance)
{
- int index;
- int fds[32];
UINT32 flags;
- int rd_count = 0;
- int wr_count = 0;
- void* rd_fds[32];
- void* wr_fds[32];
rdpPointer rdp_pointer;
mfContext *mfc = (mfContext*) instance->context;
@@ -908,7 +885,7 @@ BOOL mac_post_connect(freerdp* instance)
rdp_pointer.SetNull = mf_Pointer_SetNull;
rdp_pointer.SetDefault = mf_Pointer_SetDefault;
- flags = CLRBUF_32BPP;
+ flags = CLRBUF_32BPP | CLRCONV_ALPHA;
gdi_init(instance, flags, NULL);
rdpGdi* gdi = instance->context->gdi;
@@ -927,9 +904,6 @@ BOOL mac_post_connect(freerdp* instance)
view->pasteboard_rd = [NSPasteboard generalPasteboard];
view->pasteboard_changecount = (int) [view->pasteboard_rd changeCount];
view->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:mfc->view selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES];
-
- /* we want to be notified when window resizes */
- [[NSNotificationCenter defaultCenter] addObserver:mfc->view selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil];
return TRUE;
}
@@ -992,6 +966,11 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
cursor_data = (BYTE*) malloc(rect.size.width * rect.size.height * 4);
mrdpCursor->cursor_data = cursor_data;
+ if (pointer->xorBpp > 24)
+ {
+ freerdp_image_swap_color_order(pointer->xorMaskData, pointer->width, pointer->height);
+ }
+
freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData,
pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv);
@@ -1066,19 +1045,16 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
NSMutableArray* ma = view->cursors;
- return; /* disable pointer until it is fixed */
-
- if (!view->mouseInClientArea)
- return;
-
for (MRDPCursor* cursor in ma)
{
if (cursor->pointer == pointer)
{
- [cursor->nsCursor set];
+ [view setCursor:cursor->nsCursor];
return;
}
}
+
+ NSLog(@"Cursor not found");
}
/** *********************************************************************
@@ -1096,7 +1072,9 @@ void mf_Pointer_SetNull(rdpContext* context)
void mf_Pointer_SetDefault(rdpContext* context)
{
-
+ mfContext* mfc = (mfContext*) context;
+ MRDPView* view = (MRDPView*) mfc->view;
+ [view setCursor:[NSCursor arrowCursor]];
}
/** *********************************************************************
@@ -1152,10 +1130,10 @@ void mac_end_paint(rdpContext* context)
for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++)
{
- drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x;
- drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y;
- drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w;
- drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h;
+ drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x - 1;
+ drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y - 1;
+ drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w + 1;
+ drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h + 1;
windows_to_apple_cords(mfc->view, &drawRect);
[view setNeedsDisplayInRect:drawRect];
}
@@ -1168,16 +1146,15 @@ void mac_end_paint(rdpContext* context)
* called when update data is available
***********************************************************************/
-static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info)
+static void update_activity_cb(freerdp* instance)
{
int status;
wMessage message;
wMessageQueue* queue;
- freerdp* instance = (freerdp*) info;
status = 1;
queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
-
+
if (queue)
{
while (MessageQueue_Peek(queue, &message, TRUE))
@@ -1188,21 +1165,21 @@ static void update_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBack
break;
}
}
-
- CFRelease(fdref);
- register_update_fds(instance);
+ else
+ {
+ fprintf(stderr, "update_activity_cb: No queue!\n");
+ }
}
/** *********************************************************************
* called when input data is available
***********************************************************************/
-static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info)
+static void input_activity_cb(freerdp* instance)
{
int status;
wMessage message;
- wMessageQueue* queue;
- freerdp* instance = (freerdp*) info;
+ wMessageQueue* queue;
status = 1;
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
@@ -1211,33 +1188,32 @@ static void input_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackT
{
while (MessageQueue_Peek(queue, &message, TRUE))
{
- fprintf(stderr, "input_activity_cb: message %d\n", message.id);
-
status = freerdp_message_queue_process_message(instance, FREERDP_INPUT_MESSAGE_QUEUE, &message);
if (!status)
break;
}
}
-
- CFRelease(fdref);
- register_input_fds(instance);
+ else
+ {
+ fprintf(stderr, "input_activity_cb: No queue!\n");
+ }
}
/** *********************************************************************
* called when data is available on a virtual channel
***********************************************************************/
-static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info)
+static void channel_activity_cb(freerdp* instance)
{
- wMessage* event;
- freerdp* instance = (freerdp*) info;
+ wMessage* event;
freerdp_channels_process_pending_messages(instance);
event = freerdp_channels_pop_event(instance->context->channels);
if (event)
{
- switch (GetMessageClass(event->id))
+ fprintf(stderr, "channel_activity_cb: message %d\n", event->id);
+ switch (GetMessageClass(event->id))
{
case CliprdrChannel_Class:
process_cliprdr_event(instance, event);
@@ -1246,90 +1222,6 @@ static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBac
freerdp_event_free(event);
}
-
- CFRelease(fdref);
- register_channels_fds(instance);
-}
-
-/** *********************************************************************
- * setup callbacks for data availability on update message queue
- ***********************************************************************/
-
-int register_update_fds(freerdp* instance)
-{
- int fd_update_event;
- HANDLE update_event;
- CFFileDescriptorRef fdref;
- CFFileDescriptorContext fd_context = { 0, instance, NULL, NULL, NULL };
- mfContext* mfc = (mfContext*) instance->context;
- MRDPView* view = (MRDPView*) mfc->view;
-
- if (instance->settings->AsyncUpdate)
- {
- update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
- fd_update_event = GetEventFileDescriptor(update_event);
-
- fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd_update_event, true, update_activity_cb, &fd_context);
- CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
- view->run_loop_src_update = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), view->run_loop_src_update, kCFRunLoopDefaultMode);
- }
-
- return 0;
-}
-
-/** *********************************************************************
- * setup callbacks for data availability on input message queue
- ***********************************************************************/
-
-int register_input_fds(freerdp* instance)
-{
- int fd_input_event;
- HANDLE input_event;
- CFFileDescriptorRef fdref;
- CFFileDescriptorContext fd_context = { 0, instance, NULL, NULL, NULL };
- mfContext* mfc = (mfContext*) instance->context;
- MRDPView* view = (MRDPView*) mfc->view;
-
- if (instance->settings->AsyncInput)
- {
- input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
- fd_input_event = GetEventFileDescriptor(input_event);
-
- fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd_input_event, true, input_activity_cb, &fd_context);
- CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
- view->run_loop_src_input = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), view->run_loop_src_input, kCFRunLoopDefaultMode);
- }
-
- return 0;
-}
-
-/** *********************************************************************
- * setup callbacks for data availability on channels
- ***********************************************************************/
-
-int register_channels_fds(freerdp* instance)
-{
- int fd_channel_event;
- HANDLE channel_event;
- CFFileDescriptorRef fdref;
- CFFileDescriptorContext fd_context = { 0, instance, NULL, NULL, NULL };
- mfContext* mfc = (mfContext*) instance->context;
- MRDPView* view = (MRDPView*) mfc->view;
-
- if (instance->settings->AsyncChannels)
- {
- channel_event = freerdp_channels_get_event_handle(instance);
- fd_channel_event = GetEventFileDescriptor(channel_event);
-
- fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd_channel_event, true, channel_activity_cb, &fd_context);
- CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
- view->run_loop_src_channels = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), view->run_loop_src_channels, kCFRunLoopDefaultMode);
- }
-
- return 0;
}
/** *********************************************************************
@@ -1567,20 +1459,12 @@ void cliprdr_send_supported_format_list(freerdp* instance)
freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
}
-
-/**
- * given a rect with 0,0 at the bottom left (apple cords)
- * convert it to a rect with 0,0 at the top left (windows cords)
- */
-
-void apple_to_windows_cords(MRDPView* view, NSRect* r)
-{
- r->origin.y = view->height - (r->origin.y + r->size.height);
-}
-
/**
* given a rect with 0,0 at the top left (windows cords)
* convert it to a rect with 0,0 at the bottom left (apple cords)
+ *
+ * Note: the formula works for conversions in both directions.
+ *
*/
void windows_to_apple_cords(MRDPView* view, NSRect* r)
diff --git a/client/Mac/cli/AppDelegate.h b/client/Mac/cli/AppDelegate.h
index fe2671351..91439c06f 100644
--- a/client/Mac/cli/AppDelegate.h
+++ b/client/Mac/cli/AppDelegate.h
@@ -7,8 +7,8 @@
//
#import
-#import
-#import
+#import
+#import
@interface AppDelegate : NSObject
{
@@ -18,8 +18,9 @@
MRDPView* mrdpView;
}
+- (void) rdpConnectError: (NSString*) customMessage;
+
@property (assign) IBOutlet NSWindow *window;
@property (assign) rdpContext *context;
-@property (assign) IBOutlet MRDPView *mrdpView;
@end
diff --git a/client/Mac/cli/AppDelegate.m b/client/Mac/cli/AppDelegate.m
index 1eb3d13c1..aec62be91 100644
--- a/client/Mac/cli/AppDelegate.m
+++ b/client/Mac/cli/AppDelegate.m
@@ -7,8 +7,13 @@
//
#import "AppDelegate.h"
-#import "MacFreeRDP-library/mfreerdp.h"
-#import "MacFreeRDP-library/mf_client.h"
+#import "MacFreeRDP/mfreerdp.h"
+#import "MacFreeRDP/mf_client.h"
+
+static AppDelegate* _singleDelegate = nil;
+void AppDelegate_EmbedWindowEventHandler(void* context, EmbedWindowEventArgs* e);
+void AppDelegate_ConnectionResultEventHandler(void* context, ConnectionResultEventArgs* e);
+void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
@implementation AppDelegate
@@ -19,7 +24,6 @@
@synthesize window = window;
-@synthesize mrdpView = mrdpView;
@synthesize context = context;
@@ -28,6 +32,7 @@
int status;
mfContext* mfc;
+ _singleDelegate = self;
[self CreateContext];
status = [self ParseCommandLineArguments];
@@ -41,6 +46,10 @@
}
else
{
+ PubSub_SubscribeConnectionResult(context->pubSub, AppDelegate_ConnectionResultEventHandler);
+ PubSub_SubscribeErrorInfo(context->pubSub, AppDelegate_ErrorInfoEventHandler);
+ PubSub_SubscribeEmbedWindow(context->pubSub, AppDelegate_EmbedWindowEventHandler);
+
freerdp_client_start(context);
}
}
@@ -48,6 +57,7 @@
- (void) applicationWillTerminate:(NSNotification*)notification
{
[mrdpView releaseResources];
+ _singleDelegate = nil;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
@@ -103,4 +113,92 @@
context = nil;
}
+
+/** *********************************************************************
+ * called when we fail to connect to a RDP server - Make sure this is called from the main thread.
+ ***********************************************************************/
+
+- (void) rdpConnectError : (NSString*) withMessage
+{
+ NSString* message = withMessage ? withMessage : @"Error connecting to server";
+
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:message];
+ [alert beginSheetModalForWindow:[self window]
+ modalDelegate:self
+ didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
+ contextInfo:nil];
+}
+
+
+/** *********************************************************************
+ * just a terminate selector for above call
+ ***********************************************************************/
+
+- (void) alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci
+{
+ [NSApp terminate:nil];
+}
+
+
@end
+
+void AppDelegate_EmbedWindowEventHandler(void* ctx, EmbedWindowEventArgs* e)
+{
+ rdpContext* context = (rdpContext*) ctx;
+
+ if (_singleDelegate)
+ {
+ mfContext* mfc = (mfContext*) context;
+ _singleDelegate->mrdpView = mfc->view;
+
+ if (_singleDelegate->window)
+ {
+ [[_singleDelegate->window contentView] addSubview:mfc->view];
+ }
+ }
+}
+
+/** *********************************************************************
+ * On connection error, display message and quit application
+ ***********************************************************************/
+
+void AppDelegate_ConnectionResultEventHandler(void* ctx, ConnectionResultEventArgs* e)
+{
+ NSLog(@"ConnectionResult event result:%d\n", e->result);
+ if (_singleDelegate)
+ {
+ if (e->result != 0)
+ {
+ NSString* message = nil;
+ if (connectErrorCode == AUTHENTICATIONERROR)
+ {
+ message = [NSString stringWithFormat:@"%@:\n%@", message, @"Authentication failure, check credentials."];
+ }
+
+
+ // Making sure this should be invoked on the main UI thread.
+ [_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:) withObject:message waitUntilDone:FALSE];
+ [message release];
+ }
+ }
+}
+
+void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e)
+{
+ NSLog(@"ErrorInfo event code:%d\n", e->code);
+ if (_singleDelegate)
+ {
+ // Retrieve error message associated with error code
+ NSString* message = nil;
+ if (e->code != ERRINFO_NONE)
+ {
+ const char* errorMessage = freerdp_get_error_info_string(e->code);
+ message = [[NSString alloc] initWithUTF8String:errorMessage];
+ }
+
+ // Making sure this should be invoked on the main UI thread.
+ [_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:) withObject:message waitUntilDone:TRUE];
+ [message release];
+ }
+}
\ No newline at end of file
diff --git a/client/Mac/cli/CMakeLists.txt b/client/Mac/cli/CMakeLists.txt
index 46643227d..e8033e2f5 100644
--- a/client/Mac/cli/CMakeLists.txt
+++ b/client/Mac/cli/CMakeLists.txt
@@ -1,15 +1,14 @@
-project(MacFreeRDP-client)
+
+project(MacFreeRDP)
set(MODULE_NAME "MacFreeRDP")
set(MODULE_OUTPUT_NAME "MacFreeRDP")
set(MODULE_PREFIX "FREERDP_CLIENT_MAC_CLIENT")
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min=10.5")
# Import libraries
find_library(FOUNDATION_LIBRARY Foundation)
find_library(COCOA_LIBRARY Cocoa)
find_library(APPKIT_LIBRARY AppKit)
-#find_library(FREERDP_LIBRARY NAMES MacFreeRDP PATHS ${CMAKE_CURRENT_BINARY_DIR}/../${CONFIGURATION})
set(MACOSX_BUNDLE_INFO_STRING "MacFreeRDP")
set(MACOSX_BUNDLE_ICON_FILE "FreeRDP.icns")
@@ -27,28 +26,32 @@ set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication")
mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY)
set(APP_TYPE MACOSX_BUNDLE)
-# OS X Interface Builder files
-file(GLOB ${MODULE_NAME}_XIBS *.xib)
+set(${MODULE_PREFIX}_XIBS MainMenu.xib)
-set(${MODULE_NAME}_RESOURCES ${MACOSX_BUNDLE_ICON_FILE})
+set(${MODULE_PREFIX}_SOURCES "")
+
+set(${MODULE_PREFIX}_OBJECTIVE_SOURCES
+ main.m
+ AppDelegate.m)
+
+list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES})
+
+set(${MODULE_PREFIX}_HEADERS
+ AppDelegate.h)
+
+set(${MODULE_PREFIX}_RESOURCES ${MACOSX_BUNDLE_ICON_FILE})
# Include XIB file in Xcode resources.
if("${CMAKE_GENERATOR}" MATCHES "Xcode")
message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}")
- set(${MODULE_NAME}_RESOURCES ${${MODULE_NAME}_RESOURCES} ${${MODULE_NAME}_XIBS})
-endif("${CMAKE_GENERATOR}" MATCHES "Xcode")
-
-# Headers
-file(GLOB ${MODULE_NAME}_HEADERS *.h)
-
-# Source
-file(GLOB ${MODULE_NAME}_SOURCES *.m)
+ set(${MODULE_PREFIX}_RESOURCES ${${MODULE_PREFIX}_RESOURCES} ${${MODULE_PREFIX}_XIBS})
+endif()
add_executable(${MODULE_NAME}
${APP_TYPE}
- ${${MODULE_NAME}_HEADERS}
- ${${MODULE_NAME}_SOURCES}
- ${${MODULE_NAME}_RESOURCES})
+ ${${MODULE_PREFIX}_HEADERS}
+ ${${MODULE_PREFIX}_SOURCES}
+ ${${MODULE_PREFIX}_RESOURCES})
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAME}")
@@ -56,14 +59,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAM
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
# This allows for automatic xib to nib ibitool
-set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_NAME}_RESOURCES}")
-
-# Automatic ref counting
-# temporary turn off for x86_64 build issue
-# set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
-
-# Support for automatic reference counting requires non-fragile abi.
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi")
+set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_PREFIX}_RESOURCES}")
# Tell the compiler where to look for the FreeRDP framework
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F../")
@@ -72,8 +68,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F../")
set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS
"${XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS} ${CMAKE_CURRENT_BINARY_DIR}/../$(CONFIGURATION)")
-set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)")
-
# Set the info plist to the custom instance
set_target_properties(${MODULE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
@@ -86,7 +80,7 @@ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Mac")
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND mkdir ARGS -p ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.app/Contents/Frameworks
COMMAND ditto ${CMAKE_CURRENT_BINARY_DIR}/../$(CONFIGURATION)/MacFreeRDP.framework ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.app/Contents/Frameworks/MacFreeRDP.framework
- COMMAND install_name_tool -change "@executable_path/../../Frameworks/MacFreeRDP.framework/Versions/1.1.0/MacFreeRDP"
+ COMMAND install_name_tool -change "@executable_path/../Frameworks/MacFreeRDP.framework/Versions/${MAC_OS_X_BUNDLE_BUNDLE_VERSION}/MacFreeRDP"
"@executable_path/../Frameworks/MacFreeRDP.framework/Versions/Current/MacFreeRDP"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.app/Contents/MacOS/${MODULE_NAME}"
COMMENT Setting install name for MacFreeRDP)
@@ -106,13 +100,13 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
add_custom_command(TARGET ${MODULE_NAME} PRE_BUILD COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${MODULE_OUTPUT_NAME}.app/Contents/Resources)
# Compile the .xib files using the 'ibtool' program with the destination being the app package
- foreach(xib ${${MODULE_NAME}_XIBS})
+ foreach(xib ${${MODULE_PREFIX}_XIBS})
get_filename_component(XIB_WE ${xib} NAME_WE)
add_custom_command (TARGET ${MODULE_NAME} POST_BUILD
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
- --compile ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${MODULE_OUTPUT_NAME}.app/Contents/Resources/${XIB_WE}.nib ${xib}
+ --compile ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${MODULE_OUTPUT_NAME}.app/Contents/Resources/${XIB_WE}.nib ${CMAKE_CURRENT_SOURCE_DIR}/${xib}
COMMENT "Compiling ${xib}")
endforeach()
-endif("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
+endif()
diff --git a/client/Mac/cli/MainMenu.xib b/client/Mac/cli/MainMenu.xib
index 90e992462..65e72b118 100755
--- a/client/Mac/cli/MainMenu.xib
+++ b/client/Mac/cli/MainMenu.xib
@@ -2,18 +2,16 @@
1070
- 12D78
+ 12E55
3084
- 1187.37
+ 1187.39
626.00
- IBNSLayoutConstraint
NSCustomObject
- NSCustomView
NSMenu
NSMenuItem
NSView
@@ -257,24 +255,12 @@
- {{0, 0}, {1440, 878}}
+ {{0, 0}, {1920, 1178}}
{1024, 790}
{1024, 790}
128
@@ -369,14 +355,6 @@
493
-
-
- mrdpView
-
-
-
- 569
-
window
@@ -551,73 +529,7 @@
372
-
-
-
-
- 6
- 0
-
- 6
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
-
- 5
- 0
-
- 5
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
-
- 4
- 0
-
- 4
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
-
- 3
- 0
-
- 3
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
+
@@ -657,31 +569,6 @@
-
- 551
-
-
-
-
- 561
-
-
-
-
- 562
-
-
-
-
- 563
-
-
-
-
- 564
-
-
-
@@ -706,12 +593,6 @@
com.apple.InterfaceBuilder.CocoaPlugin
{{380, 496}, {480, 360}}
-
-
-
-
-
-
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -720,13 +601,7 @@
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
-
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -738,48 +613,7 @@
570
-
-
-
- AppDelegate
- NSObject
-
- MRDPView
- NSWindow
-
-
-
- mrdpView
- MRDPView
-
-
- window
- NSWindow
-
-
-
- IBProjectSource
- ./Classes/AppDelegate.h
-
-
-
- MRDPView
- NSView
-
- IBProjectSource
- ./Classes/MRDPView.h
-
-
-
- NSLayoutConstraint
- NSObject
-
- IBProjectSource
- ./Classes/NSLayoutConstraint.h
-
-
-
-
+
0
IBCocoaFramework
diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m
index 20aa3ce01..cf830d3c7 100755
--- a/client/Mac/mf_client.m
+++ b/client/Mac/mf_client.m
@@ -25,6 +25,7 @@
#include
#include
#include
+#import "MRDPView.h"
/**
* Client Interface
@@ -46,6 +47,13 @@ int mfreerdp_client_start(rdpContext* context)
MRDPView* view;
mfContext* mfc = (mfContext*) context;
+ if (mfc->view == NULL)
+ {
+ // view not specified beforehand. Create view dynamically
+ mfc->view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
+ mfc->view_ownership = TRUE;
+ }
+
view = (MRDPView*) mfc->view;
[view rdpStart:context];
@@ -60,19 +68,40 @@ int mfreerdp_client_stop(rdpContext* context)
{
wMessageQueue* queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE);
- MessageQueue_PostQuit(queue, 0);
+ if (queue)
+ {
+ MessageQueue_PostQuit(queue, 0);
+ }
}
-
- if (context->settings->AsyncInput)
+ else if (context->settings->AsyncInput)
{
wMessageQueue* queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
- MessageQueue_PostQuit(queue, 0);
- }
+ if (queue)
+ {
+ MessageQueue_PostQuit(queue, 0);
+ }
+ }
else
{
mfc->disconnect = TRUE;
}
+
+ if (mfc->thread)
+ {
+ SetEvent(mfc->stopEvent);
+ WaitForSingleObject(mfc->thread, INFINITE);
+ CloseHandle(mfc->thread);
+ mfc->thread = NULL;
+ }
+
+ if (mfc->view_ownership)
+ {
+ MRDPView* view = (MRDPView*) mfc->view;
+ [view releaseResources];
+ [view release];
+ mfc->view = nil;
+ }
return 0;
}
@@ -84,12 +113,19 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
mfc = (mfContext*) instance->context;
- context->channels = freerdp_channels_new();
+ mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ context->instance->PreConnect = mac_pre_connect;
+ context->instance->PostConnect = mac_post_connect;
+ context->instance->ReceiveChannelData = mac_receive_channel_data;
+ context->instance->Authenticate = mac_authenticate;
+
+ context->channels = freerdp_channels_new();
settings = instance->settings;
- settings->AsyncUpdate = TRUE;
- // TODO settings->AsyncInput = TRUE;
+ settings->AsyncUpdate = TRUE;
+ settings->AsyncInput = TRUE;
settings->AsyncChannels = TRUE;
settings->AsyncTransport = TRUE;
settings->RedirectClipboard = TRUE;
diff --git a/client/Mac/mfreerdp.h b/client/Mac/mfreerdp.h
index 02b0272e2..52e7be122 100644
--- a/client/Mac/mfreerdp.h
+++ b/client/Mac/mfreerdp.h
@@ -28,6 +28,7 @@ struct mf_context
DEFINE_RDP_CLIENT_COMMON();
void* view;
+ BOOL view_ownership; // TRUE indicates that the window was created and should be freed by the API.
int width;
int height;
@@ -43,6 +44,7 @@ struct mf_context
int client_height;
HANDLE keyboardThread;
+ HANDLE stopEvent;
HGDI_DC hdc;
UINT16 srcBpp;
diff --git a/client/Windows/CMakeLists.txt b/client/Windows/CMakeLists.txt
index 0f2b26d65..f32422cd3 100644
--- a/client/Windows/CMakeLists.txt
+++ b/client/Windows/CMakeLists.txt
@@ -63,8 +63,10 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(WITH_CLIENT_INTERFACE)
+ if (NOT WITH_WAYK)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
add_subdirectory(cli)
+ endif()
else()
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
endif()
diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c
index 41fae28d0..15e9b4363 100644
--- a/client/Windows/wf_gdi.c
+++ b/client/Windows/wf_gdi.c
@@ -575,14 +575,14 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
/* blit each tile */
- for (i = 0; i < message->num_tiles; i++)
+ for (i = 0; i < message->numTiles; i++)
{
tx = message->tiles[i]->x + surface_bits_command->destLeft;
ty = message->tiles[i]->y + surface_bits_command->destTop;
freerdp_image_convert(message->tiles[i]->data, wfc->tile->pdata, 64, 64, 32, 32, wfc->clrconv);
- for (j = 0; j < message->num_rects; j++)
+ for (j = 0; j < message->numRects; j++)
{
wf_set_clip_rgn(wfc,
surface_bits_command->destLeft + message->rects[j].x,
@@ -596,7 +596,7 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
wf_set_null_clip_rgn(wfc);
/* invalidate regions */
- for (i = 0; i < message->num_rects; i++)
+ for (i = 0; i < message->numRects; i++)
{
tx = surface_bits_command->destLeft + message->rects[i].x;
ty = surface_bits_command->destTop + message->rects[i].y;
@@ -618,7 +618,7 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
bitmap_info.bmiHeader.biCompression = BI_RGB;
SetDIBitsToDevice(wfc->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop,
surface_bits_command->width, surface_bits_command->height, 0, 0, 0, surface_bits_command->height,
- nsc_context->bmpdata, &bitmap_info, DIB_RGB_COLORS);
+ nsc_context->BitmapData, &bitmap_info, DIB_RGB_COLORS);
wf_invalidate_region(wfc, surface_bits_command->destLeft, surface_bits_command->destTop,
surface_bits_command->width, surface_bits_command->height);
}
@@ -664,8 +664,8 @@ void wf_gdi_register_update_callbacks(rdpUpdate* update)
{
rdpPrimaryUpdate* primary = update->primary;
- update->Palette = wf_gdi_palette_update;
- update->SetBounds = wf_gdi_set_bounds;
+ update->Palette = (pPalette) wf_gdi_palette_update;
+ update->SetBounds = (pSetBounds) wf_gdi_set_bounds;
primary->DstBlt = (pDstBlt) wf_gdi_dstblt;
primary->PatBlt = (pPatBlt) wf_gdi_patblt;
@@ -690,8 +690,8 @@ void wf_gdi_register_update_callbacks(rdpUpdate* update)
primary->EllipseSC = NULL;
primary->EllipseCB = NULL;
- update->SurfaceBits = wf_gdi_surface_bits;
- update->SurfaceFrameMarker = wf_gdi_surface_frame_marker;
+ update->SurfaceBits = (pSurfaceBits) wf_gdi_surface_bits;
+ update->SurfaceFrameMarker = (pSurfaceFrameMarker) wf_gdi_surface_frame_marker;
}
void wf_update_canvas_diff(wfContext* wfc)
diff --git a/client/X11/.gitignore b/client/X11/.gitignore
new file mode 100644
index 000000000..de7ef2209
--- /dev/null
+++ b/client/X11/.gitignore
@@ -0,0 +1,2 @@
+*.xml
+generate_argument_docbook
diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt
index 56dd96bdb..907200733 100644
--- a/client/X11/CMakeLists.txt
+++ b/client/X11/CMakeLists.txt
@@ -2,6 +2,7 @@
# FreeRDP X11 Client
#
# Copyright 2012 Marc-Andre Moreau
+# Copyright 2013 Corey Clayton
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,7 +19,7 @@
set(MODULE_NAME "xfreerdp-client")
set(MODULE_PREFIX "FREERDP_CLIENT_X11_CONTROL")
-include(FindXmlto)
+include(FindDocBookXSL)
include_directories(${X11_INCLUDE_DIRS})
set(${MODULE_PREFIX}_SRCS
@@ -28,6 +29,8 @@ set(${MODULE_PREFIX}_SRCS
xf_rail.h
xf_tsmf.c
xf_tsmf.h
+ xf_input.c
+ xf_input.h
xf_event.c
xf_event.h
xf_input.c
@@ -65,18 +68,55 @@ set(${MODULE_PREFIX}_LIBS
${CMAKE_DL_LIBS})
if(WITH_MANPAGES)
- if(XMLTO_FOUND)
+ find_program( XSLTPROC_EXECUTABLE NAMES xsltproc)
+
+ if(DOCBOOKXSL_FOUND AND XSLTPROC_EXECUTABLE)
+
+ # We need the variable ${MAN_TODAY} to contain the current date in ISO
+ # format to replace it in the configure_file step.
+ include(today)
+
+ TODAY(MAN_TODAY)
+
+ configure_file(xfreerdp.1.xml.in xfreerdp.1.xml @ONLY IMMEDIATE)
+
+ add_executable(generate_argument_docbook generate_argument_docbook.c)
+
+ set(GAD_LIBS freerdp-client)
+
+ set_complex_link_libraries(VARIABLE GAD_LIBS MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE winpr
+ MODULES winpr-utils)
+
+ set_complex_link_libraries(VARIABLE GAD_LIBS MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE freerdp
+ MODULES freerdp-core freerdp-utils)
+
+ message(WARNING "GAD_LIBS: ${GAD_LIBS}")
+
+ target_link_libraries(generate_argument_docbook ${GAD_LIBS})
+
add_custom_command(OUTPUT xfreerdp.1
- COMMAND ${XMLTO_EXECUTABLE} man ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp.1.xml
- DEPENDS xfreerdp.1.xml)
+ COMMAND generate_argument_docbook
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${XSLTPROC_EXECUTABLE} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl xfreerdp.1.xml
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS
+ ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml
+ generate_argument_docbook)
add_custom_target(xfreerdp.manpage ALL
DEPENDS xfreerdp.1)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1 DESTINATION share/man/man1)
- else(XMLTO_FOUND)
- message(WARNING "WITH_MANPAGES was set, but xmlto was not found. man-pages will not be installed")
- endif(XMLTO_FOUND)
+ else()
+ message(WARNING "WITH_MANPAGES was set, but xsltproc was not found. man-pages will not be installed")
+ endif()
endif(WITH_MANPAGES)
set(XSHM_FEATURE_TYPE "REQUIRED")
@@ -101,11 +141,11 @@ set(XV_FEATURE_DESCRIPTION "X11 video extension")
set(XI_FEATURE_TYPE "RECOMMENDED")
set(XI_FEATURE_PURPOSE "input")
-set(XI_FEATURE_DESCRIPTION "X11 input extension")
+set(XI_FEATURE_DESCRIPTION "X11 input extension")
set(XRENDER_FEATURE_TYPE "RECOMMENDED")
set(XRENDER_FEATURE_PURPOSE "rendering")
-set(XRENDER_FEATURE_DESCRIPTION "X11 render extension")
+set(XRENDER_FEATURE_DESCRIPTION "X11 render extension")
find_feature(XShm ${XSHM_FEATURE_TYPE} ${XSHM_FEATURE_PURPOSE} ${XSHM_FEATURE_DESCRIPTION})
find_feature(Xinerama ${XINERAMA_FEATURE_TYPE} ${XINERAMA_FEATURE_PURPOSE} ${XINERAMA_FEATURE_DESCRIPTION})
diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c
new file mode 100644
index 000000000..0c1da21a8
--- /dev/null
+++ b/client/X11/generate_argument_docbook.c
@@ -0,0 +1,177 @@
+
+#include
+#include
+#include
+
+#include
+
+/* We need to include the command line c file to get access to
+ * the argument struct. */
+#include "../common/cmdline.c"
+
+LPSTR tmp = NULL;
+
+LPCSTR tr_esc_str(LPCSTR arg)
+{
+ size_t cs = 0, x, ds;
+ size_t s;
+
+ if( NULL == arg )
+ return NULL;
+
+ s = strlen(arg);
+
+ /* Find trailing whitespaces */
+ while( (s > 0) && isspace(arg[s-1]))
+ s--;
+
+ /* Prepare a initial buffer with the size of the result string. */
+ tmp = malloc(s * sizeof(LPCSTR));
+ if( NULL == tmp )
+ {
+ fprintf(stderr, "Could not allocate string buffer.");
+ exit(-2);
+ }
+
+ /* Copy character for character and check, if it is necessary to escape. */
+ ds = s + 1;
+ for(x=0; x':
+ ds += 3;
+ tmp = realloc(tmp, ds * sizeof(LPCSTR));
+ if( NULL == tmp )
+ {
+ fprintf(stderr, "Could not reallocate string buffer.");
+ exit(-4);
+ }
+ tmp[cs++] = '&';
+ tmp[cs++] = 'g';
+ tmp[cs++] = 't';
+ tmp[cs++] = ';';
+ break;
+ case '\'':
+ ds += 5;
+ tmp = realloc(tmp, ds * sizeof(LPCSTR));
+ if( NULL == tmp )
+ {
+ fprintf(stderr, "Could not reallocate string buffer.");
+ exit(-5);
+ }
+ tmp[cs++] = '&';
+ tmp[cs++] = 'a';
+ tmp[cs++] = 'p';
+ tmp[cs++] = 'o';
+ tmp[cs++] = 's';
+ tmp[cs++] = ';';
+ break;
+ case '"':
+ ds += 5;
+ tmp = realloc(tmp, ds * sizeof(LPCSTR));
+ if( NULL == tmp )
+ {
+ fprintf(stderr, "Could not reallocate string buffer.");
+ exit(-6);
+ }
+ tmp[cs++] = '&';
+ tmp[cs++] = 'q';
+ tmp[cs++] = 'u';
+ tmp[cs++] = 'o';
+ tmp[cs++] = 't';
+ tmp[cs++] = ';';
+ break;
+ case '&':
+ ds += 4;
+ tmp = realloc(tmp, ds * sizeof(LPCSTR));
+ if( NULL == tmp )
+ {
+ fprintf(stderr, "Could not reallocate string buffer.");
+ exit(-7);
+ }
+ tmp[cs++] = '&';
+ tmp[cs++] = 'a';
+ tmp[cs++] = 'm';
+ tmp[cs++] = 'p';
+ tmp[cs++] = ';';
+ break;
+ default:
+ tmp[cs++] = arg[x];
+ break;
+ }
+
+ /* Assure, the string is '\0' terminated. */
+ tmp[ds-1] = '\0';
+ }
+
+ return tmp;
+}
+
+int main(int argc, char *argv[])
+{
+ size_t elements = sizeof(args)/sizeof(args[0]);
+ size_t x;
+ const char *fname = "xfreerdp-argument.1.xml";
+ FILE *fp = NULL;
+
+ /* Open output file for writing, truncate if existing. */
+ fp = fopen(fname, "w");
+ if( NULL == fp )
+ {
+ fprintf(stderr, "Could not open '%s' for writing.", fname);
+ return -1;
+ }
+
+ /* The tag used as header in the manpage */
+ fprintf(fp, "\n");
+ fprintf(fp, "\tOptions\n");
+ fprintf(fp, "\t\t\n");
+
+ /* Iterate over argument struct and write data to docbook 4.5
+ * compatible XML */
+ if( elements < 2 )
+ {
+ fprintf(stderr, "The argument array 'args' is empty, writing an empty file.");
+ elements = 1;
+ }
+
+ for(x=0; x\n");
+ if( COMMAND_LINE_VALUE_REQUIRED == arg->Flags )
+ fprintf(fp, "\t\t\t\t %s\n", tr_esc_str(arg->Name), tr_esc_str(arg->Format) );
+ else
+ fprintf(fp, "\t\t\t\t\n", tr_esc_str(arg->Name) );
+ fprintf(fp, "\t\t\t\t\n");
+ fprintf(fp, "\t\t\t\t\t%s\n", tr_esc_str(arg->Text));
+
+ fprintf(fp, "\t\t\t\t\n");
+ fprintf(fp, "\t\t\t\n");
+ }
+
+ fprintf(fp, "\t\t\n");
+ fprintf(fp, "\t\n");
+ fclose(fp);
+
+ if(NULL != tmp)
+ free(tmp);
+
+ return 0;
+}
+
diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c
index 91dda0b8e..24325046e 100644
--- a/client/X11/xf_channels.c
+++ b/client/X11/xf_channels.c
@@ -26,19 +26,17 @@
#include "xf_client.h"
#include "xfreerdp.h"
-int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface)
+void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
{
- xfContext* xfc = (xfContext*) instance->context;
+ xfContext* xfc = (xfContext*) context;
- if (strcmp(name, RDPEI_DVC_CHANNEL_NAME) == 0)
+ if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
- xfc->rdpei = (RdpeiClientContext*) pInterface;
+ xfc->rdpei = (RdpeiClientContext*) e->pInterface;
}
-
- return 0;
}
-int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface)
+void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
{
- return 0;
+
}
diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h
index 1aeaf1a66..bb52d5e52 100644
--- a/client/X11/xf_channels.h
+++ b/client/X11/xf_channels.h
@@ -27,4 +27,7 @@
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);
+void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e);
+void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e);
+
#endif
diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c
index 7e958feeb..5ad3f4f04 100644
--- a/client/X11/xf_client.c
+++ b/client/X11/xf_client.c
@@ -3,6 +3,7 @@
* X11 Client Interface
*
* Copyright 2013 Marc-Andre Moreau
+ * Copyright 2013 Corey Clayton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +25,14 @@
#include
#include
+#ifdef WITH_XRENDER
+#include
+#endif
+
+#ifdef WITH_XI
+#include
+#endif
+
#ifdef WITH_XCURSOR
#include
#endif
@@ -73,6 +82,7 @@
#include
#include
#include
+#include
#include "xf_gdi.h"
#include "xf_rail.h"
@@ -83,14 +93,51 @@
#include "xf_monitor.h"
#include "xf_graphics.h"
#include "xf_keyboard.h"
+#include "xf_input.h"
#include "xf_channels.h"
-
#include "xfreerdp.h"
static long xv_port = 0;
static const size_t password_size = 512;
-void xf_draw_screen_scaled(xfContext* xfc)
+void xf_transform_window(xfContext* xfc)
+{
+ int ret;
+ int w;
+ int h;
+ long supplied;
+ Atom hints_atom;
+ XSizeHints* size_hints = NULL;
+
+ hints_atom = XInternAtom(xfc->display, "WM_SIZE_HINTS", 1);
+
+ ret = XGetWMSizeHints(xfc->display, xfc->window->handle, size_hints, &supplied, hints_atom);
+
+ if(ret == 0)
+ size_hints = XAllocSizeHints();
+
+ w = (xfc->originalWidth * xfc->settings->ScalingFactor) + xfc->offset_x;
+ h = (xfc->originalHeight * xfc->settings->ScalingFactor) + xfc->offset_y;
+
+ if(w < 1)
+ w = 1;
+
+ if(h < 1)
+ h = 1;
+
+ if (size_hints)
+ {
+ size_hints->flags |= PMinSize | PMaxSize;
+ size_hints->min_width = size_hints->max_width = w;
+ size_hints->min_height = size_hints->max_height = h;
+ XSetWMNormalHints(xfc->display, xfc->window->handle, size_hints);
+ XResizeWindow(xfc->display, xfc->window->handle, w, h);
+
+ XFree(size_hints);
+ }
+}
+
+void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale)
{
#ifdef WITH_XRENDER
XTransform transform;
@@ -98,6 +145,7 @@ void xf_draw_screen_scaled(xfContext* xfc)
Picture primaryPicture;
XRenderPictureAttributes pa;
XRenderPictFormat* picFormat;
+ XRectangle xr;
picFormat = XRenderFindStandardFormat(xfc->display, PictStandardRGB24);
pa.subwindow_mode = IncludeInferiors;
@@ -114,11 +162,38 @@ void xf_draw_screen_scaled(xfContext* xfc)
transform.matrix[2][0] = XDoubleToFixed(0);
transform.matrix[2][1] = XDoubleToFixed(0);
- transform.matrix[2][2] = XDoubleToFixed(xfc->scale);
+ transform.matrix[2][2] = XDoubleToFixed(xfc->settings->ScalingFactor);
+
+ if( (w != 0) && (h != 0) )
+ {
+
+ if(scale == TRUE)
+ {
+ xr.x = x * xfc->settings->ScalingFactor;
+ xr.y = y * xfc->settings->ScalingFactor;
+ xr.width = (w+1) * xfc->settings->ScalingFactor;
+ xr.height = (h+1) * xfc->settings->ScalingFactor;
+ }
+ else
+ {
+ xr.x = x;
+ xr.y = y;
+ xr.width = w;
+ xr.height = h;
+ }
+
+ XRenderSetPictureClipRectangles(xfc->display, primaryPicture, 0, 0, &xr, 1);
+ }
XRenderSetPictureTransform(xfc->display, primaryPicture, &transform);
- XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, 0, 0, xfc->currentWidth, xfc->currentHeight);
+
+ XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, xfc->offset_x, xfc->offset_y, xfc->currentWidth, xfc->currentHeight);
+
+ XRenderFreePicture(xfc->display, primaryPicture);
+ XRenderFreePicture(xfc->display, windowPicture);
+
#endif
+
}
void xf_sw_begin_paint(rdpContext* context)
@@ -153,9 +228,9 @@ void xf_sw_end_paint(rdpContext* context)
XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h);
- if (xfc->scale != 1.0)
+ if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
{
- xf_draw_screen_scaled(xfc);
+ xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
else
{
@@ -184,12 +259,13 @@ void xf_sw_end_paint(rdpContext* context)
y = cinvalid[i].y;
w = cinvalid[i].w;
h = cinvalid[i].h;
-
+
+ //combine xfc->primary with xfc->image
XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h);
- if (xfc->scale != 1.0)
+ if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
{
- xf_draw_screen_scaled(xfc);
+ xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
else
{
@@ -271,12 +347,12 @@ void xf_hw_end_paint(rdpContext* context)
y = xfc->hdc->hwnd->invalid->y;
w = xfc->hdc->hwnd->invalid->w;
h = xfc->hdc->hwnd->invalid->h;
-
+
xf_lock_x11(xfc, FALSE);
- if (xfc->scale != 1.0)
+ if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
{
- xf_draw_screen_scaled(xfc);
+ xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
else
{
@@ -305,10 +381,10 @@ void xf_hw_end_paint(rdpContext* context)
y = cinvalid[i].y;
w = cinvalid[i].w;
h = cinvalid[i].h;
-
- if (xfc->scale != 1.0)
+
+ if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
{
- xf_draw_screen_scaled(xfc);
+ xf_draw_screen_scaled(xfc, x, y, w, h, TRUE);
}
else
{
@@ -666,8 +742,11 @@ BOOL xf_pre_connect(freerdp* instance)
settings = instance->settings;
channels = instance->context->channels;
- instance->OnChannelConnected = xf_on_channel_connected;
- instance->OnChannelDisconnected = xf_on_channel_disconnected;
+ PubSub_SubscribeChannelConnected(instance->context->pubSub,
+ (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler);
+
+ PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
+ (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler);
freerdp_client_load_addins(channels, instance->settings);
@@ -829,7 +908,10 @@ BOOL xf_post_connect(freerdp* instance)
xfc->originalHeight = settings->DesktopHeight;
xfc->currentWidth = xfc->originalWidth;
xfc->currentHeight = xfc->originalWidth;
- xfc->scale = 1.0;
+ xfc->settings->ScalingFactor = 1.0;
+
+ xfc->offset_x = 0;
+ xfc->offset_y = 0;
xfc->width = settings->DesktopWidth;
xfc->height = settings->DesktopHeight;
@@ -1480,6 +1562,8 @@ void* xf_thread(void* param)
gdi_free(instance);
ExitThread(exit_code);
+
+ return NULL;
}
DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
@@ -1520,6 +1604,66 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
}
}
+void xf_ParamChangeEventHandler(rdpContext* context, ParamChangeEventArgs* e)
+{
+
+ xfContext* xfc = (xfContext*) context;
+
+ switch (e->id)
+ {
+ case FreeRDP_ScalingFactor:
+
+ xfc->currentWidth = xfc->originalWidth * xfc->settings->ScalingFactor;
+ xfc->currentHeight = xfc->originalHeight * xfc->settings->ScalingFactor;
+
+ xf_transform_window(xfc);
+
+ {
+ ResizeWindowEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
+ e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
+ PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+ xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
+{
+ xfContext* xfc = (xfContext*) context;
+
+ xfc->settings->ScalingFactor += e->ScalingFactor;
+
+ if (xfc->settings->ScalingFactor > 1.2)
+ xfc->settings->ScalingFactor = 1.2;
+ if (xfc->settings->ScalingFactor < 0.8)
+ xfc->settings->ScalingFactor = 0.8;
+
+
+ xfc->currentWidth = xfc->originalWidth * xfc->settings->ScalingFactor;
+ xfc->currentHeight = xfc->originalHeight * xfc->settings->ScalingFactor;
+
+ xf_transform_window(xfc);
+
+ {
+ ResizeWindowEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
+ e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
+ PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+ xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
+
+}
+
/**
* Client Interface
*/
@@ -1573,28 +1717,6 @@ int xfreerdp_client_stop(rdpContext* context)
return 0;
}
-double freerdp_client_get_scale(rdpContext* context)
-{
- xfContext* xfc = (xfContext*) context;
- return xfc->scale;
-}
-
-void freerdp_client_reset_scale(rdpContext* context)
-{
- ResizeWindowEventArgs e;
- xfContext* xfc = (xfContext*) context;
-
- xfc->scale = 1.0;
- XResizeWindow(xfc->display, xfc->window->handle, xfc->originalWidth * xfc->scale, xfc->originalHeight * xfc->scale);
-
- EventArgsInit(&e, "xfreerdp");
- e.width = (int) xfc->originalWidth * xfc->scale;
- e.height = (int) xfc->originalHeight * xfc->scale;
- PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
-
- xf_draw_screen_scaled(xfc);
-}
-
int xfreerdp_client_new(freerdp* instance, rdpContext* context)
{
xfContext* xfc;
@@ -1643,6 +1765,9 @@ int xfreerdp_client_new(freerdp* instance, rdpContext* context)
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler);
+ PubSub_SubscribeParamChange(context->pubSub, (pParamChangeEventHandler) xf_ParamChangeEventHandler);
+ PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
+
return 0;
}
diff --git a/client/X11/xf_client.h b/client/X11/xf_client.h
index 604e46700..dec4876f2 100644
--- a/client/X11/xf_client.h
+++ b/client/X11/xf_client.h
@@ -44,6 +44,7 @@ extern "C" {
* Client Interface
*/
+
FREERDP_API int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints);
#ifdef __cplusplus
diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c
index bf64b63b4..7205a7b67 100644
--- a/client/X11/xf_event.c
+++ b/client/X11/xf_event.c
@@ -32,6 +32,7 @@
#include "xf_input.h"
#include "xf_event.h"
+#include "xf_input.h"
const char* const X11_EVENT_STRINGS[] =
{
@@ -88,22 +89,24 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
{
int x, y;
int w, h;
-
+
x = event->xexpose.x;
y = event->xexpose.y;
w = event->xexpose.width;
h = event->xexpose.height;
-
+
if (!app)
{
- if (xfc->scale != 1.0)
+ if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
- xf_draw_screen_scaled(xfc);
+ xf_draw_screen_scaled(xfc, x - xfc->offset_x,
+ y - xfc->offset_y, w, h, FALSE);
}
else
{
XCopyArea(xfc->display, xfc->primary,
- xfc->window->handle, xfc->gc, x, y, w, h, x, y);
+ xfc->window->handle, xfc->gc, x, y, w,
+ h, x, y);
}
}
else
@@ -111,16 +114,17 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
xfWindow* xfw;
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfc)->rail;
-
- window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
-
- if (window != NULL)
+
+ window = window_list_get_by_extra_id(rail->list,
+ (void*) event->xexpose.window);
+
+ if (window)
{
xfw = (xfWindow*) window->extra;
xf_UpdateWindowArea(xfc, xfw, x, y, w, h);
}
}
-
+
return TRUE;
}
@@ -156,12 +160,12 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
RootWindowOfScreen(xfc->screen),
x, y, &x, &y, &childWindow);
}
-
- if (xfc->scale != 1.0)
+
+ /* Take scaling in to consideration */
+ if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
{
- /* Take scaling in to consideration */
- x = (int) (x * (1.0 / xfc->scale));
- y = (int) (y * (1.0 / xfc->scale));
+ x = (int)((x - xfc->offset_x) * (1.0 / xfc->settings->ScalingFactor) );
+ y = (int)((y - xfc->offset_y) * (1.0 / xfc->settings->ScalingFactor) );
}
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
@@ -176,6 +180,9 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app)
{
+ if (xfc->use_xinput)
+ return TRUE;
+
return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y,
event->xmotion.state, event->xmotion.window, app);
}
@@ -257,13 +264,16 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window win
XTranslateCoordinates(xfc->display, window,
RootWindowOfScreen(xfc->screen),
x, y, &x, &y, &childWindow);
+
}
- if (xfc->scale != 1.0)
+ if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x)
+ || (xfc->offset_y))
{
- /* Take scaling in to consideration */
- x = (int) (x * (1.0 / xfc->scale));
- y = (int) (y * (1.0 / xfc->scale));
+ x = (int) ((x - xfc->offset_x)
+ * (1.0 / xfc->settings->ScalingFactor));
+ y = (int) ((y - xfc->offset_y)
+ * (1.0 / xfc->settings->ScalingFactor));
}
if (extended)
@@ -278,6 +288,9 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window win
static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app)
{
+ if (xfc->use_xinput)
+ return TRUE;
+
return xf_generic_ButtonPress(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
}
@@ -290,6 +303,7 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w
rdpInput* input;
Window childWindow;
+
flags = 0;
wheel = FALSE;
extended = FALSE;
@@ -343,11 +357,11 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w
x, y, &x, &y, &childWindow);
}
- if (xfc->scale != 1.0)
+
+ if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
- /* Take scaling in to consideration */
- x = (int) (x * (1.0 / xfc->scale));
- y = (int) (y * (1.0 / xfc->scale));
+ x = (int) ((x - xfc->offset_x) * (1.0 / xfc->settings->ScalingFactor));
+ y = (int) ((y - xfc->offset_y) * (1.0 / xfc->settings->ScalingFactor));
}
if (extended)
@@ -361,6 +375,9 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w
static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app)
{
+ if (xfc->use_xinput)
+ return TRUE;
+
return xf_generic_ButtonRelease(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
}
@@ -542,15 +559,18 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app)
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfc)->rail;
+
+/* This is for resizing the window by dragging the border
+
if (xfc->width != event->xconfigure.width)
{
- xfc->scale = (double) event->xconfigure.width / (double) xfc->originalWidth;
+ xfc->settings->ScalingFactor = (double) event->xconfigure.width / (double) xfc->originalWidth;
xfc->currentWidth = event->xconfigure.width;
xfc->currentHeight = event->xconfigure.width;
xf_draw_screen_scaled(xfc);
}
-
+*/
window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
if (window != NULL)
@@ -568,6 +588,9 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app)
RootWindowOfScreen(xfc->screen),
0, 0, &xfw->left, &xfw->top, &childWindow);
+
+
+
xfw->width = event->xconfigure.width;
xfw->height = event->xconfigure.height;
xfw->right = xfw->left + xfw->width - 1;
@@ -926,7 +949,6 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
case MotionNotify:
status = xf_event_MotionNotify(xfc, event, xfc->remote_app);
break;
-
case ButtonPress:
status = xf_event_ButtonPress(xfc, event, xfc->remote_app);
break;
@@ -1003,6 +1025,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
case PropertyNotify:
status = xf_event_PropertyNotify(xfc, event, xfc->remote_app);
break;
+
}
xf_input_handle_event(xfc, event);
diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c
index acdc0da47..158c61778 100644
--- a/client/X11/xf_gdi.c
+++ b/client/X11/xf_gdi.c
@@ -950,10 +950,10 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
XSetClipRectangles(xfc->display, xfc->gc,
surface_bits_command->destLeft, surface_bits_command->destTop,
- (XRectangle*) message->rects, message->num_rects, YXBanded);
+ (XRectangle*) message->rects, message->numRects, YXBanded);
/* Draw the tiles to primary surface, each is 64x64. */
- for (i = 0; i < message->num_tiles; i++)
+ for (i = 0; i < message->numTiles; i++)
{
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) message->tiles[i]->data, 64, 64, 32, 0);
@@ -966,7 +966,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
}
/* Copy the updated region from backstore to the window. */
- for (i = 0; i < message->num_rects; i++)
+ for (i = 0; i < message->numRects; i++)
{
tx = message->rects[i].x + surface_bits_command->destLeft;
ty = message->rects[i].y + surface_bits_command->destTop;
@@ -988,7 +988,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc,
surface_bits_command->width * surface_bits_command->height * 4);
- freerdp_image_flip(nsc_context->bmpdata, xfc->bmp_codec_nsc,
+ freerdp_image_flip(nsc_context->BitmapData, xfc->bmp_codec_nsc,
surface_bits_command->width, surface_bits_command->height, 32);
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c
index 96fbf974d..b3e296966 100644
--- a/client/X11/xf_graphics.c
+++ b/client/X11/xf_graphics.c
@@ -131,7 +131,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
RFX_MESSAGE* msg;
xfContext* xfc = (xfContext*) context;
- size = width * height * (bpp + 7) / 8;
+ size = width * height * ((bpp + 7) / 8);
if (bitmap->data == NULL)
bitmap->data = (BYTE*) malloc(size);
@@ -255,7 +255,7 @@ void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
xf_lock_x11(xfc, FALSE);
- if (((xfPointer*) pointer)->cursor != 0)
+ if (((xfPointer*) pointer)->cursor)
XFreeCursor(xfc->display, ((xfPointer*) pointer)->cursor);
xf_unlock_x11(xfc, FALSE);
@@ -269,10 +269,12 @@ void xf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
xf_lock_x11(xfc, FALSE);
+ xfc->pointer = (xfPointer*) pointer;
+
/* in RemoteApp mode, window can be null if none has had focus */
- if (xfc->window != NULL)
- XDefineCursor(xfc->display, xfc->window->handle, ((xfPointer*) pointer)->cursor);
+ if (xfc->window)
+ XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
xf_unlock_x11(xfc, FALSE);
#endif
@@ -299,7 +301,9 @@ void xf_Pointer_SetNull(rdpContext* context)
nullcursor = XcursorImageLoadCursor(xfc->display, &ci);
}
- if (xfc->window != NULL && nullcursor != None)
+ xfc->pointer = NULL;
+
+ if ((xfc->window) && (nullcursor != None))
XDefineCursor(xfc->display, xfc->window->handle, nullcursor);
xf_unlock_x11(xfc, FALSE);
@@ -313,7 +317,9 @@ void xf_Pointer_SetDefault(rdpContext* context)
xf_lock_x11(xfc, FALSE);
- if (xfc->window != NULL)
+ xfc->pointer = NULL;
+
+ if (xfc->window)
XUndefineCursor(xfc->display, xfc->window->handle);
xf_unlock_x11(xfc, FALSE);
diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c
index 4b7309821..7f19d4ba3 100644
--- a/client/X11/xf_input.c
+++ b/client/X11/xf_input.c
@@ -21,6 +21,13 @@
#include "config.h"
#endif
+#include
+#include
+
+#ifdef WITH_XCURSOR
+#include
+#endif
+
#ifdef WITH_XI
#include
#endif
@@ -28,13 +35,17 @@
#include
#include "xf_event.h"
-
#include "xf_input.h"
#ifdef WITH_XI
#define MAX_CONTACTS 2
+#define PAN_THRESHOLD 50
+#define ZOOM_THRESHOLD 10
+
+#define MIN_FINGER_DIST 5
+
typedef struct touch_contact
{
int id;
@@ -43,16 +54,21 @@ typedef struct touch_contact
double pos_y;
double last_x;
double last_y;
-
+
} touchContact;
touchContact contacts[MAX_CONTACTS];
int active_contacts;
+int lastEvType;
XIDeviceEvent lastEvent;
double firstDist = -1.0;
double lastDist;
+
double z_vector;
+double px_vector;
+double py_vector;
+
int xinput_opcode;
int scale_cnt;
@@ -68,10 +84,11 @@ const char* xf_input_get_class_string(int class)
return "XIScrollClass";
else if (class == XITouchClass)
return "XITouchClass";
-
+
return "XIUnknownClass";
}
+
int xf_input_init(xfContext* xfc, Window window)
{
int i, j;
@@ -84,87 +101,94 @@ int xf_input_init(xfContext* xfc, Window window)
XIEventMask evmasks[64];
int opcode, event, error;
BYTE masks[8][XIMaskLen(XI_LASTEVENT)];
-
+
+ z_vector = 0;
+ px_vector = 0;
+ py_vector = 0;
+
nmasks = 0;
ndevices = 0;
active_contacts = 0;
ZeroMemory(contacts, sizeof(touchContact) * MAX_CONTACTS);
-
+
if (!XQueryExtension(xfc->display, "XInputExtension", &opcode, &event, &error))
{
printf("XInput extension not available.\n");
return -1;
}
-
+
xfc->XInputOpcode = opcode;
-
+
XIQueryVersion(xfc->display, &major, &minor);
-
+
if (major * 1000 + minor < 2002)
{
printf("Server does not support XI 2.2\n");
return -1;
}
-
+
if (xfc->settings->MultiTouchInput)
xfc->use_xinput = TRUE;
-
+
info = XIQueryDevice(xfc->display, XIAllDevices, &ndevices);
-
+
for (i = 0; i < ndevices; i++)
{
BOOL touch = FALSE;
XIDeviceInfo* dev = &info[i];
-
+
for (j = 0; j < dev->num_classes; j++)
{
XIAnyClassInfo* class = dev->classes[j];
XITouchClassInfo* t = (XITouchClassInfo*) class;
-
+
if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) &&
- (strcmp(dev->name, "Virtual core pointer") != 0))
+ (strcmp(dev->name, "Virtual core pointer") != 0))
{
touch = TRUE;
}
}
-
+
for (j = 0; j < dev->num_classes; j++)
{
XIAnyClassInfo* class = dev->classes[j];
XITouchClassInfo* t = (XITouchClassInfo*) class;
-
+
if (xfc->settings->MultiTouchInput)
{
printf("%s (%d) \"%s\" id: %d\n",
- xf_input_get_class_string(class->type),
- class->type, dev->name, dev->deviceid);
+ xf_input_get_class_string(class->type),
+ class->type, dev->name, dev->deviceid);
}
-
+
evmasks[nmasks].mask = masks[nmasks];
evmasks[nmasks].mask_len = sizeof(masks[0]);
ZeroMemory(masks[nmasks], sizeof(masks[0]));
evmasks[nmasks].deviceid = dev->deviceid;
-
+
if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) &&
- (strcmp(dev->name, "Virtual core pointer") != 0))
+ (strcmp(dev->name, "Virtual core pointer") != 0))
{
if (xfc->settings->MultiTouchInput)
{
printf("%s %s touch device (id: %d, mode: %d), supporting %d touches.\n",
- dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent",
- dev->deviceid, t->mode, t->num_touches);
+ dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent",
+ dev->deviceid, t->mode, t->num_touches);
}
-
+
XISetMask(masks[nmasks], XI_TouchBegin);
XISetMask(masks[nmasks], XI_TouchUpdate);
XISetMask(masks[nmasks], XI_TouchEnd);
nmasks++;
}
-
+
if (xfc->use_xinput)
{
- if (!touch && (class->type == XIButtonClass))
+ if (!touch && (class->type == XIButtonClass) && strcmp(dev->name, "Virtual core pointer"))
{
+ printf("%s button device (id: %d, mode: %d)\n",
+ dev->name,
+ dev->deviceid, t->mode);
XISetMask(masks[nmasks], XI_ButtonPress);
XISetMask(masks[nmasks], XI_ButtonRelease);
XISetMask(masks[nmasks], XI_Motion);
@@ -173,51 +197,181 @@ int xf_input_init(xfContext* xfc, Window window)
}
}
}
-
+
if (nmasks > 0)
xstatus = XISelectEvents(xfc->display, window, evmasks, nmasks);
-
+
return 0;
}
-BOOL xf_input_is_duplicate(XIDeviceEvent* event)
+BOOL xf_input_is_duplicate(XGenericEventCookie* cookie)
{
+ XIDeviceEvent* event;
+
+ event = cookie->data;
+
+
if ( (lastEvent.time == event->time) &&
- (lastEvent.detail == event->detail) &&
- (lastEvent.event_x == event->event_x) &&
- (lastEvent.event_y == event->event_y) )
+ (lastEvType == cookie->evtype) &&
+ (lastEvent.detail == event->detail) &&
+ (lastEvent.event_x == event->event_x) &&
+ (lastEvent.event_y == event->event_y) )
{
return TRUE;
}
-
+
return FALSE;
}
-void xf_input_save_last_event(XIDeviceEvent* event)
+void xf_input_save_last_event(XGenericEventCookie* cookie)
{
+ XIDeviceEvent* event;
+
+ event = cookie->data;
+
+ lastEvType = cookie->evtype;
+
lastEvent.time = event->time;
lastEvent.detail = event->detail;
lastEvent.event_x = event->event_x;
lastEvent.event_y = event->event_y;
+
+}
+
+void xf_input_detect_pan(xfContext* xfc)
+{
+ double dx[2];
+ double dy[2];
+
+ double px;
+ double py;
+
+ double dist_x;
+ double dist_y;
+
+ if (active_contacts != 2)
+ {
+ return;
+ }
+
+ dx[0] = contacts[0].pos_x - contacts[0].last_x;
+ dx[1] = contacts[1].pos_x - contacts[1].last_x;
+
+ dy[0] = contacts[0].pos_y - contacts[0].last_y;
+ dy[1] = contacts[1].pos_y - contacts[1].last_y;
+
+ px = fabs(dx[0]) < fabs(dx[1]) ? dx[0] : dx[1];
+ py = fabs(dy[0]) < fabs(dy[1]) ? dy[0] : dy[1];
+
+ px_vector += px;
+ py_vector += py;
+
+ dist_x = fabs(contacts[0].pos_x - contacts[1].pos_x);
+ dist_y = fabs(contacts[0].pos_y - contacts[1].pos_y);
+
+
+ //only pan in x if dist_y is greater than something
+ if(dist_y > MIN_FINGER_DIST)
+ {
+
+ if(px_vector > PAN_THRESHOLD)
+ {
+
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = 5;
+ e.YPan = 0;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+
+ px_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
+ z_vector = 0;
+ }
+ else if(px_vector < -PAN_THRESHOLD)
+ {
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = -5;
+ e.YPan = 0;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+
+ px_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
+ z_vector = 0;
+ }
+
+ }
+
+ if(dist_x > MIN_FINGER_DIST)
+ {
+
+ if(py_vector > PAN_THRESHOLD)
+ {
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = 0;
+ e.YPan = 5;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+
+ py_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
+ z_vector = 0;
+ }
+ else if(py_vector < -PAN_THRESHOLD)
+ {
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = 0;
+ e.YPan = -5;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+
+ py_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
+ z_vector = 0;
+ }
+ }
+
}
void xf_input_detect_pinch(xfContext* xfc)
{
double dist;
double zoom;
+
double delta;
ResizeWindowEventArgs e;
-
+
if (active_contacts != 2)
{
firstDist = -1.0;
return;
}
-
+
+
/* first calculate the distance */
dist = sqrt(pow(contacts[1].pos_x - contacts[0].last_x, 2.0) +
- pow(contacts[1].pos_y - contacts[0].last_y, 2.0));
-
+ pow(contacts[1].pos_y - contacts[0].last_y, 2.0));
+
/* if this is the first 2pt touch */
if (firstDist <= 0)
{
@@ -225,50 +379,69 @@ void xf_input_detect_pinch(xfContext* xfc)
lastDist = firstDist;
scale_cnt = 0;
z_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
+ z_vector = 0;
}
else
{
delta = lastDist - dist;
-
+
+ if(delta > 1.0)
+ delta = 1.0;
+ if(delta < -1.0)
+ delta = -1.0;
+
/* compare the current distance to the first one */
zoom = (dist / firstDist);
-
+
z_vector += delta;
- //printf("d: %.2f\n", delta);
-
+
+
lastDist = dist;
-
- if (z_vector > 10)
+
+ if (z_vector > ZOOM_THRESHOLD)
{
- xfc->scale -= 0.05;
-
- if (xfc->scale < 0.5)
- xfc->scale = 0.5;
-
- XResizeWindow(xfc->display, xfc->window->handle, xfc->originalWidth * xfc->scale, xfc->originalHeight * xfc->scale);
-
+ xfc->settings->ScalingFactor -= 0.05;
+
+ if (xfc->settings->ScalingFactor < 0.8)
+ xfc->settings->ScalingFactor = 0.8;
+
EventArgsInit(&e, "xfreerdp");
- e.width = (int) xfc->originalWidth * xfc->scale;
- e.height = (int) xfc->originalHeight * xfc->scale;
+ e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
+ e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
+
+ xf_transform_window(xfc);
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
-
+ xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
+
+ z_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
z_vector = 0;
}
-
- if (z_vector < -10)
+
+ if (z_vector < -ZOOM_THRESHOLD)
{
- xfc->scale += 0.05;
-
- if (xfc->scale > 1.5)
- xfc->scale = 1.5;
-
- XResizeWindow(xfc->display, xfc->window->handle, xfc->originalWidth * xfc->scale, xfc->originalHeight * xfc->scale);
-
+ xfc->settings->ScalingFactor += 0.05;
+
+ if (xfc->settings->ScalingFactor > 1.2)
+ xfc->settings->ScalingFactor = 1.2;
+
EventArgsInit(&e, "xfreerdp");
- e.width = (int) xfc->originalWidth * xfc->scale;
- e.height = (int) xfc->originalHeight * xfc->scale;
+ e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
+ e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
+
+ xf_transform_window(xfc);
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
-
+ xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
+
+ z_vector = 0;
+
+ px_vector = 0;
+ py_vector = 0;
z_vector = 0;
}
}
@@ -277,7 +450,9 @@ void xf_input_detect_pinch(xfContext* xfc)
void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
{
int i;
-
+ if(active_contacts == MAX_CONTACTS)
+ printf("Houston, we have a problem!\n\n");
+
for (i = 0; i < MAX_CONTACTS; i++)
{
if (contacts[i].id == 0)
@@ -286,7 +461,7 @@ void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
contacts[i].count = 1;
contacts[i].pos_x = event->event_x;
contacts[i].pos_y = event->event_y;
-
+
active_contacts++;
break;
}
@@ -296,7 +471,6 @@ void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
{
int i;
-
for (i = 0; i < MAX_CONTACTS; i++)
{
if (contacts[i].id == event->detail)
@@ -306,9 +480,10 @@ void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
contacts[i].last_y = contacts[i].pos_y;
contacts[i].pos_x = event->event_x;
contacts[i].pos_y = event->event_y;
-
+
xf_input_detect_pinch(xfc);
-
+ xf_input_detect_pan(xfc);
+
break;
}
}
@@ -317,7 +492,6 @@ void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
{
int i;
-
for (i = 0; i < MAX_CONTACTS; i++)
{
if (contacts[i].id == event->detail)
@@ -326,7 +500,7 @@ void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
contacts[i].count = 0;
//contacts[i].pos_x = (int)event->event_x;
//contacts[i].pos_y = (int)event->event_y;
-
+
active_contacts--;
break;printf("TouchBegin\n");
}
@@ -336,39 +510,39 @@ void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
int xf_input_handle_event_local(xfContext* xfc, XEvent* event)
{
XGenericEventCookie* cookie = &event->xcookie;
-
+
XGetEventData(xfc->display, cookie);
-
+
if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode))
{
switch (cookie->evtype)
{
case XI_TouchBegin:
- if (xf_input_is_duplicate(cookie->data) == FALSE)
+ if (xf_input_is_duplicate(cookie) == FALSE)
xf_input_touch_begin(xfc, cookie->data);
- xf_input_save_last_event(cookie->data);
+ xf_input_save_last_event(cookie);
break;
-
+
case XI_TouchUpdate:
- if (xf_input_is_duplicate(cookie->data) == FALSE)
+ if (xf_input_is_duplicate(cookie) == FALSE)
xf_input_touch_update(xfc, cookie->data);
- xf_input_save_last_event(cookie->data);
+ xf_input_save_last_event(cookie);
break;
-
+
case XI_TouchEnd:
- if (xf_input_is_duplicate(cookie->data) == FALSE)
+ if (xf_input_is_duplicate(cookie) == FALSE)
xf_input_touch_end(xfc, cookie->data);
- xf_input_save_last_event(cookie->data);
+ xf_input_save_last_event(cookie);
break;
-
+
default:
printf("unhandled xi type= %d\n", cookie->evtype);
break;
}
}
-
+
XFreeEventData(xfc->display,cookie);
-
+
return 0;
}
@@ -384,73 +558,126 @@ char* xf_input_touch_state_string(DWORD flags)
return "TouchUnknown";
}
+void xf_input_hide_cursor(xfContext* xfc)
+{
+#ifdef WITH_XCURSOR
+ if (!xfc->cursorHidden)
+ {
+ XcursorImage ci;
+ XcursorPixel xp = 0;
+ static Cursor nullcursor = None;
+
+ xf_lock_x11(xfc, FALSE);
+
+ ZeroMemory(&ci, sizeof(ci));
+ ci.version = XCURSOR_IMAGE_VERSION;
+ ci.size = sizeof(ci);
+ ci.width = ci.height = 1;
+ ci.xhot = ci.yhot = 0;
+ ci.pixels = &xp;
+ nullcursor = XcursorImageLoadCursor(xfc->display, &ci);
+
+ if ((xfc->window) && (nullcursor != None))
+ XDefineCursor(xfc->display, xfc->window->handle, nullcursor);
+
+ xfc->cursorHidden = TRUE;
+
+ xf_unlock_x11(xfc, FALSE);
+ }
+#endif
+}
+
+void xf_input_show_cursor(xfContext* xfc)
+{
+#ifdef WITH_XCURSOR
+ xf_lock_x11(xfc, FALSE);
+
+ if (xfc->cursorHidden)
+ {
+ if (xfc->window)
+ {
+ if (!xfc->pointer)
+ XUndefineCursor(xfc->display, xfc->window->handle);
+ else
+ XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
+ }
+
+ xfc->cursorHidden = FALSE;
+ }
+
+ xf_unlock_x11(xfc, FALSE);
+#endif
+}
+
int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
{
int x, y;
int touchId;
int contactId;
RdpeiClientContext* rdpei = xfc->rdpei;
-
+
if (!rdpei)
return 0;
+
+ xf_input_hide_cursor(xfc);
touchId = event->detail;
x = (int) event->event_x;
y = (int) event->event_y;
-
+
if (evtype == XI_TouchBegin)
{
- //printf("TouchBegin: %d\n", touchId);
+ printf("TouchBegin: %d\n", touchId);
contactId = rdpei->TouchBegin(rdpei, touchId, x, y);
}
else if (evtype == XI_TouchUpdate)
{
- //printf("TouchUpdate: %d\n", touchId);
+ printf("TouchUpdate: %d\n", touchId);
contactId = rdpei->TouchUpdate(rdpei, touchId, x, y);
}
else if (evtype == XI_TouchEnd)
{
- //printf("TouchEnd: %d\n", touchId);
+ printf("TouchEnd: %d\n", touchId);
contactId = rdpei->TouchEnd(rdpei, touchId, x, y);
}
-
+
return 0;
}
int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype)
{
- return TRUE;
+ xf_input_show_cursor(xfc);
switch (evtype)
{
case XI_ButtonPress:
- printf("ButtonPress\n");
+
xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y,
- event->detail, event->event, xfc->remote_app);
+ event->detail, event->event, xfc->remote_app);
break;
-
+
case XI_ButtonRelease:
- printf("ButtonRelease\n");
+
xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y,
- event->detail, event->event, xfc->remote_app);
+ event->detail, event->event, xfc->remote_app);
break;
-
+
case XI_Motion:
- printf("Motion\n");
+
xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y,
- event->detail, event->event, xfc->remote_app);
+ event->detail, event->event, xfc->remote_app);
break;
}
-
+
return 0;
}
int xf_input_handle_event_remote(xfContext* xfc, XEvent* event)
{
XGenericEventCookie* cookie = &event->xcookie;
-
+
XGetEventData(xfc->display, cookie);
-
+
if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode))
{
switch (cookie->evtype)
@@ -458,23 +685,23 @@ int xf_input_handle_event_remote(xfContext* xfc, XEvent* event)
case XI_TouchBegin:
xf_input_touch_remote(xfc, cookie->data, XI_TouchBegin);
break;
-
+
case XI_TouchUpdate:
xf_input_touch_remote(xfc, cookie->data, XI_TouchUpdate);
break;
-
+
case XI_TouchEnd:
xf_input_touch_remote(xfc, cookie->data, XI_TouchEnd);
break;
-
+
default:
xf_input_event(xfc, cookie->data, cookie->evtype);
break;
}
}
-
+
XFreeEventData(xfc->display,cookie);
-
+
return 0;
}
@@ -493,10 +720,10 @@ void xf_process_rdpei_event(xfContext* xfc, wMessage* event)
{
case RdpeiChannel_ServerReady:
break;
-
+
case RdpeiChannel_SuspendTouch:
break;
-
+
case RdpeiChannel_ResumeTouch:
break;
}
@@ -505,14 +732,16 @@ void xf_process_rdpei_event(xfContext* xfc, wMessage* event)
int xf_input_handle_event(xfContext* xfc, XEvent* event)
{
#ifdef WITH_XI
- if (xfc->settings->MultiTouchInput)
+ //printf("m:%d g:%d\n", (xfc->settings->MultiTouchInput), (xfc->settings->MultiTouchGestures) );
+ if (xfc->settings->MultiTouchInput)
{
return xf_input_handle_event_remote(xfc, event);
}
-
- if (xfc->enableScaling)
+
+ if (xfc->settings->MultiTouchGestures)
return xf_input_handle_event_local(xfc, event);
+
#endif
-
+
return 0;
}
diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c
index 0c85119c8..8b5cf0b33 100644
--- a/client/X11/xf_keyboard.c
+++ b/client/X11/xf_keyboard.c
@@ -216,7 +216,160 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
return TRUE;
}
}
-
+
+ if (keysym == XK_period)
+ {
+ if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
+ || xf_kbd_key_pressed(xfc, XK_Alt_R))
+ && (xf_kbd_key_pressed(xfc, XK_Control_L)
+ || xf_kbd_key_pressed(xfc,
+ XK_Control_R)))
+ {
+ //Zoom in (scale larger)
+ double s = xfc->settings->ScalingFactor;
+ s += 0.1;
+ if (s > 2.0)
+ s = 2.0;
+
+ xfc->settings->ScalingFactor = s;
+
+ xfc->currentWidth = xfc->originalWidth * s;
+ xfc->currentHeight = xfc->originalHeight * s;
+
+ xf_transform_window(xfc);
+
+ {
+ ResizeWindowEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
+ e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
+ PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+ xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
+ return TRUE;
+ }
+ }
+
+ if (keysym == XK_comma)
+ {
+ if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
+ || xf_kbd_key_pressed(xfc, XK_Alt_R))
+ && (xf_kbd_key_pressed(xfc, XK_Control_L)
+ || xf_kbd_key_pressed(xfc,
+ XK_Control_R)))
+ {
+ //Zoom out (scale smaller)
+ double s = xfc->settings->ScalingFactor;
+ s -= 0.1;
+ if (s < 0.5)
+ s = 0.5;
+
+ xfc->settings->ScalingFactor = s;
+
+ xfc->currentWidth = xfc->originalWidth * s;
+ xfc->currentHeight = xfc->originalHeight * s;
+
+ xf_transform_window(xfc);
+
+ {
+ ResizeWindowEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
+ e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
+ PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+
+ xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
+ return TRUE;
+ }
+ }
+
+ if (keysym == XK_KP_4)
+ {
+ if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
+ || xf_kbd_key_pressed(xfc, XK_Alt_R))
+ && (xf_kbd_key_pressed(xfc, XK_Control_L)
+ || xf_kbd_key_pressed(xfc,
+ XK_Control_R)))
+ {
+
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = -5;
+ e.YPan = 0;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+
+ return TRUE;
+ }
+ }
+
+ if (keysym == XK_KP_6)
+ {
+ if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
+ || xf_kbd_key_pressed(xfc, XK_Alt_R))
+ && (xf_kbd_key_pressed(xfc, XK_Control_L)
+ || xf_kbd_key_pressed(xfc,
+ XK_Control_R)))
+ {
+
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = 5;
+ e.YPan = 0;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+ return TRUE;
+ }
+ }
+
+ if (keysym == XK_KP_8)
+ {
+ if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
+ || xf_kbd_key_pressed(xfc, XK_Alt_R))
+ && (xf_kbd_key_pressed(xfc, XK_Control_L)
+ || xf_kbd_key_pressed(xfc,
+ XK_Control_R)))
+ {
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = 0;
+ e.YPan = -5;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+ return TRUE;
+ }
+ }
+
+ if (keysym == XK_KP_2)
+ {
+ if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
+ || xf_kbd_key_pressed(xfc, XK_Alt_R))
+ && (xf_kbd_key_pressed(xfc, XK_Control_L)
+ || xf_kbd_key_pressed(xfc,
+ XK_Control_R)))
+ {
+ {
+ PanningChangeEventArgs e;
+
+ EventArgsInit(&e, "xfreerdp");
+ e.XPan = 0;
+ e.YPan = 5;
+ PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
+ }
+ return TRUE;
+ }
+ }
+
+
return FALSE;
}
diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c
index a24ac7190..e12cdc344 100644
--- a/client/X11/xf_window.c
+++ b/client/X11/xf_window.c
@@ -44,6 +44,7 @@
#ifdef WITH_XI
#include
+#include "xf_input.h"
#endif
#include "xf_input.h"
diff --git a/client/X11/xfreerdp-channels.1.xml b/client/X11/xfreerdp-channels.1.xml
new file mode 100644
index 000000000..e69de29bb
diff --git a/client/X11/xfreerdp-examples.1.xml b/client/X11/xfreerdp-examples.1.xml
new file mode 100644
index 000000000..462649f68
--- /dev/null
+++ b/client/X11/xfreerdp-examples.1.xml
@@ -0,0 +1,89 @@
+
+ Examples
+
+
+ xfreerdp connection.rdp /p:Pwd123! /f
+
+ Connect in fullscreen mode using a stored configuration connection.rdp and the password Pwd123!
+
+
+
+ xfreerdp /u:CONTOSO\\JohnDoe /p:Pwd123! /v:rdp.contoso.com
+
+ Connect to host rdp.contoso.com with user CONTOSO\\JohnDoe and password Pwd123!
+
+
+
+ xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192.168.1.100:4489
+
+ Connect to host 192.168.1.100 on port 4489 with user JohnDoe, password Pwd123!. The screen width is set to 1366 and the height to 768
+
+
+
+ xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:192.168. 1.100
+
+ Establish a connection to host 192.168.1.100 with user JohnDoe, password Pwd123! and connect to Hyper-V console (use port 2179, disable negotiation) with VMID C824F53E-95D2-46C6-9A18-23A5BB403532
+
+
+
+ +clipboard
+
+ Activate clipboard redirection
+
+
+
+ /drive:home,/home/user
+
+ Activate drive redirection of /home/user as home drive
+
+
+
+ /smartcard:<device>
+
+ Activate smartcard redirection for device device
+
+
+
+ /printer:<device>,<driver>
+
+ Activate printer redirection for printer device using driver driver
+
+
+
+ /serial:<device>
+
+ Activate serial port redirection for port device
+
+
+
+ /parallel:<device>
+
+ Activate parallel port redirection for port device
+
+
+
+ /sound:sys:alsa
+
+ Activate audio output redirection using device sys:alsa
+
+
+
+ /microphone:sys:alsa
+
+ Activate audio input redirection using device sys:alsa
+
+
+
+ /multimedia:sys:alsa
+
+ Activate multimedia redirection using device sys:alsa
+
+
+
+ /usb:id,dev:054c:0268
+
+ Activate USB device redirection for the device identified by 054c:0268
+
+
+
+
diff --git a/client/X11/xfreerdp.1.xml b/client/X11/xfreerdp.1.xml
deleted file mode 100644
index bf7f774e6..000000000
--- a/client/X11/xfreerdp.1.xml
+++ /dev/null
@@ -1,571 +0,0 @@
-
-
-
- 2011-08-27
-
- The FreeRDP Team
-
-
-
- xfreerdp
- 1
- freerdp
- xfreerdp
-
-
- xfreerdp
- FreeRDP X11 client
-
-
-
- 2011-08-27
-
-
- xfreerdp [options] server[:port] [[options] server[:port] …]
-
-
-
-
- 2011-08-27
-
- DESCRIPTION
-
- xfreerdp is an X11 Remote Desktop Protocol (RDP)
- client which is part of the FreeRDP project. An RDP server is built-in
- to many editions of Windows. Alternative servers included xrdp and VRDP (VirtualBox).
-
-
-
- OPTIONS
-
-
- -0
-
-
- Attach to the admin console of the server.
-
-
-
-
- -a bpp
-
-
- Sets the color depth for the connection to bpp bits per pixel.
- Valid values are 8, 15, 16, 24 and 32. The default value is the color depth of the FreeRDP-window.
-
-
-
-
- -c dir
-
-
- Sets the working-dir to dir.
- This parameter is only used when an AlternateShell () is requested.
- dir should contain the executable file specified in the AlternateShell.
-
-
-
-
- -D
-
-
- Removes the windows decorations.
-
-
-
-
- -d
-
-
- Domain used in authentication.
-
-
-
-
- -f
-
-
- start in full screen mode. This mode can always be en- and disabled using Ctrl-Alt-Enter.
-
-
-
-
- -T text
-
-
- Sets the window title to text.
-
-
-
-
- -g geometry
-
-
- Sets the size of the FreeRDP window (and of the remote desktop, when establishing a new connection).
- geometry can have one of the following forms:
-
-
-
- WxH -
- in this case the resulting window will be of
- WxH pixels.
-
-
-
-
- P% -
- in this case the resulting window will be P%
- of your screen.
-
-
-
-
- The special keyword workarea -
- in this case the resulting window will be of the same size as your workarea.
-
-
-
-
-
-
-
- -h
-
-
- Print help.
-
-
-
-
- -k id
-
-
- Sets the keyboard-layout-id to id.
-
-
-
-
- -K
-
-
- Do not interfere with window manager bindings. Normally, xfreerdp captures all keystrokes while its window is focused.
-
-
-
-
- -n hostname
-
-
- Set the reported client hostname to hostname.
- Default is to automatically detect the hostname.
-
-
-
-
- -o
-
-
- Play audio on the console instead of redirecting to the client.
-
-
-
-
- -p password
-
-
- Password used in authentication.
-
-
-
-
- -s shell
-
-
- Sets the startup-shell to shell.
- This parameter should contain a complete path to the alternate shell.
- If the alternete shell requires a different working directory use .
-
-
-
-
- -t port
-
-
- Connect to port, instead of the default 3389.
-
-
-
-
- -u username
-
-
- Username used in authentication.
-
-
-
-
- -x flag
-
-
- Set the experience performance flags.
- flag can be one of:
-
-
-
- m - (modem): Equivalent to 15.
-
-
-
-
- b - (broadband): Equivalent to 1.
-
-
-
-
- l - (lan): Equivalent to 0.
-
-
-
-
- num - A hexadecimal number that
- represents a bit-mask, were numbers mean the following
- Taken from
- MS-RDPBCGR Section 2.2.1.11.1.1.1 - Extended Info Packet:
-
-
- 1: Disable desktop wallpaper.
-
-
- 2: Disable full-window drag (only the window outline is displayed when the window is moved).
-
-
- 4: Disable menu animations.
-
-
- 8: Disable user interface themes.
-
-
- 20: Disable mouse cursor shadows.
-
-
- 40: Disable cursor blinking.
-
-
- 80: Enable font smoothing.
-
-
- 100: Enable Desktop Composition.
-
-
-
-
-
-
-
-
-
- -X xid
-
- embed xfreerdp into window with xid.
-
-
-
- -z
-
-
- Enable compression.
-
-
-
-
- --app
-
-
- initialize a RemoteApp connection. This implies -g workarea.
-
-
-
-
- --no-auth
-
-
- Skips authentication. This is useful e.g. for the current FreeRDP server that doesn't yet support server-side authentication.
-
-
-
-
- --authonly
-
-
- Only authenticates. This is useful to test your credentials (username and password).
- Returns status code 0 if the client can connect, 1 otherwise. Requires a username,
- password and connection host at the command line.
-
-
-
-
- --bcv3 codec
-
- Use codec for bitmap cache v3
-
-
-
-
- --no-bmp-cache
-
-
- Disable bitmap cache.
-
-
-
-
- --certificate-name name
-
-
- use name for the logon certificate, instead of the server name
-
-
-
-
- --composition
-
-
- Enable composition (RDVH only, not to be confused with remote composition).
-
-
-
-
- --ext extname
-
-
- load extension extname
-
-
-
-
- --no-fastpath
-
-
- Disables fast-path. Use slow-path packets instead, which have larger headers.
- It might be good for debugging certain issues when you suspect it might be
- linked to the parsing of one of the two header types.
-
-
-
-
- --from-stdin
-
- Prompts for unspecified arguments -u username, -p
- password, -d domain and connection host. This is useful to
- hide arguments from ps. Also useful for scripts that will
- feed these arguments to the client via (what else?) stdin.
-
-
-
-
- --disable-full-window-drag
-
-
- Disable full window drag.
-
-
-
-
- --gdi backend
-
-
- GDI (Graphics Device Interface) rendering backend. backend can be either sw (software) or hw (hardware).
-
-
-
-
- --ignore-certificate
-
-
- ignore verification of logon certificate.
-
-
-
-
- --kbd-list
-
-
- list all keyboard layout ids used by -k
-
-
-
-
- --disable-menu-animations
-
-
- Disable menu animations.
-
-
-
-
- --no-motion
-
-
- Don't send mouse motion events.
-
-
-
-
- --no-nego
-
- disable negotiation of security layer and enforce highest enabled security protocol.
-
-
-
-
- --no-nla
-
-
- Disable network level authentication.
-
-
-
-
- --nsc
-
-
- Enable NSCodec.
-
-
-
-
- --no-osb
-
-
- Disable off screen bitmaps.
-
-
-
-
- --pcb blob
-
-
- Use preconnection blob.
-
-
-
-
- --pcid id
-
-
- Use preconnection id.
-
-
-
-
- --plugin pluginname
-
-
- load pluginname
-
-
-
-
- --no-rdp
-
-
- Disable Standard RDP encryption.
-
-
-
-
- --rfx
-
-
- Enable RemoteFX.
-
-
-
-
- --rfx-mode
-
-
- RemoteFX operational flags. flags can be either v[ideo], i[mage]), default is video.
-
-
-
-
- --no-salted-checksum
-
-
- disable salted checksums with Standard RDP encryption.
-
-
-
-
- --ntlm
-
-
- force NTLM protocol version. version can be one of 1 or 2.
-
-
-
-
- --sec proto
-
-
- force protocol security. proto can be one of rdp, tls or nla.
-
-
-
-
- --disable-theming
-
-
- Disable theming.
-
-
-
-
- --no-tls
-
-
- Disable TLS encryption.
-
-
-
-
- --tsg
-username
-password
-hostname
-
-
- Use Terminal Server Gateway with
-username
-password
-hostname.
-
-
-
-
- --version
-
-
- Print version information.
-
-
-
-
- --disable-wallpaper
-
-
- Disable wallpaper.
-
-
-
-
-
-
- LINKS
-
- http://www.freerdp.com/
-
-
-
diff --git a/client/X11/xfreerdp.1.xml.in b/client/X11/xfreerdp.1.xml.in
new file mode 100644
index 000000000..4dbb42083
--- /dev/null
+++ b/client/X11/xfreerdp.1.xml.in
@@ -0,0 +1,60 @@
+
+
+
+
+ ]
+>
+
+
+
+ @MAN_TODAY@
+
+ The FreeRDP Team
+
+
+
+ xfreerdp
+ 1
+ freerdp
+ xfreerdp
+
+
+ xfreerdp
+ FreeRDP X11 client
+
+
+
+ @MAN_TODAY@
+
+
+ xfreerdp [file] [options] [/v:server[:port]]
+
+
+
+
+ @MAN_TODAY@
+
+ DESCRIPTION
+
+ xfreerdp is an X11 Remote Desktop Protocol (RDP)
+ client which is part of the FreeRDP project. An RDP server is built-in
+ to many editions of Windows. Alternative servers included xrdp and VRDP (VirtualBox).
+
+
+
+ &syntax;
+
+ &channels;
+
+ &examples;
+
+
+ LINKS
+
+ http://www.freerdp.com/
+
+
+
diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h
index 37f187487..a7aaa70a2 100644
--- a/client/X11/xfreerdp.h
+++ b/client/X11/xfreerdp.h
@@ -89,6 +89,7 @@ struct xf_context
BOOL unobscured;
BOOL debug;
xfWindow* window;
+ xfPointer* pointer;
xfWorkArea workArea;
int current_desktop;
BOOL remote_app;
@@ -96,6 +97,7 @@ struct xf_context
HCLRCONV clrconv;
HANDLE mutex;
BOOL UseXThreads;
+ BOOL cursorHidden;
HGDI_DC hdc;
BYTE* primary_buffer;
@@ -106,7 +108,6 @@ struct xf_context
UINT16 frame_x2;
UINT16 frame_y2;
- double scale;
int originalWidth;
int originalHeight;
int currentWidth;
@@ -114,6 +115,9 @@ struct xf_context
int XInputOpcode;
BOOL enableScaling;
+ int offset_x;
+ int offset_y;
+
BOOL focused;
BOOL use_xinput;
BOOL mouse_active;
@@ -208,7 +212,8 @@ enum XF_EXIT_CODE
void xf_lock_x11(xfContext* xfc, BOOL display);
void xf_unlock_x11(xfContext* xfc, BOOL display);
-void xf_draw_screen_scaled(xfContext* xfc);
+void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale);
+void xf_transform_window(xfContext* xfc);
DWORD xf_exit_code_from_disconnect_reason(DWORD reason);
diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt
index e249cd0db..2b9841e5f 100644
--- a/client/common/CMakeLists.txt
+++ b/client/common/CMakeLists.txt
@@ -25,9 +25,10 @@ set(${MODULE_PREFIX}_SRCS
compatibility.h
file.c)
-set(FREERDP_CHANNELS_CLIENT_PATH "../../channels/client")
foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS})
- set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} "${FREERDP_CHANNELS_CLIENT_PATH}/${FREERDP_CHANNELS_CLIENT_SRC}")
+ get_filename_component(NINC ${FREERDP_CHANNELS_CLIENT_SRC} PATH)
+ include_directories(${NINC})
+ set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} "${FREERDP_CHANNELS_CLIENT_SRC}")
endforeach()
if(MSVC)
@@ -53,7 +54,9 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
-install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
+if (NOT WITH_WAYK)
+ install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
+endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Common")
diff --git a/client/common/client.c b/client/common/client.c
index acc47d064..824b46859 100644
--- a/client/common/client.c
+++ b/client/common/client.c
@@ -56,8 +56,8 @@ rdpContext* freerdp_client_context_new(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
freerdp_context_new(instance);
context = instance->context;
- context->instance = instance;
- context->settings = instance->settings;
+ context->instance = instance;
+ context->settings = instance->settings;
return context;
}
@@ -112,16 +112,13 @@ int freerdp_client_parse_command_line(rdpContext* context, int argc, char** argv
if (settings->ConnectionFile)
{
- rdpFile* file = freerdp_client_rdp_file_new();
- freerdp_client_parse_rdp_file(file, settings->ConnectionFile);
- freerdp_client_populate_settings_from_rdp_file(file, settings);
- freerdp_client_rdp_file_free(file);
+ return freerdp_client_parse_connection_file(context, settings->ConnectionFile);
}
return status;
}
-int freerdp_client_parse_connection_file(rdpContext* context, char* filename)
+int freerdp_client_parse_connection_file(rdpContext* context, const char* filename)
{
rdpFile* file;
@@ -136,11 +133,35 @@ int freerdp_client_parse_connection_file(rdpContext* context, char* filename)
int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffer, size_t size)
{
rdpFile* file;
+ int status = -1;
file = freerdp_client_rdp_file_new();
- freerdp_client_parse_rdp_file_buffer(file, buffer, size);
- freerdp_client_populate_settings_from_rdp_file(file, context->settings);
+ if (freerdp_client_parse_rdp_file_buffer(file, buffer, size)
+ && freerdp_client_populate_settings_from_rdp_file(file, context->settings))
+ {
+ status = 0;
+ }
+
freerdp_client_rdp_file_free(file);
- return 0;
+ return status;
+}
+
+int freerdp_client_write_connection_file(rdpContext* context, const char* filename, BOOL unicode)
+{
+ rdpFile* file;
+ int status = -1;
+
+ file = freerdp_client_rdp_file_new();
+ if (freerdp_client_populate_rdp_file_from_settings(file, context->settings))
+ {
+ if (freerdp_client_write_rdp_file(file, filename, unicode))
+ {
+ status = 0;
+ }
+ }
+
+ freerdp_client_rdp_file_free(file);
+
+ return status;
}
diff --git a/client/common/cmdline.c b/client/common/cmdline.c
index 06514b59a..ce14ab125 100644
--- a/client/common/cmdline.c
+++ b/client/common/cmdline.c
@@ -90,7 +90,9 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "printer", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect printer device" },
{ "usb", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect USB device" },
{ "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" },
+ { "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" },
{ "echo", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "echo", "Echo channel" },
+ { "disp", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Display control" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Smooth fonts (ClearType)" },
{ "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueFalse, -1, NULL, "Desktop composition" },
{ "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Full window drag" },
@@ -134,6 +136,8 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "wm-class", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "set the WM_CLASS hint for the window instance" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "print version" },
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" },
+ { "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Replay rfx pcap file" },
+ { "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
@@ -595,6 +599,11 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
p[0] = "rdpei";
freerdp_client_add_dynamic_channel(settings, count, p);
}
+ CommandLineSwitchCase(arg, "gestures")
+ {
+ printf("gestures\n");
+ settings->MultiTouchGestures = TRUE;
+ }
CommandLineSwitchCase(arg, "echo")
{
char* p[1];
@@ -605,6 +614,16 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
freerdp_client_add_dynamic_channel(settings, count, p);
}
+ CommandLineSwitchCase(arg, "disp")
+ {
+ char* p[1];
+ int count;
+
+ count = 1;
+ p[0] = "disp";
+
+ freerdp_client_add_dynamic_channel(settings, count, p);
+ }
CommandLineSwitchCase(arg, "sound")
{
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
@@ -863,13 +882,10 @@ int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, int*
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
- if (detect_status == 0)
- {
- if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
- detect_status = -1;
- }
+ if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
+ detect_status = -1;
- return 0;
+ return detect_status;
}
int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, int* count)
@@ -899,13 +915,10 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, int* c
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
- if (detect_status == 0)
- {
- if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
- detect_status = -1;
- }
+ if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
+ detect_status = -1;
- return 0;
+ return detect_status;
}
BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
@@ -1032,6 +1045,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter);
}
+
arg = CommandLineFindArgumentA(args, "v");
arg = args;
@@ -1241,8 +1255,9 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
settings->GatewayHostname = _strdup(settings->ServerHostname);
}
- settings->GatewayUsageMethod = TRUE;
+ settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
settings->GatewayUseSameCredentials = TRUE;
+ settings->GatewayEnabled = TRUE;
}
CommandLineSwitchCase(arg, "gu")
{
@@ -1426,6 +1441,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
CommandLineSwitchCase(arg, "nsc")
{
settings->NSCodec = TRUE;
+ settings->ColorDepth = 32;
}
CommandLineSwitchCase(arg, "jpeg")
{
@@ -1597,6 +1613,15 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
{
settings->WmClass = _strdup(arg->Value);
}
+ CommandLineSwitchCase(arg, "play-rfx")
+ {
+ settings->PlayRemoteFxFile = _strdup(arg->Value);
+ settings->PlayRemoteFx = TRUE;
+ }
+ CommandLineSwitchCase(arg, "auth-only")
+ {
+ settings->AuthenticationOnly = arg->Value ? TRUE : FALSE;
+ }
CommandLineSwitchDefault(arg)
{
@@ -1626,7 +1651,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
if (settings->DisableThemes)
settings->PerformanceFlags |= PERF_DISABLE_THEMING;
- if (settings->GatewayUsageMethod)
+ if (settings->GatewayEnabled)
{
if (settings->GatewayUseSameCredentials)
{
@@ -1655,7 +1680,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
FillMemory(arg->Value, strlen(arg->Value), '*');
}
- return 1;
+ return status;
}
int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* settings, char* name, void* data)
diff --git a/client/common/compatibility.c b/client/common/compatibility.c
index 8f14199b9..788b41354 100644
--- a/client/common/compatibility.c
+++ b/client/common/compatibility.c
@@ -473,7 +473,9 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
CommandLineSwitchCase(arg, "p")
{
settings->Password = _strdup(arg->Value);
- fprintf(stderr, "-p %s -> /p:%s\n", arg->Value, arg->Value);
+ fprintf(stderr, "-p ****** -> /p:******\n");
+ /* Hide the value from 'ps'. */
+ FillMemory(arg->Value, strlen(arg->Value), '*');
}
CommandLineSwitchCase(arg, "s")
{
diff --git a/client/common/file.c b/client/common/file.c
index afe40e9b1..a1ec5a362 100644
--- a/client/common/file.c
+++ b/client/common/file.c
@@ -439,7 +439,7 @@ BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t si
return freerdp_client_parse_rdp_file_buffer_ascii(file, buffer, size);
}
-BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name)
+BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
{
BYTE* buffer;
FILE* fp = NULL;
@@ -480,7 +480,8 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name)
return freerdp_client_parse_rdp_file_buffer(file, buffer, file_size);
}
-#define SETTING_MODIFIED(_settings, _field) (_settings->settings_modified[FreeRDP_##_field])
+#define WRITE_ALL_SETTINGS FALSE
+#define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->settings_modified[FreeRDP_##_field])
#define SETTING_MODIFIED_SET(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _settings->_field
BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings)
@@ -529,9 +530,9 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings*
}
-BOOL freerdp_client_write_rdp_file(rdpFile* file, char* name, BOOL unicode)
+BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode)
{
- BOOL success = FALSE;
+ int rc = 0;
char* buffer;
int len, len2;
FILE* fp = NULL;
@@ -559,22 +560,22 @@ BOOL freerdp_client_write_rdp_file(rdpFile* file, char* name, BOOL unicode)
fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp);
fwrite(unicodestr, 2, len, fp);
- free(unicodestr);
+ free(unicodestr);
}
else
{
fwrite(buffer, 1, len, fp);
}
- fflush(fp);
- fclose(fp);
+ rc = fflush(fp);
+ rc = fclose(fp);
}
}
if (buffer != NULL)
free(buffer);
- return success;
+ return (rc == 0);
}
#define WRITE_RDP_FILE_DECLARE(_file, _buffer, _size) \
@@ -604,7 +605,6 @@ if (~__rdpFile->_field) \
#define WRITE_RDP_FILE_VALUE_RETURN \
return __required_size;
-// TODO: Optimize by only writing the fields that have a value i.e ~((size_t) file->FieldName) != 0
size_t freerdp_client_write_rdp_file_buffer(rdpFile* file, char* buffer, size_t size)
{
WRITE_RDP_FILE_DECLARE(file, buffer, size)
@@ -731,11 +731,19 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (~((size_t) file->GatewayHostname))
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, file->GatewayHostname);
+
if (~file->GatewayUsageMethod)
- freerdp_set_param_bool(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
+ {
+ freerdp_set_param_uint32(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
+
+ if (file->GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
+ freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
+ else if (file->GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
+ freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, FALSE);
+ }
+
if (~file->PromptCredentialOnce)
- freerdp_set_param_bool(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
- settings->GatewayUseSameCredentials = TRUE;
+ freerdp_set_param_bool(settings, FreeRDP_GatewayUseSameCredentials, TRUE);
if (~file->RemoteApplicationMode)
freerdp_set_param_bool(settings, FreeRDP_RemoteApplicationMode, file->RemoteApplicationMode);
diff --git a/client/iOS/Models/RDPSession.m b/client/iOS/Models/RDPSession.m
index df924e29f..d61d59a57 100644
--- a/client/iOS/Models/RDPSession.m
+++ b/client/iOS/Models/RDPSession.m
@@ -175,7 +175,8 @@ NSString* TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect"
settings->GatewayUsername = strdup([_params UTF8StringForKey:@"tsg_username"]);
settings->GatewayPassword = strdup([_params UTF8StringForKey:@"tsg_password"]);
settings->GatewayDomain = strdup([_params UTF8StringForKey:@"tsg_domain"]);
- settings->GatewayUsageMethod = TRUE;
+ settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
+ settings->GatewayEnabled = TRUE;
settings->GatewayUseSameCredentials = FALSE;
}
diff --git a/cmake/AndroidToolchain.cmake b/cmake/AndroidToolchain.cmake
index 9216bf55d..9eeb7beaf 100644
--- a/cmake/AndroidToolchain.cmake
+++ b/cmake/AndroidToolchain.cmake
@@ -1,5 +1,5 @@
# Copyright (c) 2010-2011, Ethan Rublee
-# Copyright (c) 2011-2012, Andrey Kamaev
+# Copyright (c) 2011-2013, Andrey Kamaev
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,6 @@
#
# The file is mantained by the OpenCV project. The latest version can be get at
# http://code.opencv.org/projects/opencv/repository/revisions/master/changes/android/android.toolchain.cmake
-# Git commit: 084b1c796900b0825fc4e0593ab3143da3f3a90e
#
# Usage Linux:
# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk
@@ -282,8 +281,19 @@
# [+] updated for NDK r8c
# [+] added support for clang compiler
# - December 2012
+# [+] suppress warning about unused CMAKE_TOOLCHAIN_FILE variable
+# [+] adjust API level to closest compatible as NDK does
# [~] fixed ccache full path search
# [+] updated for NDK r8d
+# [~] compiler options are aligned with NDK r8d
+# - March 2013
+# [+] updated for NDK r8e (x86 version)
+# [+] support x86_64 version of NDK
+# - April 2013
+# [+] support non-release NDK layouts (from Linaro git and Android git)
+# [~] automatically detect if explicit link to crtbegin_*.o is needed
+# - June 2013
+# [~] fixed stl include path for standalone toolchain made by NDK >= r8c
# ------------------------------------------------------------------------------
cmake_minimum_required( VERSION 2.6.3 )
@@ -293,6 +303,10 @@ if( DEFINED CMAKE_CROSSCOMPILING )
return()
endif()
+if( CMAKE_TOOLCHAIN_FILE )
+ # touch toolchain variable only to suppress "unused variable" warning
+endif()
+
get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
if( _CMAKE_IN_TRY_COMPILE )
include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL )
@@ -312,7 +326,7 @@ endif()
# rpath makes low sence for Android
set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
-set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
+set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS)
if( CMAKE_HOST_WIN32 )
file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
@@ -456,19 +470,32 @@ if( ANDROID_FORBID_SYGWIN )
endif()
endif()
+
# detect current host platform
+if( NOT DEFINED ANDROID_NDK_HOST_X64 AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64")
+ set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" )
+ mark_as_advanced( ANDROID_NDK_HOST_X64 )
+endif()
+
set( TOOL_OS_SUFFIX "" )
if( CMAKE_HOST_APPLE )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" )
elseif( CMAKE_HOST_WIN32 )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "windows" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" )
set( TOOL_OS_SUFFIX ".exe" )
elseif( CMAKE_HOST_UNIX )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" )
else()
message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
endif()
+if( NOT ANDROID_NDK_HOST_X64 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
+endif()
+
# see if we have path to Android NDK
__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
if( NOT ANDROID_NDK )
@@ -500,35 +527,19 @@ if( NOT ANDROID_NDK )
endif( ANDROID_NDK )
endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
endif( NOT ANDROID_NDK )
+
# remember found paths
if( ANDROID_NDK )
get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
- # try to detect change
- if( CMAKE_AR )
- string( LENGTH "${ANDROID_NDK}" __length )
- string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
- if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK )
- message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
- " )
- endif()
- unset( __androidNdkPreviousPath )
- unset( __length )
- endif()
set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
set( BUILD_WITH_ANDROID_NDK True )
- file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_TXT LIMIT_COUNT 1 REGEX r[0-9]+[a-z]? )
-
- if(${ANDROID_NDK_RELEASE_TXT} MATCHES "^r[0-9]+[a-z] \([^ ]+\)$")
- string( REGEX REPLACE "^(r[0-9]+[a-z]) \(([^ ]+)\)$" "\\1" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_TXT}" )
- string( REGEX REPLACE "^(r[0-9]+[a-z]) \(([^ ]+)\)$" "\\2" ANDROID_NDK_RELEASE_EXTRA "${ANDROID_NDK_RELEASE_TXT}" )
-
- set( ANDROID_NDK_64BIT True)
- set( ANDROID_NDK_HOST_SYSTEM_NAME "${ANDROID_NDK_HOST_SYSTEM_NAME}_64" )
-
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
+ file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX r[0-9]+[a-z]? )
+ string( REGEX MATCH r[0-9]+[a-z]? ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
else()
- set( ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_TXT}" )
+ set( ANDROID_NDK_RELEASE "r1x" )
+ set( ANDROID_NDK_RELEASE_FULL "unreleased" )
endif()
-
elseif( ANDROID_STANDALONE_TOOLCHAIN )
get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
# try to detect change
@@ -555,6 +566,51 @@ else()
sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
endif()
+# android NDK layout
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT DEFINED ANDROID_NDK_LAYOUT )
+ # try to automatically detect the layout
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
+ set( ANDROID_NDK_LAYOUT "RELEASE" )
+ elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
+ set( ANDROID_NDK_LAYOUT "LINARO" )
+ elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
+ set( ANDROID_NDK_LAYOUT "ANDROID" )
+ endif()
+ endif()
+ set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
+ mark_as_advanced( ANDROID_NDK_LAYOUT )
+ if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+ set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+ set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE"
+ set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
+ endif()
+ get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
+
+ # try to detect change of NDK
+ if( CMAKE_AR )
+ string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length )
+ string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
+ if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH )
+ message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
+ " )
+ endif()
+ unset( __androidNdkPreviousPath )
+ unset( __length )
+ endif()
+endif()
+
+
# get all the details about standalone toolchain
if( BUILD_WITH_STANDALONE_TOOLCHAIN )
__DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
@@ -582,22 +638,27 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN )
endif()
endif()
-macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar )
- foreach( __toolchain ${${__availableToolchainsVar}} )
- if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK}/toolchains/${__toolchain}/prebuilt/" )
+macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
+ foreach( __toolchain ${${__availableToolchainsLst}} )
+ if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
else()
set( __gcc_toolchain "${__toolchain}" )
endif()
- __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK}/toolchains/${__gcc_toolchain}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+ __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" )
if( __machine )
- string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?$" __version "${__gcc_toolchain}" )
- string( REGEX MATCH "^[^-]+" __arch "${__gcc_toolchain}" )
+ string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" )
+ if( __machine MATCHES i686 )
+ set( __arch "x86" )
+ elseif( __machine MATCHES arm )
+ set( __arch "arm" )
+ elseif( __machine MATCHES mipsel )
+ set( __arch "mipsel" )
+ endif()
list( APPEND __availableToolchainMachines "${__machine}" )
list( APPEND __availableToolchainArchs "${__arch}" )
list( APPEND __availableToolchainCompilerVersions "${__version}" )
- else()
- list( REMOVE_ITEM ${__availableToolchainsVar} "${__toolchain}" )
+ list( APPEND ${__availableToolchainsVar} "${__toolchain}" )
endif()
unset( __gcc_toolchain )
endforeach()
@@ -611,19 +672,31 @@ if( BUILD_WITH_ANDROID_NDK )
set( __availableToolchainMachines "" )
set( __availableToolchainArchs "" )
set( __availableToolchainCompilerVersions "" )
- if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/" )
+ if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
# do not go through all toolchains if we know the name
- set( __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains )
+ set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+ if( __availableToolchains )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+ endif()
+ endif()
endif()
if( NOT __availableToolchains )
- file( GLOB __availableToolchains RELATIVE "${ANDROID_NDK}/toolchains" "${ANDROID_NDK}/toolchains/*" )
+ file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
if( __availableToolchains )
- list(SORT __availableToolchains) # we need clang to go after gcc
+ list(SORT __availableToolchainsLst) # we need clang to go after gcc
+ endif()
+ __LIST_FILTER( __availableToolchainsLst "^[.]" )
+ __LIST_FILTER( __availableToolchainsLst "llvm" )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+ __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+ if( __availableToolchains )
+ set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+ endif()
endif()
- __LIST_FILTER( __availableToolchains "^[.]" )
- __LIST_FILTER( __availableToolchains "llvm" )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains )
endif()
if( NOT __availableToolchains )
message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." )
@@ -636,11 +709,11 @@ set( __uniqToolchainArchNames ${__availableToolchainArchs} )
list( REMOVE_DUPLICATES __uniqToolchainArchNames )
list( SORT __uniqToolchainArchNames )
foreach( __arch ${__uniqToolchainArchNames} )
-list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
+ list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
endforeach()
unset( __uniqToolchainArchNames )
if( NOT ANDROID_SUPPORTED_ABIS )
-message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
+ message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
endif()
# choose target ABI
@@ -752,6 +825,7 @@ else()
list( GET __availableToolchainArchs ${__idx} __toolchainArch )
if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME )
list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
+ string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}")
if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
set( __toolchainMaxVersion "${__toolchainVersion}" )
set( __toolchainIdx ${__idx} )
@@ -779,11 +853,22 @@ unset( __availableToolchainCompilerVersions )
# choose native API level
__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
string( REGEX MATCH "[0-9]+" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" )
-# TODO: filter out unsupported levels
+# adjust API level
+set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} )
+foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ if( NOT __level GREATER ANDROID_NATIVE_API_LEVEL AND NOT __level LESS __real_api_level )
+ set( __real_api_level ${__level} )
+ endif()
+endforeach()
+if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL EQUAL __real_api_level )
+ message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'")
+ set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} )
+endif()
+unset(__real_api_level)
# validate
list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
if( __levelIdx EQUAL -1 )
- message( SEND_ERROR "Specified Android native API level (${ANDROID_NATIVE_API_LEVEL}) is not supported by your NDK/toolchain." )
+ message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )
else()
if( BUILD_WITH_ANDROID_NDK )
__DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" )
@@ -893,7 +978,11 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN )
set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
if( NOT ANDROID_STL STREQUAL "none" )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" )
+ if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" )
+ # old location ( pre r8c )
+ set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
+ endif()
if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" )
list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" )
elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" )
@@ -944,11 +1033,11 @@ if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-4.6" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
- if( NOT EXISTS "${ANDROID_NDK}/toolchains/llvm-${ANDROID_CLANG_VERSION}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}/bin/clang${TOOL_OS_SUFFIX}" )
- message( FATAL_ERROR "Could not find the " )
+ if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
+ message( FATAL_ERROR "Could not find the Clang compiler driver" )
endif()
set( ANDROID_COMPILER_IS_CLANG 1 )
- set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/llvm-${ANDROID_CLANG_VERSION}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
else()
set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
unset( ANDROID_COMPILER_IS_CLANG CACHE )
@@ -962,7 +1051,7 @@ endif()
# setup paths and STL for NDK
if( BUILD_WITH_ANDROID_NDK )
- set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_GCC_TOOLCHAIN_NAME}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" )
if( ANDROID_STL STREQUAL "none" )
@@ -1021,11 +1110,11 @@ if( BUILD_WITH_ANDROID_NDK )
endif()
# find libsupc++.a - rtti & exceptions
if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" )
- if( ANDROID_NDK_RELEASE STRGREATER "r8" ) # r8b
- set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
- elseif( NOT ANDROID_NDK_RELEASE STRLESS "r7" AND ANDROID_NDK_RELEASE STRLESS "r8b")
- set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
- else( ANDROID_NDK_RELEASE STRLESS "r7" )
+ set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer
+ if( NOT EXISTS "${__libsupcxx}" )
+ set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8
+ endif()
+ if( NOT EXISTS "${__libsupcxx}" ) # before r7
if( ARMEABI_V7A )
if( ANDROID_FORCE_ARM_BUILD )
set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
@@ -1075,7 +1164,7 @@ unset( _ndk_ccache )
# setup the cross-compiler
if( NOT CMAKE_C_COMPILER )
- if( NDK_CCACHE )
+ if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" )
set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" )
if( ANDROID_COMPILER_IS_CLANG )
@@ -1147,11 +1236,25 @@ set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
remove_definitions( -DANDROID )
add_definitions( -DANDROID )
-if(ANDROID_SYSROOT MATCHES "[ ;\"]")
- set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
+if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ if( CMAKE_HOST_WIN32 )
+ # try to convert path to 8.3 form
+ file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" )
+ execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}"
+ OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE __result ERROR_QUIET )
+ if( __result EQUAL 0 )
+ file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT )
+ set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+ else()
+ set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
+ endif()
+ else()
+ set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" )
+ endif()
if( NOT _CMAKE_IN_TRY_COMPILE )
- # quotes will break try_compile and compiler identification
- message(WARNING "Your Android system root has non-alphanumeric symbols. It can break compiler features detection and the whole build.")
+ # quotes can break try_compile and compiler identification
+ message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n")
endif()
else()
set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
@@ -1159,38 +1262,52 @@ endif()
# NDK flags
if( ARMEABI OR ARMEABI_V7A )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -funwind-tables" )
if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
- # It is recommended to use the -mthumb compiler flag to force the generation
- # of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
- set( ANDROID_CXX_FLAGS_RELEASE "-mthumb" )
- set( ANDROID_CXX_FLAGS_DEBUG "-marm -finline-limit=64" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" )
+ endif()
else()
# always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
- # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc
- set( ANDROID_CXX_FLAGS_RELEASE "-marm" )
- set( ANDROID_CXX_FLAGS_DEBUG "-marm -finline-limit=300" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+ endif()
endif()
elseif( X86 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
- set( ANDROID_CXX_FLAGS_RELEASE "" )
- set( ANDROID_CXX_FLAGS_DEBUG "-finline-limit=300" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+ else()
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fPIC" )
+ endif()
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
elseif( MIPS )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -frename-registers" )
- set( ANDROID_CXX_FLAGS_RELEASE "-finline-limit=300 -fno-strict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-finline-functions -fgcse-after-reload -frerun-cse-after-loop" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
+ set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
+ set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
elseif()
set( ANDROID_CXX_FLAGS_RELEASE "" )
set( ANDROID_CXX_FLAGS_DEBUG "" )
endif()
-if( NOT X86 )
- set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
+set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
+
+if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
endif()
-set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
-set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -fomit-frame-pointer" )
-set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer" )
+if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/
+endif()
# ABI-specific flags
if( ARMEABI_V7A )
@@ -1208,22 +1325,18 @@ elseif( ARMEABI )
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" )
endif()
+if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " )
+ set( CMAKE_CXX_LINK_EXECUTABLE " -o " )
+else()
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " )
+ set( CMAKE_CXX_LINK_EXECUTABLE " -o " )
+endif()
+
# STL
if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
- if( ANDROID_STL MATCHES "gnustl" )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " )
- set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " )
- set( CMAKE_CXX_LINK_EXECUTABLE " -o " )
- else()
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " )
- set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " )
- set( CMAKE_CXX_LINK_EXECUTABLE " -o " )
- endif()
- if ( X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" )
- # workaround "undefined reference to `__dso_handle'" problem
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
- endif()
if( EXISTS "${__libstl}" )
set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" )
set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" )
@@ -1242,9 +1355,12 @@ if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
endif()
if( ANDROID_STL MATCHES "gnustl" )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} -lm" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} -lm" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -lm" )
+ if( NOT EXISTS "${ANDROID_LIBM_PATH}" )
+ set( ANDROID_LIBM_PATH -lm )
+ endif()
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" )
+ set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" )
endif()
endif()
@@ -1280,7 +1396,14 @@ if( ARMEABI_V7A )
endif()
if( ANDROID_NO_UNDEFINED )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
+ if( MIPS )
+ # there is some sysroot-related problem in mips linker...
+ if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" )
+ endif()
+ else()
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
+ endif()
endif()
if( ANDROID_SO_UNDEFINED )
@@ -1327,9 +1450,6 @@ if( ANDROID_COMPILER_IS_CLANG )
set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS}" )
endif()
if( BUILD_WITH_ANDROID_NDK )
- if(ANDROID_ARCH_NAME STREQUAL "arm" )
- set( ANDROID_CXX_FLAGS "-isystem ${ANDROID_CLANG_TOOLCHAIN_ROOT}/lib/clang/${ANDROID_CLANG_VERSION}/include ${ANDROID_CXX_FLAGS}" )
- endif()
set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" )
endif()
endif()
@@ -1345,6 +1465,12 @@ set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared li
set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" )
set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" )
+# put flags to cache (for debug purpose only)
+set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" )
+set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" )
+set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" )
+set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" )
+
# finish flags
set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
@@ -1357,9 +1483,9 @@ set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FL
set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
- set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
- set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
- set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
+ set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
+ set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
+ set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
endif()
# configure rtti
@@ -1386,6 +1512,43 @@ endif()
include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} )
link_directories( "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" )
+# detect if need link crtbegin_so.o explicitly
+if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK )
+ set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" )
+ string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" )
+ string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" )
+ string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "" "" __cmd "${__cmd}" )
+ string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "" "-shared" __cmd "${__cmd}" )
+ string( REPLACE "" "" __cmd "${__cmd}" )
+ string( REPLACE "" "" __cmd "${__cmd}" )
+ string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" )
+ string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" )
+ string( REPLACE "" "" __cmd "${__cmd}" )
+ separate_arguments( __cmd )
+ foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN )
+ if( ${__var} )
+ set( __tmp "${${__var}}" )
+ separate_arguments( __tmp )
+ string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}")
+ endif()
+ endforeach()
+ string( REPLACE "'" "" __cmd "${__cmd}" )
+ string( REPLACE "\"" "" __cmd "${__cmd}" )
+ execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET )
+ if( __cmd_result EQUAL 0 )
+ set( ANDROID_EXPLICIT_CRT_LINK ON )
+ else()
+ set( ANDROID_EXPLICIT_CRT_LINK OFF )
+ endif()
+endif()
+
+if( ANDROID_EXPLICIT_CRT_LINK )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+endif()
+
# setup output directories
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
@@ -1475,7 +1638,9 @@ endmacro()
if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
set( __toolchain_config "")
foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN ANDROID_SET_OBSOLETE_VARIABLES
+ ANDROID_NDK_HOST_X64
ANDROID_NDK
+ ANDROID_NDK_LAYOUT
ANDROID_STANDALONE_TOOLCHAIN
ANDROID_TOOLCHAIN_NAME
ANDROID_ABI
@@ -1489,6 +1654,8 @@ if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
ANDROID_GOLD_LINKER
ANDROID_NOEXECSTACK
ANDROID_RELRO
+ ANDROID_LIBM_PATH
+ ANDROID_EXPLICIT_CRT_LINK
)
if( DEFINED ${__var} )
if( "${__var}" MATCHES " ")
@@ -1531,6 +1698,8 @@ endif()
# ANDROID_NDK
# ANDROID_STANDALONE_TOOLCHAIN
# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
+# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
+# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
# LIBRARY_OUTPUT_PATH_ROOT :
# NDK_CCACHE :
# Obsolete:
@@ -1553,7 +1722,7 @@ endif()
# BUILD_ANDROID : always TRUE
# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
-# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86", "linux-x86_64" or "darwin-x86" depending on host platform
+# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86" or "mips" depending on ANDROID_ABI
# ANDROID_NDK_RELEASE : one of r5, r5b, r5c, r6, r6b, r7, r7b, r7c, r8, r8b, r8c, r8d, r8e; set only for NDK
# ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI
@@ -1576,6 +1745,7 @@ endif()
# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
# ANDROID_CLANG_VERSION : version of clang compiler if clang is used
+# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos`
#
# Defaults:
# ANDROID_DEFAULT_NDK_API_LEVEL
diff --git a/cmake/FindDBus.cmake b/cmake/FindDBus.cmake
new file mode 100644
index 000000000..b002a754b
--- /dev/null
+++ b/cmake/FindDBus.cmake
@@ -0,0 +1,73 @@
+# - Try to find the low-level D-Bus library
+# Once done this will define
+#
+# DBUS_FOUND - system has D-Bus
+# DBUS_INCLUDE_DIR - the D-Bus include directory
+# DBUS_ARCH_INCLUDE_DIR - the D-Bus architecture-specific include directory
+# DBUS_LIBRARIES - the libraries needed to use D-Bus
+
+# Copyright (c) 2008, Kevin Kofler,
+# modeled after FindLibArt.cmake:
+# Copyright (c) 2006, Alexander Neundorf,
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+if (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
+ # in cache already
+ SET(DBUS_FOUND TRUE)
+
+else (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
+ IF (NOT WIN32)
+ FIND_PACKAGE(PkgConfig)
+ IF (PKG_CONFIG_FOUND)
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ pkg_check_modules(_DBUS_PC QUIET dbus-1)
+ ENDIF (PKG_CONFIG_FOUND)
+ ENDIF (NOT WIN32)
+
+ FIND_PATH(DBUS_INCLUDE_DIR dbus/dbus.h
+ ${_DBUS_PC_INCLUDE_DIRS}
+ /usr/include
+ /usr/include/dbus-1.0
+ /usr/local/include
+ )
+
+ FIND_PATH(DBUS_ARCH_INCLUDE_DIR dbus/dbus-arch-deps.h
+ ${_DBUS_PC_INCLUDE_DIRS}
+ /usr/lib${LIB_SUFFIX}/include
+ /usr/lib${LIB_SUFFIX}/dbus-1.0/include
+ /usr/lib64/include
+ /usr/lib64/dbus-1.0/include
+ /usr/lib/include
+ /usr/lib/dbus-1.0/include
+ )
+
+ FIND_LIBRARY(DBUS_LIBRARIES NAMES dbus-1 dbus
+ PATHS
+ ${_DBUS_PC_LIBDIR}
+ )
+
+
+ if (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+ set(DBUS_FOUND TRUE)
+ endif (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
+
+ if (DBUS_FOUND)
+ if (NOT DBus_FIND_QUIETLY)
+ message(STATUS "Found D-Bus: ${DBUS_LIBRARIES}")
+ endif (NOT DBus_FIND_QUIETLY)
+ else (DBUS_FOUND)
+ if (DBus_FIND_REQUIRED)
+ message(FATAL_ERROR "Could NOT find D-Bus")
+ endif (DBus_FIND_REQUIRED)
+ endif (DBUS_FOUND)
+
+ MARK_AS_ADVANCED(DBUS_INCLUDE_DIR DBUS_ARCH_INCLUDE_DIR DBUS_LIBRARIES)
+
+endif (DBUS_INCLUDE_DIR AND DBUS_ARCH_INCLUDE_DIR AND DBUS_LIBRARIES)
+
diff --git a/cmake/FindDbusGlib.cmake b/cmake/FindDbusGlib.cmake
new file mode 100644
index 000000000..ae966bc65
--- /dev/null
+++ b/cmake/FindDbusGlib.cmake
@@ -0,0 +1,38 @@
+# DbusGlib library detection
+#
+# Copyright 2013 Thinstuff Technologies GmbH
+# Copyright 2013 Armin Novak
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+find_package(PkgConfig)
+pkg_check_modules(PC_DBUS_GLIB QUIET dbus-glib-1)
+set(DBUS_GLIB_DEFINITIONS ${PC_DBUS_GLIB_CFLAGS_OTHER})
+
+find_path(DBUS_GLIB_INCLUDE_DIR dbus/dbus-glib.h
+ HINTS ${PC_DBUS_GLIB_INCLUDEDIR} ${PC_DBUS_GLIB_INCLUDE_DIRS}
+ PATH_SUFFIXES dbus-glib-1 )
+
+find_library(DBUS_GLIB_LIBRARY NAMES dbus-glib-1 dbus-glib
+ HINTS ${PC_DBUS_GLIB_LIBDIR} ${PC_DBUS_GLIB_LIBRARY_DIRS} )
+
+set(DBUS_GLIB_LIBRARIES ${DBUS_GLIB_LIBRARY} )
+set(DBUS_GLIB_INCLUDE_DIRS ${DBUS_GLIB_INCLUDE_DIR} )
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set DBUS_GLIB_FOUND to TRUE
+# if all listed variables are TRUE
+find_package_handle_standard_args(dbus-glib DEFAULT_MSG
+ DBUS_GLIB_LIBRARY DBUS_GLIB_INCLUDE_DIR)
+
+mark_as_advanced(DBUS_GLIB_INCLUDE_DIR DBUS_GLIB_LIBRARY )
diff --git a/cmake/FindDocBookXSL.cmake b/cmake/FindDocBookXSL.cmake
new file mode 100644
index 000000000..9192ef9b3
--- /dev/null
+++ b/cmake/FindDocBookXSL.cmake
@@ -0,0 +1,52 @@
+# Try to find DocBook XSL stylesheet
+# Once done, it will define:
+#
+# DOCBOOKXSL_FOUND - system has the required DocBook XML DTDs
+# DOCBOOKXSL_DIR - the directory containing the stylesheets
+# used to process DocBook XML
+
+# Copyright (c) 2010, Luigi Toscano,
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+set (STYLESHEET_PATH_LIST
+ share/xml/docbook/stylesheet/docbook-xsl
+ share/xml/docbook/xsl-stylesheets
+ share/sgml/docbook/xsl-stylesheets
+ share/xml/docbook/stylesheet/nwalsh/current
+ share/xml/docbook/stylesheet/nwalsh
+ share/xsl/docbook
+ share/xsl/docbook-xsl
+)
+
+find_path (DOCBOOKXSL_DIR lib/lib.xsl
+ PATHS ${CMAKE_SYSTEM_PREFIX_PATH}
+ PATH_SUFFIXES ${STYLESHEET_PATH_LIST}
+)
+
+if (NOT DOCBOOKXSL_DIR)
+ # hacks for systems that put the version in the stylesheet dirs
+ set (STYLESHEET_PATH_LIST)
+ foreach (STYLESHEET_PREFIX_ITER ${CMAKE_SYSTEM_PREFIX_PATH})
+ file(GLOB STYLESHEET_SUFFIX_ITER RELATIVE ${STYLESHEET_PREFIX_ITER}
+ ${STYLESHEET_PREFIX_ITER}/share/xml/docbook/xsl-stylesheets-*
+ )
+ if (STYLESHEET_SUFFIX_ITER)
+ list (APPEND STYLESHEET_PATH_LIST ${STYLESHEET_SUFFIX_ITER})
+ endif ()
+ endforeach ()
+
+ find_path (DOCBOOKXSL_DIR VERSION
+ PATHS ${CMAKE_SYSTEM_PREFIX_PATH}
+ PATH_SUFFIXES ${STYLESHEET_PATH_LIST}
+ )
+endif (NOT DOCBOOKXSL_DIR)
+
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args (DocBookXSL
+ "Could NOT find DocBook XSL stylesheets"
+ DOCBOOKXSL_DIR)
+
+mark_as_advanced (DOCBOOKXSL_DIR)
diff --git a/cmake/FindImageMagick.cmake b/cmake/FindImageMagick.cmake
new file mode 100644
index 000000000..4e8e6d598
--- /dev/null
+++ b/cmake/FindImageMagick.cmake
@@ -0,0 +1,237 @@
+# - Find the ImageMagick binary suite.
+# This module will search for a set of ImageMagick tools specified
+# as components in the FIND_PACKAGE call. Typical components include,
+# but are not limited to (future versions of ImageMagick might have
+# additional components not listed here):
+#
+# animate
+# compare
+# composite
+# conjure
+# convert
+# display
+# identify
+# import
+# mogrify
+# montage
+# stream
+#
+# If no component is specified in the FIND_PACKAGE call, then it only
+# searches for the ImageMagick executable directory. This code defines
+# the following variables:
+#
+# ImageMagick_FOUND - TRUE if all components are found.
+# ImageMagick_EXECUTABLE_DIR - Full path to executables directory.
+# ImageMagick__FOUND - TRUE if is found.
+# ImageMagick__EXECUTABLE - Full path to executable.
+# ImageMagick_VERSION_STRING - the version of ImageMagick found
+# (since CMake 2.8.8)
+#
+# ImageMagick_VERSION_STRING will not work for old versions like 5.2.3.
+#
+# There are also components for the following ImageMagick APIs:
+#
+# Magick++
+# MagickWand
+# MagickCore
+#
+# For these components the following variables are set:
+#
+# ImageMagick_FOUND - TRUE if all components are found.
+# ImageMagick_INCLUDE_DIRS - Full paths to all include dirs.
+# ImageMagick_LIBRARIES - Full paths to all libraries.
+# ImageMagick__FOUND - TRUE if is found.
+# ImageMagick__INCLUDE_DIRS - Full path to include dirs.
+# ImageMagick__LIBRARIES - Full path to libraries.
+#
+# Example Usages:
+# find_package(ImageMagick)
+# find_package(ImageMagick COMPONENTS convert)
+# find_package(ImageMagick COMPONENTS convert mogrify display)
+# find_package(ImageMagick COMPONENTS Magick++)
+# find_package(ImageMagick COMPONENTS Magick++ convert)
+#
+# Note that the standard FIND_PACKAGE features are supported
+# (i.e., QUIET, REQUIRED, etc.).
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+# Copyright 2007-2008 Miguel A. Figueroa-Villanueva
+# Copyright 2012 Rolf Eike Beer
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+#---------------------------------------------------------------------
+# Helper functions
+#---------------------------------------------------------------------
+function(FIND_IMAGEMAGICK_API component header)
+ set(ImageMagick_${component}_FOUND FALSE PARENT_SCOPE)
+
+ find_path(ImageMagick_${component}_INCLUDE_DIR
+ NAMES ${header}
+ PATHS
+ ${ImageMagick_INCLUDE_DIRS}
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include"
+ PATH_SUFFIXES
+ ImageMagick
+ DOC "Path to the ImageMagick include dir."
+ )
+ find_library(ImageMagick_${component}_LIBRARY
+ NAMES ${ARGN}
+ PATHS
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/lib"
+ DOC "Path to the ImageMagick Magick++ library."
+ )
+
+ if(ImageMagick_${component}_INCLUDE_DIR AND ImageMagick_${component}_LIBRARY)
+ set(ImageMagick_${component}_FOUND TRUE PARENT_SCOPE)
+
+ list(APPEND ImageMagick_INCLUDE_DIRS
+ ${ImageMagick_${component}_INCLUDE_DIR}
+ )
+ list(REMOVE_DUPLICATES ImageMagick_INCLUDE_DIRS)
+ set(ImageMagick_INCLUDE_DIRS ${ImageMagick_INCLUDE_DIRS} PARENT_SCOPE)
+
+ list(APPEND ImageMagick_LIBRARIES
+ ${ImageMagick_${component}_LIBRARY}
+ )
+ set(ImageMagick_LIBRARIES ${ImageMagick_LIBRARIES} PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(FIND_IMAGEMAGICK_EXE component)
+ set(_IMAGEMAGICK_EXECUTABLE
+ ${ImageMagick_EXECUTABLE_DIR}/${component}${CMAKE_EXECUTABLE_SUFFIX})
+ if(EXISTS ${_IMAGEMAGICK_EXECUTABLE})
+ set(ImageMagick_${component}_EXECUTABLE
+ ${_IMAGEMAGICK_EXECUTABLE}
+ PARENT_SCOPE
+ )
+ set(ImageMagick_${component}_FOUND TRUE PARENT_SCOPE)
+ else()
+ set(ImageMagick_${component}_FOUND FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
+#---------------------------------------------------------------------
+# Start Actual Work
+#---------------------------------------------------------------------
+# Try to find a ImageMagick installation binary path.
+find_path(ImageMagick_EXECUTABLE_DIR
+ NAMES mogrify${CMAKE_EXECUTABLE_SUFFIX}
+ PATHS
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]"
+ DOC "Path to the ImageMagick binary directory."
+ NO_DEFAULT_PATH
+ )
+find_path(ImageMagick_EXECUTABLE_DIR
+ NAMES mogrify${CMAKE_EXECUTABLE_SUFFIX}
+ )
+
+# Find each component. Search for all tools in same dir
+# ; otherwise they should be found
+# independently and not in a cohesive module such as this one.
+unset(ImageMagick_REQUIRED_VARS)
+unset(ImageMagick_DEFAULT_EXECUTABLES)
+foreach(component ${ImageMagick_FIND_COMPONENTS}
+ # DEPRECATED: forced components for backward compatibility
+ convert mogrify import montage composite
+ )
+ if(component STREQUAL "Magick++")
+ FIND_IMAGEMAGICK_API(Magick++ Magick++.h
+ Magick++ CORE_RL_Magick++_ Magick++-Q16 Magick++-Q8
+ )
+ list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY)
+ elseif(component STREQUAL "MagickWand")
+ FIND_IMAGEMAGICK_API(MagickWand wand/MagickWand.h
+ Wand MagickWand CORE_RL_wand_ MagickWand-Q16 MagickWand-Q8
+ )
+ list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY)
+ elseif(component STREQUAL "MagickCore")
+ FIND_IMAGEMAGICK_API(MagickCore magick/MagickCore.h
+ Magick MagickCore CORE_RL_magick_ MagickCore-6 MagickCore-Q16 MagickCore-Q8
+ )
+ list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickCore_LIBRARY)
+ else()
+ if(ImageMagick_EXECUTABLE_DIR)
+ FIND_IMAGEMAGICK_EXE(${component})
+ endif()
+
+ if(ImageMagick_FIND_COMPONENTS)
+ list(FIND ImageMagick_FIND_COMPONENTS ${component} is_requested)
+ if(is_requested GREATER -1)
+ list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_${component}_EXECUTABLE)
+ endif()
+ elseif(ImageMagick_${component}_EXECUTABLE)
+ # if no components were requested explicitly put all (default) executables
+ # in the list
+ list(APPEND ImageMagick_DEFAULT_EXECUTABLES ImageMagick_${component}_EXECUTABLE)
+ endif()
+ endif()
+endforeach()
+
+if(NOT ImageMagick_FIND_COMPONENTS AND NOT ImageMagick_DEFAULT_EXECUTABLES)
+ # No components were requested, and none of the default components were
+ # found. Just insert mogrify into the list of the default components to
+ # find so FPHSA below has something to check
+ list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_mogrify_EXECUTABLE)
+elseif(ImageMagick_DEFAULT_EXECUTABLES)
+ list(APPEND ImageMagick_REQUIRED_VARS ${ImageMagick_DEFAULT_EXECUTABLES})
+endif()
+
+set(ImageMagick_INCLUDE_DIRS ${ImageMagick_INCLUDE_DIRS})
+set(ImageMagick_LIBRARIES ${ImageMagick_LIBRARIES})
+
+if(ImageMagick_mogrify_EXECUTABLE)
+ execute_process(COMMAND ${ImageMagick_mogrify_EXECUTABLE} -version
+ OUTPUT_VARIABLE imagemagick_version
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(imagemagick_version MATCHES "^Version: ImageMagick [0-9]")
+ string(REGEX REPLACE "^Version: ImageMagick ([-0-9\\.]+).*" "\\1" ImageMagick_VERSION_STRING "${imagemagick_version}")
+ endif()
+ unset(imagemagick_version)
+endif()
+
+#---------------------------------------------------------------------
+# Standard Package Output
+#---------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ImageMagick
+ REQUIRED_VARS ${ImageMagick_REQUIRED_VARS}
+ VERSION_VAR ImageMagick_VERSION_STRING
+ )
+# Maintain consistency with all other variables.
+set(ImageMagick_FOUND ${IMAGEMAGICK_FOUND})
+
+#---------------------------------------------------------------------
+# DEPRECATED: Setting variables for backward compatibility.
+#---------------------------------------------------------------------
+set(IMAGEMAGICK_BINARY_PATH ${ImageMagick_EXECUTABLE_DIR}
+ CACHE PATH "Path to the ImageMagick binary directory.")
+set(IMAGEMAGICK_CONVERT_EXECUTABLE ${ImageMagick_convert_EXECUTABLE}
+ CACHE FILEPATH "Path to ImageMagick's convert executable.")
+set(IMAGEMAGICK_MOGRIFY_EXECUTABLE ${ImageMagick_mogrify_EXECUTABLE}
+ CACHE FILEPATH "Path to ImageMagick's mogrify executable.")
+set(IMAGEMAGICK_IMPORT_EXECUTABLE ${ImageMagick_import_EXECUTABLE}
+ CACHE FILEPATH "Path to ImageMagick's import executable.")
+set(IMAGEMAGICK_MONTAGE_EXECUTABLE ${ImageMagick_montage_EXECUTABLE}
+ CACHE FILEPATH "Path to ImageMagick's montage executable.")
+set(IMAGEMAGICK_COMPOSITE_EXECUTABLE ${ImageMagick_composite_EXECUTABLE}
+ CACHE FILEPATH "Path to ImageMagick's composite executable.")
+mark_as_advanced(
+ IMAGEMAGICK_BINARY_PATH
+ IMAGEMAGICK_CONVERT_EXECUTABLE
+ IMAGEMAGICK_MOGRIFY_EXECUTABLE
+ IMAGEMAGICK_IMPORT_EXECUTABLE
+ IMAGEMAGICK_MONTAGE_EXECUTABLE
+ IMAGEMAGICK_COMPOSITE_EXECUTABLE
+ )
\ No newline at end of file
diff --git a/cmake/FindPixman.cmake b/cmake/FindPixman.cmake
new file mode 100644
index 000000000..7bfca77bd
--- /dev/null
+++ b/cmake/FindPixman.cmake
@@ -0,0 +1,40 @@
+# - Find Pixman
+# Find the Pixman libraries
+#
+# This module defines the following variables:
+# PIXMAN_FOUND - true if PIXMAN_INCLUDE_DIR & PIXMAN_LIBRARY are found
+# PIXMAN_LIBRARIES - Set when PIXMAN_LIBRARY is found
+# PIXMAN_INCLUDE_DIRS - Set when PIXMAN_INCLUDE_DIR is found
+#
+# PIXMAN_INCLUDE_DIR - where to find pixman.h, etc.
+# PIXMAN_LIBRARY - the Pixman library
+#
+
+#=============================================================================
+# Copyright 2013 Marc-Andre Moreau
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+find_path(PIXMAN_INCLUDE_DIR NAMES pixman.h PATH_SUFFIXES pixman-1)
+
+find_library(PIXMAN_LIBRARY NAMES pixman-1)
+
+find_package_handle_standard_args(pixman-1 DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)
+
+if(PIXMAN-1_FOUND)
+ set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY})
+ set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(PIXMAN_INCLUDE_DIR PIXMAN_LIBRARY)
diff --git a/cmake/FindUDev.cmake b/cmake/FindUDev.cmake
new file mode 100644
index 000000000..f16761572
--- /dev/null
+++ b/cmake/FindUDev.cmake
@@ -0,0 +1,53 @@
+# razor-de: Configure libudev environment
+#
+# UDEV_FOUND - system has a libudev
+# UDEV_INCLUDE_DIR - where to find header files
+# UDEV_LIBRARIES - the libraries to link against udev
+# UDEV_STABLE - it's true when is the version greater or equals to 143 - version when the libudev was stabilized in its API
+#
+# copyright (c) 2011 Petr Vanek
+# Redistribution and use is allowed according to the terms of the BSD license.
+#
+
+FIND_PATH(
+ UDEV_INCLUDE_DIR
+ libudev.h
+ /usr/include
+ /usr/local/include
+ ${UDEV_PATH_INCLUDES}
+)
+
+FIND_LIBRARY(
+ UDEV_LIBRARIES
+ NAMES udev libudev
+ PATHS
+ /usr/lib${LIB_SUFFIX}
+ /usr/local/lib${LIB_SUFFIX}
+ ${UDEV_PATH_LIB}
+)
+
+IF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
+ SET(UDEV_FOUND "YES")
+ execute_process(COMMAND pkg-config --atleast-version=143 libudev RESULT_VARIABLE UDEV_STABLE)
+ # retvale is 0 of the condition is "true" so we need to negate the value...
+ if (UDEV_STABLE)
+set(UDEV_STABLE 0)
+ else (UDEV_STABLE)
+set(UDEV_STABLE 1)
+ endif (UDEV_STABLE)
+ message(STATUS "libudev stable: ${UDEV_STABLE}")
+ENDIF (UDEV_LIBRARIES AND UDEV_INCLUDE_DIR)
+
+IF (UDEV_FOUND)
+ MESSAGE(STATUS "Found UDev: ${UDEV_LIBRARIES}")
+ MESSAGE(STATUS " include: ${UDEV_INCLUDE_DIR}")
+ELSE (UDEV_FOUND)
+ MESSAGE(STATUS "UDev not found.")
+ MESSAGE(STATUS "UDev: You can specify includes: -DUDEV_PATH_INCLUDES=/opt/udev/include")
+ MESSAGE(STATUS " currently found includes: ${UDEV_INCLUDE_DIR}")
+ MESSAGE(STATUS "UDev: You can specify libs: -DUDEV_PATH_LIB=/opt/udev/lib")
+ MESSAGE(STATUS " currently found libs: ${UDEV_LIBRARIES}")
+ IF (UDev_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find UDev library")
+ ENDIF (UDev_FIND_REQUIRED)
+ENDIF (UDEV_FOUND)
diff --git a/cmake/FindUUID.cmake b/cmake/FindUUID.cmake
new file mode 100644
index 000000000..330e5caba
--- /dev/null
+++ b/cmake/FindUUID.cmake
@@ -0,0 +1,113 @@
+# - Try to find UUID
+# Once done this will define
+#
+# UUID_FOUND - system has UUID
+# UUID_INCLUDE_DIRS - the UUID include directory
+# UUID_LIBRARIES - Link these to use UUID
+# UUID_DEFINITIONS - Compiler switches required for using UUID
+#
+# Copyright (c) 2006 Andreas Schneider
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+
+if (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
+# in cache already
+set(UUID_FOUND TRUE)
+else (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
+find_path(UUID_INCLUDE_DIR
+NAMES
+uuid/uuid.h
+PATHS
+${UUID_DIR}/include
+$ENV{UUID_DIR}/include
+$ENV{UUID_DIR}
+${DELTA3D_EXT_DIR}/inc
+$ENV{DELTA_ROOT}/ext/inc
+$ENV{DELTA_ROOT}
+~/Library/Frameworks
+/Library/Frameworks
+/usr/local/include
+/usr/include
+/usr/include/gdal
+/sw/include # Fink
+/opt/local/include # DarwinPorts
+/opt/csw/include # Blastwave
+/opt/include
+[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include
+/usr/freeware/include
+
+)
+
+find_library(UUID_LIBRARY
+NAMES
+uuid
+PATHS
+${UUID_DIR}/lib
+$ENV{UUID_DIR}/lib
+$ENV{UUID_DIR}
+${DELTA3D_EXT_DIR}/lib
+$ENV{DELTA_ROOT}/ext/lib
+$ENV{DELTA_ROOT}
+$ENV{OSG_ROOT}/lib
+~/Library/Frameworks
+/Library/Frameworks
+/usr/local/lib
+/usr/lib
+/sw/lib
+/opt/local/lib
+/opt/csw/lib
+/opt/lib
+/usr/freeware/lib64
+)
+
+find_library(UUID_LIBRARY_DEBUG
+NAMES
+uuidd
+PATHS
+${UUID_DIR}/lib
+$ENV{UUID_DIR}/lib
+$ENV{UUID_DIR}
+${DELTA3D_EXT_DIR}/lib
+$ENV{DELTA_ROOT}/ext/lib
+$ENV{DELTA_ROOT}
+$ENV{OSG_ROOT}/lib
+~/Library/Frameworks
+/Library/Frameworks
+/usr/local/lib
+/usr/lib
+/sw/lib
+/opt/local/lib
+/opt/csw/lib
+/opt/lib
+/usr/freeware/lib64
+)
+
+set(UUID_INCLUDE_DIRS
+${UUID_INCLUDE_DIR}
+)
+set(UUID_LIBRARIES
+${UUID_LIBRARY}
+)
+
+if (UUID_INCLUDE_DIRS AND UUID_LIBRARIES)
+set(UUID_FOUND TRUE)
+endif (UUID_INCLUDE_DIRS AND UUID_LIBRARIES)
+
+if (UUID_FOUND)
+if (NOT UUID_FIND_QUIETLY)
+message(STATUS "Found UUID: ${UUID_LIBRARIES}")
+endif (NOT UUID_FIND_QUIETLY)
+else (UUID_FOUND)
+if (UUID_FIND_REQUIRED)
+message(FATAL_ERROR "Could not find UUID")
+endif (UUID_FIND_REQUIRED)
+endif (UUID_FOUND)
+
+# show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced view
+mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES)
+
+endif (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
diff --git a/cmake/FindXi.cmake b/cmake/FindXi.cmake
index d01f4002b..cdd352d82 100644
--- a/cmake/FindXi.cmake
+++ b/cmake/FindXi.cmake
@@ -14,6 +14,7 @@
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador
# Copyright 2011 Marc-Andre Moreau
+# Copyright 2013 Corey Clayton
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/cmake/FindXrender.cmake b/cmake/FindXrender.cmake
index 461217578..efcf72595 100644
--- a/cmake/FindXrender.cmake
+++ b/cmake/FindXrender.cmake
@@ -1,13 +1,13 @@
-# - Find Xrender
-# Find the Xrender libraries
+# - Find XRender
+# Find the XRender libraries
#
# This module defines the following variables:
-# Xrender_FOUND - true if Xrender_INCLUDE_DIR & Xrender_LIBRARY are found
-# Xrender_LIBRARIES - Set when Xrender_LIBRARY is found
-# Xrender_INCLUDE_DIRS - Set when Xrender_INCLUDE_DIR is found
+# XRENDER_FOUND - true if XRENDER_INCLUDE_DIR & XRENDER_LIBRARY are found
+# XRENDER_LIBRARIES - Set when Xrender_LIBRARY is found
+# XRENDER_INCLUDE_DIRS - Set when Xrender_INCLUDE_DIR is found
#
-# Xrender_INCLUDE_DIR - where to find Xrendernput2.h, etc.
-# Xrender_LIBRARY - the Xrender library
+# XRENDER_INCLUDE_DIR - where to find Xrender.h, etc.
+# XRENDER_LIBRARY - the Xrender library
#
#=============================================================================
@@ -36,9 +36,10 @@ include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xrender DEFAULT_MSG XRENDER_LIBRARY XRENDER_INCLUDE_DIR)
if(XRENDER_FOUND)
+
set(XRENDER_LIBRARIES ${XRENDER_LIBRARY})
set(XRENDER_INCLUDE_DIRS ${XRENDER_INCLUDE_DIR})
+
endif()
-mark_as_advanced(XRENDER_INCLUDE_DIRS XRENDER_LIBRARIES)
-
+mark_as_advanced(XRENDER_INCLUDE_DIR XRENDER_LIBRARY)
diff --git a/cmake/Findlibusb-1.0.cmake b/cmake/Findlibusb-1.0.cmake
new file mode 100644
index 000000000..0163bd521
--- /dev/null
+++ b/cmake/Findlibusb-1.0.cmake
@@ -0,0 +1,98 @@
+# - Try to find libusb-1.0
+# Once done this will define
+#
+# LIBUSB_1_FOUND - system has libusb
+# LIBUSB_1_INCLUDE_DIRS - the libusb include directory
+# LIBUSB_1_LIBRARIES - Link these to use libusb
+# LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb
+#
+# Adapted from cmake-modules Google Code project
+#
+# Copyright (c) 2006 Andreas Schneider
+#
+# (Changes for libusb) Copyright (c) 2008 Kyle Machulis
+#
+# Redistribution and use is allowed according to the terms of the New BSD license.
+#
+# CMake-Modules Project New BSD License
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the CMake-Modules Project nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
+ # in cache already
+ set(LIBUSB_FOUND TRUE)
+else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
+ find_path(LIBUSB_1_INCLUDE_DIR
+ NAMES
+libusb.h
+ PATHS
+ /usr/include
+ /usr/local/include
+ /opt/local/include
+ /sw/include
+PATH_SUFFIXES
+libusb-1.0
+ )
+
+ find_library(LIBUSB_1_LIBRARY
+ NAMES
+ usb-1.0 usb
+ PATHS
+ /usr/lib
+ /usr/local/lib
+ /opt/local/lib
+ /sw/lib
+ )
+
+ set(LIBUSB_1_INCLUDE_DIRS
+ ${LIBUSB_1_INCLUDE_DIR}
+ )
+ set(LIBUSB_1_LIBRARIES
+ ${LIBUSB_1_LIBRARY}
+)
+
+ if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
+ set(LIBUSB_1_FOUND TRUE)
+ endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
+
+ if (LIBUSB_1_FOUND)
+ if (NOT libusb_1_FIND_QUIETLY)
+ message(STATUS "Found libusb-1.0:")
+message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
+message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
+ endif (NOT libusb_1_FIND_QUIETLY)
+ else (LIBUSB_1_FOUND)
+ if (libusb_1_FIND_REQUIRED)
+ message(FATAL_ERROR "Could not find libusb")
+ endif (libusb_1_FIND_REQUIRED)
+ endif (LIBUSB_1_FOUND)
+
+ # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
+ mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
+
+endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
diff --git a/cmake/MSVCRuntime.cmake b/cmake/MSVCRuntime.cmake
index c71a750a5..1c59932c3 100644
--- a/cmake/MSVCRuntime.cmake
+++ b/cmake/MSVCRuntime.cmake
@@ -5,17 +5,20 @@ macro(configure_msvc_runtime)
if("${MSVC_RUNTIME}" STREQUAL "")
set(MSVC_RUNTIME "dynamic")
endif()
+
# Set compiler options.
set(variables
+ CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELWITHDEBINFO
+ CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELEASE
- CMAKE_CXX_FLAGS_RELWITHDEBINFO
- )
+ CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+
if(${MSVC_RUNTIME} STREQUAL "static")
message(STATUS "MSVC: using statically-linked runtime (/MT and /MTd).")
foreach(variable ${variables})
@@ -31,6 +34,25 @@ macro(configure_msvc_runtime)
endif()
endforeach()
endif()
+
+ foreach(variable ${variables})
+ if(${variable} MATCHES "/Ob0")
+ string(REGEX REPLACE "/Ob0" "/Ob2" ${variable} "${${variable}}")
+ endif()
+ endforeach()
+
+ foreach(variable ${variables})
+ if(${variable} MATCHES "/W3")
+ string(REGEX REPLACE "/W3" "/W2" ${variable} "${${variable}}")
+ endif()
+ endforeach()
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
+
foreach(variable ${variables})
set(${variable} "${${variable}}" CACHE STRING "MSVC_${variable}" FORCE)
endforeach()
diff --git a/cmake/MergeStaticLibs.cmake b/cmake/MergeStaticLibs.cmake
new file mode 100644
index 000000000..a0673fa7e
--- /dev/null
+++ b/cmake/MergeStaticLibs.cmake
@@ -0,0 +1,130 @@
+
+# Copyright (C) 2012 Modelon AB
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the BSD style license.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# FMILIB_License.txt file for more details.
+
+# You should have received a copy of the FMILIB_License.txt file
+# along with this program. If not, contact Modelon AB .
+
+# Merge_static_libs(outlib lib1 lib2 ... libn) merges a number of static
+# libs into a single static library
+function(merge_static_libs outlib)
+ set(libs ${ARGV})
+ list(REMOVE_AT libs 0)
+# Create a dummy file that the target will depend on
+ set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${outlib}_dummy.c)
+ file(WRITE ${dummyfile} "const char * dummy = \"${dummyfile}\";")
+
+ add_library(${outlib} STATIC ${dummyfile})
+
+ if("${CMAKE_CFG_INTDIR}" STREQUAL ".")
+ set(multiconfig FALSE)
+ else()
+ set(multiconfig TRUE)
+ endif()
+
+# First get the file names of the libraries to be merged
+ foreach(lib ${libs})
+ get_target_property(libtype ${lib} TYPE)
+ if(NOT libtype STREQUAL "STATIC_LIBRARY")
+ message(FATAL_ERROR "Merge_static_libs can only process static libraries")
+ endif()
+ if(multiconfig)
+ foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
+ get_target_property("libfile_${CONFIG_TYPE}" ${lib} "LOCATION_${CONFIG_TYPE}")
+ list(APPEND libfiles_${CONFIG_TYPE} ${libfile_${CONFIG_TYPE}})
+ endforeach()
+ else()
+ get_target_property(libfile ${lib} LOCATION)
+ list(APPEND libfiles "${libfile}")
+ endif(multiconfig)
+ endforeach()
+ #message(STATUS "will be merging ${libfiles}")
+# Just to be sure: cleanup from duplicates
+ if(multiconfig)
+ foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
+ list(REMOVE_DUPLICATES libfiles_${CONFIG_TYPE})
+ set(libfiles ${libfiles} ${libfiles_${CONFIG_TYPE}})
+ endforeach()
+ endif()
+ list(REMOVE_DUPLICATES libfiles)
+
+# Now the easy part for MSVC and for MAC
+ if(MSVC)
+ # lib.exe does the merging of libraries just need to conver the list into string
+ foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
+ set(flags "")
+ foreach(lib ${libfiles_${CONFIG_TYPE}})
+ set(flags "${flags} ${lib}")
+ endforeach()
+ string(TOUPPER "STATIC_LIBRARY_FLAGS_${CONFIG_TYPE}" PROPNAME)
+ set_target_properties(${outlib} PROPERTIES ${PROPNAME} "${flags}")
+ endforeach()
+
+ elseif(APPLE)
+ # Use OSX's libtool to merge archives
+ if(multiconfig)
+ message(FATAL_ERROR "Multiple configurations are not supported")
+ endif()
+ get_target_property(outfile ${outlib} LOCATION)
+ add_custom_command(TARGET ${outlib} POST_BUILD
+ COMMAND rm ${outfile}
+ COMMAND /usr/bin/libtool -static -o ${outfile}
+ ${libfiles}
+ )
+ else()
+ # general UNIX - need to "ar -x" and then "ar -ru"
+ if(multiconfig)
+ message(FATAL_ERROR "Multiple configurations are not supported")
+ endif()
+ get_target_property(outfile ${outlib} LOCATION)
+ message(STATUS "outfile location is ${outfile}")
+ foreach(lib ${libfiles})
+# objlistfile will contain the list of object files for the library
+ set(objlistfile ${lib}.objlist)
+ set(objdir ${lib}.objdir)
+ set(objlistcmake ${objlistfile}.cmake)
+# we only need to extract files once
+ if(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/cmake.check_cache IS_NEWER_THAN ${objlistcmake})
+#---------------------------------
+ FILE(WRITE ${objlistcmake}
+"# Extract object files from the library
+message(STATUS \"Extracting object files from ${lib}\")
+EXECUTE_PROCESS(COMMAND ${CMAKE_AR} -x ${lib}
+ WORKING_DIRECTORY ${objdir})
+# save the list of object files
+EXECUTE_PROCESS(COMMAND ls .
+ OUTPUT_FILE ${objlistfile}
+ WORKING_DIRECTORY ${objdir})")
+#---------------------------------
+ file(MAKE_DIRECTORY ${objdir})
+ add_custom_command(
+ OUTPUT ${objlistfile}
+ COMMAND ${CMAKE_COMMAND} -P ${objlistcmake}
+ DEPENDS ${lib})
+ endif()
+ list(APPEND extrafiles "${objlistfile}")
+ # relative path is needed by ar under MSYS
+ file(RELATIVE_PATH objlistfilerpath ${objdir} ${objlistfile})
+ add_custom_command(TARGET ${outlib} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_AR} ru ${outfile} @${objlistfilerpath}"
+ COMMAND ${CMAKE_AR} ru "${outfile}" @"${objlistfilerpath}"
+ WORKING_DIRECTORY ${objdir})
+ endforeach()
+ add_custom_command(TARGET ${outlib} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_RANLIB} ${outfile}"
+ COMMAND ${CMAKE_RANLIB} ${outfile})
+ endif()
+ file(WRITE ${dummyfile}.base "const char* ${outlib}_sublibs=\"${libs}\";")
+ add_custom_command(
+ OUTPUT ${dummyfile}
+ COMMAND ${CMAKE_COMMAND} -E copy ${dummyfile}.base ${dummyfile}
+ DEPENDS ${libs} ${extrafiles})
+
+endfunction()
diff --git a/cmake/today.cmake b/cmake/today.cmake
new file mode 100644
index 000000000..51d0031a8
--- /dev/null
+++ b/cmake/today.cmake
@@ -0,0 +1,16 @@
+# This script returns the current date in ISO format
+#
+# YYYY-MM-DD
+#
+MACRO (TODAY RESULT)
+ IF (WIN32)
+ EXECUTE_PROCESS(COMMAND "cmd" " /C date +%Y-%m-%d" OUTPUT_VARIABLE ${RESULT})
+ string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}})
+ ELSEIF(UNIX)
+ EXECUTE_PROCESS(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE ${RESULT})
+ string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}})
+ ELSE (WIN32)
+ MESSAGE(SEND_ERROR "date not implemented")
+ SET(${RESULT} 000000)
+ ENDIF (WIN32)
+ENDMACRO (TODAY)
diff --git a/config.h.in b/config.h.in
index 63de66d8d..83b0abecb 100755
--- a/config.h.in
+++ b/config.h.in
@@ -30,6 +30,7 @@
#cmakedefine HAVE_SYS_SELECT_H
#cmakedefine HAVE_SYS_STRTIO_H
#cmakedefine HAVE_EVENTFD_H
+#cmakedefine HAVE_TIMERFD_H
#cmakedefine HAVE_TM_GMTOFF
diff --git a/cunit/test_rfx.c b/cunit/test_rfx.c
index aae5b2472..153c7cc64 100644
--- a/cunit/test_rfx.c
+++ b/cunit/test_rfx.c
@@ -404,7 +404,7 @@ void test_message(void)
message = rfx_process_message(context, s->pointer, s->capacity);
if (i == 0)
{
- for (j = 0; j < message->num_tiles; j++)
+ for (j = 0; j < message->numTiles; j++)
{
dump_ppm_image(message->tiles[j]->data);
}
diff --git a/docs/README.android b/docs/README.android
index 44a4dbd67..e83af9107 100644
--- a/docs/README.android
+++ b/docs/README.android
@@ -34,8 +34,8 @@ However, any other static build should work as well.
To build openssl:
-git clone git@github.com:bmiklautz/Android-external-openssl-ndk-static.git
-cd Android-external-openssl-ndk-static
+git clone git@github.com:bmiklautz/android-external-openssl-ndk-static.git
+cd android-external-openssl-ndk-static
ndk-build # found in the Android NDK
diff --git a/docs/README.directfb b/docs/README.directfb
new file mode 100644
index 000000000..db72c0e85
--- /dev/null
+++ b/docs/README.directfb
@@ -0,0 +1,3 @@
+The dfreerdp FreeRDP client is currently orphaned and unmaintained so please don't expect it to build and work without problems.
+
+If you are interested to update and maintain the dfreerdp client please let us know.
diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h
index 4aa209481..88b1bbe79 100644
--- a/include/freerdp/channels/rdpdr.h
+++ b/include/freerdp/channels/rdpdr.h
@@ -138,17 +138,7 @@ enum FILE_CREATE_OPTION
#define FILE_WRITE_ATTRIBUTES 0x00000100
#endif
-#define DELETE 0x00010000
-#define READ_CONTROL 0x00020000
-#define WRITE_DAC 0x00040000
-#define WRITE_OWNER 0x00080000
-#define SYNCHRONIZE 0x00100000
-#define ACCESS_SYSTEM_SECURITY 0x01000000
-#define MAXIMUM_ALLOWED 0x02000000
-#define GENERIC_ALL 0x10000000
-#define GENERIC_EXECUTE 0x20000000
-#define GENERIC_WRITE 0x40000000
-#define GENERIC_READ 0x80000000
+#include
#endif
diff --git a/include/freerdp/client.h b/include/freerdp/client.h
index 67d7a5ebf..ddca7169c 100644
--- a/include/freerdp/client.h
+++ b/include/freerdp/client.h
@@ -84,8 +84,9 @@ FREERDP_API freerdp* freerdp_client_get_instance(rdpContext* context);
FREERDP_API HANDLE freerdp_client_get_thread(rdpContext* context);
FREERDP_API int freerdp_client_parse_command_line(rdpContext* context, int argc, char** argv);
-FREERDP_API int freerdp_client_parse_connection_file(rdpContext* context, char* filename);
+FREERDP_API int freerdp_client_parse_connection_file(rdpContext* context, const char* filename);
FREERDP_API int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffer, size_t size);
+FREERDP_API int freerdp_client_write_connection_file(rdpContext* context, const char* filename, BOOL unicode);
#ifdef __cplusplus
}
diff --git a/include/freerdp/client/disp.h b/include/freerdp/client/disp.h
new file mode 100644
index 000000000..fa747db52
--- /dev/null
+++ b/include/freerdp/client/disp.h
@@ -0,0 +1,64 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Display Update Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_CHANNEL_CLIENT_DISP_H
+#define FREERDP_CHANNEL_CLIENT_DISP_H
+
+#define ORIENTATION_LANDSCAPE 0
+#define ORIENTATION_PORTRAIT 90
+#define ORIENTATION_LANDSCAPE_FLIPPED 180
+#define ORIENTATION_PORTRAIT_FLIPPED 270
+
+#define DISPLAY_CONTROL_MONITOR_PRIMARY 0x00000001
+
+struct _DISPLAY_CONTROL_MONITOR_LAYOUT
+{
+ UINT32 Flags;
+ INT32 Left;
+ INT32 Top;
+ UINT32 Width;
+ UINT32 Height;
+ UINT32 PhysicalWidth;
+ UINT32 PhysicalHeight;
+ UINT32 Orientation;
+ UINT32 DesktopScaleFactor;
+ UINT32 DeviceScaleFactor;
+};
+typedef struct _DISPLAY_CONTROL_MONITOR_LAYOUT DISPLAY_CONTROL_MONITOR_LAYOUT;
+
+/**
+ * Client Interface
+ */
+
+#define DISP_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::DisplayControl"
+
+typedef struct _disp_client_context DispClientContext;
+
+typedef int (*pcDispSendMonitorLayout)(DispClientContext* context, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors);
+
+struct _disp_client_context
+{
+ void* handle;
+ void* custom;
+
+ pcDispSendMonitorLayout SendMonitorLayout;
+};
+
+#endif /* FREERDP_CHANNEL_CLIENT_DISP_H */
+
diff --git a/include/freerdp/client/file.h b/include/freerdp/client/file.h
index e83aa5ced..8fffdfbe8 100644
--- a/include/freerdp/client/file.h
+++ b/include/freerdp/client/file.h
@@ -137,12 +137,12 @@ typedef struct rdp_file rdpFile;
extern "C" {
#endif
-FREERDP_API BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name);
+FREERDP_API BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name);
FREERDP_API BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t size);
FREERDP_API BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings);
FREERDP_API BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings);
-FREERDP_API BOOL freerdp_client_write_rdp_file(rdpFile* file, char* name, BOOL unicode);
+FREERDP_API BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode);
FREERDP_API size_t freerdp_client_write_rdp_file_buffer(rdpFile* file, char* buffer, size_t size);
FREERDP_API rdpFile* freerdp_client_rdp_file_new(void);
diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h
index a0a2e4c82..c652a921b 100644
--- a/include/freerdp/codec/bitmap.h
+++ b/include/freerdp/codec/bitmap.h
@@ -23,6 +23,12 @@
#include
#include
+#include
+#include
+
FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp);
+FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
+ wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
+
#endif /* FREERDP_CODEC_BITMAP_H */
diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h
index 16fc580f1..9601fb8c2 100644
--- a/include/freerdp/codec/nsc.h
+++ b/include/freerdp/codec/nsc.h
@@ -42,9 +42,25 @@ struct _NSC_STREAM
};
typedef struct _NSC_STREAM NSC_STREAM;
+struct _NSC_MESSAGE
+{
+ int x;
+ int y;
+ UINT32 width;
+ UINT32 height;
+ BYTE* data;
+ int scanline;
+ UINT32 MaxPlaneSize;
+ BYTE* PlaneBuffers[5];
+ UINT32 OrgByteCount[4];
+ UINT32 PlaneByteCount[4];
+};
+typedef struct _NSC_MESSAGE NSC_MESSAGE;
+
typedef struct _NSC_CONTEXT_PRIV NSC_CONTEXT_PRIV;
typedef struct _NSC_CONTEXT NSC_CONTEXT;
+
struct _NSC_CONTEXT
{
UINT32 OrgByteCount[4]; /* original byte length of luma, chroma orange, chroma green, alpha variable in order */
@@ -52,15 +68,15 @@ struct _NSC_CONTEXT
UINT16 bpp;
UINT16 width;
UINT16 height;
- BYTE* bmpdata; /* final argb values in little endian order */
- UINT32 bmpdata_length; /* the maximum length of the buffer that bmpdata points to */
+ BYTE* BitmapData; /* final argb values in little endian order */
+ UINT32 BitmapDataLength; /* the maximum length of the buffer that bmpdata points to */
RDP_PIXEL_FORMAT pixel_format;
/* color palette allocated by the application */
const BYTE* palette;
void (*decode)(NSC_CONTEXT* context);
- void (*encode)(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride);
+ void (*encode)(NSC_CONTEXT* context, BYTE* BitmapData, int rowstride);
NSC_CONTEXT_PRIV* priv;
};
@@ -73,6 +89,11 @@ FREERDP_API void nsc_compose_message(NSC_CONTEXT* context, wStream* s,
BYTE* bmpdata, int width, int height, int rowstride);
FREERDP_API void nsc_context_free(NSC_CONTEXT* context);
+FREERDP_API NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
+ int width, int height, int scanline, int* numMessages, int maxDataSize);
+FREERDP_API int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message);
+FREERDP_API int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h
index d3ba0536a..254cadfb5 100644
--- a/include/freerdp/codec/rfx.h
+++ b/include/freerdp/codec/rfx.h
@@ -22,6 +22,7 @@
#include
#include
+#include
#include
#include
@@ -50,18 +51,36 @@ struct _RFX_TILE
{
UINT16 x;
UINT16 y;
+ int width;
+ int height;
BYTE* data;
+ int scanline;
+
+ BYTE quantIdxY;
+ BYTE quantIdxCb;
+ BYTE quantIdxCr;
+ UINT16 xIdx;
+ UINT16 yIdx;
+ UINT16 YLen;
+ UINT16 CbLen;
+ UINT16 CrLen;
+ BYTE* YData;
+ BYTE* CbData;
+ BYTE* CrData;
};
typedef struct _RFX_TILE RFX_TILE;
struct _RFX_MESSAGE
{
+ UINT32 frameIdx;
+
/**
* The rects array represents the updated region of the frame. The UI
* requires to clip drawing destination base on the union of the rects.
*/
- UINT16 num_rects;
+ UINT16 numRects;
RFX_RECT* rects;
+ BOOL freeRects;
/**
* The tiles array represents the actual frame data. Each tile is always
@@ -69,15 +88,35 @@ struct _RFX_MESSAGE
* rects described above) are valid. Pixels outside of the region may
* contain arbitrary data.
*/
- UINT16 num_tiles;
+ UINT16 numTiles;
RFX_TILE** tiles;
+
+ UINT16 numQuant;
+ UINT32* quantVals;
+
+ UINT32 tilesDataSize;
+
+ BOOL freeArray;
};
typedef struct _RFX_MESSAGE RFX_MESSAGE;
typedef struct _RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV;
+enum _RFX_STATE
+{
+ RFX_STATE_INITIAL,
+ RFX_STATE_SERVER_UNINITIALIZED,
+ RFX_STATE_SEND_HEADERS,
+ RFX_STATE_SEND_FRAME_DATA,
+ RFX_STATE_FRAME_DATA_SENT,
+ RFX_STATE_FINAL
+};
+typedef enum _RFX_STATE RFX_STATE;
+
struct _RFX_CONTEXT
{
+ RFX_STATE state;
+
UINT16 flags;
UINT16 properties;
UINT16 width;
@@ -93,19 +132,20 @@ struct _RFX_CONTEXT
const BYTE* palette;
/* temporary data within a frame */
- UINT32 frame_idx;
- BOOL header_processed;
- BYTE num_quants;
+ UINT32 frameIdx;
+ BYTE numQuant;
UINT32* quants;
- BYTE quant_idx_y;
- BYTE quant_idx_cb;
- BYTE quant_idx_cr;
+ BYTE quantIdxY;
+ BYTE quantIdxCb;
+ BYTE quantIdxCr;
/* routines */
void (*quantization_decode)(INT16* buffer, const UINT32* quantization_values);
void (*quantization_encode)(INT16* buffer, const UINT32* quantization_values);
void (*dwt_2d_decode)(INT16* buffer, INT16* dwt_buffer);
void (*dwt_2d_encode)(INT16* buffer, INT16* dwt_buffer);
+ int (*rlgr_decode)(RLGR_MODE mode, const BYTE* data, int data_size, INT16* buffer, int buffer_size);
+ int (*rlgr_encode)(RLGR_MODE mode, const INT16* data, int data_size, BYTE* buffer, int buffer_size);
/* private definitions */
RFX_CONTEXT_PRIV* priv;
@@ -128,6 +168,12 @@ FREERDP_API void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s);
FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s,
const RFX_RECT* rects, int num_rects, BYTE* image_data, int width, int height, int rowstride);
+FREERDP_API RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
+ int numRects, BYTE* data, int width, int height, int scanline);
+FREERDP_API RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects,
+ BYTE* data, int width, int height, int scanline, int* numMessages, int maxDataSize);
+FREERDP_API void rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h
index c396679b3..7e9aca995 100644
--- a/include/freerdp/crypto/tls.h
+++ b/include/freerdp/crypto/tls.h
@@ -61,6 +61,7 @@ FREERDP_API int tls_write_all(rdpTls* tls, BYTE* data, int length);
FREERDP_API int tls_wait_read(rdpTls* tls);
FREERDP_API int tls_wait_write(rdpTls* tls);
+FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
diff --git a/include/freerdp/error.h b/include/freerdp/error.h
old mode 100644
new mode 100755
index 8b0abd8f0..3c00b5c13
--- a/include/freerdp/error.h
+++ b/include/freerdp/error.h
@@ -20,6 +20,10 @@
#ifndef FREERDP_ERROR_H
#define FREERDP_ERROR_H
+#include
+
+#include
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -128,6 +132,9 @@ extern "C" {
#define ERRINFO_SUCCESS 0x00000000
#define ERRINFO_NONE 0xFFFFFFFF
+FREERDP_API const char* freerdp_get_error_info_string(UINT32 code);
+FREERDP_API const char* freerdp_get_error_info_name(UINT32 code);
+
/**
* This static variable holds an error code if the return value from connect is FALSE.
* This variable is always set to 0 in the beginning of the connect sequence.
@@ -135,7 +142,7 @@ extern "C" {
* The value can hold one of the defined error codes below OR an error according to errno
*/
-extern int connectErrorCode;
+FREERDP_API extern int connectErrorCode;
#define ERRORSTART 10000
#define PREECONNECTERROR ERRORSTART + 1
diff --git a/include/freerdp/event.h b/include/freerdp/event.h
index 7753e133d..3f6d51196 100644
--- a/include/freerdp/event.h
+++ b/include/freerdp/event.h
@@ -41,6 +41,20 @@ DEFINE_EVENT_BEGIN(ResizeWindow)
int width;
int height;
DEFINE_EVENT_END(ResizeWindow)
+
+DEFINE_EVENT_BEGIN(PanningChange)
+ int XPan;
+ int YPan;
+DEFINE_EVENT_END(PanningChange)
+
+DEFINE_EVENT_BEGIN(ScalingFactorChange)
+ double ScalingFactor;
+DEFINE_EVENT_END(ScalingFactorChange)
+
+DEFINE_EVENT_BEGIN(LocalResizeWindow)
+ int width;
+ int height;
+DEFINE_EVENT_END(LocalResizeWindow)
DEFINE_EVENT_BEGIN(EmbedWindow)
BOOL embed;
@@ -59,6 +73,20 @@ DEFINE_EVENT_BEGIN(Terminate)
int code;
DEFINE_EVENT_END(Terminate)
+DEFINE_EVENT_BEGIN(ConnectionResult)
+ int result;
+DEFINE_EVENT_END(ConnectionResult)
+
+DEFINE_EVENT_BEGIN(ChannelConnected)
+ const char* name;
+ void* pInterface;
+DEFINE_EVENT_END(ChannelConnected)
+
+DEFINE_EVENT_BEGIN(ChannelDisconnected)
+ const char* name;
+ void* pInterface;
+DEFINE_EVENT_END(ChannelDisconnected)
+
#ifdef __cplusplus
}
#endif
diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h
index 214c2f719..e3ce2bf84 100644
--- a/include/freerdp/freerdp.h
+++ b/include/freerdp/freerdp.h
@@ -66,9 +66,6 @@ typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
typedef int (*pSendChannelData)(freerdp* instance, int channelId, BYTE* data, int size);
typedef int (*pReceiveChannelData)(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size);
-typedef int (*pOnChannelConnected)(freerdp* instance, const char* name, void* pInterface);
-typedef int (*pOnChannelDisconnected)(freerdp* instance, const char* name, void* pInterface);
-
/**
* Defines the context for a given instance of RDP connection.
* It is embedded in the rdp_freerdp structure, and allocated by a call to freerdp_context_new().
@@ -208,9 +205,6 @@ struct rdp_freerdp
This is called by freerdp_channel_process() (if not NULL).
Clients will typically use a function that calls freerdp_channels_data() to perform the needed tasks. */
- ALIGN64 pOnChannelConnected OnChannelConnected;
- ALIGN64 pOnChannelDisconnected OnChannelDisconnected;
-
UINT64 paddingE[80 - 66]; /* 66 */
};
diff --git a/include/freerdp/listener.h b/include/freerdp/listener.h
index 49cd12217..9ae1156d6 100644
--- a/include/freerdp/listener.h
+++ b/include/freerdp/listener.h
@@ -34,6 +34,7 @@ extern "C" {
typedef BOOL (*psListenerOpen)(freerdp_listener* instance, const char* bind_address, UINT16 port);
typedef BOOL (*psListenerOpenLocal)(freerdp_listener* instance, const char* path);
typedef BOOL (*psListenerGetFileDescriptor)(freerdp_listener* instance, void** rfds, int* rcount);
+typedef int (*psListenerGetEventHandles)(freerdp_listener* instance, HANDLE* events, DWORD* nCount);
typedef BOOL (*psListenerCheckFileDescriptor)(freerdp_listener* instance);
typedef void (*psListenerClose)(freerdp_listener* instance);
typedef void (*psPeerAccepted)(freerdp_listener* instance, freerdp_peer* client);
@@ -50,6 +51,7 @@ struct rdp_freerdp_listener
psListenerOpen Open;
psListenerOpenLocal OpenLocal;
psListenerGetFileDescriptor GetFileDescriptor;
+ psListenerGetEventHandles GetEventHandles;
psListenerCheckFileDescriptor CheckFileDescriptor;
psListenerClose Close;
diff --git a/include/freerdp/locale/keyboard.h b/include/freerdp/locale/keyboard.h
index 32a7ed5fe..147067d8e 100644
--- a/include/freerdp/locale/keyboard.h
+++ b/include/freerdp/locale/keyboard.h
@@ -205,6 +205,7 @@ extern "C" {
FREERDP_API DWORD freerdp_keyboard_init(DWORD keyboardLayoutId);
FREERDP_API RDP_KEYBOARD_LAYOUT* freerdp_keyboard_get_layouts(DWORD types);
+FREERDP_API void freerdp_keyboard_layouts_free(RDP_KEYBOARD_LAYOUT* layouts);
FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(DWORD keyboardLayoutId);
FREERDP_API DWORD freerdp_keyboard_get_layout_id_from_name(const char* name);
FREERDP_API DWORD freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode);
diff --git a/include/freerdp/peer.h b/include/freerdp/peer.h
index 6279c92bc..e447ba014 100644
--- a/include/freerdp/peer.h
+++ b/include/freerdp/peer.h
@@ -33,6 +33,7 @@ typedef void (*psPeerContextFree)(freerdp_peer* client, rdpContext* context);
typedef BOOL (*psPeerInitialize)(freerdp_peer* client);
typedef BOOL (*psPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount);
+typedef HANDLE (*psPeerGetEventHandle)(freerdp_peer* client);
typedef BOOL (*psPeerCheckFileDescriptor)(freerdp_peer* client);
typedef BOOL (*psPeerClose)(freerdp_peer* client);
typedef void (*psPeerDisconnect)(freerdp_peer* client);
@@ -60,6 +61,7 @@ struct rdp_freerdp_peer
psPeerInitialize Initialize;
psPeerGetFileDescriptor GetFileDescriptor;
+ psPeerGetEventHandle GetEventHandle;
psPeerCheckFileDescriptor CheckFileDescriptor;
psPeerClose Close;
psPeerDisconnect Disconnect;
diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h
index eb3541cf2..b9ca69342 100644
--- a/include/freerdp/settings.h
+++ b/include/freerdp/settings.h
@@ -609,6 +609,9 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_WmClass 1549
#define FreeRDP_EmbeddedWindow 1550
#define FreeRDP_SmartSizing 1551
+#define FreeRDP_XPan 1552
+#define FreeRDP_YPan 1553
+#define FreeRDP_ScalingFactor 1554
#define FreeRDP_SoftwareGdi 1601
#define FreeRDP_LocalConnection 1602
#define FreeRDP_AuthenticationOnly 1603
@@ -630,6 +633,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_GatewayDomain 1989
#define FreeRDP_GatewayCredentialsSource 1990
#define FreeRDP_GatewayUseSameCredentials 1991
+#define FreeRDP_GatewayEnabled 1992
#define FreeRDP_RemoteApplicationMode 2112
#define FreeRDP_RemoteApplicationName 2113
#define FreeRDP_RemoteApplicationIcon 2114
@@ -677,6 +681,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_UnicodeInput 2629
#define FreeRDP_FastPathInput 2630
#define FreeRDP_MultiTouchInput 2631
+#define FreeRDP_MultiTouchGestures 2632
#define FreeRDP_BrushSupportLevel 2688
#define FreeRDP_GlyphSupportLevel 2752
#define FreeRDP_GlyphCache 2753
@@ -976,7 +981,10 @@ struct rdp_settings
ALIGN64 char* WmClass; /* 1549 */
ALIGN64 BOOL EmbeddedWindow; /* 1550 */
ALIGN64 BOOL SmartSizing; /* 1551 */
- UINT64 padding1600[1600 - 1552]; /* 1552 */
+ ALIGN64 int XPan; /* 1552 */
+ ALIGN64 int YPan; /* 1553 */
+ ALIGN64 double ScalingFactor; /* 1554 */
+ UINT64 padding1600[1600 - 1555]; /* 1555 */
/* Miscellaneous */
ALIGN64 BOOL SoftwareGdi; /* 1601 */
@@ -1012,7 +1020,7 @@ struct rdp_settings
*/
/* Gateway */
- ALIGN64 BOOL GatewayUsageMethod; /* 1984 */
+ ALIGN64 UINT32 GatewayUsageMethod; /* 1984 */
ALIGN64 UINT32 GatewayPort; /* 1985 */
ALIGN64 char* GatewayHostname; /* 1986 */
ALIGN64 char* GatewayUsername; /* 1987 */
@@ -1020,7 +1028,8 @@ struct rdp_settings
ALIGN64 char* GatewayDomain; /* 1989 */
ALIGN64 UINT32 GatewayCredentialsSource; /* 1990 */
ALIGN64 BOOL GatewayUseSameCredentials; /* 1991 */
- UINT64 padding2048[2048 - 1992]; /* 1992 */
+ ALIGN64 BOOL GatewayEnabled; /* 1992 */
+ UINT64 padding2048[2048 - 1993]; /* 1993 */
UINT64 padding2112[2112 - 2048]; /* 2048 */
/**
@@ -1101,7 +1110,8 @@ struct rdp_settings
ALIGN64 BOOL UnicodeInput; /* 2629 */
ALIGN64 BOOL FastPathInput; /* 2630 */
ALIGN64 BOOL MultiTouchInput; /* 2631 */
- UINT64 padding2688[2688 - 2632]; /* 2632 */
+ ALIGN64 BOOL MultiTouchGestures; /* 2632 */
+ UINT64 padding2688[2688 - 2633]; /* 2633 */
/* Brush Capabilities */
ALIGN64 UINT32 BrushSupportLevel; /* 2688 */
@@ -1310,6 +1320,9 @@ FREERDP_API void freerdp_dynamic_channel_collection_free(rdpSettings* settings);
FREERDP_API BOOL freerdp_get_param_bool(rdpSettings* settings, int id);
FREERDP_API int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param);
+FREERDP_API int freerdp_get_param_int(rdpSettings* settings, int id);
+FREERDP_API int freerdp_set_param_int(rdpSettings* settings, int id, int param);
+
FREERDP_API UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id);
FREERDP_API int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param);
@@ -1319,6 +1332,9 @@ FREERDP_API int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 p
FREERDP_API char* freerdp_get_param_string(rdpSettings* settings, int id);
FREERDP_API int freerdp_set_param_string(rdpSettings* settings, int id, char* param);
+FREERDP_API double freerdp_get_param_double(rdpSettings* settings, int id);
+FREERDP_API int freerdp_set_param_double(rdpSettings* settings, int id, double param);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/freerdp/update.h b/include/freerdp/update.h
index db6f36bb9..a6aa8caa9 100644
--- a/include/freerdp/update.h
+++ b/include/freerdp/update.h
@@ -134,6 +134,14 @@ enum SURFCMD_FRAMEACTION
SURFACECMD_FRAMEACTION_END = 0x0001
};
+struct _SURFACE_FRAME
+{
+ UINT32 frameId;
+ UINT32 commandCount;
+ SURFACE_BITS_COMMAND* commands;
+};
+typedef struct _SURFACE_FRAME SURFACE_FRAME;
+
/* defined inside libfreerdp-core */
typedef struct rdp_update_proxy rdpUpdateProxy;
diff --git a/include/freerdp/utils/stopwatch.h b/include/freerdp/utils/stopwatch.h
index 843d1bd12..af6aa1ee3 100644
--- a/include/freerdp/utils/stopwatch.h
+++ b/include/freerdp/utils/stopwatch.h
@@ -20,17 +20,15 @@
#ifndef FREERDP_UTILS_STOPWATCH_H
#define FREERDP_UTILS_STOPWATCH_H
-#include
-
#include
#include
struct _STOPWATCH
{
- clock_t start;
- clock_t end;
- double elapsed;
- clock_t count;
+ UINT64 start;
+ UINT64 end;
+ UINT64 elapsed;
+ UINT32 count;
};
typedef struct _STOPWATCH STOPWATCH;
diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt
index 6dccb0771..bbc714b15 100644
--- a/libfreerdp/CMakeLists.txt
+++ b/libfreerdp/CMakeLists.txt
@@ -59,9 +59,11 @@ if(MONOLITHIC_BUILD)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
- install(TARGETS ${MODULE_NAME}
- DESTINATION ${CMAKE_INSTALL_LIBDIR}
- COMPONENT libraries)
+ if(NOT WITH_WAYK)
+ install(TARGETS ${MODULE_NAME}
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ COMPONENT libraries)
+ endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
endif()
diff --git a/libfreerdp/cache/bitmap.c b/libfreerdp/cache/bitmap.c
index a1136a08a..fcd653b5f 100644
--- a/libfreerdp/cache/bitmap.c
+++ b/libfreerdp/cache/bitmap.c
@@ -40,6 +40,8 @@ void update_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
bitmap = offscreen_cache_get(cache->offscreen, memblt->cacheIndex);
else
bitmap = bitmap_cache_get(cache->bitmap, (BYTE) memblt->cacheId, memblt->cacheIndex);
+ /* XP-SP2 servers sometimes ask for cached bitmaps they've never defined. */
+ if (bitmap == NULL) return;
memblt->bitmap = bitmap;
IFCALL(cache->bitmap->MemBlt, context, memblt);
@@ -56,6 +58,8 @@ void update_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
bitmap = offscreen_cache_get(cache->offscreen, mem3blt->cacheIndex);
else
bitmap = bitmap_cache_get(cache->bitmap, (BYTE) mem3blt->cacheId, mem3blt->cacheIndex);
+ /* XP-SP2 servers sometimes ask for cached bitmaps they've never defined. */
+ if (bitmap == NULL) return;
style = brush->style;
diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c
index 847ac3849..14f2f69dd 100644
--- a/libfreerdp/cache/glyph.c
+++ b/libfreerdp/cache/glyph.c
@@ -500,6 +500,7 @@ void glyph_cache_free(rdpGlyphCache* glyph_cache)
Glyph_Free(glyph_cache->context, glyph);
free(glyph->aj);
free(glyph);
+ glyph_cache->glyphCache[i].entries[j] = NULL;
}
}
free(glyph_cache->glyphCache[i].entries);
@@ -509,6 +510,7 @@ void glyph_cache_free(rdpGlyphCache* glyph_cache)
{
fragment = glyph_cache->fragCache.entries[i].fragment;
free(fragment);
+ glyph_cache->fragCache.entries[i].fragment = NULL;
}
free(glyph_cache->fragCache.entries);
diff --git a/libfreerdp/cache/pointer.c b/libfreerdp/cache/pointer.c
index 484c2985b..57bc3a4ef 100644
--- a/libfreerdp/cache/pointer.c
+++ b/libfreerdp/cache/pointer.c
@@ -68,9 +68,18 @@ void update_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_col
pointer->height = pointer_color->height;
pointer->lengthAndMask = pointer_color->lengthAndMask;
pointer->lengthXorMask = pointer_color->lengthXorMask;
- pointer->xorMaskData = pointer_color->xorMaskData;
- pointer->andMaskData = pointer_color->andMaskData;
+ if (pointer->lengthAndMask && pointer_color->xorMaskData)
+ {
+ pointer->andMaskData = (BYTE*) malloc(pointer->lengthAndMask);
+ CopyMemory(pointer->andMaskData, pointer_color->andMaskData, pointer->lengthAndMask);
+ }
+
+ if (pointer->lengthXorMask && pointer_color->xorMaskData)
+ {
+ pointer->xorMaskData = (BYTE*) malloc(pointer->lengthXorMask);
+ CopyMemory(pointer->xorMaskData, pointer_color->xorMaskData, pointer->lengthXorMask);
+ }
pointer->New(context, pointer);
pointer_cache_put(cache->pointer, pointer_color->cacheIndex, pointer);
Pointer_Set(context, pointer);
@@ -202,7 +211,10 @@ void pointer_cache_free(rdpPointerCache* pointer_cache)
pointer = pointer_cache->entries[i];
if (pointer != NULL)
+ {
Pointer_Free(pointer_cache->update->context, pointer);
+ pointer_cache->entries[i] = NULL;
+ }
}
free(pointer_cache->entries);
diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt
index 8895848b2..19533017b 100644
--- a/libfreerdp/codec/CMakeLists.txt
+++ b/libfreerdp/codec/CMakeLists.txt
@@ -20,9 +20,10 @@ set(MODULE_PREFIX "FREERDP_CODEC")
set(${MODULE_PREFIX}_SRCS
dsp.c
- bitmap.c
color.c
audio.c
+ bitmap_decode.c
+ bitmap_encode.c
rfx_bitstream.h
rfx_constants.h
rfx_decode.c
diff --git a/libfreerdp/codec/bitmap.c b/libfreerdp/codec/bitmap_decode.c
similarity index 99%
rename from libfreerdp/codec/bitmap.c
rename to libfreerdp/codec/bitmap_decode.c
index 598017081..431a213a8 100644
--- a/libfreerdp/codec/bitmap.c
+++ b/libfreerdp/codec/bitmap_decode.c
@@ -1,6 +1,6 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
- * Compressed Bitmap
+ * Bitmap Decompression
*
* Copyright 2011 Jay Sorg
*
diff --git a/libfreerdp/codec/bitmap_encode.c b/libfreerdp/codec/bitmap_encode.c
new file mode 100644
index 000000000..84ab3b14a
--- /dev/null
+++ b/libfreerdp/codec/bitmap_encode.c
@@ -0,0 +1,1724 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Bitmap Compression
+ *
+ * Copyright 2004-2012 Jay Sorg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+
+#define GETPIXEL8(d, x, y, w) (*(((unsigned char*)d) + ((y) * (w) + (x))))
+#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
+#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
+
+/*****************************************************************************/
+#define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+ { \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL8(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+ }
+
+/*****************************************************************************/
+#define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+ { \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL16(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+ }
+
+/*****************************************************************************/
+#define IN_PIXEL32(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+ { \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL32(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+ }
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT1(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x60); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf3); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write_UINT8(in_s, in_data); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_data); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x60); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_data); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf3); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write_UINT16(in_s, in_data); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT3(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x60); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf3); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write_UINT8(in_s, in_data & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT1(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x80); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf4); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
+ } \
+ } \
+ in_count = 0; \
+ Stream_SetPosition(in_data, 0); \
+ }
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT2(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 2; \
+ Stream_Write(in_s, Stream_Buffer(in_data), temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x80); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 2; \
+ Stream_Write(in_s, Stream_Buffer(in_data), temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf4); \
+ Stream_Write_UINT16(in_s, in_count); \
+ temp = in_count * 2; \
+ Stream_Write(in_s, Stream_Buffer(in_data), temp); \
+ } \
+ } \
+ in_count = 0; \
+ Stream_SetPosition(in_data, 0); \
+ }
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT3(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 3; \
+ Stream_Write(in_s, Stream_Pointer(in_data), temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x80); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 3; \
+ Stream_Write(in_s, Stream_Pointer(in_data), temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf4); \
+ Stream_Write_UINT16(in_s, in_count); \
+ temp = in_count * 3; \
+ Stream_Write(in_s, Stream_Pointer(in_data), temp); \
+ } \
+ } \
+ in_count = 0; \
+ Stream_SetPosition(in_data, 0); \
+ }
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT1(in_count, in_s, in_color1, in_color2) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1); \
+ Stream_Write_UINT8(in_s, in_color2); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ Stream_Write_UINT8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1); \
+ Stream_Write_UINT8(in_s, in_color2); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ Stream_Write_UINT16(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1); \
+ Stream_Write_UINT8(in_s, in_color2); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_color1); \
+ Stream_Write_UINT16(in_s, in_color2); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ Stream_Write_UINT8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_color1); \
+ Stream_Write_UINT16(in_s, in_color2); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ Stream_Write_UINT16(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_color1); \
+ Stream_Write_UINT16(in_s, in_color2); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT3(in_count, in_s, in_color1, in_color2) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF); \
+ Stream_Write_UINT8(in_s, in_color2 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ Stream_Write_UINT8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF); \
+ Stream_Write_UINT8(in_s, in_color2 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ Stream_Write_UINT16(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF); \
+ Stream_Write_UINT8(in_s, in_color2 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT1(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ Stream_Write_UINT8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x0); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf0); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT2(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ Stream_Write_UINT8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x0); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf0); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT3(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ Stream_Write_UINT8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x0); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf0); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT1(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x20); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf1); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT2(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x20); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf1); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT3(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x20); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf1); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fom */
+#define OUT_FOM_COUNT1(in_count, in_s, in_mask, in_mask_len) \
+ { \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ Stream_Write_UINT8(in_s, 0x40); \
+ temp = in_count - 1; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf2); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fom */
+#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \
+ { \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ Stream_Write_UINT8(in_s, 0x40); \
+ temp = in_count - 1; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf2); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill or mix (fom) */
+#define OUT_FOM_COUNT3(in_count, in_s, in_mask, in_mask_len) \
+ { \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ Stream_Write_UINT8(in_s, 0x40); \
+ temp = in_count - 1; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf2); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+#define TEST_FILL \
+ ((last_line == 0 && pixel == 0) || \
+ (last_line != 0 && pixel == ypixel))
+#define TEST_MIX \
+ ((last_line == 0 && pixel == mix) || \
+ (last_line != 0 && pixel == (ypixel ^ mix)))
+#define TEST_FOM (TEST_FILL || TEST_MIX)
+#define TEST_COLOR (pixel == last_pixel)
+#define TEST_BICOLOR \
+ ( \
+ (pixel != last_pixel) && \
+ ( \
+ (!bicolor_spin && pixel == bicolor1 && last_pixel == bicolor2) || \
+ (bicolor_spin && pixel == bicolor2 && last_pixel == bicolor1) \
+ ) \
+ )
+#define RESET_COUNTS \
+ { \
+ bicolor_count = 0; \
+ fill_count = 0; \
+ color_count = 0; \
+ mix_count = 0; \
+ fom_count = 0; \
+ fom_mask_len = 0; \
+ bicolor_spin = 0; \
+ }
+
+/*****************************************************************************/
+int freerdp_bitmap_compress(char* in_data, int width, int height,
+ wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e)
+{
+ char *line;
+ char *last_line;
+ char fom_mask[8192]; /* good for up to 64K bitmap */
+ int lines_sent;
+ int pixel;
+ int count;
+ int color_count;
+ int last_pixel;
+ int bicolor_count;
+ int bicolor1;
+ int bicolor2;
+ int bicolor_spin;
+ int end;
+ int i;
+ int out_count;
+ int ypixel;
+ int last_ypixel;
+ int fill_count;
+ int mix_count;
+ int mix;
+ int fom_count;
+ int fom_mask_len;
+ int temp; /* used in macros */
+
+ Stream_SetPosition(temp_s, 0);
+ fom_mask_len = 0;
+ last_line = 0;
+ lines_sent = 0;
+ end = width + e;
+ count = 0;
+ color_count = 0;
+ last_pixel = 0;
+ last_ypixel = 0;
+ bicolor_count = 0;
+ bicolor1 = 0;
+ bicolor2 = 0;
+ bicolor_spin = 0;
+ fill_count = 0;
+ mix_count = 0;
+ fom_count = 0;
+
+ if (bpp == 8)
+ {
+ mix = 0xFF;
+ out_count = end;
+ line = in_data + width * start_line;
+
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = Stream_GetPosition(s) + count;
+
+ if (i - color_count >= byte_limit &&
+ i - bicolor_count >= byte_limit &&
+ i - fill_count >= byte_limit &&
+ i - mix_count >= byte_limit &&
+ i - fom_count >= byte_limit)
+ {
+ break;
+ }
+
+ out_count += end;
+
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL8(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL8(last_line, i, 0, width, last_ypixel, ypixel);
+
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+ }
+
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+ }
+
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_COLOR_COUNT1(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+
+ color_count = 0;
+ }
+
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ RESET_COUNTS;
+ }
+
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+
+ fom_count++;
+ }
+
+ Stream_Write_UINT8(temp_s, pixel);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ last_line = line;
+ line = line - width;
+ start_line--;
+ lines_sent++;
+ }
+
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_COLOR_COUNT1(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT1(count, s, temp_s);
+ }
+ }
+ else if ((bpp == 15) || (bpp == 16))
+ {
+ mix = (bpp == 15) ? 0xBA1F : 0xFFFF;
+ out_count = end * 2;
+ line = in_data + width * start_line * 2;
+
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = Stream_GetPosition(s) + count * 2;
+
+ if (i - (color_count * 2) >= byte_limit &&
+ i - (bicolor_count * 2) >= byte_limit &&
+ i - (fill_count * 2) >= byte_limit &&
+ i - (mix_count * 2) >= byte_limit &&
+ i - (fom_count * 2) >= byte_limit)
+ {
+ break;
+ }
+
+ out_count += end * 2;
+
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL16(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL16(last_line, i, 0, width, last_ypixel, ypixel);
+
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+ }
+
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+ }
+
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_COLOR_COUNT2(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+
+ color_count = 0;
+ }
+
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ RESET_COUNTS;
+ }
+
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+
+ fom_count++;
+ }
+
+ Stream_Write_UINT16(temp_s, pixel);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ last_line = line;
+ line = line - width * 2;
+ start_line--;
+ lines_sent++;
+ }
+
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_COLOR_COUNT2(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT2(count, s, temp_s);
+ }
+ }
+ else if (bpp == 24)
+ {
+ mix = 0xFFFFFF;
+ out_count = end * 3;
+ line = in_data + width * start_line * 4;
+
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = Stream_GetPosition(s) + count * 3;
+
+ if (i - (color_count * 3) >= byte_limit &&
+ i - (bicolor_count * 3) >= byte_limit &&
+ i - (fill_count * 3) >= byte_limit &&
+ i - (mix_count * 3) >= byte_limit &&
+ i - (fom_count * 3) >= byte_limit)
+ {
+ break;
+ }
+
+ out_count += end * 3;
+
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL32(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL32(last_line, i, 0, width, last_ypixel, ypixel);
+
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FILL_COUNT3(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+ }
+
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_MIX_COUNT3(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+ }
+
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_COLOR_COUNT3(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+
+ color_count = 0;
+ }
+
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ RESET_COUNTS;
+ }
+
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+
+ fom_count++;
+ }
+
+ Stream_Write_UINT8(temp_s, pixel & 0xff);
+ Stream_Write_UINT8(temp_s, (pixel >> 8) & 0xff);
+ Stream_Write_UINT8(temp_s, (pixel >> 16) & 0xff);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FILL_COUNT3(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_MIX_COUNT3(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ last_line = line;
+ line = line - width * 4;
+ start_line--;
+ lines_sent++;
+ }
+
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FILL_COUNT3(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_MIX_COUNT3(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_COLOR_COUNT3(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT3(count, s, temp_s);
+ }
+ }
+
+ return lines_sent;
+}
+
+/**
+ * RDP6 Bitmap Test Case ([MS-RDPEGDI])
+ */
+
+const BYTE TEST_RDP6_COMPRESSED_BITMAP[220] =
+ "\x85\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x06\x8B\x99\xD6\x99"
+ "\xD6\x99\xD6\x10\x84\x08\x42\x08\x42\x10\x84\x99\xD6\x99\xD6\x99"
+ "\xD6\x99\xD6\x06\x84\x99\xD6\x99\xD6\x99\xD6\xFF\xFF\x16\x69\x99"
+ "\xD6\x06\x69\x99\xD6\x04\xCC\x89\x52\x03\x6E\xFF\xFF\x02\x6E\x08"
+ "\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18\xC6\x01\x81\x08\x42\xCE"
+ "\x66\x29\x02\xCD\x89\x52\x03\x88\x10\x84\x99\xD6\x99\xD6\x99\xD6"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\xD8\x99\xD6\x03\xF8\x01\x00\x00"
+ "\x00\x00\xF0\x66\x99\xD6\x05\x6A\x99\xD6\x00\xC4\xCC\x89\x52\x03"
+ "\x6E\xFF\xFF\x02\x6E\x08\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18"
+ "\xC6\x01\x81\x08\x42\xCE\x66\x29\x02\xCD\x89\x52\x03\x00\x04\xD6"
+ "\x99\xD6\xC3\x80\x61\x00\xA5\x80\x40\xEC\x52\x00\x5A\x00\x2D\x00"
+ "\x24\x00\x12\x00\x24\x00\x12\x00\x5A\x00\x2D\x00\xA5\x80\x52\x00"
+ "\xC3\x80\x61\x00\x00\x00\x00\x00\xCC\x89\x52\x03\x6E\xFF\xFF\x02"
+ "\xCB\x18\xC6\x84\x08\x42\x08\x42\x08\x42\xFF\xFF";
+
+const BYTE TEST_RDP6_UNCOMPRESSED_BITMAP[2048] =
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
+ "\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
+ "\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
+ "\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
+ "\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
+ "\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
+ "\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
+ "\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
+ "\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
+ "\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
+ "\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
+ "\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
+ "\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
+ "\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
+ "\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
+ "\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
+ "\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF";
diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
index ba435a0c8..b869b028f 100644
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -61,7 +61,7 @@ static void nsc_decode(NSC_CONTEXT* context)
INT16 b_val;
BYTE* bmpdata;
- bmpdata = context->bmpdata;
+ bmpdata = context->BitmapData;
rw = ROUND_UP_TO(context->width, 8);
shift = context->nsc_stream.ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
@@ -69,17 +69,19 @@ static void nsc_decode(NSC_CONTEXT* context)
{
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
{
- yplane = context->priv->plane_buf[0] + y * rw; /* Y */
- coplane = context->priv->plane_buf[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */
- cgplane = context->priv->plane_buf[2] + (y >> 1) * (rw >> 1); /* Cg, supersampled */
+ yplane = context->priv->PlaneBuffers[0] + y * rw; /* Y */
+ coplane = context->priv->PlaneBuffers[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */
+ cgplane = context->priv->PlaneBuffers[2] + (y >> 1) * (rw >> 1); /* Cg, supersampled */
}
else
{
- yplane = context->priv->plane_buf[0] + y * context->width; /* Y */
- coplane = context->priv->plane_buf[1] + y * context->width; /* Co */
- cgplane = context->priv->plane_buf[2] + y * context->width; /* Cg */
+ yplane = context->priv->PlaneBuffers[0] + y * context->width; /* Y */
+ coplane = context->priv->PlaneBuffers[1] + y * context->width; /* Co */
+ cgplane = context->priv->PlaneBuffers[2] + y * context->width; /* Cg */
}
- aplane = context->priv->plane_buf[3] + y * context->width; /* A */
+
+ aplane = context->priv->PlaneBuffers[3] + y * context->width; /* A */
+
for (x = 0; x < context->width; x++)
{
y_val = (INT16) *yplane;
@@ -100,13 +102,14 @@ static void nsc_decode(NSC_CONTEXT* context)
}
}
-static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
+static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
{
UINT32 len;
UINT32 left;
BYTE value;
- left = origsz;
+ left = originalSize;
+
while (left > 4)
{
value = *in++;
@@ -119,6 +122,7 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
else if (value == *in)
{
in++;
+
if (*in < 0xFF)
{
len = (UINT32) *in++;
@@ -130,7 +134,8 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
len = *((UINT32*) in);
in += 4;
}
- memset(out, value, len);
+
+ FillMemory(out, len, value);
out += len;
left -= len;
}
@@ -148,24 +153,24 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
{
UINT16 i;
BYTE* rle;
- UINT32 origsize;
- UINT32 planesize;
+ UINT32 planeSize;
+ UINT32 originalSize;
rle = context->nsc_stream.Planes;
for (i = 0; i < 4; i++)
{
- origsize = context->OrgByteCount[i];
- planesize = context->nsc_stream.PlaneByteCount[i];
+ originalSize = context->OrgByteCount[i];
+ planeSize = context->nsc_stream.PlaneByteCount[i];
- if (planesize == 0)
- memset(context->priv->plane_buf[i], 0xff, origsize);
- else if (planesize < origsize)
- nsc_rle_decode(rle, context->priv->plane_buf[i], origsize);
+ if (planeSize == 0)
+ FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
+ else if (planeSize < originalSize)
+ nsc_rle_decode(rle, context->priv->PlaneBuffers[i], originalSize);
else
- memcpy(context->priv->plane_buf[i], rle, origsize);
+ CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
- rle += planesize;
+ rle += planeSize;
}
}
@@ -192,31 +197,37 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
nsc_stream_initialize(context, s);
length = context->width * context->height * 4;
- if (context->bmpdata == NULL)
+
+ if (!context->BitmapData)
{
- context->bmpdata = malloc(length + 16);
- ZeroMemory(context->bmpdata, length + 16);
- context->bmpdata_length = length;
+ context->BitmapData = malloc(length + 16);
+ ZeroMemory(context->BitmapData, length + 16);
+ context->BitmapDataLength = length;
}
- else if (length > context->bmpdata_length)
+ else if (length > context->BitmapDataLength)
{
- context->bmpdata = realloc(context->bmpdata, length + 16);
- context->bmpdata_length = length;
+ context->BitmapData = realloc(context->BitmapData, length + 16);
+ context->BitmapDataLength = length;
}
tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2);
+
/* The maximum length a decoded plane can reach in all cases */
length = tempWidth * tempHeight;
- if (length > context->priv->plane_buf_length)
+
+ if (length > context->priv->PlaneBuffersLength)
{
for (i = 0; i < 4; i++)
- context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length);
- context->priv->plane_buf_length = length;
+ context->priv->PlaneBuffers[i] = (BYTE*) realloc(context->priv->PlaneBuffers[i], length);
+
+ context->priv->PlaneBuffersLength = length;
}
for (i = 0; i < 4; i++)
- context->OrgByteCount[i]=context->width * context->height;
+ {
+ context->OrgByteCount[i] = context->width * context->height;
+ }
if (context->nsc_stream.ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */
{
@@ -238,20 +249,58 @@ static void nsc_profiler_print(NSC_CONTEXT* context)
PROFILER_PRINT_FOOTER;
}
+NSC_CONTEXT* nsc_context_new(void)
+{
+ UINT8 i;
+ NSC_CONTEXT* context;
+
+ context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT));
+ context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV));
+
+ for (i = 0; i < 5; ++i)
+ {
+ context->priv->PlaneBuffers[i] = NULL;
+ }
+
+ context->BitmapData = NULL;
+
+ context->decode = nsc_decode;
+ context->encode = nsc_encode;
+
+ context->priv->PlanePool = BufferPool_New(TRUE, 0, 16);
+
+ PROFILER_CREATE(context->priv->prof_nsc_rle_decompress_data, "nsc_rle_decompress_data");
+ PROFILER_CREATE(context->priv->prof_nsc_decode, "nsc_decode");
+ PROFILER_CREATE(context->priv->prof_nsc_rle_compress_data, "nsc_rle_compress_data");
+ PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode");
+
+ /* Default encoding parameters */
+ context->nsc_stream.ColorLossLevel = 3;
+ context->nsc_stream.ChromaSubSamplingLevel = 1;
+
+ /* init optimized methods */
+ NSC_INIT_SIMD(context);
+
+ return context;
+}
+
void nsc_context_free(NSC_CONTEXT* context)
{
int i;
for (i = 0; i < 4; i++)
{
- if (context->priv->plane_buf[i])
+ if (context->priv->PlaneBuffers[i])
{
- free(context->priv->plane_buf[i]);
- context->priv->plane_buf[i] = NULL;
+ free(context->priv->PlaneBuffers[i]);
+ context->priv->PlaneBuffers[i] = NULL;
}
}
- if (context->bmpdata)
- free(context->bmpdata);
+
+ if (context->BitmapData)
+ free(context->BitmapData);
+
+ BufferPool_Free(context->priv->PlanePool);
nsc_profiler_print(context);
PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data);
@@ -261,71 +310,44 @@ void nsc_context_free(NSC_CONTEXT* context)
free(context->priv);
free(context);
- context = NULL;
-}
-
-NSC_CONTEXT* nsc_context_new(void)
-{
- NSC_CONTEXT* nsc_context;
- UINT8 i;
-
- nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT));
- nsc_context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV));
- for (i=0; i < 5; ++i)
- {
- nsc_context->priv->plane_buf[i] = NULL;
- }
- nsc_context->bmpdata = NULL;
-
- nsc_context->decode = nsc_decode;
- nsc_context->encode = nsc_encode;
-
- PROFILER_CREATE(nsc_context->priv->prof_nsc_rle_decompress_data, "nsc_rle_decompress_data");
- PROFILER_CREATE(nsc_context->priv->prof_nsc_decode, "nsc_decode");
- PROFILER_CREATE(nsc_context->priv->prof_nsc_rle_compress_data, "nsc_rle_compress_data");
- PROFILER_CREATE(nsc_context->priv->prof_nsc_encode, "nsc_encode");
-
- /* Default encoding parameters */
- nsc_context->nsc_stream.ColorLossLevel = 3;
- nsc_context->nsc_stream.ChromaSubSamplingLevel = 1;
-
- /* init optimized methods */
- NSC_INIT_SIMD(nsc_context);
-
- return nsc_context;
}
void nsc_context_set_pixel_format(NSC_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format)
{
context->pixel_format = pixel_format;
+
switch (pixel_format)
{
case RDP_PIXEL_FORMAT_B8G8R8A8:
case RDP_PIXEL_FORMAT_R8G8B8A8:
context->bpp = 32;
break;
+
case RDP_PIXEL_FORMAT_B8G8R8:
case RDP_PIXEL_FORMAT_R8G8B8:
context->bpp = 24;
break;
+
case RDP_PIXEL_FORMAT_B5G6R5_LE:
case RDP_PIXEL_FORMAT_R5G6B5_LE:
context->bpp = 16;
break;
+
case RDP_PIXEL_FORMAT_P4_PLANER:
context->bpp = 4;
break;
+
case RDP_PIXEL_FORMAT_P8:
context->bpp = 8;
break;
+
default:
context->bpp = 0;
break;
}
}
-void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp,
- UINT16 width, UINT16 height, BYTE* data, UINT32 length)
+void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, UINT16 width, UINT16 height, BYTE* data, UINT32 length)
{
wStream* s;
diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c
index 143e44dc5..627d032f4 100644
--- a/libfreerdp/codec/nsc_encode.c
+++ b/libfreerdp/codec/nsc_encode.c
@@ -24,10 +24,13 @@
#include
#include
#include
+
#ifdef HAVE_STDINT_H
#include
#endif
+#include
+
#include
#include "nsc_types.h"
@@ -42,13 +45,16 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context)
tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2);
+
/* The maximum length a decoded plane can reach in all cases */
length = tempWidth * tempHeight + 16;
- if (length > context->priv->plane_buf_length)
+
+ if (length > context->priv->PlaneBuffersLength)
{
for (i = 0; i < 5; i++)
- context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length);
- context->priv->plane_buf_length = length;
+ context->priv->PlaneBuffers[i] = (BYTE*) realloc(context->priv->PlaneBuffers[i], length);
+
+ context->priv->PlaneBuffersLength = length;
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
@@ -67,7 +73,7 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context)
}
}
-static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
+static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scanline)
{
UINT16 x;
UINT16 y;
@@ -89,18 +95,19 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
tempHeight = ROUND_UP_TO(context->height, 2);
rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width);
ccl = context->nsc_stream.ColorLossLevel;
- yplane = context->priv->plane_buf[0];
- coplane = context->priv->plane_buf[1];
- cgplane = context->priv->plane_buf[2];
- aplane = context->priv->plane_buf[3];
+ yplane = context->priv->PlaneBuffers[0];
+ coplane = context->priv->PlaneBuffers[1];
+ cgplane = context->priv->PlaneBuffers[2];
+ aplane = context->priv->PlaneBuffers[3];
for (y = 0; y < context->height; y++)
{
- src = bmpdata + (context->height - 1 - y) * rowstride;
- yplane = context->priv->plane_buf[0] + y * rw;
- coplane = context->priv->plane_buf[1] + y * rw;
- cgplane = context->priv->plane_buf[2] + y * rw;
- aplane = context->priv->plane_buf[3] + y * context->width;
+ src = data + (context->height - 1 - y) * scanline;
+ yplane = context->priv->PlaneBuffers[0] + y * rw;
+ coplane = context->priv->PlaneBuffers[1] + y * rw;
+ cgplane = context->priv->PlaneBuffers[2] + y * rw;
+ aplane = context->priv->PlaneBuffers[3] + y * context->width;
+
for (x = 0; x < context->width; x++)
{
switch (context->pixel_format)
@@ -111,24 +118,28 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
r_val = *src++;
a_val = *src++;
break;
+
case RDP_PIXEL_FORMAT_R8G8B8A8:
r_val = *src++;
g_val = *src++;
b_val = *src++;
a_val = *src++;
break;
+
case RDP_PIXEL_FORMAT_B8G8R8:
b_val = *src++;
g_val = *src++;
r_val = *src++;
a_val = 0xFF;
break;
+
case RDP_PIXEL_FORMAT_R8G8B8:
r_val = *src++;
g_val = *src++;
b_val = *src++;
a_val = 0xFF;
break;
+
case RDP_PIXEL_FORMAT_B5G6R5_LE:
b_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
@@ -136,6 +147,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
a_val = 0xFF;
src += 2;
break;
+
case RDP_PIXEL_FORMAT_R5G6B5_LE:
r_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
@@ -143,6 +155,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
a_val = 0xFF;
src += 2;
break;
+
case RDP_PIXEL_FORMAT_P4_PLANER:
{
int shift;
@@ -162,6 +175,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
}
a_val = 0xFF;
break;
+
case RDP_PIXEL_FORMAT_P8:
{
int idx = (*src) * 3;
@@ -173,16 +187,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
}
a_val = 0xFF;
break;
+
default:
r_val = g_val = b_val = a_val = 0;
break;
}
+
*yplane++ = (BYTE) ((r_val >> 2) + (g_val >> 1) + (b_val >> 2));
+
/* Perform color loss reduction here */
*coplane++ = (BYTE) ((r_val - b_val) >> ccl);
*cgplane++ = (BYTE) ((-(r_val >> 1) + g_val - (b_val >> 1)) >> ccl);
*aplane++ = a_val;
}
+
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 1)
{
*yplane = *(yplane - 1);
@@ -190,11 +208,12 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
*cgplane = *(cgplane - 1);
}
}
+
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
{
- memcpy(yplane + rw, yplane, rw);
- memcpy(coplane + rw, coplane, rw);
- memcpy(cgplane + rw, cgplane, rw);
+ CopyMemory(yplane + rw, yplane, rw);
+ CopyMemory(coplane + rw, coplane, rw);
+ CopyMemory(cgplane + rw, cgplane, rw);
}
}
@@ -216,12 +235,13 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
for (y = 0; y < tempHeight >> 1; y++)
{
- co_dst = context->priv->plane_buf[1] + y * (tempWidth >> 1);
- cg_dst = context->priv->plane_buf[2] + y * (tempWidth >> 1);
- co_src0 = (INT8*) context->priv->plane_buf[1] + (y << 1) * tempWidth;
+ co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
+ cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
+ co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
co_src1 = co_src0 + tempWidth;
- cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth;
+ cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
cg_src1 = cg_src0 + tempWidth;
+
for (x = 0; x < tempWidth >> 1; x++)
{
*co_dst++ = (BYTE) (((INT16) *co_src0 + (INT16) *(co_src0 + 1) +
@@ -239,24 +259,25 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
void nsc_encode(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
{
nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
+
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
{
nsc_encode_subsampling(context);
}
}
-static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
+static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize)
{
UINT32 left;
UINT32 runlength = 1;
- UINT32 planesize = 0;
+ UINT32 planeSize = 0;
- left = origsz;
+ left = originalSize;
/**
* We quit the loop if the running compressed size is larger than the original.
* In such cases data will be sent uncompressed.
*/
- while (left > 4 && planesize < origsz - 4)
+ while (left > 4 && planeSize < originalSize - 4)
{
if (left > 5 && *in == *(in + 1))
{
@@ -265,7 +286,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
else if (runlength == 1)
{
*out++ = *in;
- planesize++;
+ planeSize++;
}
else if (runlength < 256)
{
@@ -273,7 +294,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
*out++ = *in;
*out++ = runlength - 2;
runlength = 1;
- planesize += 3;
+ planeSize += 3;
}
else
{
@@ -285,52 +306,213 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
*out++ = (runlength & 0x00FF0000) >> 16;
*out++ = (runlength & 0xFF000000) >> 24;
runlength = 1;
- planesize += 7;
+ planeSize += 7;
}
in++;
left--;
}
- if (planesize < origsz - 4)
- {
- memcpy(out, in, 4);
- }
- planesize += 4;
- return planesize;
+ if (planeSize < originalSize - 4)
+ CopyMemory(out, in, 4);
+
+ planeSize += 4;
+
+ return planeSize;
}
static void nsc_rle_compress_data(NSC_CONTEXT* context)
{
UINT16 i;
- BYTE* rle;
- UINT32 origsize;
- UINT32 planesize;
-
- rle = context->nsc_stream.Planes;
+ UINT32 planeSize;
+ UINT32 originalSize;
for (i = 0; i < 4; i++)
{
- origsize = context->OrgByteCount[i];
- if (origsize == 0)
+ originalSize = context->OrgByteCount[i];
+
+ if (originalSize == 0)
{
- planesize = 0;
+ planeSize = 0;
}
else
{
- planesize = nsc_rle_encode(context->priv->plane_buf[i],
- context->priv->plane_buf[4], origsize);
- if (planesize < origsize)
- memcpy(context->priv->plane_buf[i], context->priv->plane_buf[4], planesize);
+ planeSize = nsc_rle_encode(context->priv->PlaneBuffers[i], context->priv->PlaneBuffers[4], originalSize);
+
+ if (planeSize < originalSize)
+ CopyMemory(context->priv->PlaneBuffers[i], context->priv->PlaneBuffers[4], planeSize);
else
- planesize = origsize;
+ planeSize = originalSize;
}
- context->nsc_stream.PlaneByteCount[i] = planesize;
+ context->nsc_stream.PlaneByteCount[i] = planeSize;
}
}
-void nsc_compose_message(NSC_CONTEXT* context, wStream* s,
- BYTE* bmpdata, int width, int height, int rowstride)
+UINT32 nsc_compute_byte_count(NSC_CONTEXT* context, UINT32* ByteCount, UINT32 width, UINT32 height)
+{
+ UINT32 tempWidth;
+ UINT32 tempHeight;
+ UINT32 maxPlaneSize;
+
+ tempWidth = ROUND_UP_TO(width, 8);
+ tempHeight = ROUND_UP_TO(height, 2);
+
+ maxPlaneSize = tempWidth * tempHeight + 16;
+
+ if (context->nsc_stream.ChromaSubSamplingLevel > 0)
+ {
+ ByteCount[0] = tempWidth * height;
+ ByteCount[1] = tempWidth * tempHeight / 4;
+ ByteCount[2] = tempWidth * tempHeight / 4;
+ ByteCount[3] = width * height;
+ }
+ else
+ {
+ ByteCount[0] = width * height;
+ ByteCount[1] = width * height;
+ ByteCount[2] = width * height;
+ ByteCount[3] = width * height;
+ }
+
+ return maxPlaneSize;
+}
+
+NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
+ int width, int height, int scanline, int* numMessages, int maxDataSize)
+{
+ int i, j, k;
+ int dataOffset;
+ int rows, cols;
+ int BytesPerPixel;
+ int MaxRegionWidth;
+ int MaxRegionHeight;
+ UINT32 ByteCount[4];
+ UINT32 MaxPlaneSize;
+ UINT32 MaxMessageSize;
+ NSC_MESSAGE* messages;
+
+ k = 0;
+ MaxRegionWidth = 64 * 4;
+ MaxRegionHeight = 64 * 2;
+ BytesPerPixel = (context->bpp / 8);
+
+ rows = (width + (MaxRegionWidth - (width % MaxRegionWidth))) / MaxRegionWidth;
+ cols = (height + (MaxRegionHeight - (height % MaxRegionHeight))) / MaxRegionHeight;
+ *numMessages = rows * cols;
+
+ MaxPlaneSize = nsc_compute_byte_count(context, (UINT32*) ByteCount, width, height);
+ MaxMessageSize = ByteCount[0] + ByteCount[1] + ByteCount[2] + ByteCount[3] + 20;
+
+ maxDataSize -= 1024; /* reserve enough space for headers */
+
+ messages = (NSC_MESSAGE*) malloc(sizeof(NSC_MESSAGE) * (*numMessages));
+ ZeroMemory(messages, sizeof(sizeof(NSC_MESSAGE) * (*numMessages)));
+
+ for (i = 0; i < rows; i++)
+ {
+ for (j = 0; j < cols; j++)
+ {
+ messages[k].x = x + (i * MaxRegionWidth);
+ messages[k].y = y + (j * MaxRegionHeight);
+ messages[k].width = (i < (rows - 1)) ? MaxRegionWidth : width - (i * MaxRegionWidth);
+ messages[k].height = (j < (cols - 1)) ? MaxRegionHeight : height - (j * MaxRegionHeight);
+ messages[k].data = data;
+ messages[k].scanline = scanline;
+
+ messages[k].MaxPlaneSize = nsc_compute_byte_count(context,
+ (UINT32*) messages[k].OrgByteCount, messages[k].width, messages[k].height);
+
+ k++;
+ }
+ }
+
+ *numMessages = k;
+
+ for (i = 0; i < *numMessages; i++)
+ {
+ messages[i].PlaneBuffers[0] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[1] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[2] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[3] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[4] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ }
+
+ for (i = 0; i < *numMessages; i++)
+ {
+ context->width = messages[i].width;
+ context->height = messages[i].height;
+ context->OrgByteCount[0] = messages[i].OrgByteCount[0];
+ context->OrgByteCount[1] = messages[i].OrgByteCount[1];
+ context->OrgByteCount[2] = messages[i].OrgByteCount[2];
+ context->OrgByteCount[3] = messages[i].OrgByteCount[3];
+ context->priv->PlaneBuffersLength = messages[i].MaxPlaneSize;
+ context->priv->PlaneBuffers[0] = messages[i].PlaneBuffers[0];
+ context->priv->PlaneBuffers[1] = messages[i].PlaneBuffers[1];
+ context->priv->PlaneBuffers[2] = messages[i].PlaneBuffers[2];
+ context->priv->PlaneBuffers[3] = messages[i].PlaneBuffers[3];
+ context->priv->PlaneBuffers[4] = messages[i].PlaneBuffers[4];
+
+ dataOffset = (messages[i].y * messages[i].scanline) + (messages[i].x * BytesPerPixel);
+
+ PROFILER_ENTER(context->priv->prof_nsc_encode);
+ context->encode(context, &data[dataOffset], scanline);
+ PROFILER_EXIT(context->priv->prof_nsc_encode);
+
+ PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data);
+ nsc_rle_compress_data(context);
+ PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data);
+
+ messages[i].PlaneByteCount[0] = context->nsc_stream.PlaneByteCount[0];
+ messages[i].PlaneByteCount[1] = context->nsc_stream.PlaneByteCount[1];
+ messages[i].PlaneByteCount[2] = context->nsc_stream.PlaneByteCount[2];
+ messages[i].PlaneByteCount[3] = context->nsc_stream.PlaneByteCount[3];
+ }
+
+ context->priv->PlaneBuffers[0] = NULL;
+ context->priv->PlaneBuffers[1] = NULL;
+ context->priv->PlaneBuffers[2] = NULL;
+ context->priv->PlaneBuffers[3] = NULL;
+ context->priv->PlaneBuffers[4] = NULL;
+
+ return messages;
+}
+
+int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
+{
+ int i;
+
+ Stream_EnsureRemainingCapacity(s, 20);
+ Stream_Write_UINT32(s, message->PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT32(s, message->PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT32(s, message->PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT32(s, message->PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */
+ Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
+ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
+
+ for (i = 0; i < 4; i++)
+ {
+ if (message->PlaneByteCount[i] > 0)
+ {
+ Stream_EnsureRemainingCapacity(s, (int) message->PlaneByteCount[i]);
+ Stream_Write(s, message->PlaneBuffers[i], message->PlaneByteCount[i]);
+ }
+ }
+
+ return 0;
+}
+
+int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
+{
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[0]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[1]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[2]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[3]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[4]);
+ return 0;
+}
+
+void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width, int height, int scanline)
{
int i;
@@ -340,7 +522,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s,
/* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */
PROFILER_ENTER(context->priv->prof_nsc_encode);
- context->encode(context, bmpdata, rowstride);
+ context->encode(context, data, scanline);
PROFILER_EXIT(context->priv->prof_nsc_encode);
/* RLE encode */
@@ -363,7 +545,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s,
if (context->nsc_stream.PlaneByteCount[i] > 0)
{
Stream_EnsureRemainingCapacity(s, (int) context->nsc_stream.PlaneByteCount[i]);
- Stream_Write(s, context->priv->plane_buf[i], context->nsc_stream.PlaneByteCount[i]);
+ Stream_Write(s, context->priv->PlaneBuffers[i], context->nsc_stream.PlaneByteCount[i]);
}
}
}
diff --git a/libfreerdp/codec/nsc_sse2.c b/libfreerdp/codec/nsc_sse2.c
index f1a033fc4..f4f1eb1bf 100644
--- a/libfreerdp/codec/nsc_sse2.c
+++ b/libfreerdp/codec/nsc_sse2.c
@@ -28,10 +28,12 @@
#include
#include
+#include
+
#include "nsc_types.h"
#include "nsc_sse2.h"
-static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
+static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int scanline)
{
UINT16 x;
UINT16 y;
@@ -56,18 +58,19 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
tempHeight = ROUND_UP_TO(context->height, 2);
rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width);
ccl = context->nsc_stream.ColorLossLevel;
- yplane = context->priv->plane_buf[0];
- coplane = context->priv->plane_buf[1];
- cgplane = context->priv->plane_buf[2];
- aplane = context->priv->plane_buf[3];
+ yplane = context->priv->PlaneBuffers[0];
+ coplane = context->priv->PlaneBuffers[1];
+ cgplane = context->priv->PlaneBuffers[2];
+ aplane = context->priv->PlaneBuffers[3];
for (y = 0; y < context->height; y++)
{
- src = bmpdata + (context->height - 1 - y) * rowstride;
- yplane = context->priv->plane_buf[0] + y * rw;
- coplane = context->priv->plane_buf[1] + y * rw;
- cgplane = context->priv->plane_buf[2] + y * rw;
- aplane = context->priv->plane_buf[3] + y * context->width;
+ src = data + (context->height - 1 - y) * scanline;
+ yplane = context->priv->PlaneBuffers[0] + y * rw;
+ coplane = context->priv->PlaneBuffers[1] + y * rw;
+ cgplane = context->priv->PlaneBuffers[2] + y * rw;
+ aplane = context->priv->PlaneBuffers[3] + y * context->width;
+
for (x = 0; x < context->width; x += 8)
{
switch (context->pixel_format)
@@ -79,6 +82,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19), *(src + 15), *(src + 11), *(src + 7), *(src + 3));
src += 32;
break;
+
case RDP_PIXEL_FORMAT_R8G8B8A8:
r_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16), *(src + 12), *(src + 8), *(src + 4), *src);
g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17), *(src + 13), *(src + 9), *(src + 5), *(src + 1));
@@ -86,6 +90,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19), *(src + 15), *(src + 11), *(src + 7), *(src + 3));
src += 32;
break;
+
case RDP_PIXEL_FORMAT_B8G8R8:
b_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12), *(src + 9), *(src + 6), *(src + 3), *src);
g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13), *(src + 10), *(src + 7), *(src + 4), *(src + 1));
@@ -93,6 +98,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
a_val = _mm_set1_epi16(0xFF);
src += 24;
break;
+
case RDP_PIXEL_FORMAT_R8G8B8:
r_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12), *(src + 9), *(src + 6), *(src + 3), *src);
g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13), *(src + 10), *(src + 7), *(src + 4), *(src + 1));
@@ -100,6 +106,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
a_val = _mm_set1_epi16(0xFF);
src += 24;
break;
+
case RDP_PIXEL_FORMAT_B5G6R5_LE:
b_val = _mm_set_epi16(
(((*(src + 15)) & 0xF8) | ((*(src + 15)) >> 5)),
@@ -131,6 +138,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
a_val = _mm_set1_epi16(0xFF);
src += 16;
break;
+
case RDP_PIXEL_FORMAT_R5G6B5_LE:
r_val = _mm_set_epi16(
(((*(src + 15)) & 0xF8) | ((*(src + 15)) >> 5)),
@@ -162,6 +170,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
a_val = _mm_set1_epi16(0xFF);
src += 16;
break;
+
case RDP_PIXEL_FORMAT_P4_PLANER:
{
int shift;
@@ -206,6 +215,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
}
a_val = _mm_set1_epi16(0xFF);
break;
+
case RDP_PIXEL_FORMAT_P8:
{
r_val = _mm_set_epi16(
@@ -239,6 +249,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
}
a_val = _mm_set1_epi16(0xFF);
break;
+
default:
r_val = g_val = b_val = a_val = _mm_set1_epi16(0);
break;
@@ -266,18 +277,20 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata,
cgplane += 8;
aplane += 8;
}
+
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (context->width % 2) == 1)
{
- context->priv->plane_buf[0][y * rw + context->width] = context->priv->plane_buf[0][y * rw + context->width - 1];
- context->priv->plane_buf[1][y * rw + context->width] = context->priv->plane_buf[1][y * rw + context->width - 1];
- context->priv->plane_buf[2][y * rw + context->width] = context->priv->plane_buf[2][y * rw + context->width - 1];
+ context->priv->PlaneBuffers[0][y * rw + context->width] = context->priv->PlaneBuffers[0][y * rw + context->width - 1];
+ context->priv->PlaneBuffers[1][y * rw + context->width] = context->priv->PlaneBuffers[1][y * rw + context->width - 1];
+ context->priv->PlaneBuffers[2][y * rw + context->width] = context->priv->PlaneBuffers[2][y * rw + context->width - 1];
}
}
+
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
{
- memcpy(yplane + rw, yplane, rw);
- memcpy(coplane + rw, coplane, rw);
- memcpy(cgplane + rw, cgplane, rw);
+ CopyMemory(yplane + rw, yplane, rw);
+ CopyMemory(coplane + rw, coplane, rw);
+ CopyMemory(cgplane + rw, cgplane, rw);
}
}
@@ -302,12 +315,13 @@ static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context)
for (y = 0; y < tempHeight >> 1; y++)
{
- co_dst = context->priv->plane_buf[1] + y * (tempWidth >> 1);
- cg_dst = context->priv->plane_buf[2] + y * (tempWidth >> 1);
- co_src0 = (INT8*) context->priv->plane_buf[1] + (y << 1) * tempWidth;
+ co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
+ cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
+ co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
co_src1 = co_src0 + tempWidth;
- cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth;
+ cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
cg_src1 = cg_src0 + tempWidth;
+
for (x = 0; x < tempWidth >> 1; x += 8)
{
t = _mm_loadu_si128((__m128i*) co_src0);
@@ -333,9 +347,10 @@ static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context)
}
}
-static void nsc_encode_sse2(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
+static void nsc_encode_sse2(NSC_CONTEXT* context, BYTE* data, int scanline)
{
- nsc_encode_argb_to_aycocg_sse2(context, bmpdata, rowstride);
+ nsc_encode_argb_to_aycocg_sse2(context, data, scanline);
+
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
{
nsc_encode_subsampling_sse2(context);
diff --git a/libfreerdp/codec/nsc_types.h b/libfreerdp/codec/nsc_types.h
index 060b89daa..0964167a2 100644
--- a/libfreerdp/codec/nsc_types.h
+++ b/libfreerdp/codec/nsc_types.h
@@ -25,6 +25,9 @@
#include "config.h"
#endif
+#include
+#include
+
#include
#include