40 #include <cairo/cairo-xlib.h> 42 #include <gdk/gdkkeysyms.h> 43 #include <glib/gi18n.h> 64 #ifdef GDK_WINDOWING_WAYLAND 65 #include <gdk/gdkwayland.h> 69 #define DEBUG_KB_GRABBING 0 77 #define MOTION_TIME 100 80 #define TB_HIDE_TIME_TIME 1000 82 #define FULL_SCREEN_TARGET_MONITOR_UNDEFINED -1 84 struct _RemminaConnectionWindowPriv {
85 GtkNotebook * notebook;
86 GtkWidget * floating_toolbar_widget;
89 GtkWidget * overlay_ftb_overlay;
91 GtkWidget * floating_toolbar_label;
92 gdouble floating_toolbar_opacity;
95 guint acs_eventsourceid;
96 guint spf_eventsourceid;
97 guint grab_retry_eventsourceid;
98 guint ftb_hide_eventsource;
99 guint tar_eventsource;
100 guint hidetb_eventsource;
101 guint dwp_eventsourceid;
107 GtkToolItem * toolitem_autofit;
108 GtkToolItem * toolitem_fullscreen;
109 GtkToolItem * toolitem_switch_page;
110 GtkToolItem * toolitem_dynres;
111 GtkToolItem * toolitem_scale;
112 GtkToolItem * toolitem_grab;
113 GtkToolItem * toolitem_preferences;
114 GtkToolItem * toolitem_tools;
115 GtkToolItem * toolitem_duplicate;
116 GtkToolItem * toolitem_screenshot;
117 GtkWidget * fullscreen_option_button;
118 GtkWidget * fullscreen_scaler_button;
119 GtkWidget * scaler_option_button;
121 GtkWidget * pin_button;
128 gboolean toolbar_is_reconfiguring;
139 gint ss_width, ss_height;
140 gboolean ss_maximized;
143 gboolean pointer_captured;
144 gboolean hostkey_activated;
145 gboolean hostkey_used;
147 gboolean pointer_entered;
187 static void rcw_place_toolbar(GtkToolbar *toolbar, GtkGrid *grid, GtkWidget *sibling,
int toolbar_placement);
192 static void rcw_ftb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data);
197 (
char *)
"text/x-remmina-ftb",
198 GTK_TARGET_SAME_APP | GTK_TARGET_OTHER_WIDGET,
206 (
char *)
"text/x-remmina-tb",
214 TRACE_CALL(__func__);
215 GtkCssProvider *provider;
216 provider = gtk_css_provider_new();
222 #if GTK_CHECK_VERSION(3, 14, 0) 223 gtk_css_provider_load_from_data(provider,
224 "#remmina-cw-viewport, #remmina-cw-aspectframe {\n" 227 " background-color: black;\n" 232 " -GtkWidget-window-dragging: 0;\n" 234 "#remmina-connection-window-fullscreen {\n" 235 " border-color: black;\n" 237 "#remmina-small-button {\n" 238 " outline-offset: 0;\n" 239 " outline-width: 0;\n" 243 "#remmina-pin-button {\n" 244 " outline-offset: 0;\n" 245 " outline-width: 0;\n" 249 "#remmina-tab-page {\n" 250 " background-color: black;\n" 252 "#remmina-scrolled-container {\n" 254 "#remmina-scrolled-container.undershoot {\n" 255 " background: none;\n" 257 "#remmina-tab-page {\n" 260 " background-color: white;\n" 262 " border-style: none solid solid solid;\n" 263 " border-width: 1px;\n" 264 " border-radius: 4px;\n" 268 " background-color: white;\n" 270 " border-style: solid solid none solid;\n" 271 " border-width: 1px;\n" 272 " border-radius: 4px;\n" 278 " border: 0px solid;\n" 279 " padding: 20px 20px 20px 20px;\n" 281 ".message_panel entry {\n" 282 " background-image: none;\n" 283 " border-width: 4px;\n" 284 " border-radius: 8px;\n" 286 ".message_panel .title_label {\n" 287 " font-size: 2em; \n" 292 gtk_css_provider_load_from_data(provider,
293 "#remmina-cw-viewport, #remmina-cw-aspectframe {\n" 296 " background-color: black;\n" 298 "#remmina-cw-message-panel {\n" 303 " -GtkWidget-window-dragging: 0;\n" 305 "#remmina-connection-window-fullscreen {\n" 306 " border-color: black;\n" 308 "#remmina-small-button {\n" 309 " -GtkWidget-focus-padding: 0;\n" 310 " -GtkWidget-focus-line-width: 0;\n" 314 "#remmina-pin-button {\n" 315 " -GtkWidget-focus-padding: 0;\n" 316 " -GtkWidget-focus-line-width: 0;\n" 320 "#remmina-scrolled-container {\n" 322 "#remmina-scrolled-container.undershoot {\n" 323 " background: none\n" 325 "#remmina-tab-page {\n" 328 " border-style: none solid solid solid;\n" 329 " border-width: 1px;\n" 330 " border-radius: 4px;\n" 334 " border-style: solid solid none solid;\n" 335 " border-width: 1px;\n" 336 " border-radius: 4px;\n" 345 gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
346 GTK_STYLE_PROVIDER(provider),
347 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
349 g_object_unref(provider);
354 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
361 if (!cnnwin->
priv->notebook)
363 po = gtk_notebook_get_nth_page(GTK_NOTEBOOK(cnnwin->
priv->notebook), npage);
364 return g_object_get_data(G_OBJECT(po),
"cnnobj");
371 if (cnnwin != NULL && cnnwin->
priv != NULL && cnnwin->
priv->notebook != NULL) {
372 np = gtk_notebook_get_current_page(GTK_NOTEBOOK(cnnwin->
priv->notebook));
383 TRACE_CALL(__func__);
385 gboolean plugin_has_dynres, plugin_can_scale;
404 *scale_avail = plugin_can_scale;
413 TRACE_CALL(__func__);
421 TRACE_CALL(__func__);
423 #if GTK_CHECK_VERSION(3, 24, 0) 426 GdkDeviceManager *manager;
427 GdkDevice *keyboard = NULL;
430 if (cnnwin->
priv->grab_retry_eventsourceid) {
431 g_source_remove(cnnwin->
priv->grab_retry_eventsourceid);
432 cnnwin->
priv->grab_retry_eventsourceid = 0;
435 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
436 #if GTK_CHECK_VERSION(3, 24, 0) 437 seat = gdk_display_get_default_seat(display);
440 manager = gdk_display_get_device_manager(display);
441 keyboard = gdk_device_manager_get_client_pointer(manager);
444 if (!cnnwin->
priv->kbcaptured && !cnnwin->
priv->pointer_captured)
447 #if DEBUG_KB_GRABBING 448 printf(
"DEBUG_KB_GRABBING: --- ungrabbing\n");
453 #if GTK_CHECK_VERSION(3, 24, 0) 455 gdk_seat_ungrab(seat);
457 if (keyboard != NULL) {
458 if (gdk_device_get_source(keyboard) != GDK_SOURCE_KEYBOARD)
459 keyboard = gdk_device_get_associated_device(keyboard);
460 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
461 gdk_device_ungrab(keyboard, GDK_CURRENT_TIME);
462 G_GNUC_END_IGNORE_DEPRECATIONS
465 cnnwin->
priv->kbcaptured = FALSE;
466 cnnwin->
priv->pointer_captured = FALSE;
472 TRACE_CALL(__func__);
476 cnnwin->
priv->grab_retry_eventsourceid = 0;
477 return G_SOURCE_REMOVE;
482 #if GTK_CHECK_VERSION(3, 24, 0) 485 if (!cnnwin->
priv->pointer_captured)
488 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
489 seat = gdk_display_get_default_seat(display);
490 gdk_seat_ungrab(seat);
496 TRACE_CALL(__func__);
497 #if GTK_CHECK_VERSION(3, 24, 0) 501 if (cnnwin->
priv->pointer_captured) {
502 #if DEBUG_KB_GRABBING 503 printf(
"DEBUG_KB_GRABBING: pointer_captured is true, it should not\n");
508 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
509 seat = gdk_display_get_default_seat(display);
510 ggs = gdk_seat_grab(seat, gtk_widget_get_window(GTK_WIDGET(cnnwin)),
511 GDK_SEAT_CAPABILITY_ALL_POINTING, TRUE, NULL, NULL, NULL, NULL);
512 if (ggs != GDK_GRAB_SUCCESS) {
513 #if DEBUG_KB_GRABBING 514 printf(
"DEBUG_KB_GRABBING: GRAB of POINTER failed. GdkGrabStatus: %d\n", (
int)ggs);
517 cnnwin->
priv->pointer_captured = TRUE;
526 TRACE_CALL(__func__);
528 #if GTK_CHECK_VERSION(3, 24, 0) 531 GdkDeviceManager *manager;
534 GdkDevice *keyboard = NULL;
536 if (cnnwin->
priv->kbcaptured)
539 display = gtk_widget_get_display(GTK_WIDGET(cnnwin));
540 #if GTK_CHECK_VERSION(3, 24, 0) 541 seat = gdk_display_get_default_seat(display);
542 keyboard = gdk_seat_get_pointer(seat);
544 manager = gdk_display_get_device_manager(display);
545 keyboard = gdk_device_manager_get_client_pointer(manager);
548 if (keyboard != NULL) {
549 if (gdk_device_get_source(keyboard) != GDK_SOURCE_KEYBOARD)
550 keyboard = gdk_device_get_associated_device(keyboard);
553 #if DEBUG_KB_GRABBING 554 printf(
"DEBUG_KB_GRABBING: profile asks for grabbing, let’s try.\n");
574 #if GTK_CHECK_VERSION(3, 24, 0) 575 ggs = gdk_seat_grab(seat, gtk_widget_get_window(GTK_WIDGET(cnnwin)),
576 GDK_SEAT_CAPABILITY_KEYBOARD, TRUE, NULL, NULL, NULL, NULL);
578 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
579 ggs = gdk_device_grab(keyboard, gtk_widget_get_window(GTK_WIDGET(cnnwin)), GDK_OWNERSHIP_WINDOW,
580 TRUE, GDK_KEY_PRESS | GDK_KEY_RELEASE, NULL, GDK_CURRENT_TIME);
581 G_GNUC_END_IGNORE_DEPRECATIONS
583 if (ggs != GDK_GRAB_SUCCESS) {
584 #if DEBUG_KB_GRABBING 585 printf(
"GRAB of keyboard failed.\n");
588 if (cnnwin->
priv->grab_retry_eventsourceid == 0)
591 #if DEBUG_KB_GRABBING 592 printf(
"Keyboard grabbed\n");
594 if (cnnwin->
priv->grab_retry_eventsourceid != 0) {
595 g_source_remove(cnnwin->
priv->grab_retry_eventsourceid);
596 cnnwin->
priv->grab_retry_eventsourceid = 0;
598 cnnwin->
priv->kbcaptured = TRUE;
608 GtkNotebook *notebook = GTK_NOTEBOOK(priv->notebook);
613 if (GTK_IS_WIDGET(notebook)) {
614 n = gtk_notebook_get_n_pages(notebook);
615 for (i = n - 1; i >= 0; i--) {
616 w = gtk_notebook_get_nth_page(notebook, i);
626 TRACE_CALL(__func__);
628 GtkNotebook *notebook = GTK_NOTEBOOK(priv->notebook);
632 if (!REMMINA_IS_CONNECTION_WINDOW(cnnwin))
636 n = gtk_notebook_get_n_pages(notebook);
638 dialog = gtk_message_dialog_new(GTK_WINDOW(cnnwin), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
640 _(
"Are you sure you want to close %i active connections in the current window?"), n);
641 i = gtk_dialog_run(GTK_DIALOG(dialog));
642 gtk_widget_destroy(dialog);
643 if (i != GTK_RESPONSE_YES)
654 TRACE_CALL(__func__);
661 TRACE_CALL(__func__);
665 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
671 if (priv->kbcaptured)
674 if (priv->acs_eventsourceid) {
675 g_source_remove(priv->acs_eventsourceid);
676 priv->acs_eventsourceid = 0;
678 if (priv->spf_eventsourceid) {
679 g_source_remove(priv->spf_eventsourceid);
680 priv->spf_eventsourceid = 0;
682 if (priv->grab_retry_eventsourceid) {
683 g_source_remove(priv->grab_retry_eventsourceid);
684 priv->grab_retry_eventsourceid = 0;
686 if (priv->ftb_hide_eventsource) {
687 g_source_remove(priv->ftb_hide_eventsource);
688 priv->ftb_hide_eventsource = 0;
690 if (priv->tar_eventsource) {
691 g_source_remove(priv->tar_eventsource);
692 priv->tar_eventsource = 0;
694 if (priv->hidetb_eventsource) {
695 g_source_remove(priv->hidetb_eventsource);
696 priv->hidetb_eventsource = 0;
698 if (priv->dwp_eventsourceid) {
699 g_source_remove(priv->dwp_eventsourceid);
700 priv->dwp_eventsourceid = 0;
712 TRACE_CALL(__func__);
715 if (G_TYPE_CHECK_INSTANCE_TYPE(widget, rcwtype)) {
716 g_signal_emit_by_name(G_OBJECT(widget),
"toolbar-place");
723 GtkDragResult result, gpointer user_data)
725 TRACE_CALL(__func__);
734 gtk_widget_show(GTK_WIDGET(priv->toolbar));
740 gint x, gint y, guint time, gpointer user_data)
742 TRACE_CALL(__func__);
744 gint new_toolbar_placement;
751 gtk_widget_get_allocation(widget, &wa);
753 if (wa.width * y >= wa.height * x) {
754 if (wa.width * y > wa.height * (wa.width - x))
759 if (wa.width * y > wa.height * (wa.width - x))
765 gtk_drag_finish(context, TRUE, TRUE, time);
776 gtk_widget_show(GTK_WIDGET(priv->toolbar));
783 TRACE_CALL(__func__);
785 cairo_surface_t *surface;
788 double dashes[] = { 10 };
790 gtk_widget_get_allocation(widget, &wa);
792 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 16, 16);
793 cr = cairo_create(surface);
794 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
795 cairo_set_line_width(cr, 4);
796 cairo_set_dash(cr, dashes, 1, 0);
797 cairo_rectangle(cr, 0, 0, 16, 16);
801 gtk_widget_hide(widget);
803 gtk_drag_set_icon_surface(context, surface);
808 TRACE_CALL(__func__);
815 priv->floating_toolbar_opacity = (1.0 - TOOLBAR_OPACITY_MIN) / ((gdouble)TOOLBAR_OPACITY_LEVEL)
817 + TOOLBAR_OPACITY_MIN;
818 if (priv->floating_toolbar_widget)
819 gtk_widget_set_opacity(GTK_WIDGET(priv->overlay_ftb_overlay), priv->floating_toolbar_opacity);
824 TRACE_CALL(__func__);
826 gtk_widget_set_opacity(GTK_WIDGET(priv->overlay_ftb_overlay), 0.0);
827 priv->ftb_hide_eventsource = 0;
828 return G_SOURCE_REMOVE;
833 TRACE_CALL(__func__);
836 if (priv->floating_toolbar_widget == NULL)
839 if (show || priv->pin_down) {
843 if (priv->ftb_hide_eventsource) {
844 g_source_remove(priv->ftb_hide_eventsource);
845 priv->ftb_hide_eventsource = 0;
851 if (priv->ftb_hide_eventsource == 0)
855 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer), show || priv->pin_down);
860 TRACE_CALL(__func__);
876 TRACE_CALL(__func__);
879 gtk_scrolled_window_set_policy(scrolled_window,
886 GtkWidget *scrolled_container;
891 scrolled_container = gtk_scrolled_window_new(NULL, NULL);
893 gtk_container_set_border_width(GTK_CONTAINER(scrolled_container), 0);
894 gtk_widget_set_can_focus(scrolled_container, FALSE);
897 gtk_widget_set_name(scrolled_container,
"remmina-scrolled-container");
898 gtk_widget_show(scrolled_container);
900 return scrolled_container;
905 TRACE_CALL(__func__);
909 gint dwidth, dheight;
910 GtkAllocation nba, ca, ta;
912 cnnwin->
priv->tar_eventsource = 0;
914 if (priv->toolbar_is_reconfiguring)
915 return G_SOURCE_REMOVE;
921 gtk_widget_get_allocation(GTK_WIDGET(priv->notebook), &nba);
923 gtk_widget_get_allocation(priv->toolbar, &ta);
926 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), MAX(1, dwidth + ta.width + nba.width - ca.width),
927 MAX(1, dheight + nba.height - ca.height));
929 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), MAX(1, dwidth + nba.width - ca.width),
930 MAX(1, dheight + ta.height + nba.height - ca.height));
931 gtk_container_check_resize(GTK_CONTAINER(cnnobj->
cnnwin));
936 return G_SOURCE_REMOVE;
941 TRACE_CALL(__func__);
944 if (cnnwin->
priv->toolbar_is_reconfiguring)
949 if ((gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) != 0)
950 gtk_window_unmaximize(GTK_WINDOW(cnnwin));
954 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
962 TRACE_CALL(__func__);
967 GdkRectangle monitor_geometry;
969 sz->x = sz->y = sz->width = sz->height = 0;
975 if (!gtk_widget_is_visible(GTK_WIDGET(cnnobj->
cnnwin)))
978 #if GTK_CHECK_VERSION(3, 22, 0) 981 display = gtk_widget_get_display(GTK_WIDGET(cnnobj->
cnnwin));
982 monitor = gdk_display_get_monitor_at_window(display, gtk_widget_get_window(GTK_WIDGET(cnnobj->
cnnwin)));
986 screen = gtk_window_get_screen(GTK_WINDOW(cnnobj->
cnnwin));
987 monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(GTK_WIDGET(cnnobj->
cnnwin)));
990 #if GTK_CHECK_VERSION(3, 22, 0) 991 gdk_monitor_get_workarea(monitor, &monitor_geometry);
996 #ifdef GDK_WINDOWING_WAYLAND 997 if (GDK_IS_WAYLAND_DISPLAY(display)) {
998 int monitor_scale_factor = gdk_monitor_get_scale_factor(monitor);
999 monitor_geometry.width *= monitor_scale_factor;
1000 monitor_geometry.height *= monitor_scale_factor;
1003 #elif gdk_screen_get_monitor_workarea 1004 gdk_screen_get_monitor_workarea(screen, monitor, &monitor_geometry);
1006 gdk_screen_get_monitor_geometry(screen, monitor, &monitor_geometry);
1008 *sz = monitor_geometry;
1013 TRACE_CALL(__func__);
1014 gboolean scroll_required = FALSE;
1016 GdkRectangle monitor_geometry;
1017 gint rd_width, rd_height;
1030 (monitor_geometry.width < rd_width || monitor_geometry.height < rd_height) &&
1032 scroll_required = TRUE;
1036 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), monitor_geometry.width, monitor_geometry.height);
1038 (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER),
1039 (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER));
1043 bordersz = scroll_required ? SCROLL_BORDER_SIZE : 0;
1044 gtk_window_resize(GTK_WINDOW(cnnobj->
cnnwin), monitor_geometry.width, monitor_geometry.height);
1055 gtk_window_set_default_size(GTK_WINDOW(cnnobj->
cnnwin),
1056 MIN(rd_width, monitor_geometry.width), MIN(rd_height, monitor_geometry.height));
1057 if (rd_width >= monitor_geometry.width || rd_height >= monitor_geometry.height) {
1058 gtk_window_maximize(GTK_WINDOW(cnnobj->
cnnwin));
1066 gtk_window_maximize(GTK_WINDOW(cnnobj->
cnnwin));
1077 TRACE_CALL(__func__);
1081 if (remmina_pref.
hostkey && key1) {
1083 s1 = g_strdup_printf(
" (%s + %s,%s)", gdk_keyval_name(remmina_pref.
hostkey),
1084 gdk_keyval_name(gdk_keyval_to_upper(key1)), gdk_keyval_name(gdk_keyval_to_upper(key2)));
1085 else if (key1 == remmina_pref.
hostkey)
1086 s1 = g_strdup_printf(
" (%s)", gdk_keyval_name(remmina_pref.
hostkey));
1088 s1 = g_strdup_printf(
" (%s + %s)", gdk_keyval_name(remmina_pref.
hostkey),
1089 gdk_keyval_name(gdk_keyval_to_upper(key1)));
1093 s2 = g_strdup_printf(
"%s%s", tip, s1 ? s1 :
"");
1094 gtk_widget_set_tooltip_text(item, s2);
1101 TRACE_CALL(__func__);
1103 gboolean scaledexpandedmode;
1104 int rdwidth, rdheight;
1110 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1111 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1123 aratio = (gfloat)rdwidth / (gfloat)rdheight;
1126 cnnobj->
aspectframe = gtk_aspect_frame_new(NULL, 0.5, 0.5, aratio, FALSE);
1127 gtk_widget_set_name(cnnobj->
aspectframe,
"remmina-cw-aspectframe");
1128 gtk_frame_set_shadow_type(GTK_FRAME(cnnobj->
aspectframe), GTK_SHADOW_NONE);
1129 g_object_ref(cnnobj->
proto);
1130 gtk_container_remove(GTK_CONTAINER(cnnobj->
viewport), cnnobj->
proto);
1133 g_object_unref(cnnobj->
proto);
1135 if (cnnobj != NULL && cnnobj->
cnnwin != NULL && cnnobj->
cnnwin->
priv->notebook != NULL)
1138 gtk_aspect_frame_set(GTK_ASPECT_FRAME(cnnobj->
aspectframe), 0.5, 0.5, aratio, FALSE);
1145 g_object_ref(cnnobj->
proto);
1150 gtk_container_add(GTK_CONTAINER(cnnobj->
viewport), cnnobj->
proto);
1151 g_object_unref(cnnobj->
proto);
1152 if (cnnobj != NULL && cnnobj->
cnnwin != NULL && cnnobj->
cnnwin->
priv->notebook != NULL)
1161 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1162 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
1166 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_CENTER);
1167 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_CENTER);
1176 np = gtk_notebook_get_n_pages(notebook);
1177 for (i = 0; i < np; i++) {
1178 if (gtk_notebook_get_nth_page(notebook, i) == page) {
1179 gtk_notebook_set_current_page(notebook, i);
1194 lst = gtk_container_get_children(GTK_CONTAINER(frompage));
1195 for (l = lst; l != NULL; l = l->next) {
1196 if (REMMINA_IS_MESSAGE_PANEL(l->data)) {
1197 g_object_ref(l->data);
1198 gtk_container_remove(GTK_CONTAINER(frompage), GTK_WIDGET(l->data));
1199 gtk_container_add(GTK_CONTAINER(topage), GTK_WIDGET(l->data));
1200 g_object_unref(l->data);
1201 gtk_box_reorder_child(GTK_BOX(topage), GTK_WIDGET(l->data), 0);
1207 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1209 G_GNUC_END_IGNORE_DEPRECATIONS
1218 GtkNotebook *from_notebook;
1219 GtkWidget *frompage, *newpage;
1223 tag = g_strdup((gchar *)g_object_get_data(G_OBJECT(from),
"tag"));
1224 g_object_set_data_full(G_OBJECT(to),
"tag", tag, (GDestroyNotify)g_free);
1227 from_notebook = from->
priv->notebook;
1228 if (from_notebook && GTK_IS_NOTEBOOK(from_notebook)) {
1229 cp = gtk_notebook_get_current_page(from_notebook);
1230 np = gtk_notebook_get_n_pages(from_notebook);
1233 for (i = 0; i < np; i++) {
1234 frompage = gtk_notebook_get_nth_page(from_notebook, i);
1235 cnnobj = g_object_get_data(G_OBJECT(frompage),
"cnnobj");
1241 for (i = np - 1; i >= 0; i--)
1242 gtk_notebook_remove_page(from_notebook, i);
1243 gtk_notebook_set_current_page(to->
priv->notebook, cp);
1251 gint old_width, old_height;
1254 old_mode = cnnwin->
priv->view_mode;
1255 if (old_mode == newmode)
1262 gtk_window_get_size(GTK_WINDOW(cnnwin), &old_width, &old_height);
1263 s = gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnwin)));
1268 newwin->
priv->ss_maximized = (s & GDK_WINDOW_STATE_MAXIMIZED) ? TRUE : FALSE;
1269 newwin->
priv->ss_width = old_width;
1270 newwin->
priv->ss_height = old_height;
1274 cnnwin->
priv->ss_maximized);
1279 newwin->
priv->fss_view_mode = old_mode;
1283 newwin->
priv->hostkey_used = TRUE;
1289 TRACE_CALL(__func__);
1293 if (cnnwin->
priv->toolbar_is_reconfiguring)
1298 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget)))
1306 TRACE_CALL(__func__);
1308 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1317 TRACE_CALL(__func__);
1319 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1328 TRACE_CALL(__func__);
1331 priv->sticky = FALSE;
1332 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->fullscreen_option_button), FALSE);
1338 TRACE_CALL(__func__);
1341 GtkWidget *menuitem;
1344 if (cnnwin->
priv->toolbar_is_reconfiguring)
1349 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1352 cnnwin->
priv->sticky = TRUE;
1354 menu = gtk_menu_new();
1356 menuitem = gtk_radio_menu_item_new_with_label(NULL, _(
"Viewport fullscreen mode"));
1357 gtk_widget_show(menuitem);
1358 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1359 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
1361 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1364 menuitem = gtk_radio_menu_item_new_with_label(group, _(
"Scrolled fullscreen"));
1365 gtk_widget_show(menuitem);
1366 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1368 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1373 #if GTK_CHECK_VERSION(3, 22, 0) 1374 gtk_menu_popup_at_widget(GTK_MENU(menu), widget,
1375 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1378 gtk_get_current_event_time());
1385 TRACE_CALL(__func__);
1387 if (priv->toolbar_is_reconfiguring)
1389 priv->sticky = FALSE;
1390 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->scaler_option_button), FALSE);
1396 TRACE_CALL(__func__);
1399 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1410 TRACE_CALL(__func__);
1413 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
1426 TRACE_CALL(__func__);
1430 GtkWidget *menuitem;
1432 gboolean scaler_expand;
1434 if (cnnwin->
priv->toolbar_is_reconfiguring)
1438 priv = cnnwin->
priv;
1440 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1445 priv->sticky = TRUE;
1447 menu = gtk_menu_new();
1449 menuitem = gtk_radio_menu_item_new_with_label(NULL, _(
"Keep aspect ratio when scaled"));
1450 gtk_widget_show(menuitem);
1451 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1452 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
1454 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1457 menuitem = gtk_radio_menu_item_new_with_label(group, _(
"Fill client window when scaled"));
1458 gtk_widget_show(menuitem);
1459 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1461 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1462 g_signal_connect(G_OBJECT(menuitem),
"toggled", G_CALLBACK(
rcw_scaler_expand), cnnwin);
1466 #if GTK_CHECK_VERSION(3, 22, 0) 1467 gtk_menu_popup_at_widget(GTK_MENU(menu), widget,
1468 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1471 gtk_get_current_event_time());
1477 TRACE_CALL(__func__);
1481 page_num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem),
"new-page-num"));
1482 gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), page_num);
1487 TRACE_CALL(__func__);
1490 priv->sticky = FALSE;
1492 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_switch_page), FALSE);
1498 TRACE_CALL(__func__);
1504 GtkWidget *menuitem;
1508 if (priv->toolbar_is_reconfiguring)
1512 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget)))
1515 priv->sticky = TRUE;
1517 menu = gtk_menu_new();
1519 n = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook));
1520 for (i = 0; i < n; i++) {
1524 gtk_widget_show(menuitem);
1525 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1528 gtk_widget_show(image);
1530 g_object_set_data(G_OBJECT(menuitem),
"new-page-num", GINT_TO_POINTER(i));
1532 if (i == gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook)))
1533 gtk_widget_set_sensitive(menuitem, FALSE);
1539 #if GTK_CHECK_VERSION(3, 22, 0) 1540 gtk_menu_popup_at_widget(GTK_MENU(menu), widget,
1541 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1549 TRACE_CALL(__func__);
1551 GtkToolItem *toolitem;
1554 toolitem = priv->toolitem_autofit;
1557 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
1593 TRACE_CALL(__func__);
1594 gboolean bdyn, bscale;
1597 if (cnnwin->
priv->toolbar_is_reconfiguring)
1602 bdyn = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget));
1603 bscale = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_scale));
1605 if (bdyn && bscale) {
1606 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_scale), FALSE);
1617 TRACE_CALL(__func__);
1618 gboolean bdyn, bscale;
1621 if (cnnwin->
priv->toolbar_is_reconfiguring)
1625 bdyn = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_dynres));
1626 bscale = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget));
1628 if (bdyn && bscale) {
1629 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_dynres), FALSE);
1638 TRACE_CALL(__func__);
1641 if (cnnwin->
priv->toolbar_is_reconfiguring)
1647 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(cnnobj->
cnnwin->
priv->toolitem_preferences), FALSE);
1653 TRACE_CALL(__func__);
1656 if (priv->toolbar_is_reconfiguring)
1659 priv->sticky = FALSE;
1661 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_tools), FALSE);
1667 TRACE_CALL(__func__);
1671 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
1673 value = g_object_get_data(G_OBJECT(menuitem),
"feature-value");
1682 TRACE_CALL(__func__);
1687 value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
1694 TRACE_CALL(__func__);
1704 TRACE_CALL(__func__);
1705 GtkWidget *menuitem;
1713 list = (
const gchar **)feature->
opt3;
1714 for (i = 0; list[i]; i += 2) {
1715 menuitem = gtk_radio_menu_item_new_with_label(group, g_dgettext(domain, list[i + 1]));
1716 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
1717 gtk_widget_show(menuitem);
1718 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1721 g_object_set_data(G_OBJECT(menuitem),
"feature-type", (gpointer)feature);
1722 g_object_set_data(G_OBJECT(menuitem),
"feature-value", (gpointer)list[i]);
1724 if (value && g_strcmp0(list[i], value) == 0)
1725 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
1727 g_signal_connect(G_OBJECT(menuitem),
"toggled",
1730 gtk_widget_set_sensitive(menuitem, FALSE);
1737 const gchar *domain, gboolean enabled)
1739 TRACE_CALL(__func__);
1740 GtkWidget *menuitem;
1742 menuitem = gtk_check_menu_item_new_with_label(g_dgettext(domain, (
const gchar *)feature->
opt3));
1743 gtk_widget_show(menuitem);
1744 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1747 g_object_set_data(G_OBJECT(menuitem),
"feature-type", (gpointer)feature);
1749 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
1752 g_signal_connect(G_OBJECT(menuitem),
"toggled",
1755 gtk_widget_set_sensitive(menuitem, FALSE);
1761 TRACE_CALL(__func__);
1766 GtkWidget *menuitem;
1771 if (cnnwin->
priv->toolbar_is_reconfiguring)
1776 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget)))
1779 priv->sticky = TRUE;
1784 menu = gtk_menu_new();
1791 menuitem = gtk_separator_menu_item_new();
1792 gtk_widget_show(menuitem);
1793 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1797 switch (GPOINTER_TO_INT(feature->
opt1)) {
1798 case REMMINA_PROTOCOL_FEATURE_PREF_RADIO:
1803 case REMMINA_PROTOCOL_FEATURE_PREF_CHECK:
1814 #if GTK_CHECK_VERSION(3, 22, 0) 1815 gtk_menu_popup_at_widget(GTK_MENU(menu), widget,
1816 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1824 TRACE_CALL(__func__);
1829 GtkWidget *menuitem = NULL;
1830 GtkMenu *submenu_keystrokes;
1831 const gchar *domain;
1834 gchar **keystroke_values;
1837 if (cnnwin->
priv->toolbar_is_reconfiguring)
1842 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget)))
1845 priv->sticky = TRUE;
1848 menu = gtk_menu_new();
1855 menuitem = gtk_menu_item_new_with_label(g_dgettext(domain, (
const gchar *)feature->
opt1));
1858 gtk_widget_show(menuitem);
1859 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1863 g_object_set_data(G_OBJECT(menuitem),
"feature-type", (gpointer)feature);
1865 g_signal_connect(G_OBJECT(menuitem),
"activate",
1868 gtk_widget_set_sensitive(menuitem, FALSE);
1877 keystrokes = g_strsplit(remmina_pref.
keystrokes, STRING_DELIMITOR, -1);
1878 if (g_strv_length(keystrokes)) {
1880 menuitem = gtk_menu_item_new_with_label(_(
"Keystrokes"));
1881 submenu_keystrokes = GTK_MENU(gtk_menu_new());
1882 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(submenu_keystrokes));
1883 gtk_widget_show(menuitem);
1884 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1886 for (i = 0; i < g_strv_length(keystrokes); i++) {
1887 keystroke_values = g_strsplit(keystrokes[i], STRING_DELIMITOR2, -1);
1888 if (g_strv_length(keystroke_values) > 1) {
1890 menuitem = gtk_menu_item_new_with_label(
1891 g_strdup(keystroke_values[strlen(keystroke_values[0]) ? 0 : 1]));
1892 g_object_set_data(G_OBJECT(menuitem),
"keystrokes", g_strdup(keystroke_values[1]));
1893 g_signal_connect_swapped(G_OBJECT(menuitem),
"activate",
1895 REMMINA_PROTOCOL_WIDGET(cnnobj->
proto));
1896 gtk_widget_show(menuitem);
1897 gtk_menu_shell_append(GTK_MENU_SHELL(submenu_keystrokes), menuitem);
1899 g_strfreev(keystroke_values);
1902 g_strfreev(keystrokes);
1904 #if GTK_CHECK_VERSION(3, 22, 0) 1905 gtk_menu_popup_at_widget(GTK_MENU(menu), widget,
1906 GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
1914 TRACE_CALL(__func__);
1919 if (cnnwin->
priv->toolbar_is_reconfiguring)
1930 TRACE_CALL(__func__);
1932 GdkPixbuf *screenshot;
1933 GdkWindow *active_window;
1942 cairo_surface_t *srcsurface;
1943 cairo_format_t cairo_format;
1944 cairo_surface_t *surface;
1947 if (cnnwin->
priv->toolbar_is_reconfiguring)
1951 GDateTime *date = g_date_time_new_now_utc();
1954 gp = REMMINA_PROTOCOL_WIDGET(cnnobj->
proto);
1957 g_debug (
"deny_screenshot_clipboard is set to %s", denyclip);
1959 GtkClipboard *c = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
1964 remmina_debug(
"Screenshot from plugin: w=%d h=%d bpp=%d bytespp=%d\n",
1971 cairo_format = CAIRO_FORMAT_ARGB32;
1973 cairo_format = CAIRO_FORMAT_RGB24;
1975 cairo_format = CAIRO_FORMAT_RGB16_565;
1977 stride = cairo_format_stride_for_width(cairo_format, width);
1979 srcsurface = cairo_image_surface_create_for_data(rpsd.
buffer, cairo_format, width, height, stride);
1981 if (denyclip && (g_strcmp0 (denyclip,
"true")))
1982 gtk_clipboard_set_image(c, gdk_pixbuf_get_from_surface(
1983 srcsurface, 0, 0, width, height));
1984 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
1985 cr = cairo_create(surface);
1986 cairo_set_source_surface(cr, srcsurface, 0, 0);
1987 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1989 cairo_surface_destroy(srcsurface);
1998 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
1999 _(
"Turn off scaling to avoid screenshot distortion."));
2000 g_signal_connect(G_OBJECT(dialog),
"response", G_CALLBACK(gtk_widget_destroy), NULL);
2001 gtk_widget_show(dialog);
2005 active_window = gtk_widget_get_window(GTK_WIDGET(gp));
2007 width = gdk_window_get_width(active_window);
2009 height = gdk_window_get_height(active_window);
2011 screenshot = gdk_pixbuf_get_from_window(active_window, 0, 0, width, height);
2012 if (screenshot == NULL)
2013 g_print(
"gdk_pixbuf_get_from_window failed\n");
2016 if (denyclip && (g_strcmp0 (denyclip,
"true")))
2017 gtk_clipboard_set_image(c, screenshot);
2019 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
2020 cr = cairo_create(surface);
2023 gdk_cairo_set_source_pixbuf(cr, screenshot, 0, 0);
2027 g_object_unref(screenshot);
2033 pngstr = g_string_new(g_strdup_printf(
"%s/%s.png",
2041 g_strdup_printf(
"%d", g_date_time_get_year(date)));
2043 g_date_time_get_month(date)));
2045 g_strdup_printf(
"%d", g_date_time_get_day_of_month(date)));
2047 g_strdup_printf(
"%d", g_date_time_get_hour(date)));
2049 g_strdup_printf(
"%d", g_date_time_get_minute(date)));
2051 g_strdup_printf(
"%f", g_date_time_get_seconds(date)));
2052 g_date_time_unref(date);
2053 pngname = g_string_free(pngstr, FALSE);
2055 cairo_surface_write_to_png(surface, pngname);
2058 if (g_file_test(pngname, G_FILE_TEST_EXISTS))
2063 cairo_surface_destroy(surface);
2068 TRACE_CALL(__func__);
2070 if (cnnwin->
priv->toolbar_is_reconfiguring)
2074 gtk_window_iconify(GTK_WINDOW(cnnwin));
2079 TRACE_CALL(__func__);
2081 if (cnnwin->
priv->toolbar_is_reconfiguring)
2089 TRACE_CALL(__func__);
2093 if (cnnwin->
priv->toolbar_is_reconfiguring)
2097 capture = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget));
2100 #if DEBUG_KB_GRABBING 2101 printf(
"DEBUG_KB_GRABBING: Grabbing for button\n");
2115 TRACE_CALL(__func__);
2119 GtkToolItem *toolitem;
2125 priv->toolbar_is_reconfiguring = TRUE;
2127 toolbar = gtk_toolbar_new();
2128 gtk_widget_show(toolbar);
2129 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
2130 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), GTK_ICON_SIZE_SMALL_TOOLBAR);
2131 gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), FALSE);
2134 toolitem = gtk_tool_button_new(NULL, NULL);
2135 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-fit-window-symbolic");
2136 rcw_set_tooltip(GTK_WIDGET(toolitem), _(
"Resize the window to fit in remote resolution"),
2139 priv->toolitem_autofit = toolitem;
2140 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2141 gtk_widget_show(GTK_WIDGET(toolitem));
2145 toolitem = gtk_toggle_tool_button_new();
2146 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-fullscreen-symbolic");
2149 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2150 gtk_widget_show(GTK_WIDGET(toolitem));
2151 priv->toolitem_fullscreen = toolitem;
2153 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), FALSE);
2155 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), mode !=
SCROLLED_WINDOW_MODE);
2160 toolitem = gtk_tool_item_new();
2161 gtk_widget_show(GTK_WIDGET(toolitem));
2162 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2163 widget = gtk_toggle_button_new();
2164 gtk_widget_show(widget);
2165 gtk_container_set_border_width(GTK_CONTAINER(widget), 0);
2166 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
2167 #if GTK_CHECK_VERSION(3, 20, 0) 2168 gtk_widget_set_focus_on_click(GTK_WIDGET(widget), FALSE);
2170 gtk_widget_set_name(widget,
"remmina-small-button");
2173 gtk_button_set_focus_on_click(GTK_BUTTON(widget), FALSE);
2175 gtk_container_add(GTK_CONTAINER(toolitem), widget);
2177 #if GTK_CHECK_VERSION(3, 14, 0) 2178 arrow = gtk_image_new_from_icon_name(
"remmina-pan-down-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
2180 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2182 gtk_widget_show(arrow);
2183 gtk_container_add(GTK_CONTAINER(widget), arrow);
2185 priv->fullscreen_option_button = widget;
2187 gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE);
2190 toolitem = gtk_toggle_tool_button_new();
2191 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-switch-page-symbolic");
2194 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2195 gtk_widget_show(GTK_WIDGET(toolitem));
2197 priv->toolitem_switch_page = toolitem;
2199 toolitem = gtk_separator_tool_item_new();
2200 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2201 gtk_widget_show(GTK_WIDGET(toolitem));
2204 toolitem = gtk_toggle_tool_button_new();
2205 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-dynres-symbolic");
2206 rcw_set_tooltip(GTK_WIDGET(toolitem), _(
"Toggle dynamic resolution update"),
2208 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2209 gtk_widget_show(GTK_WIDGET(toolitem));
2210 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_dynres), cnnwin);
2211 priv->toolitem_dynres = toolitem;
2214 toolitem = gtk_toggle_tool_button_new();
2215 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-scale-symbolic");
2217 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2218 gtk_widget_show(GTK_WIDGET(toolitem));
2220 priv->toolitem_scale = toolitem;
2223 toolitem = gtk_tool_item_new();
2224 gtk_widget_show(GTK_WIDGET(toolitem));
2225 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2226 widget = gtk_toggle_button_new();
2227 gtk_widget_show(widget);
2228 gtk_container_set_border_width(GTK_CONTAINER(widget), 0);
2229 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
2230 #if GTK_CHECK_VERSION(3, 20, 0) 2231 gtk_widget_set_focus_on_click(GTK_WIDGET(widget), FALSE);
2233 gtk_button_set_focus_on_click(GTK_BUTTON(widget), FALSE);
2236 gtk_widget_set_name(widget,
"remmina-small-button");
2237 gtk_container_add(GTK_CONTAINER(toolitem), widget);
2238 #if GTK_CHECK_VERSION(3, 14, 0) 2239 arrow = gtk_image_new_from_icon_name(
"remmina-pan-down-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
2241 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2243 gtk_widget_show(arrow);
2244 gtk_container_add(GTK_CONTAINER(widget), arrow);
2246 priv->scaler_option_button = widget;
2249 toolitem = gtk_toggle_tool_button_new();
2250 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-keyboard-symbolic");
2253 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2254 gtk_widget_show(GTK_WIDGET(toolitem));
2255 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_grab), cnnwin);
2256 priv->toolitem_grab = toolitem;
2258 toolitem = gtk_toggle_tool_button_new();
2259 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-preferences-system-symbolic");
2260 gtk_tool_item_set_tooltip_text(toolitem, _(
"_Preferences"));
2261 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2262 gtk_widget_show(GTK_WIDGET(toolitem));
2264 priv->toolitem_preferences = toolitem;
2266 toolitem = gtk_toggle_tool_button_new();
2267 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-system-run-symbolic");
2268 gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolitem), _(
"_Tools"));
2269 gtk_tool_item_set_tooltip_text(toolitem, _(
"Tools"));
2270 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2271 gtk_widget_show(GTK_WIDGET(toolitem));
2272 g_signal_connect(G_OBJECT(toolitem),
"toggled", G_CALLBACK(
rcw_toolbar_tools), cnnwin);
2273 priv->toolitem_tools = toolitem;
2275 toolitem = gtk_separator_tool_item_new();
2276 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2277 gtk_widget_show(GTK_WIDGET(toolitem));
2279 toolitem = gtk_tool_button_new(NULL,
"Duplicate connection");
2280 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-duplicate-symbolic");
2281 gtk_tool_item_set_tooltip_text(toolitem, _(
"Duplicate current connection"));
2282 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2283 gtk_widget_show(GTK_WIDGET(toolitem));
2286 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2288 priv->toolitem_duplicate = toolitem;
2290 toolitem = gtk_tool_button_new(NULL,
"_Screenshot");
2291 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-camera-photo-symbolic");
2293 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2294 gtk_widget_show(GTK_WIDGET(toolitem));
2296 priv->toolitem_screenshot = toolitem;
2298 toolitem = gtk_tool_button_new(NULL,
"_Bottom");
2299 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-go-bottom-symbolic");
2301 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2302 gtk_widget_show(GTK_WIDGET(toolitem));
2305 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
2307 toolitem = gtk_tool_button_new(NULL,
"_Disconnect");
2308 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem),
"remmina-disconnect-symbolic");
2310 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
2311 gtk_widget_show(GTK_WIDGET(toolitem));
2314 priv->toolbar_is_reconfiguring = FALSE;
2318 static void rcw_place_toolbar(GtkToolbar *toolbar, GtkGrid *grid, GtkWidget *sibling,
int toolbar_placement)
2323 gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_VERTICAL);
2325 gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
2328 switch (toolbar_placement) {
2330 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), TRUE);
2331 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), FALSE);
2332 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_TOP, 1, 1);
2335 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), TRUE);
2336 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), FALSE);
2337 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_RIGHT, 1, 1);
2340 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), TRUE);
2341 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), FALSE);
2342 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_BOTTOM, 1, 1);
2345 gtk_widget_set_vexpand(GTK_WIDGET(toolbar), TRUE);
2346 gtk_widget_set_hexpand(GTK_WIDGET(toolbar), FALSE);
2347 gtk_grid_attach_next_to(GTK_GRID(grid), GTK_WIDGET(toolbar), sibling, GTK_POS_LEFT, 1, 1);
2354 TRACE_CALL(__func__);
2356 GtkToolItem *toolitem;
2357 gboolean bval, dynres_avail, scale_avail;
2358 gboolean test_floating_toolbar;
2361 priv->toolbar_is_reconfiguring = TRUE;
2366 toolitem = priv->toolitem_switch_page;
2370 bval = (gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)) > 1);
2371 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval);
2374 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_duplicate), TRUE);
2376 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_duplicate), FALSE);
2379 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_dynres), dynres_avail && cnnobj->
connected);
2380 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_scale), scale_avail && cnnobj->
connected);
2382 switch (scalemode) {
2384 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_dynres), FALSE);
2385 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), FALSE);
2386 gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), FALSE);
2389 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_dynres), FALSE);
2390 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), TRUE);
2391 gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), TRUE && cnnobj->
connected);
2394 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_dynres), TRUE);
2395 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), FALSE);
2396 gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), FALSE);
2400 toolitem = priv->toolitem_grab;
2401 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), cnnobj->
connected);
2402 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem),
2405 toolitem = priv->toolitem_preferences;
2406 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), cnnobj->
connected);
2409 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval && cnnobj->
connected);
2411 toolitem = priv->toolitem_tools;
2414 gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval && cnnobj->
connected);
2416 gtk_widget_set_sensitive(GTK_WIDGET(priv->toolitem_screenshot), cnnobj->
connected);
2420 test_floating_toolbar = (priv->floating_toolbar_widget != NULL);
2421 if (test_floating_toolbar)
2422 gtk_label_set_text(GTK_LABEL(priv->floating_toolbar_label),
2425 priv->toolbar_is_reconfiguring = FALSE;
2430 TRACE_CALL(__func__);
2435 gtk_widget_hide(priv->toolbar);
2437 gtk_widget_show(priv->toolbar);
2444 TRACE_CALL(__func__);
2452 TRACE_CALL(__func__);
2463 TRACE_CALL(__func__);
2465 #if DEBUG_KB_GRABBING 2466 printf(
"DEBUG_KB_GRABBING: leave detail=");
2467 switch (event->detail) {
2468 case GDK_NOTIFY_ANCESTOR: printf(
"GDK_NOTIFY_ANCESTOR");
break;
2469 case GDK_NOTIFY_VIRTUAL: printf(
"GDK_NOTIFY_VIRTUAL");
break;
2470 case GDK_NOTIFY_NONLINEAR: printf(
"GDK_NOTIFY_NONLINEAR");
break;
2471 case GDK_NOTIFY_NONLINEAR_VIRTUAL: printf(
"GDK_NOTIFY_NONLINEAR_VIRTUAL");
break;
2472 case GDK_NOTIFY_UNKNOWN: printf(
"GDK_NOTIFY_UNKNOWN");
break;
2473 case GDK_NOTIFY_INFERIOR: printf(
"GDK_NOTIFY_INFERIOR");
break;
2474 default: printf(
"unknown");
2478 #if DEBUG_KB_GRABBING 2479 printf(
"DEBUG_KB_GRABBING: leave mode=");
2480 switch (event->mode) {
2481 case GDK_CROSSING_NORMAL: printf(
"GDK_CROSSING_NORMAL");
break;
2482 case GDK_CROSSING_GRAB: printf(
"GDK_CROSSING_GRAB");
break;
2483 case GDK_CROSSING_UNGRAB: printf(
"GDK_CROSSING_UNGRAB");
break;
2484 case GDK_CROSSING_GTK_GRAB: printf(
"GDK_CROSSING_GTK_GRAB");
break;
2485 case GDK_CROSSING_GTK_UNGRAB: printf(
"GDK_CROSSING_GTK_UNGRAB");
break;
2486 case GDK_CROSSING_STATE_CHANGED: printf(
"GDK_CROSSING_STATE_CHANGED");
break;
2487 case GDK_CROSSING_TOUCH_BEGIN: printf(
"GDK_CROSSING_TOUCH_BEGIN");
break;
2488 case GDK_CROSSING_TOUCH_END: printf(
"GDK_CROSSING_TOUCH_END");
break;
2489 case GDK_CROSSING_DEVICE_SWITCH: printf(
"GDK_CROSSING_DEVICE_SWITCH");
break;
2491 default: printf(
"unknown");
2496 cnnobj->
cnnwin->
priv->pointer_entered = FALSE;
2499 if (event->mode == GDK_CROSSING_NORMAL)
2509 TRACE_CALL(__func__);
2512 #if DEBUG_KB_GRABBING 2513 printf(
"DEBUG_KB_GRABBING: %s: enter event received\n", __func__);
2517 if (!priv->sticky && event->mode == GDK_CROSSING_NORMAL) {
2521 priv->pointer_entered = TRUE;
2524 active = gtk_window_is_active(GTK_WINDOW(cnnobj->
cnnwin));
2535 TRACE_CALL(__func__);
2541 #if DEBUG_KB_GRABBING 2542 printf(
"DEBUG_KB_GRABBING: Received focus in and grabbing enabled, requesting kb grab\n");
2546 #if DEBUG_KB_GRABBING 2547 printf(
"DEBUG_KB_GRABBING: requesting also pointer grab, because of pointer_entered\n");
2556 TRACE_CALL(__func__);
2561 cnnwin->
priv->hostkey_activated = FALSE;
2575 TRACE_CALL(__func__);
2577 priv->hidetb_eventsource = 0;
2579 return G_SOURCE_REMOVE;
2585 TRACE_CALL(__func__);
2595 switch (event->direction) {
2603 case GDK_SCROLL_DOWN:
2604 if (opacity < TOOLBAR_OPACITY_LEVEL) {
2610 #ifdef GDK_SCROLL_SMOOTH 2611 case GDK_SCROLL_SMOOTH:
2612 if (event->delta_y < 0 && opacity > 0) {
2617 if (event->delta_y > 0 && opacity < TOOLBAR_OPACITY_LEVEL) {
2632 TRACE_CALL(__func__);
2640 if (!cnnobj || !cnnobj->
cnnwin)
2643 s = gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnobj->
cnnwin)));
2648 npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnobj->
cnnwin->
priv->notebook));
2649 for (ipg = 0; ipg < npages; ipg++) {
2650 cnnobj = g_object_get_data(
2651 G_OBJECT(gtk_notebook_get_nth_page(GTK_NOTEBOOK(cnnobj->
cnnwin->
priv->notebook), ipg)),
2653 if (s & GDK_WINDOW_STATE_MAXIMIZED) {
2656 gtk_window_get_size(GTK_WINDOW(cnnobj->
cnnwin), &width, &height);
2669 TRACE_CALL(__func__);
2673 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
2680 if (cnnwin->
priv->acs_eventsourceid) {
2681 g_source_remove(cnnwin->
priv->acs_eventsourceid);
2682 cnnwin->
priv->acs_eventsourceid = 0;
2685 if (gtk_widget_get_window(GTK_WIDGET(cnnwin))
2700 TRACE_CALL(__func__);
2701 if (cnnwin->
priv->pin_down)
2702 gtk_button_set_image(GTK_BUTTON(cnnwin->
priv->pin_button),
2703 gtk_image_new_from_icon_name(
"remmina-pin-down-symbolic", GTK_ICON_SIZE_MENU));
2705 gtk_button_set_image(GTK_BUTTON(cnnwin->
priv->pin_button),
2706 gtk_image_new_from_icon_name(
"remmina-pin-up-symbolic", GTK_ICON_SIZE_MENU));
2711 TRACE_CALL(__func__);
2719 TRACE_CALL(__func__);
2722 GtkWidget *ftb_widget;
2726 GtkWidget *pinbutton;
2731 ftb_widget = gtk_event_box_new();
2733 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
2734 gtk_widget_show(vbox);
2736 gtk_container_add(GTK_CONTAINER(ftb_widget), vbox);
2739 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2740 gtk_widget_show(hbox);
2744 pinbutton = gtk_button_new();
2745 gtk_widget_show(pinbutton);
2746 gtk_box_pack_start(GTK_BOX(hbox), pinbutton, FALSE, FALSE, 0);
2747 gtk_button_set_relief(GTK_BUTTON(pinbutton), GTK_RELIEF_NONE);
2748 #if GTK_CHECK_VERSION(3, 20, 0) 2749 gtk_widget_set_focus_on_click(GTK_WIDGET(pinbutton), FALSE);
2751 gtk_button_set_focus_on_click(GTK_BUTTON(pinbutton), FALSE);
2753 gtk_widget_set_name(pinbutton,
"remmina-pin-button");
2754 g_signal_connect(G_OBJECT(pinbutton),
"clicked", G_CALLBACK(
rcw_toolbar_pin), cnnwin);
2755 priv->pin_button = pinbutton;
2760 label = gtk_label_new(
"");
2761 gtk_label_set_max_width_chars(GTK_LABEL(label), 50);
2762 gtk_widget_show(label);
2764 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2766 priv->floating_toolbar_label = label;
2769 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2770 gtk_box_pack_start(GTK_BOX(vbox), tb, FALSE, FALSE, 0);
2772 gtk_box_pack_start(GTK_BOX(vbox), tb, FALSE, FALSE, 0);
2773 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
2776 priv->floating_toolbar_widget = ftb_widget;
2777 gtk_widget_show(ftb_widget);
2782 TRACE_CALL(__func__);
2785 priv = cnnwin->
priv;
2787 if (priv->toolbar && priv->grid) {
2788 g_object_ref(priv->toolbar);
2789 gtk_container_remove(GTK_CONTAINER(priv->grid), priv->toolbar);
2791 g_object_unref(priv->toolbar);
2798 TRACE_CALL(__func__);
2802 cnnwin->
priv = priv;
2808 priv->floating_toolbar_opacity = 1.0;
2809 priv->kbcaptured = FALSE;
2810 priv->pointer_captured = FALSE;
2811 priv->pointer_entered = FALSE;
2813 priv->ss_width = 640;
2814 priv->ss_height = 480;
2815 priv->ss_maximized = FALSE;
2820 static gboolean
rcw_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
2822 TRACE_CALL(__func__);
2824 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
2827 if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED) {
2828 if (event->new_window_state & GDK_WINDOW_STATE_FOCUSED)
2839 gint target_monitor;
2841 TRACE_CALL(__func__);
2843 if (!REMMINA_IS_CONNECTION_WINDOW(widget))
2846 target_monitor = GPOINTER_TO_INT(data);
2848 #if GTK_CHECK_VERSION(3, 18, 0) 2850 if (target_monitor == FULL_SCREEN_TARGET_MONITOR_UNDEFINED)
2851 gtk_window_fullscreen(GTK_WINDOW(widget));
2853 gtk_window_fullscreen_on_monitor(GTK_WINDOW(widget), gtk_window_get_screen(GTK_WINDOW(widget)),
2856 remmina_debug(
"Fullscreen managed by WM or by the user, as per settings");
2857 gtk_window_fullscreen(GTK_WINDOW(widget));
2860 remmina_debug(
"Cannot fullscreen on a specific monitor, feature available from GTK 3.18");
2861 gtk_window_fullscreen(GTK_WINDOW(widget));
2868 rcw_new(gboolean fullscreen,
int full_screen_target_monitor)
2870 TRACE_CALL(__func__);
2873 cnnwin = RCW(g_object_new(REMMINA_TYPE_CONNECTION_WINDOW, NULL));
2878 g_signal_connect(G_OBJECT(cnnwin),
"map-event", G_CALLBACK(
rcw_map_event_fullscreen), GINT_TO_POINTER(full_screen_target_monitor));
2880 gtk_container_set_border_width(GTK_CONTAINER(cnnwin), 0);
2883 g_signal_connect(G_OBJECT(cnnwin),
"delete-event", G_CALLBACK(
rcw_delete_event), NULL);
2884 g_signal_connect(G_OBJECT(cnnwin),
"destroy", G_CALLBACK(
rcw_destroy), NULL);
2888 g_signal_connect(G_OBJECT(cnnwin),
"window-state-event", G_CALLBACK(
rcw_state_event), NULL);
2893 g_signal_connect(G_OBJECT(cnnwin),
"configure_event", G_CALLBACK(
rcw_on_configure), NULL);
2903 TRACE_CALL(__func__);
2917 g_object_set_data_full(G_OBJECT(cnnwin),
"tag", tag, (GDestroyNotify)g_free);
2922 TRACE_CALL(__func__);
2927 if (GTK_IS_WIDGET(cnnobj->
proto))
2934 GtkWidget *found_page, *pg;
2936 if (cnnobj == NULL || cnnobj->
cnnwin == NULL || cnnobj->
cnnwin->
priv == NULL)
2939 np = gtk_notebook_get_n_pages(cnnobj->
cnnwin->
priv->notebook);
2940 for (i = 0; i < np; i++) {
2941 pg = gtk_notebook_get_nth_page(cnnobj->
cnnwin->
priv->notebook, i);
2942 if (g_object_get_data(G_OBJECT(pg),
"cnnobj") == cnnobj) {
2954 TRACE_CALL(__func__);
2956 GtkWidget *page_to_remove;
2958 if (cnnobj && cnnobj->
cnnwin) {
2960 if (page_to_remove) {
2961 gtk_notebook_remove_page(
2963 gtk_notebook_page_num(cnnobj->
cnnwin->
priv->notebook, page_to_remove));
2976 TRACE_CALL(__func__);
2977 if (REMMINA_IS_PROTOCOL_WIDGET(cnnobj->
proto)) {
2987 TRACE_CALL(__func__);
2992 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
2993 gtk_widget_show(hbox);
2996 gtk_widget_show(widget);
2997 gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
3000 gtk_widget_set_valign(widget, GTK_ALIGN_CENTER);
3001 gtk_widget_set_halign(widget, GTK_ALIGN_CENTER);
3003 gtk_widget_show(widget);
3004 gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
3006 button = gtk_button_new();
3007 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
3008 #if GTK_CHECK_VERSION(3, 20, 0) 3009 gtk_widget_set_focus_on_click(GTK_WIDGET(widget), FALSE);
3011 gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
3013 gtk_widget_set_name(button,
"remmina-small-button");
3014 gtk_widget_show(button);
3016 widget = gtk_image_new_from_icon_name(
"window-close", GTK_ICON_SIZE_MENU);
3017 gtk_widget_show(widget);
3018 gtk_container_add(GTK_CONTAINER(button), widget);
3020 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3034 page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
3035 gtk_widget_set_name(page,
"remmina-tab-page");
3043 TRACE_CALL(__func__);
3044 GtkWidget *page, *label;
3045 GtkNotebook *notebook;
3047 notebook = cnnwin->
priv->notebook;
3050 g_object_set_data(G_OBJECT(page),
"cnnobj", cnnobj);
3055 gtk_notebook_append_page(notebook, page, label);
3056 gtk_notebook_set_tab_reorderable(notebook, page, TRUE);
3057 gtk_notebook_set_tab_detachable(notebook, page, TRUE);
3059 gtk_widget_set_can_focus(gtk_widget_get_parent(label), FALSE);
3062 printf(
"REMMINA WARNING in %s: scrolled_container already has a parent\n", __func__);
3065 gtk_widget_show(page);
3073 TRACE_CALL(__func__);
3074 GtkNotebook *notebook;
3077 notebook = GTK_NOTEBOOK(cnnwin->
priv->notebook);
3079 switch (cnnwin->
priv->view_mode) {
3081 n = gtk_notebook_get_n_pages(notebook);
3082 gtk_notebook_set_show_tabs(notebook, remmina_pref.
always_show_tab ? TRUE : n > 1);
3083 gtk_notebook_set_show_border(notebook, remmina_pref.
always_show_tab ? TRUE : n > 1);
3086 gtk_notebook_set_show_tabs(notebook, FALSE);
3087 gtk_notebook_set_show_border(notebook, FALSE);
3094 TRACE_CALL(__func__);
3107 if (GTK_IS_WIDGET(cnnobj->
cnnwin)) {
3109 if (!priv->hidetb_eventsource)
3110 priv->hidetb_eventsource = g_timeout_add(TB_HIDE_TIME_TIME, (GSourceFunc)
3117 priv->spf_eventsourceid = 0;
3124 TRACE_CALL(__func__);
3128 cnnobj_newpage = g_object_get_data(G_OBJECT(newpage),
"cnnobj");
3129 if (priv->spf_eventsourceid)
3130 g_source_remove(priv->spf_eventsourceid);
3137 if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnwin->
priv->notebook)) > 0)
3144 TRACE_CALL(__func__);
3146 if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnwin->
priv->notebook)) <= 0)
3147 gtk_widget_destroy(GTK_WIDGET(cnnwin));
3150 static GtkNotebook *
3156 TRACE_CALL(__func__);
3164 #if GTK_CHECK_VERSION(3, 20, 0) 3167 GdkDeviceManager *manager;
3169 GdkDevice *device = NULL;
3171 #if GTK_CHECK_VERSION(3, 20, 0) 3172 seat = gdk_display_get_default_seat(gdk_display_get_default());
3173 device = gdk_seat_get_pointer(seat);
3175 manager = gdk_display_get_device_manager(gdk_display_get_default());
3176 device = gdk_device_manager_get_client_pointer(manager);
3179 window = gdk_device_get_window_at_position(device, &x, &y);
3180 srccnnwin = RCW(gtk_widget_get_toplevel(GTK_WIDGET(notebook)));
3183 if (srccnnwin == dstcnnwin)
3186 if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(srccnnwin->
priv->notebook)) == 1 && !dstcnnwin)
3195 srctag = (gchar *)g_object_get_data(G_OBJECT(srccnnwin),
"tag");
3196 gtk_window_get_size(GTK_WINDOW(srccnnwin), &width, &height);
3198 g_object_set_data_full(G_OBJECT(dstcnnwin),
"tag", g_strdup(srctag), (GDestroyNotify)g_free);
3201 cnnobj->
cnnwin = dstcnnwin;
3203 cnnobj->
cnnwin = dstcnnwin;
3209 return GTK_NOTEBOOK(cnnobj->
cnnwin->
priv->notebook);
3212 static GtkNotebook *
3215 TRACE_CALL(__func__);
3216 GtkNotebook *notebook;
3218 notebook = GTK_NOTEBOOK(gtk_notebook_new());
3220 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3221 gtk_widget_show(GTK_WIDGET(notebook));
3224 g_signal_connect(G_OBJECT(notebook),
"switch-page", G_CALLBACK(
rcw_on_switch_page), cnnwin);
3225 g_signal_connect(G_OBJECT(notebook),
"page-added", G_CALLBACK(
rcw_on_page_added), cnnwin);
3226 g_signal_connect(G_OBJECT(notebook),
"page-removed", G_CALLBACK(
rcw_on_page_removed), cnnwin);
3227 gtk_widget_set_can_focus(GTK_WIDGET(notebook), FALSE);
3235 TRACE_CALL(__func__);
3239 GtkNotebook *notebook;
3242 gtk_widget_realize(GTK_WIDGET(cnnwin));
3244 gtk_window_set_default_size(GTK_WINDOW(cnnwin), width, height);
3253 grid = gtk_grid_new();
3256 gtk_grid_attach(GTK_GRID(grid), GTK_WIDGET(notebook), 0, 0, 1, 1);
3258 gtk_widget_set_hexpand(GTK_WIDGET(notebook), TRUE);
3259 gtk_widget_set_vexpand(GTK_WIDGET(notebook), TRUE);
3263 gtk_container_add(GTK_CONTAINER(cnnwin), grid);
3266 gtk_drag_source_set(GTK_WIDGET(toolbar), GDK_BUTTON1_MASK,
3267 dnd_targets_tb,
sizeof dnd_targets_tb /
sizeof *dnd_targets_tb, GDK_ACTION_MOVE);
3268 g_signal_connect_after(GTK_WIDGET(toolbar),
"drag-begin", G_CALLBACK(
rcw_tb_drag_begin), NULL);
3269 g_signal_connect(GTK_WIDGET(toolbar),
"drag-failed", G_CALLBACK(
rcw_tb_drag_failed), cnnwin);
3272 gtk_drag_dest_set(GTK_WIDGET(notebook), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
3273 dnd_targets_tb,
sizeof dnd_targets_tb /
sizeof *dnd_targets_tb, GDK_ACTION_MOVE);
3274 gtk_drag_dest_set_track_motion(GTK_WIDGET(notebook), TRUE);
3275 g_signal_connect(GTK_WIDGET(notebook),
"drag-drop", G_CALLBACK(
rcw_tb_drag_drop), cnnwin);
3278 cnnwin->
priv->toolbar = toolbar;
3279 cnnwin->
priv->grid = grid;
3280 cnnwin->
priv->notebook = notebook;
3281 cnnwin->
priv->ss_width = width;
3282 cnnwin->
priv->ss_height = height;
3283 cnnwin->
priv->ss_maximized = maximize;
3287 gtk_widget_show(grid);
3288 gtk_widget_show(GTK_WIDGET(cnnwin));
3289 GtkWindowGroup * wingrp = gtk_window_group_new ();
3290 gtk_window_group_add_window (wingrp, GTK_WINDOW(cnnwin));
3291 gtk_window_set_transient_for(GTK_WINDOW(cnnwin), NULL);
3294 gtk_window_maximize(GTK_WINDOW(cnnwin));
3304 TRACE_CALL(__func__);
3306 GtkWidget *revealer;
3308 priv = cnnwin->
priv;
3310 if (priv->overlay_ftb_overlay != NULL) {
3311 gtk_widget_destroy(priv->overlay_ftb_overlay);
3312 priv->overlay_ftb_overlay = NULL;
3313 priv->revealer = NULL;
3318 priv->overlay_ftb_overlay = gtk_event_box_new();
3320 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
3321 gtk_container_set_border_width(GTK_CONTAINER(vbox), 0);
3323 GtkWidget *handle = gtk_drawing_area_new();
3324 gtk_widget_set_size_request(handle, 4, 4);
3325 gtk_widget_set_name(handle,
"ftb-handle");
3327 revealer = gtk_revealer_new();
3329 gtk_widget_set_halign(GTK_WIDGET(priv->overlay_ftb_overlay), GTK_ALIGN_CENTER);
3332 gtk_box_pack_start(GTK_BOX(vbox), handle, FALSE, FALSE, 0);
3333 gtk_box_pack_start(GTK_BOX(vbox), revealer, FALSE, FALSE, 0);
3334 gtk_revealer_set_transition_type(GTK_REVEALER(revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
3335 gtk_widget_set_valign(GTK_WIDGET(priv->overlay_ftb_overlay), GTK_ALIGN_END);
3337 gtk_box_pack_start(GTK_BOX(vbox), revealer, FALSE, FALSE, 0);
3338 gtk_box_pack_start(GTK_BOX(vbox), handle, FALSE, FALSE, 0);
3339 gtk_revealer_set_transition_type(GTK_REVEALER(revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
3340 gtk_widget_set_valign(GTK_WIDGET(priv->overlay_ftb_overlay), GTK_ALIGN_START);
3344 gtk_container_add(GTK_CONTAINER(revealer), priv->floating_toolbar_widget);
3345 gtk_widget_set_halign(GTK_WIDGET(revealer), GTK_ALIGN_CENTER);
3346 gtk_widget_set_valign(GTK_WIDGET(revealer), GTK_ALIGN_START);
3348 priv->revealer = revealer;
3351 fr = gtk_frame_new(NULL);
3352 gtk_container_add(GTK_CONTAINER(priv->overlay_ftb_overlay), fr);
3353 gtk_container_add(GTK_CONTAINER(fr), vbox);
3355 gtk_widget_show(vbox);
3356 gtk_widget_show(revealer);
3357 gtk_widget_show(handle);
3358 gtk_widget_show(priv->overlay_ftb_overlay);
3359 gtk_widget_show(fr);
3362 gtk_widget_set_name(fr,
"ftbbox-lower");
3364 gtk_widget_set_name(fr,
"ftbbox-upper");
3366 gtk_overlay_add_overlay(GTK_OVERLAY(priv->overlay), priv->overlay_ftb_overlay);
3372 gtk_widget_add_events(GTK_WIDGET(priv->overlay_ftb_overlay), GDK_SCROLL_MASK);
3375 gtk_drag_source_set(GTK_WIDGET(priv->overlay_ftb_overlay), GDK_BUTTON1_MASK,
3376 dnd_targets_ftb,
sizeof dnd_targets_ftb /
sizeof *dnd_targets_ftb, GDK_ACTION_MOVE);
3377 g_signal_connect_after(GTK_WIDGET(priv->overlay_ftb_overlay),
"drag-begin", G_CALLBACK(rcw_ftb_drag_begin), cnnwin);
3381 gtk_widget_hide(fr);
3389 TRACE_CALL(__func__);
3391 gint new_floating_toolbar_placement;
3394 gtk_widget_get_allocation(widget, &wa);
3396 if (y >= wa.height / 2)
3401 gtk_drag_finish(context, TRUE, TRUE, time);
3417 TRACE_CALL(__func__);
3419 cairo_surface_t *surface;
3422 double dashes[] = { 10 };
3424 gtk_widget_get_allocation(widget, &wa);
3426 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, wa.width, wa.height);
3427 cr = cairo_create(surface);
3428 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
3429 cairo_set_line_width(cr, 2);
3430 cairo_set_dash(cr, dashes, 1, 0);
3431 cairo_rectangle(cr, 0, 0, wa.width, wa.height);
3435 gtk_drag_set_icon_surface(context, surface);
3440 TRACE_CALL(__func__);
3442 GtkNotebook *notebook;
3443 #if GTK_CHECK_VERSION(3, 22, 0) 3446 GdkMonitor *old_monitor;
3447 GdkDisplay *old_display;
3448 GdkWindow *old_window;
3450 gint full_screen_target_monitor;
3452 full_screen_target_monitor = FULL_SCREEN_TARGET_MONITOR_UNDEFINED;
3454 #if GTK_CHECK_VERSION(3, 22, 0) 3455 old_window = gtk_widget_get_window(GTK_WIDGET(old));
3456 old_display = gdk_window_get_display(old_window);
3457 old_monitor = gdk_display_get_monitor_at_window(old_display, old_window);
3458 n_monitors = gdk_display_get_n_monitors(old_display);
3459 for (i = 0; i < n_monitors; ++i) {
3460 if (gdk_display_get_monitor(old_display, i) == old_monitor) {
3461 full_screen_target_monitor = i;
3466 full_screen_target_monitor = gdk_screen_get_monitor_at_window(
3467 gdk_screen_get_default(),
3468 gtk_widget_get_window(GTK_WIDGET(old)));
3472 cnnwin =
rcw_new(TRUE, full_screen_target_monitor);
3473 gtk_widget_set_name(GTK_WIDGET(cnnwin),
"remmina-connection-window-fullscreen");
3474 gtk_widget_realize(GTK_WIDGET(cnnwin));
3481 cnnwin->
priv->overlay = gtk_overlay_new();
3482 gtk_container_add(GTK_CONTAINER(cnnwin), cnnwin->
priv->overlay);
3483 gtk_container_add(GTK_CONTAINER(cnnwin->
priv->overlay), GTK_WIDGET(notebook));
3484 gtk_widget_show(GTK_WIDGET(cnnwin->
priv->overlay));
3486 cnnwin->
priv->notebook = notebook;
3487 cnnwin->
priv->view_mode = view_mode;
3488 cnnwin->
priv->fss_view_mode = view_mode;
3493 gtk_drag_dest_set(GTK_WIDGET(cnnwin->
priv->overlay), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
3494 dnd_targets_ftb,
sizeof dnd_targets_ftb /
sizeof *dnd_targets_ftb, GDK_ACTION_MOVE);
3495 gtk_drag_dest_set_track_motion(GTK_WIDGET(cnnwin->
priv->notebook), TRUE);
3496 g_signal_connect(GTK_WIDGET(cnnwin->
priv->overlay),
"drag-drop", G_CALLBACK(
rcw_ftb_drag_drop), cnnwin);
3498 gtk_widget_show(GTK_WIDGET(cnnwin));
3499 GtkWindowGroup * wingrp = gtk_window_group_new ();
3500 gtk_window_group_add_window (wingrp, GTK_WINDOW(cnnwin));
3501 gtk_window_set_transient_for(GTK_WINDOW(cnnwin), NULL);
3508 TRACE_CALL(__func__);
3516 priv->hostkey_activated = FALSE;
3517 if (priv->hostkey_used)
3524 else if (priv->hostkey_activated) {
3532 }
else if (remmina_pref.
hostkey && keyval == remmina_pref.
hostkey) {
3534 priv->hostkey_activated = TRUE;
3535 priv->hostkey_used = FALSE;
3537 }
else if (!priv->hostkey_activated) {
3542 priv->hostkey_used = TRUE;
3543 keyval = gdk_keyval_to_lower(keyval);
3544 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down
3545 || keyval == GDK_KEY_Left || keyval == GDK_KEY_Right) {
3546 GtkAdjustment *adjust;
3550 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down)
3551 adjust = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container));
3553 adjust = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container));
3555 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Left)
3558 pos = gtk_adjustment_get_upper(adjust);
3560 gtk_adjustment_set_value(adjust, pos);
3561 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down)
3562 gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container), adjust);
3564 gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(cnnobj->
scrolled_container), adjust);
3577 child = gtk_bin_get_child(GTK_BIN(gsv));
3578 if (!GTK_IS_VIEWPORT(child))
3581 gsvwin = gtk_widget_get_window(GTK_WIDGET(gsv));
3585 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Down) {
3586 sz = gdk_window_get_height(gsvwin) + 2;
3587 adj = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(child));
3589 sz = gdk_window_get_width(gsvwin) + 2;
3590 adj = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(child));
3593 if (keyval == GDK_KEY_Up || keyval == GDK_KEY_Left)
3596 value = gtk_adjustment_get_upper(GTK_ADJUSTMENT(adj)) - (gdouble)sz + 2.0;
3598 gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), value);
3603 switch (priv->view_mode) {
3615 if (priv->toolitem_autofit && gtk_widget_is_sensitive(GTK_WIDGET(priv->toolitem_autofit)))
3618 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook)) + 1;
3619 if (i >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)))
3621 gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), i);
3623 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook)) - 1;
3625 i = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)) - 1;
3626 gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), i);
3628 if (gtk_widget_is_sensitive(GTK_WIDGET(priv->toolitem_scale))) {
3629 gtk_toggle_tool_button_set_active(
3630 GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale),
3631 !gtk_toggle_tool_button_get_active(
3632 GTK_TOGGLE_TOOL_BUTTON(
3633 priv->toolitem_scale)));
3636 gtk_toggle_tool_button_set_active(
3637 GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_grab),
3638 !gtk_toggle_tool_button_get_active(
3639 GTK_TOGGLE_TOOL_BUTTON(
3640 priv->toolitem_grab)));
3662 REMMINA_PROTOCOL_WIDGET(
3664 feature && feature->
type;
3668 && GPOINTER_TO_UINT(
3672 REMMINA_PROTOCOL_WIDGET(
3681 cnnobj->
cnnwin->
priv->hostkey_activated = FALSE;
3689 TRACE_CALL(__func__);
3714 gtk_window_present_with_time(GTK_WINDOW(cnnwin), (guint32)(g_get_monotonic_time() / 1000));
3717 cnnwin->
priv->dwp_eventsourceid = 0;
3718 return G_SOURCE_REMOVE;
3723 TRACE_CALL(__func__);
3725 gchar *last_success;
3727 g_debug(
"Connect signal emitted");
3728 GDateTime *date = g_date_time_new_now_utc();
3741 last_success = g_strdup_printf(
"%d%02d%02d",
3742 g_date_time_get_year(date),
3743 g_date_time_get_month(date),
3744 g_date_time_get_day_of_month(date));
3749 g_debug(
"Stats are allowed, we save the last successful connection date");
3751 g_debug(
"Last connection was made on %s.", last_success);
3754 g_debug(
"Saving credentials");
3758 if (cnnobj->
cnnwin->
priv->floating_toolbar_widget)
3759 gtk_widget_show(cnnobj->
cnnwin->
priv->floating_toolbar_widget);
3763 g_debug(
"Trying to present the window");
3770 TRACE_CALL(__func__);
3776 TRACE_CALL(__func__);
3781 g_debug(
"Disconnect signal received on RemminaProtocolWidget");
3785 pparent = gtk_widget_get_parent(cnnobj->
proto);
3786 if (pparent != NULL) {
3787 g_object_ref(cnnobj->
proto);
3788 gtk_container_remove(GTK_CONTAINER(pparent), cnnobj->
proto);
3800 gtk_toggle_tool_button_set_active(
3801 GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_grab),
3806 RemminaMessagePanel *mp;
3817 g_debug(
"Could not disconnect");
3820 g_debug(
"Disconnected");
3826 TRACE_CALL(__func__);
3834 TRACE_CALL(__func__);
3841 TRACE_CALL(__func__);
3849 TRACE_CALL(__func__);
3858 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
3859 _(
"The file \"%s\" is corrupted, unreadable, or could not be found."), filename);
3860 g_signal_connect(G_OBJECT(dialog),
"response", G_CALLBACK(gtk_widget_destroy), NULL);
3861 gtk_widget_show(dialog);
3894 TRACE_CALL(__func__);
3900 TRACE_CALL(__func__);
3911 if (disconnect_cb) {
3912 g_print(
"disconnect_cb is deprecated inside rcw_open_from_file_full() and should be null");
3928 dialog = gtk_message_dialog_new(wparent, GTK_DIALOG_DESTROY_WITH_PARENT,
3929 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
"%s", msg);
3930 gtk_dialog_run(GTK_DIALOG(dialog));
3931 gtk_widget_destroy(dialog);
3939 gtk_widget_set_name(GTK_WIDGET(cnnobj->
proto),
"remmina-protocol-widget");
3941 gtk_widget_set_halign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
3942 gtk_widget_set_valign(GTK_WIDGET(cnnobj->
proto), GTK_ALIGN_FILL);
3945 g_object_set_data(G_OBJECT(cnnobj->
proto),
"user-data", data);
3952 cnnobj->
viewport = gtk_viewport_new(NULL, NULL);
3953 gtk_widget_set_name(cnnobj->
viewport,
"remmina-cw-viewport");
3955 gtk_container_set_border_width(GTK_CONTAINER(cnnobj->
viewport), 0);
3956 gtk_viewport_set_shadow_type(GTK_VIEWPORT(cnnobj->
viewport), GTK_SHADOW_NONE);
3970 gtk_container_add(GTK_CONTAINER(cnnobj->
viewport), cnnobj->
proto);
3977 switch (view_mode) {
3994 gtk_window_present(GTK_WINDOW(cnnobj->
cnnwin));
4001 gtk_widget_show(cnnobj->
proto);
4018 dialog = gtk_message_dialog_new(
4019 GTK_WINDOW(cnnobj->
cnnwin),
4021 GTK_MESSAGE_WARNING,
4023 _(
"Warning: This plugin requires GtkSocket, but it’s not available."));
4024 g_signal_connect(G_OBJECT(dialog),
"response", G_CALLBACK(gtk_widget_destroy), NULL);
4025 gtk_widget_show(dialog);
4029 if (cnnobj->
cnnwin->
priv->floating_toolbar_widget)
4030 gtk_widget_show(cnnobj->
cnnwin->
priv->floating_toolbar_widget);
4033 printf(
"OK, an error occurred in initializing the protocol plugin before connecting. The error is %s.\n" 4035 return cnnobj->
proto;
4047 return cnnobj->
proto;
4052 TRACE_CALL(__func__);
4053 cnnwin->
priv->on_delete_confirm_mode = mode;
4062 TRACE_CALL(__func__);
4064 RemminaMessagePanel *lastPanel;
4065 gboolean was_visible;
4069 childs = gtk_container_get_children(GTK_CONTAINER(page));
4070 cc = g_list_first(childs);
4071 while (cc != NULL) {
4072 if ((RemminaMessagePanel *)cc->data == mp)
4074 cc = g_list_next(cc);
4076 g_list_free(childs);
4079 printf(
"Remmina: Warning, request to destroy a RemminaMessagePanel, which is not on the page\n");
4082 was_visible = gtk_widget_is_visible(GTK_WIDGET(mp));
4083 gtk_widget_destroy(GTK_WIDGET(mp));
4087 childs = gtk_container_get_children(GTK_CONTAINER(page));
4088 cc = g_list_first(childs);
4090 while (cc != NULL) {
4091 if (G_TYPE_CHECK_INSTANCE_TYPE(cc->data, REMMINA_TYPE_MESSAGE_PANEL))
4092 lastPanel = (RemminaMessagePanel *)cc->data;
4093 cc = g_list_next(cc);
4095 g_list_free(childs);
4097 gtk_widget_show(GTK_WIDGET(lastPanel));
4109 TRACE_CALL(__func__);
4115 childs = gtk_container_get_children(GTK_CONTAINER(page));
4116 cc = g_list_first(childs);
4117 while (cc != NULL) {
4118 if (G_TYPE_CHECK_INSTANCE_TYPE(cc->data, REMMINA_TYPE_MESSAGE_PANEL))
4119 gtk_widget_hide(GTK_WIDGET(cc->data));
4120 cc = g_list_next(cc);
4122 g_list_free(childs);
4125 gtk_box_pack_start(GTK_BOX(page), GTK_WIDGET(mp), FALSE, FALSE, 0);
4126 gtk_box_reorder_child(GTK_BOX(page), GTK_WIDGET(mp), 0);
4129 gtk_widget_show_all(GTK_WIDGET(mp));
static RemminaConnectionWindow * rcw_find(RemminaFile *remminafile)
guint shortcutkey_fullscreen
static void rco_update_toolbar(RemminaConnectionObject *cnnobj)
gulong deferred_open_size_allocate_handler
gint floating_toolbar_placement
static gboolean rcw_after_configure_scrolled(gpointer user_data)
static void rcw_focus_in(RemminaConnectionWindow *cnnwin)
static void rcw_init(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_screenshot(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static RemminaScaleMode get_current_allowed_scale_mode(RemminaConnectionObject *cnnobj, gboolean *dynres_avail, gboolean *scale_avail)
guint shortcutkey_minimize
static void rcw_toolbar_minimize(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
const gchar * remmina_file_get_string(RemminaFile *remminafile, const gchar *setting)
static void rcw_update_tag(RemminaConnectionWindow *cnnwin, RemminaConnectionObject *cnnobj)
static void rcw_tb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
static void rcw_toolbar_disconnect(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rco_call_protocol_feature_check(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static void rcw_toolbar_preferences_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
gchar * remmina_pref_file
static void rcw_on_switch_page(GtkNotebook *notebook, GtkWidget *newpage, guint page_num, RemminaConnectionWindow *cnnwin)
GtkWindow * remmina_main_get_window()
void rco_set_scrolled_policy(RemminaConnectionObject *cnnobj, GtkScrolledWindow *scrolled_window)
void rcw_toolbar_tools_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static gboolean rcw_hostkey_func(RemminaProtocolWidget *gp, guint keyval, gboolean release)
static void rcw_toolbar_autofit(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void nb_set_current_page(GtkNotebook *notebook, GtkWidget *page)
static gboolean rco_leave_protocol_widget(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionObject *cnnobj)
const gchar * remmina_file_get_filename(RemminaFile *remminafile)
void remmina_public_send_notification(const gchar *notification_id, const gchar *notification_title, const gchar *notification_message)
void rco_on_disconnect(RemminaProtocolWidget *gp, gpointer data)
guint shortcutkey_screenshot
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
guint shortcutkey_prevtab
static RemminaConnectionWindow * rcw_create_scrolled(gint width, gint height, gboolean maximize)
void rco_show_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp)
Each cnnobj->page can have more than one RemminaMessagePanel, but 0 or 1 are visible.
gboolean plugin_can_scale
GtkWidget * rcw_open_from_file_full(RemminaFile *remminafile, GCallback disconnect_cb, gpointer data, guint *handler)
static gboolean rcw_ftb_drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, RemminaConnectionWindow *cnnwin)
static void rcw_focus_out(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_pin(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_destroy(GtkWidget *widget, gpointer data)
static void rcw_toolbar_scaled_mode(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_create_floating_toolbar(RemminaConnectionWindow *cnnwin, gint mode)
void rcw_toolbar_preferences_radio(RemminaConnectionObject *cnnobj, RemminaFile *remminafile, GtkWidget *menu, const RemminaProtocolFeature *feature, const gchar *domain, gboolean enabled)
static void rcw_create_overlay_ftb_overlay(RemminaConnectionWindow *cnnwin)
gboolean rcw_delete(RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_tools(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_dynres(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_toolbar_duplicate(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp)
static void rcw_scaler_keep_aspect(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static gboolean rcw_tb_drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data)
static void rcw_scaler_expand(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rco_call_protocol_feature_radio(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static void rcw_place_toolbar(GtkToolbar *toolbar, GtkGrid *grid, GtkWidget *sibling, int toolbar_placement)
guint shortcutkey_autofit
static GtkWidget * rco_create_tab_label(RemminaConnectionObject *cnnobj)
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...
static void rco_viewport_fullscreen_mode(GtkWidget *widget, RemminaConnectionObject *cnnobj)
static void rcw_update_pin(RemminaConnectionWindow *cnnwin)
void rco_on_connect(RemminaProtocolWidget *gp, RemminaConnectionObject *cnnobj)
static GtkWidget * nb_find_page_by_cnnobj(GtkNotebook *notebook, RemminaConnectionObject *cnnobj)
static gboolean rcw_keyboard_grab_retry(gpointer user_data)
void remmina_pref_add_recent(const gchar *protocol, const gchar *server)
static gboolean rcw_floating_toolbar_hide(RemminaConnectionWindow *cnnwin)
static gboolean rcw_floating_toolbar_on_enter(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionWindow *cnnwin)
static const GtkTargetEntry dnd_targets_tb[]
static void cb_lasterror_confirmed(void *cbdata, int btn)
static void rcw_set_toolbar_visibility(RemminaConnectionWindow *cnnwin)
void rco_switch_page_activate(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static void rcw_migrate(RemminaConnectionWindow *from, RemminaConnectionWindow *to)
static void rco_get_desktop_size(RemminaConnectionObject *cnnobj, gint *width, gint *height)
gchar * remmina_pref_get_value(const gchar *key)
static RemminaConnectionObject * rcw_get_visible_cnnobj(RemminaConnectionWindow *cnnwin)
void remmina_debug(const gchar *fmt,...)
Print a string in the Remmina Debug Windows and in the terminal.
RemminaConnectionWindowOnDeleteConfirmMode
static void rco_check_resize(RemminaConnectionObject *cnnobj)
struct _RemminaConnectionWindowPriv RemminaConnectionWindowPriv
G_DEFINE_TYPE(RemminaConnectionWindow, rcw, GTK_TYPE_WINDOW)
static gboolean rcw_map_event_fullscreen(GtkWidget *widget, GdkEvent *event, gpointer data)
static void remmina_protocol_widget_update_alignment(RemminaConnectionObject *cnnobj)
static gboolean rcw_on_switch_page_finalsel(gpointer user_data)
General utility functions, non-GTK related.
static void rcw_ftb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
const gchar * screenshot_path
static const GtkTargetEntry dnd_targets_ftb[]
static void rpw_size_allocated_on_connection(GtkWidget *w, GdkRectangle *allocation, gpointer user_data)
RemminaProtocolFeatureType type
gboolean rcw_toolbar_autofit_restore(RemminaConnectionWindow *cnnwin)
gboolean remmina_plugin_manager_query_feature_by_type(RemminaPluginType ptype, const gchar *name, RemminaProtocolFeatureType ftype)
static void rcw_on_page_removed(GtkNotebook *notebook, GtkWidget *child, guint page_num, RemminaConnectionWindow *cnnwin)
static RemminaConnectionWindow * rcw_new(gboolean fullscreen, int full_screen_target_monitor)
static gboolean rcw_on_leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
void rcw_set_delete_confirm_mode(RemminaConnectionWindow *cnnwin, RemminaConnectionWindowOnDeleteConfirmMode mode)
void rco_on_update_align(RemminaProtocolWidget *gp, gpointer data)
gboolean rcw_notify_widget_toolbar_placement(GtkWidget *widget, gpointer data)
static void rco_scrolled_fullscreen_mode(GtkWidget *widget, RemminaConnectionObject *cnnobj)
static void rco_disconnect_current_page(RemminaConnectionObject *cnnobj)
void remmina_file_set_int(RemminaFile *remminafile, const gchar *setting, gint value)
guint shortcutkey_disconnect
void remmina_exec_command(RemminaCommandType command, const gchar *data)
gboolean remmina_gtksocket_available()
gboolean small_toolbutton
static void rcw_toolbar_switch_page(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
gboolean toolbar_pin_down
static void rcw_toolbar_place_signal(RemminaConnectionWindow *cnnwin, gpointer data)
static GtkNotebook * rcw_on_notebook_create_window(GtkNotebook *notebook, GtkWidget *page, gint x, gint y, gpointer data)
struct _RemminaConnectionObject RemminaConnectionObject
static void rcw_pointer_grab(RemminaConnectionWindow *cnnwin)
static void rco_call_protocol_feature_activate(GtkMenuItem *menuitem, RemminaConnectionObject *cnnobj)
static guint rcw_signals[LAST_SIGNAL]
static GtkWidget * rco_create_scrolled_container(RemminaConnectionObject *cnnobj, int view_mode)
gboolean periodic_usage_stats_permitted
void remmina_public_popup_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
static void rcw_kp_ungrab(RemminaConnectionWindow *cnnwin)
void rco_closewin(RemminaProtocolWidget *gp)
static gboolean rcw_on_configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
static void rcw_fullscreen_option_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
void rcw_toolbar_preferences_check(RemminaConnectionObject *cnnobj, GtkWidget *menu, const RemminaProtocolFeature *feature, const gchar *domain, gboolean enabled)
static RemminaConnectionWindow * rcw_create_fullscreen(GtkWindow *old, gint view_mode)
static void rcw_toolbar_fullscreen(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static GtkWidget * rcw_create_toolbar(RemminaConnectionWindow *cnnwin, gint mode)
static gboolean open_connection_last_stage(gpointer user_data)
guint shortcutkey_nexttab
static RemminaConnectionObject * rcw_get_cnnobj_at_page(RemminaConnectionWindow *cnnwin, gint npage)
static gboolean rcw_tb_drag_failed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result, gpointer user_data)
static gboolean rcw_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
static void rcw_class_init(RemminaConnectionWindowClass *klass)
void rco_on_unlock_dynres(RemminaProtocolWidget *gp, gpointer data)
static GtkNotebook * rcw_create_notebook(RemminaConnectionWindow *cnnwin)
RemminaConnectionWindowPriv * priv
void rcw_open_from_file(RemminaFile *remminafile)
static void rcw_toolbar_preferences(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_floating_toolbar_show(RemminaConnectionWindow *cnnwin, gboolean show)
GType rcw_get_type(void) G_GNUC_CONST
gint remmina_file_get_int(RemminaFile *remminafile, const gchar *setting, gint default_value)
void rco_on_desktop_resize(RemminaProtocolWidget *gp, gpointer data)
static void nb_migrate_page_content(GtkWidget *frompage, GtkWidget *topage)
guint remmina_utils_string_replace_all(GString *haystack, const gchar *needle, const gchar *replace)
Replaces all occurrences of needle in haystack with replace.
static void rcw_pointer_ungrab(RemminaConnectionWindow *cnnwin)
guint shortcutkey_toolbar
GtkWidget * scrolled_container
RemminaFile * remmina_file
static void rco_change_scalemode(RemminaConnectionObject *cnnobj, gboolean bdyn, gboolean bscale)
static void rcw_toolbar_grab(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_update_notebook(RemminaConnectionWindow *cnnwin)
gboolean remmina_pref_save(void)
void rcw_toolbar_switch_page_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static gboolean rcw_floating_toolbar_make_invisible(gpointer data)
void rcw_toolbar_fullscreen_option(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
const gchar * screenshot_name
static gboolean rcw_floating_toolbar_on_scroll(GtkWidget *widget, GdkEventScroll *event, RemminaConnectionWindow *cnnwin)
gboolean hide_connection_toolbar
void rcw_update_toolbar_opacity(RemminaConnectionWindow *cnnwin)
gboolean rcw_open_from_filename(const gchar *filename)
static void rcw_close_all_connections(RemminaConnectionWindow *cnnwin)
RemminaConnectionWindow * cnnwin
void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data)
void remmina_application_condexit(RemminaCondExitType why)
void rco_update_toolbar_autofit_button(RemminaConnectionObject *cnnobj)
void remmina_file_set_string(RemminaFile *remminafile, const gchar *setting, const gchar *value)
void remmina_file_save(RemminaFile *remminafile)
static GtkWidget * rcw_append_new_page(RemminaConnectionWindow *cnnwin, RemminaConnectionObject *cnnobj)
void rco_get_monitor_geometry(RemminaConnectionObject *cnnobj, GdkRectangle *sz)
RemminaFile * remmina_file_manager_load_file(const gchar *filename)
gboolean rco_enter_protocol_widget(GtkWidget *widget, GdkEventCrossing *event, RemminaConnectionObject *cnnobj)
static GtkWidget * rco_create_tab_page(RemminaConnectionObject *cnnobj)
static gboolean rcw_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
const gchar * remmina_file_get_icon_name(RemminaFile *remminafile)
guint shortcutkey_viewonly
void rco_on_close_button_clicked(GtkButton *button, RemminaConnectionObject *cnnobj)
static void rcw_switch_viewmode(RemminaConnectionWindow *cnnwin, int newmode)
static void rcw_toolbar_scaler_option(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_on_page_added(GtkNotebook *notebook, GtkWidget *child, guint page_num, RemminaConnectionWindow *cnnwin)
gboolean fullscreen_on_auto
void rcw_grab_focus(RemminaConnectionWindow *cnnwin)
RemminaMessagePanel * remmina_message_panel_new()
static void rcw_scaler_option_popdown(GtkWidget *widget, RemminaConnectionWindow *cnnwin)
static void rcw_set_tooltip(GtkWidget *item, const gchar *tip, guint key1, guint key2)
gint fullscreen_toolbar_visibility
gboolean rcw_delayed_window_present(gpointer user_data)
static void rcw_keyboard_grab(RemminaConnectionWindow *cnnwin)