summaryrefslogtreecommitdiffstats
path: root/plugins/rdp/rdp_plugin.h
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/rdp/rdp_plugin.h')
-rw-r--r--plugins/rdp/rdp_plugin.h400
1 files changed, 400 insertions, 0 deletions
diff --git a/plugins/rdp/rdp_plugin.h b/plugins/rdp/rdp_plugin.h
new file mode 100644
index 0000000..a0f0cc7
--- /dev/null
+++ b/plugins/rdp/rdp_plugin.h
@@ -0,0 +1,400 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2010-2011 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#pragma once
+
+#include "common/remmina_plugin.h"
+#include <freerdp/freerdp.h>
+#include <freerdp/version.h>
+#include <freerdp/channels/channels.h>
+#include <freerdp/codec/color.h>
+#include <freerdp/codec/rfx.h>
+#include <freerdp/gdi/gdi.h>
+#include <freerdp/gdi/dc.h>
+#include <freerdp/gdi/region.h>
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/client/disp.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#elif defined(GDK_WINDOWING_WAYLAND)
+#include <gdk/gdkwayland.h>
+#endif
+
+#include <winpr/clipboard.h>
+
+/**
+ * FREERDP_CHECK_VERSION:
+ * @major: major version (e.g. 2 for version 2.1.0)
+ * @minor: minor version (e.g. 0 for version 2.1.0)
+ * @release: release version (e.g. 0 for version 2.1.0)
+ *
+ * Returns %TRUE if the version of the FRERDDP header files
+ * is the same as or newer than the passed-in version.
+ *
+ * Returns: %TRUE if FREERDP headers are new enough
+ */
+#define FREERDP_CHECK_VERSION(major,minor,revision) \
+ (FREERDP_VERSION_MAJOR > (major) || \
+ (FREERDP_VERSION_MAJOR == (major) && FREERDP_VERSION_MINOR > (minor)) || \
+ (FREERDP_VERSION_MAJOR == (major) && FREERDP_VERSION_MINOR == (minor) && \
+ FREERDP_VERSION_REVISION >= (revision)))
+
+/**
+ * Constants to workaround FreeRDP issue #5417 (min resolution in AVC mode)
+ * Must be 4 aligned (multiple of 4).
+ * We should instead check destRect and be sure the condition is met
+ * See https://gitlab.com/Remmina/Remmina/-/issues/2507 for a deep discussion
+ */
+#define AVC_MIN_DESKTOP_WIDTH 644
+#define AVC_MIN_DESKTOP_HEIGHT 480
+
+typedef struct rf_context rfContext;
+
+#define GET_PLUGIN_DATA(gp) (rfContext *)g_object_get_data(G_OBJECT(gp), "plugin-data")
+
+/**
+ * Performance Flags, from FreeRDP source
+ *
+ * PERF_FLAG_NONE 0x00000000
+ * PERF_DISABLE_WALLPAPER 0x00000001
+ * PERF_DISABLE_FULLWINDOWDRAG 0x00000002
+ * PERF_DISABLE_MENUANIMATIONS 0x00000004
+ * PERF_DISABLE_THEMING 0x00000008
+ * PERF_DISABLE_CURSOR_SHADOW 0x00000020
+ * PERF_DISABLE_CURSORSETTINGS 0x00000040
+ * PERF_ENABLE_FONT_SMOOTHING 0x00000080
+ * PERF_ENABLE_DESKTOP_COMPOSITION 0x00000100
+ */
+/* Poor (default) - all disabled */
+#define DEFAULT_QUALITY_0 0x6f
+/* Medium - only THEMING, CURSOR_SHADOW and CURSORSETTINGS enabled, all other disabled */
+#define DEFAULT_QUALITY_1 0x07
+/* Good - WALLPAPER, FONT_SMOOTHING, DESKTOP_COMPOSITION disabled, all other enabled */
+#define DEFAULT_QUALITY_2 0x01
+/* Best - DESKTOP_COMPOSITION disabled, all other enabled */
+#define DEFAULT_QUALITY_9 0x80
+
+extern RemminaPluginService *remmina_plugin_service;
+
+#define REMMINA_PLUGIN_INFO(fmt, ...) \
+ remmina_plugin_service->_remmina_info(__func__, fmt, ##__VA_ARGS__)
+
+#define REMMINA_PLUGIN_MESSAGE(fmt, ...) \
+ remmina_plugin_service->_remmina_message(__func, fmt, ##__VA_ARGS__)
+
+#define REMMINA_PLUGIN_DEBUG(fmt, ...) \
+ remmina_plugin_service->_remmina_debug(__func__, fmt, ##__VA_ARGS__)
+
+#define REMMINA_PLUGIN_WARNING(fmt, ...) \
+ remmina_plugin_service->_remmina_warning(__func__, fmt, ##__VA_ARGS__)
+
+/* This will intentionally crash Remmina */
+#define REMMINA_PLUGIN_ERROR(fmt, ...) \
+ remmina_plugin_service->_remmina_error(__func__, fmt, ##__VA_ARGS__)
+
+#define REMMINA_PLUGIN_CRITICAL(fmt, ...) \
+ remmina_plugin_service->_remmina_critical(__func__, fmt, ##__VA_ARGS__)
+#define REMMINA_PLUGIN_AUDIT(fmt, ...) \
+ remmina_plugin_service->_remmina_audit(__func__, fmt, ##__VA_ARGS__)
+
+struct rf_clipboard {
+ rfContext * rfi;
+ CliprdrClientContext * context;
+ wClipboard * system;
+ int requestedFormatId;
+
+ UINT32 format;
+ gulong clipboard_handler;
+
+ pthread_mutex_t transfer_clip_mutex;
+ pthread_cond_t transfer_clip_cond;
+ enum { SCDW_NONE, SCDW_BUSY_WAIT, SCDW_ABORTING } srv_clip_data_wait;
+ gpointer srv_data;
+ pthread_mutex_t srv_data_mutex;
+
+ UINT32 server_html_format_id;
+
+ /* Stats for clipboard download */
+ struct timeval clientformatdatarequest_tv;
+};
+typedef struct rf_clipboard rfClipboard;
+
+
+struct rf_pointer {
+ rdpPointer pointer;
+ GdkCursor * cursor;
+};
+typedef struct rf_pointer rfPointer;
+
+#ifdef RF_BITMAP
+struct rf_bitmap {
+ rdpBitmap bitmap;
+ Pixmap pixmap;
+ cairo_surface_t * surface;
+};
+typedef struct rf_bitmap rfBitmap;
+#endif
+
+#ifdef RF_GLYPH
+struct rf_glyph {
+ rdpGlyph glyph;
+ Pixmap pixmap;
+};
+typedef struct rf_glyph rfGlyph;
+#endif
+
+typedef enum {
+ REMMINA_RDP_EVENT_TYPE_SCANCODE,
+ REMMINA_RDP_EVENT_TYPE_SCANCODE_UNICODE,
+ REMMINA_RDP_EVENT_TYPE_MOUSE,
+ REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_LIST,
+ REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_DATA_RESPONSE,
+ REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_DATA_REQUEST,
+ REMMINA_RDP_EVENT_TYPE_SEND_MONITOR_LAYOUT,
+ REMMINA_RDP_EVENT_DISCONNECT
+} RemminaPluginRdpEventType;
+
+struct remmina_plugin_rdp_event {
+ RemminaPluginRdpEventType type;
+ union {
+ struct {
+ BOOL up;
+ BOOL extended;
+ UINT8 key_code;
+ UINT32 unicode_code;
+ BOOL extended1;
+ } key_event;
+ struct {
+ UINT16 flags;
+ UINT16 x;
+ UINT16 y;
+ BOOL extended;
+ } mouse_event;
+ struct {
+ CLIPRDR_FORMAT_LIST *pFormatList;
+ } clipboard_formatlist;
+ struct {
+ BYTE * data;
+ int size;
+ } clipboard_formatdataresponse;
+ struct {
+ CLIPRDR_FORMAT_DATA_REQUEST *pFormatDataRequest;
+ } clipboard_formatdatarequest;
+ struct {
+ gint Flags;
+ gint Left;
+ gint Top;
+ gint width;
+ gint height;
+ gint desktopOrientation;
+ gint desktopScaleFactor;
+ gint deviceScaleFactor;
+ gint physicalWidth;
+ gint physicalHeight;
+ } monitor_layout;
+ };
+};
+typedef struct remmina_plugin_rdp_event RemminaPluginRdpEvent;
+
+typedef enum {
+ REMMINA_RDP_UI_UPDATE_REGIONS = 0,
+ REMMINA_RDP_UI_CONNECTED,
+ REMMINA_RDP_UI_RECONNECT_PROGRESS,
+ REMMINA_RDP_UI_CURSOR,
+ REMMINA_RDP_UI_NOCODEC,
+ REMMINA_RDP_UI_CLIPBOARD,
+ REMMINA_RDP_UI_EVENT
+} RemminaPluginRdpUiType;
+
+typedef enum {
+ REMMINA_RDP_UI_CLIPBOARD_FORMATLIST,
+ REMMINA_RDP_UI_CLIPBOARD_GET_DATA,
+ REMMINA_RDP_UI_CLIPBOARD_SET_DATA
+} RemminaPluginRdpUiClipboardType;
+
+typedef enum {
+ REMMINA_RDP_POINTER_NEW,
+ REMMINA_RDP_POINTER_FREE,
+ REMMINA_RDP_POINTER_SET,
+ REMMINA_RDP_POINTER_NULL,
+ REMMINA_RDP_POINTER_DEFAULT,
+ REMMINA_RDP_POINTER_SETPOS
+} RemminaPluginRdpUiPointerType;
+
+typedef enum {
+ REMMINA_RDP_UI_EVENT_UPDATE_SCALE,
+ REMMINA_RDP_UI_EVENT_DESTROY_CAIRO_SURFACE
+} RemminaPluginRdpUiEeventType;
+
+typedef struct {
+ gint x, y, w, h;
+} region;
+
+struct remmina_plugin_rdp_ui_object {
+ RemminaPluginRdpUiType type;
+ gboolean sync;
+ gboolean complete;
+ pthread_mutex_t sync_wait_mutex;
+ pthread_cond_t sync_wait_cond;
+ union {
+ struct {
+ region *ureg;
+ gint ninvalid;
+ } reg;
+ struct {
+ rdpContext * context;
+ rfPointer * pointer;
+ RemminaPluginRdpUiPointerType type;
+ } cursor;
+ struct {
+ gint left;
+ gint top;
+ RFX_MESSAGE * message;
+ } rfx;
+ struct {
+ gint left;
+ gint top;
+ gint width;
+ gint height;
+ UINT8 * bitmap;
+ } nocodec;
+ struct {
+ RemminaPluginRdpUiClipboardType type;
+ GtkTargetList * targetlist;
+ UINT32 format;
+ rfClipboard * clipboard;
+ gpointer data;
+ } clipboard;
+ struct {
+ RemminaPluginRdpUiEeventType type;
+ } event;
+ struct {
+ gint x;
+ gint y;
+ } pos;
+ };
+ /* We can also return values here, usually integers*/
+ int retval;
+ /* Some functions also may return a pointer. */
+ void * retptr;
+};
+
+typedef struct remmina_plugin_rdp_keymap_entry {
+ unsigned orig_keycode;
+ unsigned translated_keycode;
+} RemminaPluginRdpKeymapEntry;
+
+struct rf_context {
+ rdpClientContext clientContext;
+
+ RemminaProtocolWidget *protocol_widget;
+
+ /* main */
+ pthread_t remmina_plugin_thread;
+ RemminaScaleMode scale;
+ gboolean user_cancelled;
+ gboolean thread_cancelled;
+
+ CliprdrClientContext * cliprdr;
+ DispClientContext * dispcontext;
+
+ RDP_PLUGIN_DATA rdpdr_data[5];
+ RDP_PLUGIN_DATA drdynvc_data[5];
+ gchar rdpsnd_options[20];
+
+ gboolean rdpgfxchan;
+
+ gboolean connected;
+ gboolean is_reconnecting;
+ gboolean stop_reconnecting_requested;
+ /* orphaned: rf_context has still one or more libfreerdp thread active,
+ * but no longer maintained by an open RemminaProtocolWidget/tab.
+ * When the orphaned thread terminates, we must cleanup rf_context.
+ */
+ gboolean orphaned;
+ int reconnect_maxattempts;
+ int reconnect_nattempt;
+
+ gboolean sw_gdi;
+ GtkWidget * drawing_area;
+ gint scale_width;
+ gint scale_height;
+ gdouble scale_x;
+ gdouble scale_y;
+ guint delayed_monitor_layout_handler;
+ gboolean use_client_keymap;
+
+ gint srcBpp;
+ GdkDisplay * display;
+ GdkVisual * visual;
+ cairo_surface_t * surface;
+ cairo_format_t cairo_format;
+ gint bpp;
+ gint scanline_pad;
+ gint * colormap;
+
+ guint object_id_seq;
+ GHashTable * object_table;
+
+ GAsyncQueue * ui_queue;
+ pthread_mutex_t ui_queue_mutex;
+ guint ui_handler;
+
+ GArray * pressed_keys;
+ GAsyncQueue * event_queue;
+ gint event_pipe[2];
+ HANDLE event_handle;
+ UINT16 last_x;
+ UINT16 last_y;
+
+ rfClipboard clipboard;
+
+ GArray * keymap; /* Array of RemminaPluginRdpKeymapEntry */
+
+ gboolean attempt_interactive_authentication;
+
+ enum { REMMINA_POSTCONNECT_ERROR_OK = 0, REMMINA_POSTCONNECT_ERROR_GDI_INIT = 1, REMMINA_POSTCONNECT_ERROR_NO_H264 } postconnect_error;
+};
+
+typedef struct remmina_plugin_rdp_ui_object RemminaPluginRdpUiObject;
+
+void rf_init(RemminaProtocolWidget *gp);
+void rf_uninit(RemminaProtocolWidget *gp);
+void rf_get_fds(RemminaProtocolWidget *gp, void **rfds, int *rcount);
+BOOL rf_check_fds(RemminaProtocolWidget *gp);
+void rf_object_free(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *obj);
+
+void remmina_rdp_event_event_push(RemminaProtocolWidget *gp, const RemminaPluginRdpEvent *e);