40 #ifdef GDK_WINDOWING_X11
41 #include <cairo/cairo-xlib.h>
43 #include <cairo/cairo.h>
46 #include <gdk/gdkkeysyms.h>
47 #include <glib/gi18n.h>
70 #ifdef GDK_WINDOWING_WAYLAND
71 #include <gdk/gdkwayland.h>
75 #define DEBUG_KB_GRABBING 0
83 #define MOTION_TIME 100
86 #define TB_HIDE_TIME_TIME 1500
88 #define FULL_SCREEN_TARGET_MONITOR_UNDEFINED -1
90 struct _RemminaConnectionWindowPriv {
91 GtkNotebook * notebook;
92 GtkWidget * floating_toolbar_widget;
95 GtkWidget * overlay_ftb_overlay;
96 GtkWidget * overlay_ftb_fr;
98 GtkWidget * floating_toolbar_label;
99 gdouble floating_toolbar_opacity;
102 guint acs_eventsourceid;
103 guint spf_eventsourceid;
104 guint grab_retry_eventsourceid;
105 guint delayed_grab_eventsourceid;
106 guint ftb_hide_eventsource;
107 guint tar_eventsource;
108 guint hidetb_eventsource;
109 guint dwp_eventsourceid;
115 GtkToolItem * toolitem_menu;
116 GtkToolItem * toolitem_autofit;
117 GtkToolItem * toolitem_fullscreen;
118 GtkToolItem * toolitem_switch_page;
119 GtkToolItem * toolitem_dynres;
120 GtkToolItem * toolitem_scale;
121 GtkToolItem * toolitem_grab;
122 GtkToolItem * toolitem_multimon;
123 GtkToolItem * toolitem_preferences;
124 GtkToolItem * toolitem_tools;
125 GtkToolItem * toolitem_new;
126 GtkToolItem * toolitem_duplicate;
127 GtkToolItem * toolitem_screenshot;
128 GtkWidget * fullscreen_option_button;
129 GtkWidget * fullscreen_scaler_button;
130 GtkWidget * scaler_option_button;
132 GtkWidget * pin_button;
139 gboolean toolbar_is_reconfiguring;
150 gint ss_width, ss_height;
151 gboolean ss_maximized;
154 gboolean pointer_captured;
155 gboolean hostkey_activated;
156 gboolean hostkey_used;
158 gboolean pointer_entered;
197 static void rcw_place_toolbar(GtkToolbar *toolbar, GtkGrid *grid, GtkWidget *sibling,
int toolbar_placement);
203 static void rcw_ftb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data);
208 (
char *)
"text/x-remmina-ftb",
209 GTK_TARGET_SAME_APP | GTK_TARGET_OTHER_WIDGET,
217 (
char *)
"text/x-remmina-tb",
225 TRACE_CALL(__func__);
226 GtkCssProvider *provider;
228 provider = gtk_css_provider_new();
234 #if GTK_CHECK_VERSION(3, 14, 0)
235 gtk_css_provider_load_from_data(provider,
236 "#remmina-cw-viewport, #remmina-cw-aspectframe {\n"
239 " background-color: black;\n"
244 " -GtkWidget-window-dragging: 0;\n"
246 "#remmina-connection-window-fullscreen {\n"
247 " border-color: black;\n"
249 "#remmina-small-button {\n"
250 " outline-offset: 0;\n"
251 " outline-width: 0;\n"
255 "#remmina-pin-button {\n"
256 " outline-offset: 0;\n"
257 " outline-width: 0;\n"
261 "#remmina-tab-page {\n"
262 " background-color: black;\n"
264 "#remmina-scrolled-container {\n"
266 "#remmina-scrolled-container.undershoot {\n"
267 " background: none;\n"
269 "#remmina-tab-page {\n"
272 " background-color: white;\n"
274 " border-style: none solid solid solid;\n"
275 " border-width: 1px;\n"
276 " border-radius: 4px;\n"
280 " background-color: white;\n"
282 " border-style: solid solid none solid;\n"
283 " border-width: 1px;\n"
284 " border-radius: 4px;\n"
290 " border: 0px solid;\n"
291 " padding: 20px 20px 20px 20px;\n"
293 ".message_panel entry {\n"
294 " background-image: none;\n"
295 " border-width: 4px;\n"
296 " border-radius: 8px;\n"
298 ".message_panel .title_label {\n"
299 " font-size: 2em; \n"
304 gtk_css_provider_load_from_data(provider,
305 "#remmina-cw-viewport, #remmina-cw-aspectframe {\n"
308 " background-color: black;\n"
310 "#remmina-cw-message-panel {\n"
315 " -GtkWidget-window-dragging: 0;\n"
317 "#remmina-connection-window-fullscreen {\n"
318 " border-color: black;\n"
320 "#remmina-small-button {\n"
321 " -GtkWidget-focus-padding: 0;\n"
322 " -GtkWidget-focus-line-width: 0;\n"
326 "#remmina-pin-button {\n"
327 " -GtkWidget-focus-padding: 0;\n"
328 " -GtkWidget-focus-line-width: 0;\n"
332 "#remmina-scrolled-container {\n"
334 "#remmina-scrolled-container.undershoot {\n"
335 " background: none\n"
337 "#remmina-tab-page {\n"
340 " border-style: none solid solid solid;\n"
341 " border-width: 1px;\n"
342 " border-radius: 4px;\n"
346 " border-style: solid solid none solid;\n"
347 " border-width: 1px;\n"
348 " border-radius: 4px;\n"
357 gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
358 GTK_STYLE_PROVIDER(provider),
359 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
361 g_object_unref(provider);
366 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
373 if (!cnnwin->
priv->notebook)
375 po = gtk_notebook_get_nth_page(GTK_NOTEBOOK(cnnwin->
priv->notebook), npage);
376 return g_object_get_data(G_OBJECT(po),
"cnnobj");
383 if (cnnwin != NULL && cnnwin->
priv != NULL && cnnwin->
priv->notebook != NULL) {
384 np = gtk_notebook_get_current_page(GTK_NOTEBOOK(cnnwin->
priv->notebook));
395 TRACE_CALL(__func__);
397 gboolean plugin_has_dynres, plugin_can_scale;
416 *scale_avail = plugin_can_scale;
425 TRACE_CALL(__func__);
433 TRACE_CALL(__func__);
436 #if GTK_CHECK_VERSION(3, 20, 0)
439 GdkDeviceManager *manager;
440 GdkDevice *keyboard = NULL;
443 if (cnnwin->
priv->grab_retry_eventsourceid) {
444 g_source_remove(cnnwin->
priv->grab_retry_eventsourceid);
445 cnnwin->
priv->grab_retry_eventsourceid = 0;
447 if (cnnwin->
priv->delayed_grab_eventsourceid) {
448 g_source_remove(cnnwin->
priv->delayed_grab_eventsourceid);
449 cnnwin->
priv->delayed_grab_eventsourceid = 0;
452 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
453 #if GTK_CHECK_VERSION(3, 20, 0)
454 seat = gdk_display_get_default_seat(display);
457 manager = gdk_display_get_device_manager(display);
458 keyboard = gdk_device_manager_get_client_pointer(manager);
461 if (!cnnwin->
priv->kbcaptured && !cnnwin->
priv->pointer_captured)
464 #if DEBUG_KB_GRABBING
465 printf(
"DEBUG_KB_GRABBING: --- ungrabbing\n");
470 #if GTK_CHECK_VERSION(3, 20, 0)
472 gdk_seat_ungrab(seat);
474 if (keyboard != NULL) {
475 if (gdk_device_get_source(keyboard) != GDK_SOURCE_KEYBOARD)
476 keyboard = gdk_device_get_associated_device(keyboard);
477 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
478 gdk_device_ungrab(keyboard, GDK_CURRENT_TIME);
479 G_GNUC_END_IGNORE_DEPRECATIONS
482 cnnwin->
priv->kbcaptured = FALSE;
483 cnnwin->
priv->pointer_captured = FALSE;
488 TRACE_CALL(__func__);
491 #if DEBUG_KB_GRABBING
492 printf(
"%s retry grab\n", __func__);
495 cnnwin->
priv->grab_retry_eventsourceid = 0;
496 return G_SOURCE_REMOVE;
501 TRACE_CALL(__func__);
502 #if GTK_CHECK_VERSION(3, 20, 0)
505 if (!cnnwin->
priv->pointer_captured)
508 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
509 seat = gdk_display_get_default_seat(display);
510 gdk_seat_ungrab(seat);
516 TRACE_CALL(__func__);
519 #if GTK_CHECK_VERSION(3, 20, 0)
525 if (cnnwin->
priv->pointer_captured) {
526 #if DEBUG_KB_GRABBING
527 printf(
"DEBUG_KB_GRABBING: pointer_captured is true, it should not\n");
532 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
533 seat = gdk_display_get_default_seat(display);
534 ggs = gdk_seat_grab(seat, gtk_widget_get_window(GTK_WIDGET(cnnwin)),
535 GDK_SEAT_CAPABILITY_ALL_POINTING, TRUE, NULL, NULL, NULL, NULL);
536 if (ggs != GDK_GRAB_SUCCESS) {
537 #if DEBUG_KB_GRABBING
538 printf(
"DEBUG_KB_GRABBING: GRAB of POINTER failed. GdkGrabStatus: %d\n", (
int)ggs);
541 cnnwin->
priv->pointer_captured = TRUE;
549 TRACE_CALL(__func__);
552 #if GTK_CHECK_VERSION(3, 20, 0)
555 GdkDeviceManager *manager;
558 GdkDevice *keyboard = NULL;
560 if (cnnwin->
priv->kbcaptured) {
561 #if DEBUG_KB_GRABBING
562 printf(
"DEBUG_KB_GRABBING: %s not grabbing because already grabbed.\n", __func__);
567 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
568 #if GTK_CHECK_VERSION(3, 20, 0)
569 seat = gdk_display_get_default_seat(display);
570 keyboard = gdk_seat_get_pointer(seat);
572 manager = gdk_display_get_device_manager(display);
573 keyboard = gdk_device_manager_get_client_pointer(manager);
576 if (keyboard != NULL) {
577 if (gdk_device_get_source(keyboard) != GDK_SOURCE_KEYBOARD)
578 keyboard = gdk_device_get_associated_device(keyboard);
581 #if DEBUG_KB_GRABBING
582 printf(
"DEBUG_KB_GRABBING: profile asks for grabbing, let’s try.\n");
602 #if GTK_CHECK_VERSION(3, 20, 0)
603 ggs = gdk_seat_grab(seat, gtk_widget_get_window(GTK_WIDGET(cnnwin)),
604 GDK_SEAT_CAPABILITY_KEYBOARD, TRUE, NULL, NULL, NULL, NULL);
606 ggs = gdk_device_grab(keyboard, gtk_widget_get_window(GTK_WIDGET(cnnwin)), GDK_OWNERSHIP_WINDOW,
607 TRUE, GDK_KEY_PRESS | GDK_KEY_RELEASE, NULL, GDK_CURRENT_TIME);
609 if (ggs != GDK_GRAB_SUCCESS) {
610 #if DEBUG_KB_GRABBING
611 printf(
"GRAB of keyboard failed.\n");
614 if (cnnwin->
priv->grab_retry_eventsourceid == 0)
617 #if DEBUG_KB_GRABBING
618 printf(
"Keyboard grabbed\n");
620 if (cnnwin->
priv->grab_retry_eventsourceid != 0) {
621 g_source_remove(cnnwin->
priv->grab_retry_eventsourceid);
622 cnnwin->
priv->grab_retry_eventsourceid = 0;
624 cnnwin->
priv->kbcaptured = TRUE;
634 GtkNotebook *notebook = GTK_NOTEBOOK(priv->notebook);
639 if (GTK_IS_WIDGET(notebook)) {
640 n = gtk_notebook_get_n_pages(notebook);
641 for (i = n - 1; i >= 0; i--) {
642 w = gtk_notebook_get_nth_page(notebook, i);
652 TRACE_CALL(__func__);
654 GtkNotebook *notebook = GTK_NOTEBOOK(priv->notebook);
658 if (!REMMINA_IS_CONNECTION_WINDOW(cnnwin))
662 n = gtk_notebook_get_n_pages(notebook);
665 for(i = 0; i < n; i ++) {
671 dialog = gtk_message_dialog_new(GTK_WINDOW(cnnwin), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
673 _(
"Are you sure you want to close %i active connections in the current window?"), nopen);
674 i = gtk_dialog_run(GTK_DIALOG(dialog));
675 gtk_widget_destroy(dialog);
676 if (i != GTK_RESPONSE_YES)
679 else if (nopen == 1) {
681 dialog = gtk_message_dialog_new(GTK_WINDOW(cnnwin), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
683 _(
"Are you sure you want to close this last active connection?"));
684 i = gtk_dialog_run(GTK_DIALOG(dialog));
685 gtk_widget_destroy(dialog);
686 if (i != GTK_RESPONSE_YES)
698 TRACE_CALL(__func__);
705 TRACE_CALL(__func__);
709 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
715 if (priv->kbcaptured)
718 if (priv->acs_eventsourceid) {
719 g_source_remove(priv->acs_eventsourceid);
720 priv->acs_eventsourceid = 0;
722 if (priv->spf_eventsourceid) {
723 g_source_remove(priv->spf_eventsourceid);
724 priv->spf_eventsourceid = 0;
726 if (priv->grab_retry_eventsourceid) {
727 g_source_remove(priv->grab_retry_eventsourceid);
728 priv->grab_retry_eventsourceid = 0;
730 if (cnnwin->
priv->delayed_grab_eventsourceid) {
731 g_source_remove(cnnwin->
priv->delayed_grab_eventsourceid);
732 cnnwin->
priv->delayed_grab_eventsourceid = 0;
734 if (priv->ftb_hide_eventsource) {
735 g_source_remove(priv->ftb_hide_eventsource);
736 priv->ftb_hide_eventsource = 0;
738 if (priv->tar_eventsource) {
739 g_source_remove(priv->tar_eventsource);
740 priv->tar_eventsource = 0;
742 if (priv->hidetb_eventsource) {
743 g_source_remove(priv->hidetb_eventsource);
744 priv->hidetb_eventsource = 0;
746 if (priv->dwp_eventsourceid) {
747 g_source_remove(priv->dwp_eventsourceid);
748 priv->dwp_eventsourceid = 0;
760 TRACE_CALL(__func__);
764 if (G_TYPE_CHECK_INSTANCE_TYPE(widget, rcwtype)) {
765 g_signal_emit_by_name(G_OBJECT(widget),
"toolbar-place");
772 GtkDragResult result, gpointer user_data)
774 TRACE_CALL(__func__);
783 gtk_widget_show(GTK_WIDGET(priv->toolbar));
789 gint x, gint y, guint time, gpointer user_data)
791 TRACE_CALL(__func__);
793 gint new_toolbar_placement;
800 gtk_widget_get_allocation(widget, &wa);
802 if (wa.width * y >= wa.height * x) {
803 if (wa.width * y > wa.height * (wa.width - x))
808 if (wa.width * y > wa.height * (wa.width - x))
814 gtk_drag_finish(context, TRUE, TRUE, time);
825 gtk_widget_show(GTK_WIDGET(priv->toolbar));
832 TRACE_CALL(__func__);
834 cairo_surface_t *surface;
837 double dashes[] = { 10 };
839 gtk_widget_get_allocation(widget, &wa);
841 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 16, 16);
842 cr = cairo_create(surface);
843 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
844 cairo_set_line_width(cr, 4);
845 cairo_set_dash(cr, dashes, 1, 0);
846 cairo_rectangle(cr, 0, 0, 16, 16);
850 gtk_widget_hide(widget);
852 gtk_drag_set_icon_surface(context, surface);
857 TRACE_CALL(__func__);
864 priv->floating_toolbar_opacity = (1.0 - TOOLBAR_OPACITY_MIN) / ((gdouble)TOOLBAR_OPACITY_LEVEL)
866 + TOOLBAR_OPACITY_MIN;
867 if (priv->floating_toolbar_widget)
868 gtk_widget_set_opacity(GTK_WIDGET(priv->overlay_ftb_overlay), priv->floating_toolbar_opacity);
873 TRACE_CALL(__func__);
876 gtk_widget_set_opacity(GTK_WIDGET(priv->overlay_ftb_overlay), 0.0);
877 priv->ftb_hide_eventsource = 0;
878 return G_SOURCE_REMOVE;
883 TRACE_CALL(__func__);
886 if (priv->floating_toolbar_widget == NULL)
889 if (show || priv->pin_down) {
893 if (priv->ftb_hide_eventsource) {
894 g_source_remove(priv->ftb_hide_eventsource);
895 priv->ftb_hide_eventsource = 0;
901 if (priv->ftb_hide_eventsource == 0)
905 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer), show || priv->pin_down);
910 TRACE_CALL(__func__);
926 TRACE_CALL(__func__);
928 gtk_scrolled_window_set_policy(scrolled_window,
935 GtkWidget *scrolled_container;
940 scrolled_container = gtk_scrolled_window_new(NULL, NULL);
942 gtk_container_set_border_width(GTK_CONTAINER(scrolled_container), 0);
943 gtk_widget_set_can_focus(scrolled_container, FALSE);
946 gtk_widget_set_name(scrolled_container,
"remmina-scrolled-container");
947 gtk_widget_show(scrolled_container);
949 return scrolled_container;
954 TRACE_CALL(__func__);
958 gint dwidth, dheight;
959 GtkAllocation nba, ca, ta;
961 cnnwin->
priv->tar_eventsource = 0;
963 if (priv->toolbar_is_reconfiguring)
964 return G_SOURCE_REMOVE;
970 gtk_widget_get_allocation(GTK_WIDGET(priv->notebook), &nba);
972 gtk_widget_get_allocation(priv->toolbar, &ta);
975 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), MAX(1, dwidth + ta.width + nba.width - ca.width),
976 MAX(1, dheight + nba.height - ca.height));
978 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), MAX(1, dwidth + nba.width - ca.width),
979 MAX(1, dheight + ta.height + nba.height - ca.height));
980 gtk_container_check_resize(GTK_CONTAINER(cnnobj->
cnnwin));
987 return G_SOURCE_REMOVE;
992 TRACE_CALL(__func__);
995 if (cnnwin->
priv->toolbar_is_reconfiguring)
1000 if ((gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) != 0)
1001 gtk_window_unmaximize(GTK_WINDOW(cnnwin));
1005 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
1013 TRACE_CALL(__func__);
1018 GdkRectangle monitor_geometry;
1020 sz->x = sz->y = sz->width = sz->height = 0;
1026 if (!gtk_widget_is_visible(GTK_WIDGET(cnnobj->
cnnwin)))
1029 #if GTK_CHECK_VERSION(3, 22, 0)
1030 GdkDisplay *display;
1031 GdkMonitor *monitor;
1032 display = gtk_widget_get_display(GTK_WIDGET(cnnobj->
cnnwin));
1033 monitor = gdk_display_get_monitor_at_window(display, gtk_widget_get_window(GTK_WIDGET(cnnobj->
cnnwin)));
1037 screen = gtk_window_get_screen(GTK_WINDOW(cnnobj->
cnnwin));
1038 monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(GTK_WIDGET(cnnobj->
cnnwin)));
1041 #if GTK_CHECK_VERSION(3, 22, 0)
1042 gdk_monitor_get_workarea(monitor, &monitor_geometry);
1047 #ifdef GDK_WINDOWING_WAYLAND
1048 if (GDK_IS_WAYLAND_DISPLAY(display)) {
1049 int monitor_scale_factor = gdk_monitor_get_scale_factor(monitor);
1050 monitor_geometry.width *= monitor_scale_factor;
1051 monitor_geometry.height *= monitor_scale_factor;
1054 #elif gdk_screen_get_monitor_workarea
1055 gdk_screen_get_monitor_workarea(screen, monitor, &monitor_geometry);
1057 gdk_screen_get_monitor_geometry(screen, monitor, &monitor_geometry);
1059 *sz = monitor_geometry;
1064 TRACE_CALL(__func__);
1065 gboolean scroll_required = FALSE;
1067 GdkRectangle monitor_geometry;
1068 gint rd_width, rd_height;
1081 (monitor_geometry.width < rd_width || monitor_geometry.height < rd_height) &&
1083 scroll_required = TRUE;
1087 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), monitor_geometry.width, monitor_geometry.height);
1089 (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER),
1090 (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER));
1094 bordersz = scroll_required ? SCROLL_BORDER_SIZE : 0;
1095 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), monitor_geometry.width, monitor_geometry.height);
1106 gtk_window_set_default_size(GTK_WINDOW(cnnobj->
cnnwin),
1107 MIN(rd_width, monitor_geometry.width), MIN(rd_height, monitor_geometry.height));
1108 if (rd_width >= monitor_geometry.width || rd_height >= monitor_geometry.height) {
1109 gtk_window_maximize(GTK_WINDOW(cnnobj->
cnnwin));
1117 gtk_window_maximize(GTK_WINDOW(cnnobj->
cnnwin));
1128 TRACE_CALL(__func__);
1135 gdk_keyval_name(gdk_keyval_to_upper(key1)), gdk_keyval_name(gdk_keyval_to_upper(key2)));
1140 gdk_keyval_name(gdk_keyval_to_upper(key1)));
1144 s2 = g_strdup_printf(
"%s%s", tip, s1 ? s1 :
"");
1145 gtk_widget_set_tooltip_text(
item, s2);
1152 TRACE_CALL(__func__);
1154 gboolean scaledexpandedmode;
1155 int rdwidth, rdheight;
1161 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1162 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1174 aratio = (gfloat)rdwidth / (gfloat)rdheight;
1177 cnnobj->
aspectframe = gtk_aspect_frame_new(NULL, 0.5, 0.5, aratio, FALSE);
1178 gtk_widget_set_name(cnnobj->
aspectframe,
"remmina-cw-aspectframe");
1179 gtk_frame_set_shadow_type(GTK_FRAME(cnnobj->
aspectframe), GTK_SHADOW_NONE);
1180 g_object_ref(cnnobj->
proto);
1181 gtk_container_remove(GTK_CONTAINER(cnnobj->
viewport), cnnobj->
proto);
1184 g_object_unref(cnnobj->
proto);
1186 if (cnnobj != NULL && cnnobj->
cnnwin != NULL && cnnobj->
cnnwin->
priv->notebook != NULL)
1189 gtk_aspect_frame_set(GTK_ASPECT_FRAME(cnnobj->
aspectframe), 0.5, 0.5, aratio, FALSE);
1196 g_object_ref(cnnobj->
proto);
1201 gtk_container_add(GTK_CONTAINER(cnnobj->
viewport), cnnobj->
proto);
1202 g_object_unref(cnnobj->
proto);
1203 if (cnnobj != NULL && cnnobj->
cnnwin != NULL && cnnobj->
cnnwin->
priv->notebook != NULL)
1212 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1213 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1217 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_CENTER);
1218 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_CENTER);
1227 np = gtk_notebook_get_n_pages(notebook);
1228 for (i = 0; i < np; i++) {
1229 if (gtk_notebook_get_nth_page(notebook, i) == page) {
1230 gtk_notebook_set_current_page(notebook, i);
1242 lst = gtk_container_get_children(GTK_CONTAINER(frompage));
1243 for (l = lst; l != NULL; l = l->next) {
1244 if (REMMINA_IS_MESSAGE_PANEL(l->data)) {
1245 g_object_ref(l->data);
1246 gtk_container_remove(GTK_CONTAINER(frompage), GTK_WIDGET(l->data));
1247 gtk_container_add(GTK_CONTAINER(topage), GTK_WIDGET(l->data));
1248 g_object_unref(l->data);
1249 gtk_box_reorder_child(GTK_BOX(topage), GTK_WIDGET(l->data), 0);
1262 GtkNotebook *from_notebook;
1263 GtkWidget *frompage, *newpage, *old_scrolled_container;
1268 tag = g_strdup((gchar *)g_object_get_data(G_OBJECT(from),
"tag"));
1269 g_object_set_data_full(G_OBJECT(to),
"tag", tag, (GDestroyNotify)g_free);
1272 from_notebook = from->
priv->notebook;
1273 if (from_notebook && GTK_IS_NOTEBOOK(from_notebook)) {
1275 cp = gtk_notebook_get_current_page(from_notebook);
1276 np = gtk_notebook_get_n_pages(from_notebook);
1279 for (i = 0; i < np; i++) {
1280 frompage = gtk_notebook_get_nth_page(from_notebook, i);
1281 cnnobj = g_object_get_data(G_OBJECT(frompage),
"cnnobj");
1295 gtk_container_remove(GTK_CONTAINER(old_scrolled_container), cnnobj->
viewport);
1301 gtk_widget_destroy(old_scrolled_container);
1306 for (i = np - 1; i >= 0; i--)
1307 gtk_notebook_remove_page(from_notebook, i);
1308 gtk_notebook_set_current_page(to->
priv->notebook, cp);
1317 gint old_width, old_height;
1320 old_mode = cnnwin->
priv->view_mode;
1321 if (old_mode == newmode)
1328 gtk_window_get_size(GTK_WINDOW(cnnwin), &old_width, &old_height);
1329 s = gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnwin)));
1334 newwin->
priv->ss_maximized = (s & GDK_WINDOW_STATE_MAXIMIZED) ? TRUE : FALSE;
1335 newwin->
priv->ss_width = old_width;
1336 newwin->
priv->ss_height = old_height;
1340 cnnwin->
priv->ss_maximized);
1345 newwin->
priv->fss_view_mode = old_mode;
1349 newwin->
priv->hostkey_used = TRUE;
1355 TRACE_CALL(__func__);
1359 if (cnnwin->
priv->toolbar_is_reconfiguring)
1367 REMMINA_DEBUG(
"Fullscreen on all monitor");
1368 gdk_window_set_fullscreen_mode(gtk_widget_get_window(GTK_WIDGET(toggle)), GDK_FULLSCREEN_ON_ALL_MONITORS);
1370 REMMINA_DEBUG(
"Fullscreen on one monitor");
1373 if ((toggle != NULL && toggle == cnnwin->
priv->toolitem_fullscreen)) {
1374 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle))) {
1376 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnwin->
priv->toolitem_multimon), TRUE);
1382 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(cnnwin->
priv->toolitem_multimon))) {
1391 TRACE_CALL(__func__);
1394 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1403 TRACE_CALL(__func__);
1406 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1415 TRACE_CALL(__func__);
1418 priv->sticky = FALSE;
1419 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->fullscreen_option_button), FALSE);
1425 TRACE_CALL(__func__);
1428 GtkWidget *menuitem;
1431 if (cnnwin->
priv->toolbar_is_reconfiguring)
1436 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)))
1439 cnnwin->
priv->sticky = TRUE;
1441 menu = gtk_menu_new();
1443 menuitem = gtk_radio_menu_item_new_with_label(NULL, _(
"Viewport fullscreen mode"));
1444 gtk_widget_show(menuitem);
1445 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1446 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
1448 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1451 menuitem = gtk_radio_menu_item_new_with_label(group, _(
"Scrolled fullscreen"));
1452 gtk_widget_show(menuitem);
1453 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1455 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1460 #if GTK_CHECK_VERSION(3, 22, 0)
1461 gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(toggle),
1462 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1465 gtk_get_current_event_time());
1472 TRACE_CALL(__func__);
1475 if (priv->toolbar_is_reconfiguring)
1477 priv->sticky = FALSE;
1478 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->scaler_option_button), FALSE);
1484 TRACE_CALL(__func__);
1487 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1498 TRACE_CALL(__func__);
1501 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1514 TRACE_CALL(__func__);
1518 GtkWidget *menuitem;
1520 gboolean scaler_expand;
1522 if (cnnwin->
priv->toolbar_is_reconfiguring)
1526 priv = cnnwin->
priv;
1528 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)))
1533 priv->sticky = TRUE;
1535 menu = gtk_menu_new();
1537 menuitem = gtk_radio_menu_item_new_with_label(NULL, _(
"Keep aspect ratio when scaled"));
1538 gtk_widget_show(menuitem);
1539 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1540 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
1542 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1545 menuitem = gtk_radio_menu_item_new_with_label(group, _(
"Fill client window when scaled"));
1546 gtk_widget_show(menuitem);
1547 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1549 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1550 g_signal_connect(G_OBJECT(menuitem),
"toggled", G_CALLBACK(
rcw_scaler_expand), cnnwin);
1554 #if GTK_CHECK_VERSION(3, 22, 0)
1555 gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(toggle),
1556 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1559 gtk_get_current_event_time());
1565 TRACE_CALL(__func__);
1569 page_num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem),
"new-page-num"));
1570 gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), page_num);
1575 TRACE_CALL(__func__);
1578 priv->sticky = FALSE;
1580 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_switch_page), FALSE);
1586 TRACE_CALL(__func__);
1592 GtkWidget *menuitem;
1596 if (priv->toolbar_is_reconfiguring)
1600 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle)))
1603 priv->sticky = TRUE;
1605 menu = gtk_menu_new();
1607 n = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook));
1608 for (i = 0; i < n; i++) {
1612 gtk_widget_show(menuitem);
1613 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1616 gtk_widget_show(image);
1618 g_object_set_data(G_OBJECT(menuitem),
"new-page-num", GINT_TO_POINTER(i));
1620 if (i == gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook)))
1621 gtk_widget_set_sensitive(menuitem, FALSE);
1627 #if GTK_CHECK_VERSION(3, 22, 0)
1628 gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(toggle),
1629 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1637 TRACE_CALL(__func__);
1639 GtkToolItem *toolitem;
1642 toolitem = priv->toolitem_autofit;
1645 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
1682 TRACE_CALL(__func__);
1683 gboolean bdyn, bscale;
1686 if (cnnwin->
priv->toolbar_is_reconfiguring)
1691 bdyn = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle));
1692 bscale = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_scale));
1694 if (bdyn && bscale) {
1695 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_scale), FALSE);
1705 TRACE_CALL(__func__);
1706 gboolean bdyn, bscale;
1709 if (cnnwin->
priv->toolbar_is_reconfiguring)
1713 bdyn = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_dynres));
1714 bscale = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle));
1716 if (bdyn && bscale) {
1717 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_dynres), FALSE);
1726 TRACE_CALL(__func__);
1729 if (cnnwin->
priv->toolbar_is_reconfiguring)
1734 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle))) {
1735 REMMINA_DEBUG(
"Saving multimon as 1");
1740 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(cnnwin->
priv->toolitem_fullscreen)))
1741 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnwin->
priv->toolitem_fullscreen), TRUE);
1743 REMMINA_DEBUG(
"Saving multimon as 0");
1752 TRACE_CALL(__func__);
1754 if (cnnwin->
priv->toolbar_is_reconfiguring)
1762 TRACE_CALL(__func__);
1765 if (cnnwin->
priv->toolbar_is_reconfiguring)
1771 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_preferences), FALSE);
1777 TRACE_CALL(__func__);
1780 if (priv->toolbar_is_reconfiguring)
1783 priv->sticky = FALSE;
1785 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_menu), FALSE);
1791 TRACE_CALL(__func__);
1794 if (priv->toolbar_is_reconfiguring)
1797 priv->sticky = FALSE;
1799 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_tools), FALSE);
1805 TRACE_CALL(__func__);
1809 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
1811 value = g_object_get_data(G_OBJECT(menuitem),
"feature-value");
1820 TRACE_CALL(__func__);
1825 value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
1832 TRACE_CALL(__func__);
1842 TRACE_CALL(__func__);
1843 GtkWidget *menuitem;
1851 list = (
const gchar **)feature->
opt3;
1852 for (i = 0; list[i]; i += 2) {
1853 menuitem = gtk_radio_menu_item_new_with_label(group, g_dgettext(domain, list[i + 1]));
1854 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
1855 gtk_widget_show(menuitem);
1856 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1859 g_object_set_data(G_OBJECT(menuitem),
"feature-type", (gpointer)feature);
1860 g_object_set_data(G_OBJECT(menuitem),
"feature-value", (gpointer)list[i]);
1862 if (value && g_strcmp0(list[i], value) == 0)
1863 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1865 g_signal_connect(G_OBJECT(menuitem),
"toggled",
1868 gtk_widget_set_sensitive(menuitem, FALSE);
1875 const gchar *domain, gboolean enabled)
1877 TRACE_CALL(__func__);
1878 GtkWidget *menuitem;
1880 menuitem = gtk_check_menu_item_new_with_label(g_dgettext(domain, (
const gchar *)feature->
opt3));
1881 gtk_widget_show(menuitem);
1882 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1885 g_object_set_data(G_OBJECT(menuitem),
"feature-type", (gpointer)feature);
1887 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
1890 g_signal_connect(G_OBJECT(menuitem),
"toggled",
1893 gtk_widget_set_sensitive(menuitem, FALSE);
1899 TRACE_CALL(__func__);
1904 GtkWidget *menuitem;
1909 if (cnnwin->
priv->toolbar_is_reconfiguring)
1914 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle)))
1917 priv->sticky = TRUE;
1922 menu = gtk_menu_new();
1929 menuitem = gtk_separator_menu_item_new();
1930 gtk_widget_show(menuitem);
1931 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1935 switch (GPOINTER_TO_INT(feature->
opt1)) {
1936 case REMMINA_PROTOCOL_FEATURE_PREF_RADIO:
1941 case REMMINA_PROTOCOL_FEATURE_PREF_CHECK:
1952 #if GTK_CHECK_VERSION(3, 22, 0)
1953 gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(toggle),
1954 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1962 TRACE_CALL(__func__);
1973 s = g_strdup_printf(
"%s,%s", menuitem->
protocol, menuitem->
name);
1982 TRACE_CALL(__func__);
1986 GtkWidget *menuitem = NULL;
1988 if (cnnwin->
priv->toolbar_is_reconfiguring)
1994 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle)))
1997 priv->sticky = TRUE;
2005 menuitem = gtk_separator_menu_item_new();
2006 gtk_widget_show(menuitem);
2007 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
2008 #if GTK_CHECK_VERSION(3, 22, 0)
2009 gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(toggle),
2010 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
2019 TRACE_CALL(__func__);
2024 GtkWidget *menuitem = NULL;
2025 GtkMenu *submenu_keystrokes;
2026 const gchar *domain;
2029 gchar **keystroke_values;
2032 if (cnnwin->
priv->toolbar_is_reconfiguring)
2037 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle)))
2040 priv->sticky = TRUE;
2043 menu = gtk_menu_new();
2050 menuitem = gtk_menu_item_new_with_label(g_dgettext(domain, (
const gchar *)feature->
opt1));
2053 gtk_widget_show(menuitem);
2054 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
2058 g_object_set_data(G_OBJECT(menuitem),
"feature-type", (gpointer)feature);
2060 g_signal_connect(G_OBJECT(menuitem),
"activate",
2063 gtk_widget_set_sensitive(menuitem, FALSE);
2071 if (g_strv_length(keystrokes)) {
2073 menuitem = gtk_menu_item_new_with_label(_(
"Keystrokes"));
2074 submenu_keystrokes = GTK_MENU(gtk_menu_new());
2075 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(submenu_keystrokes));
2076 gtk_widget_show(menuitem);
2077 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
2079 for (i = 0; i < g_strv_length(keystrokes); i++) {
2080 keystroke_values = g_strsplit(keystrokes[i], STRING_DELIMITOR2, -1);
2081 if (g_strv_length(keystroke_values) > 1) {
2083 menuitem = gtk_menu_item_new_with_label(
2084 g_strdup(keystroke_values[strlen(keystroke_values[0]) ? 0 : 1]));
2085 g_object_set_data(G_OBJECT(menuitem),
"keystrokes", g_strdup(keystroke_values[1]));
2086 g_signal_connect_swapped(G_OBJECT(menuitem),
"activate",
2088 REMMINA_PROTOCOL_WIDGET(cnnobj->
proto));
2089 gtk_widget_show(menuitem);
2090 gtk_menu_shell_append(GTK_MENU_SHELL(submenu_keystrokes), menuitem);
2092 g_strfreev(keystroke_values);
2094 menuitem = gtk_menu_item_new_with_label(_(
"Send clipboard content as keystrokes"));
2095 static gchar k_tooltip[] =
2096 N_(
"CAUTION: Pasted text will be sent as a sequence of key-codes as if typed on your local keyboard.\n"
2098 " • For best results use same keyboard settings for both, client and server.\n"
2100 " • If client-keyboard is different from server-keyboard the received text can contain wrong or erroneous characters.\n"
2102 " • Unicode characters and other special characters that can't be translated to local key-codes won’t be sent to the server.\n"
2104 gtk_widget_set_tooltip_text(menuitem, k_tooltip);
2105 gtk_menu_shell_append(GTK_MENU_SHELL(submenu_keystrokes), menuitem);
2106 g_signal_connect_swapped(G_OBJECT(menuitem),
"activate",
2108 REMMINA_PROTOCOL_WIDGET(cnnobj->
proto));
2109 gtk_widget_show(menuitem);
2111 g_strfreev(keystrokes);
2116 #if GTK_CHECK_VERSION(3, 22, 0)
2117 gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(toggle),
2118 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
2126 TRACE_CALL(__func__);
2130 if (cnnwin->
priv->toolbar_is_reconfiguring)
2141 TRACE_CALL(__func__);
2143 GdkPixbuf *screenshot;
2144 GdkWindow *active_window;
2153 cairo_surface_t *srcsurface;
2154 cairo_format_t cairo_format;
2155 cairo_surface_t *surface;
2158 if (cnnwin->
priv->toolbar_is_reconfiguring)
2162 GDateTime *date = g_date_time_new_now_utc();
2165 gp = REMMINA_PROTOCOL_WIDGET(cnnobj->
proto);
2169 REMMINA_DEBUG(
"deny_screenshot_clipboard is set to %s", denyclip);
2171 GtkClipboard *c = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
2177 REMMINA_DEBUG(
"Screenshot from plugin: w=%d h=%d bpp=%d bytespp=%d\n",
2184 cairo_format = CAIRO_FORMAT_ARGB32;
2186 cairo_format = CAIRO_FORMAT_RGB24;
2188 cairo_format = CAIRO_FORMAT_RGB16_565;
2190 stride = cairo_format_stride_for_width(cairo_format, width);
2192 srcsurface = cairo_image_surface_create_for_data(rpsd.
buffer, cairo_format, width, height, stride);
2194 if (denyclip && (g_strcmp0(denyclip,
"true")))
2195 gtk_clipboard_set_image(c, gdk_pixbuf_get_from_surface(
2196 srcsurface, 0, 0, width, height));
2197 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
2198 cr = cairo_create(surface);
2199 cairo_set_source_surface(cr, srcsurface, 0, 0);
2200 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
2202 cairo_surface_destroy(srcsurface);
2211 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
2212 _(
"Turn off scaling to avoid screenshot distortion."));
2213 g_signal_connect(G_OBJECT(dialog),
"response", G_CALLBACK(gtk_widget_destroy), NULL);
2214 gtk_widget_show(dialog);
2218 active_window = gtk_widget_get_window(GTK_WIDGET(gp));
2220 width = gdk_window_get_width(active_window);
2222 height = gdk_window_get_height(active_window);
2224 screenshot = gdk_pixbuf_get_from_window(active_window, 0, 0, width, height);
2225 if (screenshot == NULL)
2226 g_print(
"gdk_pixbuf_get_from_window failed\n");
2229 if (denyclip && (g_strcmp0(denyclip,
"true")))
2230 gtk_clipboard_set_image(c, screenshot);
2232 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
2233 cr = cairo_create(surface);
2236 gdk_cairo_set_source_pixbuf(cr, screenshot, 0, 0);
2240 g_object_unref(screenshot);
2246 pngstr = g_string_new(g_strdup_printf(
"%s/%s.png",
2254 g_strdup_printf(
"%d", g_date_time_get_year(date)));
2256 g_date_time_get_month(date)));
2258 g_strdup_printf(
"%02d", g_date_time_get_day_of_month(date)));
2260 g_strdup_printf(
"%02d", g_date_time_get_hour(date)));
2262 g_strdup_printf(
"%02d", g_date_time_get_minute(date)));
2264 g_strdup_printf(
"%02d", g_date_time_get_second(date)));
2265 g_date_time_unref(date);
2266 pngname = g_string_free(pngstr, FALSE);
2268 cairo_surface_write_to_png(surface, pngname);
2271 if (g_file_test(pngname, G_FILE_TEST_EXISTS))
2276 cairo_surface_destroy(surface);
2281 TRACE_CALL(__func__);
2283 if (cnnwin->
priv->toolbar_is_reconfiguring)
2287 gtk_window_iconify(GTK_WINDOW(cnnwin));
2292 TRACE_CALL(__func__);
2295 if (cnnwin->
priv->toolbar_is_reconfiguring)
2303 TRACE_CALL(__func__);
2307 if (cnnwin->
priv->toolbar_is_reconfiguring)
2311 capture = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle));
2319 #if DEBUG_KB_GRABBING
2320 printf(
"DEBUG_KB_GRABBING: Grabbing for button\n");
2335 TRACE_CALL(__func__);
2339 GtkToolItem *toolitem;
2343 GdkDisplay *display;
2346 display = gdk_display_get_default();
2347 n_monitors = gdk_display_get_n_monitors(display);
2351 priv->toolbar_is_reconfiguring = TRUE;
2353 toolbar = gtk_toolbar_new();
2354 gtk_widget_show(toolbar);
2355 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
2360 toolitem = gtk_toggle_tool_button_new();
2361 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"view-more-symbolic");
2362 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolitem), _(
"_Menu"));
2363 gtk_tool_item_set_tooltip_text(toolitem, _(
"Menu"));
2364 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2365 gtk_widget_show(GTK_WIDGET(toolitem));
2366 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_menu), cnnwin);
2367 priv->toolitem_menu = toolitem;
2370 toolitem = gtk_tool_button_new(NULL,
"Open Remmina Main window");
2371 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"go-home-symbolic");
2372 gtk_tool_item_set_tooltip_text(toolitem, _(
"Open the Remmina main window"));
2373 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2374 gtk_widget_show(GTK_WIDGET(toolitem));
2377 priv->toolitem_new = toolitem;
2380 toolitem = gtk_tool_button_new(NULL,
"Duplicate connection");
2381 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-duplicate-symbolic");
2382 gtk_tool_item_set_tooltip_text(toolitem, _(
"Duplicate current connection"));
2383 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2384 gtk_widget_show(GTK_WIDGET(toolitem));
2387 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2389 priv->toolitem_duplicate = toolitem;
2392 toolitem = gtk_separator_tool_item_new();
2393 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2394 gtk_widget_show(GTK_WIDGET(toolitem));
2397 toolitem = gtk_tool_button_new(NULL, NULL);
2398 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-fit-window-symbolic");
2399 rcw_set_tooltip(GTK_WIDGET(toolitem), _(
"Resize the window to fit in remote resolution"),
2402 priv->toolitem_autofit = toolitem;
2403 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2404 gtk_widget_show(GTK_WIDGET(toolitem));
2408 toolitem = gtk_toggle_tool_button_new();
2409 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-fullscreen-symbolic");
2412 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2413 gtk_widget_show(GTK_WIDGET(toolitem));
2414 priv->toolitem_fullscreen = toolitem;
2416 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), FALSE);
2418 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), mode !=
SCROLLED_WINDOW_MODE);
2423 toolitem = gtk_tool_item_new();
2424 gtk_widget_show(GTK_WIDGET(toolitem));
2425 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2426 widget = gtk_toggle_button_new();
2427 gtk_widget_show(widget);
2428 gtk_container_set_border_width(GTK_CONTAINER(widget), 0);
2429 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
2430 #if GTK_CHECK_VERSION(3, 20, 0)
2431 gtk_widget_set_focus_on_click(GTK_WIDGET(widget), FALSE);
2433 gtk_widget_set_name(widget,
"remmina-small-button");
2436 gtk_button_set_focus_on_click(GTK_BUTTON(widget), FALSE);
2438 gtk_container_add(GTK_CONTAINER(toolitem), widget);
2440 #if GTK_CHECK_VERSION(3, 14, 0)
2441 arrow = gtk_image_new_from_icon_name(
"org.remmina.Remmina-pan-down-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
2443 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2445 gtk_widget_show(arrow);
2446 gtk_container_add(GTK_CONTAINER(widget), arrow);
2448 priv->fullscreen_option_button = widget;
2450 gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE);
2453 if (n_monitors > 1) {
2454 toolitem = gtk_toggle_tool_button_new();
2455 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-multi-monitor-symbolic");
2458 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2459 gtk_widget_show(GTK_WIDGET(toolitem));
2461 priv->toolitem_multimon = toolitem;
2463 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2465 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem),
2470 toolitem = gtk_toggle_tool_button_new();
2471 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-dynres-symbolic");
2472 rcw_set_tooltip(GTK_WIDGET(toolitem), _(
"Toggle dynamic resolution update"),
2474 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2475 gtk_widget_show(GTK_WIDGET(toolitem));
2476 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_dynres), cnnwin);
2477 priv->toolitem_dynres = toolitem;
2480 toolitem = gtk_toggle_tool_button_new();
2481 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-scale-symbolic");
2483 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2484 gtk_widget_show(GTK_WIDGET(toolitem));
2486 priv->toolitem_scale = toolitem;
2489 toolitem = gtk_tool_item_new();
2490 gtk_widget_show(GTK_WIDGET(toolitem));
2491 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2492 widget = gtk_toggle_button_new();
2493 gtk_widget_show(widget);
2494 gtk_container_set_border_width(GTK_CONTAINER(widget), 0);
2495 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
2496 #if GTK_CHECK_VERSION(3, 20, 0)
2497 gtk_widget_set_focus_on_click(GTK_WIDGET(widget), FALSE);
2499 gtk_button_set_focus_on_click(GTK_BUTTON(widget), FALSE);
2502 gtk_widget_set_name(widget,
"remmina-small-button");
2503 gtk_container_add(GTK_CONTAINER(toolitem), widget);
2504 #if GTK_CHECK_VERSION(3, 14, 0)
2505 arrow = gtk_image_new_from_icon_name(
"org.remmina.Remmina-pan-down-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
2507 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2509 gtk_widget_show(arrow);
2510 gtk_container_add(GTK_CONTAINER(widget), arrow);
2512 priv->scaler_option_button = widget;
2515 toolitem = gtk_separator_tool_item_new();
2516 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2517 gtk_widget_show(GTK_WIDGET(toolitem));
2520 toolitem = gtk_toggle_tool_button_new();
2521 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-switch-page-symbolic");
2524 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2525 gtk_widget_show(GTK_WIDGET(toolitem));
2527 priv->toolitem_switch_page = toolitem;
2530 toolitem = gtk_toggle_tool_button_new();
2531 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-keyboard-symbolic");
2534 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2535 gtk_widget_show(GTK_WIDGET(toolitem));
2536 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_grab), cnnwin);
2537 priv->toolitem_grab = toolitem;
2539 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2542 if (g_strcmp0(protocol,
"SFTP") == 0 || g_strcmp0(protocol,
"SSH") == 0)
2543 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2547 toolitem = gtk_toggle_tool_button_new();
2548 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-preferences-system-symbolic");
2549 gtk_tool_item_set_tooltip_text(toolitem, _(
"Preferences"));
2550 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2551 gtk_widget_show(GTK_WIDGET(toolitem));
2553 priv->toolitem_preferences = toolitem;
2556 toolitem = gtk_toggle_tool_button_new();
2557 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-system-run-symbolic");
2558 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolitem), _(
"_Tools"));
2559 gtk_tool_item_set_tooltip_text(toolitem, _(
"Tools"));
2560 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2561 gtk_widget_show(GTK_WIDGET(toolitem));
2562 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_tools), cnnwin);
2563 priv->toolitem_tools = toolitem;
2566 toolitem = gtk_separator_tool_item_new();
2567 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2568 gtk_widget_show(GTK_WIDGET(toolitem));
2570 toolitem = gtk_tool_button_new(NULL,
"_Screenshot");
2571 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-camera-photo-symbolic");
2573 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2574 gtk_widget_show(GTK_WIDGET(toolitem));
2576 priv->toolitem_screenshot = toolitem;
2579 toolitem = gtk_separator_tool_item_new();
2580 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2581 gtk_widget_show(GTK_WIDGET(toolitem));
2584 toolitem = gtk_tool_button_new(NULL,
"_Bottom");
2585 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-go-bottom-symbolic");
2587 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2588 gtk_widget_show(GTK_WIDGET(toolitem));
2591 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2594 toolitem = gtk_tool_button_new(NULL,
"_Disconnect");
2595 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"org.remmina.Remmina-disconnect-symbolic");
2597 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2598 gtk_widget_show(GTK_WIDGET(toolitem));
2601 priv->toolbar_is_reconfiguring = FALSE;
2605 static void rcw_place_toolbar(GtkToolbar *toolbar, GtkGrid *grid, GtkWidget *sibling,
int toolbar_placement)
2610 gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_VERTICAL);
2612 gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
2615 switch (toolbar_placement) {
2617 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), TRUE);
2618 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), FALSE);
2619 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_TOP, 1, 1);
2622 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), TRUE);
2623 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), FALSE);
2624 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_RIGHT, 1, 1);
2627 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), TRUE);
2628 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), FALSE);
2629 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_BOTTOM, 1, 1);
2632 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), TRUE);
2633 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), FALSE);
2634 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_LEFT, 1, 1);
2641 TRACE_CALL(__func__);
2643 GtkToolItem *toolitem;
2644 gboolean bval, dynres_avail, scale_avail;
2645 gboolean test_floating_toolbar;
2648 priv->toolbar_is_reconfiguring = TRUE;
2652 toolitem = priv->toolitem_switch_page;
2656 bval = (gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)) > 1);
2657 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval);
2660 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_duplicate), TRUE);
2662 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_duplicate), FALSE);
2665 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_dynres), dynres_avail && cnnobj->
connected);
2666 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_scale), scale_avail && cnnobj->
connected);
2668 switch (scalemode) {
2670 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_dynres), FALSE);
2671 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), FALSE);
2672 gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), FALSE);
2675 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_dynres), FALSE);
2676 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), TRUE);
2677 gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), TRUE && cnnobj->
connected);
2680 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_dynres), TRUE);
2681 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), FALSE);
2682 gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), FALSE);
2687 toolitem = priv->toolitem_multimon;
2692 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), cnnobj->
connected);
2693 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem),
2695 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), hasmultimon);
2698 toolitem = priv->toolitem_grab;
2699 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), cnnobj->
connected);
2700 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem),
2703 if (g_strcmp0(protocol,
"SFTP") == 0 || g_strcmp0(protocol,
"SSH") == 0) {
2704 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2705 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), FALSE);
2709 toolitem = priv->toolitem_preferences;
2710 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), cnnobj->
connected);
2713 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval && cnnobj->
connected);
2715 toolitem = priv->toolitem_tools;
2718 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval && cnnobj->
connected);
2720 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_screenshot), cnnobj->
connected);
2724 test_floating_toolbar = (priv->floating_toolbar_widget != NULL);
2726 if (test_floating_toolbar) {
2728 const gchar *format;
2733 if (!gdk_rgba_parse(&rgba, bg)) {
2734 REMMINA_DEBUG(
"%s cannot be parsed as a color", bg);
2735 bg = g_strdup(
"#00FF00");
2737 REMMINA_DEBUG(
"Using %s as background color", bg);
2742 gtk_widget_override_background_color(priv->overlay_ftb_fr, GTK_STATE_NORMAL, &rgba);
2743 format = g_strconcat(
"<span bgcolor=\"", bg,
"\" size=\"large\"><b>(G: ON) - \%s</b></span>", NULL);
2745 gtk_widget_override_background_color(priv->overlay_ftb_fr, GTK_STATE_NORMAL, NULL);
2746 format =
"<big><b>(G: ON) - \%s</b></big>";
2749 gtk_widget_override_background_color(priv->overlay_ftb_fr, GTK_STATE_NORMAL, NULL);
2750 format =
"<big><b>(G:OFF) - \%s</b></big>";
2754 markup = g_markup_printf_escaped(format, str);
2755 gtk_label_set_markup(GTK_LABEL(priv->floating_toolbar_label), markup);
2760 priv->toolbar_is_reconfiguring = FALSE;
2765 TRACE_CALL(__func__);
2770 gtk_widget_hide(priv->toolbar);
2772 gtk_widget_show(priv->toolbar);
2776 #if DEBUG_KB_GRABBING
2778 printf(
"DEBUG_KB_GRABBING: --- Crossing event detail: ");
2779 switch (event->detail) {
2780 case GDK_NOTIFY_ANCESTOR: printf(
"GDK_NOTIFY_ANCESTOR");
break;
2781 case GDK_NOTIFY_VIRTUAL: printf(
"GDK_NOTIFY_VIRTUAL");
break;
2782 case GDK_NOTIFY_NONLINEAR: printf(
"GDK_NOTIFY_NONLINEAR");
break;
2783 case GDK_NOTIFY_NONLINEAR_VIRTUAL: printf(
"GDK_NOTIFY_NONLINEAR_VIRTUAL");
break;
2784 case GDK_NOTIFY_UNKNOWN: printf(
"GDK_NOTIFY_UNKNOWN");
break;
2785 case GDK_NOTIFY_INFERIOR: printf(
"GDK_NOTIFY_INFERIOR");
break;
2786 default: printf(
"unknown");
2789 printf(
"DEBUG_KB_GRABBING: --- Crossing event mode=");
2790 switch (event->mode) {
2791 case GDK_CROSSING_NORMAL: printf(
"GDK_CROSSING_NORMAL");
break;
2792 case GDK_CROSSING_GRAB: printf(
"GDK_CROSSING_GRAB");
break;
2793 case GDK_CROSSING_UNGRAB: printf(
"GDK_CROSSING_UNGRAB");
break;
2794 case GDK_CROSSING_GTK_GRAB: printf(
"GDK_CROSSING_GTK_GRAB");
break;
2795 case GDK_CROSSING_GTK_UNGRAB: printf(
"GDK_CROSSING_GTK_UNGRAB");
break;
2796 case GDK_CROSSING_STATE_CHANGED: printf(
"GDK_CROSSING_STATE_CHANGED");
break;
2797 case GDK_CROSSING_TOUCH_BEGIN: printf(
"GDK_CROSSING_TOUCH_BEGIN");
break;
2798 case GDK_CROSSING_TOUCH_END: printf(
"GDK_CROSSING_TOUCH_END");
break;
2799 case GDK_CROSSING_DEVICE_SWITCH: printf(
"GDK_CROSSING_DEVICE_SWITCH");
break;
2800 default: printf(
"unknown");
2809 TRACE_CALL(__func__);
2817 TRACE_CALL(__func__);
2818 if (event->detail != GDK_NOTIFY_INFERIOR)
2827 TRACE_CALL(__func__);
2828 #if DEBUG_KB_GRABBING
2829 printf(
"DEBUG_KB_GRABBING: enter-notify-event on rcw received\n");
2840 TRACE_CALL(__func__);
2843 #if DEBUG_KB_GRABBING
2844 printf(
"DEBUG_KB_GRABBING: leave-notify-event on rcw received\n");
2848 if (event->mode != GDK_CROSSING_NORMAL && event->mode != GDK_CROSSING_UNGRAB) {
2849 #if DEBUG_KB_GRABBING
2850 printf(
"DEBUG_KB_GRABBING: ignored because mode is not GDK_CROSSING_NORMAL GDK_CROSSING_UNGRAB\n");
2855 if (cnnwin->
priv->delayed_grab_eventsourceid) {
2856 g_source_remove(cnnwin->
priv->delayed_grab_eventsourceid);
2857 cnnwin->
priv->delayed_grab_eventsourceid = 0;
2861 if (event->mode != GDK_CROSSING_UNGRAB) {
2865 #if DEBUG_KB_GRABBING
2866 printf(
"DEBUG_KB_GRABBING: not ungrabbing, this event seems to be an unwanted event from GTK\n");
2877 TRACE_CALL(__func__);
2879 #if DEBUG_KB_GRABBING
2880 printf(
"DEBUG_KB_GRABBING: received leave event on RCO.\n");
2884 if (cnnobj->
cnnwin->
priv->delayed_grab_eventsourceid) {
2885 g_source_remove(cnnobj->
cnnwin->
priv->delayed_grab_eventsourceid);
2886 cnnobj->
cnnwin->
priv->delayed_grab_eventsourceid = 0;
2889 cnnobj->
cnnwin->
priv->pointer_entered = FALSE;
2892 if (event->mode == GDK_CROSSING_NORMAL && event->detail != GDK_NOTIFY_INFERIOR)
2902 TRACE_CALL(__func__);
2905 #if DEBUG_KB_GRABBING
2906 printf(
"DEBUG_KB_GRABBING: %s: enter on protocol widget event received\n", __func__);
2911 if (!priv->sticky && event->mode == GDK_CROSSING_NORMAL)
2914 priv->pointer_entered = TRUE;
2916 if (event->mode == GDK_CROSSING_UNGRAB) {
2919 cnnobj->
cnnwin->
priv->pointer_captured = FALSE;
2924 active = gtk_window_is_active(GTK_WINDOW(cnnobj->
cnnwin));
2935 TRACE_CALL(__func__);
2937 #if DEBUG_KB_GRABBING
2938 printf(
"DEBUG_KB_GRABBING: %s\n", __func__);
2940 if (cnnwin->
priv->pointer_entered) {
2941 #if DEBUG_KB_GRABBING
2942 printf(
"DEBUG_KB_GRABBING: delayed requesting kb and pointer grab, because of pointer inside\n");
2947 #if DEBUG_KB_GRABBING
2949 printf(
"DEBUG_KB_GRABBING: %s not grabbing because pointer_entered is false\n", __func__);
2952 cnnwin->
priv->delayed_grab_eventsourceid = 0;
2953 return G_SOURCE_REMOVE;
2963 TRACE_CALL(__func__);
2969 #if DEBUG_KB_GRABBING
2970 printf(
"DEBUG_KB_GRABBING: Received focus in on rcw, grabbing enabled: requesting kb grab, delayed\n");
2972 if (cnnwin->
priv->delayed_grab_eventsourceid == 0)
2975 #if DEBUG_KB_GRABBING
2977 printf(
"DEBUG_KB_GRABBING: Received focus in on rcw, but a condition will prevent to grab\n");
2989 TRACE_CALL(__func__);
2994 cnnwin->
priv->hostkey_activated = FALSE;
3008 TRACE_CALL(__func__);
3011 priv->hidetb_eventsource = 0;
3013 return G_SOURCE_REMOVE;
3019 TRACE_CALL(__func__);
3029 switch (event->direction) {
3037 case GDK_SCROLL_DOWN:
3038 if (opacity < TOOLBAR_OPACITY_LEVEL) {
3044 #if GTK_CHECK_VERSION(3, 4, 0)
3045 case GDK_SCROLL_SMOOTH:
3046 if (event->delta_y < 0 && opacity > 0) {
3051 if (event->delta_y > 0 && opacity < TOOLBAR_OPACITY_LEVEL) {
3066 TRACE_CALL(__func__);
3074 if (!cnnwin || !cnnwin->
priv)
3077 s = gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnwin)));
3082 npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnwin->
priv->notebook));
3083 for (ipg = 0; ipg < npages; ipg++) {
3085 cnnobj = g_object_get_data(
3086 G_OBJECT(gtk_notebook_get_nth_page(GTK_NOTEBOOK(cnnwin->
priv->notebook), ipg)),
3088 if (s & GDK_WINDOW_STATE_MAXIMIZED) {
3091 gtk_window_get_size(GTK_WINDOW(cnnobj->
cnnwin), &width, &height);
3097 cnnwin->
priv->acs_eventsourceid = 0;
3104 TRACE_CALL(__func__);
3108 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
3115 if (cnnwin->
priv->acs_eventsourceid) {
3116 g_source_remove(cnnwin->
priv->acs_eventsourceid);
3117 cnnwin->
priv->acs_eventsourceid = 0;
3120 if (gtk_widget_get_window(GTK_WIDGET(cnnwin))
3135 TRACE_CALL(__func__);
3136 if (cnnwin->
priv->pin_down)
3137 gtk_button_set_image(GTK_BUTTON(cnnwin->
priv->pin_button),
3138 gtk_image_new_from_icon_name(
"org.remmina.Remmina-pin-down-symbolic", GTK_ICON_SIZE_MENU));
3140 gtk_button_set_image(GTK_BUTTON(cnnwin->
priv->pin_button),
3141 gtk_image_new_from_icon_name(
"org.remmina.Remmina-pin-up-symbolic", GTK_ICON_SIZE_MENU));
3146 TRACE_CALL(__func__);
3154 TRACE_CALL(__func__);
3157 GtkWidget *ftb_widget;
3161 GtkWidget *pinbutton;
3166 ftb_widget = gtk_event_box_new();
3168 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
3169 gtk_widget_show(vbox);
3171 gtk_container_add(GTK_CONTAINER(ftb_widget), vbox);
3174 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
3175 gtk_widget_show(hbox);
3179 pinbutton = gtk_button_new();
3180 gtk_widget_show(pinbutton);
3181 gtk_box_pack_start(GTK_BOX(hbox), pinbutton, FALSE, FALSE, 0);
3182 gtk_button_set_relief(GTK_BUTTON(pinbutton), GTK_RELIEF_NONE);
3183 #if GTK_CHECK_VERSION(3, 20, 0)
3184 gtk_widget_set_focus_on_click(GTK_WIDGET(pinbutton), FALSE);
3186 gtk_button_set_focus_on_click(GTK_BUTTON(pinbutton), FALSE);
3188 gtk_widget_set_name(pinbutton,
"remmina-pin-button");
3189 g_signal_connect(G_OBJECT(pinbutton),
"clicked", G_CALLBACK(
rcw_toolbar_pin), cnnwin);
3190 priv->pin_button = pinbutton;
3195 label = gtk_label_new(
"");
3196 gtk_label_set_max_width_chars(GTK_LABEL(label), 50);
3197 gtk_widget_show(label);
3199 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3201 priv->floating_toolbar_label = label;
3204 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
3205 gtk_box_pack_start(GTK_BOX(vbox), tb, FALSE, FALSE, 0);
3207 gtk_box_pack_start(GTK_BOX(vbox), tb, FALSE, FALSE, 0);
3208 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
3211 priv->floating_toolbar_widget = ftb_widget;
3212 gtk_widget_show(ftb_widget);
3217 TRACE_CALL(__func__);
3220 priv = cnnwin->
priv;
3222 if (priv->toolbar && priv->grid) {
3223 g_object_ref(priv->toolbar);
3224 gtk_container_remove(GTK_CONTAINER(priv->grid), priv->toolbar);
3226 g_object_unref(priv->toolbar);
3233 TRACE_CALL(__func__);
3237 cnnwin->
priv = priv;
3243 priv->floating_toolbar_opacity = 1.0;
3244 priv->kbcaptured = FALSE;
3245 priv->pointer_captured = FALSE;
3246 priv->pointer_entered = FALSE;
3248 priv->ss_width = 640;
3249 priv->ss_height = 480;
3250 priv->ss_maximized = FALSE;
3257 TRACE_CALL(__func__);
3258 #if DEBUG_KB_GRABBING
3259 printf(
"DEBUG_KB_GRABBING: RCW focus-in-event received\n");
3267 TRACE_CALL(__func__);
3268 #if DEBUG_KB_GRABBING
3269 printf(
"DEBUG_KB_GRABBING: RCW focus-out-event received\n");
3276 static gboolean
rcw_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
3278 TRACE_CALL(__func__);
3280 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
3283 #if DEBUG_KB_GRABBING
3284 printf(
"DEBUG_KB_GRABBING: window-state-event received\n");
3287 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED) {
3288 if (event->new_window_state & GDK_WINDOW_STATE_FOCUSED)
3297 static gboolean
rcw_map_event(GtkWidget *widget, GdkEvent *event, gpointer data)
3299 TRACE_CALL(__func__);
3307 if (cnnwin->
priv->toolbar_is_reconfiguring)
return FALSE;
3310 gp = REMMINA_PROTOCOL_WIDGET(cnnobj->
proto);
3311 REMMINA_DEBUG(
"Mapping: %s", gtk_widget_get_name(widget));
3313 REMMINA_DEBUG(
"Called plugin mapping function");
3319 TRACE_CALL(__func__);
3325 if (cnnwin->
priv->toolbar_is_reconfiguring)
return FALSE;
3328 gp = REMMINA_PROTOCOL_WIDGET(cnnobj->
proto);
3329 REMMINA_DEBUG(
"Unmapping: %s", gtk_widget_get_name(widget));
3331 REMMINA_DEBUG(
"Called plugin mapping function");
3337 TRACE_CALL(__func__);
3339 gint target_monitor;
3341 REMMINA_DEBUG(
"Mapping: %s", gtk_widget_get_name(widget));
3343 if (!REMMINA_IS_CONNECTION_WINDOW(widget)) {
3344 REMMINA_DEBUG(
"Remmina Connection Window undefined, cannot go fullscreen");
3352 REMMINA_DEBUG(
"Remmina Connection Object undefined, cannot go fullscreen");
3359 REMMINA_DEBUG(
"Remmina Protocol Widget undefined, cannot go fullscreen");
3362 REMMINA_DEBUG(
"Fullscreen on all monitor");
3363 gdk_window_set_fullscreen_mode(gtk_widget_get_window(widget), GDK_FULLSCREEN_ON_ALL_MONITORS);
3364 gdk_window_fullscreen(gtk_widget_get_window(widget));
3367 REMMINA_DEBUG(
"Fullscreen on one monitor");
3370 target_monitor = GPOINTER_TO_INT(data);
3372 #if GTK_CHECK_VERSION(3, 18, 0)
3374 if (target_monitor == FULL_SCREEN_TARGET_MONITOR_UNDEFINED)
3375 gtk_window_fullscreen(GTK_WINDOW(widget));
3377 gtk_window_fullscreen_on_monitor(GTK_WINDOW(widget), gtk_window_get_screen(GTK_WINDOW(widget)),
3380 REMMINA_DEBUG(
"Fullscreen managed by WM or by the user, as per settings");
3381 gtk_window_fullscreen(GTK_WINDOW(widget));
3384 REMMINA_DEBUG(
"Cannot fullscreen on a specific monitor, feature available from GTK 3.18");
3385 gtk_window_fullscreen(GTK_WINDOW(widget));
3389 REMMINA_DEBUG(
"Called plugin mapping function");
3397 TRACE_CALL(__func__);
3400 cnnwin = RCW(g_object_new(REMMINA_TYPE_CONNECTION_WINDOW, NULL));
3405 g_signal_connect(G_OBJECT(cnnwin),
"map-event", G_CALLBACK(
rcw_map_event_fullscreen), GINT_TO_POINTER(full_screen_target_monitor));
3407 g_signal_connect(G_OBJECT(cnnwin),
"map-event", G_CALLBACK(
rcw_map_event), NULL);
3408 g_signal_connect(G_OBJECT(cnnwin),
"unmap-event", G_CALLBACK(
rcw_unmap_event), NULL);
3410 gtk_container_set_border_width(GTK_CONTAINER(cnnwin), 0);
3413 g_signal_connect(G_OBJECT(cnnwin),
"delete-event", G_CALLBACK(
rcw_delete_event), NULL);
3414 g_signal_connect(G_OBJECT(cnnwin),
"destroy", G_CALLBACK(
rcw_destroy), NULL);
3421 g_signal_connect(G_OBJECT(cnnwin),
"window-state-event", G_CALLBACK(
rcw_state_event), NULL);
3422 g_signal_connect(G_OBJECT(cnnwin),
"focus-in-event", G_CALLBACK(
rcw_focus_in_event), NULL);
3423 g_signal_connect(G_OBJECT(cnnwin),
"focus-out-event", G_CALLBACK(
rcw_focus_out_event), NULL);
3429 g_signal_connect(G_OBJECT(cnnwin),
"configure_event", G_CALLBACK(
rcw_on_configure), NULL);
3439 TRACE_CALL(__func__);
3453 g_object_set_data_full(G_OBJECT(cnnwin),
"tag", tag, (GDestroyNotify)g_free);
3458 TRACE_CALL(__func__);
3463 if (GTK_IS_WIDGET(cnnobj->
proto))
3470 GtkWidget *found_page, *pg;
3472 if (cnnobj == NULL || cnnobj->
cnnwin == NULL || cnnobj->
cnnwin->
priv == NULL)
3475 np = gtk_notebook_get_n_pages(cnnobj->
cnnwin->
priv->notebook);
3476 for (i = 0; i < np; i++) {
3477 pg = gtk_notebook_get_nth_page(cnnobj->
cnnwin->
priv->notebook, i);
3478 if (g_object_get_data(G_OBJECT(pg),
"cnnobj") == cnnobj) {
3490 TRACE_CALL(__func__);
3492 GtkWidget *page_to_remove;
3496 REMMINA_DEBUG(
"deleting motion");
3500 if (cnnobj && cnnobj->
cnnwin) {
3502 if (page_to_remove) {
3503 gtk_notebook_remove_page(
3505 gtk_notebook_page_num(cnnobj->
cnnwin->
priv->notebook, page_to_remove));
3525 TRACE_CALL(__func__);
3526 if (REMMINA_IS_PROTOCOL_WIDGET(cnnobj->
proto)) {
3536 TRACE_CALL(__func__);
3541 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
3542 gtk_widget_show(hbox);
3545 gtk_widget_show(widget);
3546 gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
3549 gtk_widget_set_valign(widget, GTK_ALIGN_CENTER);
3550 gtk_widget_set_halign(widget, GTK_ALIGN_CENTER);
3552 gtk_widget_show(widget);
3553 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
3555 button = gtk_button_new();
3556 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
3557 #if GTK_CHECK_VERSION(3, 20, 0)
3558 gtk_widget_set_focus_on_click(GTK_WIDGET(widget), FALSE);
3560 gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
3562 gtk_widget_set_name(button,
"remmina-small-button");
3563 gtk_widget_show(button);
3565 widget = gtk_image_new_from_icon_name(
"window-close", GTK_ICON_SIZE_MENU);
3566 gtk_widget_show(widget);
3567 gtk_container_add(GTK_CONTAINER(button), widget);
3569 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3581 page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
3582 gtk_widget_set_name(page,
"remmina-tab-page");
3590 TRACE_CALL(__func__);
3591 GtkWidget *page, *label;
3592 GtkNotebook *notebook;
3594 notebook = cnnwin->
priv->notebook;
3597 g_object_set_data(G_OBJECT(page),
"cnnobj", cnnobj);
3602 gtk_notebook_append_page(notebook, page, label);
3603 gtk_notebook_set_tab_reorderable(notebook, page, TRUE);
3604 gtk_notebook_set_tab_detachable(notebook, page, TRUE);
3606 gtk_widget_set_can_focus(gtk_widget_get_parent(label), FALSE);
3609 printf(
"REMMINA WARNING in %s: scrolled_container already has a parent\n", __func__);
3612 gtk_widget_show(page);
3620 TRACE_CALL(__func__);
3621 GtkNotebook *notebook;
3624 notebook = GTK_NOTEBOOK(cnnwin->
priv->notebook);
3626 switch (cnnwin->
priv->view_mode) {
3628 n = gtk_notebook_get_n_pages(notebook);
3633 gtk_notebook_set_show_tabs(notebook, FALSE);
3634 gtk_notebook_set_show_border(notebook, FALSE);
3641 TRACE_CALL(__func__);
3654 if (GTK_IS_WIDGET(cnnobj->
cnnwin)) {
3656 if (!priv->hidetb_eventsource)
3657 priv->hidetb_eventsource = g_timeout_add(TB_HIDE_TIME_TIME, (GSourceFunc)
3664 priv->spf_eventsourceid = 0;
3671 TRACE_CALL(__func__);
3675 cnnobj_newpage = g_object_get_data(G_OBJECT(newpage),
"cnnobj");
3676 if (priv->spf_eventsourceid)
3677 g_source_remove(priv->spf_eventsourceid);
3684 if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnwin->
priv->notebook)) > 0)
3691 TRACE_CALL(__func__);
3693 if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnwin->
priv->notebook)) <= 0)
3694 gtk_widget_destroy(GTK_WIDGET(cnnwin));
3698 static GtkNotebook *
3704 TRACE_CALL(__func__);
3712 #if GTK_CHECK_VERSION(3, 20, 0)
3715 GdkDeviceManager *manager;
3717 GdkDevice *device = NULL;
3719 #if GTK_CHECK_VERSION(3, 20, 0)
3720 seat = gdk_display_get_default_seat(gdk_display_get_default());
3721 device = gdk_seat_get_pointer(seat);
3723 manager = gdk_display_get_device_manager(gdk_display_get_default());
3724 device = gdk_device_manager_get_client_pointer(manager);
3727 window = gdk_device_get_window_at_position(device, &x, &y);
3728 srccnnwin = RCW(gtk_widget_get_toplevel(GTK_WIDGET(notebook)));
3731 if (srccnnwin == dstcnnwin)
3734 if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(srccnnwin->
priv->notebook)) == 1 && !dstcnnwin)
3743 srctag = (gchar *)g_object_get_data(G_OBJECT(srccnnwin),
"tag");
3744 gtk_window_get_size(GTK_WINDOW(srccnnwin), &width, &height);
3746 g_object_set_data_full(G_OBJECT(dstcnnwin),
"tag", g_strdup(srctag), (GDestroyNotify)g_free);
3749 cnnobj->
cnnwin = dstcnnwin;
3751 cnnobj->
cnnwin = dstcnnwin;
3757 return GTK_NOTEBOOK(cnnobj->
cnnwin->
priv->notebook);
3760 static GtkNotebook *
3763 TRACE_CALL(__func__);
3764 GtkNotebook *notebook;
3766 notebook = GTK_NOTEBOOK(gtk_notebook_new());
3768 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3769 gtk_widget_show(GTK_WIDGET(notebook));
3772 g_signal_connect(G_OBJECT(notebook),
"switch-page", G_CALLBACK(
rcw_on_switch_page), cnnwin);
3773 g_signal_connect(G_OBJECT(notebook),
"page-added", G_CALLBACK(
rcw_on_page_added), cnnwin);
3774 g_signal_connect(G_OBJECT(notebook),
"page-removed", G_CALLBACK(
rcw_on_page_removed), cnnwin);
3775 gtk_widget_set_can_focus(GTK_WIDGET(notebook), FALSE);
3783 TRACE_CALL(__func__);
3787 GtkNotebook *notebook;
3788 GtkSettings *settings = gtk_settings_get_default();
3791 gtk_widget_realize(GTK_WIDGET(cnnwin));
3793 gtk_window_set_default_size(GTK_WINDOW(cnnwin), width, height);
3803 grid = gtk_grid_new();
3806 gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(notebook), 0, 0, 1, 1);
3808 gtk_widget_set_hexpand(GTK_WIDGET(notebook), TRUE);
3809 gtk_widget_set_vexpand(GTK_WIDGET(notebook), TRUE);
3813 gtk_container_add(GTK_CONTAINER(cnnwin), grid);
3816 gtk_drag_source_set(GTK_WIDGET(toolbar), GDK_BUTTON1_MASK,
3818 g_signal_connect_after(GTK_WIDGET(toolbar),
"drag-begin", G_CALLBACK(
rcw_tb_drag_begin), NULL);
3819 g_signal_connect(GTK_WIDGET(toolbar),
"drag-failed", G_CALLBACK(
rcw_tb_drag_failed), cnnwin);
3822 gtk_drag_dest_set(GTK_WIDGET(notebook), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
3824 gtk_drag_dest_set_track_motion(GTK_WIDGET(notebook), TRUE);
3825 g_signal_connect(GTK_WIDGET(notebook),
"drag-drop", G_CALLBACK(
rcw_tb_drag_drop), cnnwin);
3828 cnnwin->
priv->toolbar = toolbar;
3829 cnnwin->
priv->grid = grid;
3830 cnnwin->
priv->notebook = notebook;
3831 cnnwin->
priv->ss_width = width;
3832 cnnwin->
priv->ss_height = height;
3833 cnnwin->
priv->ss_maximized = maximize;
3837 gtk_widget_show(grid);
3838 gtk_widget_show(GTK_WIDGET(cnnwin));
3839 GtkWindowGroup *wingrp = gtk_window_group_new();
3841 gtk_window_group_add_window(wingrp, GTK_WINDOW(cnnwin));
3842 gtk_window_set_transient_for(GTK_WINDOW(cnnwin), NULL);
3845 gtk_window_maximize(GTK_WINDOW(cnnwin));
3855 TRACE_CALL(__func__);
3857 GtkWidget *revealer;
3860 priv = cnnwin->
priv;
3862 if (priv->overlay_ftb_overlay != NULL) {
3863 gtk_widget_destroy(priv->overlay_ftb_overlay);
3864 priv->overlay_ftb_overlay = NULL;
3865 priv->revealer = NULL;
3867 if (priv->overlay_ftb_fr != NULL) {
3868 gtk_widget_destroy(priv->overlay_ftb_fr);
3869 priv->overlay_ftb_fr = NULL;
3874 priv->overlay_ftb_overlay = gtk_event_box_new();
3876 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
3878 gtk_container_set_border_width(GTK_CONTAINER(vbox), 0);
3880 GtkWidget *handle = gtk_drawing_area_new();
3882 gtk_widget_set_size_request(handle, 4, 4);
3883 gtk_widget_set_name(handle,
"ftb-handle");
3885 revealer = gtk_revealer_new();
3887 gtk_widget_set_halign(GTK_WIDGET(priv->overlay_ftb_overlay), GTK_ALIGN_CENTER);
3890 gtk_box_pack_start(GTK_BOX(vbox), handle, FALSE, FALSE, 0);
3891 gtk_box_pack_start(GTK_BOX(vbox), revealer, FALSE, FALSE, 0);
3892 gtk_revealer_set_transition_type(GTK_REVEALER(revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
3893 gtk_widget_set_valign(GTK_WIDGET(priv->overlay_ftb_overlay), GTK_ALIGN_END);
3895 gtk_box_pack_start(GTK_BOX(vbox), revealer, FALSE, FALSE, 0);
3896 gtk_box_pack_start(GTK_BOX(vbox), handle, FALSE, FALSE, 0);
3897 gtk_revealer_set_transition_type(GTK_REVEALER(revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
3898 gtk_widget_set_valign(GTK_WIDGET(priv->overlay_ftb_overlay), GTK_ALIGN_START);
3902 gtk_container_add(GTK_CONTAINER(revealer), priv->floating_toolbar_widget);
3903 gtk_widget_set_halign(GTK_WIDGET(revealer), GTK_ALIGN_CENTER);
3904 gtk_widget_set_valign(GTK_WIDGET(revealer), GTK_ALIGN_START);
3906 priv->revealer = revealer;
3910 fr = gtk_frame_new(NULL);
3911 priv->overlay_ftb_fr = fr;
3912 gtk_container_add(GTK_CONTAINER(priv->overlay_ftb_overlay), fr);
3913 gtk_container_add(GTK_CONTAINER(fr), vbox);
3915 gtk_widget_show(vbox);
3916 gtk_widget_show(revealer);
3917 gtk_widget_show(handle);
3918 gtk_widget_show(priv->overlay_ftb_overlay);
3919 gtk_widget_show(fr);
3922 gtk_widget_set_name(fr,
"ftbbox-lower");
3924 gtk_widget_set_name(fr,
"ftbbox-upper");
3926 gtk_overlay_add_overlay(GTK_OVERLAY(priv->overlay), priv->overlay_ftb_overlay);
3933 gtk_widget_add_events(
3934 GTK_WIDGET(priv->overlay_ftb_overlay),
3936 #
if GTK_CHECK_VERSION(3, 4, 0)
3937 | GDK_SMOOTH_SCROLL_MASK
3942 gtk_drag_source_set(GTK_WIDGET(priv->overlay_ftb_overlay), GDK_BUTTON1_MASK,
3944 g_signal_connect_after(GTK_WIDGET(priv->overlay_ftb_overlay),
"drag-begin", G_CALLBACK(
rcw_ftb_drag_begin), cnnwin);
3948 gtk_widget_hide(fr);
3955 TRACE_CALL(__func__);
3957 gint new_floating_toolbar_placement;
3960 gtk_widget_get_allocation(widget, &wa);
3962 if (y >= wa.height / 2)
3967 gtk_drag_finish(context, TRUE, TRUE, time);
3983 TRACE_CALL(__func__);
3985 cairo_surface_t *surface;
3988 double dashes[] = { 10 };
3990 gtk_widget_get_allocation(widget, &wa);
3992 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, wa.width, wa.height);
3993 cr = cairo_create(surface);
3994 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
3995 cairo_set_line_width(cr, 2);
3996 cairo_set_dash(cr, dashes, 1, 0);
3997 cairo_rectangle(cr, 0, 0, wa.width, wa.height);
4001 gtk_drag_set_icon_surface(context, surface);
4006 TRACE_CALL(__func__);
4008 GtkNotebook *notebook;
4010 #if GTK_CHECK_VERSION(3, 22, 0)
4013 GdkMonitor *old_monitor;
4014 GdkDisplay *old_display;
4015 GdkWindow *old_window;
4017 gint full_screen_target_monitor;
4019 full_screen_target_monitor = FULL_SCREEN_TARGET_MONITOR_UNDEFINED;
4021 #if GTK_CHECK_VERSION(3, 22, 0)
4022 old_window = gtk_widget_get_window(GTK_WIDGET(old));
4023 old_display = gdk_window_get_display(old_window);
4024 old_monitor = gdk_display_get_monitor_at_window(old_display, old_window);
4025 n_monitors = gdk_display_get_n_monitors(old_display);
4026 for (i = 0; i < n_monitors; ++i) {
4027 if (gdk_display_get_monitor(old_display, i) == old_monitor) {
4028 full_screen_target_monitor = i;
4033 full_screen_target_monitor = gdk_screen_get_monitor_at_window(
4034 gdk_screen_get_default(),
4035 gtk_widget_get_window(GTK_WIDGET(old)));
4039 cnnwin =
rcw_new(TRUE, full_screen_target_monitor);
4040 gtk_widget_set_name(GTK_WIDGET(cnnwin),
"remmina-connection-window-fullscreen");
4041 gtk_widget_realize(GTK_WIDGET(cnnwin));
4048 cnnwin->
priv->overlay = gtk_overlay_new();
4049 gtk_container_add(GTK_CONTAINER(cnnwin), cnnwin->
priv->overlay);
4050 gtk_container_add(GTK_CONTAINER(cnnwin->
priv->overlay), GTK_WIDGET(notebook));
4051 gtk_widget_show(GTK_WIDGET(cnnwin->
priv->overlay));
4053 cnnwin->
priv->notebook = notebook;
4054 cnnwin->
priv->view_mode = view_mode;
4055 cnnwin->
priv->fss_view_mode = view_mode;
4060 gtk_drag_dest_set(GTK_WIDGET(cnnwin->
priv->overlay), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
4062 gtk_drag_dest_set_track_motion(GTK_WIDGET(cnnwin->
priv->notebook), TRUE);
4063 g_signal_connect(GTK_WIDGET(cnnwin->
priv->overlay),
"drag-drop", G_CALLBACK(
rcw_ftb_drag_drop), cnnwin);
4065 gtk_widget_show(GTK_WIDGET(cnnwin));
4066 GtkWindowGroup *wingrp = gtk_window_group_new();
4067 gtk_window_group_add_window(wingrp, GTK_WINDOW(cnnwin));
4068 gtk_window_set_transient_for(GTK_WINDOW(cnnwin), NULL);
4075 TRACE_CALL(__func__);
4083 priv->hostkey_activated = FALSE;
4084 if (priv->hostkey_used)
4091 else if (priv->hostkey_activated) {
4101 priv->hostkey_activated = TRUE;
4102 priv->hostkey_used = FALSE;
4104 }
else if (!priv->hostkey_activated) {
4109 priv->hostkey_used = TRUE;
4110 keyval = gdk_keyval_to_lower(keyval);
4111 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down
4112 || keyval == GDK_KEY_Left || keyval == GDK_KEY_Right) {
4113 GtkAdjustment *adjust;
4117 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down)
4118 adjust = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container));
4120 adjust = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container));
4122 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Left)
4125 pos = gtk_adjustment_get_upper(adjust);
4127 gtk_adjustment_set_value(adjust, pos);
4128 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down)
4129 gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container), adjust);
4131 gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container), adjust);
4144 child = gtk_bin_get_child(GTK_BIN(gsv));
4145 if (!GTK_IS_VIEWPORT(child))
4148 gsvwin = gtk_widget_get_window(GTK_WIDGET(gsv));
4152 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down) {
4153 sz = gdk_window_get_height(gsvwin) + 2;
4154 adj = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(child));
4156 sz = gdk_window_get_width(gsvwin) + 2;
4157 adj = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(child));
4160 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Left)
4163 value = gtk_adjustment_get_upper(GTK_ADJUSTMENT(adj)) - (gdouble)sz + 2.0;
4165 gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), value);
4170 switch (priv->view_mode) {
4182 if (priv->toolitem_autofit && gtk_widget_is_sensitive(GTK_WIDGET(priv->toolitem_autofit)))
4185 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook)) + 1;
4186 if (i >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)))
4188 gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), i);
4190 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook)) - 1;
4192 i = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)) - 1;
4193 gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), i);
4199 if (gtk_widget_is_sensitive(GTK_WIDGET(priv->toolitem_scale))) {
4200 gtk_toggle_tool_button_set_active(
4201 GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale),
4202 !gtk_toggle_tool_button_get_active(
4203 GTK_TOGGLE_TOOL_BUTTON(
4204 priv->toolitem_scale)));
4207 gtk_toggle_tool_button_set_active(
4208 GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_grab),
4209 !gtk_toggle_tool_button_get_active(
4210 GTK_TOGGLE_TOOL_BUTTON(
4211 priv->toolitem_grab)));
4233 REMMINA_PROTOCOL_WIDGET(
4235 feature && feature->
type;
4239 && GPOINTER_TO_UINT(
4243 REMMINA_PROTOCOL_WIDGET(
4252 cnnobj->
cnnwin->
priv->hostkey_activated = FALSE;
4260 TRACE_CALL(__func__);
4285 gtk_window_present_with_time(GTK_WINDOW(cnnwin), (guint32)(g_get_monotonic_time() / 1000));
4288 cnnwin->
priv->dwp_eventsourceid = 0;
4289 return G_SOURCE_REMOVE;
4294 TRACE_CALL(__func__);
4296 REMMINA_DEBUG(
"Connect signal emitted");
4312 REMMINA_DEBUG(
"We save the last successful connection date");
4317 REMMINA_DEBUG(
"Saving credentials");
4321 if (cnnobj->
cnnwin->
priv->floating_toolbar_widget)
4322 gtk_widget_show(cnnobj->
cnnwin->
priv->floating_toolbar_widget);
4326 REMMINA_DEBUG(
"Trying to present the window");
4333 TRACE_CALL(__func__);
4339 TRACE_CALL(__func__);
4344 REMMINA_DEBUG(
"Disconnect signal received on RemminaProtocolWidget");
4348 pparent = gtk_widget_get_parent(cnnobj->
proto);
4349 if (pparent != NULL) {
4350 g_object_ref(cnnobj->
proto);
4351 gtk_container_remove(GTK_CONTAINER(pparent), cnnobj->
proto);
4363 gtk_toggle_tool_button_set_active(
4364 GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_grab),
4369 RemminaMessagePanel *mp;
4380 REMMINA_DEBUG(
"Could not disconnect");
4383 REMMINA_DEBUG(
"Disconnected");
4389 TRACE_CALL(__func__);
4398 TRACE_CALL(__func__);
4406 TRACE_CALL(__func__);
4415 TRACE_CALL(__func__);
4424 TRACE_CALL(__func__);
4436 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
4437 _(
"The file “%s” is corrupted, unreadable, or could not be found."), filename);
4438 g_signal_connect(G_OBJECT(dialog),
"response", G_CALLBACK(gtk_widget_destroy), NULL);
4439 gtk_widget_show(dialog);
4472 TRACE_CALL(__func__);
4478 TRACE_CALL(__func__);
4479 GtkWidget *widget = GTK_WIDGET(data);
4481 if (GTK_IS_LABEL(widget))
4482 gtk_label_set_selectable(GTK_LABEL(widget), TRUE);
4502 TRACE_CALL(__func__);
4504 GError *error = NULL;
4507 gtk_show_uri_on_window(
4511 _(
"https://gitlab.com/Remmina/Remmina/-/wikis/GtkSocket-feature-is-not-available-in-a-Wayland-session"),
4512 GDK_CURRENT_TIME, &error
4520 gtk_widget_destroy(GTK_WIDGET(
self));
4525 TRACE_CALL(__func__);
4537 if (disconnect_cb) {
4538 g_print(
"disconnect_cb is deprecated inside rcw_open_from_file_full() and should be null\n");
4554 dialog = gtk_message_dialog_new(wparent, GTK_DIALOG_DESTROY_WITH_PARENT,
4555 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
"%s", msg);
4556 gtk_dialog_run(GTK_DIALOG(dialog));
4557 gtk_widget_destroy(dialog);
4565 gtk_widget_set_name(GTK_WIDGET(cnnobj->
proto),
"remmina-protocol-widget");
4567 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
4568 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
4571 g_object_set_data(G_OBJECT(cnnobj->
proto),
"user-data", data);
4585 cnnobj->
viewport = gtk_viewport_new(NULL, NULL);
4586 gtk_widget_set_name(cnnobj->
viewport,
"remmina-cw-viewport");
4588 gtk_container_set_border_width(GTK_CONTAINER(cnnobj->
viewport), 0);
4589 gtk_viewport_set_shadow_type(GTK_VIEWPORT(cnnobj->
viewport), GTK_SHADOW_NONE);
4604 gtk_container_add(GTK_CONTAINER(cnnobj->
viewport), cnnobj->
proto);
4611 switch (view_mode) {
4628 gtk_window_present(GTK_WINDOW(cnnobj->
cnnwin));
4635 gtk_widget_show(cnnobj->
proto);
4655 gchar *title = _(
"Warning: This plugin requires GtkSocket, but this "
4656 "feature is unavailable in a Wayland session.");
4661 _(
"Plugins relying on GtkSocket can't run in a "
4662 "Wayland session.\nFor more info and a possible "
4663 "workaround, please visit the Remmina wiki at:\n\n"
4664 "https://gitlab.com/Remmina/Remmina/-/wikis/GtkSocket-feature-is-not-available-in-a-Wayland-session");
4666 dialog = gtk_message_dialog_new(
4667 GTK_WINDOW(cnnobj->
cnnwin),
4669 GTK_MESSAGE_WARNING,
4673 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
"%s",
4675 gtk_dialog_add_button(GTK_DIALOG(dialog), _(
"Open in web browser"),
4678 REMMINA_CRITICAL(g_strdup_printf(
"%s\n%s", title, err_msg));
4680 g_signal_connect(G_OBJECT(dialog),
4686 GtkWidget *area = gtk_message_dialog_get_message_area(
4687 GTK_MESSAGE_DIALOG(dialog));
4688 GtkContainer *box = (GtkContainer *)area;
4690 GList *children = gtk_container_get_children(box);
4692 g_list_free(children);
4694 gtk_widget_show(dialog);
4699 if (cnnobj->
cnnwin->
priv->floating_toolbar_widget)
4700 gtk_widget_show(cnnobj->
cnnwin->
priv->floating_toolbar_widget);
4703 printf(
"OK, an error occurred in initializing the protocol plugin before connecting. The error is %s.\n"
4705 return cnnobj->
proto;
4717 return cnnobj->
proto;
4731 TRACE_CALL(__func__);
4732 cnnwin->
priv->on_delete_confirm_mode = mode;
4741 TRACE_CALL(__func__);
4743 RemminaMessagePanel *lastPanel;
4744 gboolean was_visible;
4748 childs = gtk_container_get_children(GTK_CONTAINER(page));
4749 cc = g_list_first(childs);
4750 while (cc != NULL) {
4751 if ((RemminaMessagePanel *)cc->data == mp)
4753 cc = g_list_next(cc);
4755 g_list_free(childs);
4758 printf(
"Remmina: Warning. There was a request to destroy a RemminaMessagePanel that is not on the page\n");
4761 was_visible = gtk_widget_is_visible(GTK_WIDGET(mp));
4762 gtk_widget_destroy(GTK_WIDGET(mp));
4766 childs = gtk_container_get_children(GTK_CONTAINER(page));
4767 cc = g_list_first(childs);
4769 while (cc != NULL) {
4770 if (G_TYPE_CHECK_INSTANCE_TYPE(cc->data, REMMINA_TYPE_MESSAGE_PANEL))
4771 lastPanel = (RemminaMessagePanel *)cc->data;
4772 cc = g_list_next(cc);
4774 g_list_free(childs);
4776 gtk_widget_show(GTK_WIDGET(lastPanel));
4788 TRACE_CALL(__func__);
4794 childs = gtk_container_get_children(GTK_CONTAINER(page));
4795 cc = g_list_first(childs);
4796 while (cc != NULL) {
4797 if (G_TYPE_CHECK_INSTANCE_TYPE(cc->data, REMMINA_TYPE_MESSAGE_PANEL))
4798 gtk_widget_hide(GTK_WIDGET(cc->data));
4799 cc = g_list_next(cc);
4801 g_list_free(childs);
4804 gtk_box_pack_start(GTK_BOX(page), GTK_WIDGET(mp), FALSE, FALSE, 0);
4805 gtk_box_reorder_child(GTK_BOX(page), GTK_WIDGET(mp), 0);
4808 gtk_widget_show_all(GTK_WIDGET(mp));
@ REMMINA_PLUGIN_TYPE_PROTOCOL
static void rcw_focus_out(RemminaConnectionWindow *cnnwin)
void rco_on_lock_dynres(RemminaProtocolWidget *gp, gpointer data)
void rco_on_disconnect(RemminaProtocolWidget *gp, gpointer data)
void rcw_toolbar_switch_page_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rco_change_scalemode(RemminaConnectionObject *cnnobj, gboolean bdyn, gboolean bscale)
gboolean rco_enter_protocol_widget(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionObject *cnnobj)
static gboolean rcw_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
static void rcw_on_page_removed(GtkNotebook *notebook, GtkWidget *child, guint page_num, RemminaConnectionWindow *cnnwin)
static void print_crossing_event(GdkEventCrossing *event)
static void rcw_tb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
static void rcw_create_overlay_ftb_overlay(RemminaConnectionWindow *cnnwin)
static void rcw_migrate(RemminaConnectionWindow *from, RemminaConnectionWindow *to)
static void rcw_update_pin(RemminaConnectionWindow *cnnwin)
static void rcw_floating_toolbar_show(RemminaConnectionWindow *cnnwin, gboolean show)
static void rcw_init(RemminaConnectionWindow *cnnwin)
static RemminaConnectionWindow * rcw_create_fullscreen(GtkWindow *old, gint view_mode)
static gboolean rcw_unmap_event(GtkWidget *widget, GdkEvent *event, gpointer data)
static gboolean rcw_tb_drag_failed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result, gpointer user_data)
static void rcw_pointer_ungrab(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_scaled_mode(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static gboolean rcw_on_configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
void rcw_open_from_file(RemminaFile *remminafile)
static GtkWidget * rco_create_tab_page(RemminaConnectionObject *cnnobj)
static GtkNotebook * rcw_create_notebook(RemminaConnectionWindow *cnnwin)
G_DEFINE_TYPE(RemminaConnectionWindow, rcw, GTK_TYPE_WINDOW)
void rcw_toolbar_fullscreen_option(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
void rco_update_toolbar_autofit_button(RemminaConnectionObject *cnnobj)
static void rcw_set_toolbar_visibility(RemminaConnectionWindow *cnnwin)
static void rco_disconnect_current_page(RemminaConnectionObject *cnnobj)
void rco_set_scrolled_policy(RemminaScaleMode scalemode, GtkScrolledWindow *scrolled_window)
static gboolean rcw_on_leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static gboolean rcw_after_configure_scrolled(gpointer user_data)
static void rcw_toolbar_open_main(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static GtkWidget * rcw_create_toolbar(RemminaConnectionWindow *cnnwin, gint mode)
static guint rcw_signals[LAST_SIGNAL]
static gboolean rcw_floating_toolbar_on_scroll(GtkWidget *widget, GdkEventScroll *event, RemminaConnectionWindow *cnnwin)
static void rco_update_toolbar(RemminaConnectionObject *cnnobj)
void rco_on_connect(RemminaProtocolWidget *gp, RemminaConnectionObject *cnnobj)
static void rcw_update_notebook(RemminaConnectionWindow *cnnwin)
static void rco_viewport_fullscreen_mode(GtkWidget *widget, RemminaConnectionObject *cnnobj)
static void rcw_keyboard_grab(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_place_signal(RemminaConnectionWindow *cnnwin, gpointer data)
void rcw_toolbar_preferences_check(RemminaConnectionObject *cnnobj, GtkWidget *menu, const RemminaProtocolFeature *feature, const gchar *domain, gboolean enabled)
static void rcw_class_init(RemminaConnectionWindowClass *klass)
static GtkWidget * rco_create_scrolled_container(RemminaScaleMode scalemode, int view_mode)
static GtkWidget * rco_create_tab_label(RemminaConnectionObject *cnnobj)
static void rco_call_protocol_feature_radio(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static void rco_call_protocol_feature_activate(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static RemminaConnectionWindow * rcw_new(gboolean fullscreen, int full_screen_target_monitor)
static gboolean rcw_floating_toolbar_on_leave(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionWindow *cnnwin)
void rcw_set_delete_confirm_mode(RemminaConnectionWindow *cnnwin, RemminaConnectionWindowOnDeleteConfirmMode mode)
static gboolean rcw_floating_toolbar_hide(RemminaConnectionWindow *cnnwin)
static void rcw_scaler_option_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
void rcw_toolbar_menu_popdown(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static gboolean rcw_ftb_drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, RemminaConnectionWindow *cnnwin)
struct _RemminaConnectionObject RemminaConnectionObject
static void rcw_toolbar_switch_page(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static gboolean rcw_floating_toolbar_make_invisible(gpointer data)
static gboolean focus_in_delayed_grab(RemminaConnectionWindow *cnnwin)
static void cb_lasterror_confirmed(void *cbdata, int btn)
void rcw_update_toolbar_opacity(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_multi_monitor_mode(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void nb_set_current_page(GtkNotebook *notebook, GtkWidget *page)
static gboolean rcw_map_event_fullscreen(GtkWidget *widget, GdkEvent *event, gpointer data)
gboolean rcw_notify_widget_toolbar_placement(GtkWidget *widget, gpointer data)
void rco_on_desktop_resize(RemminaProtocolWidget *gp, gpointer data)
static const GtkTargetEntry dnd_targets_ftb[]
static void rcw_toolbar_grab(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static RemminaConnectionWindow * rcw_find(RemminaFile *remminafile)
static void rcw_close_all_connections(RemminaConnectionWindow *cnnwin)
static GtkNotebook * rcw_on_notebook_create_window(GtkNotebook *notebook, GtkWidget *page, gint x, gint y, gpointer data)
static gboolean rcw_map_event(GtkWidget *widget, GdkEvent *event, gpointer data)
static gboolean rcw_tb_drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data)
static gboolean rcw_keyboard_grab_retry(gpointer user_data)
void rcw_grab_focus(RemminaConnectionWindow *cnnwin)
static void rcw_ftb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
static GtkWidget * nb_find_page_by_cnnobj(GtkNotebook *notebook, RemminaConnectionObject *cnnobj)
static void set_label_selectable(gpointer data, gpointer user_data)
static void rco_scrolled_fullscreen_mode(GtkWidget *widget, RemminaConnectionObject *cnnobj)
static const GtkTargetEntry dnd_targets_tb[]
static gboolean open_connection_last_stage(gpointer user_data)
void rcw_toolbar_tools_popdown(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_kp_ungrab(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_disconnect(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_focus_in(RemminaConnectionWindow *cnnwin)
static gboolean rcw_focus_out_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
static void rco_get_desktop_size(RemminaConnectionObject *cnnobj, gint *width, gint *height)
static void rcw_toolbar_preferences_popdown(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_on_switch_page(GtkNotebook *notebook, GtkWidget *newpage, guint page_num, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_screenshot(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static RemminaConnectionWindow * rcw_create_scrolled(gint width, gint height, gboolean maximize)
static gboolean rcw_floating_toolbar_on_enter(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionWindow *cnnwin)
void rco_destroy_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp)
Deletes a RemminaMessagePanel from the current cnnobj and if it was visible, make visible the last re...
GtkWidget * rcw_get_gtkviewport(RemminaConnectionObject *cnnobj)
static void nb_migrate_message_panels(GtkWidget *frompage, GtkWidget *topage)
static void rcw_fullscreen_option_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
gboolean rcw_toolbar_autofit_restore(RemminaConnectionWindow *cnnwin)
gboolean rcw_open_from_filename(const gchar *filename)
void rco_on_unlock_dynres(RemminaProtocolWidget *gp, gpointer data)
static void rcw_destroy(GtkWidget *widget, gpointer data)
static gboolean rcw_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
static RemminaConnectionObject * rcw_get_cnnobj_at_page(RemminaConnectionWindow *cnnwin, gint npage)
GTKSOCKET_NOT_AVAIL_RESPONSE_TYPE
These define the response id's of the gtksocket-is-not-available-warning-dialog buttons.
@ GTKSOCKET_NOT_AVAIL_RESPONSE_OPEN_BROWSER
@ GTKSOCKET_NOT_AVAIL_RESPONSE_NUM
void rco_closewin(RemminaProtocolWidget *gp)
static gboolean rcw_focus_in_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
static void rcw_toolbar_preferences(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void remmina_protocol_widget_update_alignment(RemminaConnectionObject *cnnobj)
static void rcw_toolbar_dynres(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_tools(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_pin(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static RemminaScaleMode get_current_allowed_scale_mode(RemminaConnectionObject *cnnobj, gboolean *dynres_avail, gboolean *scale_avail)
static void rcw_scaler_keep_aspect(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_menu_on_launch_item(RemminaAppletMenu *menu, RemminaAppletMenuItem *menuitem, gpointer data)
static void rcw_pointer_grab(RemminaConnectionWindow *cnnwin)
void rco_show_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp)
Each cnnobj->page can have more than one RemminaMessagePanel, but 0 or 1 are visible.
static gboolean rcw_hostkey_func(RemminaProtocolWidget *gp, guint keyval, gboolean release)
static void rcw_set_tooltip(GtkWidget *item, const gchar *tip, guint key1, guint key2)
void rco_switch_page_activate(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
void rcw_toolbar_preferences_radio(RemminaConnectionObject *cnnobj, RemminaFile *remminafile, GtkWidget *menu, const RemminaProtocolFeature *feature, const gchar *domain, gboolean enabled)
GtkWidget * rcw_open_from_file_full(RemminaFile *remminafile, GCallback disconnect_cb, gpointer data, guint *handler)
static void rcw_create_floating_toolbar(RemminaConnectionWindow *cnnwin, gint mode)
static gboolean rco_leave_protocol_widget(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionObject *cnnobj)
static void rcw_on_page_added(GtkNotebook *notebook, GtkWidget *child, guint page_num, RemminaConnectionWindow *cnnwin)
static GtkWidget * rcw_append_new_page(RemminaConnectionWindow *cnnwin, RemminaConnectionObject *cnnobj)
static void rpw_size_allocated_on_connection(GtkWidget *w, GdkRectangle *allocation, gpointer user_data)
gboolean rcw_delete(RemminaConnectionWindow *cnnwin)
void rco_on_update_align(RemminaProtocolWidget *gp, gpointer data)
gboolean rcw_delayed_window_present(gpointer user_data)
static void rcw_toolbar_autofit(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static gboolean rcw_on_enter_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static void rco_call_protocol_feature_check(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static void rco_check_resize(RemminaConnectionObject *cnnobj)
static void rcw_toolbar_menu(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_scaler_expand(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_scaler_option(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
void rco_get_monitor_geometry(RemminaConnectionObject *cnnobj, GdkRectangle *sz)
static void rcw_toolbar_duplicate(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static void rcw_gtksocket_not_available_dialog_response(GtkDialog *self, gint response_id, RemminaConnectionObject *cnnobj)
Gets called if the user interacts with the gtksocket-is-not-available-warning-dialog.
static void rcw_toolbar_fullscreen(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
void rco_on_close_button_clicked(GtkButton *button, RemminaConnectionObject *cnnobj)
gchar * remmina_pref_file
static void rcw_update_tag(RemminaConnectionWindow *cnnwin, RemminaConnectionObject *cnnobj)
static void rcw_toolbar_minimize(GtkToolItem *toggle, RemminaConnectionWindow *cnnwin)
static gboolean rcw_on_switch_page_finalsel(gpointer user_data)
static void rcw_place_toolbar(GtkToolbar *toolbar, GtkGrid *grid, GtkWidget *sibling, int toolbar_placement)
static void rcw_switch_viewmode(RemminaConnectionWindow *cnnwin, int newmode)
GtkWindow * rcw_get_gtkwindow(RemminaConnectionObject *cnnobj)
static RemminaConnectionObject * rcw_get_visible_cnnobj(RemminaConnectionWindow *cnnwin)
RemminaConnectionWindowOnDeleteConfirmMode
@ RCW_ONDELETE_CONFIRM_IF_2_OR_MORE
GType rcw_get_type(void) G_GNUC_CONST
struct _RemminaConnectionWindowPriv RemminaConnectionWindowPriv
void remmina_exec_command(RemminaCommandType command, const gchar *data)
void remmina_application_condexit(RemminaCondExitType why)
@ REMMINA_COMMAND_CONNECT
@ REMMINA_CONDEXIT_ONDISCONNECT
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
gint remmina_file_get_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
void remmina_file_state_last_success(RemminaFile *remminafile)
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
void remmina_file_save(RemminaFile *remminafile)
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
const gchar * remmina_file_get_filename(RemminaFile *remminafile)
void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
GtkWindow * remmina_main_get_window()
RemminaMessagePanel * remmina_message_panel_new()
void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp)
void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
gboolean remmina_plugin_manager_query_feature_by_type(RemminaPluginType ptype, const gchar *name, RemminaProtocolFeatureType ftype)
gboolean remmina_gtksocket_available()
gchar * remmina_pref_get_value(const gchar *key)
gboolean remmina_pref_get_boolean(const gchar *key)
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
gboolean remmina_pref_save(void)
@ VIEWPORT_FULLSCREEN_MODE
@ SCROLLED_FULLSCREEN_MODE
@ FLOATING_TOOLBAR_VISIBILITY_DISABLE
@ FLOATING_TOOLBAR_VISIBILITY_INVISIBLE
@ FLOATING_TOOLBAR_PLACEMENT_BOTTOM
@ FLOATING_TOOLBAR_PLACEMENT_TOP
@ TOOLBAR_PLACEMENT_BOTTOM
@ TOOLBAR_PLACEMENT_RIGHT
@ REMMINA_TAB_BY_PROTOCOL
void remmina_public_send_notification(const gchar *notification_id, const gchar *notification_title, const gchar *notification_message)
void remmina_public_popup_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
gint remmina_unlock_new(GtkWindow *parent)
guint remmina_utils_string_replace_all(GString *haystack, const gchar *needle, const gchar *replace)
Replaces all occurrences of needle in haystack with replace.
General utility functions, non-GTK related.
gulong deferred_open_size_allocate_handler
gboolean plugin_can_scale
RemminaFile * remmina_file
RemminaConnectionWindow * cnnwin
GtkWidget * scrolled_container
RemminaConnectionWindowPriv * priv
guint shortcutkey_fullscreen
guint shortcutkey_disconnect
guint shortcutkey_screenshot
guint shortcutkey_clipboard
gboolean small_toolbutton
const gchar * screenshot_path
guint shortcutkey_prevtab
gboolean fullscreen_on_auto
guint shortcutkey_viewonly
guint shortcutkey_multimon
gboolean toolbar_pin_down
guint shortcutkey_nexttab
guint shortcutkey_minimize
gboolean hide_connection_toolbar
gint fullscreen_toolbar_visibility
guint shortcutkey_toolbar
gint floating_toolbar_placement
gboolean applet_hide_count
const gchar * screenshot_name
guint shortcutkey_autofit
RemminaProtocolFeatureType type
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
@ REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS
@ REMMINA_PROTOCOL_FEATURE_TYPE_DYNRESUPDATE
@ REMMINA_PROTOCOL_FEATURE_TYPE_PREF
@ REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET
@ REMMINA_PROTOCOL_FEATURE_TYPE_TOOL
@ REMMINA_PROTOCOL_FEATURE_TYPE_MULTIMON
@ REMMINA_PROTOCOL_FEATURE_TYPE_SCALE
@ REMMINA_PROTOCOL_WIDGET_SCALE_MODE_DYNRES
@ REMMINA_PROTOCOL_WIDGET_SCALE_MODE_SCALED
@ REMMINA_PROTOCOL_WIDGET_SCALE_MODE_NONE
N_("Unable to connect to VNC server")