2
* Remmina - The GTK+ Remote Desktop Client
3
* Copyright (C) 2010 Jay Sorg
4
* Copyright (C) 2010-2011 Vic Lee
5
* Copyright (C) 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330,
20
* Boston, MA 02111-1307, USA.
23
/* X11 drawings were ported from xfreerdp */
25
#include "rdp_plugin.h"
26
#include "rdp_event.h"
28
#include <gdk/gdkkeysyms.h>
29
#include <cairo/cairo-xlib.h>
30
#include <freerdp/kbd/kbd.h>
32
static void remmina_rdp_event_event_push(RemminaProtocolWidget* gp, const RemminaPluginRdpEvent* e)
35
RemminaPluginRdpEvent* event;
41
event = g_memdup(e, sizeof(RemminaPluginRdpEvent));
42
g_async_queue_push(rfi->event_queue, event);
44
if (write(rfi->event_pipe[1], "\0", 1))
50
static void remmina_rdp_event_release_key(RemminaProtocolWidget* gp, gint scancode)
54
RemminaPluginRdpEvent rdp_event = { 0 };
57
rdp_event.type = REMMINA_RDP_EVENT_TYPE_SCANCODE;
61
/* Send all release key events for previously pressed keys */
62
rdp_event.key_event.up = True;
64
for (i = 0; i < rfi->pressed_keys->len; i++)
66
rdp_event.key_event.key_code = g_array_index(rfi->pressed_keys, gint, i);
67
remmina_rdp_event_event_push(gp, &rdp_event);
70
g_array_set_size(rfi->pressed_keys, 0);
74
/* Unregister the keycode only */
75
for (i = 0; i < rfi->pressed_keys->len; i++)
77
k = g_array_index(rfi->pressed_keys, gint, i);
81
g_array_remove_index_fast(rfi->pressed_keys, i);
88
static void remmina_rdp_event_scale_area(RemminaProtocolWidget* gp, gint* x, gint* y, gint* w, gint* h)
96
if (!rfi->rgb_surface)
99
width = remmina_plugin_service->protocol_plugin_get_width(gp);
100
height = remmina_plugin_service->protocol_plugin_get_height(gp);
102
if ((width == 0) || (height == 0))
105
if ((rfi->scale_width == width) && (rfi->scale_height == height))
107
/* Same size, just copy the pixels */
108
*x = MIN(MAX(0, *x), width - 1);
109
*y = MIN(MAX(0, *y), height - 1);
110
*w = MIN(width - *x, *w);
111
*h = MIN(height - *y, *h);
115
/* We have to extend the scaled region one scaled pixel, to avoid gaps */
117
sx = MIN(MAX(0, (*x) * rfi->scale_width / width
118
- rfi->scale_width / width - 2), rfi->scale_width - 1);
120
sy = MIN(MAX(0, (*y) * rfi->scale_height / height
121
- rfi->scale_height / height - 2), rfi->scale_height - 1);
123
sw = MIN(rfi->scale_width - sx, (*w) * rfi->scale_width / width
124
+ rfi->scale_width / width + 4);
126
sh = MIN(rfi->scale_height - sy, (*h) * rfi->scale_height / height
127
+ rfi->scale_height / height + 4);
135
void remmina_rdp_event_update_region(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
142
w = ui->region.width;
143
h = ui->region.height;
149
XPutImage(rfi->display, rfi->primary, rfi->gc, rfi->image, x, y, x, y, w, h);
150
XCopyArea(rfi->display, rfi->primary, rfi->rgb_surface, rfi->gc, x, y, w, h, x, y);
153
if (remmina_plugin_service->protocol_plugin_get_scale(gp))
154
remmina_rdp_event_scale_area(gp, &x, &y, &w, &h);
156
gtk_widget_queue_draw_area(rfi->drawing_area, x, y, w, h);
159
void remmina_rdp_event_update_rect(RemminaProtocolWidget* gp, gint x, gint y, gint w, gint h)
167
XPutImage(rfi->display, rfi->primary, rfi->gc, rfi->image, x, y, x, y, w, h);
168
XCopyArea(rfi->display, rfi->primary, rfi->rgb_surface, rfi->gc, x, y, w, h, x, y);
171
if (remmina_plugin_service->protocol_plugin_get_scale(gp))
172
remmina_rdp_event_scale_area(gp, &x, &y, &w, &h);
174
gtk_widget_queue_draw_area(rfi->drawing_area, x, y, w, h);
177
static gboolean remmina_rdp_event_update_scale_factor(RemminaProtocolWidget* gp)
183
gint gpwidth, gpheight;
184
RemminaFile* remminafile;
188
remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
190
gtk_widget_get_allocation(GTK_WIDGET(gp), &a);
193
scale = remmina_plugin_service->protocol_plugin_get_scale(gp);
197
if ((width > 1) && (height > 1))
199
gpwidth = remmina_plugin_service->protocol_plugin_get_width(gp);
200
gpheight = remmina_plugin_service->protocol_plugin_get_height(gp);
201
hscale = remmina_plugin_service->file_get_int(remminafile, "hscale", 0);
202
vscale = remmina_plugin_service->file_get_int(remminafile, "vscale", 0);
204
rfi->scale_width = (hscale > 0 ?
205
MAX(1, gpwidth * hscale / 100) : width);
206
rfi->scale_height = (vscale > 0 ?
207
MAX(1, gpheight * vscale / 100) : height);
209
rfi->scale_x = (gdouble) rfi->scale_width / (gdouble) gpwidth;
210
rfi->scale_y = (gdouble) rfi->scale_height / (gdouble) gpheight;
215
rfi->scale_width = 0;
216
rfi->scale_height = 0;
221
if ((width > 1) && (height > 1))
222
gtk_widget_queue_draw_area(GTK_WIDGET(gp), 0, 0, width, height);
224
rfi->scale_handler = 0;
230
static gboolean remmina_rdp_event_on_expose(GtkWidget *widget, GdkEventExpose *event, RemminaProtocolWidget *gp)
232
static gboolean remmina_rdp_event_on_draw(GtkWidget* widget, cairo_t* context, RemminaProtocolWidget* gp)
244
if (!rfi->rgb_cairo_surface)
247
scale = remmina_plugin_service->protocol_plugin_get_scale(gp);
253
context = gdk_cairo_create(gtk_widget_get_window (rfi->drawing_area));
254
cairo_rectangle(context, x, y, event->area.width, event->area.height);
256
cairo_rectangle(context, 0, 0, gtk_widget_get_allocated_width(widget),
257
gtk_widget_get_allocated_height(widget));
261
cairo_scale(context, rfi->scale_x, rfi->scale_y);
263
cairo_set_source_surface(context, rfi->rgb_cairo_surface, 0, 0);
267
cairo_destroy(context);
273
static gboolean remmina_rdp_event_on_configure(GtkWidget* widget, GdkEventConfigure* event, RemminaProtocolWidget* gp)
279
/* We do a delayed reallocating to improve performance */
281
if (rfi->scale_handler)
282
g_source_remove(rfi->scale_handler);
284
rfi->scale_handler = g_timeout_add(1000, (GSourceFunc) remmina_rdp_event_update_scale_factor, gp);
289
static void remmina_rdp_event_translate_pos(RemminaProtocolWidget* gp, int ix, int iy, uint16* ox, uint16* oy)
295
if ((rfi->scale) && (rfi->scale_width >= 1) && (rfi->scale_height >= 1))
297
*ox = (uint16) (ix * remmina_plugin_service->protocol_plugin_get_width(gp) / rfi->scale_width);
298
*oy = (uint16) (iy * remmina_plugin_service->protocol_plugin_get_height(gp) / rfi->scale_height);
307
static gboolean remmina_rdp_event_on_motion(GtkWidget* widget, GdkEventMotion* event, RemminaProtocolWidget* gp)
309
RemminaPluginRdpEvent rdp_event = { 0 };
311
rdp_event.type = REMMINA_RDP_EVENT_TYPE_MOUSE;
312
rdp_event.mouse_event.flags = PTR_FLAGS_MOVE;
314
remmina_rdp_event_translate_pos(gp, event->x, event->y, &rdp_event.mouse_event.x, &rdp_event.mouse_event.y);
315
remmina_rdp_event_event_push(gp, &rdp_event);
320
static gboolean remmina_rdp_event_on_button(GtkWidget* widget, GdkEventButton* event, RemminaProtocolWidget* gp)
323
RemminaPluginRdpEvent rdp_event = { 0 };
325
/* We only accept 3 buttons */
326
if ((event->button < 1) || (event->button > 3))
329
/* We bypass 2button-press and 3button-press events */
330
if ((event->type != GDK_BUTTON_PRESS) && (event->type != GDK_BUTTON_RELEASE))
333
rdp_event.type = REMMINA_RDP_EVENT_TYPE_MOUSE;
334
remmina_rdp_event_translate_pos(gp, event->x, event->y, &rdp_event.mouse_event.x, &rdp_event.mouse_event.y);
338
if (event->type == GDK_BUTTON_PRESS)
339
flag = PTR_FLAGS_DOWN;
341
switch (event->button)
344
flag |= PTR_FLAGS_BUTTON1;
347
flag |= PTR_FLAGS_BUTTON3;
350
flag |= PTR_FLAGS_BUTTON2;
356
rdp_event.mouse_event.flags = flag;
357
remmina_rdp_event_event_push(gp, &rdp_event);
363
static gboolean remmina_rdp_event_on_scroll(GtkWidget* widget, GdkEventScroll* event, RemminaProtocolWidget* gp)
366
RemminaPluginRdpEvent rdp_event = { 0 };
369
rdp_event.type = REMMINA_RDP_EVENT_TYPE_MOUSE;
371
switch (event->direction)
374
flag = PTR_FLAGS_WHEEL | 0x0078;
377
case GDK_SCROLL_DOWN:
378
flag = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
385
rdp_event.mouse_event.flags = flag;
386
remmina_rdp_event_translate_pos(gp, event->x, event->y, &rdp_event.mouse_event.x, &rdp_event.mouse_event.y);
387
remmina_rdp_event_event_push(gp, &rdp_event);
392
static gboolean remmina_rdp_event_on_key(GtkWidget* widget, GdkEventKey* event, RemminaProtocolWidget* gp)
395
KeyCode cooked_keycode;
397
RemminaPluginRdpEvent rdp_event;
400
rdp_event.type = REMMINA_RDP_EVENT_TYPE_SCANCODE;
401
rdp_event.key_event.up = (event->type == GDK_KEY_PRESS ? False : True);
402
rdp_event.key_event.extended = False;
404
switch (event->keyval)
407
rdp_event.key_event.key_code = 0x1D;
408
rdp_event.key_event.up = False;
409
remmina_rdp_event_event_push(gp, &rdp_event);
410
rdp_event.key_event.key_code = 0x45;
411
rdp_event.key_event.up = False;
412
remmina_rdp_event_event_push(gp, &rdp_event);
413
rdp_event.key_event.key_code = 0x1D;
414
rdp_event.key_event.up = True;
415
remmina_rdp_event_event_push(gp, &rdp_event);
416
rdp_event.key_event.key_code = 0x45;
417
rdp_event.key_event.up = True;
418
remmina_rdp_event_event_push(gp, &rdp_event);
422
if (!rfi->use_client_keymap)
424
rdp_event.key_event.key_code = freerdp_kbd_get_scancode_by_keycode(event->hardware_keycode, &rdp_event.key_event.extended);
425
remmina_plugin_service->log_printf("[RDP]keyval=%04X keycode=%i scancode=%i extended=%i\n",
426
event->keyval, event->hardware_keycode, rdp_event.key_event.key_code, &rdp_event.key_event.extended);
430
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default());
431
cooked_keycode = XKeysymToKeycode(display, XKeycodeToKeysym(display, event->hardware_keycode, 0));
432
rdp_event.key_event.key_code = freerdp_kbd_get_scancode_by_keycode(cooked_keycode, &rdp_event.key_event.extended);
433
remmina_plugin_service->log_printf("[RDP]keyval=%04X raw_keycode=%i cooked_keycode=%i scancode=%i extended=%i\n",
434
event->keyval, event->hardware_keycode, cooked_keycode, rdp_event.key_event.key_code, &rdp_event.key_event.extended);
437
if (rdp_event.key_event.key_code)
438
remmina_rdp_event_event_push(gp, &rdp_event);
443
/* Register/unregister the pressed key */
444
if (rdp_event.key_event.key_code)
446
if (event->type == GDK_KEY_PRESS)
447
g_array_append_val(rfi->pressed_keys, rdp_event.key_event.key_code);
449
remmina_rdp_event_release_key(gp, rdp_event.key_event.key_code);
455
void remmina_rdp_event_init(RemminaProtocolWidget* gp)
461
XPixmapFormatValues* pf;
462
XPixmapFormatValues* pfs;
466
rfi->drawing_area = gtk_drawing_area_new();
467
gtk_widget_show(rfi->drawing_area);
468
gtk_container_add(GTK_CONTAINER(gp), rfi->drawing_area);
470
gtk_widget_add_events(rfi->drawing_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK
471
| GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
472
gtk_widget_set_can_focus(rfi->drawing_area, TRUE);
474
remmina_plugin_service->protocol_plugin_register_hostkey(gp, rfi->drawing_area);
476
s = remmina_plugin_service->pref_get_value("rdp_use_client_keymap");
477
rfi->use_client_keymap = (s && s[0] == '1' ? TRUE : FALSE);
481
g_signal_connect(G_OBJECT(rfi->drawing_area), "draw",
482
G_CALLBACK(remmina_rdp_event_on_draw), gp);
483
#elif GTK_VERSION == 2
484
g_signal_connect(G_OBJECT(rfi->drawing_area), "expose-event",
485
G_CALLBACK(remmina_rdp_event_on_expose), gp);
487
g_signal_connect(G_OBJECT(rfi->drawing_area), "configure-event",
488
G_CALLBACK(remmina_rdp_event_on_configure), gp);
489
g_signal_connect(G_OBJECT(rfi->drawing_area), "motion-notify-event",
490
G_CALLBACK(remmina_rdp_event_on_motion), gp);
491
g_signal_connect(G_OBJECT(rfi->drawing_area), "button-press-event",
492
G_CALLBACK(remmina_rdp_event_on_button), gp);
493
g_signal_connect(G_OBJECT(rfi->drawing_area), "button-release-event",
494
G_CALLBACK(remmina_rdp_event_on_button), gp);
495
g_signal_connect(G_OBJECT(rfi->drawing_area), "scroll-event",
496
G_CALLBACK(remmina_rdp_event_on_scroll), gp);
497
g_signal_connect(G_OBJECT(rfi->drawing_area), "key-press-event",
498
G_CALLBACK(remmina_rdp_event_on_key), gp);
499
g_signal_connect(G_OBJECT(rfi->drawing_area), "key-release-event",
500
G_CALLBACK(remmina_rdp_event_on_key), gp);
502
rfi->pressed_keys = g_array_new(FALSE, TRUE, sizeof (gint));
503
rfi->event_queue = g_async_queue_new_full(g_free);
504
rfi->ui_queue = g_async_queue_new();
506
if (pipe(rfi->event_pipe))
508
g_print("Error creating pipes.\n");
509
rfi->event_pipe[0] = -1;
510
rfi->event_pipe[1] = -1;
514
flags = fcntl(rfi->event_pipe[0], F_GETFL, 0);
515
fcntl(rfi->event_pipe[0], F_SETFL, flags | O_NONBLOCK);
518
rfi->object_table = g_hash_table_new_full(NULL, NULL, NULL, g_free);
520
rfi->display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
521
rfi->depth = DefaultDepth(rfi->display, DefaultScreen(rfi->display));
522
rfi->visual = GDK_VISUAL_XVISUAL(gdk_visual_get_best_with_depth(rfi->depth));
523
pfs = XListPixmapFormats(rfi->display, &n);
527
for (i = 0; i < n; i++)
531
if (pf->depth == rfi->depth)
533
rfi->scanline_pad = pf->scanline_pad;
534
rfi->bpp = pf->bits_per_pixel;
543
void remmina_rdp_event_uninit(RemminaProtocolWidget* gp)
546
RemminaPluginRdpUiObject* ui;
550
if (rfi->scale_handler)
552
g_source_remove(rfi->scale_handler);
553
rfi->scale_handler = 0;
557
g_source_remove(rfi->ui_handler);
560
while ((ui =(RemminaPluginRdpUiObject*) g_async_queue_try_pop(rfi->ui_queue)) != NULL)
562
rf_object_free(gp, ui);
567
XFreeGC(rfi->display, rfi->gc);
572
XFreeGC(rfi->display, rfi->gc_default);
575
if (rfi->rgb_cairo_surface)
577
cairo_surface_destroy(rfi->rgb_cairo_surface);
578
rfi->rgb_cairo_surface = NULL;
580
if (rfi->rgb_surface)
582
XFreePixmap(rfi->display, rfi->rgb_surface);
583
rfi->rgb_surface = 0;
587
XFreeGC(rfi->display, rfi->gc_mono);
590
if (rfi->bitmap_mono)
592
XFreePixmap(rfi->display, rfi->bitmap_mono);
593
rfi->bitmap_mono = 0;
596
g_hash_table_destroy(rfi->object_table);
598
g_array_free(rfi->pressed_keys, TRUE);
599
g_async_queue_unref(rfi->event_queue);
600
rfi->event_queue = NULL;
601
g_async_queue_unref(rfi->ui_queue);
602
rfi->ui_queue = NULL;
603
close(rfi->event_pipe[0]);
604
close(rfi->event_pipe[1]);
607
void remmina_rdp_event_update_scale(RemminaProtocolWidget* gp)
611
RemminaFile* remminafile;
615
remminafile = remmina_plugin_service->protocol_plugin_get_file(gp);
617
width = remmina_plugin_service->protocol_plugin_get_width(gp);
618
height = remmina_plugin_service->protocol_plugin_get_height(gp);
619
hscale = remmina_plugin_service->file_get_int(remminafile, "hscale", 0);
620
vscale = remmina_plugin_service->file_get_int(remminafile, "vscale", 0);
624
gtk_widget_set_size_request(rfi->drawing_area,
625
(hscale > 0 ? width * hscale / 100 : -1),
626
(vscale > 0 ? height * vscale / 100 : -1));
630
gtk_widget_set_size_request(rfi->drawing_area, width, height);
633
remmina_plugin_service->protocol_plugin_emit_signal(gp, "update-align");
636
static uint8 remmina_rdp_event_rop2_map[] =
640
GXandInverted, /* DPna */
641
GXcopyInverted, /* Pn */
642
GXandReverse, /* PDna */
649
GXorInverted, /* DPno */
651
GXorReverse, /* PDno */
656
static void remmina_rdp_event_set_rop2(rfContext* rfi, gint rop2)
658
if ((rop2 < 0x01) || (rop2 > 0x10))
660
remmina_plugin_service->log_printf("[RDP]unknown rop2 0x%x", rop2);
664
XSetFunction(rfi->display, rfi->gc, remmina_rdp_event_rop2_map[rop2 - 1]);
668
static void remmina_rdp_event_set_rop3(rfContext* rfi, gint rop3)
672
case 0x00: /* 0 - 0 */
673
XSetFunction(rfi->display, rfi->gc, GXclear);
675
case 0x05: /* ~(P | D) - DPon */
676
XSetFunction(rfi->display, rfi->gc, GXnor);
678
case 0x0a: /* ~P & D - DPna */
679
XSetFunction(rfi->display, rfi->gc, GXandInverted);
681
case 0x0f: /* ~P - Pn */
682
XSetFunction(rfi->display, rfi->gc, GXcopyInverted);
684
case 0x11: /* ~(S | D) - DSon */
685
XSetFunction(rfi->display, rfi->gc, GXnor);
687
case 0x22: /* ~S & D - DSna */
688
XSetFunction(rfi->display, rfi->gc, GXandInverted);
690
case 0x33: /* ~S - Sn */
691
XSetFunction(rfi->display, rfi->gc, GXcopyInverted);
693
case 0x44: /* S & ~D - SDna */
694
XSetFunction(rfi->display, rfi->gc, GXandReverse);
696
case 0x50: /* P & ~D - PDna */
697
XSetFunction(rfi->display, rfi->gc, GXandReverse);
699
case 0x55: /* ~D - Dn */
700
XSetFunction(rfi->display, rfi->gc, GXinvert);
702
case 0x5a: /* D ^ P - DPx */
703
XSetFunction(rfi->display, rfi->gc, GXxor);
705
case 0x5f: /* ~(P & D) - DPan */
706
XSetFunction(rfi->display, rfi->gc, GXnand);
708
case 0x66: /* D ^ S - DSx */
709
XSetFunction(rfi->display, rfi->gc, GXxor);
711
case 0x77: /* ~(S & D) - DSan */
712
XSetFunction(rfi->display, rfi->gc, GXnand);
714
case 0x88: /* D & S - DSa */
715
XSetFunction(rfi->display, rfi->gc, GXand);
717
case 0x99: /* ~(S ^ D) - DSxn */
718
XSetFunction(rfi->display, rfi->gc, GXequiv);
720
case 0xa0: /* P & D - DPa */
721
XSetFunction(rfi->display, rfi->gc, GXand);
723
case 0xa5: /* ~(P ^ D) - PDxn */
724
XSetFunction(rfi->display, rfi->gc, GXequiv);
726
case 0xaa: /* D - D */
727
XSetFunction(rfi->display, rfi->gc, GXnoop);
729
case 0xaf: /* ~P | D - DPno */
730
XSetFunction(rfi->display, rfi->gc, GXorInverted);
732
case 0xbb: /* ~S | D - DSno */
733
XSetFunction(rfi->display, rfi->gc, GXorInverted);
735
case 0xcc: /* S - S */
736
XSetFunction(rfi->display, rfi->gc, GXcopy);
738
case 0xdd: /* S | ~D - SDno */
739
XSetFunction(rfi->display, rfi->gc, GXorReverse);
741
case 0xee: /* D | S - DSo */
742
XSetFunction(rfi->display, rfi->gc, GXor);
744
case 0xf0: /* P - P */
745
XSetFunction(rfi->display, rfi->gc, GXcopy);
747
case 0xf5: /* P | ~D - PDno */
748
XSetFunction(rfi->display, rfi->gc, GXorReverse);
750
case 0xfa: /* P | D - DPo */
751
XSetFunction(rfi->display, rfi->gc, GXor);
753
case 0xff: /* 1 - 1 */
754
XSetFunction(rfi->display, rfi->gc, GXset);
757
remmina_plugin_service->log_printf("[RDP]unknown rop3 0x%x", rop3);
762
static void remmina_rdp_event_insert_drawable(rfContext* rfi, guint object_id, Drawable obj)
766
p = g_new(Drawable, 1);
768
g_hash_table_insert(rfi->object_table, GINT_TO_POINTER(object_id), p);
771
static Drawable remmina_rdp_event_get_drawable(rfContext* rfi, guint object_id)
775
p = (Drawable*) g_hash_table_lookup(rfi->object_table, GINT_TO_POINTER(object_id));
783
static void remmina_rdp_event_connected(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
789
gtk_widget_realize(rfi->drawing_area);
791
rfi->drawable = GDK_WINDOW_XID(gtk_widget_get_window(rfi->drawing_area));
793
rfi->rgb_surface = XCreatePixmap(rfi->display, rfi->drawable,
794
rfi->settings->width, rfi->settings->height, rfi->depth);
796
rfi->rgb_cairo_surface = cairo_xlib_surface_create(rfi->display,
797
rfi->rgb_surface, rfi->visual, rfi->width, rfi->height);
799
rfi->drw_surface = rfi->rgb_surface;
801
remmina_rdp_event_update_scale(gp);
804
static void remmina_rdp_event_rfx(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
808
RFX_MESSAGE* message;
812
message = ui->rfx.message;
814
XSetFunction(rfi->display, rfi->gc, GXcopy);
815
XSetFillStyle(rfi->display, rfi->gc, FillSolid);
817
XSetClipRectangles(rfi->display, rfi->gc, ui->rfx.left, ui->rfx.top,
818
(XRectangle*) message->rects, message->num_rects, YXBanded);
820
/* Draw the tiles to primary surface, each is 64x64. */
821
for (i = 0; i < message->num_tiles; i++)
823
image = XCreateImage(rfi->display, rfi->visual, 24, ZPixmap, 0,
824
(char*) message->tiles[i]->data, 64, 64, 32, 0);
826
tx = message->tiles[i]->x + ui->rfx.left;
827
ty = message->tiles[i]->y + ui->rfx.top;
829
XPutImage(rfi->display, rfi->rgb_surface, rfi->gc, image, 0, 0, tx, ty, 64, 64);
832
remmina_rdp_event_update_rect(gp, tx, ty, message->rects[i].width, message->rects[i].height);
835
XSetClipMask(rfi->display, rfi->gc, None);
838
static void remmina_rdp_event_nocodec(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui)
845
XSetFunction(rfi->display, rfi->gc, GXcopy);
846
XSetFillStyle(rfi->display, rfi->gc, FillSolid);
848
image = XCreateImage(rfi->display, rfi->visual, 24, ZPixmap, 0,
849
(char*) ui->nocodec.bitmap, ui->nocodec.width, ui->nocodec.height, 32, 0);
851
XPutImage(rfi->display, rfi->rgb_surface, rfi->gc, image, 0, 0,
852
ui->nocodec.left, ui->nocodec.top,
853
ui->nocodec.width, ui->nocodec.height);
855
remmina_rdp_event_update_rect(gp,
856
ui->nocodec.left, ui->nocodec.top,
857
ui->nocodec.width, ui->nocodec.height);
859
XSetClipMask(rfi->display, rfi->gc, None);
862
gboolean remmina_rdp_event_queue_ui(RemminaProtocolWidget* gp)
865
RemminaPluginRdpUiObject* ui;
869
ui = (RemminaPluginRdpUiObject*) g_async_queue_try_pop(rfi->ui_queue);
875
case REMMINA_RDP_UI_UPDATE_REGION:
876
remmina_rdp_event_update_region(gp, ui);
879
case REMMINA_RDP_UI_CONNECTED:
880
remmina_rdp_event_connected(gp, ui);
883
case REMMINA_RDP_UI_RFX:
884
remmina_rdp_event_rfx(gp, ui);
887
case REMMINA_RDP_UI_NOCODEC:
888
remmina_rdp_event_nocodec(gp, ui);
894
rf_object_free(gp, ui);
907
void remmina_rdp_event_unfocus(RemminaProtocolWidget* gp)
909
remmina_rdp_event_release_key(gp, 0);