mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #5160 from akallabeth/wayland_clipboard
Wayland clipboard
This commit is contained in:
commit
281c855981
|
@ -586,10 +586,10 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
||||
CLIPRDR_CAPABILITIES* capabilities)
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
wStream* s;
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
|
||||
const CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
|
||||
|
||||
|
@ -601,7 +601,7 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
|||
|
||||
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */
|
||||
Stream_Write_UINT16(s, 0); /* pad1 */
|
||||
generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets;
|
||||
generalCapabilitySet = (const CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets;
|
||||
Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */
|
||||
Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */
|
||||
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
|
||||
|
@ -616,7 +616,7 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
||||
CLIPRDR_TEMP_DIRECTORY* tempDirectory)
|
||||
const CLIPRDR_TEMP_DIRECTORY* tempDirectory)
|
||||
{
|
||||
int length;
|
||||
wStream* s;
|
||||
|
@ -652,7 +652,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_LIST* formatList)
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
wStream* s;
|
||||
UINT32 index;
|
||||
|
@ -782,14 +782,12 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE;
|
||||
formatListResponse->dataLen = 0;
|
||||
s = cliprdr_packet_new(formatListResponse->msgType,
|
||||
formatListResponse->msgFlags, formatListResponse->dataLen);
|
||||
s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE,
|
||||
formatListResponse->msgFlags, 0);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
|
@ -807,7 +805,7 @@ static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
|
||||
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
@ -832,7 +830,7 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
|
||||
CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
@ -857,15 +855,12 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST;
|
||||
formatDataRequest->msgFlags = 0;
|
||||
formatDataRequest->dataLen = 4;
|
||||
s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags,
|
||||
formatDataRequest->dataLen);
|
||||
|
||||
s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
|
@ -884,12 +879,12 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE;
|
||||
s = cliprdr_packet_new(formatDataResponse->msgType,
|
||||
|
||||
s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE,
|
||||
formatDataResponse->msgFlags, formatDataResponse->dataLen);
|
||||
|
||||
if (!s)
|
||||
|
@ -910,7 +905,7 @@ static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
||||
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
@ -944,7 +939,7 @@ static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
|
|
@ -143,7 +143,7 @@ static UINT android_cliprdr_send_client_capabilities(CliprdrClientContext*
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_MONITOR_READY* monitorReady)
|
||||
const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
UINT rc;
|
||||
androidContext* afc;
|
||||
|
@ -172,7 +172,7 @@ static UINT android_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_capabilities(CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_CAPABILITIES* capabilities)
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
UINT32 index;
|
||||
CLIPRDR_CAPABILITY_SET* capabilitySet;
|
||||
|
@ -209,7 +209,7 @@ static UINT android_cliprdr_server_capabilities(CliprdrClientContext* cliprdr,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_format_list(CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_FORMAT_LIST* formatList)
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
UINT rc;
|
||||
UINT32 index;
|
||||
|
@ -291,7 +291,7 @@ static UINT android_cliprdr_server_format_list(CliprdrClientContext* cliprdr,
|
|||
*/
|
||||
static UINT android_cliprdr_server_format_list_response(
|
||||
CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
if (!cliprdr || !formatListResponse)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
@ -306,7 +306,7 @@ static UINT android_cliprdr_server_format_list_response(
|
|||
*/
|
||||
static UINT android_cliprdr_server_lock_clipboard_data(CliprdrClientContext*
|
||||
cliprdr,
|
||||
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
if (!cliprdr || !lockClipboardData)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
@ -321,7 +321,7 @@ static UINT android_cliprdr_server_lock_clipboard_data(CliprdrClientContext*
|
|||
*/
|
||||
static UINT android_cliprdr_server_unlock_clipboard_data(
|
||||
CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
if (!cliprdr || !unlockClipboardData)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
@ -336,7 +336,7 @@ static UINT android_cliprdr_server_unlock_clipboard_data(
|
|||
*/
|
||||
static UINT android_cliprdr_server_format_data_request(CliprdrClientContext*
|
||||
cliprdr,
|
||||
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
UINT rc;
|
||||
BYTE* data;
|
||||
|
@ -379,7 +379,7 @@ static UINT android_cliprdr_server_format_data_request(CliprdrClientContext*
|
|||
*/
|
||||
static UINT android_cliprdr_server_format_data_response(
|
||||
CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
BYTE* data;
|
||||
UINT32 size;
|
||||
|
@ -455,7 +455,7 @@ static UINT android_cliprdr_server_format_data_response(
|
|||
*/
|
||||
static UINT android_cliprdr_server_file_contents_request(
|
||||
CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
if (!cliprdr || !fileContentsRequest)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
@ -470,7 +470,7 @@ static UINT android_cliprdr_server_file_contents_request(
|
|||
*/
|
||||
static UINT android_cliprdr_server_file_contents_response(
|
||||
CliprdrClientContext* cliprdr,
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
if (!cliprdr || !fileContentsResponse)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
|
|
@ -70,7 +70,7 @@ int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int mac_cliprdr_send_client_format_list_response(CliprdrClientContext* cliprdr, BOOL status)
|
||||
static int mac_cliprdr_send_client_format_list_response(CliprdrClientContext* cliprdr, BOOL status)
|
||||
{
|
||||
CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
|
||||
|
||||
|
@ -83,7 +83,7 @@ int mac_cliprdr_send_client_format_list_response(CliprdrClientContext* cliprdr,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int mac_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId)
|
||||
static int mac_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId)
|
||||
{
|
||||
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
|
||||
mfContext* mfc = (mfContext*) cliprdr->custom;
|
||||
|
@ -102,7 +102,7 @@ int mac_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, U
|
|||
return 1;
|
||||
}
|
||||
|
||||
int mac_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
|
||||
static int mac_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
|
||||
{
|
||||
CLIPRDR_CAPABILITIES capabilities;
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
|
||||
|
@ -126,7 +126,7 @@ int mac_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_READY* monitorReady)
|
||||
static UINT mac_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
mfContext* mfc = (mfContext*) cliprdr->custom;
|
||||
|
||||
|
@ -142,7 +142,7 @@ UINT mac_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_RE
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPABILITIES* capabilities)
|
||||
static UINT mac_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
UINT32 index;
|
||||
CLIPRDR_CAPABILITY_SET* capabilitySet;
|
||||
|
@ -171,7 +171,7 @@ UINT mac_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPA
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST* formatList)
|
||||
static UINT mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
UINT32 index;
|
||||
CLIPRDR_FORMAT* format;
|
||||
|
@ -238,7 +238,7 @@ UINT mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMA
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
static UINT mac_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ UINT mac_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIP
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
static UINT mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ UINT mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPR
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
static UINT mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ UINT mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLI
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
static UINT mac_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
BYTE* data;
|
||||
UINT32 size;
|
||||
|
@ -304,7 +304,7 @@ UINT mac_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPR
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
static UINT mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
BYTE* data;
|
||||
UINT32 size;
|
||||
|
@ -368,7 +368,7 @@ UINT mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIP
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
static UINT mac_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ UINT mac_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, CLI
|
|||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT mac_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
static UINT mac_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
|
|
@ -418,7 +418,7 @@ DWORD WINAPI mac_client_thread(void* param)
|
|||
|
||||
if (fabsf(dy) > FLT_EPSILON)
|
||||
{
|
||||
flags = PTR_FLAGS_WHEEL;
|
||||
flags = PTR_FLAGS_HWHEEL;
|
||||
units = fabsf(dy) * 120;
|
||||
|
||||
if (dy < 0)
|
||||
|
@ -426,7 +426,7 @@ DWORD WINAPI mac_client_thread(void* param)
|
|||
}
|
||||
else if (fabsf(dx) > FLT_EPSILON)
|
||||
{
|
||||
flags = PTR_FLAGS_HWHEEL;
|
||||
flags = PTR_FLAGS_WHEEL;
|
||||
units = fabsf(dx) * 120;
|
||||
|
||||
if (dx > 0)
|
||||
|
|
|
@ -148,7 +148,8 @@ void mf_scale_mouse_event(void* context, rdpInput* input, UINT16 flags,
|
|||
// Convert to windows coordinates
|
||||
y = [view frame].size.height - y;
|
||||
|
||||
mf_scale_mouse_coordinates(mfc, &x, &y);
|
||||
if ((flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL)) == 0)
|
||||
mf_scale_mouse_coordinates(mfc, &x, &y);
|
||||
freerdp_input_send_mouse_event(input, flags, x, y);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ set(${MODULE_PREFIX}_SRCS
|
|||
wlf_disp.h
|
||||
wlf_input.c
|
||||
wlf_input.h
|
||||
wlf_cliprdr.c
|
||||
wlf_cliprdr.h
|
||||
wlf_channels.c
|
||||
wlf_channels.h
|
||||
)
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <freerdp/gdi/gfx.h>
|
||||
|
||||
#include "wlf_channels.h"
|
||||
#include "wlf_cliprdr.h"
|
||||
#include "wlf_disp.h"
|
||||
#include "wlfreerdp.h"
|
||||
|
||||
|
@ -81,6 +82,7 @@ void wlf_OnChannelConnectedEventHandler(void* context,
|
|||
}
|
||||
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wlf_cliprdr_init(wlf->clipboard, (CliprdrClientContext*)e->pInterface);
|
||||
}
|
||||
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
|
@ -116,6 +118,7 @@ void wlf_OnChannelDisconnectedEventHandler(void* context,
|
|||
}
|
||||
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
wlf_cliprdr_uninit(wlf->clipboard, (CliprdrClientContext*)e->pInterface);
|
||||
}
|
||||
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,870 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Wayland Clipboard Redirection
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/image.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/clipboard.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/channels/cliprdr.h>
|
||||
|
||||
#include "wlf_cliprdr.h"
|
||||
|
||||
#define MAX_CLIPBOARD_FORMATS 255
|
||||
|
||||
static const char* mime_text[] =
|
||||
{
|
||||
"text/plain",
|
||||
"text/plain;charset=utf-8",
|
||||
"UTF8_STRING",
|
||||
"COMPOUND_TEXT",
|
||||
"TEXT",
|
||||
"STRING"
|
||||
};
|
||||
|
||||
static const char* mime_image[] =
|
||||
{
|
||||
"image/png",
|
||||
"image/bmp",
|
||||
"image/x-bmp",
|
||||
"image/x-MS-bmp",
|
||||
"image/x-icon",
|
||||
"image/x-ico",
|
||||
"image/x-win-bitmap",
|
||||
"image/vmd.microsoft.icon",
|
||||
"application/ico",
|
||||
"image/ico",
|
||||
"image/icon",
|
||||
"image/jpeg",
|
||||
"image/tiff"
|
||||
};
|
||||
|
||||
static const char* mime_html[] =
|
||||
{
|
||||
"text/html"
|
||||
};
|
||||
|
||||
struct wlf_clipboard
|
||||
{
|
||||
wlfContext* wfc;
|
||||
rdpChannels* channels;
|
||||
CliprdrClientContext* context;
|
||||
wLog* log;
|
||||
|
||||
UwacSeat* seat;
|
||||
wClipboard* system;
|
||||
wClipboardDelegate* delegate;
|
||||
|
||||
size_t numClientFormats;
|
||||
CLIPRDR_FORMAT* clientFormats;
|
||||
|
||||
size_t numServerFormats;
|
||||
CLIPRDR_FORMAT* serverFormats;
|
||||
|
||||
BOOL sync;
|
||||
|
||||
/* File clipping */
|
||||
BOOL streams_supported;
|
||||
BOOL file_formats_registered;
|
||||
|
||||
/* Server response stuff */
|
||||
FILE* responseFile;
|
||||
UINT32 responseFormat;
|
||||
const char* responseMime;
|
||||
};
|
||||
|
||||
static BOOL wlf_mime_is_text(const char* mime)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_text); x++)
|
||||
{
|
||||
if (strcmp(mime, mime_text[x]) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL wlf_mime_is_image(const char* mime)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_image); x++)
|
||||
{
|
||||
if (strcmp(mime, mime_image[x]) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL wlf_mime_is_html(const char* mime)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_html); x++)
|
||||
{
|
||||
if (strcmp(mime, mime_html[x]) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void wlf_cliprdr_free_server_formats(wfClipboard* clipboard)
|
||||
{
|
||||
if (clipboard && clipboard->serverFormats)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < clipboard->numServerFormats; j++)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = &clipboard->serverFormats[j];
|
||||
free(format->formatName);
|
||||
}
|
||||
|
||||
free(clipboard->serverFormats);
|
||||
clipboard->serverFormats = NULL;
|
||||
clipboard->numServerFormats = 0;
|
||||
}
|
||||
|
||||
UwacClipboardOfferDestroy(clipboard->seat);
|
||||
}
|
||||
|
||||
static void wlf_cliprdr_free_client_formats(wfClipboard* clipboard)
|
||||
{
|
||||
if (clipboard && clipboard->numClientFormats)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < clipboard->numClientFormats; j++)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = &clipboard->clientFormats[j];
|
||||
free(format->formatName);
|
||||
}
|
||||
|
||||
free(clipboard->clientFormats);
|
||||
clipboard->clientFormats = NULL;
|
||||
clipboard->numClientFormats = 0;
|
||||
}
|
||||
|
||||
UwacClipboardOfferDestroy(clipboard->seat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_send_client_format_list(wfClipboard* clipboard)
|
||||
{
|
||||
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
||||
formatList.msgFlags = CB_RESPONSE_OK;
|
||||
formatList.numFormats = (UINT32)clipboard->numClientFormats;
|
||||
formatList.formats = clipboard->clientFormats;
|
||||
return clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
||||
}
|
||||
|
||||
static void wfl_cliprdr_add_client_format_id(wfClipboard* clipboard, UINT32 formatId)
|
||||
{
|
||||
size_t x;
|
||||
CLIPRDR_FORMAT* format;
|
||||
const char* name = ClipboardGetFormatName(clipboard->system, formatId);
|
||||
|
||||
for (x = 0; x < clipboard->numClientFormats; x++)
|
||||
{
|
||||
format = &clipboard->clientFormats[x];
|
||||
|
||||
if (format->formatId == formatId)
|
||||
return;
|
||||
}
|
||||
|
||||
format = realloc(clipboard->clientFormats,
|
||||
(clipboard->numClientFormats + 1) * sizeof(CLIPRDR_FORMAT));
|
||||
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
clipboard->clientFormats = format;
|
||||
format = &clipboard->clientFormats[clipboard->numClientFormats++];
|
||||
format->formatId = formatId;
|
||||
format->formatName = NULL;
|
||||
|
||||
if (name && (formatId >= CF_MAX))
|
||||
format->formatName = _strdup(name);
|
||||
}
|
||||
|
||||
static void wlf_cliprdr_add_client_format(wfClipboard* clipboard, const char* mime)
|
||||
{
|
||||
if (wlf_mime_is_html(mime))
|
||||
{
|
||||
UINT32 formatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
|
||||
wfl_cliprdr_add_client_format_id(clipboard, formatId);
|
||||
}
|
||||
else if (wlf_mime_is_text(mime))
|
||||
{
|
||||
wfl_cliprdr_add_client_format_id(clipboard, CF_TEXT);
|
||||
wfl_cliprdr_add_client_format_id(clipboard, CF_OEMTEXT);
|
||||
wfl_cliprdr_add_client_format_id(clipboard, CF_UNICODETEXT);
|
||||
}
|
||||
else if (wlf_mime_is_image(mime))
|
||||
{
|
||||
UINT32 formatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
|
||||
wfl_cliprdr_add_client_format_id(clipboard, formatId);
|
||||
wfl_cliprdr_add_client_format_id(clipboard, CF_DIB);
|
||||
}
|
||||
|
||||
wlf_cliprdr_send_client_format_list(clipboard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_send_data_request(wfClipboard* clipboard,
|
||||
UINT32 formatId)
|
||||
{
|
||||
CLIPRDR_FORMAT_DATA_REQUEST request = { 0 };
|
||||
request.requestedFormatId = formatId;
|
||||
return clipboard->context->ClientFormatDataRequest(clipboard->context,
|
||||
&request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_send_data_response(wfClipboard* clipboard, const BYTE* data,
|
||||
size_t size)
|
||||
{
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
|
||||
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
|
||||
response.dataLen = size;
|
||||
response.requestedFormatData = data;
|
||||
return clipboard->context->ClientFormatDataResponse(clipboard->context,
|
||||
&response);
|
||||
}
|
||||
|
||||
BOOL wlf_cliprdr_handle_event(wfClipboard* clipboard, const UwacClipboardEvent* event)
|
||||
{
|
||||
if (!clipboard || !event)
|
||||
return FALSE;
|
||||
|
||||
if (!clipboard->context)
|
||||
return TRUE;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case UWAC_EVENT_CLIPBOARD_AVAILABLE:
|
||||
clipboard->seat = event->seat;
|
||||
return TRUE;
|
||||
|
||||
case UWAC_EVENT_CLIPBOARD_OFFER:
|
||||
WLog_Print(clipboard->log, WLOG_INFO, "client announces mime %s", event->mime);
|
||||
wlf_cliprdr_add_client_format(clipboard, event->mime);
|
||||
return TRUE;
|
||||
|
||||
case UWAC_EVENT_CLIPBOARD_SELECT:
|
||||
WLog_Print(clipboard->log, WLOG_DEBUG, "client announces new data");
|
||||
wlf_cliprdr_free_client_formats(clipboard);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_send_client_capabilities(wfClipboard* clipboard)
|
||||
{
|
||||
CLIPRDR_CAPABILITIES capabilities;
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
|
||||
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;
|
||||
|
||||
if (clipboard->streams_supported && clipboard->file_formats_registered)
|
||||
generalCapabilitySet.generalFlags |=
|
||||
CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS;
|
||||
|
||||
return clipboard->context->ClientCapabilities(clipboard->context,
|
||||
&capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_send_client_format_list_response(wfClipboard* clipboard,
|
||||
BOOL status)
|
||||
{
|
||||
CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
|
||||
formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE;
|
||||
formatListResponse.msgFlags = status ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
|
||||
formatListResponse.dataLen = 0;
|
||||
return clipboard->context->ClientFormatListResponse(clipboard->context,
|
||||
&formatListResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_monitor_ready(CliprdrClientContext* context,
|
||||
const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
wfClipboard* clipboard = (wfClipboard*) context->custom;
|
||||
UINT ret;
|
||||
|
||||
if ((ret = wlf_cliprdr_send_client_capabilities(clipboard)) != CHANNEL_RC_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = wlf_cliprdr_send_client_format_list(clipboard)) != CHANNEL_RC_OK)
|
||||
return ret;
|
||||
|
||||
clipboard->sync = TRUE;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_server_capabilities(CliprdrClientContext* context,
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
UINT32 i;
|
||||
const BYTE* capsPtr = (const BYTE*) capabilities->capabilitySets;
|
||||
wfClipboard* clipboard = (wfClipboard*) context->custom;
|
||||
clipboard->streams_supported = FALSE;
|
||||
|
||||
for (i = 0; i < capabilities->cCapabilitiesSets; i++)
|
||||
{
|
||||
const CLIPRDR_CAPABILITY_SET* caps = (const CLIPRDR_CAPABILITY_SET*) capsPtr;
|
||||
|
||||
if (caps->capabilitySetType == CB_CAPSTYPE_GENERAL)
|
||||
{
|
||||
const CLIPRDR_GENERAL_CAPABILITY_SET* generalCaps = (const CLIPRDR_GENERAL_CAPABILITY_SET*) caps;
|
||||
|
||||
if (generalCaps->generalFlags & CB_STREAM_FILECLIP_ENABLED)
|
||||
{
|
||||
clipboard->streams_supported = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
capsPtr += caps->capabilitySetLength;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static void wlf_cliprdr_transfer_data(UwacSeat* seat, void* context, const char* mime, int fd)
|
||||
{
|
||||
wfClipboard* clipboard = (wfClipboard*)context;
|
||||
size_t x;
|
||||
WINPR_UNUSED(seat);
|
||||
clipboard->responseMime = NULL;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_html); x++)
|
||||
{
|
||||
const char* mime_cur = mime_html[x];
|
||||
|
||||
if (strcmp(mime_cur, mime) == 0)
|
||||
{
|
||||
clipboard->responseMime = mime_cur;
|
||||
clipboard->responseFormat = ClipboardGetFormatId(clipboard->system, "HTML Format");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_text); x++)
|
||||
{
|
||||
const char* mime_cur = mime_text[x];
|
||||
|
||||
if (strcmp(mime_cur, mime) == 0)
|
||||
{
|
||||
clipboard->responseMime = mime_cur;
|
||||
clipboard->responseFormat = CF_UNICODETEXT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_image); x++)
|
||||
{
|
||||
const char* mime_cur = mime_image[x];
|
||||
|
||||
if (strcmp(mime_cur, mime) == 0)
|
||||
{
|
||||
clipboard->responseMime = mime_cur;
|
||||
clipboard->responseFormat = CF_DIB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clipboard->responseMime != NULL)
|
||||
{
|
||||
clipboard->responseFile = fdopen(fd, "w");
|
||||
|
||||
if (clipboard->responseFile)
|
||||
wlf_cliprdr_send_data_request(clipboard, clipboard->responseFormat);
|
||||
else
|
||||
WLog_Print(clipboard->log, WLOG_ERROR, "failed to open clipboard file descriptor for MIME %s",
|
||||
clipboard->responseMime);
|
||||
}
|
||||
}
|
||||
|
||||
static void wlf_cliprdr_cancel_data(UwacSeat* seat, void* context)
|
||||
{
|
||||
WINPR_UNUSED(seat);
|
||||
WINPR_UNUSED(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the clipboard changes server side.
|
||||
*
|
||||
* Clear the local clipboard offer and replace it with a new one
|
||||
* that announces the formats we get listed here.
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_server_format_list(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
UINT32 i;
|
||||
wfClipboard* clipboard;
|
||||
BOOL html = FALSE;
|
||||
BOOL text = FALSE;
|
||||
BOOL image = FALSE;
|
||||
|
||||
if (!context || !context->custom)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
clipboard = (wfClipboard*) context->custom;
|
||||
wlf_cliprdr_free_server_formats(clipboard);
|
||||
|
||||
if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(
|
||||
formatList->numFormats, sizeof(CLIPRDR_FORMAT))))
|
||||
{
|
||||
WLog_Print(clipboard->log, WLOG_ERROR, "failed to allocate %"PRIuz" CLIPRDR_FORMAT structs",
|
||||
clipboard->numServerFormats);
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
clipboard->numServerFormats = formatList->numFormats;
|
||||
|
||||
if (!clipboard->seat)
|
||||
{
|
||||
WLog_Print(clipboard->log, WLOG_ERROR, "clipboard->seat=NULL, check your client implementation");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < formatList->numFormats; i++)
|
||||
{
|
||||
const CLIPRDR_FORMAT* format = &formatList->formats[i];
|
||||
CLIPRDR_FORMAT* srvFormat = &clipboard->serverFormats[i];
|
||||
srvFormat->formatId = format->formatId;
|
||||
|
||||
if (format->formatName)
|
||||
{
|
||||
srvFormat->formatName = _strdup(format->formatName);
|
||||
|
||||
if (!srvFormat->formatName)
|
||||
{
|
||||
wlf_cliprdr_free_server_formats(clipboard);
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (format->formatName)
|
||||
{
|
||||
if (strcmp(format->formatName, "HTML Format") == 0)
|
||||
{
|
||||
text = TRUE;
|
||||
html = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (format->formatId)
|
||||
{
|
||||
case CF_TEXT:
|
||||
case CF_OEMTEXT:
|
||||
case CF_UNICODETEXT:
|
||||
text = TRUE;
|
||||
break;
|
||||
|
||||
case CF_DIB:
|
||||
image = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (html)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_html); x++)
|
||||
UwacClipboardOfferCreate(clipboard->seat, mime_html[x]);
|
||||
}
|
||||
|
||||
if (text)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_text); x++)
|
||||
UwacClipboardOfferCreate(clipboard->seat, mime_text[x]);
|
||||
}
|
||||
|
||||
if (image)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(mime_image); x++)
|
||||
UwacClipboardOfferCreate(clipboard->seat, mime_image[x]);
|
||||
}
|
||||
|
||||
UwacClipboardOfferAnnounce(clipboard->seat, clipboard, wlf_cliprdr_transfer_data,
|
||||
wlf_cliprdr_cancel_data);
|
||||
return wlf_cliprdr_send_client_format_list_response(clipboard, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_server_format_list_response(CliprdrClientContext*
|
||||
context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
//wfClipboard* clipboard = (wfClipboard*) context->custom;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
UINT rc;
|
||||
char* data;
|
||||
LPWSTR cdata;
|
||||
size_t size;
|
||||
const char* mime;
|
||||
UINT32 formatId = formatDataRequest->requestedFormatId;
|
||||
wfClipboard* clipboard = (wfClipboard*) context->custom;
|
||||
|
||||
switch (formatId)
|
||||
{
|
||||
case CF_TEXT:
|
||||
case CF_OEMTEXT:
|
||||
case CF_UNICODETEXT:
|
||||
mime = "text/plain;charset=utf-8";
|
||||
break;
|
||||
|
||||
case CF_DIB:
|
||||
case CF_DIBV5:
|
||||
mime = "image/bmp";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (formatId == ClipboardGetFormatId(clipboard->system, "HTML Format"))
|
||||
mime = "text/html";
|
||||
else if (formatId == ClipboardGetFormatId(clipboard->system, "image/bmp"))
|
||||
mime = "image/bmp";
|
||||
else
|
||||
mime = ClipboardGetFormatName(clipboard->system, formatId);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
data = UwacClipboardDataGet(clipboard->seat, mime, &size);
|
||||
|
||||
if (!data)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
switch (formatId)
|
||||
{
|
||||
case CF_UNICODETEXT:
|
||||
size = ConvertToUnicode(CP_UTF8, 0, data, size, &cdata, 0);
|
||||
free(data);
|
||||
data = cdata;
|
||||
size *= sizeof(WCHAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: Image conversions
|
||||
break;
|
||||
}
|
||||
|
||||
rc = wlf_cliprdr_send_data_response(clipboard, data, size);
|
||||
free(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wlf_cliprdr_server_format_data_response(CliprdrClientContext*
|
||||
context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
UINT rc = ERROR_INTERNAL_ERROR;
|
||||
BOOL freedata = FALSE;
|
||||
UINT32 size = formatDataResponse->dataLen;
|
||||
LPSTR data = formatDataResponse->requestedFormatData;
|
||||
const WCHAR* wdata = (WCHAR*)formatDataResponse->requestedFormatData;
|
||||
wfClipboard* clipboard = (wfClipboard*) context->custom;
|
||||
|
||||
switch (clipboard->responseFormat)
|
||||
{
|
||||
case CF_UNICODETEXT:
|
||||
size = ConvertFromUnicode(CP_UTF8, 0, wdata, size / sizeof(WCHAR), &data, 0, NULL, NULL);
|
||||
freedata = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO: Image conversions
|
||||
break;
|
||||
}
|
||||
|
||||
fwrite(data, 1, size, clipboard->responseFile);
|
||||
fclose(clipboard->responseFile);
|
||||
rc = CHANNEL_RC_OK;
|
||||
fail:
|
||||
|
||||
if (freedata)
|
||||
free(data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_server_file_size_request(wfClipboard* clipboard,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
wClipboardFileSizeRequest request = { 0 };
|
||||
request.streamId = fileContentsRequest->streamId;
|
||||
request.listIndex = fileContentsRequest->listIndex;
|
||||
|
||||
if (fileContentsRequest->cbRequested != sizeof(UINT64))
|
||||
{
|
||||
WLog_Print(clipboard->log, WLOG_WARN, "unexpected FILECONTENTS_SIZE request: %"PRIu32" bytes",
|
||||
fileContentsRequest->cbRequested);
|
||||
}
|
||||
|
||||
return clipboard->delegate->ClientRequestFileSize(clipboard->delegate, &request);
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_server_file_range_request(wfClipboard* clipboard,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
wClipboardFileRangeRequest request = { 0 };
|
||||
request.streamId = fileContentsRequest->streamId;
|
||||
request.listIndex = fileContentsRequest->listIndex;
|
||||
request.nPositionLow = fileContentsRequest->nPositionLow;
|
||||
request.nPositionHigh = fileContentsRequest->nPositionHigh;
|
||||
request.cbRequested = fileContentsRequest->cbRequested;
|
||||
return clipboard->delegate->ClientRequestFileRange(clipboard->delegate, &request);
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
response.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.streamId = fileContentsRequest->streamId;
|
||||
response.dwFlags = fileContentsRequest->dwFlags;
|
||||
return context->ClientFileContentsResponse(context, &response);
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
UINT error = NO_ERROR;
|
||||
wfClipboard* clipboard = context->custom;
|
||||
|
||||
/*
|
||||
* MS-RDPECLIP 2.2.5.3 File Contents Request PDU (CLIPRDR_FILECONTENTS_REQUEST):
|
||||
* The FILECONTENTS_SIZE and FILECONTENTS_RANGE flags MUST NOT be set at the same time.
|
||||
*/
|
||||
if ((fileContentsRequest->dwFlags & (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) ==
|
||||
(FILECONTENTS_SIZE | FILECONTENTS_RANGE))
|
||||
{
|
||||
WLog_Print(clipboard->log, WLOG_ERROR, "invalid CLIPRDR_FILECONTENTS_REQUEST.dwFlags");
|
||||
return wlf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
|
||||
}
|
||||
|
||||
if (fileContentsRequest->dwFlags & FILECONTENTS_SIZE)
|
||||
error = wlf_cliprdr_server_file_size_request(clipboard, fileContentsRequest);
|
||||
|
||||
if (fileContentsRequest->dwFlags & FILECONTENTS_RANGE)
|
||||
error = wlf_cliprdr_server_file_range_request(clipboard, fileContentsRequest);
|
||||
|
||||
if (error)
|
||||
{
|
||||
WLog_Print(clipboard->log, WLOG_ERROR, "failed to handle CLIPRDR_FILECONTENTS_REQUEST: 0x%08X",
|
||||
error);
|
||||
return wlf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
|
||||
const wClipboardFileSizeRequest* request, UINT64 fileSize)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
wfClipboard* clipboard = delegate->custom;
|
||||
response.msgFlags = CB_RESPONSE_OK;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_SIZE;
|
||||
response.cbRequested = sizeof(UINT64);
|
||||
response.requestedData = (BYTE*) &fileSize;
|
||||
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
|
||||
const wClipboardFileSizeRequest* request, UINT errorCode)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
wfClipboard* clipboard = delegate->custom;
|
||||
response.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_SIZE;
|
||||
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate,
|
||||
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
wfClipboard* clipboard = delegate->custom;
|
||||
response.msgFlags = CB_RESPONSE_OK;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_RANGE;
|
||||
response.cbRequested = size;
|
||||
response.requestedData = (BYTE*) data;
|
||||
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
|
||||
}
|
||||
|
||||
static UINT wlf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate,
|
||||
const wClipboardFileRangeRequest* request, UINT errorCode)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
wfClipboard* clipboard = delegate->custom;
|
||||
response.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_RANGE;
|
||||
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
|
||||
}
|
||||
|
||||
wfClipboard* wlf_clipboard_new(wlfContext* wfc)
|
||||
{
|
||||
rdpChannels* channels;
|
||||
wfClipboard* clipboard;
|
||||
|
||||
if (!(clipboard = (wfClipboard*) calloc(1, sizeof(wfClipboard))))
|
||||
return NULL;
|
||||
|
||||
clipboard->wfc = wfc;
|
||||
channels = wfc->context.channels;
|
||||
clipboard->log = WLog_Get(TAG);
|
||||
clipboard->channels = channels;
|
||||
clipboard->system = ClipboardCreate();
|
||||
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
|
||||
clipboard->delegate->custom = clipboard;
|
||||
clipboard->delegate->ClipboardFileSizeSuccess = wlf_cliprdr_clipboard_file_size_success;
|
||||
clipboard->delegate->ClipboardFileSizeFailure = wlf_cliprdr_clipboard_file_size_failure;
|
||||
clipboard->delegate->ClipboardFileRangeSuccess = wlf_cliprdr_clipboard_file_range_success;
|
||||
clipboard->delegate->ClipboardFileRangeFailure = wlf_cliprdr_clipboard_file_range_failure;
|
||||
return clipboard;
|
||||
error:
|
||||
wlf_clipboard_free(clipboard);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wlf_clipboard_free(wfClipboard* clipboard)
|
||||
{
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
wlf_cliprdr_free_server_formats(clipboard);
|
||||
wlf_cliprdr_free_client_formats(clipboard);
|
||||
ClipboardDestroy(clipboard->system);
|
||||
free(clipboard);
|
||||
}
|
||||
|
||||
BOOL wlf_cliprdr_init(wfClipboard* clipboard, CliprdrClientContext* cliprdr)
|
||||
{
|
||||
if (!cliprdr || !clipboard)
|
||||
return FALSE;
|
||||
|
||||
clipboard->context = cliprdr;
|
||||
cliprdr->custom = (void*) clipboard;
|
||||
cliprdr->MonitorReady = wlf_cliprdr_monitor_ready;
|
||||
cliprdr->ServerCapabilities = wlf_cliprdr_server_capabilities;
|
||||
cliprdr->ServerFormatList = wlf_cliprdr_server_format_list;
|
||||
cliprdr->ServerFormatListResponse = wlf_cliprdr_server_format_list_response;
|
||||
cliprdr->ServerFormatDataRequest = wlf_cliprdr_server_format_data_request;
|
||||
cliprdr->ServerFormatDataResponse = wlf_cliprdr_server_format_data_response;
|
||||
cliprdr->ServerFileContentsRequest = wlf_cliprdr_server_file_contents_request;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL wlf_cliprdr_uninit(wfClipboard* clipboard, CliprdrClientContext* cliprdr)
|
||||
{
|
||||
if (cliprdr)
|
||||
cliprdr->custom = NULL;
|
||||
|
||||
if (clipboard)
|
||||
clipboard->context = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Wayland Clipboard Redirection
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* 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_WAYLAND_CLIPRDR_H
|
||||
#define FREERDP_CLIENT_WAYLAND_CLIPRDR_H
|
||||
|
||||
#include "wlfreerdp.h"
|
||||
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
wfClipboard* wlf_clipboard_new(wlfContext* wlc);
|
||||
void wlf_clipboard_free(wfClipboard* clipboard);
|
||||
|
||||
BOOL wlf_cliprdr_init(wfClipboard* clipboard, CliprdrClientContext* cliprdr);
|
||||
BOOL wlf_cliprdr_uninit(wfClipboard* clipboard, CliprdrClientContext* cliprdr);
|
||||
|
||||
BOOL wlf_cliprdr_handle_event(wfClipboard* clipboard, const UwacClipboardEvent* event);
|
||||
|
||||
#endif /* FREERDP_CLIENT_WAYLAND_CLIPRDR_H */
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "wlfreerdp.h"
|
||||
#include "wlf_input.h"
|
||||
#include "wlf_cliprdr.h"
|
||||
#include "wlf_disp.h"
|
||||
#include "wlf_channels.h"
|
||||
|
||||
|
@ -232,6 +233,11 @@ static BOOL wl_post_connect(freerdp* instance)
|
|||
if (!(context->disp = wlf_disp_new(context)))
|
||||
return FALSE;
|
||||
|
||||
context->clipboard = wlf_clipboard_new(context);
|
||||
|
||||
if (!context->clipboard)
|
||||
return FALSE;
|
||||
|
||||
return wl_update_buffer(context, 0, 0, gdi->width, gdi->height);
|
||||
}
|
||||
|
||||
|
@ -247,6 +253,7 @@ static void wl_post_disconnect(freerdp* instance)
|
|||
|
||||
context = (wlfContext*) instance->context;
|
||||
gdi_free(instance);
|
||||
wlf_clipboard_free(context->clipboard);
|
||||
wlf_disp_free(context->disp);
|
||||
|
||||
if (context->window)
|
||||
|
@ -329,6 +336,14 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
|
|||
|
||||
break;
|
||||
|
||||
case UWAC_EVENT_CLIPBOARD_AVAILABLE:
|
||||
case UWAC_EVENT_CLIPBOARD_OFFER:
|
||||
case UWAC_EVENT_CLIPBOARD_SELECT:
|
||||
if (!wlf_cliprdr_handle_event(context->clipboard, &event.clipboard))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define TAG CLIENT_TAG("wayland")
|
||||
|
||||
typedef struct wlf_context wlfContext;
|
||||
typedef struct wlf_clipboard wfClipboard;
|
||||
typedef struct _wlfDispContext wlfDispContext;
|
||||
|
||||
struct wlf_context
|
||||
|
@ -49,6 +50,7 @@ struct wlf_context
|
|||
RdpeiClientContext* rdpei;
|
||||
RdpgfxClientContext* gfx;
|
||||
EncomspClientContext* encomsp;
|
||||
wfClipboard* clipboard;
|
||||
wlfDispContext* disp;
|
||||
wLog* log;
|
||||
};
|
||||
|
|
|
@ -1206,7 +1206,7 @@ static UINT cliprdr_send_tempdir(wfClipboard* clipboard)
|
|||
return clipboard->context->TempDirectory(clipboard->context, &tempDirectory);
|
||||
}
|
||||
|
||||
BOOL cliprdr_GetUpdatedClipboardFormats(wfClipboard* clipboard,
|
||||
static BOOL cliprdr_GetUpdatedClipboardFormats(wfClipboard* clipboard,
|
||||
PUINT lpuiFormats, UINT cFormats, PUINT pcFormatsOut)
|
||||
{
|
||||
UINT index = 0;
|
||||
|
@ -1861,7 +1861,7 @@ static UINT wf_cliprdr_send_client_capabilities(wfClipboard* clipboard)
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_cliprdr_monitor_ready(CliprdrClientContext* context,
|
||||
CLIPRDR_MONITOR_READY* monitorReady)
|
||||
const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
UINT rc;
|
||||
wfClipboard* clipboard = (wfClipboard*) context->custom;
|
||||
|
@ -1884,7 +1884,7 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_cliprdr_server_capabilities(CliprdrClientContext* context,
|
||||
CLIPRDR_CAPABILITIES* capabilities)
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
UINT32 index;
|
||||
CLIPRDR_CAPABILITY_SET* capabilitySet;
|
||||
|
@ -1916,7 +1916,7 @@ static UINT wf_cliprdr_server_capabilities(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_LIST* formatList)
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
UINT rc = ERROR_INTERNAL_ERROR;
|
||||
UINT32 i;
|
||||
|
@ -1989,7 +1989,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context,
|
|||
*/
|
||||
static UINT wf_cliprdr_server_format_list_response(CliprdrClientContext*
|
||||
context,
|
||||
CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
(void)context;
|
||||
(void)formatListResponse;
|
||||
|
@ -2006,7 +2006,7 @@ static UINT wf_cliprdr_server_format_list_response(CliprdrClientContext*
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_cliprdr_server_lock_clipboard_data(CliprdrClientContext* context,
|
||||
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
(void)context;
|
||||
(void)lockClipboardData;
|
||||
|
@ -2020,7 +2020,7 @@ static UINT wf_cliprdr_server_lock_clipboard_data(CliprdrClientContext* context,
|
|||
*/
|
||||
static UINT wf_cliprdr_server_unlock_clipboard_data(CliprdrClientContext*
|
||||
context,
|
||||
CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
(void)context;
|
||||
(void)unlockClipboardData;
|
||||
|
@ -2067,7 +2067,7 @@ static BOOL wf_cliprdr_process_filename(wfClipboard* clipboard,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT wf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
UINT rc;
|
||||
size_t size = 0;
|
||||
|
@ -2214,7 +2214,7 @@ static UINT wf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
|||
*/
|
||||
static UINT wf_cliprdr_server_format_data_response(CliprdrClientContext*
|
||||
context,
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
BYTE* data;
|
||||
HANDLE hMem;
|
||||
|
@ -2268,7 +2268,7 @@ static UINT wf_cliprdr_server_format_data_response(CliprdrClientContext*
|
|||
*/
|
||||
static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
||||
context,
|
||||
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
DWORD uSize = 0;
|
||||
BYTE* pData = NULL;
|
||||
|
@ -2282,6 +2282,7 @@ static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
|||
wfClipboard* clipboard;
|
||||
UINT rc = ERROR_INTERNAL_ERROR;
|
||||
UINT sRc;
|
||||
UINT32 cbRequested;
|
||||
|
||||
if (!context || !fileContentsRequest)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
@ -2291,10 +2292,11 @@ static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
|||
if (!clipboard)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
cbRequested = fileContentsRequest->cbRequested;
|
||||
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
||||
fileContentsRequest->cbRequested = sizeof(UINT64);
|
||||
cbRequested = sizeof(UINT64);
|
||||
|
||||
pData = (BYTE*) calloc(1, fileContentsRequest->cbRequested);
|
||||
pData = (BYTE*) calloc(1, cbRequested);
|
||||
|
||||
if (!pData)
|
||||
goto error;
|
||||
|
@ -2369,7 +2371,7 @@ static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
|||
{
|
||||
*((UINT32*) &pData[0]) = vStatStg.cbSize.LowPart;
|
||||
*((UINT32*) &pData[4]) = vStatStg.cbSize.HighPart;
|
||||
uSize = fileContentsRequest->cbRequested;
|
||||
uSize = cbRequested;
|
||||
}
|
||||
}
|
||||
else if (fileContentsRequest->dwFlags == FILECONTENTS_RANGE)
|
||||
|
@ -2381,7 +2383,7 @@ static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
|||
hRet = IStream_Seek(pStreamStc, dlibMove, STREAM_SEEK_SET, &dlibNewPosition);
|
||||
|
||||
if (SUCCEEDED(hRet))
|
||||
hRet = IStream_Read(pStreamStc, pData, fileContentsRequest->cbRequested,
|
||||
hRet = IStream_Read(pStreamStc, pData, cbRequested,
|
||||
(PULONG) &uSize);
|
||||
}
|
||||
}
|
||||
|
@ -2393,7 +2395,7 @@ static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
|||
clipboard->fileDescriptor[fileContentsRequest->listIndex]->nFileSizeLow;
|
||||
*((UINT32*) &pData[4]) =
|
||||
clipboard->fileDescriptor[fileContentsRequest->listIndex]->nFileSizeHigh;
|
||||
uSize = fileContentsRequest->cbRequested;
|
||||
uSize = cbRequested;
|
||||
}
|
||||
else if (fileContentsRequest->dwFlags == FILECONTENTS_RANGE)
|
||||
{
|
||||
|
@ -2401,7 +2403,7 @@ static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext*
|
|||
bRet = wf_cliprdr_get_file_contents(
|
||||
clipboard->file_names[fileContentsRequest->listIndex], pData,
|
||||
fileContentsRequest->nPositionLow, fileContentsRequest->nPositionHigh,
|
||||
fileContentsRequest->cbRequested, &uSize);
|
||||
cbRequested, &uSize);
|
||||
|
||||
if (bRet == FALSE)
|
||||
{
|
||||
|
@ -2442,7 +2444,7 @@ error:
|
|||
*/
|
||||
static UINT wf_cliprdr_server_file_contents_response(CliprdrClientContext*
|
||||
context,
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
wfClipboard* clipboard;
|
||||
|
||||
|
|
|
@ -266,8 +266,7 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_server_format_by_atom(
|
|||
static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard,
|
||||
UINT32 formatId)
|
||||
{
|
||||
CLIPRDR_FORMAT_DATA_REQUEST request;
|
||||
ZeroMemory(&request, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
|
||||
CLIPRDR_FORMAT_DATA_REQUEST request = { 0 };
|
||||
request.requestedFormatId = formatId;
|
||||
return clipboard->context->ClientFormatDataRequest(clipboard->context,
|
||||
&request);
|
||||
|
@ -281,8 +280,7 @@ static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard,
|
|||
static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data,
|
||||
int size)
|
||||
{
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE response;
|
||||
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
|
||||
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
|
||||
response.dataLen = size;
|
||||
response.requestedFormatData = data;
|
||||
|
@ -545,9 +543,8 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
|
|||
{
|
||||
UINT32 numFormats = 0;
|
||||
CLIPRDR_FORMAT* formats = NULL;
|
||||
CLIPRDR_FORMAT_LIST formatList;
|
||||
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
||||
formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
|
||||
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
|
||||
formatList.msgFlags = CB_RESPONSE_OK;
|
||||
formatList.numFormats = numFormats;
|
||||
formatList.formats = formats;
|
||||
|
@ -1096,10 +1093,9 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
|
|||
{
|
||||
UINT32 i, numFormats;
|
||||
CLIPRDR_FORMAT* formats = NULL;
|
||||
CLIPRDR_FORMAT_LIST formatList;
|
||||
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
||||
xfContext* xfc = clipboard->xfc;
|
||||
UINT ret;
|
||||
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
|
||||
numFormats = clipboard->numClientFormats;
|
||||
|
||||
if (numFormats)
|
||||
|
@ -1155,7 +1151,7 @@ static UINT xf_cliprdr_send_client_format_list_response(xfClipboard* clipboard,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT xf_cliprdr_monitor_ready(CliprdrClientContext* context,
|
||||
CLIPRDR_MONITOR_READY* monitorReady)
|
||||
const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
xfClipboard* clipboard = (xfClipboard*) context->custom;
|
||||
UINT ret;
|
||||
|
@ -1176,7 +1172,7 @@ static UINT xf_cliprdr_monitor_ready(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
|
||||
CLIPRDR_CAPABILITIES* capabilities)
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
UINT32 i;
|
||||
const CLIPRDR_CAPABILITY_SET* caps;
|
||||
|
@ -1211,7 +1207,7 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_LIST* formatList)
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
UINT32 i;
|
||||
int j;
|
||||
|
@ -1301,7 +1297,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext*
|
||||
context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
//xfClipboard* clipboard = (xfClipboard*) context->custom;
|
||||
return CHANNEL_RC_OK;
|
||||
|
@ -1313,7 +1309,7 @@ static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext*
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
||||
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
BOOL rawTransfer;
|
||||
xfCliprdrFormat* format = NULL;
|
||||
|
@ -1348,7 +1344,7 @@ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
|||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
|
||||
context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
BOOL bSuccess;
|
||||
BYTE* pDstData;
|
||||
|
@ -1477,8 +1473,7 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
|
|||
static UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
wClipboardFileSizeRequest request;
|
||||
ZeroMemory(&request, sizeof(request));
|
||||
wClipboardFileSizeRequest request = { 0 };
|
||||
request.streamId = fileContentsRequest->streamId;
|
||||
request.listIndex = fileContentsRequest->listIndex;
|
||||
|
||||
|
@ -1494,8 +1489,7 @@ static UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard,
|
|||
static UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
wClipboardFileRangeRequest request;
|
||||
ZeroMemory(&request, sizeof(request));
|
||||
wClipboardFileRangeRequest request = { 0 };
|
||||
request.streamId = fileContentsRequest->streamId;
|
||||
request.listIndex = fileContentsRequest->listIndex;
|
||||
request.nPositionLow = fileContentsRequest->nPositionLow;
|
||||
|
@ -1507,8 +1501,7 @@ static UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard,
|
|||
static UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
||||
ZeroMemory(&response, sizeof(response));
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
response.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.streamId = fileContentsRequest->streamId;
|
||||
response.dwFlags = fileContentsRequest->dwFlags;
|
||||
|
@ -1516,7 +1509,7 @@ static UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
|
|||
}
|
||||
|
||||
static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
|
||||
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
UINT error = NO_ERROR;
|
||||
xfClipboard* clipboard = context->custom;
|
||||
|
@ -1550,9 +1543,8 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex
|
|||
static UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
|
||||
const wClipboardFileSizeRequest* request, UINT64 fileSize)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
xfClipboard* clipboard = delegate->custom;
|
||||
ZeroMemory(&response, sizeof(response));
|
||||
response.msgFlags = CB_RESPONSE_OK;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_SIZE;
|
||||
|
@ -1564,9 +1556,8 @@ static UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
|
|||
static UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
|
||||
const wClipboardFileSizeRequest* request, UINT errorCode)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
xfClipboard* clipboard = delegate->custom;
|
||||
ZeroMemory(&response, sizeof(response));
|
||||
response.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_SIZE;
|
||||
|
@ -1576,9 +1567,8 @@ static UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
|
|||
static UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate,
|
||||
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
xfClipboard* clipboard = delegate->custom;
|
||||
ZeroMemory(&response, sizeof(response));
|
||||
response.msgFlags = CB_RESPONSE_OK;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_RANGE;
|
||||
|
@ -1590,9 +1580,8 @@ static UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate
|
|||
static UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate,
|
||||
const wClipboardFileRangeRequest* request, UINT errorCode)
|
||||
{
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response;
|
||||
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
|
||||
xfClipboard* clipboard = delegate->custom;
|
||||
ZeroMemory(&response, sizeof(response));
|
||||
response.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.streamId = request->streamId;
|
||||
response.dwFlags = FILECONTENTS_RANGE;
|
||||
|
|
|
@ -34,26 +34,26 @@
|
|||
|
||||
typedef struct _cliprdr_client_context CliprdrClientContext;
|
||||
|
||||
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
|
||||
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
|
||||
typedef UINT (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady);
|
||||
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext* context, CLIPRDR_TEMP_DIRECTORY* tempDirectory);
|
||||
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
|
||||
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
|
||||
typedef UINT (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||
typedef UINT (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||
typedef UINT (*pcCliprdrClientLockClipboardData)(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
|
||||
typedef UINT (*pcCliprdrServerLockClipboardData)(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
|
||||
typedef UINT (*pcCliprdrClientUnlockClipboardData)(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
|
||||
typedef UINT (*pcCliprdrServerUnlockClipboardData)(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
|
||||
typedef UINT (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||
typedef UINT (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||
typedef UINT (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||
typedef UINT (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||
typedef UINT (*pcCliprdrClientFileContentsRequest)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
|
||||
typedef UINT (*pcCliprdrServerFileContentsRequest)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
|
||||
typedef UINT (*pcCliprdrClientFileContentsResponse)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
|
||||
typedef UINT (*pcCliprdrServerFileContentsResponse)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
|
||||
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, const CLIPRDR_CAPABILITIES* capabilities);
|
||||
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, const CLIPRDR_CAPABILITIES* capabilities);
|
||||
typedef UINT (*pcCliprdrMonitorReady)(CliprdrClientContext* context, const CLIPRDR_MONITOR_READY* monitorReady);
|
||||
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext* context, const CLIPRDR_TEMP_DIRECTORY* tempDirectory);
|
||||
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST* formatList);
|
||||
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST* formatList);
|
||||
typedef UINT (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||
typedef UINT (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||
typedef UINT (*pcCliprdrClientLockClipboardData)(CliprdrClientContext* context, const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
|
||||
typedef UINT (*pcCliprdrServerLockClipboardData)(CliprdrClientContext* context, const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
|
||||
typedef UINT (*pcCliprdrClientUnlockClipboardData)(CliprdrClientContext* context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
|
||||
typedef UINT (*pcCliprdrServerUnlockClipboardData)(CliprdrClientContext* context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
|
||||
typedef UINT (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||
typedef UINT (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||
typedef UINT (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||
typedef UINT (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||
typedef UINT (*pcCliprdrClientFileContentsRequest)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
|
||||
typedef UINT (*pcCliprdrServerFileContentsRequest)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
|
||||
typedef UINT (*pcCliprdrClientFileContentsResponse)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
|
||||
typedef UINT (*pcCliprdrServerFileContentsResponse)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
|
||||
|
||||
struct _cliprdr_client_context
|
||||
{
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
#define UWAC_API __attribute__ ((visibility("default")))
|
||||
#define UWAC_API __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define UWAC_API
|
||||
#define UWAC_API
|
||||
#endif
|
||||
|
||||
typedef struct uwac_size UwacSize;
|
||||
|
@ -41,7 +41,8 @@ typedef uint32_t UwacSeatId;
|
|||
|
||||
|
||||
/** @brief error codes */
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
UWAC_SUCCESS = 0,
|
||||
UWAC_ERROR_NOMEMORY,
|
||||
UWAC_ERROR_UNABLE_TO_CONNECT,
|
||||
|
@ -56,21 +57,24 @@ typedef enum {
|
|||
} UwacReturnCode;
|
||||
|
||||
/** @brief input modifiers */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
UWAC_MOD_SHIFT_MASK = 0x01,
|
||||
UWAC_MOD_ALT_MASK = 0x02,
|
||||
UWAC_MOD_CONTROL_MASK = 0x04,
|
||||
};
|
||||
|
||||
/** @brief a rectangle size measure */
|
||||
struct uwac_size {
|
||||
struct uwac_size
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
|
||||
/** @brief event types */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
UWAC_EVENT_NEW_SEAT = 0,
|
||||
UWAC_EVENT_REMOVED_SEAT,
|
||||
UWAC_EVENT_NEW_OUTPUT,
|
||||
|
@ -90,91 +94,105 @@ enum {
|
|||
UWAC_EVENT_TOUCH_FRAME_END,
|
||||
UWAC_EVENT_FRAME_DONE,
|
||||
UWAC_EVENT_CLOSE,
|
||||
UWAC_EVENT_CLIPBOARD_AVAILABLE,
|
||||
UWAC_EVENT_CLIPBOARD_SELECT,
|
||||
UWAC_EVENT_CLIPBOARD_OFFER,
|
||||
};
|
||||
|
||||
/** @brief window states */
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
UWAC_WINDOW_MAXIMIZED = 0x1,
|
||||
UWAC_WINDOW_RESIZING = 0x2,
|
||||
UWAC_WINDOW_FULLSCREEN = 0x4,
|
||||
UWAC_WINDOW_ACTIVATED = 0x8,
|
||||
};
|
||||
|
||||
struct uwac_new_output_event {
|
||||
struct uwac_new_output_event
|
||||
{
|
||||
int type;
|
||||
UwacOutput *output;
|
||||
UwacOutput* output;
|
||||
};
|
||||
typedef struct uwac_new_output_event UwacOutputNewEvent;
|
||||
|
||||
struct uwac_new_seat_event {
|
||||
struct uwac_new_seat_event
|
||||
{
|
||||
int type;
|
||||
UwacSeat *seat;
|
||||
UwacSeat* seat;
|
||||
};
|
||||
typedef struct uwac_new_seat_event UwacSeatNewEvent;
|
||||
|
||||
|
||||
struct uwac_removed_seat_event {
|
||||
struct uwac_removed_seat_event
|
||||
{
|
||||
int type;
|
||||
UwacSeatId id;
|
||||
};
|
||||
typedef struct uwac_removed_seat_event UwacSeatRemovedEvent;
|
||||
|
||||
struct uwac_keyboard_enter_event {
|
||||
struct uwac_keyboard_enter_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
};
|
||||
typedef struct uwac_keyboard_enter_event UwacKeyboardEnterLeaveEvent;
|
||||
|
||||
struct uwac_pointer_enter_event {
|
||||
struct uwac_pointer_enter_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
uint32_t x, y;
|
||||
};
|
||||
typedef struct uwac_pointer_enter_event UwacPointerEnterLeaveEvent;
|
||||
|
||||
struct uwac_pointer_motion_event {
|
||||
struct uwac_pointer_motion_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
uint32_t x, y;
|
||||
};
|
||||
typedef struct uwac_pointer_motion_event UwacPointerMotionEvent;
|
||||
|
||||
struct uwac_pointer_button_event {
|
||||
struct uwac_pointer_button_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
uint32_t x, y;
|
||||
uint32_t button;
|
||||
enum wl_pointer_button_state state;
|
||||
};
|
||||
typedef struct uwac_pointer_button_event UwacPointerButtonEvent;
|
||||
|
||||
struct uwac_pointer_axis_event {
|
||||
struct uwac_pointer_axis_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
uint32_t x, y;
|
||||
uint32_t axis;
|
||||
wl_fixed_t value;
|
||||
};
|
||||
typedef struct uwac_pointer_axis_event UwacPointerAxisEvent;
|
||||
|
||||
struct uwac_touch_frame_event {
|
||||
struct uwac_touch_frame_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
};
|
||||
typedef struct uwac_touch_frame_event UwacTouchFrameBegin;
|
||||
typedef struct uwac_touch_frame_event UwacTouchFrameEnd;
|
||||
typedef struct uwac_touch_frame_event UwacTouchCancel;
|
||||
|
||||
struct uwac_touch_data {
|
||||
struct uwac_touch_data
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
UwacWindow* window;
|
||||
UwacSeat* seat;
|
||||
int32_t id;
|
||||
wl_fixed_t x;
|
||||
wl_fixed_t y;
|
||||
|
@ -183,39 +201,51 @@ typedef struct uwac_touch_data UwacTouchUp;
|
|||
typedef struct uwac_touch_data UwacTouchDown;
|
||||
typedef struct uwac_touch_data UwacTouchMotion;
|
||||
|
||||
struct uwac_frame_done_event {
|
||||
struct uwac_frame_done_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacWindow* window;
|
||||
};
|
||||
typedef struct uwac_frame_done_event UwacFrameDoneEvent;
|
||||
|
||||
struct uwac_configure_event {
|
||||
struct uwac_configure_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacWindow* window;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int states;
|
||||
};
|
||||
typedef struct uwac_configure_event UwacConfigureEvent;
|
||||
|
||||
struct uwac_key_event {
|
||||
struct uwac_key_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacWindow* window;
|
||||
uint32_t raw_key;
|
||||
uint32_t sym;
|
||||
bool pressed;
|
||||
};
|
||||
typedef struct uwac_key_event UwacKeyEvent;
|
||||
|
||||
struct uwac_close_event {
|
||||
struct uwac_close_event
|
||||
{
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacWindow* window;
|
||||
};
|
||||
typedef struct uwac_close_event UwacCloseEvent;
|
||||
|
||||
struct uwac_clipboard_event
|
||||
{
|
||||
int type;
|
||||
UwacSeat* seat;
|
||||
char mime[64];
|
||||
};
|
||||
typedef struct uwac_clipboard_event UwacClipboardEvent;
|
||||
|
||||
/** @brief */
|
||||
union uwac_event {
|
||||
union uwac_event
|
||||
{
|
||||
int type;
|
||||
UwacOutputNewEvent output_new;
|
||||
UwacSeatNewEvent seat_new;
|
||||
|
@ -225,6 +255,7 @@ union uwac_event {
|
|||
UwacPointerButtonEvent mouse_button;
|
||||
UwacPointerAxisEvent mouse_axis;
|
||||
UwacKeyboardEnterLeaveEvent keyboard_enter_leave;
|
||||
UwacClipboardEvent clipboard;
|
||||
UwacKeyEvent key;
|
||||
UwacTouchFrameBegin touchFrameBegin;
|
||||
UwacTouchUp touchUp;
|
||||
|
@ -238,7 +269,9 @@ union uwac_event {
|
|||
};
|
||||
typedef union uwac_event UwacEvent;
|
||||
|
||||
typedef bool (*UwacErrorHandler)(UwacDisplay *d, UwacReturnCode code, const char *msg, ...);
|
||||
typedef bool (*UwacErrorHandler)(UwacDisplay* d, UwacReturnCode code, const char* msg, ...);
|
||||
typedef void (*UwacDataTransferHandler)(UwacSeat* seat, void* context, const char* mime, int fd);
|
||||
typedef void (*UwacCancelDataTransferHandler)(UwacSeat* seat, void* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -261,7 +294,7 @@ UWAC_API void UwacInstallErrorHandler(UwacErrorHandler handler);
|
|||
* @param name the name of the display to open
|
||||
* @return the created UwacDisplay object
|
||||
*/
|
||||
UWAC_API UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err);
|
||||
UWAC_API UwacDisplay* UwacOpenDisplay(const char* name, UwacReturnCode* err);
|
||||
|
||||
/**
|
||||
* closes the corresponding UwacDisplay
|
||||
|
@ -269,7 +302,7 @@ UWAC_API UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err);
|
|||
* @param pdisplay a pointer on the display to close
|
||||
* @return UWAC_SUCCESS if the operation was successful, the corresponding error otherwise
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay);
|
||||
UWAC_API UwacReturnCode UwacCloseDisplay(UwacDisplay** pdisplay);
|
||||
|
||||
/**
|
||||
* Returns the file descriptor associated with the UwacDisplay, this is useful when
|
||||
|
@ -278,7 +311,7 @@ UWAC_API UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay);
|
|||
* @param display an opened UwacDisplay
|
||||
* @return the corresponding descriptor
|
||||
*/
|
||||
UWAC_API int UwacDisplayGetFd(UwacDisplay *display);
|
||||
UWAC_API int UwacDisplayGetFd(UwacDisplay* display);
|
||||
|
||||
/**
|
||||
* Returns a human readable form of a Uwac error code
|
||||
|
@ -286,7 +319,7 @@ UWAC_API int UwacDisplayGetFd(UwacDisplay *display);
|
|||
* @param error the error number
|
||||
* @return the associated string
|
||||
*/
|
||||
UWAC_API const char *UwacErrorString(UwacReturnCode error);
|
||||
UWAC_API const char* UwacErrorString(UwacReturnCode error);
|
||||
|
||||
/**
|
||||
* returns the last error that occurred on a display
|
||||
|
@ -294,7 +327,7 @@ UWAC_API const char *UwacErrorString(UwacReturnCode error);
|
|||
* @param display the display
|
||||
* @return the last error that have been set for this display
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display);
|
||||
UWAC_API UwacReturnCode UwacDisplayGetLastError(const UwacDisplay* display);
|
||||
|
||||
/**
|
||||
* retrieves the version of a given interface
|
||||
|
@ -304,7 +337,8 @@ UWAC_API UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display);
|
|||
* @param version the output variable for the version
|
||||
* @return UWAC_SUCCESS if the interface was found, UWAC_NOT_FOUND otherwise
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version);
|
||||
UWAC_API UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay* display,
|
||||
const char* name, uint32_t* version);
|
||||
|
||||
/**
|
||||
* returns the number SHM formats that have been reported by the compositor
|
||||
|
@ -312,7 +346,7 @@ UWAC_API UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *disp
|
|||
* @param display a connected UwacDisplay
|
||||
* @return the number of SHM formats supported
|
||||
*/
|
||||
UWAC_API uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display);
|
||||
UWAC_API uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay* display);
|
||||
|
||||
/**
|
||||
* returns the supported ShmFormats
|
||||
|
@ -323,7 +357,8 @@ UWAC_API uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display);
|
|||
* @param filled the number of filled entries in the formats array
|
||||
* @return UWAC_SUCCESS on success, an error otherwise
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled);
|
||||
UWAC_API UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay* display,
|
||||
enum wl_shm_format* formats, int formats_size, int* filled);
|
||||
|
||||
/**
|
||||
* returns the number of registered outputs
|
||||
|
@ -331,7 +366,7 @@ UWAC_API UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, e
|
|||
* @param display the display to query
|
||||
* @return the number of outputs
|
||||
*/
|
||||
UWAC_API uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display);
|
||||
UWAC_API uint32_t UwacDisplayGetNbOutputs(UwacDisplay* display);
|
||||
|
||||
/**
|
||||
* retrieve a particular UwacOutput object
|
||||
|
@ -340,7 +375,7 @@ UWAC_API uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display);
|
|||
* @param index index of the output
|
||||
* @return the given UwacOutput, NULL if something failed (so you should query UwacDisplayGetLastError() to have the reason)
|
||||
*/
|
||||
UWAC_API UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index);
|
||||
UWAC_API UwacOutput* UwacDisplayGetOutput(UwacDisplay* display, int index);
|
||||
|
||||
/**
|
||||
* retrieve the resolution of a given UwacOutput
|
||||
|
@ -349,7 +384,7 @@ UWAC_API UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index);
|
|||
* @param resolution a pointer on the
|
||||
* @return UWAC_SUCCESS on success
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution);
|
||||
UWAC_API UwacReturnCode UwacOutputGetResolution(UwacOutput* output, UwacSize* resolution);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -361,7 +396,8 @@ UWAC_API UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *re
|
|||
* @param format format to use for the SHM surface
|
||||
* @return the created UwacWindow, NULL if something failed (use UwacDisplayGetLastError() to know more about this)
|
||||
*/
|
||||
UWAC_API UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format);
|
||||
UWAC_API UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t height,
|
||||
enum wl_shm_format format);
|
||||
|
||||
/**
|
||||
* destroys the corresponding UwacWindow
|
||||
|
@ -369,7 +405,7 @@ UWAC_API UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, u
|
|||
* @param window a pointer on the UwacWindow to destroy
|
||||
* @return if the operation completed successfully
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacDestroyWindow(UwacWindow **window);
|
||||
UWAC_API UwacReturnCode UwacDestroyWindow(UwacWindow** window);
|
||||
|
||||
/**
|
||||
* Sets the region that should be considered opaque to the compositor.
|
||||
|
@ -381,7 +417,8 @@ UWAC_API UwacReturnCode UwacDestroyWindow(UwacWindow **window);
|
|||
* @param height
|
||||
* @return UWAC_SUCCESS on success, an error otherwise
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
UWAC_API UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow* window, uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Sets the region of the window that can trigger input events
|
||||
|
@ -393,14 +430,15 @@ UWAC_API UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x
|
|||
* @param height
|
||||
* @return
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
UWAC_API UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* retrieves a pointer on the current window content to draw a frame
|
||||
* @param window the UwacWindow
|
||||
* @return a pointer on the current window content
|
||||
*/
|
||||
UWAC_API void *UwacWindowGetDrawingBuffer(UwacWindow *window);
|
||||
UWAC_API void* UwacWindowGetDrawingBuffer(UwacWindow* window);
|
||||
|
||||
/**
|
||||
* sets a rectangle as dirty for the next frame of a window
|
||||
|
@ -412,7 +450,8 @@ UWAC_API void *UwacWindowGetDrawingBuffer(UwacWindow *window);
|
|||
* @param height the height of the dirty rectangle
|
||||
* @return UWAC_SUCCESS on success, an Uwac error otherwise
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
UWAC_API UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Sends a frame to the compositor with the content of the drawing buffer
|
||||
|
@ -421,7 +460,7 @@ UWAC_API UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint
|
|||
* @param copyContentForNextFrame if true the content to display is copied in the next drawing buffer
|
||||
* @return UWAC_SUCCESS if the operation was successful
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame);
|
||||
UWAC_API UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame);
|
||||
|
||||
/**
|
||||
* returns the geometry of the given UwacWindows
|
||||
|
@ -430,7 +469,7 @@ UWAC_API UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyCont
|
|||
* @param geometry the geometry to fill
|
||||
* @return UWAC_SUCCESS on success, an Uwac error otherwise
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry);
|
||||
UWAC_API UwacReturnCode UwacWindowGetGeometry(UwacWindow* window, UwacSize* geometry);
|
||||
|
||||
/**
|
||||
* Sets or unset the fact that the window is set fullscreen. After this call the
|
||||
|
@ -442,7 +481,8 @@ UWAC_API UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geom
|
|||
* @param isFullscreen set or unset fullscreen
|
||||
* @return UWAC_SUCCESS if the operation was a success
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen);
|
||||
UWAC_API UwacReturnCode UwacWindowSetFullscreenState(UwacWindow* window, UwacOutput* output,
|
||||
bool isFullscreen);
|
||||
|
||||
/**
|
||||
* When possible (depending on the shell) sets the title of the UwacWindow
|
||||
|
@ -450,7 +490,7 @@ UWAC_API UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOut
|
|||
* @param window the UwacWindow
|
||||
* @param name title
|
||||
*/
|
||||
UWAC_API void UwacWindowSetTitle(UwacWindow *window, const char *name);
|
||||
UWAC_API void UwacWindowSetTitle(UwacWindow* window, const char* name);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -458,7 +498,7 @@ UWAC_API void UwacWindowSetTitle(UwacWindow *window, const char *name);
|
|||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
UWAC_API int UwacDisplayDispatch(UwacDisplay *display, int timeout);
|
||||
UWAC_API int UwacDisplayDispatch(UwacDisplay* display, int timeout);
|
||||
|
||||
/**
|
||||
* Returns if you have some pending events, and you can UwacNextEvent() without blocking
|
||||
|
@ -466,7 +506,7 @@ UWAC_API int UwacDisplayDispatch(UwacDisplay *display, int timeout);
|
|||
* @param display the UwacDisplay
|
||||
* @return if there's some pending events
|
||||
*/
|
||||
UWAC_API bool UwacHasEvent(UwacDisplay *display);
|
||||
UWAC_API bool UwacHasEvent(UwacDisplay* display);
|
||||
|
||||
/** Waits until an event occurs, and when it's there copy the event from the queue to
|
||||
* event.
|
||||
|
@ -475,8 +515,7 @@ UWAC_API bool UwacHasEvent(UwacDisplay *display);
|
|||
* @param event the event to fill
|
||||
* @return if the operation completed successfully
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event);
|
||||
|
||||
UWAC_API UwacReturnCode UwacNextEvent(UwacDisplay* display, UwacEvent* event);
|
||||
|
||||
/**
|
||||
* returns the name of the given UwacSeat
|
||||
|
@ -484,7 +523,7 @@ UWAC_API UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event);
|
|||
* @param seat the UwacSeat
|
||||
* @return the name of the seat
|
||||
*/
|
||||
UWAC_API const char *UwacSeatGetName(const UwacSeat *seat);
|
||||
UWAC_API const char* UwacSeatGetName(const UwacSeat* seat);
|
||||
|
||||
/**
|
||||
* returns the id of the given UwacSeat
|
||||
|
@ -492,7 +531,18 @@ UWAC_API const char *UwacSeatGetName(const UwacSeat *seat);
|
|||
* @param seat the UwacSeat
|
||||
* @return the id of the seat
|
||||
*/
|
||||
UWAC_API UwacSeatId UwacSeatGetId(const UwacSeat *seat);
|
||||
UWAC_API UwacSeatId UwacSeatGetId(const UwacSeat* seat);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UWAC_API UwacReturnCode UwacClipboardOfferDestroy(UwacSeat* seat);
|
||||
UWAC_API UwacReturnCode UwacClipboardOfferCreate(UwacSeat* seat, const char* mime);
|
||||
UWAC_API UwacReturnCode UwacClipboardOfferAnnounce(UwacSeat* seat,
|
||||
void* context,
|
||||
UwacDataTransferHandler transfer,
|
||||
UwacCancelDataTransferHandler cancel);
|
||||
UWAC_API void* UwacClipboardDataGet(UwacSeat* seat, const char* mime, size_t* size);
|
||||
|
||||
/**
|
||||
* Inhibits or restores keyboard shortcuts.
|
||||
|
|
|
@ -58,6 +58,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
${GENERATED_SOURCES}
|
||||
uwac-display.c
|
||||
uwac-input.c
|
||||
uwac-clipboard.c
|
||||
uwac-os.c
|
||||
uwac-os.h
|
||||
uwac-output.c
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Copyright © 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright © 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "uwac-priv.h"
|
||||
#include "uwac-utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
/* paste */
|
||||
static void data_offer_offer(void* data, struct wl_data_offer* data_offer,
|
||||
const char* offered_mime_type)
|
||||
{
|
||||
UwacSeat* seat = (UwacSeat*)data;
|
||||
|
||||
assert(seat);
|
||||
if (!seat->ignore_announcement)
|
||||
{
|
||||
UwacClipboardEvent* event = (UwacClipboardEvent*)UwacDisplayNewEvent(seat->display,
|
||||
UWAC_EVENT_CLIPBOARD_OFFER);
|
||||
|
||||
if (!event)
|
||||
{
|
||||
assert(uwacErrorHandler(seat->display, UWAC_ERROR_INTERNAL,
|
||||
"failed to allocate a clipboard event\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
event->seat = seat;
|
||||
sprintf_s(event->mime, sizeof(event->mime), "%s", offered_mime_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_data_offer_listener data_offer_listener =
|
||||
{
|
||||
.offer = data_offer_offer
|
||||
};
|
||||
|
||||
static void data_device_data_offer(void* data, struct wl_data_device* data_device,
|
||||
struct wl_data_offer* data_offer)
|
||||
{
|
||||
UwacSeat* seat = (UwacSeat*)data;
|
||||
|
||||
assert(seat);
|
||||
if (!seat->ignore_announcement)
|
||||
{
|
||||
UwacClipboardEvent* event = (UwacClipboardEvent*)UwacDisplayNewEvent(seat->display,
|
||||
UWAC_EVENT_CLIPBOARD_SELECT);
|
||||
|
||||
if (!event)
|
||||
{
|
||||
assert(uwacErrorHandler(seat->display, UWAC_ERROR_INTERNAL,
|
||||
"failed to allocate a close event\n"));
|
||||
}
|
||||
else
|
||||
event->seat = seat;
|
||||
|
||||
wl_data_offer_add_listener(data_offer, &data_offer_listener, data);
|
||||
seat->offer = data_offer;
|
||||
}
|
||||
else
|
||||
seat->offer = NULL;
|
||||
}
|
||||
|
||||
static void data_device_selection(void* data, struct wl_data_device* data_device,
|
||||
struct wl_data_offer* data_offer)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_data_device_listener data_device_listener =
|
||||
{
|
||||
.data_offer = data_device_data_offer,
|
||||
.selection = data_device_selection
|
||||
};
|
||||
|
||||
/* copy */
|
||||
static void data_source_target_handler(void* data, struct wl_data_source* data_source,
|
||||
const char* mime_type)
|
||||
{
|
||||
}
|
||||
|
||||
static void data_source_send_handler(void* data, struct wl_data_source* data_source,
|
||||
const char* mime_type, int fd)
|
||||
{
|
||||
UwacSeat* seat = (UwacSeat*)data;
|
||||
seat->transfer_data(seat, seat->data_context, mime_type, fd);
|
||||
}
|
||||
|
||||
static void data_source_cancelled_handler(void* data, struct wl_data_source* data_source)
|
||||
{
|
||||
UwacSeat* seat = (UwacSeat*)data;
|
||||
seat->cancel_data(seat, seat->data_context);
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener data_source_listener =
|
||||
{
|
||||
.target = data_source_target_handler,
|
||||
.send = data_source_send_handler,
|
||||
.cancelled = data_source_cancelled_handler
|
||||
};
|
||||
|
||||
static void UwacRegisterDeviceListener(UwacSeat* s)
|
||||
{
|
||||
wl_data_device_add_listener(s->data_device, &data_device_listener, s);
|
||||
}
|
||||
|
||||
UwacReturnCode UwacCreateDataSource(UwacSeat* s)
|
||||
{
|
||||
if (!s)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
s->data_source = wl_data_device_manager_create_data_source(s->display->data_device_manager);
|
||||
wl_data_source_add_listener(s->data_source, &data_source_listener, s);
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
UwacReturnCode UwacSeatRegisterClipboard(UwacSeat* s)
|
||||
{
|
||||
UwacReturnCode rc;
|
||||
UwacClipboardEvent* event;
|
||||
|
||||
if (!s)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
UwacRegisterDeviceListener(s);
|
||||
|
||||
rc = UwacCreateDataSource(s);
|
||||
|
||||
if (rc != UWAC_SUCCESS)
|
||||
return rc;
|
||||
|
||||
event = (UwacClipboardEvent*)UwacDisplayNewEvent(s->display, UWAC_EVENT_CLIPBOARD_AVAILABLE);
|
||||
|
||||
if (!event)
|
||||
{
|
||||
assert(uwacErrorHandler(s->display, UWAC_ERROR_INTERNAL,
|
||||
"failed to allocate a clipboard event\n"));
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
event->seat = s;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
UwacReturnCode UwacClipboardOfferDestroy(UwacSeat* seat)
|
||||
{
|
||||
if (!seat)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
if (seat->data_source)
|
||||
wl_data_source_destroy(seat->data_source);
|
||||
|
||||
return UwacCreateDataSource(seat);
|
||||
}
|
||||
|
||||
UwacReturnCode UwacClipboardOfferCreate(UwacSeat* seat, const char* mime)
|
||||
{
|
||||
if (!seat || !mime)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
wl_data_source_offer(seat->data_source, mime);
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
static void callback_done(void* data, struct wl_callback* callback, uint32_t serial)
|
||||
{
|
||||
*(uint32_t*)data = serial;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener callback_listener =
|
||||
{
|
||||
.done = callback_done
|
||||
};
|
||||
|
||||
uint32_t get_serial(UwacSeat* s)
|
||||
{
|
||||
struct wl_callback* callback;
|
||||
uint32_t serial = 0;
|
||||
callback = wl_display_sync(s->display->display);
|
||||
wl_callback_add_listener(callback, &callback_listener, &serial);
|
||||
|
||||
while (serial == 0)
|
||||
{
|
||||
wl_display_dispatch(s->display->display);
|
||||
}
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
UwacReturnCode UwacClipboardOfferAnnounce(UwacSeat* seat,
|
||||
void* context,
|
||||
UwacDataTransferHandler transfer,
|
||||
UwacCancelDataTransferHandler cancel)
|
||||
{
|
||||
if (!seat)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
seat->data_context = context;
|
||||
seat->transfer_data = transfer;
|
||||
seat->cancel_data = cancel;
|
||||
seat->ignore_announcement = true;
|
||||
wl_data_device_set_selection(seat->data_device, seat->data_source, get_serial(seat));
|
||||
wl_display_roundtrip(seat->display->display);
|
||||
seat->ignore_announcement = false;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
void* UwacClipboardDataGet(UwacSeat* seat, const char* mime, size_t* size)
|
||||
{
|
||||
ssize_t r = 0;
|
||||
size_t alloc = 0;
|
||||
size_t pos = 0;
|
||||
char* data = NULL;
|
||||
int pipefd[2];
|
||||
|
||||
if (!seat || !mime || !size || !seat->offer)
|
||||
return NULL;
|
||||
|
||||
if (pipe(pipefd) != 0)
|
||||
return NULL;
|
||||
|
||||
wl_data_offer_receive(seat->offer, mime, pipefd[1]);
|
||||
close(pipefd[1]);
|
||||
wl_display_roundtrip(seat->display->display);
|
||||
wl_display_flush(seat->display->display);
|
||||
|
||||
do
|
||||
{
|
||||
void* tmp;
|
||||
alloc += 1024;
|
||||
tmp = realloc(data, alloc);
|
||||
if (!tmp)
|
||||
{
|
||||
free(data);
|
||||
close(pipefd[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = tmp;
|
||||
r = read(pipefd[0], &data[pos], alloc - pos);
|
||||
if (r > 0)
|
||||
pos += r;
|
||||
if (r < 0)
|
||||
{
|
||||
free(data);
|
||||
close(pipefd[0]);
|
||||
return NULL;
|
||||
}
|
||||
} while(r > 0);
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
*size = pos + 1;
|
||||
return data;
|
||||
}
|
|
@ -191,6 +191,7 @@ static void registry_handle_global(void* data, struct wl_registry* registry, uin
|
|||
return;
|
||||
}
|
||||
|
||||
UwacSeatRegisterClipboard(seat);
|
||||
ev = (UwacSeatNewEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT);
|
||||
|
||||
if (!ev)
|
||||
|
@ -276,7 +277,6 @@ static void registry_handle_global_remove(void* data, struct wl_registry* regist
|
|||
if (strcmp(global->interface, "wl_seat") == 0)
|
||||
{
|
||||
UwacSeatRemovedEvent* ev;
|
||||
|
||||
display_destroy_seat(d, name);
|
||||
ev = (UwacSeatRemovedEvent*)UwacDisplayNewEvent(d, UWAC_EVENT_REMOVED_SEAT);
|
||||
|
||||
|
@ -727,7 +727,6 @@ bool UwacHasEvent(UwacDisplay* display)
|
|||
return display->pop_queue != NULL;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacNextEvent(UwacDisplay* display, UwacEvent* event)
|
||||
{
|
||||
UwacEventListItem* prevItem;
|
||||
|
|
|
@ -807,6 +807,7 @@ UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version) {
|
|||
goto error_watch_timerfd;
|
||||
}
|
||||
|
||||
ret->data_device = wl_data_device_manager_get_data_device(d->data_device_manager, ret->seat);
|
||||
wl_list_insert(d->seats.prev, &ret->link);
|
||||
return ret;
|
||||
|
||||
|
@ -864,6 +865,12 @@ void UwacSeatDestroy(UwacSeat *s) {
|
|||
wl_keyboard_destroy(s->keyboard);
|
||||
}
|
||||
|
||||
if (s->data_device)
|
||||
wl_data_device_destroy(s->data_device);
|
||||
|
||||
if (s->data_source)
|
||||
wl_data_source_destroy(s->data_source);
|
||||
|
||||
wl_list_remove(&s->link);
|
||||
free(s);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ struct uwac_display {
|
|||
struct wl_shell *shell;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct xdg_wm_base *xdg_base;
|
||||
struct wl_data_device_manager* devicemanager;
|
||||
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_inhibit_manager;
|
||||
struct zxdg_decoration_manager_v1 *deco_manager;
|
||||
struct org_kde_kwin_server_decoration_manager *kde_deco_manager;
|
||||
|
@ -154,9 +155,12 @@ struct uwac_seat {
|
|||
struct wl_seat *seat;
|
||||
uint32_t seat_id;
|
||||
uint32_t seat_version;
|
||||
struct wl_data_device* data_device;
|
||||
struct wl_data_source* data_source;
|
||||
struct wl_pointer *pointer;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct wl_touch *touch;
|
||||
struct wl_data_offer* offer;
|
||||
struct xkb_context *xkb_context;
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *keyboard_inhibitor;
|
||||
|
||||
|
@ -185,6 +189,11 @@ struct uwac_seat {
|
|||
UwacTask repeat_task;
|
||||
float sx, sy;
|
||||
struct wl_list link;
|
||||
|
||||
void* data_context;
|
||||
UwacDataTransferHandler transfer_data;
|
||||
UwacCancelDataTransferHandler cancel_data;
|
||||
bool ignore_announcement;
|
||||
};
|
||||
|
||||
|
||||
|
@ -246,4 +255,6 @@ void UwacSeatDestroy(UwacSeat *s);
|
|||
UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version);
|
||||
int UwacDestroyOutput(UwacOutput *output);
|
||||
|
||||
UwacReturnCode UwacSeatRegisterClipboard(UwacSeat* s);
|
||||
|
||||
#endif /* UWAC_PRIV_H_ */
|
||||
|
|
Loading…
Reference in New Issue