From 06019703b0cb76e612006d14d31a7d366a93849c Mon Sep 17 00:00:00 2001 From: Gerasim Troeglazov <3dEyes@gmail.com> Date: Sat, 24 Dec 2022 21:11:16 +1000 Subject: Add Haiku support diff --git a/CMakeLists.txt b/CMakeLists.txt index 67f3437..a48a4b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -599,6 +599,16 @@ if(OPENBSD) set(WITH_WAYLAND "OFF") endif() +# Haiku +if(HAIKU) + set(WITH_MANPAGES "ON") + set(WITH_ALSA "OFF") + set(WITH_PULSE "OFF") + set(WITH_OSS "OFF") + set(WITH_MEDIA_KIT "ON") + set(WITH_WAYLAND "OFF") +endif() + # Android if(ANDROID) set(WITH_LIBRARY_VERSIONING "OFF") diff --git a/channels/rdpsnd/client/CMakeLists.txt b/channels/rdpsnd/client/CMakeLists.txt index 70f4aa2..d3fb3cd 100644 --- a/channels/rdpsnd/client/CMakeLists.txt +++ b/channels/rdpsnd/client/CMakeLists.txt @@ -37,6 +37,10 @@ if(WITH_ALSA) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "") endif() +if(WITH_MEDIA_KIT) + add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "haiku" "") +endif() + if(WITH_IOSAUDIO) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ios" "") endif() diff --git a/channels/rdpsnd/client/haiku/CMakeLists.txt b/channels/rdpsnd/client/haiku/CMakeLists.txt new file mode 100644 index 0000000..b8eec21 --- /dev/null +++ b/channels/rdpsnd/client/haiku/CMakeLists.txt @@ -0,0 +1,43 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Laxmikant Rashinkar +# Copyright 2012 Marc-Andre Moreau +# Copyright 2013 Corey Clayton +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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_subsystem("rdpsnd" "haiku" "") + +FIND_LIBRARY(LIB_MEDIA media) +FIND_LIBRARY(LIB_BE be) + +set(${MODULE_PREFIX}_SRCS + rdpsnd_haiku.cpp + ring_buffer.cpp ) + +include_directories(..) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + + + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} + ${LIB_MEDIA} + ${LIB_BE} ) + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/haiku") diff --git a/channels/rdpsnd/client/haiku/rdpsnd_haiku.cpp b/channels/rdpsnd/client/haiku/rdpsnd_haiku.cpp new file mode 100644 index 0000000..3925eb3 --- /dev/null +++ b/channels/rdpsnd/client/haiku/rdpsnd_haiku.cpp @@ -0,0 +1,218 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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 + +#include +#include + +#include + +#include "ring_buffer.h" +#include "rdpsnd_main.h" + +#define INPUT_BUFFER_SIZE 32768 +#define CIRCULAR_BUFFER_SIZE (INPUT_BUFFER_SIZE * 4) + +typedef struct rdpsnd_haiku_plugin +{ + rdpsndDevicePlugin device; + BSoundPlayer *player; + RingBuffer *buffer; + BOOL is_opened; + BOOL is_playing; +} rdpsndHaikuPlugin; + +#define THIS(__ptr) ((rdpsndHaikuPlugin*)__ptr) + +static void rdpsnd_haiku_soundplayer_callback(void *cookie, void *buffer, size_t len, const media_raw_audio_format &format) +{ + rdpsndHaikuPlugin* p = THIS(cookie); + unsigned char* ptr = (unsigned char*)buffer; + + int readed = p->buffer->Read(ptr, len); + + if (readed < len) + memset(ptr + readed, 0, len - readed); +} + +static BOOL rdpsnd_haiku_format_supported(rdpsndDevicePlugin* __unused device, const AUDIO_FORMAT* format) +{ + if (format->wFormatTag == WAVE_FORMAT_PCM) + { + return 1; + } + + return 0; +} + +static BOOL rdpsnd_haiku_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __unused value) +{ + return TRUE; +} + +static void rdpsnd_haiku_start(rdpsndDevicePlugin* device) +{ + rdpsndHaikuPlugin* p = THIS(device); + + if (!p->is_playing) + { + int32_t available_bytes = p->buffer->GetReadAvailable(); + + if (available_bytes > 0) + { + p->is_playing = 1; + p->player->Start(); + p->player->SetHasData(true); + } + } +} + +static void rdpsnd_haiku_stop(rdpsndDevicePlugin* device) +{ + rdpsndHaikuPlugin* p = THIS(device); + + if (p->is_playing) + { + p->player->SetHasData(false); + p->player->Stop(); + p->is_playing = 0; + p->buffer->Empty(); + } +} + +static UINT rdpsnd_haiku_play(rdpsndDevicePlugin* device, const BYTE* data, size_t size) +{ + rdpsndHaikuPlugin* p = THIS(device); + unsigned char *src_ptr = (unsigned char *)data; + + int len = size; + while ( len > 0 && len % 4 ) + len--; + + if ( len <= 0 ) + return 0; + + for (;;) + { + int writed = p->buffer->Write(src_ptr, len); + + if (writed == len) + break; + + len -= writed; + src_ptr += writed; + + snooze(100); + } + + rdpsnd_haiku_start(device); + + return 10; +} + +static int rdpsnd_haiku_open(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, unsigned int __unused latency) +{ + rdpsndHaikuPlugin* p = THIS(device); + + if (p->is_opened) + return TRUE; + + media_raw_audio_format form = { + format->nSamplesPerSec, + format->nChannels, + media_raw_audio_format::B_AUDIO_SHORT, + B_MEDIA_LITTLE_ENDIAN, + INPUT_BUFFER_SIZE + }; + + p->buffer = new RingBuffer(CIRCULAR_BUFFER_SIZE); + if (p->buffer->InitCheck() != B_OK) + { + delete p->buffer; + p->buffer = NULL; + return FALSE; + } + + p->player = new BSoundPlayer(&form, "FreeRDP", rdpsnd_haiku_soundplayer_callback, nullptr, (void*)device); + + if (p->player->InitCheck() != B_OK) + { + delete p->player; + p->player = NULL; + delete p->buffer; + p->buffer = NULL; + return FALSE; + } + + p->is_opened = 1; + return TRUE; +} + +static void rdpsnd_haiku_close(rdpsndDevicePlugin* device) +{ + rdpsndHaikuPlugin* p = THIS(device); + rdpsnd_haiku_stop(device); + + if (p->is_opened) + { + delete p->player; + p->player = NULL; + p->is_opened = 0; + delete p->buffer; + } +} + +static void rdpsnd_haiku_free(rdpsndDevicePlugin* device) +{ + rdpsndHaikuPlugin* p = THIS(device); + rdpsnd_haiku_close(device); + free(p); +} + +extern "C" { + +#ifdef BUILTIN_CHANNELS +#define freerdp_rdpsnd_client_subsystem_entry haiku_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry +#endif + +UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +{ + rdpsndHaikuPlugin* p = (rdpsndHaikuPlugin*)calloc(1, sizeof(rdpsndHaikuPlugin)); + + if (!p) + return CHANNEL_RC_NO_MEMORY; + + p->device.Open = rdpsnd_haiku_open; + p->device.FormatSupported = rdpsnd_haiku_format_supported; + p->device.SetVolume = rdpsnd_haiku_set_volume; + p->device.Play = rdpsnd_haiku_play; + p->device.Start = rdpsnd_haiku_start; + p->device.Close = rdpsnd_haiku_close; + p->device.Free = rdpsnd_haiku_free; + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); + + return CHANNEL_RC_OK; +} +} diff --git a/channels/rdpsnd/client/haiku/ring_buffer.cpp b/channels/rdpsnd/client/haiku/ring_buffer.cpp new file mode 100644 index 0000000..aed0929 --- /dev/null +++ b/channels/rdpsnd/client/haiku/ring_buffer.cpp @@ -0,0 +1,132 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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. + */ + +#include +#include +#include + +#include "ring_buffer.h" + +RingBuffer::RingBuffer(int size) +{ + initialized = false; + reader = 0; + writer = 0; + writeBytesAvailable = size; + + Buffer = new unsigned char[size]; + + if (Buffer) + { + memset( Buffer, 0, size ); + BufferSize = size; + } + else + { + BufferSize = 0; + } + + if((locker=create_sem(1,"locker")) >= B_OK) + initialized = true; + else + delete[] Buffer; +} + +RingBuffer::~RingBuffer() +{ + if (initialized) + { + delete[] Buffer; + delete_sem(locker); + } +} + +bool +RingBuffer::Empty(void) +{ + memset(Buffer, 0, BufferSize); + reader = 0; + writer = 0; + writeBytesAvailable = BufferSize; + return true; +} + +int +RingBuffer::Read(unsigned char *data, int size) +{ + acquire_sem(locker); + + if (data == 0 || size <= 0 || writeBytesAvailable == BufferSize) + { + release_sem(locker); + return 0; + } + + int readBytesAvailable = BufferSize - writeBytesAvailable; + + if (size > readBytesAvailable) + size = readBytesAvailable; + + if (size > BufferSize - reader) + { + int len = BufferSize - reader; + memcpy(data, Buffer + reader, len); + memcpy(data + len, Buffer, size-len); + } + else + { + memcpy(data, Buffer + reader, size); + } + + reader = (reader + size) % BufferSize; + writeBytesAvailable += size; + + release_sem(locker); + return size; +} + +int +RingBuffer::Write(unsigned char *data, int size) +{ + acquire_sem(locker); + + if( data == 0 || size <= 0 || writeBytesAvailable == 0 ) { + release_sem(locker); + return 0; + } + + if( size > writeBytesAvailable ) + size = writeBytesAvailable; + + if(size > BufferSize - writer) + { + int len = BufferSize - writer; + memcpy(Buffer + writer, data, len); + memcpy(Buffer, data+len, size-len); + } + else + { + memcpy(Buffer + writer, data, size); + } + + writer = (writer + size) % BufferSize; + writeBytesAvailable -= size; + + release_sem(locker); + return size; +} diff --git a/channels/rdpsnd/client/haiku/ring_buffer.h b/channels/rdpsnd/client/haiku/ring_buffer.h new file mode 100644 index 0000000..f286916 --- /dev/null +++ b/channels/rdpsnd/client/haiku/ring_buffer.h @@ -0,0 +1,50 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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_RDPSND_MEDIAKIT_RINGBUFFER_H +#define FREERDP_RDPSND_MEDIAKIT_RINGBUFFER_H + +#include + +class RingBuffer { + +public: + RingBuffer(int size); + ~RingBuffer(); + int Read(unsigned char* dataPtr, int numBytes); + int Write(unsigned char *dataPtr, int numBytes); + + bool Empty(void); + int GetSize() { return BufferSize; } + int GetWriteAvailable() { return writeBytesAvailable;} + int GetReadAvailable() { return BufferSize - writeBytesAvailable;} + + status_t InitCheck() { return initialized ? B_OK : B_ERROR; } +private: + unsigned char *Buffer; + int BufferSize; + int reader; + int writer; + int writeBytesAvailable; + + sem_id locker; + + bool initialized; +}; + +#endif // FREERDP_RDPSND_MEDIAKIT_RINGBUFFER_H diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 3de4cbc..1024841 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -1015,6 +1015,9 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd) #if defined(WITH_ALSA) { "alsa", "default" }, #endif +#if defined(WITH_MEDIA_KIT) + { "haiku", "default" }, +#endif #if defined(WITH_OSS) { "oss", "" }, #endif diff --git a/client/.gitignore b/client/.gitignore index 7c1ea95..ee0bf56 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -4,6 +4,7 @@ !/iOS !/Mac !/Sample +!/Haiku !/Windows !/X11 !/Wayland diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index af7606b..ec26961 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -54,6 +54,11 @@ if(FREERDP_VENDOR AND WITH_CLIENT) message(STATUS "Adding Android client") add_subdirectory(Android) endif() + + if(HAIKU) + message(STATUS "Adding Haiku client") + add_subdirectory(Haiku) + endif() endif() # Pick up other clients diff --git a/client/Haiku/CMakeLists.txt b/client/Haiku/CMakeLists.txt new file mode 100644 index 0000000..7fd05cc --- /dev/null +++ b/client/Haiku/CMakeLists.txt @@ -0,0 +1,36 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP Haiku UI cmake build script +# +# Copyright 2018 Gerasim Troeglazov <3dEyes@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. + +set(MODULE_NAME "FreeRDP") +set(MODULE_PREFIX "FREERDP_CLIENT_HAIKU") +set(CMAKE_POSITION_INDEPENDENT_CODE OFF) + +set(${MODULE_PREFIX}_SRCS + haiku_freerdp.cpp haiku_window.cpp haiku_view.cpp haiku_clipboard.cpp) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS}) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} be network media translation) +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +ADD_CUSTOM_COMMAND(TARGET ${MODULE_NAME} COMMAND rc -o haiku_resources.rsrc ${CMAKE_CURRENT_SOURCE_DIR}/haiku_resources.rdef COMMENT "Compiling resources") +ADD_CUSTOM_COMMAND(TARGET ${MODULE_NAME} COMMAND xres -o ${MODULE_NAME} haiku_resources.rsrc COMMENT "Adding resources to executable") +ADD_CUSTOM_COMMAND(TARGET ${MODULE_NAME} COMMAND mimeset --all ${MODULE_NAME} COMMENT "Adjusting MIME types") + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Haiku") diff --git a/client/Haiku/ModuleOptions.cmake b/client/Haiku/ModuleOptions.cmake new file mode 100644 index 0000000..130bfa1 --- /dev/null +++ b/client/Haiku/ModuleOptions.cmake @@ -0,0 +1,4 @@ + +set(FREERDP_CLIENT_NAME "hfreerdp") +set(FREERDP_CLIENT_PLATFORM "Haiku") +set(FREERDP_CLIENT_VENDOR "FreeRDP") diff --git a/client/Haiku/haiku_clipboard.cpp b/client/Haiku/haiku_clipboard.cpp new file mode 100644 index 0000000..8f6c1db --- /dev/null +++ b/client/Haiku/haiku_clipboard.cpp @@ -0,0 +1,433 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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 "haiku_freerdp.h" +#include "haiku_clipboard.h" + +#include + +UINT haiku_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr) +{ + UINT rc = ERROR_INTERNAL_ERROR; + UINT32 index; + UINT32 formatId; + UINT32 numFormats; + UINT32* pFormatIds; + const char* formatName; + CLIPRDR_FORMAT* formats; + CLIPRDR_FORMAT_LIST formatList; + + if (!cliprdr) + return ERROR_INVALID_PARAMETER; + + HaikuContext* hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc || !hfc->cliprdr) + return ERROR_INVALID_PARAMETER; + + ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST)); + pFormatIds = NULL; + numFormats = ClipboardGetFormatIds(hfc->clipboard, &pFormatIds); + formats = (CLIPRDR_FORMAT*)calloc(numFormats, sizeof(CLIPRDR_FORMAT)); + + if (!formats) + goto fail; + + for (index = 0; index < numFormats; index++) + { + formatId = pFormatIds[index]; + formatName = ClipboardGetFormatName(hfc->clipboard, formatId); + formats[index].formatId = formatId; + formats[index].formatName = NULL; + + if ((formatId > CF_MAX) && formatName) + { + formats[index].formatName = _strdup(formatName); + + if (!formats[index].formatName) + goto fail; + } + } + + formatList.msgFlags = CB_RESPONSE_OK; + formatList.numFormats = numFormats; + formatList.formats = formats; + formatList.msgType = CB_FORMAT_LIST; + + if (!hfc->cliprdr->ClientFormatList) + goto fail; + + rc = hfc->cliprdr->ClientFormatList(hfc->cliprdr, &formatList); + +fail: + free(pFormatIds); + free(formats); + + return rc; +} + +static UINT haiku_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, + UINT32 formatId) +{ + UINT rc = ERROR_INVALID_PARAMETER; + CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; + HaikuContext* hfc; + + if (!cliprdr) + goto fail; + + hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc || !hfc->clipboardRequestEvent || !cliprdr->ClientFormatDataRequest) + goto fail; + + ZeroMemory(&formatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST)); + formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; + formatDataRequest.msgFlags = 0; + formatDataRequest.requestedFormatId = formatId; + hfc->requestedFormatId = formatId; + ResetEvent(hfc->clipboardRequestEvent); + rc = cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest); + +fail: + return rc; +} + +static UINT haiku_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr) +{ + CLIPRDR_CAPABILITIES capabilities; + CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; + + if (!cliprdr || !cliprdr->ClientCapabilities) + return ERROR_INVALID_PARAMETER; + + capabilities.cCapabilitiesSets = 1; + capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)&(generalCapabilitySet); + generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; + generalCapabilitySet.capabilitySetLength = 12; + generalCapabilitySet.version = CB_CAPS_VERSION_2; + generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES; + + return cliprdr->ClientCapabilities(cliprdr, &capabilities); +} + +static UINT haiku_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, + const CLIPRDR_MONITOR_READY* monitorReady) +{ + UINT rc; + + HaikuContext* hfc; + + if (!cliprdr || !monitorReady) + return ERROR_INVALID_PARAMETER; + + hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc) + return ERROR_INVALID_PARAMETER; + + if ((rc = haiku_cliprdr_send_client_capabilities(cliprdr)) != CHANNEL_RC_OK) + return rc; + + if ((rc = haiku_cliprdr_send_client_format_list(cliprdr)) != CHANNEL_RC_OK) + return rc; + + hfc->clipboardSync = TRUE; + + return CHANNEL_RC_OK; +} + +static UINT haiku_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, + const CLIPRDR_CAPABILITIES* capabilities) +{ + UINT32 index; + CLIPRDR_CAPABILITY_SET* capabilitySet; + + HaikuContext* hfc; + + if (!cliprdr || !capabilities) + return ERROR_INVALID_PARAMETER; + + hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc) + return ERROR_INVALID_PARAMETER; + + for (index = 0; index < capabilities->cCapabilitiesSets; index++) + { + capabilitySet = &(capabilities->capabilitySets[index]); + + if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) && + (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN)) + { + CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet = + (CLIPRDR_GENERAL_CAPABILITY_SET*)capabilitySet; + hfc->clipboardCapabilities = generalCapabilitySet->generalFlags; + break; + } + } + + return CHANNEL_RC_OK; +} + +static UINT haiku_cliprdr_server_format_list(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_LIST* formatList) +{ + UINT rc; + UINT32 index; + CLIPRDR_FORMAT* format; + HaikuContext* hfc; + + if (!cliprdr || !formatList) + return ERROR_INVALID_PARAMETER; + + hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc) + return ERROR_INVALID_PARAMETER; + + if (hfc->serverFormats) + { + for (index = 0; index < hfc->numServerFormats; index++) + free(hfc->serverFormats[index].formatName); + + free(hfc->serverFormats); + hfc->serverFormats = NULL; + hfc->numServerFormats = 0; + } + + if (formatList->numFormats < 1) + return CHANNEL_RC_OK; + + hfc->numServerFormats = formatList->numFormats; + hfc->serverFormats = (CLIPRDR_FORMAT*)calloc(hfc->numServerFormats, sizeof(CLIPRDR_FORMAT)); + + if (!hfc->serverFormats) + return CHANNEL_RC_NO_MEMORY; + + for (index = 0; index < hfc->numServerFormats; index++) + { + hfc->serverFormats[index].formatId = formatList->formats[index].formatId; + hfc->serverFormats[index].formatName = NULL; + + if (formatList->formats[index].formatName) + { + hfc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName); + + if (!hfc->serverFormats[index].formatName) + return CHANNEL_RC_NO_MEMORY; + } + } + + for (index = 0; index < hfc->numServerFormats; index++) + { + format = &(hfc->serverFormats[index]); + + if (format->formatId == CF_UNICODETEXT) + { + if ((rc = haiku_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT)) != CHANNEL_RC_OK) + return rc; + break; + } + else if (format->formatId == CF_TEXT) + { + if ((rc = haiku_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT)) != CHANNEL_RC_OK) + return rc; + break; + } + } + + return CHANNEL_RC_OK; +} + +static UINT +haiku_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) +{ + return CHANNEL_RC_OK; +} + +static UINT +haiku_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, + const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) +{ + return CHANNEL_RC_OK; +} + +static UINT haiku_cliprdr_server_unlock_clipboard_data( + CliprdrClientContext* cliprdr, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +{ + return CHANNEL_RC_OK; +} + +static UINT +haiku_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) +{ + UINT rc; + BYTE* data; + UINT32 size; + UINT32 formatId; + CLIPRDR_FORMAT_DATA_RESPONSE response; + HaikuContext* hfc; + + if (!cliprdr || !formatDataRequest || !cliprdr->ClientFormatDataResponse) + return ERROR_INVALID_PARAMETER; + + hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc) + return ERROR_INVALID_PARAMETER; + + ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE)); + formatId = formatDataRequest->requestedFormatId; + data = (BYTE*)ClipboardGetData(hfc->clipboard, formatId, &size); + response.msgFlags = CB_RESPONSE_OK; + response.dataLen = size; + response.requestedFormatData = data; + + if (!data) + { + response.msgFlags = CB_RESPONSE_FAIL; + response.dataLen = 0; + response.requestedFormatData = NULL; + } + + rc = cliprdr->ClientFormatDataResponse(cliprdr, &response); + free(data); + return rc; +} + +static UINT +haiku_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) +{ + char* data; + UINT32 size; + UINT32 index; + UINT32 formatId; + CLIPRDR_FORMAT* format = NULL; + HaikuContext* hfc; + freerdp* instance; + + if (!cliprdr || !formatDataResponse) + return ERROR_INVALID_PARAMETER; + + hfc = (HaikuContext*)cliprdr->custom; + + if (!hfc) + return ERROR_INVALID_PARAMETER; + + instance = ((rdpContext*)hfc)->instance; + + if (!instance) + return ERROR_INVALID_PARAMETER; + + for (index = 0; index < hfc->numServerFormats; index++) + { + if (hfc->requestedFormatId == hfc->serverFormats[index].formatId) + format = &(hfc->serverFormats[index]); + } + + if (!format) + { + SetEvent(hfc->clipboardRequestEvent); + return ERROR_INTERNAL_ERROR; + } + + if (format->formatName) + formatId = ClipboardRegisterFormat(hfc->clipboard, format->formatName); + else + formatId = format->formatId; + + size = formatDataResponse->dataLen; + + if (!ClipboardSetData(hfc->clipboard, formatId, formatDataResponse->requestedFormatData, size)) + return ERROR_INTERNAL_ERROR; + + SetEvent(hfc->clipboardRequestEvent); + + if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT)) + { + formatId = ClipboardRegisterFormat(hfc->clipboard, "UTF8_STRING"); + data = (char*)ClipboardGetData(hfc->clipboard, formatId, &size); + + BMessage *clip = NULL; + if(be_clipboard->Lock() && size != 0) + { + be_clipboard->Clear(); + if((clip = be_clipboard->Data())) + { + clip->AddData("text/plain", B_MIME_TYPE, data, size + 1); + be_clipboard->Commit(); + } + be_clipboard->Unlock(); + } + } + + return CHANNEL_RC_OK; +} + +static UINT haiku_cliprdr_server_file_contents_request( + CliprdrClientContext* cliprdr, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) +{ + return CHANNEL_RC_OK; +} + +static UINT haiku_cliprdr_server_file_contents_response( + CliprdrClientContext* cliprdr, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) +{ + return CHANNEL_RC_OK; +} + +BOOL haiku_cliprdr_init(HaikuContext* hfc, CliprdrClientContext* cliprdr) +{ + cliprdr->custom = (void *)hfc; + hfc->cliprdr = cliprdr; + + hfc->clipboard = ClipboardCreate(); + hfc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + cliprdr->MonitorReady = haiku_cliprdr_monitor_ready; + cliprdr->ServerCapabilities = haiku_cliprdr_server_capabilities; + cliprdr->ServerFormatList = haiku_cliprdr_server_format_list; + cliprdr->ServerFormatListResponse = haiku_cliprdr_server_format_list_response; + cliprdr->ServerLockClipboardData = haiku_cliprdr_server_lock_clipboard_data; + cliprdr->ServerUnlockClipboardData = haiku_cliprdr_server_unlock_clipboard_data; + cliprdr->ServerFormatDataRequest = haiku_cliprdr_server_format_data_request; + cliprdr->ServerFormatDataResponse = haiku_cliprdr_server_format_data_response; + cliprdr->ServerFileContentsRequest = haiku_cliprdr_server_file_contents_request; + cliprdr->ServerFileContentsResponse = haiku_cliprdr_server_file_contents_response; + + return TRUE; +} + +BOOL haiku_cliprdr_uninit(HaikuContext* hfc, CliprdrClientContext* cliprdr) +{ + cliprdr->custom = NULL; + hfc->cliprdr = NULL; + + ClipboardDestroy(hfc->clipboard); + CloseHandle(hfc->clipboardRequestEvent); + + return TRUE; +} diff --git a/client/Haiku/haiku_clipboard.h b/client/Haiku/haiku_clipboard.h new file mode 100644 index 0000000..49cfa3b --- /dev/null +++ b/client/Haiku/haiku_clipboard.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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_CLIENT_HAIKU_CLIPRDR_H +#define FREERDP_CLIENT_HAIKU_CLIPRDR_H + +#include "haiku_freerdp.h" + +FREERDP_LOCAL UINT haiku_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr); +FREERDP_LOCAL BOOL haiku_cliprdr_init(haiku_context* afc, CliprdrClientContext* cliprdr); +FREERDP_LOCAL BOOL haiku_cliprdr_uninit(haiku_context* afc, CliprdrClientContext* cliprdr); + +#endif // FREERDP_CLIENT_HAIKU_CLIPRDR_H diff --git a/client/Haiku/haiku_freerdp.cpp b/client/Haiku/haiku_freerdp.cpp new file mode 100644 index 0000000..b1f1fd0 --- /dev/null +++ b/client/Haiku/haiku_freerdp.cpp @@ -0,0 +1,392 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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 +#include +#include +#include + +#include "haiku_freerdp.h" +#include "haiku_window.h" +#include "haiku_view.h" +#include "haiku_clipboard.h" + +#include +#include +#include +#include +#include +#include +#include + +#define TAG CLIENT_TAG("haiku") + +static void haiku_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e) +{ + rdpSettings* settings; + HaikuContext* hfc; + + if (!context || !e) + { + WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", __FUNCTION__, context, (void*)e); + return; + } + + hfc = (HaikuContext*)context; + + if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) + haiku_cliprdr_init(hfc, (CliprdrClientContext*)e->pInterface); +} + +static void haiku_OnChannelDisconnectedEventHandler(void* context, + ChannelDisconnectedEventArgs* e) +{ + rdpSettings* settings; + HaikuContext* hfc; + + if (!context || !e) + { + WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", __FUNCTION__, context, (void*)e); + return; + } + + hfc = (HaikuContext*)context; + + if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) + haiku_cliprdr_uninit(hfc, (CliprdrClientContext*)e->pInterface); +} + +static int haiku_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) +{ + const char* str_data = freerdp_get_logon_error_info_data(data); + const char* str_type = freerdp_get_logon_error_info_type(type); + + if (!instance || !instance->context) + return -1; + + WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type); + return 1; +} + +static BOOL haiku_begin_paint(rdpContext* context) +{ + rdpGdi* gdi = context->gdi; + gdi->primary->hdc->hwnd->invalid->null = TRUE; + return TRUE; +} + +static BOOL haiku_end_paint(rdpContext* context) +{ + HaikuContext* h_context = (HaikuContext*)context; + rdpGdi* gdi = context->gdi; + + if(h_context->window == NULL) + return TRUE; + + if (gdi->primary->hdc->hwnd->invalid->null) + return TRUE; + + char* data = (char*)h_context->window->view->GetBuffer(); + + int x = gdi->primary->hdc->hwnd->invalid->x; + int y = gdi->primary->hdc->hwnd->invalid->y; + int w = gdi->primary->hdc->hwnd->invalid->w; + int h = gdi->primary->hdc->hwnd->invalid->h; + + for (int i = 0; i < h; i++) + { + memcpy(data + ((i + y) * (gdi->width * GetBytesPerPixel( + gdi->dstFormat))) + x * GetBytesPerPixel(gdi->dstFormat), + gdi->primary_buffer + ((i + y) * (gdi->width * + GetBytesPerPixel(gdi->dstFormat))) + x * GetBytesPerPixel(gdi->dstFormat), + w * GetBytesPerPixel(gdi->dstFormat)); + } + + h_context->window->view->Paint(); + + return TRUE; +} + +static BOOL haiku_pre_connect(freerdp* instance) +{ + int rc; + rdpSettings* settings; + + if (!instance) + return FALSE; + + settings = instance->settings; + + if (!settings) + return FALSE; + + settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; + settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE; + settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; + settings->OrderSupport[NEG_LINETO_INDEX] = TRUE; + settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE; + settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; + settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; + settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE; + settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; + settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; + settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; + settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; + + PubSub_SubscribeChannelConnected(instance->context->pubSub, haiku_OnChannelConnectedEventHandler); + PubSub_SubscribeChannelDisconnected(instance->context->pubSub, haiku_OnChannelDisconnectedEventHandler); + + if (settings->Fullscreen) + { + BScreen screen; + settings->DesktopWidth = (UINT32) screen.Frame().right + 1; + settings->DesktopHeight = (UINT32) screen.Frame().bottom + 1; + } + + if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) + return FALSE; + + return TRUE; +} + +static BOOL haiku_post_connect(freerdp* instance) +{ + rdpGdi* gdi; + rdpContext* context; + rdpSettings* settings; + + context = ((rdpContext*) instance->context); + + HaikuContext* h_context = (HaikuContext*)context; + + if (!gdi_init(instance, PIXEL_FORMAT_BGRA32)) + return FALSE; + + gdi = instance->context->gdi; + settings = instance->settings; + + instance->update->BeginPaint = haiku_begin_paint; + instance->update->EndPaint = haiku_end_paint; + + if (h_context->window == NULL) + { + char wndTitle[256]={"FreeRDP"}; + + BRect rect = BRect(50, 50, 50 + gdi->width, 50 + gdi->height); + + if (settings->Fullscreen) + rect = BRect(0, 0, gdi->width, gdi->height); + + if (settings->WindowTitle != NULL) + snprintf(wndTitle, 255, "%s", settings->WindowTitle); + else if (settings->ServerPort == 3389) + snprintf(wndTitle, 255, "FreeRDP: %s", settings->ServerHostname); + else + snprintf(wndTitle, 255, "FreeRDP: %S:%u", settings->ServerHostname, settings->ServerPort); + + h_context->window = new RDPWindow(rect, wndTitle, instance); + h_context->window->Show(); + } + return TRUE; +} + +static void haiku_post_disconnect(freerdp* instance) +{ + rdpContext* context; + + if (!instance) + return; + + if (!instance->context) + return; + + context = (rdpContext*) instance->context; + HaikuContext* h_context = (HaikuContext*)context; + + if (h_context->window != NULL) + { + h_context->window->Lock(); + h_context->window->Quit(); + } + + gdi_free(instance); +} + +static DWORD WINAPI haiku_haiku_app_thread_proc(LPVOID arg) +{ + BApplication app("application/x-vnd.freerdp"); + *(BOOL*)arg = TRUE; + app.Run(); + + ExitThread(0); + return 0; +} + + +static DWORD WINAPI haiku_client_thread_proc(LPVOID arg) +{ + rdpContext* context = (rdpContext*)arg; + freerdp* instance = context->instance; + DWORD nCount; + DWORD status; + HANDLE handles[64]; + + if (!freerdp_connect(instance)) + { + WLog_ERR(TAG, "connection failure"); + return 0; + } + + while (!freerdp_shall_disconnect(instance)) + { + nCount = freerdp_get_event_handles(instance->context, &handles[0], 64); + + if (nCount == 0) + { + WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__); + break; + } + + status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); + + if (status == WAIT_FAILED) + { + WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %" PRIu32"", __FUNCTION__, + status); + break; + } + + if (!freerdp_check_event_handles(instance->context)) + { + if (client_auto_reconnect(instance)) + continue; + else + { + if (freerdp_error_info(instance) == 0) + status = 42; + } + + if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS) + WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); + + break; + } + } + + freerdp_disconnect(instance); + ExitThread(0); + return 0; +} + + +static BOOL haiku_client_new(freerdp* instance, rdpContext* context) +{ + HaikuContext* h_context = (HaikuContext*)context; + + if (!instance || !context) + return FALSE; + + instance->PreConnect = haiku_pre_connect; + instance->PostConnect = haiku_post_connect; + instance->PostDisconnect = haiku_post_disconnect; + instance->Authenticate = client_cli_authenticate; + instance->GatewayAuthenticate = client_cli_gw_authenticate; + instance->VerifyCertificateEx = client_cli_verify_certificate_ex; + instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex; + instance->PresentGatewayMessage = client_cli_present_gateway_message; + instance->LogonErrorInfo = haiku_logon_error_info; + + h_context->window = NULL; + + return TRUE; +} + + +static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) +{ + ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS)); + pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION; + pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1); + pEntryPoints->ContextSize = sizeof(HaikuContext); + pEntryPoints->ClientNew = haiku_client_new; + return 0; +} + + +int main(int argc, char* argv[]) +{ + int rc = -1; + int status; + HANDLE appThread, clientThread; + RDP_CLIENT_ENTRY_POINTS clientEntryPoints; + rdpContext* context; + rdpSettings* settings; + BOOL appThreadReady = FALSE; + + RdpClientEntry(&clientEntryPoints); + context = freerdp_client_context_new(&clientEntryPoints); + + if (!context) + goto fail; + + settings = context->settings; + + status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); + if (status) + { + rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); + goto fail; + } + + if (!(appThread = CreateThread(NULL, 0, haiku_haiku_app_thread_proc, &appThreadReady, 0, NULL))) + WLog_ERR(TAG, "Failed to create app thread"); + + while (!appThreadReady) + sched_yield(); + + if (freerdp_client_start(context) != 0) + goto fail; + + if (!(clientThread = CreateThread(NULL, 0, haiku_client_thread_proc, context, 0, NULL))) + WLog_ERR(TAG, "Failed to create client thread"); + else + WaitForSingleObject(clientThread, INFINITE); + + if (freerdp_client_stop(context) != 0) + rc = -1; + else + rc = 0; + +fail: + freerdp_client_context_free(context); + return rc; +} diff --git a/client/Haiku/haiku_freerdp.h b/client/Haiku/haiku_freerdp.h new file mode 100644 index 0000000..d157d99 --- /dev/null +++ b/client/Haiku/haiku_freerdp.h @@ -0,0 +1,60 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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_CLIENT_HAIKU_FREERDP_H +#define FREERDP_CLIENT_HAIKU_FREERDP_H + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +} + +class RDPWindow; + +struct haiku_context +{ + rdpContext _p; + + RDPWindow *window; + + wClipboard* clipboard; + BOOL clipboardSync; + UINT32 numServerFormats; + UINT32 requestedFormatId; + HANDLE clipboardRequestEvent; + CLIPRDR_FORMAT* serverFormats; + CliprdrClientContext* cliprdr; + UINT32 clipboardCapabilities; +}; +typedef struct haiku_context HaikuContext; + +#endif // FREERDP_CLIENT_HAIKU_FREERDP_H diff --git a/client/Haiku/haiku_resources.rdef b/client/Haiku/haiku_resources.rdef new file mode 100644 index 0000000..b7d7760 --- /dev/null +++ b/client/Haiku/haiku_resources.rdef @@ -0,0 +1,48 @@ +resource app_signature "application/x-vnd.freerdp"; + +resource app_flags B_MULTIPLE_LAUNCH; + +resource app_version { + major = 2, + middle = 9, + minor = 0, + variety = 0, + internal = 0, + short_info = "FreeRDP", + long_info = "FreeRDP" +}; + +resource vector_icon { + $"6E6369662803010000020016023CC7ED389BBFBA16553E39AF4977C842ADC700" + $"FFFFD3020016023C529D3753A2B8966F3D9D074B6044496AAF0047FFA0020016" + $"02BC4E75BC411A3C90D9BCA00C47587D4ABA850090FFD40200160238313C3B5C" + $"F0BFCD953C7AAB4C13943FCAF901ECFFC3054B04016B020006033E2F99387F17" + $"BA42DC3FF5B84A0E32482C90001D1E2C3D454658FF010101020006023879063B" + $"8224BE2CC73B10D94A1F6F49B89400242222FF9A9A9A020006033C69A6000000" + $"0000003E186148800049800000D4CECE58F3F3F3FFD9D9D90389FF0005000500" + $"0500030100000500033A3A4303F46E0C03010000020016023CC7ED389BBFBA16" + $"553E39AF4977C842ADC700FFFFD3020006023C529D3753A2B8966F3D9D074B60" + $"44496AAF00474747FFA5A0A002001602BC4E75BC411A3C90D9BCA00C47587D4A" + $"BA850090FFD40200160238313C3B5CF0BFCD953C7AAB4C13943FCAF901ECFFC3" + $"054B04017E020006033E2F99387F17BA42DC3FF5B84A0E32482C90001D1E2C3D" + $"454658FF010101020006023879063B8224BE2CC73B10D94A1F6F49B894002422" + $"22FF9A9A9A020006033C69A60000000000003E186148800049800000D4CECE58" + $"F3F3F3FFD9D9D9038AFF01050005000500030100000500033A3A43033A3A4303" + $"0100000300AAFF0300FF0003FFAA002200000A062228224A485E525252302C22" + $"0A042228483852302C220A044838485E525252300A042228224A485E48380A04" + $"453A45572446242C0A04B560442446242CB569B8200A0445544557244626440A" + $"0438263D234E28492C080438263D234E284E2E0A03492C4E284E2E0802425843" + $"C9830A06486054606052CA1BC5B95C4D524800000A0430303050505050300000" + $"000000000A04B570B86DB57DC12FC17CC729C17CBD8F0A062228224A485E5252" + $"52302C220A062228224A485E525252302C220A042228483852302C220A044838" + $"485E525252300A042228224A485E48380A042228224A485E48380A04453A4557" + $"2446242C0A04B560442446242CB569B8200A04B560442446242CB569B8200A04" + $"45544557244626440A0438263D234E28492C080438263D234E284E2E0A03492C" + $"4E284E2E0802425843C9830A04B570B86DB57DC12FC17CC729C17CBD8F0F0A06" + $"010C000A0001091001178400040A040108000A05010A000A0001011001178400" + $"040A010102000A03020405000A080106000A090107000A0A010B1815FF011782" + $"20040A020103000A110112023E00150000000000003E260D42CEDE44B6B40A26" + $"0112023E21EE0000000000003E260D483363471B5A0A250112023E0015000000" + $"0000003E260D42CEDE482DAD0A270112023E21EE0000000000003E41BA483363" + $"4901E6" +}; diff --git a/client/Haiku/haiku_view.cpp b/client/Haiku/haiku_view.cpp new file mode 100644 index 0000000..a886711 --- /dev/null +++ b/client/Haiku/haiku_view.cpp @@ -0,0 +1,228 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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. + */ + +#include "haiku_window.h" +#include "haiku_view.h" + + +RDPView::RDPView(BRect rect) : + BView(rect, "RDPView", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS), + showBar(false) +{ + RDPView(rect, rect.IntegerWidth(), rect.IntegerHeight()); +} + +RDPView::RDPView(BRect rect, int width, int height) : + BView(rect, "RDPView", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS), + showBar(false) +{ + buffer_width = width; + buffer_height = height; + lastButtons = 0; + + BRect fbRect = BRect(0, 0, buffer_width - 1, buffer_height - 1); + bufferView = new BView(fbRect, "bufferView", B_FOLLOW_ALL_SIDES, 0); + bufferBitmap = new BBitmap(fbRect, B_RGB32, true); + bufferBitmap->AddChild(bufferView); + + font = be_bold_font; + font.SetSize(14); + SetFont(&font, B_FONT_ALL); + + title = BString("FreeRDP"); +} + +void +RDPView::AttachedToWindow(void) +{ + tickCount = 0; +} + +void +RDPView::Pulse(void) +{ + uint32 dx = Bounds().Width() / 3; + uint32 h = showBar ? 20:2; + + if (lastPos.y >= 0 && lastPos.y < h && lastPos.x > dx && lastPos.x < dx * 2 ) + { + tickCount++; + if (tickCount > 5) + { + showBar = true; + Invalidate(); + } + return; + } + + if (showBar) + { + showBar = false; + Invalidate(); + } + tickCount = 0; +} + +void +RDPView::SetInstance(freerdp *inst) +{ + instance = inst; + title.SetTo(Window()->Title()); +} + +void RDPView::MouseMoved(BPoint p, uint32 transit,const BMessage *message) +{ + rdpInput* input = instance->input; + switch (transit) + { + case B_INSIDE_VIEW: + case B_ENTERED_VIEW: + { + input->MouseEvent(input, PTR_FLAGS_MOVE, p.x, p.y); + tickCount = 0; + break; + } + case B_EXITED_VIEW: + break; + case B_OUTSIDE_VIEW: + break; + } + lastPos = p; +} + +void RDPView::MouseDown(BPoint p) +{ + rdpInput* input = instance->input; + + uint32 dx = Bounds().Width() / 3; + uint32 h = showBar ? 20 : 2; + + uint32 buttons = Window()->CurrentMessage()->FindInt32("buttons"); + int32 clicks = Window()->CurrentMessage()->FindInt32("clicks"); + + int flags = PTR_FLAGS_DOWN; + + if (buttons & B_PRIMARY_MOUSE_BUTTON) + flags |= PTR_FLAGS_BUTTON1; + if (buttons & B_SECONDARY_MOUSE_BUTTON) + flags |= PTR_FLAGS_BUTTON2; + if (buttons & B_TERTIARY_MOUSE_BUTTON) + flags |= PTR_FLAGS_BUTTON2; + + if (showBar && buttons & B_PRIMARY_MOUSE_BUTTON) { + BRect closeButtonRect(dx + 3, 3, dx + h - 3, h - 3); + if (closeButtonRect.Contains(p)) + { + freerdp_abort_connect(instance); + } + else if (clicks == 2) + { + Window()->Minimize(true); + flags = 0; + } + } + + if (flags != 0) + input->MouseEvent(input, flags, p.x, p.y); + + lastPos = p; + lastButtons = buttons; +} + +void RDPView::MouseUp(BPoint p) +{ + rdpInput* input = instance->input; + + uint32 buttons = Window()->CurrentMessage()->FindInt32("buttons"); + int flags = 0; + + if ((buttons ^ lastButtons) & B_PRIMARY_MOUSE_BUTTON) + flags |= PTR_FLAGS_BUTTON1; + if ((buttons ^ lastButtons) & B_SECONDARY_MOUSE_BUTTON) + flags |= PTR_FLAGS_BUTTON2; + if ((buttons ^lastButtons) & B_TERTIARY_MOUSE_BUTTON) + flags |= PTR_FLAGS_BUTTON2; + + if (flags != 0) + input->MouseEvent(input, flags, p.x, p.y); + + lastPos = p; + lastButtons = buttons; +} + +void +RDPView::Draw(BRect r) +{ + uint32 dx = Bounds().Width() / 3; + uint32 h = showBar ? 20 : 2; + + DrawBitmap(bufferBitmap, r, r); + + if (showBar) + { + BRect r(dx, -1, dx * 2, h); + SetDrawingMode(B_OP_COPY); + + SetHighColor(255, 203, 0); + SetLowColor(255, 203, 0); + FillRect(r); + SetHighColor(179, 143, 0); + SetLowColor(179, 143, 0); + StrokeRect(r); + + SetDrawingMode(B_OP_ALPHA); + BRect closeButtonRect(dx + 3, 3, dx + h - 3, h - 3); + StrokeRect(closeButtonRect); + + SetHighColor(0, 0, 0); + SetLowColor(0, 0, 0); + float width = font.StringWidth(title); + DrawString(title, BPoint(Bounds().Width()/2 - width/2, 16)); + } +} + +void +RDPView::Paint() +{ + if (LockLooper()) + { + bufferView->LockLooper(); + SetDrawingMode(B_OP_COPY); + DrawBitmap(bufferBitmap); + bufferView->UnlockLooper(); + UnlockLooper(); + } +} + +uint32 * +RDPView::GetBuffer() +{ + if (bufferBitmap) + return (uint32*)bufferBitmap->Bits(); + + return NULL; +} + +uint32 +RDPView::GetBufferSize() +{ + if (bufferBitmap) + return bufferBitmap->BitsLength()/4; + + return 0; +} diff --git a/client/Haiku/haiku_view.h b/client/Haiku/haiku_view.h new file mode 100644 index 0000000..056372c --- /dev/null +++ b/client/Haiku/haiku_view.h @@ -0,0 +1,75 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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_CLIENT_HAIKU_VIEW_H +#define FREERDP_CLIENT_HAIKU_VIEW_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "haiku_freerdp.h" + +class RDPView : public BView +{ + public: + RDPView(BRect rect); + RDPView(BRect rect, int width, int height); + ~RDPView() { }; + + void Paint(); + void SetInstance(freerdp *instance); + uint32 *GetBuffer(); + uint32 GetBufferSize(); + BPoint GetLastMousePos() { return lastPos; }; + + int Width() { return buffer_width; }; + int Height() { return buffer_height; }; +protected: + virtual void Draw(BRect r); + virtual void MouseDown(BPoint p); + virtual void MouseUp(BPoint p); + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + virtual void Pulse(void); + virtual void AttachedToWindow(void); + +private: + freerdp *instance; + + int buffer_width; + int buffer_height; + BView *bufferView; + BBitmap *bufferBitmap; + uint32 lastButtons; + BPoint lastPos; + uint32 tickCount; + bool showBar; + BFont font; + BString title; +}; + +#endif // FREERDP_CLIENT_HAIKU_VIEW_H diff --git a/client/Haiku/haiku_window.cpp b/client/Haiku/haiku_window.cpp new file mode 100644 index 0000000..1c9f7a6 --- /dev/null +++ b/client/Haiku/haiku_window.cpp @@ -0,0 +1,181 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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. + */ + +#include "haiku_window.h" +#include "haiku_clipboard.h" + +#include +#include +#include + +static const uint32 haiku_scan_codes[] = { +VK_ESCAPE, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, +VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12, VK_PRINT, VK_SCROLL, 0, +////////// +VK_OEM_3,VK_KEY_1,VK_KEY_2,VK_KEY_3,VK_KEY_4,VK_KEY_5,VK_KEY_6,VK_KEY_7,VK_KEY_8, +VK_KEY_9,VK_KEY_0,VK_OEM_MINUS,VK_OEM_PLUS,VK_BACK,VK_INSERT|KBDEXT, +VK_HOME|KBDEXT,VK_PRIOR|KBDEXT,VK_NUMLOCK,VK_DIVIDE|KBDEXT,VK_MULTIPLY,VK_SUBTRACT, +////////// +VK_TAB,VK_KEY_Q,VK_KEY_W,VK_KEY_E,VK_KEY_R,VK_KEY_T,VK_KEY_Y,VK_KEY_U,VK_KEY_I, +VK_KEY_O,VK_KEY_P,VK_OEM_4,VK_OEM_6,VK_OEM_5,VK_DELETE|KBDEXT,VK_END|KBDEXT,VK_NEXT|KBDEXT, +VK_NUMPAD7,VK_NUMPAD8,VK_NUMPAD9,VK_ADD, +////////// +VK_CAPITAL,VK_KEY_A,VK_KEY_S,VK_KEY_D,VK_KEY_F,VK_KEY_G,VK_KEY_H,VK_KEY_J,VK_KEY_K,VK_KEY_L,VK_OEM_1,VK_OEM_7,VK_RETURN, +VK_NUMPAD4,VK_NUMPAD5,VK_NUMPAD6, +////////// +VK_LSHIFT,VK_KEY_Z,VK_KEY_X,VK_KEY_C,VK_KEY_V,VK_KEY_B,VK_KEY_N,VK_KEY_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2, +VK_RSHIFT,VK_UP|KBDEXT,VK_NUMPAD1,VK_NUMPAD2,VK_NUMPAD3,VK_RETURN|KBDEXT, +////////// +VK_LCONTROL,VK_LMENU,VK_SPACE,VK_RMENU,VK_RCONTROL,VK_LEFT|KBDEXT,VK_DOWN|KBDEXT,VK_RIGHT|KBDEXT,VK_NUMPAD0,VK_DECIMAL, +VK_LWIN|KBDEXT,VK_RWIN|KBDEXT,127,0 +}; + + +RDPWindow::RDPWindow(BRect frame, const char* title, freerdp *inst) + : BWindow(BRect(frame.left, frame.top, frame.right - 1, frame.bottom - 1), title, + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) +{ + view = new RDPView(Bounds(), frame.Width(), frame.Height()); + AddChild(view); + + SetInstance(inst); + + be_clipboard->StartWatching(this); + + SetPulseRate(100000); +} + +RDPWindow::~RDPWindow() +{ + be_clipboard->StopWatching(this); +} + +void +RDPWindow::MessageReceived(BMessage *message) +{ + switch (message->what) + { + case B_UNMAPPED_KEY_DOWN: + case B_KEY_DOWN: + { + rdpInput* input = instance->input; + + const char *bytes; + int32 key; + uint32 keycode; + message->FindInt32("key", &key); + + keycode = haiku_scan_codes[(uint8)key-1]; + DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, input->context->settings->KeyboardType); + + if (scancode) + freerdp_input_send_keyboard_event_ex(input, TRUE, scancode); + + break; + } + case B_UNMAPPED_KEY_UP: + case B_KEY_UP: + { + rdpInput* input = instance->input; + + const char *bytes; + int32 key; + uint32 keycode; + message->FindInt32("key",&key); + + keycode = haiku_scan_codes[(uint8)key-1]; + DWORD scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, input->context->settings->KeyboardType); + + if (scancode) + freerdp_input_send_keyboard_event_ex(input, FALSE, scancode); + + break; + } + case B_MOUSE_WHEEL_CHANGED: + { + rdpInput* input = instance->input; + BPoint pos = view->GetLastMousePos(); + + float shift=0; + UINT16 flags; + + flags = PTR_FLAGS_WHEEL; + + if(message->FindFloat("be:wheel_delta_y",&shift)==B_OK) { + if(shift<0) { + flags |= 0x0078; + } + if(shift>0) { + flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; + } + } + input->MouseEvent(input, flags, pos.x, pos.y); + break; + } + case B_CLIPBOARD_CHANGED: + { + HaikuContext *hfc = (HaikuContext*)instance->context; + + BMessage *clip = NULL; + const char *data = NULL; + ssize_t size = 0; + + if(be_clipboard->Lock()) + { + if((clip = be_clipboard->Data())) + { + if (clip->FindData("text/plain", B_MIME_TYPE, (const void**)&data, &size) == B_OK) + { + if (data != NULL && size > 0) + { + BString textString(data, size); + UINT32 formatId = ClipboardRegisterFormat(hfc->clipboard, "UTF8_STRING"); + ClipboardSetData(hfc->clipboard, formatId, textString.String(), textString.Length() + 1); + } + else + { + ClipboardEmpty(hfc->clipboard); + } + + haiku_cliprdr_send_client_format_list(hfc->cliprdr); + } + } + be_clipboard->Unlock(); + } + break; + } + default: + BWindow::MessageReceived(message); + break; + } +} + + +void +RDPWindow::SetInstance(freerdp *inst) +{ + instance = inst; + view->SetInstance(inst); +} + +bool +RDPWindow::QuitRequested() +{ + freerdp_abort_connect(instance); + return false; +} diff --git a/client/Haiku/haiku_window.h b/client/Haiku/haiku_window.h new file mode 100644 index 0000000..00e0c83 --- /dev/null +++ b/client/Haiku/haiku_window.h @@ -0,0 +1,51 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2018-2022 Gerasim Troeglazov <3deyes@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_CLIENT_HAIKU_WINDOW_H +#define FREERDP_CLIENT_HAIKU_WINDOW_H + +#include +#include +#include + +#include +#include +#include +#include + +#include "haiku_freerdp.h" +#include "haiku_view.h" + +class RDPWindow : public BWindow { + public: + RDPWindow(BRect rect, const char* name, freerdp *instance); + virtual ~RDPWindow(); + + virtual void MessageReceived(BMessage *message); + bool QuitRequested(); + + void SetInstance(freerdp *instance); + + RDPView *view; + private: + freerdp *instance; +}; + +#endif // FREERDP_CLIENT_HAIKU_WINDOW_H + + diff --git a/config.h.in b/config.h.in index 9644ab9..2140e2e 100644 --- a/config.h.in +++ b/config.h.in @@ -67,6 +67,7 @@ #cmakedefine WITH_OPENCL #cmakedefine WITH_MEDIA_FOUNDATION #cmakedefine WITH_MEDIACODEC +#cmakedefine WITH_MEDIA_KIT #cmakedefine WITH_VAAPI diff --git a/libfreerdp/locale/keyboard.c b/libfreerdp/locale/keyboard.c index 4c5ae03..bed3980 100644 --- a/libfreerdp/locale/keyboard.c +++ b/libfreerdp/locale/keyboard.c @@ -128,7 +128,7 @@ static int freerdp_keyboard_init_x11_evdev(DWORD* keyboardLayoutId, DWORD freerdp_keyboard_init(DWORD keyboardLayoutId) { DWORD keycode; -#if defined(__APPLE__) || defined(WITH_X11) || defined(WITH_WAYLAND) +#if defined(__APPLE__) || defined(__HAIKU__) || defined(WITH_X11) || defined(WITH_WAYLAND) int status = -1; #endif @@ -137,7 +137,7 @@ DWORD freerdp_keyboard_init(DWORD keyboardLayoutId) status = freerdp_keyboard_init_apple(&keyboardLayoutId, X11_KEYCODE_TO_VIRTUAL_SCANCODE); #endif -#if defined(WITH_X11) || defined(WITH_WAYLAND) +#if defined(WITH_X11) || defined(WITH_WAYLAND) || defined(__HAIKU__) #ifdef WITH_XKBFILE if (status < 0) diff --git a/winpr/include/winpr/winsock.h b/winpr/include/winpr/winsock.h index 1677609..7912ee5 100644 --- a/winpr/include/winpr/winsock.h +++ b/winpr/include/winpr/winsock.h @@ -84,6 +84,11 @@ WINPR_API INT winpr_inet_pton(INT Family, PCSTR pszAddrString, PVOID pAddrBuf); #include #include +#ifdef __HAIKU__ +#include +#include +#endif + #include #include #include diff --git a/winpr/libwinpr/CMakeLists.txt b/winpr/libwinpr/CMakeLists.txt index 2df8d89..2e3886a 100644 --- a/winpr/libwinpr/CMakeLists.txt +++ b/winpr/libwinpr/CMakeLists.txt @@ -77,7 +77,7 @@ macro (winpr_definition_add) set (WINPR_DEFINITIONS ${WINPR_DEFINITIONS} PARENT_SCOPE) endmacro() -set(CMAKE_REQUIRED_LIBRARIES rt) +#set(CMAKE_REQUIRED_LIBRARIES rt) if (NOT IOS) check_function_exists(timer_create TIMER_CREATE) check_function_exists(timer_delete TIMER_DELETE) @@ -85,7 +85,7 @@ if (NOT IOS) check_function_exists(timer_gettime TIMER_GETTIME) if (TIMER_CREATE AND TIMER_DELETE AND TIMER_SETTIME AND TIMER_GETTIME) add_definitions(-DWITH_POSIX_TIMER) - winpr_library_add_private(rt) +# winpr_library_add_private(rt) endif() endif() diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c index 4bba4ec..b1db9d4 100644 --- a/winpr/libwinpr/path/shell.c +++ b/winpr/libwinpr/path/shell.c @@ -507,10 +507,24 @@ BOOL PathMakePathA(LPCSTR path, LPSECURITY_ATTRIBUTES lpAttributes) for (p = dup; p;) #endif { + struct stat stat_info; + BOOL skip = FALSE; + if ((p = strchr(p + 1, delim))) *p = '\0'; - if (mkdir(dup, 0777) != 0) + if (stat(dup, &stat_info) == 0) + { + if ((stat_info.st_mode & S_IFDIR) == 0) + { + result = FALSE; + break; + } + + skip = TRUE; + } + + if (!skip && mkdir(dup, 0777) != 0) if (errno != EEXIST) { result = FALSE; diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 4204f59..da78812 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -854,7 +854,9 @@ static int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue) pthread_attr_init(&(timerQueue->attr)); timerQueue->param.sched_priority = sched_get_priority_max(SCHED_FIFO); pthread_attr_setschedparam(&(timerQueue->attr), &(timerQueue->param)); +#ifndef __HAIKU__ pthread_attr_setschedpolicy(&(timerQueue->attr), SCHED_FIFO); +#endif pthread_create(&(timerQueue->thread), &(timerQueue->attr), TimerQueueThread, timerQueue); return 0; } diff --git a/winpr/libwinpr/sysinfo/CMakeLists.txt b/winpr/libwinpr/sysinfo/CMakeLists.txt index 799df05..18723bb 100644 --- a/winpr/libwinpr/sysinfo/CMakeLists.txt +++ b/winpr/libwinpr/sysinfo/CMakeLists.txt @@ -21,7 +21,7 @@ endif() winpr_module_add(sysinfo.c) -if((NOT WIN32) AND (NOT APPLE) AND (NOT ANDROID) AND (NOT OPENBSD)) +if((NOT WIN32) AND (NOT APPLE) AND (NOT ANDROID) AND (NOT OPENBSD) AND (NOT HAIKU)) winpr_library_add_private(rt) endif() diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index b1acf9a..d1b0c6f 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -171,7 +171,7 @@ if(UNIX) winpr_library_add_private(m) endif() -if((FREEBSD) AND (NOT KFREEBSD)) +if(((FREEBSD) AND (NOT KFREEBSD)) OR HAIKU) winpr_library_add_private(execinfo) endif() diff --git a/winpr/libwinpr/winsock/CMakeLists.txt b/winpr/libwinpr/winsock/CMakeLists.txt index ef13cd1..8cd6a62 100644 --- a/winpr/libwinpr/winsock/CMakeLists.txt +++ b/winpr/libwinpr/winsock/CMakeLists.txt @@ -20,3 +20,7 @@ winpr_module_add(winsock.c) if(WIN32) winpr_library_add_public(ws2_32) endif() + +if(HAIKU) + winpr_library_add_public(network) +endif() diff --git a/winpr/libwinpr/winsock/winsock.c b/winpr/libwinpr/winsock/winsock.c index 6e82be9..d7d6613 100644 --- a/winpr/libwinpr/winsock/winsock.c +++ b/winpr/libwinpr/winsock/winsock.c @@ -381,9 +381,11 @@ void WSASetLastError(int iError) errno = EPROTONOSUPPORT; break; +#ifdef ESOCKTNOSUPPORT case WSAESOCKTNOSUPPORT: errno = ESOCKTNOSUPPORT; break; +#endif case WSAEOPNOTSUPP: errno = EOPNOTSUPP; @@ -441,9 +443,11 @@ void WSASetLastError(int iError) errno = ESHUTDOWN; break; +#ifdef ETOOMANYREFS case WSAETOOMANYREFS: errno = ETOOMANYREFS; break; +#endif case WSAETIMEDOUT: errno = ETIMEDOUT; @@ -472,16 +476,18 @@ void WSASetLastError(int iError) case WSAENOTEMPTY: errno = ENOTEMPTY; break; -#ifdef EPROCLIM +#ifdef EPROCLIM case WSAEPROCLIM: errno = EPROCLIM; break; #endif +#ifdef EUSERS case WSAEUSERS: errno = EUSERS; break; +#endif case WSAEDQUOT: errno = EDQUOT; @@ -491,9 +497,11 @@ void WSASetLastError(int iError) errno = ESTALE; break; +#ifdef EREMOTE case WSAEREMOTE: errno = EREMOTE; break; +#endif } } @@ -566,9 +574,11 @@ int WSAGetLastError(void) iError = WSAEPROTONOSUPPORT; break; +#ifdef ESOCKTNOSUPPORT case ESOCKTNOSUPPORT: iError = WSAESOCKTNOSUPPORT; break; +#endif case EOPNOTSUPP: iError = WSAEOPNOTSUPP; @@ -626,9 +636,11 @@ int WSAGetLastError(void) iError = WSAESHUTDOWN; break; +#ifdef ETOOMANYREFS case ETOOMANYREFS: iError = WSAETOOMANYREFS; break; +#endif case ETIMEDOUT: iError = WSAETIMEDOUT; @@ -657,16 +669,18 @@ int WSAGetLastError(void) case ENOTEMPTY: iError = WSAENOTEMPTY; break; -#ifdef EPROCLIM +#ifdef EPROCLIM case EPROCLIM: iError = WSAEPROCLIM; break; #endif +#ifdef EUSERS case EUSERS: iError = WSAEUSERS; break; +#endif case EDQUOT: iError = WSAEDQUOT; @@ -676,18 +690,19 @@ int WSAGetLastError(void) iError = WSAESTALE; break; +#ifdef EREMOTE case EREMOTE: iError = WSAEREMOTE; break; +#endif + /* Special cases */ #if (EAGAIN != EWOULDBLOCK) - case EAGAIN: iError = WSAEWOULDBLOCK; break; #endif #if defined(EPROTO) - case EPROTO: iError = WSAECONNRESET; break; diff --git a/winpr/winpr.pc.in b/winpr/winpr.pc.in index 6b0c950..f94f8f9 100644 --- a/winpr/winpr.pc.in +++ b/winpr/winpr.pc.in @@ -11,5 +11,5 @@ Version: @WINPR_VERSION@ Requires: Requires.private: libssl Libs: -L${libdir} ${libs} -Libs.private: -ldl -lrt -lm -lpthread +Libs.private: -ldl -lnetwork -lm -lpthread Cflags: -I${includedir} -- 2.43.2 From a48b688eb7b7e40b50d598f7ee6c44e1f99d78be Mon Sep 17 00:00:00 2001 From: Schrijvers Luc Date: Sat, 20 Apr 2024 11:53:38 +0200 Subject: Fix headers installation paths, fix cmake configuration paths for includeDir diff --git a/CMakeLists.txt b/CMakeLists.txt index a48a4b2..40c705f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,7 +129,7 @@ endif() message(STATUS "Git Revision ${GIT_REVISION}") -set(FREERDP_INCLUDE_DIR "include/freerdp${FREERDP_VERSION_MAJOR}/") +set(FREERDP_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}/freerdp${FREERDP_VERSION_MAJOR}/") # Compatibility options if(DEFINED STATIC_CHANNELS) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index a020dc5..4f9f35a 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -19,7 +19,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp/version.h) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp/build-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp/build-config.h) -set(FREERDP_INSTALL_INCLUDE_DIR include/freerdp${FREERDP_VERSION_MAJOR}/freerdp) +set(FREERDP_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/freerdp${FREERDP_VERSION_MAJOR}/freerdp) file(GLOB FREERDP_HEADERS "freerdp/*.h") install(FILES ${FREERDP_HEADERS} DESTINATION ${FREERDP_INSTALL_INCLUDE_DIR} COMPONENT headers) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 748582b..5f85a04 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -238,7 +238,7 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") SetFreeRDPCMakeInstallDir(WINPR_CMAKE_INSTALL_DIR "WinPR${WINPR_VERSION_MAJOR}") - set(WINPR_INCLUDE_DIR "include/winpr${WINPR_VERSION_MAJOR}") + set(WINPR_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}/winpr${WINPR_VERSION_MAJOR}") configure_package_config_file(WinPRConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/WinPRConfig.cmake INSTALL_DESTINATION ${WINPR_CMAKE_INSTALL_DIR} diff --git a/winpr/include/CMakeLists.txt b/winpr/include/CMakeLists.txt index 452383d..577f604 100644 --- a/winpr/include/CMakeLists.txt +++ b/winpr/include/CMakeLists.txt @@ -17,7 +17,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/winpr/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/winpr/version.h) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/winpr/wtypes.h.in ${CMAKE_CURRENT_BINARY_DIR}/winpr/wtypes.h) -set(WINPR_INSTALL_INCLUDE_DIR include/winpr${WINPR_VERSION_MAJOR}/winpr) +set(WINPR_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/winpr${WINPR_VERSION_MAJOR}/winpr) file(GLOB WINPR_HEADERS "winpr/*.h") install(FILES ${WINPR_HEADERS} DESTINATION ${WINPR_INSTALL_INCLUDE_DIR} COMPONENT headers) -- 2.43.2