Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Armin Novak 2013-08-06 11:58:21 +02:00
commit 21d7e433c9
78 changed files with 3996 additions and 727 deletions

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string></string>
<key>CFBundleIconFile</key>
<string>FreeRDP</string>
<key>CFBundleIdentifier</key>
<string>FreeRDP.Mac</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string></string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string></string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2012 __MyCompanyName__. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -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;

View File

@ -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;
}

View File

@ -0,0 +1,22 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# 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()

View File

@ -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})

View File

@ -0,0 +1,47 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# 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")

View File

@ -0,0 +1,341 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Display Update Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/print.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <winpr/cmdline.h>
#include <winpr/collections.h>
#include <freerdp/addin.h>
#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;
}

View File

@ -0,0 +1,40 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Display Update Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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 <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/utils/debug.h>
#include <freerdp/client/disp.h>
#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 */

View File

@ -212,7 +212,7 @@ 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);
@ -249,6 +249,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 +265,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 +332,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 +362,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;
}

View File

@ -35,7 +35,8 @@
/* Protocol Version */
#define RDPINPUT_PROTOCOL_V1 0x00010000
#define RDPINPUT_PROTOCOL_V10 0x00010000
#define RDPINPUT_PROTOCOL_V101 0x00010001
/* Client Ready Flags */

View File

@ -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}

View File

@ -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);

View File

@ -106,15 +106,15 @@ if (${BUILD_SHARED_LIBS})
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:${LIB}>"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
COMMENT "Copying ${LIB} to output directory"
COMMAND install_name_tool -change "$<TARGET_SONAME_FILE:${LIB}>"
"@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/${MODULE_NAME}"
"@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${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 "$<TARGET_SONAME_FILE:${LIB}>"
"@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/${MODULE_NAME}")
"@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${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 +123,8 @@ if (${BUILD_SHARED_LIBS})
# message("adding post-build dependency: ${LIB}")
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND install_name_tool -change "$<TARGET_SONAME_FILE:${LIB}>"
"@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Contents/$<TARGET_FILE_NAME:${DEST}>"
"@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$<TARGET_FILE_NAME:${LIB}>"
"${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Contents/$<TARGET_FILE_NAME:${DEST}>"
COMMENT Setting install name for ${LIB} in module ${DEST})
endforeach()
endforeach()
@ -145,7 +145,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,7 +153,7 @@ 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 ${xib}
COMMENT "Compiling ${xib}")
endforeach()
endif()
@ -162,13 +162,13 @@ endif()
foreach(HEADER ${${MODULE_NAME}_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 ${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
COMMENT Copying FreeRDP header files to ${MODULE_NAME})
add_subdirectory(cli)

View File

@ -78,6 +78,8 @@
int kdlmeta;
int kdrmeta;
int kdcapslock;
BOOL initialized;
@public
NSPasteboard* pasteboard_rd; /* for reading from clipboard */
@ -107,3 +109,8 @@
#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);

View File

@ -75,9 +75,6 @@ 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);
@ -129,28 +126,19 @@ struct rgba_data
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);
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);
status = freerdp_connect(context->instance);
if (!status)
{
@ -185,7 +173,7 @@ struct rgba_data
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
self = [super initWithFrame:frame];
if (self)
{
@ -201,24 +189,34 @@ 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];
mouseInClientArea = YES;
initialized = YES;
}
}
/** *********************************************************************
@ -619,11 +617,6 @@ struct rgba_data
if (run_loop_src_channels != 0)
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_channels, kCFRunLoopDefaultMode);
freerdp_client_stop(self->context);
freerdp_client_context_free(self->context);
}
/** *********************************************************************
@ -782,8 +775,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;
@ -868,8 +870,7 @@ 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];
[view setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight];
freerdp_channels_pre_connect(instance->context->channels, instance);
return TRUE;
@ -888,13 +889,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 +903,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 +922,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;
}
@ -983,7 +975,7 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
MRDPCursor* mrdpCursor = [[MRDPCursor alloc] init];
mfContext* mfc = (mfContext*) context;
MRDPView* view = (MRDPView*) mfc->view;
rect.size.width = pointer->width;
rect.size.height = pointer->height;
rect.origin.x = pointer->xPos;
@ -994,10 +986,7 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData,
pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv);
// TODO if xorBpp is > 24 need to call freerdp_image_swap_color_order
// see file df_graphics.c
/* store cursor bitmap image in representation - required by NSImage */
bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data
pixelsWide:rect.size.width
@ -1065,8 +1054,6 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
MRDPView* view = (MRDPView*) mfc->view;
NSMutableArray* ma = view->cursors;
return; /* disable pointer until it is fixed */
if (!view->mouseInClientArea)
return;
@ -1152,10 +1139,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];
}
@ -1235,6 +1222,7 @@ static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBac
freerdp_channels_process_pending_messages(instance);
event = freerdp_channels_pop_event(instance->context->channels);
if (event)
{
switch (GetMessageClass(event->id))

View File

@ -7,8 +7,8 @@
//
#import <Cocoa/Cocoa.h>
#import <MacFreeRDP-library/MRDPView.h>
#import <MacFreeRDP-library/mfreerdp.h>
#import <MacFreeRDP/MRDPView.h>
#import <MacFreeRDP/mfreerdp.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
@ -20,6 +20,5 @@
@property (assign) IBOutlet NSWindow *window;
@property (assign) rdpContext *context;
@property (assign) IBOutlet MRDPView *mrdpView;
@end

View File

@ -7,8 +7,12 @@
//
#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(rdpContext* context, EmbedWindowEventArgs* e);
@implementation AppDelegate
@ -19,7 +23,6 @@
@synthesize window = window;
@synthesize mrdpView = mrdpView;
@synthesize context = context;
@ -28,6 +31,7 @@
int status;
mfContext* mfc;
_singleDelegate = self;
[self CreateContext];
status = [self ParseCommandLineArguments];
@ -41,6 +45,7 @@
}
else
{
PubSub_Subscribe(context->pubSub, "EmbedWindow", (pEventHandler) AppDelegate_EmbedWindowEventHandler);
freerdp_client_start(context);
}
}
@ -48,6 +53,7 @@
- (void) applicationWillTerminate:(NSNotification*)notification
{
[mrdpView releaseResources];
_singleDelegate = nil;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
@ -103,4 +109,19 @@
context = nil;
}
@end
void AppDelegate_EmbedWindowEventHandler(rdpContext* context, EmbedWindowEventArgs* e)
{
if (_singleDelegate)
{
mfContext* mfc = (mfContext*) context;
_singleDelegate->mrdpView = mfc->view;
if (_singleDelegate->window)
{
[[_singleDelegate->window contentView] addSubview:mfc->view];
}
}
}

View File

@ -2,18 +2,16 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1070</int>
<string key="IBDocument.SystemVersion">12D78</string>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.37</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">3084</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>NSCustomObject</string>
<string>NSCustomView</string>
<string>NSMenu</string>
<string>NSMenuItem</string>
<string>NSView</string>
@ -257,24 +255,12 @@
<object class="NSView" key="NSWindowView" id="439893737">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSCustomView" id="467991374">
<reference key="NSNextResponder" ref="439893737"/>
<int key="NSvFlags">268</int>
<string key="NSFrameSize">{1024, 768}</string>
<reference key="NSSuperview" ref="439893737"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<string key="NSClassName">MRDPView</string>
</object>
</array>
<array class="NSMutableArray" key="NSSubviews"/>
<string key="NSFrameSize">{1024, 768}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="467991374"/>
<reference key="NSNextKeyView"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
<string key="NSMinSize">{1024, 790}</string>
<string key="NSMaxSize">{1024, 790}</string>
<int key="NSWindowCollectionBehavior">128</int>
@ -369,14 +355,6 @@
</object>
<int key="connectionID">493</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">mrdpView</string>
<reference key="source" ref="976324537"/>
<reference key="destination" ref="467991374"/>
</object>
<int key="connectionID">569</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">window</string>
@ -551,73 +529,7 @@
<object class="IBObjectRecord">
<int key="objectID">372</int>
<reference key="object" ref="439893737"/>
<array class="NSMutableArray" key="children">
<reference ref="467991374"/>
<object class="IBNSLayoutConstraint" id="334327932">
<reference key="firstItem" ref="467991374"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="439893737"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="439893737"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="890641817">
<reference key="firstItem" ref="467991374"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="439893737"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="439893737"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="437142032">
<reference key="firstItem" ref="467991374"/>
<int key="firstAttribute">4</int>
<int key="relation">0</int>
<reference key="secondItem" ref="439893737"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="439893737"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="934352021">
<reference key="firstItem" ref="467991374"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="439893737"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="439893737"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
</array>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="972006081"/>
</object>
<object class="IBObjectRecord">
@ -657,31 +569,6 @@
<reference key="object" ref="976324537"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">551</int>
<reference key="object" ref="467991374"/>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">561</int>
<reference key="object" ref="334327932"/>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">562</int>
<reference key="object" ref="890641817"/>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">563</int>
<reference key="object" ref="437142032"/>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">564</int>
<reference key="object" ref="934352021"/>
<reference key="parent" ref="439893737"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -706,12 +593,6 @@
<string key="371.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="371.IBWindowTemplateEditedContentRect">{{380, 496}, {480, 360}}</string>
<integer value="1" key="371.NSWindowTemplate.visibleAtLaunch"/>
<array class="NSMutableArray" key="372.IBNSViewMetadataConstraints">
<reference ref="334327932"/>
<reference ref="890641817"/>
<reference ref="437142032"/>
<reference ref="934352021"/>
</array>
<string key="372.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="375.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="420.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
@ -720,13 +601,7 @@
<string key="492.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="494.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="551.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="551.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="56.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="561.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="562.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="563.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="564.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="57.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="58.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="83.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
@ -738,48 +613,7 @@
<nil key="sourceID"/>
<int key="maxID">570</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">AppDelegate</string>
<string key="superclassName">NSObject</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="mrdpView">MRDPView</string>
<string key="window">NSWindow</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="mrdpView">
<string key="name">mrdpView</string>
<string key="candidateClassName">MRDPView</string>
</object>
<object class="IBToOneOutletInfo" key="window">
<string key="name">window</string>
<string key="candidateClassName">NSWindow</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/AppDelegate.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MRDPView</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MRDPView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">

View File

@ -25,6 +25,7 @@
#include <freerdp/constants.h>
#include <freerdp/utils/signal.h>
#include <freerdp/client/cmdline.h>
#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,20 +68,34 @@ 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)
{
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->view_ownership)
{
MRDPView* view = (MRDPView*) mfc->view;
[view releaseResources];
[view release];
mfc->view = nil;
}
return 0;
}
@ -84,7 +106,12 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
mfc = (mfContext*) instance->context;
context->channels = freerdp_channels_new();
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;

View File

@ -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;

View File

@ -2,6 +2,7 @@
# FreeRDP X11 Client
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -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
@ -101,11 +104,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})

View File

@ -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;
}

View File

@ -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

View File

@ -3,6 +3,7 @@
* X11 Client Interface
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
*
* 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 <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef WITH_XRENDER
#include <X11/extensions/Xrender.h>
#endif
#ifdef WITH_XI
#include <X11/extensions/XInput2.h>
#endif
#ifdef WITH_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
@ -73,6 +82,7 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/file.h>
#include <winpr/print.h>
#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)
@ -1522,16 +1606,64 @@ void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
void xf_ParamChangeEventHandler(rdpContext* context, ParamChangeEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
switch (e->id)
{
case FreeRDP_ScalingFactor:
break;
case FreeRDP_ScalingFactor:
default:
break;
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
*/
@ -1585,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;
@ -1656,6 +1766,8 @@ int xfreerdp_client_new(freerdp* instance, rdpContext* context)
PubSub_SubscribeTerminate(context->pubSub, (pTerminateEventHandler) xf_TerminateEventHandler);
PubSub_SubscribeParamChange(context->pubSub, (pParamChangeEventHandler) xf_ParamChangeEventHandler);
PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
return 0;
}

View File

@ -44,6 +44,7 @@ extern "C" {
* Client Interface
*/
FREERDP_API int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints);
#ifdef __cplusplus

View File

@ -32,6 +32,7 @@
#include "xf_input.h"
#include "xf_event.h"
#include "xf_input.h"
const char* const X11_EVENT_STRINGS[] =
{
@ -88,39 +89,40 @@ 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);
}
else
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
} else
{
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 != NULL )
{
xfw = (xfWindow*) window->extra;
xf_UpdateWindowArea(xfc, xfw, x, y, w, h);
}
}
return TRUE;
}
@ -156,12 +158,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 +178,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 +262,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 +286,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 +301,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 +355,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 +373,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 +557,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 +586,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 +947,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 +1023,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);

View File

@ -28,13 +28,17 @@
#include <math.h>
#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 +47,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 +77,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 +94,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 +190,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 +372,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 +443,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 +454,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 +464,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 +473,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 +485,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 +493,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 +503,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;
}
@ -390,67 +557,66 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
int touchId;
int contactId;
RdpeiClientContext* rdpei = xfc->rdpei;
if (!rdpei)
return 0;
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;
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 +624,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 +659,10 @@ void xf_process_rdpei_event(xfContext* xfc, wMessage* event)
{
case RdpeiChannel_ServerReady:
break;
case RdpeiChannel_SuspendTouch:
break;
case RdpeiChannel_ResumeTouch:
break;
}
@ -505,14 +671,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;
}

View File

@ -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;
}

View File

@ -44,6 +44,7 @@
#ifdef WITH_XI
#include <X11/extensions/XInput2.h>
#include "xf_input.h"
#endif
#include "xf_input.h"

View File

@ -106,7 +106,7 @@ struct xf_context
UINT16 frame_x2;
UINT16 frame_y2;
double scale;
//double scale;
int originalWidth;
int originalHeight;
int currentWidth;
@ -114,6 +114,9 @@ struct xf_context
int XInputOpcode;
BOOL enableScaling;
int offset_x;
int offset_y;
BOOL focused;
BOOL use_xinput;
BOOL mouse_active;
@ -208,7 +211,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);

View File

@ -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;
}

View File

@ -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" },
@ -597,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];
@ -607,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)
@ -1238,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")
{
@ -1633,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)
{

View File

@ -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")
{

View File

@ -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 TRUE
#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) \
@ -731,11 +732,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);

View File

@ -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;
}

237
cmake/FindImageMagick.cmake Normal file
View File

@ -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_<component>_FOUND - TRUE if <component> is found.
# ImageMagick_<component>_EXECUTABLE - Full path to <component> 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_<component>_FOUND - TRUE if <component> is found.
# ImageMagick_<component>_INCLUDE_DIRS - Full path to <component> include dirs.
# ImageMagick_<component>_LIBRARIES - Full path to <component> 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 <miguelf at ieee dot org>
# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de>
#
# 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
# <ImageMagick_EXECUTABLE_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
)

View File

@ -14,6 +14,7 @@
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -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)

View File

@ -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 <mail@cynapses.org>
#
# (Changes for libusb) Copyright (c) 2008 Kyle Machulis <kyle@nonpolynomial.com>
#
# 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)

View File

@ -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
}

View File

@ -0,0 +1,64 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Display Update Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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 */

View File

@ -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);

View File

@ -23,6 +23,12 @@
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
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 */

View File

@ -41,11 +41,6 @@ DEFINE_EVENT_BEGIN(ResizeWindow)
int width;
int height;
DEFINE_EVENT_END(ResizeWindow)
DEFINE_EVENT_BEGIN(EmbedWindow)
BOOL embed;
void* handle;
DEFINE_EVENT_END(EmbedWindow)
DEFINE_EVENT_BEGIN(PanningChange)
int XPan;
@ -56,6 +51,16 @@ 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;
void* handle;
DEFINE_EVENT_END(EmbedWindow)
DEFINE_EVENT_BEGIN(ErrorInfo)
UINT32 code;
DEFINE_EVENT_END(ErrorInfo)
@ -68,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

View File

@ -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 */
};

View File

@ -633,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
@ -1019,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 */
@ -1027,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 */
/**

View File

@ -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;

View File

@ -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

View File

@ -1,6 +1,6 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Compressed Bitmap
* Bitmap Decompression
*
* Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
*

File diff suppressed because it is too large Load Diff

View File

@ -156,7 +156,6 @@ RFX_CONTEXT* rfx_context_new(void)
ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV));
context->priv->TilePool = Queue_New(TRUE, -1, -1);
context->priv->TileQueue = Queue_New(TRUE, -1, -1);
/*
* align buffers to 16 byte boundary (needed for SSE/NEON instructions)
@ -254,7 +253,6 @@ void rfx_context_free(RFX_CONTEXT* context)
free(context->quants);
Queue_Free(context->priv->TilePool);
Queue_Free(context->priv->TileQueue);
rfx_profiler_print(context);
rfx_profiler_free(context);
@ -314,8 +312,7 @@ RFX_TILE* rfx_tile_pool_take(RFX_CONTEXT* context)
{
RFX_TILE* tile = NULL;
if (WaitForSingleObject(Queue_Event(context->priv->TilePool), 0) == WAIT_OBJECT_0)
tile = Queue_Dequeue(context->priv->TilePool);
tile = Queue_Dequeue(context->priv->TilePool);
if (!tile)
{

View File

@ -40,7 +40,6 @@
struct _RFX_CONTEXT_PRIV
{
wQueue* TilePool;
wQueue* TileQueue;
BOOL UseThreads;
DWORD MinThreadCount;

View File

@ -562,14 +562,14 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
return settings->PlayRemoteFx;
break;
case FreeRDP_GatewayUsageMethod:
return settings->GatewayUsageMethod;
break;
case FreeRDP_GatewayUseSameCredentials:
return settings->GatewayUseSameCredentials;
break;
case FreeRDP_GatewayEnabled:
return settings->GatewayEnabled;
break;
case FreeRDP_RemoteApplicationMode:
return settings->RemoteApplicationMode;
break;
@ -1017,14 +1017,14 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->PlayRemoteFx = param;
break;
case FreeRDP_GatewayUsageMethod:
settings->GatewayUsageMethod = param;
break;
case FreeRDP_GatewayUseSameCredentials:
settings->GatewayUseSameCredentials = param;
break;
case FreeRDP_GatewayEnabled:
settings->GatewayEnabled = param;
break;
case FreeRDP_RemoteApplicationMode:
settings->RemoteApplicationMode = param;
break;
@ -1417,6 +1417,10 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id)
return settings->PercentScreen;
break;
case FreeRDP_GatewayUsageMethod:
return settings->GatewayUsageMethod;
break;
case FreeRDP_GatewayPort:
return settings->GatewayPort;
break;
@ -1736,6 +1740,10 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
settings->PercentScreen = param;
break;
case FreeRDP_GatewayUsageMethod:
settings->GatewayUsageMethod = param;
break;
case FreeRDP_GatewayPort:
settings->GatewayPort = param;
break;
@ -2323,3 +2331,4 @@ int freerdp_set_param_double(rdpSettings* settings, int id, double param)
return 0;
}

View File

@ -75,17 +75,21 @@ BOOL rdp_client_connect(rdpRdp* rdp)
nego_init(rdp->nego);
nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort);
if (settings->GatewayUsageMethod)
if (settings->GatewayEnabled)
{
char* user;
char* user;
char* domain;
char* cookie;
int user_length;
int user_length = 0;
int domain_length;
int cookie_length;
user = settings->Username;
user_length = strlen(settings->Username);
if (settings->Username)
{
user = settings->Username;
user_length = strlen(settings->Username);
}
if (settings->Domain)
domain = settings->Domain;
@ -100,8 +104,11 @@ BOOL rdp_client_connect(rdpRdp* rdp)
CopyMemory(cookie, domain, domain_length);
CharUpperBuffA(cookie, domain_length);
cookie[domain_length] = '\\';
CopyMemory(&cookie[domain_length + 1], user, user_length);
cookie[cookie_length] = '\0';
if (settings->Username)
CopyMemory(&cookie[domain_length + 1], user, user_length);
cookie[cookie_length] = '\0';
nego_set_cookie(rdp->nego, cookie);
free(cookie);

View File

@ -856,6 +856,8 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
comp_flags = FASTPATH_OUTPUT_COMPRESSION_USED;
header_bytes = 7 + sec_bytes;
bm = (BYTE*) (rdp->mppc_enc->outputBuffer - header_bytes);
if (comp_update)
Stream_Free(comp_update, FALSE);
comp_update = Stream_New(bm, pdu_data_bytes + header_bytes);
ls = comp_update;
}
@ -902,6 +904,8 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
Stream_Write_UINT16(ls, pdu_data_bytes);
if (update)
Stream_Free(update, FALSE);
update = Stream_New(bm, pduLength);
Stream_Seek(update, pduLength);

View File

@ -56,6 +56,7 @@ BOOL freerdp_connect(freerdp* instance)
rdpRdp* rdp;
rdpSettings* settings;
BOOL status = FALSE;
ConnectionResultEventArgs e;
/* We always set the return code to 0 before we start the connect sequence*/
connectErrorCode = 0;
@ -169,6 +170,10 @@ BOOL freerdp_connect(freerdp* instance)
SetEvent(rdp->transport->connectedEvent);
EventArgsInit(&e, "freerdp");
e.result = status ? 0 : -1;
PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e);
return status;
}
@ -325,12 +330,16 @@ static wEventType FreeRDP_Events[] =
{
DEFINE_EVENT_ENTRY(WindowStateChange)
DEFINE_EVENT_ENTRY(ResizeWindow)
DEFINE_EVENT_ENTRY(LocalResizeWindow)
DEFINE_EVENT_ENTRY(EmbedWindow)
DEFINE_EVENT_ENTRY(PanningChange)
DEFINE_EVENT_ENTRY(ScalingFactorChange)
DEFINE_EVENT_ENTRY(ErrorInfo)
DEFINE_EVENT_ENTRY(ParamChange)
DEFINE_EVENT_ENTRY(Terminate)
DEFINE_EVENT_ENTRY(ConnectionResult)
DEFINE_EVENT_ENTRY(ChannelConnected)
DEFINE_EVENT_ENTRY(ChannelDisconnected)
};
/** Allocator function for a rdp context.

View File

@ -1369,6 +1369,10 @@ BOOL tsg_disconnect(rdpTsg* tsg)
* | |
*/
if (tsg == NULL)
return FALSE;
tsg->rpc->client->SynchronousReceive = TRUE;
/* if we are already in state pending (i.e. if a server initiated disconnect was issued)
@ -1392,7 +1396,12 @@ BOOL tsg_disconnect(rdpTsg* tsg)
int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
{
int CopyLength;
rdpRpc* rpc = tsg->rpc;
rdpRpc* rpc;
if (tsg == NULL)
return -1;
rpc = tsg->rpc;
if (tsg->PendingPdu)
{

View File

@ -213,7 +213,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
}
if (transport->settings->GatewayUsageMethod)
if (transport->settings->GatewayEnabled)
{
transport->layer = TRANSPORT_LAYER_TSG;
transport->TcpOut = tcp_new(settings);
@ -788,7 +788,6 @@ static void* transport_client_thread(void* arg)
freerdp* instance;
rdpContext* context;
rdpTransport* transport;
TerminateEventArgs e;
transport = (rdpTransport*) arg;
instance = (freerdp*) transport->settings->instance;

View File

@ -184,7 +184,7 @@ BOOL tls_connect(rdpTls* tls)
return FALSE;
}
if (tls->settings->GatewayUsageMethod)
if (tls->settings->GatewayEnabled)
hostname = tls->settings->GatewayHostname;
else
hostname = tls->settings->ServerHostname;

View File

@ -739,6 +739,28 @@ void gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb)
fprintf(stderr, "EllipseCB\n");
}
void gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
{
DEBUG_GDI("frameId %d frameAction %d",
surface_frame_marker->frameId,
surface_frame_marker->frameAction);
/* TODO: Implement frame marker completely */
switch (surface_frame_marker->frameAction)
{
case SURFACECMD_FRAMEACTION_BEGIN:
break;
case SURFACECMD_FRAMEACTION_END:
if (context->instance->settings->FrameAcknowledge > 0)
{
IFCALL(context->instance->update->SurfaceFrameAcknowledge, context, surface_frame_marker->frameId);
}
break;
}
}
int tilenum = 0;
void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
@ -890,6 +912,7 @@ void gdi_register_update_callbacks(rdpUpdate* update)
primary->EllipseCB = gdi_ellipse_cb;
update->SurfaceBits = gdi_surface_bits;
update->SurfaceFrameMarker = gdi_surface_frame_marker;
}
void gdi_init_primary(rdpGdi* gdi)

View File

@ -91,14 +91,24 @@ BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode)
0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hKey);
if (status != ERROR_SUCCESS)
{
printf("Error opening RegKey: status=%0X\n", status);
if (status == ERROR_ACCESS_DENIED)
printf("access denied. Do you have admin privleges?\n");
return FALSE;
}
dwSize = sizeof(DWORD);
status = RegQueryValueEx(hKey, _T("Attach.ToDesktop"),
NULL, &dwType, (BYTE*) &dwValue, &dwSize);
if (status != ERROR_SUCCESS)
{
printf("Error querying RegKey: status=%0X\n", status);
if (status == ERROR_ACCESS_DENIED)
printf("access denied. Do you have admin privleges?\n");
return FALSE;
}
if (dwValue ^ mode) //only if we want to change modes
{
@ -240,6 +250,28 @@ BOOL wf_mirror_driver_map_memory(wfInfo* wfi)
if (wfi->driverDC == NULL)
{
_tprintf(_T("Could not create device driver context!\n"));
{
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
_tprintf(_T("CreateDC failed on device [%s] with error %d: %s\n"), wfi->deviceName, dw, lpMsgBuf);
LocalFree(lpMsgBuf);
}
return FALSE;
}

View File

@ -58,7 +58,7 @@ struct _wQueue
int tail;
int size;
void** array;
HANDLE mutex;
CRITICAL_SECTION lock;
HANDLE event;
wObject object;
@ -67,8 +67,8 @@ typedef struct _wQueue wQueue;
WINPR_API int Queue_Count(wQueue* queue);
WINPR_API BOOL Queue_Lock(wQueue* queue);
WINPR_API BOOL Queue_Unlock(wQueue* queue);
WINPR_API void Queue_Lock(wQueue* queue);
WINPR_API void Queue_Unlock(wQueue* queue);
WINPR_API HANDLE Queue_Event(wQueue* queue);
@ -93,7 +93,7 @@ struct _wStack
int size;
int capacity;
void** array;
HANDLE mutex;
CRITICAL_SECTION lock;
BOOL synchronized;
wObject object;
};
@ -125,7 +125,7 @@ struct _wArrayList
int size;
void** array;
HANDLE mutex;
CRITICAL_SECTION lock;
wObject object;
};
@ -137,8 +137,8 @@ WINPR_API BOOL ArrayList_IsFixedSized(wArrayList* arrayList);
WINPR_API BOOL ArrayList_IsReadOnly(wArrayList* arrayList);
WINPR_API BOOL ArrayList_IsSynchronized(wArrayList* arrayList);
WINPR_API BOOL ArrayList_Lock(wArrayList* arrayList);
WINPR_API BOOL ArrayList_Unlock(wArrayList* arrayList);
WINPR_API void ArrayList_Lock(wArrayList* arrayList);
WINPR_API void ArrayList_Unlock(wArrayList* arrayList);
WINPR_API void* ArrayList_GetItem(wArrayList* arrayList, int index);
WINPR_API void ArrayList_SetItem(wArrayList* arrayList, int index, void* obj);
@ -165,19 +165,45 @@ WINPR_API void ArrayList_Free(wArrayList* arrayList);
struct _wDictionary
{
BOOL synchronized;
HANDLE mutex;
CRITICAL_SECTION lock;
};
typedef struct _wDictionary wDictionary;
/* System.Collections.Specialized.ListDictionary */
typedef struct _wListDictionaryItem wListDictionaryItem;
struct _wListDictionaryItem
{
void* key;
void* value;
wListDictionaryItem* next;
};
struct _wListDictionary
{
BOOL synchronized;
HANDLE mutex;
CRITICAL_SECTION lock;
wListDictionaryItem* head;
};
typedef struct _wListDictionary wListDictionary;
WINPR_API int ListDictionary_Count(wListDictionary* listDictionary);
WINPR_API void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value);
WINPR_API void ListDictionary_Remove(wListDictionary* listDictionary, void* key);
WINPR_API void ListDictionary_Clear(wListDictionary* listDictionary);
WINPR_API BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key);
WINPR_API void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key);
WINPR_API BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value);
WINPR_API wListDictionary* ListDictionary_New(BOOL synchronized);
WINPR_API void ListDictionary_Free(wListDictionary* listDictionary);
/* System.Collections.Generic.KeyValuePair<TKey,TValue> */
struct _wKeyValuePair
@ -201,7 +227,7 @@ typedef int (*REFERENCE_FREE)(void* context, void* ptr);
struct _wReferenceTable
{
UINT32 size;
HANDLE mutex;
CRITICAL_SECTION lock;
void* context;
BOOL synchronized;
wReference* array;
@ -220,7 +246,7 @@ WINPR_API void ReferenceTable_Free(wReferenceTable* referenceTable);
struct _wCountdownEvent
{
DWORD count;
HANDLE mutex;
CRITICAL_SECTION lock;
HANDLE event;
DWORD initialCount;
};
@ -245,7 +271,7 @@ struct _wBufferPool
int size;
int capacity;
void** array;
HANDLE mutex;
CRITICAL_SECTION lock;
int fixedSize;
DWORD alignment;
BOOL synchronized;
@ -266,7 +292,7 @@ struct _wObjectPool
int size;
int capacity;
void** array;
HANDLE mutex;
CRITICAL_SECTION lock;
wObject object;
BOOL synchronized;
};
@ -304,7 +330,7 @@ struct _wMessageQueue
int size;
int capacity;
wMessage* array;
HANDLE mutex;
CRITICAL_SECTION lock;
HANDLE event;
};
typedef struct _wMessageQueue wMessageQueue;
@ -401,7 +427,7 @@ typedef struct _wEventType wEventType;
struct _wPubSub
{
HANDLE mutex;
CRITICAL_SECTION lock;
BOOL synchronized;
int size;
@ -410,8 +436,8 @@ struct _wPubSub
};
typedef struct _wPubSub wPubSub;
WINPR_API BOOL PubSub_Lock(wPubSub* pubSub);
WINPR_API BOOL PubSub_Unlock(wPubSub* pubSub);
WINPR_API void PubSub_Lock(wPubSub* pubSub);
WINPR_API void PubSub_Unlock(wPubSub* pubSub);
WINPR_API wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count);
WINPR_API void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, int count);

View File

@ -24,6 +24,7 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/endian.h>
#include <winpr/synch.h>
#ifdef __cplusplus
extern "C" {
@ -236,7 +237,7 @@ struct _wStreamPool
int uCapacity;
wStream** uArray;
HANDLE mutex;
CRITICAL_SECTION lock;
BOOL synchronized;
size_t defaultSize;
};

View File

@ -31,6 +31,12 @@
#ifndef _WIN32
/**
* TODO: EnterCriticalSection allows recursive calls from the same thread.
* Implement this using pthreads (see PTHREAD_MUTEX_RECURSIVE_NP)
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms682608%28v=vs.85%29.aspx
*/
VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
if (lpCriticalSection)
@ -44,60 +50,65 @@ VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
lpCriticalSection->OwningThread = NULL;
lpCriticalSection->LockSemaphore = NULL;
lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t));
#if defined __APPLE__
semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, 1);
#else
sem_init(lpCriticalSection->LockSemaphore, 0, 1);
#endif
lpCriticalSection->LockSemaphore = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(lpCriticalSection->LockSemaphore, NULL);
}
}
BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags)
{
return TRUE;
if (Flags != 0) {
fprintf(stderr, "warning: InitializeCriticalSectionEx Flags unimplemented\n");
}
return InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount);
}
BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount)
{
InitializeCriticalSection(lpCriticalSection);
SetCriticalSectionSpinCount(lpCriticalSection, dwSpinCount);
return TRUE;
}
DWORD SetCriticalSectionSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount)
{
return 0;
DWORD dwPreviousSpinCount = lpCriticalSection->SpinCount;
lpCriticalSection->SpinCount = dwSpinCount;
return dwPreviousSpinCount;
}
VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
#if defined __APPLE__
semaphore_wait(*((winpr_sem_t*) lpCriticalSection->LockSemaphore));
#else
sem_wait((winpr_sem_t*) lpCriticalSection->LockSemaphore);
/**
* Linux NPTL thread synchronization primitives are implemented using
* the futex system calls ... no need for performing a trylock loop.
*/
#if !defined(__linux__)
ULONG spin = lpCriticalSection->SpinCount;
while (spin--)
{
if (pthread_mutex_trylock((pthread_mutex_t*)lpCriticalSection->LockSemaphore) == 0)
return;
pthread_yield();
}
#endif
pthread_mutex_lock((pthread_mutex_t*)lpCriticalSection->LockSemaphore);
}
BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
return TRUE;
return (pthread_mutex_trylock((pthread_mutex_t*)lpCriticalSection->LockSemaphore) == 0 ? TRUE : FALSE);
}
VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
#if defined __APPLE__
semaphore_signal(*((winpr_sem_t*) lpCriticalSection->LockSemaphore));
#else
sem_post((winpr_sem_t*) lpCriticalSection->LockSemaphore);
#endif
pthread_mutex_unlock((pthread_mutex_t*)lpCriticalSection->LockSemaphore);
}
VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
#if defined __APPLE__
semaphore_destroy(mach_task_self(), *((winpr_sem_t*) lpCriticalSection->LockSemaphore));
#else
sem_destroy((winpr_sem_t*) lpCriticalSection->LockSemaphore);
#endif
pthread_mutex_destroy((pthread_mutex_t*)lpCriticalSection->LockSemaphore);
free(lpCriticalSection->LockSemaphore);
}
#endif

View File

@ -210,6 +210,9 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
return WAIT_FAILED;
}
if (fd == -1)
return WAIT_FAILED;
FD_SET(fd, &fds);
if (fd > maxfd)

View File

@ -83,18 +83,18 @@ BOOL ArrayList_IsSynchronized(wArrayList* arrayList)
* Lock access to the ArrayList
*/
BOOL ArrayList_Lock(wArrayList* arrayList)
void ArrayList_Lock(wArrayList* arrayList)
{
return (WaitForSingleObject(arrayList->mutex, INFINITE) == WAIT_OBJECT_0) ? TRUE : FALSE;
EnterCriticalSection(&arrayList->lock);
}
/**
* Unlock access to the ArrayList
*/
BOOL ArrayList_Unlock(wArrayList* arrayList)
void ArrayList_Unlock(wArrayList* arrayList)
{
return ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
}
/**
@ -164,7 +164,7 @@ void ArrayList_Clear(wArrayList* arrayList)
int index;
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
for (index = 0; index < arrayList->size; index++)
{
@ -177,7 +177,7 @@ void ArrayList_Clear(wArrayList* arrayList)
arrayList->size = 0;
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
}
/**
@ -187,10 +187,10 @@ void ArrayList_Clear(wArrayList* arrayList)
BOOL ArrayList_Contains(wArrayList* arrayList, void* obj)
{
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
return FALSE;
}
@ -204,7 +204,7 @@ int ArrayList_Add(wArrayList* arrayList, void* obj)
int index;
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
if (arrayList->size + 1 > arrayList->capacity)
{
@ -216,7 +216,7 @@ int ArrayList_Add(wArrayList* arrayList, void* obj)
index = arrayList->size;
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
return index;
}
@ -228,7 +228,7 @@ int ArrayList_Add(wArrayList* arrayList, void* obj)
void ArrayList_Insert(wArrayList* arrayList, int index, void* obj)
{
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
if ((index >= 0) && (index < arrayList->size))
{
@ -237,7 +237,7 @@ void ArrayList_Insert(wArrayList* arrayList, int index, void* obj)
}
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
}
/**
@ -250,7 +250,7 @@ void ArrayList_Remove(wArrayList* arrayList, void* obj)
BOOL found = FALSE;
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
for (index = 0; index < arrayList->size; index++)
{
@ -265,7 +265,7 @@ void ArrayList_Remove(wArrayList* arrayList, void* obj)
ArrayList_Shift(arrayList, index, -1);
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
}
/**
@ -275,7 +275,7 @@ void ArrayList_Remove(wArrayList* arrayList, void* obj)
void ArrayList_RemoveAt(wArrayList* arrayList, int index)
{
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
if ((index >= 0) && (index < arrayList->size))
{
@ -283,7 +283,7 @@ void ArrayList_RemoveAt(wArrayList* arrayList, int index)
}
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
}
/**
@ -302,7 +302,7 @@ int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int coun
BOOL found = FALSE;
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
if (startIndex < 0)
startIndex = 0;
@ -323,7 +323,7 @@ int ArrayList_IndexOf(wArrayList* arrayList, void* obj, int startIndex, int coun
index = -1;
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
return index;
}
@ -344,7 +344,7 @@ int ArrayList_LastIndexOf(wArrayList* arrayList, void* obj, int startIndex, int
BOOL found = FALSE;
if (arrayList->synchronized)
WaitForSingleObject(arrayList->mutex, INFINITE);
EnterCriticalSection(&arrayList->lock);
if (startIndex < 0)
startIndex = 0;
@ -365,7 +365,7 @@ int ArrayList_LastIndexOf(wArrayList* arrayList, void* obj, int startIndex, int
index = -1;
if (arrayList->synchronized)
ReleaseMutex(arrayList->mutex);
LeaveCriticalSection(&arrayList->lock);
return index;
}
@ -390,7 +390,7 @@ wArrayList* ArrayList_New(BOOL synchronized)
arrayList->array = (void**) malloc(sizeof(void*) * arrayList->capacity);
arrayList->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&arrayList->lock);
ZeroMemory(&arrayList->object, sizeof(wObject));
}
@ -402,7 +402,7 @@ void ArrayList_Free(wArrayList* arrayList)
{
ArrayList_Clear(arrayList);
CloseHandle(arrayList->mutex);
DeleteCriticalSection(&arrayList->lock);
free(arrayList->array);
free(arrayList);
}

View File

@ -43,7 +43,7 @@ void* BufferPool_Take(wBufferPool* pool, int bufferSize)
void* buffer = NULL;
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
if (pool->fixedSize)
{
@ -64,7 +64,7 @@ void* BufferPool_Take(wBufferPool* pool, int bufferSize)
}
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
return buffer;
}
@ -76,7 +76,7 @@ void* BufferPool_Take(wBufferPool* pool, int bufferSize)
void BufferPool_Return(wBufferPool* pool, void* buffer)
{
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
if ((pool->size + 1) >= pool->capacity)
{
@ -87,7 +87,7 @@ void BufferPool_Return(wBufferPool* pool, void* buffer)
pool->array[(pool->size)++] = buffer;
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -97,7 +97,7 @@ void BufferPool_Return(wBufferPool* pool, void* buffer)
void BufferPool_Clear(wBufferPool* pool)
{
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
while (pool->size > 0)
{
@ -110,7 +110,7 @@ void BufferPool_Clear(wBufferPool* pool)
}
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -134,7 +134,7 @@ wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment)
pool->synchronized = synchronized;
if (pool->synchronized)
pool->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&pool->lock);
if (!pool->fixedSize)
{
@ -156,7 +156,7 @@ void BufferPool_Free(wBufferPool* pool)
BufferPool_Clear(pool);
if (pool->synchronized)
CloseHandle(pool->mutex);
DeleteCriticalSection(&pool->lock);
free(pool->array);

View File

@ -89,14 +89,14 @@ HANDLE CountdownEvent_WaitHandle(wCountdownEvent* countdown)
void CountdownEvent_AddCount(wCountdownEvent* countdown, DWORD signalCount)
{
WaitForSingleObject(countdown->mutex, INFINITE);
EnterCriticalSection(&countdown->lock);
countdown->count += signalCount;
if (countdown->count > 0)
ResetEvent(countdown->event);
ReleaseMutex(countdown->mutex);
LeaveCriticalSection(&countdown->lock);
}
/**
@ -111,7 +111,7 @@ BOOL CountdownEvent_Signal(wCountdownEvent* countdown, DWORD signalCount)
status = newStatus = oldStatus = FALSE;
WaitForSingleObject(countdown->mutex, INFINITE);
EnterCriticalSection(&countdown->lock);
if (WaitForSingleObject(countdown->event, 0) == WAIT_OBJECT_0)
oldStatus = TRUE;
@ -130,7 +130,7 @@ BOOL CountdownEvent_Signal(wCountdownEvent* countdown, DWORD signalCount)
status = TRUE;
}
ReleaseMutex(countdown->mutex);
LeaveCriticalSection(&countdown->lock);
return status;
}
@ -158,7 +158,7 @@ wCountdownEvent* CountdownEvent_New(DWORD initialCount)
{
countdown->count = initialCount;
countdown->initialCount = initialCount;
countdown->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&countdown->lock);
countdown->event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (countdown->count == 0)
@ -170,7 +170,7 @@ wCountdownEvent* CountdownEvent_New(DWORD initialCount)
void CountdownEvent_Free(wCountdownEvent* countdown)
{
CloseHandle(countdown->mutex);
DeleteCriticalSection(&countdown->lock);
CloseHandle(countdown->event);
free(countdown);

View File

@ -26,6 +26,8 @@
/**
* C equivalent of the C# ListDictionary Class:
* http://msdn.microsoft.com/en-us/library/system.collections.specialized.listdictionary.aspx
*
* Internal implementation uses a singly-linked list
*/
/**
@ -38,7 +40,21 @@
int ListDictionary_Count(wListDictionary* listDictionary)
{
return 0;
int count = 0;
wListDictionaryItem* item;
if (!listDictionary->head)
return 0;
item = listDictionary->head;
while (item)
{
count++;
item = item->next;
}
return count;
}
/**
@ -78,7 +94,28 @@ BOOL ListDictionary_IsSynchronized(wListDictionary* listDictionary)
void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value)
{
wListDictionaryItem* item;
wListDictionaryItem* lastItem;
item = (wListDictionaryItem*) malloc(sizeof(wListDictionaryItem));
item->key = key;
item->value = value;
item->next = NULL;
if (!listDictionary->head)
{
listDictionary->head = item;
return;
}
lastItem = listDictionary->head;
while (lastItem->next)
lastItem = lastItem->next;
lastItem->next = item;
}
/**
@ -87,7 +124,22 @@ void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value)
void ListDictionary_Clear(wListDictionary* listDictionary)
{
wListDictionaryItem* item;
wListDictionaryItem* nextItem;
if (!listDictionary->head)
return;
item = listDictionary->head;
while (item)
{
nextItem = item->next;
free(item);
item = nextItem;
}
listDictionary->head = NULL;
}
/**
@ -96,7 +148,22 @@ void ListDictionary_Clear(wListDictionary* listDictionary)
BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key)
{
return FALSE;
wListDictionaryItem* item;
if (!listDictionary->head)
return FALSE;
item = listDictionary->head;
while (item)
{
if (item->key == key)
break;
item = item->next;
}
return (item) ? TRUE : FALSE;
}
/**
@ -105,7 +172,89 @@ BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key)
void ListDictionary_Remove(wListDictionary* listDictionary, void* key)
{
wListDictionaryItem* item;
wListDictionaryItem* prevItem;
if (!listDictionary->head)
return;
item = listDictionary->head;
if (listDictionary->head->key == key)
{
listDictionary->head = listDictionary->head->next;
free(item);
return;
}
if (!item->next)
return;
prevItem = item;
item = item->next;
while (item)
{
if (item->key == key)
{
prevItem->next = item->next;
free(item);
break;
}
item = item->next;
}
}
/**
* Get an item value using key
*/
void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key)
{
wListDictionaryItem* item;
if (!listDictionary->head)
return NULL;
item = listDictionary->head;
while (item)
{
if (item->key == key)
break;
item = item->next;
}
return (item) ? item->value : NULL;
}
/**
* Set an item value using key
*/
BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value)
{
wListDictionaryItem* item;
if (!listDictionary->head)
return FALSE;
item = listDictionary->head;
while (item)
{
if (item->key == key)
break;
item = item->next;
}
if (item)
item->value = value;
return (item) ? TRUE : FALSE;
}
/**
@ -121,6 +270,8 @@ wListDictionary* ListDictionary_New(BOOL synchronized)
if (listDictionary)
{
listDictionary->synchronized = synchronized;
listDictionary->head = NULL;
}
return listDictionary;
@ -128,6 +279,10 @@ wListDictionary* ListDictionary_New(BOOL synchronized)
void ListDictionary_Free(wListDictionary* listDictionary)
{
free(listDictionary);
if (listDictionary)
{
ListDictionary_Clear(listDictionary);
free(listDictionary);
}
}

View File

@ -69,7 +69,7 @@ BOOL MessageQueue_Wait(wMessageQueue* queue)
void MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
{
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
if (queue->size == queue->capacity)
{
@ -100,7 +100,7 @@ void MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
if (queue->size > 0)
SetEvent(queue->event);
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
}
void MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* wParam, void* lParam)
@ -127,7 +127,7 @@ int MessageQueue_Get(wMessageQueue* queue, wMessage* message)
if (!MessageQueue_Wait(queue))
return status;
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
if (queue->size > 0)
{
@ -142,7 +142,7 @@ int MessageQueue_Get(wMessageQueue* queue, wMessage* message)
status = (message->id != WMQ_QUIT) ? 1 : 0;
}
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
return status;
}
@ -151,7 +151,7 @@ int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove)
{
int status = 0;
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
if (queue->size > 0)
{
@ -169,7 +169,7 @@ int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove)
}
}
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
return status;
}
@ -194,7 +194,7 @@ wMessageQueue* MessageQueue_New()
queue->array = (wMessage*) malloc(sizeof(wMessage) * queue->capacity);
ZeroMemory(queue->array, sizeof(wMessage) * queue->capacity);
queue->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&queue->lock);
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
}
@ -204,7 +204,7 @@ wMessageQueue* MessageQueue_New()
void MessageQueue_Free(wMessageQueue* queue)
{
CloseHandle(queue->event);
CloseHandle(queue->mutex);
DeleteCriticalSection(&queue->lock);
free(queue->array);
free(queue);

View File

@ -43,7 +43,7 @@ void* ObjectPool_Take(wObjectPool* pool)
void* obj = NULL;
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
if (pool->size > 0)
obj = pool->array[--(pool->size)];
@ -55,7 +55,7 @@ void* ObjectPool_Take(wObjectPool* pool)
}
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
return obj;
}
@ -67,7 +67,7 @@ void* ObjectPool_Take(wObjectPool* pool)
void ObjectPool_Return(wObjectPool* pool, void* obj)
{
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
if ((pool->size + 1) >= pool->capacity)
{
@ -78,7 +78,7 @@ void ObjectPool_Return(wObjectPool* pool, void* obj)
pool->array[(pool->size)++] = obj;
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -88,7 +88,7 @@ void ObjectPool_Return(wObjectPool* pool, void* obj)
void ObjectPool_Clear(wObjectPool* pool)
{
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
while (pool->size > 0)
{
@ -99,7 +99,7 @@ void ObjectPool_Clear(wObjectPool* pool)
}
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -119,7 +119,7 @@ wObjectPool* ObjectPool_New(BOOL synchronized)
pool->synchronized = synchronized;
if (pool->synchronized)
pool->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&pool->lock);
pool->size = 0;
pool->capacity = 32;
@ -136,7 +136,7 @@ void ObjectPool_Free(wObjectPool* pool)
ObjectPool_Clear(pool);
if (pool->synchronized)
CloseHandle(pool->mutex);
DeleteCriticalSection(&pool->lock);
free(pool->array);

View File

@ -46,14 +46,14 @@ wEventType* PubSub_GetEventTypes(wPubSub* pubSub, int* count)
* Methods
*/
BOOL PubSub_Lock(wPubSub* pubSub)
void PubSub_Lock(wPubSub* pubSub)
{
return (WaitForSingleObject(pubSub->mutex, INFINITE) == WAIT_OBJECT_0) ? TRUE : FALSE;
EnterCriticalSection(&pubSub->lock);
}
BOOL PubSub_Unlock(wPubSub* pubSub)
void PubSub_Unlock(wPubSub* pubSub)
{
return ReleaseMutex(pubSub->mutex);
LeaveCriticalSection(&pubSub->lock);
}
wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName)
@ -202,7 +202,7 @@ wPubSub* PubSub_New(BOOL synchronized)
pubSub->synchronized = synchronized;
if (pubSub->synchronized)
pubSub->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&pubSub->lock);
pubSub->count = 0;
pubSub->size = 64;
@ -219,7 +219,7 @@ void PubSub_Free(wPubSub* pubSub)
if (pubSub)
{
if (pubSub->synchronized)
CloseHandle(pubSub->mutex);
DeleteCriticalSection(&pubSub->lock);
if (pubSub->events)
free(pubSub->events);

View File

@ -47,18 +47,18 @@ int Queue_Count(wQueue* queue)
* Lock access to the ArrayList
*/
BOOL Queue_Lock(wQueue* queue)
void Queue_Lock(wQueue* queue)
{
return (WaitForSingleObject(queue->mutex, INFINITE) == WAIT_OBJECT_0) ? TRUE : FALSE;
EnterCriticalSection(&queue->lock);
}
/**
* Unlock access to the ArrayList
*/
BOOL Queue_Unlock(wQueue* queue)
void Queue_Unlock(wQueue* queue)
{
return ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
}
/**
@ -83,7 +83,7 @@ void Queue_Clear(wQueue* queue)
int index;
if (queue->synchronized)
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
for (index = queue->head; index != queue->tail; index = (index + 1) % queue->capacity)
{
@ -97,7 +97,7 @@ void Queue_Clear(wQueue* queue)
queue->head = queue->tail = 0;
if (queue->synchronized)
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
}
/**
@ -110,7 +110,7 @@ BOOL Queue_Contains(wQueue* queue, void* obj)
BOOL found = FALSE;
if (queue->synchronized)
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
for (index = 0; index < queue->tail; index++)
{
@ -122,7 +122,7 @@ BOOL Queue_Contains(wQueue* queue, void* obj)
}
if (queue->synchronized)
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
return found;
}
@ -134,7 +134,7 @@ BOOL Queue_Contains(wQueue* queue, void* obj)
void Queue_Enqueue(wQueue* queue, void* obj)
{
if (queue->synchronized)
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
if (queue->size == queue->capacity)
{
@ -162,7 +162,7 @@ void Queue_Enqueue(wQueue* queue, void* obj)
SetEvent(queue->event);
if (queue->synchronized)
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
}
/**
@ -174,7 +174,7 @@ void* Queue_Dequeue(wQueue* queue)
void* obj = NULL;
if (queue->synchronized)
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
if (queue->size > 0)
{
@ -188,7 +188,7 @@ void* Queue_Dequeue(wQueue* queue)
ResetEvent(queue->event);
if (queue->synchronized)
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
return obj;
}
@ -202,13 +202,13 @@ void* Queue_Peek(wQueue* queue)
void* obj = NULL;
if (queue->synchronized)
WaitForSingleObject(queue->mutex, INFINITE);
EnterCriticalSection(&queue->lock);
if (queue->size > 0)
obj = queue->array[queue->head];
if (queue->synchronized)
ReleaseMutex(queue->mutex);
LeaveCriticalSection(&queue->lock);
return obj;
}
@ -243,7 +243,7 @@ wQueue* Queue_New(BOOL synchronized, int capacity, int growthFactor)
queue->array = (void**) malloc(sizeof(void*) * queue->capacity);
ZeroMemory(queue->array, sizeof(void*) * queue->capacity);
queue->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&queue->lock);
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
ZeroMemory(&queue->object, sizeof(wObject));
@ -257,7 +257,7 @@ void Queue_Free(wQueue* queue)
Queue_Clear(queue);
CloseHandle(queue->event);
CloseHandle(queue->mutex);
DeleteCriticalSection(&queue->lock);
free(queue->array);
free(queue);
}

View File

@ -88,7 +88,7 @@ UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr)
wReference* reference = NULL;
if (referenceTable->synchronized)
WaitForSingleObject(referenceTable->mutex, INFINITE);
EnterCriticalSection(&referenceTable->lock);
reference = ReferenceTable_FindEntry(referenceTable, ptr);
@ -102,7 +102,7 @@ UINT32 ReferenceTable_Add(wReferenceTable* referenceTable, void* ptr)
count = ++(reference->Count);
if (referenceTable->synchronized)
ReleaseMutex(referenceTable->mutex);
LeaveCriticalSection(&referenceTable->lock);
return count;
}
@ -113,7 +113,7 @@ UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr)
wReference* reference = NULL;
if (referenceTable->synchronized)
WaitForSingleObject(referenceTable->mutex, INFINITE);
EnterCriticalSection(&referenceTable->lock);
reference = ReferenceTable_FindEntry(referenceTable, ptr);
@ -133,7 +133,7 @@ UINT32 ReferenceTable_Release(wReferenceTable* referenceTable, void* ptr)
}
if (referenceTable->synchronized)
ReleaseMutex(referenceTable->mutex);
LeaveCriticalSection(&referenceTable->lock);
return count;
}
@ -154,7 +154,7 @@ wReferenceTable* ReferenceTable_New(BOOL synchronized, void* context, REFERENCE_
ZeroMemory(referenceTable->array, sizeof(wReference) * referenceTable->size);
referenceTable->synchronized = synchronized;
referenceTable->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&referenceTable->lock);
}
return referenceTable;
@ -164,7 +164,7 @@ void ReferenceTable_Free(wReferenceTable* referenceTable)
{
if (referenceTable)
{
CloseHandle(referenceTable->mutex);
DeleteCriticalSection(&referenceTable->lock);
free(referenceTable->array);
free(referenceTable);
}

View File

@ -84,7 +84,7 @@ BOOL Stack_Contains(wStack* stack, void* obj)
void Stack_Push(wStack* stack, void* obj)
{
if (stack->synchronized)
WaitForSingleObject(stack->mutex, INFINITE);
EnterCriticalSection(&stack->lock);
if ((stack->size + 1) >= stack->capacity)
{
@ -95,7 +95,7 @@ void Stack_Push(wStack* stack, void* obj)
stack->array[(stack->size)++] = obj;
if (stack->synchronized)
ReleaseMutex(stack->mutex);
LeaveCriticalSection(&stack->lock);
}
/**
@ -107,13 +107,13 @@ void* Stack_Pop(wStack* stack)
void* obj = NULL;
if (stack->synchronized)
WaitForSingleObject(stack->mutex, INFINITE);
EnterCriticalSection(&stack->lock);
if (stack->size > 0)
obj = stack->array[--(stack->size)];
if (stack->synchronized)
ReleaseMutex(stack->mutex);
LeaveCriticalSection(&stack->lock);
return obj;
}
@ -127,13 +127,13 @@ void* Stack_Peek(wStack* stack)
void* obj = NULL;
if (stack->synchronized)
WaitForSingleObject(stack->mutex, INFINITE);
EnterCriticalSection(&stack->lock);
if (stack->size > 0)
obj = stack->array[stack->size];
if (stack->synchronized)
ReleaseMutex(stack->mutex);
LeaveCriticalSection(&stack->lock);
return obj;
}
@ -153,7 +153,7 @@ wStack* Stack_New(BOOL synchronized)
stack->synchronized = synchronized;
if (stack->synchronized)
stack->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&stack->lock);
stack->size = 0;
stack->capacity = 32;
@ -168,7 +168,7 @@ void Stack_Free(wStack* stack)
if (stack)
{
if (stack->synchronized)
CloseHandle(stack->mutex);
DeleteCriticalSection(&stack->lock);
free(stack->array);

View File

@ -118,7 +118,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
BOOL found = FALSE;
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
if (size == 0)
size = pool->defaultSize;
@ -153,7 +153,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
StreamPool_AddUsed(pool, s);
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
return s;
}
@ -165,7 +165,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
void StreamPool_Return(wStreamPool* pool, wStream* s)
{
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
if ((pool->aSize + 1) >= pool->aCapacity)
{
@ -177,7 +177,7 @@ void StreamPool_Return(wStreamPool* pool, wStream* s)
StreamPool_RemoveUsed(pool, s);
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -186,7 +186,7 @@ void StreamPool_Return(wStreamPool* pool, wStream* s)
void StreamPool_Lock(wStreamPool* pool)
{
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
}
/**
@ -195,7 +195,7 @@ void StreamPool_Lock(wStreamPool* pool)
void StreamPool_Unlock(wStreamPool* pool)
{
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -241,7 +241,7 @@ wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr)
wStream* s = NULL;
BOOL found = FALSE;
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
for (index = 0; index < pool->uSize; index++)
{
@ -254,7 +254,7 @@ wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr)
}
}
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
return (found) ? s : NULL;
}
@ -294,7 +294,7 @@ void StreamPool_Release(wStreamPool* pool, BYTE* ptr)
void StreamPool_Clear(wStreamPool* pool)
{
if (pool->synchronized)
WaitForSingleObject(pool->mutex, INFINITE);
EnterCriticalSection(&pool->lock);
while (pool->aSize > 0)
{
@ -303,7 +303,7 @@ void StreamPool_Clear(wStreamPool* pool)
}
if (pool->synchronized)
ReleaseMutex(pool->mutex);
LeaveCriticalSection(&pool->lock);
}
/**
@ -323,8 +323,7 @@ wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize)
pool->synchronized = synchronized;
pool->defaultSize = defaultSize;
if (pool->synchronized)
pool->mutex = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&pool->lock);
pool->aSize = 0;
pool->aCapacity = 32;
@ -344,8 +343,7 @@ void StreamPool_Free(wStreamPool* pool)
{
StreamPool_Clear(pool);
if (pool->synchronized)
CloseHandle(pool->mutex);
DeleteCriticalSection(&pool->lock);
free(pool->aArray);
free(pool->uArray);

View File

@ -9,6 +9,7 @@ set(${MODULE_PREFIX}_TESTS
TestPrint.c
TestPubSub.c
TestArrayList.c
TestListDictionary.c
TestCmdLine.c
TestStreamPool.c
TestMessageQueue.c

View File

@ -0,0 +1,130 @@
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/collections.h>
static char* key1 = "key1";
static char* key2 = "key2";
static char* key3 = "key3";
static char* val1 = "val1";
static char* val2 = "val2";
static char* val3 = "val3";
int TestListDictionary(int argc, char* argv[])
{
int count;
char* value;
wListDictionary* list;
list = ListDictionary_New(FALSE);
ListDictionary_Add(list, key1, val1);
ListDictionary_Add(list, key2, val2);
ListDictionary_Add(list, key3, val3);
count = ListDictionary_Count(list);
if (count != 3)
{
printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count);
return -1;
}
ListDictionary_Remove(list, key2);
count = ListDictionary_Count(list);
if (count != 2)
{
printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 2, count);
return -1;
}
ListDictionary_Remove(list, key3);
count = ListDictionary_Count(list);
if (count != 1)
{
printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 1, count);
return -1;
}
ListDictionary_Remove(list, key1);
count = ListDictionary_Count(list);
if (count != 0)
{
printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count);
return -1;
}
ListDictionary_Add(list, key1, val1);
ListDictionary_Add(list, key2, val2);
ListDictionary_Add(list, key3, val3);
count = ListDictionary_Count(list);
if (count != 3)
{
printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count);
return -1;
}
value = (char*) ListDictionary_GetItemValue(list, key1);
if (strcmp(value, val1) != 0)
{
printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val1, value);
return -1;
}
value = (char*) ListDictionary_GetItemValue(list, key2);
if (strcmp(value, val2) != 0)
{
printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val2, value);
return -1;
}
value = (char*) ListDictionary_GetItemValue(list, key3);
if (strcmp(value, val3) != 0)
{
printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val3, value);
return -1;
}
ListDictionary_SetItemValue(list, key2, "apple");
value = (char*) ListDictionary_GetItemValue(list, key2);
if (strcmp(value, "apple") != 0)
{
printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", "apple", value);
return -1;
}
if (!ListDictionary_Contains(list, key2))
{
printf("ListDictionary_Contains: Expected : %d, Actual: %d\n", TRUE, FALSE);
return -1;
}
ListDictionary_Clear(list);
count = ListDictionary_Count(list);
if (count != 0)
{
printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count);
return -1;
}
ListDictionary_Free(list);
return 0;
}