43 #include <gdk/gdkkeysyms.h> 44 #include <cairo/cairo-xlib.h> 45 #include <freerdp/locale/keyboard.h> 52 GdkModifierType state;
54 #if GTK_CHECK_VERSION(3, 20, 0) 57 GdkDeviceManager *manager;
59 GdkDevice *keyboard = NULL;
65 UINT32 toggle_keys_state = 0;
67 #if GTK_CHECK_VERSION(3, 20, 0) 68 seat = gdk_display_get_default_seat(gdk_display_get_default());
69 keyboard = gdk_seat_get_pointer(seat);
71 manager = gdk_display_get_device_manager(gdk_display_get_default());
72 keyboard = gdk_device_manager_get_client_pointer(manager);
74 gdk_window_get_device_position(gdk_get_default_root_window(), keyboard, NULL, NULL, &state);
76 if (state & GDK_LOCK_MASK) {
77 toggle_keys_state |= KBD_SYNC_CAPS_LOCK;
79 if (state & GDK_MOD2_MASK) {
80 toggle_keys_state |= KBD_SYNC_NUM_LOCK;
82 if (state & GDK_MOD5_MASK) {
83 toggle_keys_state |= KBD_SYNC_SCROLL_LOCK;
86 input->SynchronizeEvent(input, toggle_keys_state);
87 input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x0F);
114 TRACE_CALL(__func__);
135 TRACE_CALL(__func__);
161 TRACE_CALL(__func__);
177 TRACE_CALL(__func__);
188 if ((width == 0) || (height == 0))
193 *x = MIN(MAX(0, *x), width - 1);
194 *y = MIN(MAX(0, *y), height - 1);
195 *w = MIN(width - *x, *w);
196 *h = MIN(height - *y, *h);
222 TRACE_CALL(__func__);
226 for(i = 0; i < ui->
reg.ninvalid; i++) {
227 x = ui->
reg.ureg[i].x;
228 y = ui->
reg.ureg[i].y;
229 w = ui->
reg.ureg[i].w;
230 h = ui->
reg.ureg[i].h;
235 gtk_widget_queue_draw_area(rfi->
drawing_area, x, y, w, h);
237 g_free(ui->
reg.ureg);
242 TRACE_CALL(__func__);
248 gtk_widget_queue_draw_area(rfi->
drawing_area, x, y, w, h);
253 TRACE_CALL(__func__);
255 gint rdwidth, rdheight;
256 gint gpwidth, gpheight;
259 gtk_widget_get_allocation(GTK_WIDGET(gp), &a);
264 if ((gpwidth > 1) && (gpheight > 1)) {
285 TRACE_CALL(__func__);
289 cairo_text_extents_t extents;
298 width = gtk_widget_get_allocated_width(widget);
299 height = gtk_widget_get_allocated_height(widget);
302 msg = g_strdup_printf(_(
"Reconnection attempt %d of %d…"),
305 cairo_select_font_face(context,
"Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
306 cairo_set_font_size(context, 24);
307 cairo_set_source_rgb(context, 0.9, 0.9, 0.9);
308 cairo_text_extents(context, msg, &extents);
309 cairo_move_to(context, (width - (extents.width + extents.x_bearing)) / 2, (height - (extents.height + extents.y_bearing)) / 2);
310 cairo_show_text(context, msg);
322 cairo_set_source_surface(context, rfi->
surface, 0, 0);
324 cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
325 cairo_paint(context);
333 TRACE_CALL(__func__);
338 gint desktopOrientation, desktopScaleFactor, deviceScaleFactor;
347 gint gpwidth, gpheight, prevwidth, prevheight;
351 gtk_widget_get_allocation(GTK_WIDGET(gp), &a);
357 if ((gpwidth != prevwidth || gpheight != prevheight) &&
358 gpwidth >= 200 && gpwidth < 8192 &&
359 gpheight >= 200 && gpheight < 8192
363 if (gpwidth < AVC_MIN_DESKTOP_WIDTH)
364 gpwidth = AVC_MIN_DESKTOP_WIDTH;
365 if (gpheight < AVC_MIN_DESKTOP_HEIGHT)
366 gpheight = AVC_MIN_DESKTOP_HEIGHT;
383 TRACE_CALL(__func__);
399 TRACE_CALL(__func__);
417 TRACE_CALL(__func__);
439 TRACE_CALL(__func__);
461 TRACE_CALL(__func__);
476 TRACE_CALL(__func__);
478 gboolean extended = FALSE;
482 if ((event->type != GDK_BUTTON_PRESS) && (event->type != GDK_BUTTON_RELEASE))
487 switch (event->button) {
489 flag |= PTR_FLAGS_BUTTON1;
492 flag |= PTR_FLAGS_BUTTON3;
495 flag |= PTR_FLAGS_BUTTON2;
500 flag |= PTR_XFLAGS_BUTTON1;
505 flag |= PTR_XFLAGS_BUTTON2;
511 if (event->type == GDK_BUTTON_PRESS) {
513 flag |= PTR_XFLAGS_DOWN;
515 flag |= PTR_FLAGS_DOWN;
532 TRACE_CALL(__func__);
539 switch (event->direction) {
541 flag = PTR_FLAGS_WHEEL | 0x0078;
544 case GDK_SCROLL_DOWN:
545 flag = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
548 #ifdef GDK_SCROLL_SMOOTH 549 case GDK_SCROLL_SMOOTH:
550 if (event->delta_y < 0)
551 flag = PTR_FLAGS_WHEEL | 0x0078;
552 if (event->delta_y > 0)
553 flag = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
578 if (strmap == NULL || strmap[0] == 0) {
585 v1 = strtol(s, &endptr, 10);
586 if (endptr == s)
break;
588 if (*s !=
':')
break;
590 v2 = strtol(s, &endptr, 10);
591 if (endptr == s)
break;
595 g_array_append_val(rfi->
keymap, ke);
596 if (*s !=
',')
break;
599 if (rfi->
keymap->len == 0) {
600 g_array_unref(rfi->
keymap);
608 TRACE_CALL(__func__);
609 guint32 unicode_keyval;
610 guint16 hardware_keycode;
620 #ifdef ENABLE_GTK_INSPECTOR_KEY 623 if ( ( event->state & GDK_CONTROL_MASK ) != 0 && ( event->keyval == GDK_KEY_I || event->keyval == GDK_KEY_D ) ) {
629 rdp_event.
key_event.up = (
event->type == GDK_KEY_PRESS ? False : True);
632 switch (event->keyval) {
655 hardware_keycode =
event->hardware_keycode;
657 for(ik = 0; ik < rfi->
keymap->len; ik++) {
665 scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(hardware_keycode);
667 rdp_event.
key_event.key_code = scancode & 0xFF;
668 rdp_event.
key_event.extended = scancode & 0x100;
673 unicode_keyval = gdk_keyval_to_unicode(event->keyval);
682 if (event->keyval >= 0xfe00 ||
683 event->hardware_keycode == 0x41 ||
684 unicode_keyval == 0 ||
685 (event->state & (GDK_MOD1_MASK | GDK_CONTROL_MASK | GDK_SUPER_MASK)) != 0
687 scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(event->hardware_keycode);
688 rdp_event.
key_event.key_code = scancode & 0xFF;
689 rdp_event.
key_event.extended = scancode & 0x100;
696 rdp_event.
key_event.unicode_code = unicode_keyval;
711 TRACE_CALL(__func__);
713 CLIPRDR_FORMAT_LIST* pFormatList;
726 if (gtk_clipboard_get_owner(gtkClipboard) != (GObject*)gp) {
730 gtk_clipboard_get_owner(gtkClipboard), (GObject*)gp);
744 TRACE_CALL(__func__);
748 GtkClipboard* clipboard;
756 gtk_container_add(GTK_CONTAINER(gp), rfi->
drawing_area);
758 gtk_widget_add_events(rfi->
drawing_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
759 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_SCROLL_MASK | GDK_FOCUS_CHANGE_MASK);
772 fprintf(stderr,
"RDP profile error: you cannot define both rdp_map_hardware_keycode and have 'Use client keuboard mapping' enabled\n");
777 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"configure-event",
779 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"motion-notify-event",
781 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"button-press-event",
783 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"button-release-event",
785 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"scroll-event",
787 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"key-press-event",
789 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"key-release-event",
791 g_signal_connect(G_OBJECT(rfi->
drawing_area),
"focus-in-event",
795 clipboard = gtk_widget_get_clipboard(rfi->
drawing_area, GDK_SELECTION_CLIPBOARD);
801 rfi->
ui_queue = g_async_queue_new();
805 g_print(
"Error creating pipes.\n");
810 flags = fcntl(rfi->
event_pipe[0], F_GETFL, 0);
811 fcntl(rfi->
event_pipe[0], F_SETFL, flags | O_NONBLOCK);
814 g_print(
"CreateFileDescriptorEvent() failed\n");
818 rfi->
object_table = g_hash_table_new_full(NULL, NULL, NULL, g_free);
820 rfi->
display = gdk_display_get_default();
822 #if GTK_CHECK_VERSION(3, 22, 0) 823 GdkVisual *visual = gdk_screen_get_system_visual(
824 gdk_display_get_default_screen(rfi->
display));
825 rfi->
bpp = gdk_visual_get_depth (visual);
827 rfi->
bpp = gdk_visual_get_best_depth();
835 TRACE_CALL(__func__);
857 TRACE_CALL(__func__);
880 cairo_surface_destroy(rfi->
surface);
888 g_array_free(rfi->
keymap, TRUE);
914 gdi = ((rdpContext *)rfi)->gdi;
920 cairo_surface_destroy(rfi->
surface);
923 stride = cairo_format_stride_for_width(rfi->
cairo_format, gdi->width);
924 rfi->
surface = cairo_image_surface_create_for_data((
unsigned char*)gdi->primary_buffer, rfi->
cairo_format, gdi->width, gdi->height, stride);
929 TRACE_CALL(__func__);
937 gdi = ((rdpContext*)rfi)->gdi;
944 if ( rfi->
surface && (cairo_image_surface_get_width(rfi->
surface) != gdi->width ||
945 cairo_image_surface_get_height(rfi->
surface) != gdi->height) ) {
947 cairo_surface_destroy(rfi->
surface);
950 }
else if ( rfi->
surface == NULL ) {
956 if (width != gdi->width)
958 if (height != gdi->height)
965 gtk_widget_set_size_request(rfi->
drawing_area, -1, -1 );
968 gtk_widget_set_size_request(rfi->
drawing_area, width, height);
975 TRACE_CALL(__func__);
979 gdi = ((rdpContext *)rfi)->gdi;
984 gtk_widget_queue_draw_area(rfi->
drawing_area, 0, 0, gdi->width, gdi->height);
993 TRACE_CALL(__func__);
995 gdk_window_invalidate_rect(gtk_widget_get_window(rfi->
drawing_area), NULL, TRUE);
1000 TRACE_CALL(__func__);
1003 rdpPointer* pointer = (rdpPointer*)ui->
cursor.pointer;
1004 cairo_surface_t* surface;
1005 UINT8* data = malloc(pointer->width * pointer->height * 4);
1007 if (freerdp_image_copy_from_pointer_data(
1008 (BYTE*)data, PIXEL_FORMAT_BGRA32,
1009 pointer->width * 4, 0, 0, pointer->width, pointer->height,
1010 pointer->xorMaskData, pointer->lengthXorMask,
1011 pointer->andMaskData, pointer->lengthAndMask,
1012 pointer->xorBpp, &(ui->
cursor.context->gdi->palette)) < 0) {
1017 surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, pointer->width, pointer->height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pointer->width));
1018 pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, pointer->width, pointer->height);
1019 cairo_surface_destroy(surface);
1021 ((
rfPointer*)ui->
cursor.pointer)->cursor = gdk_cursor_new_from_pixbuf(rfi->
display, pixbuf, pointer->xPos, pointer->yPos);
1022 g_object_unref(pixbuf);
1029 TRACE_CALL(__func__);
1030 g_object_unref(ui->
cursor.pointer->cursor);
1031 ui->
cursor.pointer->cursor = NULL;
1036 TRACE_CALL(__func__);
1038 gint nx, ny, wx, wy;
1039 #if GTK_CHECK_VERSION(3, 20, 0) 1042 GdkDeviceManager *manager;
1051 #if GTK_CHECK_VERSION(3, 20, 0) 1052 seat = gdk_display_get_default_seat(gdk_display_get_default());
1053 dev = gdk_seat_get_pointer(seat);
1055 manager = gdk_display_get_device_manager(gdk_display_get_default());
1056 dev = gdk_device_manager_get_client_pointer(manager);
1059 nw = gdk_device_get_window_at_position(dev, NULL, NULL);
1065 gdk_window_get_root_coords(w, nx, ny, &wx, &wy);
1066 gdk_device_warp(dev, gdk_window_get_screen(w), wx, wy);
1073 TRACE_CALL(__func__);
1076 switch (ui->
cursor.type) {
1086 gdk_window_set_cursor(gtk_widget_get_window(rfi->
drawing_area), ui->
cursor.pointer->cursor);
1095 gdk_window_set_cursor(gtk_widget_get_window(rfi->
drawing_area),
1096 gdk_cursor_new_for_display(gdk_display_get_default(),
1102 gdk_window_set_cursor(gtk_widget_get_window(rfi->
drawing_area), NULL);
1110 TRACE_CALL(__func__);
1116 TRACE_CALL(__func__);
1126 TRACE_CALL(__func__);
1128 cairo_surface_destroy(rfi->
surface);
1134 TRACE_CALL(__func__);
1135 switch (ui->
event.type) {
1147 TRACE_CALL(__func__);
1180 TRACE_CALL(__func__);
1213 TRACE_CALL(__func__);
1215 gboolean ui_sync_save;
1227 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldcanceltype);
1231 ui_sync_save = ui->
sync;
1241 g_async_queue_push(rfi->
ui_queue, ui);
1259 pthread_setcanceltype(oldcanceltype, NULL);
1270 TRACE_CALL(__func__);
1281 TRACE_CALL(__func__);
struct remmina_plugin_rdp_event::@40::@44 clipboard_formatlist
gboolean thread_cancelled
static void remmina_rdp_event_free_cursor(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static void remmina_rdp_event_create_cairo_surface(rfContext *rfi)
RemminaScaleMode(* remmina_protocol_widget_get_current_scale_mode)(RemminaProtocolWidget *gp)
static void remmina_rdp_event_process_event(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
guint delayed_monitor_layout_handler
static void remmina_rdp_event_update_scale_factor(RemminaProtocolWidget *gp)
void(* debug)(const gchar *fmt,...)
struct remmina_plugin_rdp_ui_object::@48::@52 rfx
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
cairo_surface_t * surface
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
void remmina_rdp_settings_get_orientation_scale_prefs(int *desktopOrientation, int *desktopScaleFactor, int *deviceScaleFactor)
void * remmina_rdp_event_queue_ui_sync_retptr(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
void remmina_rdp_event_update_rect(RemminaProtocolWidget *gp, gint x, gint y, gint w, gint h)
pthread_mutex_t sync_wait_mutex
static gboolean remmina_rdp_event_process_ui_queue(RemminaProtocolWidget *gp)
static BOOL remmina_rdp_event_create_cursor(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static void remmina_rdp_event_release_key(RemminaProtocolWidget *gp, RemminaPluginRdpEvent rdp_event)
static void remmina_rdp_event_queue_ui(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
gint(* protocol_plugin_get_width)(RemminaProtocolWidget *gp)
gint(* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value)
static gboolean remmina_rdp_event_on_key(GtkWidget *widget, GdkEventKey *event, RemminaProtocolWidget *gp)
void remmina_rdp_event_free_event(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *obj)
static gboolean remmina_rdp_event_on_motion(GtkWidget *widget, GdkEventMotion *event, RemminaProtocolWidget *gp)
struct remmina_plugin_rdp_ui_object::@48::@50 reg
void(* protocol_plugin_update_align)(RemminaProtocolWidget *gp)
void(* protocol_plugin_signal_connection_opened)(RemminaProtocolWidget *gp)
void remmina_rdp_event_process_clipboard(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
struct remmina_plugin_rdp_event::@40::@43 mouse_event
int reconnect_maxattempts
static void remmina_rdp_ui_event_update_scale(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static gboolean remmina_rdp_event_on_focus_in(GtkWidget *widget, GdkEventKey *event, RemminaProtocolWidget *gp)
RemminaPluginRdpEventType type
void remmina_rdp_event_update_regions(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static gboolean remmina_rdp_event_delayed_monitor_layout(RemminaProtocolWidget *gp)
static RemminaPluginService * remmina_plugin_service
unsigned translated_keycode
cairo_format_t cairo_format
static gboolean remmina_rdp_event_on_configure(GtkWidget *widget, GdkEventConfigure *event, RemminaProtocolWidget *gp)
struct remmina_plugin_rdp_event::@40::@42 key_event
int remmina_rdp_event_queue_ui_sync_retint(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
void remmina_rdp_event_init(RemminaProtocolWidget *gp)
void remmina_rdp_clipboard_abort_transfer(rfContext *rfi)
gboolean use_client_keymap
static gboolean remmina_rdp_event_on_scroll(GtkWidget *widget, GdkEventScroll *event, RemminaProtocolWidget *gp)
gchar *(* pref_get_value)(const gchar *key)
static void remmina_rdp_event_reconnect_progress(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static void remmina_rdp_event_scale_area(RemminaProtocolWidget *gp, gint *x, gint *y, gint *w, gint *h)
void remmina_rdp_event_queue_ui_async(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static gboolean remmina_rdp_event_on_button(GtkWidget *widget, GdkEventButton *event, RemminaProtocolWidget *gp)
gint(* protocol_plugin_get_height)(RemminaProtocolWidget *gp)
struct remmina_plugin_rdp_ui_object::@48::@53 nocodec
void remmina_rdp_event_send_delayed_monitor_layout(RemminaProtocolWidget *gp)
GAsyncQueue * event_queue
static void remmina_rdp_event_release_all_keys(RemminaProtocolWidget *gp)
CLIPRDR_FORMAT_LIST * remmina_rdp_cliprdr_get_client_format_list(RemminaProtocolWidget *gp)
pthread_cond_t sync_wait_cond
static void remmina_rdp_event_init_keymap(rfContext *rfi, const gchar *strmap)
static void remmina_rdp_event_translate_pos(RemminaProtocolWidget *gp, int ix, int iy, UINT16 *ox, UINT16 *oy)
static void remmina_rdp_ui_event_destroy_cairo_surface(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
void remmina_rdp_event_uninit(RemminaProtocolWidget *gp)
RemminaFile *(* protocol_plugin_get_file)(RemminaProtocolWidget *gp)
struct remmina_plugin_rdp_event::@40::@47 monitor_layout
GHashTable * object_table
gboolean remmina_rdp_event_on_clipboard(GtkClipboard *gtkClipboard, GdkEvent *event, RemminaProtocolWidget *gp)
static void remmina_rdp_event_reverse_translate_pos_reverse(RemminaProtocolWidget *gp, int ix, int iy, int *ox, int *oy)
static void remmina_rdp_event_process_ui_event(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
static void keypress_list_add(RemminaProtocolWidget *gp, RemminaPluginRdpEvent rdp_event)
DispClientContext * dispcontext
static BOOL remmina_rdp_event_set_pointer_position(RemminaProtocolWidget *gp, gint x, gint y)
void(* protocol_plugin_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget)
struct remmina_plugin_rdp_ui_object::@48::@55 event
static void remmina_rdp_event_connected(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
void remmina_rdp_event_update_scale(RemminaProtocolWidget *gp)
void(* protocol_plugin_set_height)(RemminaProtocolWidget *gp, gint height)
void remmina_rdp_event_unfocus(RemminaProtocolWidget *gp)
struct remmina_plugin_rdp_ui_object::@48::@51 cursor
void remmina_rdp_event_event_push(RemminaProtocolWidget *gp, const RemminaPluginRdpEvent *e)
struct remmina_plugin_rdp_ui_object::@48::@56 pos
RFX_CONTEXT * rfx_context
static void remmina_rdp_event_cursor(RemminaProtocolWidget *gp, RemminaPluginRdpUiObject *ui)
gboolean(* is_main_thread)(void)
static gboolean remmina_rdp_event_on_draw(GtkWidget *widget, cairo_t *context, RemminaProtocolWidget *gp)
pthread_mutex_t ui_queue_mutex
RemminaPluginRdpUiType type