diff options
author | Antenore Gatta <antenore@simbiosi.org> | 2016-03-18 01:43:04 +0300 |
---|---|---|
committer | Antenore Gatta <antenore@simbiosi.org> | 2016-03-18 01:43:04 +0300 |
commit | 860af6bf9b16e831f2cd09e098329d3f5605efe2 (patch) | |
tree | 2e14945dc2c2a1643ac2bfbf602711808606ff17 | |
parent | ac2a205d2ffeb8979c9b0c558eadd4c28943463e (diff) | |
parent | 395bfe8f645e6b4392e66024cf5558161d1ca9b5 (diff) |
Merge pull request #802 from FreeRDP/remmina_screenshot1.2.0.rcgit.11
Remote machine screenshot [feature request] closes #644 and closes #801
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | remmina-plugins-gnome/src/glibsecret_plugin.c | 10 | ||||
-rw-r--r-- | remmina-plugins/nx/nx_plugin.c | 3 | ||||
-rw-r--r-- | remmina-plugins/rdp/rdp_event.c | 3 | ||||
-rw-r--r-- | remmina-plugins/rdp/rdp_plugin.c | 37 | ||||
-rw-r--r-- | remmina-plugins/vnc/vnc_plugin.c | 3 | ||||
-rw-r--r-- | remmina-plugins/xdmcp/xdmcp_plugin.c | 7 | ||||
-rw-r--r-- | remmina/include/remmina/plugin.h | 1 | ||||
-rw-r--r-- | remmina/include/remmina/types.h | 13 | ||||
-rw-r--r-- | remmina/src/remmina_connection_window.c | 828 | ||||
-rw-r--r-- | remmina/src/remmina_file_editor.c | 19 | ||||
-rw-r--r-- | remmina/src/remmina_pref.c | 16 | ||||
-rw-r--r-- | remmina/src/remmina_pref.h | 9 | ||||
-rw-r--r-- | remmina/src/remmina_pref_dialog.c | 11 | ||||
-rw-r--r-- | remmina/src/remmina_pref_dialog.h | 2 | ||||
-rw-r--r-- | remmina/src/remmina_protocol_widget.c | 12 | ||||
-rw-r--r-- | remmina/src/remmina_protocol_widget.h | 2 | ||||
-rw-r--r-- | remmina/src/remmina_public.c | 57 | ||||
-rw-r--r-- | remmina/src/remmina_public.h | 7 | ||||
-rw-r--r-- | remmina/ui/remmina_about.glade | 2 | ||||
-rw-r--r-- | remmina/ui/remmina_preferences.glade | 331 |
22 files changed, 862 insertions, 515 deletions
@@ -13,6 +13,7 @@ Authors of Remmina Project Ben Kohler <bkohler@gmail.com> Christopher Rawlings <chris.rawlings+git@gmail.com> Daniel M. Weeks <dan@danweeks.net> + Daniele Tieghi <notdisclosed> Dmitry Kubatkin <maelnor@gmail.com> dupondje <jean-louis@dupondje.be> Emmanuel Grognet <emmanuel@grognet.fr> @@ -30,6 +31,7 @@ Authors of Remmina Project Kyle Sanderson <kyle.leet@gmail.com> Luca Falavigna <dktrkranz@debian.org> Marc-AndrĂ© Moreau <marcandre.moreau@gmail.com> + Michele Sartori <mik.thrasher@aol.com> Mike Dalessio <mike@csa.net> Mike Gilbert <floppym@gentoo.org> Muflone <muflone@vbsimple.net> diff --git a/CMakeLists.txt b/CMakeLists.txt index 78a8317c2..b7b6c69f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ set(WITH_LIBRARY_VERSIONING "ON") set(REMMINA_VERSION_MAJOR "1") set(REMMINA_VERSION_MINOR "2") set(REMMINA_VERSION_REVISION "0") -set(REMMINA_VERSION_SUFFIX "rcgit.10") +set(REMMINA_VERSION_SUFFIX "rcgit.11") set(REMMINA_VERSION "${REMMINA_VERSION_MAJOR}.${REMMINA_VERSION_MINOR}.${REMMINA_VERSION_REVISION}-${REMMINA_VERSION_SUFFIX}") include(GetGitRevisionDescription) diff --git a/remmina-plugins-gnome/src/glibsecret_plugin.c b/remmina-plugins-gnome/src/glibsecret_plugin.c index 380eea914..35ca27522 100644 --- a/remmina-plugins-gnome/src/glibsecret_plugin.c +++ b/remmina-plugins-gnome/src/glibsecret_plugin.c @@ -62,9 +62,8 @@ static void remmina_plugin_glibsecret_unlock_secret_service() #ifdef LIBSECRET_VERSION_0_18 GError *error = NULL; - GList *l, *ul; + GList *objects, *ul; gchar* lbl; - gint nu; if (secretservice && defaultcollection) { @@ -72,10 +71,9 @@ static void remmina_plugin_glibsecret_unlock_secret_service() { lbl = secret_collection_get_label(defaultcollection); remmina_plugin_service->log_printf("[glibsecret] requesting unlock of the default '%s' collection\n", lbl); - l = NULL; - g_list_append(l, defaultcollection); - nu = secret_service_unlock_sync(secretservice, l, NULL, &ul, &error); - g_list_free(l); + objects = g_list_append(NULL, defaultcollection); + secret_service_unlock_sync(secretservice, objects, NULL, &ul, &error); + g_list_free(objects); g_list_free(ul); } } diff --git a/remmina-plugins/nx/nx_plugin.c b/remmina-plugins/nx/nx_plugin.c index 62eb391ea..0406d96af 100644 --- a/remmina-plugins/nx/nx_plugin.c +++ b/remmina-plugins/nx/nx_plugin.c @@ -799,7 +799,8 @@ static RemminaProtocolPlugin remmina_plugin_nx = remmina_plugin_nx_close_connection, // Plugin close connection remmina_plugin_nx_query_feature, // Query for available features remmina_plugin_nx_call_feature, // Call a feature - NULL // Send a keystroke + NULL, // Send a keystroke + NULL // Screenshot }; G_MODULE_EXPORT gboolean diff --git a/remmina-plugins/rdp/rdp_event.c b/remmina-plugins/rdp/rdp_event.c index 90ab78d6b..39b62e335 100644 --- a/remmina-plugins/rdp/rdp_event.c +++ b/remmina-plugins/rdp/rdp_event.c @@ -1077,6 +1077,3 @@ int remmina_rdp_event_queue_ui(RemminaProtocolWidget* gp, RemminaPluginRdpUiObje pthread_setcanceltype(oldcanceltype, NULL); return rc; } - - - diff --git a/remmina-plugins/rdp/rdp_plugin.c b/remmina-plugins/rdp/rdp_plugin.c index 848fd4835..82ef9435b 100644 --- a/remmina-plugins/rdp/rdp_plugin.c +++ b/remmina-plugins/rdp/rdp_plugin.c @@ -1230,6 +1230,40 @@ static void remmina_rdp_keystroke(RemminaProtocolWidget *gp, const guint keystro return; } +static gboolean remmina_rdp_get_screenshot(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd) +{ + rfContext* rfi = GET_PLUGIN_DATA(gp); + rdpGdi* gdi; + size_t szmem; + + if (!rfi) + return FALSE; + + /* ToDo: we should lock freerdp subthread to update rfi->primary_buffer, rfi->gdi and w/h, + * from here to memcpy, but... how ? */ + + gdi = ((rdpContext *)rfi)->gdi; + + szmem = gdi->width * gdi->height * rfi->hdc->bytesPerPixel; + remmina_plugin_service->log_printf("[RDP] allocating %zu bytes for a full screenshot\n", szmem); + rpsd->buffer = malloc(szmem); + if (!rpsd->buffer) + { + remmina_plugin_service->log_printf("[RDP] unable to allocate %zu bytes for a full screenshot\n", szmem); + return FALSE; + } + rpsd->width = gdi->width; + rpsd->height = gdi->height; + rpsd->bitsPerPixel = rfi->hdc->bitsPerPixel; + rpsd->bytesPerPixel = rfi->hdc->bytesPerPixel; + + memcpy(rpsd->buffer, rfi->primary_buffer, szmem); + + /* Returning TRUE instruct also the caller to deallocate rpsd->buffer */ + return TRUE; + +} + /* Array of key/value pairs for color depths */ static gpointer colordepth_list[] = { @@ -1355,7 +1389,8 @@ static RemminaProtocolPlugin remmina_rdp = remmina_rdp_close_connection, // Plugin close connection remmina_rdp_query_feature, // Query for available features remmina_rdp_call_feature, // Call a feature - remmina_rdp_keystroke // Send a keystroke + remmina_rdp_keystroke, // Send a keystroke + remmina_rdp_get_screenshot // Screenshot }; /* File plugin definition and features */ diff --git a/remmina-plugins/vnc/vnc_plugin.c b/remmina-plugins/vnc/vnc_plugin.c index 2001285b1..c6a903d7d 100644 --- a/remmina-plugins/vnc/vnc_plugin.c +++ b/remmina-plugins/vnc/vnc_plugin.c @@ -2088,7 +2088,8 @@ static RemminaProtocolPlugin remmina_plugin_vnci = remmina_plugin_vnc_close_connection, // Plugin close connection remmina_plugin_vnc_query_feature, // Query for available features remmina_plugin_vnc_call_feature, // Call a feature - remmina_plugin_vnc_keystroke // Send a keystroke + remmina_plugin_vnc_keystroke, // Send a keystroke + NULL // No screenshot support available }; G_MODULE_EXPORT gboolean diff --git a/remmina-plugins/xdmcp/xdmcp_plugin.c b/remmina-plugins/xdmcp/xdmcp_plugin.c index 3cb7a77a7..58c824894 100644 --- a/remmina-plugins/xdmcp/xdmcp_plugin.c +++ b/remmina-plugins/xdmcp/xdmcp_plugin.c @@ -1,6 +1,6 @@ /* * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2010 Vic Lee + * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo * * This program is free software; you can redistribute it and/or modify @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * In addition, as a special exception, the copyright holders give @@ -422,7 +422,8 @@ static RemminaProtocolPlugin remmina_plugin_xdmcp = remmina_plugin_xdmcp_close_connection, // Plugin close connection remmina_plugin_xdmcp_query_feature, // Query for available features remmina_plugin_xdmcp_call_feature, // Call a feature - NULL // Send a keystroke + NULL, // Send a keystroke + NULL // Screenshot }; G_MODULE_EXPORT gboolean diff --git a/remmina/include/remmina/plugin.h b/remmina/include/remmina/plugin.h index 27a056eef..4afe35415 100644 --- a/remmina/include/remmina/plugin.h +++ b/remmina/include/remmina/plugin.h @@ -81,6 +81,7 @@ typedef struct _RemminaProtocolPlugin gboolean (* query_feature) (RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature); void (* call_feature) (RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature); void (* send_keystrokes) (RemminaProtocolWidget *gp, const guint keystrokes[], const gint keylen); + gboolean (* get_plugin_screenshot)(RemminaProtocolWidget *gp, RemminaPluginScreenshotData *rpsd); } RemminaProtocolPlugin; typedef struct _RemminaEntryPlugin diff --git a/remmina/include/remmina/types.h b/remmina/include/remmina/types.h index cf5541ca2..13bc09624 100644 --- a/remmina/include/remmina/types.h +++ b/remmina/include/remmina/types.h @@ -1,6 +1,6 @@ /* * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2010 Vic Lee + * Copyright (C) 2010 Vic Lee * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo * * This program is free software; you can redistribute it and/or modify @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * In addition, as a special exception, the copyright holders give @@ -61,6 +61,15 @@ typedef struct _RemminaProtocolFeature gpointer opt3; } RemminaProtocolFeature; +typedef struct _RemminaPluginScreenshotData { + unsigned char* buffer; + int bitsPerPixel; + int bytesPerPixel; + int width; + int height; +} RemminaPluginScreenshotData; + + typedef struct _RemminaProtocolWidgetClass RemminaProtocolWidgetClass; typedef struct _RemminaProtocolWidget RemminaProtocolWidget; typedef gpointer RemminaTunnelInitFunc; diff --git a/remmina/src/remmina_connection_window.c b/remmina/src/remmina_connection_window.c index d5aa70501..9d9e9cd65 100644 --- a/remmina/src/remmina_connection_window.c +++ b/remmina/src/remmina_connection_window.c @@ -35,11 +35,14 @@ #include "config.h" -#include <gtk/gtk.h> -#include <gdk/gdkkeysyms.h> -#include <glib/gi18n.h> #include <stdlib.h> +#include <cairo/cairo-xlib.h> +#include <glib/gi18n.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + #include "remmina_connection_window.h" #include "remmina_file.h" #include "remmina_file_manager.h" @@ -51,6 +54,7 @@ #include "remmina_public.h" #include "remmina_scrolled_viewport.h" #include "remmina_widget_pool.h" +#include "remmina_log.h" #include "remmina/remmina_trace_calls.h" G_DEFINE_TYPE( RemminaConnectionWindow, remmina_connection_window, GTK_TYPE_WINDOW) @@ -59,9 +63,9 @@ G_DEFINE_TYPE( RemminaConnectionWindow, remmina_connection_window, GTK_TYPE_WIND #define FLOATING_TOOLBAR_WIDGET (GTK_CHECK_VERSION(3, 10, 0)) -typedef struct _RemminaConnectionHolder RemminaConnectionHolder; + typedef struct _RemminaConnectionHolder RemminaConnectionHolder; -struct _RemminaConnectionWindowPriv + struct _RemminaConnectionWindowPriv { RemminaConnectionHolder* cnnhld; @@ -99,6 +103,7 @@ struct _RemminaConnectionWindowPriv GtkToolItem* toolitem_grab; GtkToolItem* toolitem_preferences; GtkToolItem* toolitem_tools; + GtkToolItem* toolitem_screenshot; GtkWidget* fullscreen_option_button; GtkWidget* fullscreen_scaler_button; GtkWidget* scaler_option_button; @@ -154,22 +159,22 @@ static guint remmina_connection_window_signals[LAST_SIGNAL] = { 0 }; #define DECLARE_CNNOBJ \ - if (!cnnhld || !cnnhld->cnnwin || gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) < 0) return; \ - RemminaConnectionObject* cnnobj = (RemminaConnectionObject*) g_object_get_data ( \ - G_OBJECT(gtk_notebook_get_nth_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), \ - gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)))), "cnnobj"); + if (!cnnhld || !cnnhld->cnnwin || gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) < 0) return; \ +RemminaConnectionObject* cnnobj = (RemminaConnectionObject*) g_object_get_data ( \ + G_OBJECT(gtk_notebook_get_nth_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), \ + gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)))), "cnnobj"); #define DECLARE_CNNOBJ_WITH_RETURN(r) \ - if (!cnnhld || !cnnhld->cnnwin || gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) < 0) return r; \ - RemminaConnectionObject* cnnobj = (RemminaConnectionObject*) g_object_get_data ( \ - G_OBJECT(gtk_notebook_get_nth_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), \ - gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)))), "cnnobj"); + if (!cnnhld || !cnnhld->cnnwin || gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) < 0) return r; \ +RemminaConnectionObject* cnnobj = (RemminaConnectionObject*) g_object_get_data ( \ + G_OBJECT(gtk_notebook_get_nth_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), \ + gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)))), "cnnobj"); static void remmina_connection_holder_create_scrolled(RemminaConnectionHolder* cnnhld, RemminaConnectionObject* cnnobj); static void remmina_connection_holder_create_fullscreen(RemminaConnectionHolder* cnnhld, RemminaConnectionObject* cnnobj, - gint view_mode); + gint view_mode); static gboolean remmina_connection_window_hostkey_func(RemminaProtocolWidget* gp, guint keyval, gboolean release, - RemminaConnectionHolder* cnnhld); + RemminaConnectionHolder* cnnhld); static void remmina_connection_holder_grab_focus(GtkNotebook *notebook); static GtkWidget* remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint mode); @@ -209,70 +214,70 @@ static void remmina_connection_window_class_init(RemminaConnectionWindowClass* k * we will never know its internal area size, because GtkViweport::viewport_get_view_allocation, * which returns the internal size of the GtkViewport, is private and we cannot access it */ gtk_css_provider_load_from_data (provider, - "GtkViewport, GtkAspectFrame {\n" - " padding:0;\n" - " border:0;\n" - " background-color: black;\n" - "}\n" - "GtkDrawingArea {\n" - " background-color: black;\n" - "}\n" - "GtkToolbar {\n" - " -GtkWidget-window-dragging: 0;\n" - "}\n" - "#remmina-connection-window-fullscreen {\n" - " background-color: black;\n" - "}\n" - "#remmina-small-button {\n" - " -GtkWidget-focus-padding: 0;\n" - " -GtkWidget-focus-line-width: 0;\n" - " padding: 0;\n" - " border: 0;\n" - "}\n" - "#remmina-pin-button {\n" - " -GtkWidget-focus-padding: 0;\n" - " -GtkWidget-focus-line-width: 0;\n" - " padding: 2px;\n" - " border: 0;\n" - "}\n" - "#remmina-scrolled-container {\n" - " background-color: black;\n" - "}\n" - "#remmina-scrolled-container.undershoot {\n" - " background: none\n" - "}\n" - "#ftbbox-upper {\n" - " border-style: none solid solid solid;\n" - " border-width: 1px;\n" - " border-radius: 4px;\n" - " border-color: #808080;\n" - " padding: 0px;\n" - " background-color: #f0f0f0;\n" - "}\n" - "#ftbbox-lower {\n" - " border-style: solid solid none solid;\n" - " border-width: 1px;\n" - " border-radius: 4px;\n" - " border-color: #808080;\n" - " padding: 0px;\n" - " background-color: #f0f0f0;\n" - "}\n" - "#ftb-handle {\n" - " background-color: #f0f0f0;\n" - "}\n" - - ,-1, NULL); + "GtkViewport, GtkAspectFrame {\n" + " padding:0;\n" + " border:0;\n" + " background-color: black;\n" + "}\n" + "GtkDrawingArea {\n" + " background-color: black;\n" + "}\n" + "GtkToolbar {\n" + " -GtkWidget-window-dragging: 0;\n" + "}\n" + "#remmina-connection-window-fullscreen {\n" + " background-color: black;\n" + "}\n" + "#remmina-small-button {\n" + " -GtkWidget-focus-padding: 0;\n" + " -GtkWidget-focus-line-width: 0;\n" + " padding: 0;\n" + " border: 0;\n" + "}\n" + "#remmina-pin-button {\n" + " -GtkWidget-focus-padding: 0;\n" + " -GtkWidget-focus-line-width: 0;\n" + " padding: 2px;\n" + " border: 0;\n" + "}\n" + "#remmina-scrolled-container {\n" + " background-color: black;\n" + "}\n" + "#remmina-scrolled-container.undershoot {\n" + " background: none\n" + "}\n" + "#ftbbox-upper {\n" + " border-style: none solid solid solid;\n" + " border-width: 1px;\n" + " border-radius: 4px;\n" + " border-color: #808080;\n" + " padding: 0px;\n" + " background-color: #f0f0f0;\n" + "}\n" + "#ftbbox-lower {\n" + " border-style: solid solid none solid;\n" + " border-width: 1px;\n" + " border-radius: 4px;\n" + " border-color: #808080;\n" + " padding: 0px;\n" + " background-color: #f0f0f0;\n" + "}\n" + "#ftb-handle {\n" + " background-color: #f0f0f0;\n" + "}\n" + + ,-1, NULL); gtk_style_context_add_provider_for_screen (gdk_screen_get_default(), - GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); g_object_unref(provider); /* Define a signal used to notify all remmina_connection_windows of toolbar move */ remmina_connection_window_signals[TOOLBARPLACE_SIGNAL] = g_signal_new("toolbar-place", G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(RemminaConnectionWindowClass, toolbar_place), NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(RemminaConnectionWindowClass, toolbar_place), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } @@ -355,8 +360,8 @@ void remmina_connection_window_delete(RemminaConnectionWindow* cnnwin) if (n > 1) { dialog = gtk_message_dialog_new(GTK_WINDOW(cnnwin), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - _("There are %i active connections in the current window. Are you sure to close?"), n); + GTK_BUTTONS_YES_NO, + _("There are %i active connections in the current window. Are you sure to close?"), n); i = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (i != GTK_RESPONSE_YES) @@ -439,7 +444,7 @@ gboolean remmina_connection_window_notify_widget_toolbar_placement(GtkWidget *wi } static gboolean remmina_connection_window_tb_drag_failed(GtkWidget *widget, GdkDragContext *context, - GtkDragResult result, gpointer user_data) + GtkDragResult result, gpointer user_data) { TRACE_CALL("remmina_connection_window_tb_drag_failed"); RemminaConnectionHolder* cnnhld; @@ -455,7 +460,7 @@ static gboolean remmina_connection_window_tb_drag_failed(GtkWidget *widget, GdkD } static gboolean remmina_connection_window_tb_drag_drop(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint time, gpointer user_data) + gint x, gint y, guint time, gpointer user_data) { TRACE_CALL("remmina_connection_window_tb_drag_drop"); GtkAllocation wa; @@ -539,8 +544,8 @@ static void remmina_connection_holder_update_toolbar_opacity(RemminaConnectionHo RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv; priv->floating_toolbar_opacity = (1.0 - TOOLBAR_OPACITY_MIN) / ((gdouble) TOOLBAR_OPACITY_LEVEL) - * ((gdouble)(TOOLBAR_OPACITY_LEVEL - remmina_file_get_int(cnnobj->remmina_file, "toolbar_opacity", 0))) - + TOOLBAR_OPACITY_MIN; + * ((gdouble)(TOOLBAR_OPACITY_LEVEL - remmina_file_get_int(cnnobj->remmina_file, "toolbar_opacity", 0))) + + TOOLBAR_OPACITY_MIN; #if FLOATING_TOOLBAR_WIDGET if (priv->floating_toolbar_widget) { @@ -598,10 +603,10 @@ static gboolean remmina_connection_holder_floating_toolbar_motion(RemminaConnect { #if GTK_CHECK_VERSION(3, 8, 0) gtk_widget_set_opacity(GTK_WIDGET(priv->floating_toolbar_window), - (gdouble)(y - t) / (gdouble)(-t) * priv->floating_toolbar_opacity); + (gdouble)(y - t) / (gdouble)(-t) * priv->floating_toolbar_opacity); #else gtk_window_set_opacity(GTK_WINDOW(priv->floating_toolbar_window), - (gdouble)(y - t) / (gdouble)(-t) * priv->floating_toolbar_opacity); + (gdouble)(y - t) / (gdouble)(-t) * priv->floating_toolbar_opacity); #endif } if ((priv->floating_toolbar_motion_show && y >= 0) || (!priv->floating_toolbar_motion_show && y <= t)) @@ -629,14 +634,14 @@ static void remmina_connection_holder_floating_toolbar_update(RemminaConnectionH if (priv->floating_toolbar_motion_handler) g_source_remove(priv->floating_toolbar_motion_handler); priv->floating_toolbar_motion_handler = g_idle_add( - (GSourceFunc) remmina_connection_holder_floating_toolbar_motion, cnnhld); + (GSourceFunc) remmina_connection_holder_floating_toolbar_motion, cnnhld); } else { if (priv->floating_toolbar_motion_handler == 0) { priv->floating_toolbar_motion_handler = g_timeout_add(MOTION_TIME, - (GSourceFunc) remmina_connection_holder_floating_toolbar_motion, cnnhld); + (GSourceFunc) remmina_connection_holder_floating_toolbar_motion, cnnhld); } } } @@ -728,7 +733,7 @@ static void remmina_connection_object_set_scrolled_policy(RemminaConnectionObjec gboolean scale; scale = remmina_protocol_widget_get_scale(REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); gtk_scrolled_window_set_policy(scrolled_window, scale ? GTK_POLICY_NEVER : GTK_POLICY_AUTOMATIC, - scale ? GTK_POLICY_NEVER : GTK_POLICY_AUTOMATIC); + scale ? GTK_POLICY_NEVER : GTK_POLICY_AUTOMATIC); } static gboolean remmina_connection_holder_toolbar_autofit_restore(RemminaConnectionHolder* cnnhld) @@ -746,15 +751,15 @@ static gboolean remmina_connection_holder_toolbar_autofit_restore(RemminaConnect gtk_widget_get_allocation(cnnobj->scrolled_container, &ca); gtk_widget_get_allocation(priv->toolbar, &ta); if (remmina_pref.toolbar_placement == TOOLBAR_PLACEMENT_LEFT || - remmina_pref.toolbar_placement == TOOLBAR_PLACEMENT_RIGHT) + remmina_pref.toolbar_placement == TOOLBAR_PLACEMENT_RIGHT) { gtk_window_resize(GTK_WINDOW(cnnhld->cnnwin), MAX(1, dwidth + ta.width + nba.width - ca.width), - MAX(1, dheight + nba.height - ca.height)); + MAX(1, dheight + nba.height - ca.height)); } else { gtk_window_resize(GTK_WINDOW(cnnhld->cnnwin), MAX(1, dwidth + nba.width - ca.width), - MAX(1, dheight + ta.height + nba.height - ca.height)); + MAX(1, dheight + ta.height + nba.height - ca.height)); } gtk_container_check_resize(GTK_CONTAINER(cnnhld->cnnwin)); } @@ -770,21 +775,21 @@ static void remmina_connection_holder_toolbar_autofit(GtkWidget* widget, Remmina TRACE_CALL("remmina_connection_holder_toolbar_autofit"); DECLARE_CNNOBJ - if (GTK_IS_SCROLLED_WINDOW(cnnobj->scrolled_container)) - { - if ((gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) != 0) + if (GTK_IS_SCROLLED_WINDOW(cnnobj->scrolled_container)) { - gtk_window_unmaximize(GTK_WINDOW(cnnhld->cnnwin)); - } + if ((gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) != 0) + { + gtk_window_unmaximize(GTK_WINDOW(cnnhld->cnnwin)); + } - /* It's tricky to make the toolbars disappear automatically, while keeping scrollable. - Please tell me if you know a better way to do this */ - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cnnobj->scrolled_container), GTK_POLICY_NEVER, - GTK_POLICY_NEVER); + /* It's tricky to make the toolbars disappear automatically, while keeping scrollable. + Please tell me if you know a better way to do this */ + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cnnobj->scrolled_container), GTK_POLICY_NEVER, + GTK_POLICY_NEVER); - /* ToDo: save returned source id in priv->something and then delete when main object is destroyed */ - g_timeout_add(200, (GSourceFunc) remmina_connection_holder_toolbar_autofit_restore, cnnhld); - } + /* ToDo: save returned source id in priv->something and then delete when main object is destroyed */ + g_timeout_add(200, (GSourceFunc) remmina_connection_holder_toolbar_autofit_restore, cnnhld); + } } @@ -813,60 +818,60 @@ static void remmina_connection_holder_check_resize(RemminaConnectionHolder* cnnh screen_height = screen_size.height; if (!remmina_protocol_widget_get_expand(REMMINA_PROTOCOL_WIDGET(cnnobj->proto)) - && (server_width <= 0 || server_height <= 0 || screen_width < server_width - || screen_height < server_height)) + && (server_width <= 0 || server_height <= 0 || screen_width < server_width + || screen_height < server_height)) { scroll_required = TRUE; } switch (cnnhld->cnnwin->priv->view_mode) { - case SCROLLED_FULLSCREEN_MODE: - gtk_window_resize(GTK_WINDOW(cnnhld->cnnwin), screen_width, screen_height); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cnnobj->scrolled_container), - (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER), - (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER)); - break; - - case VIEWPORT_FULLSCREEN_MODE: - bordersz = scroll_required ? 1 : 0; - gtk_window_resize (GTK_WINDOW(cnnhld->cnnwin), screen_width , screen_height); - if (REMMINA_IS_SCROLLED_VIEWPORT(cnnobj->scrolled_container)) - { - /* Put a border around Notebook content (RemminaScrolledViewpord), so we can - * move the mouse over the border to scroll */ - gtk_container_set_border_width (GTK_CONTAINER (cnnobj->scrolled_container), bordersz); - } - - break; + case SCROLLED_FULLSCREEN_MODE: + gtk_window_resize(GTK_WINDOW(cnnhld->cnnwin), screen_width, screen_height); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cnnobj->scrolled_container), + (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER), + (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER)); + break; - case SCROLLED_WINDOW_MODE: - if (remmina_file_get_int (cnnobj->remmina_file, "viewmode", AUTO_MODE) == AUTO_MODE) - { - gtk_window_set_default_size (GTK_WINDOW(cnnhld->cnnwin), - MIN (server_width, screen_width), MIN (server_height, screen_height)); - if (server_width >= screen_width || server_height >= screen_height) + case VIEWPORT_FULLSCREEN_MODE: + bordersz = scroll_required ? 1 : 0; + gtk_window_resize (GTK_WINDOW(cnnhld->cnnwin), screen_width , screen_height); + if (REMMINA_IS_SCROLLED_VIEWPORT(cnnobj->scrolled_container)) { - gtk_window_maximize (GTK_WINDOW(cnnhld->cnnwin)); - remmina_file_set_int (cnnobj->remmina_file, "window_maximize", TRUE); + /* Put a border around Notebook content (RemminaScrolledViewpord), so we can + * move the mouse over the border to scroll */ + gtk_container_set_border_width (GTK_CONTAINER (cnnobj->scrolled_container), bordersz); } - else + + break; + + case SCROLLED_WINDOW_MODE: + if (remmina_file_get_int (cnnobj->remmina_file, "viewmode", AUTO_MODE) == AUTO_MODE) { - remmina_connection_holder_toolbar_autofit (NULL, cnnhld); - remmina_file_set_int (cnnobj->remmina_file, "window_maximize", FALSE); + gtk_window_set_default_size (GTK_WINDOW(cnnhld->cnnwin), + MIN (server_width, screen_width), MIN (server_height, screen_height)); + if (server_width >= screen_width || server_height >= screen_height) + { + gtk_window_maximize (GTK_WINDOW(cnnhld->cnnwin)); + remmina_file_set_int (cnnobj->remmina_file, "window_maximize", TRUE); + } + else + { + remmina_connection_holder_toolbar_autofit (NULL, cnnhld); + remmina_file_set_int (cnnobj->remmina_file, "window_maximize", FALSE); + } } - } - else - { - if (remmina_file_get_int (cnnobj->remmina_file, "window_maximize", FALSE)) + else { - gtk_window_maximize (GTK_WINDOW(cnnhld->cnnwin)); + if (remmina_file_get_int (cnnobj->remmina_file, "window_maximize", FALSE)) + { + gtk_window_maximize (GTK_WINDOW(cnnhld->cnnwin)); + } } - } - break; + break; - default: - break; + default: + break; } } @@ -881,7 +886,7 @@ static void remmina_connection_holder_set_tooltip(GtkWidget* item, const gchar* if (key2) { s1 = g_strdup_printf(" (%s + %s,%s)", gdk_keyval_name(remmina_pref.hostkey), - gdk_keyval_name(gdk_keyval_to_upper(key1)), gdk_keyval_name(gdk_keyval_to_upper(key2))); + gdk_keyval_name(gdk_keyval_to_upper(key1)), gdk_keyval_name(gdk_keyval_to_upper(key2))); } else if (key1 == remmina_pref.hostkey) { @@ -890,7 +895,7 @@ static void remmina_connection_holder_set_tooltip(GtkWidget* item, const gchar* else { s1 = g_strdup_printf(" (%s + %s)", gdk_keyval_name(remmina_pref.hostkey), - gdk_keyval_name(gdk_keyval_to_upper(key1))); + gdk_keyval_name(gdk_keyval_to_upper(key1))); } } else @@ -1068,7 +1073,7 @@ static void remmina_connection_holder_toolbar_fullscreen_option(GtkWidget* widge g_signal_connect(G_OBJECT(menu), "deactivate", G_CALLBACK(remmina_connection_holder_fullscreen_option_popdown), cnnhld); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, remmina_public_popup_position, priv->toolitem_fullscreen, 0, - gtk_get_current_event_time()); + gtk_get_current_event_time()); } @@ -1143,7 +1148,7 @@ static void remmina_connection_holder_toolbar_scaler_option(GtkWidget* widget, R g_signal_connect(G_OBJECT(menu), "deactivate", G_CALLBACK(remmina_connection_holder_scaler_option_popdown), cnnhld); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, remmina_public_popup_position, priv->toolitem_fullscreen, 0, - gtk_get_current_event_time()); + gtk_get_current_event_time()); } static void remmina_connection_holder_switch_page_activate(GtkMenuItem* menuitem, RemminaConnectionHolder* cnnhld) @@ -1202,7 +1207,7 @@ static void remmina_connection_holder_toolbar_switch_page(GtkWidget* widget, Rem g_object_set_data(G_OBJECT(menuitem), "new-page-num", GINT_TO_POINTER(i)); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(remmina_connection_holder_switch_page_activate), - cnnhld); + cnnhld); if (i == gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook))) { gtk_widget_set_sensitive(menuitem, FALSE); @@ -1210,7 +1215,7 @@ static void remmina_connection_holder_toolbar_switch_page(GtkWidget* widget, Rem } g_signal_connect(G_OBJECT(menu), "deactivate", G_CALLBACK(remmina_connection_holder_toolbar_switch_page_popdown), - cnnhld); + cnnhld); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, remmina_public_popup_position, widget, 0, gtk_get_current_event_time()); } @@ -1252,7 +1257,7 @@ static void remmina_connection_holder_toolbar_scaled_mode(GtkWidget* widget, Rem gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), scale); remmina_protocol_widget_call_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - REMMINA_PROTOCOL_FEATURE_TYPE_SCALE, 0); + REMMINA_PROTOCOL_FEATURE_TYPE_SCALE, 0); if (cnnhld->cnnwin->priv->view_mode != SCROLLED_WINDOW_MODE) { remmina_connection_holder_check_resize(cnnhld); @@ -1334,7 +1339,7 @@ static void remmina_connection_holder_call_protocol_feature_activate(GtkMenuItem } static void remmina_connection_holder_toolbar_preferences_radio(RemminaConnectionHolder* cnnhld, RemminaFile* remminafile, - GtkWidget* menu, const RemminaProtocolFeature* feature, const gchar* domain, gboolean enabled) + GtkWidget* menu, const RemminaProtocolFeature* feature, const gchar* domain, gboolean enabled) { TRACE_CALL("remmina_connection_holder_toolbar_preferences_radio"); GtkWidget* menuitem; @@ -1364,7 +1369,7 @@ static void remmina_connection_holder_toolbar_preferences_radio(RemminaConnectio } g_signal_connect(G_OBJECT(menuitem), "toggled", - G_CALLBACK(remmina_connection_holder_call_protocol_feature_radio), cnnhld); + G_CALLBACK(remmina_connection_holder_call_protocol_feature_radio), cnnhld); } else { @@ -1374,7 +1379,7 @@ static void remmina_connection_holder_toolbar_preferences_radio(RemminaConnectio } static void remmina_connection_holder_toolbar_preferences_check(RemminaConnectionHolder* cnnhld, RemminaFile* remminafile, - GtkWidget* menu, const RemminaProtocolFeature* feature, const gchar* domain, gboolean enabled) + GtkWidget* menu, const RemminaProtocolFeature* feature, const gchar* domain, gboolean enabled) { TRACE_CALL("remmina_connection_holder_toolbar_preferences_check"); GtkWidget* menuitem; @@ -1388,10 +1393,10 @@ static void remmina_connection_holder_toolbar_preferences_check(RemminaConnectio g_object_set_data(G_OBJECT(menuitem), "feature-type", (gpointer) feature); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), - remmina_file_get_int(remminafile, (const gchar*) feature->opt2, FALSE)); + remmina_file_get_int(remminafile, (const gchar*) feature->opt2, FALSE)); g_signal_connect(G_OBJECT(menuitem), "toggled", - G_CALLBACK(remmina_connection_holder_call_protocol_feature_check), cnnhld); + G_CALLBACK(remmina_connection_holder_call_protocol_feature_check), cnnhld); } else { @@ -1421,7 +1426,7 @@ static void remmina_connection_holder_toolbar_preferences(GtkWidget* widget, Rem domain = remmina_protocol_widget_get_domain(REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); menu = gtk_menu_new(); for (feature = remmina_protocol_widget_get_features(REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); feature && feature->type; - feature++) + feature++) { if (feature->type != REMMINA_PROTOCOL_FEATURE_TYPE_PREF) continue; @@ -1436,20 +1441,20 @@ static void remmina_connection_holder_toolbar_preferences(GtkWidget* widget, Rem enabled = remmina_protocol_widget_query_feature_by_ref(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), feature); switch (GPOINTER_TO_INT(feature->opt1)) { - case REMMINA_PROTOCOL_FEATURE_PREF_RADIO: - remmina_connection_holder_toolbar_preferences_radio(cnnhld, cnnobj->remmina_file, menu, feature, - domain, enabled); - separator = TRUE; - break; - case REMMINA_PROTOCOL_FEATURE_PREF_CHECK: - remmina_connection_holder_toolbar_preferences_check(cnnhld, cnnobj->remmina_file, menu, feature, - domain, enabled); - break; + case REMMINA_PROTOCOL_FEATURE_PREF_RADIO: + remmina_connection_holder_toolbar_preferences_radio(cnnhld, cnnobj->remmina_file, menu, feature, + domain, enabled); + separator = TRUE; + break; + case REMMINA_PROTOCOL_FEATURE_PREF_CHECK: + remmina_connection_holder_toolbar_preferences_check(cnnhld, cnnobj->remmina_file, menu, feature, + domain, enabled); + break; } } g_signal_connect(G_OBJECT(menu), "deactivate", G_CALLBACK(remmina_connection_holder_toolbar_preferences_popdown), - cnnhld); + cnnhld); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, remmina_public_popup_position, widget, 0, gtk_get_current_event_time()); } @@ -1477,7 +1482,7 @@ static void remmina_connection_holder_toolbar_tools(GtkWidget* widget, RemminaCo domain = remmina_protocol_widget_get_domain(REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); menu = gtk_menu_new(); for (feature = remmina_protocol_widget_get_features(REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); feature && feature->type; - feature++) + feature++) { if (feature->type != REMMINA_PROTOCOL_FEATURE_TYPE_TOOL) continue; @@ -1499,7 +1504,7 @@ static void remmina_connection_holder_toolbar_tools(GtkWidget* widget, RemminaCo g_object_set_data(G_OBJECT(menuitem), "feature-type", (gpointer) feature); g_signal_connect(G_OBJECT(menuitem), "activate", - G_CALLBACK(remmina_connection_holder_call_protocol_feature_activate), cnnhld); + G_CALLBACK(remmina_connection_holder_call_protocol_feature_activate), cnnhld); } else { @@ -1530,11 +1535,11 @@ static void remmina_connection_holder_toolbar_tools(GtkWidget* widget, RemminaCo { /* Add the keystroke if no description was available */ menuitem = gtk_menu_item_new_with_label( - g_strdup(keystroke_values[strlen(keystroke_values[0]) ? 0 : 1])); + g_strdup(keystroke_values[strlen(keystroke_values[0]) ? 0 : 1])); g_object_set_data(G_OBJECT(menuitem), "keystrokes", g_strdup(keystroke_values[1])); g_signal_connect_swapped(G_OBJECT(menuitem), "activate", - G_CALLBACK(remmina_protocol_widget_send_keystrokes), - REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); + G_CALLBACK(remmina_protocol_widget_send_keystrokes), + REMMINA_PROTOCOL_WIDGET(cnnobj->proto)); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(submenu_keystrokes), menuitem); } @@ -1547,6 +1552,123 @@ static void remmina_connection_holder_toolbar_tools(GtkWidget* widget, RemminaCo gtk_menu_popup(GTK_MENU(menu), NULL, NULL, remmina_public_popup_position, widget, 0, gtk_get_current_event_time()); } +static void remmina_connection_holder_toolbar_screenshot(GtkWidget* widget, RemminaConnectionHolder* cnnhld) +{ + TRACE_CALL("remmina_connection_holder_toolbar_screenshot"); + + GdkPixbuf *screenshot; + GdkWindow *active_window; + cairo_t *cr; + gint width, height; + const gchar* remminafile; + gchar* pngname; + gchar* pngdate; + GtkWidget* dialog; + RemminaProtocolWidget *gp; + RemminaPluginScreenshotData rpsd; + cairo_surface_t *srcsurface; + cairo_format_t cairo_format; + cairo_surface_t *surface; + int stride; + + GDateTime *date = g_date_time_new_now_utc (); + + // We will take a screenshot of the currently displayed RemminaProtocolWidget. + // DECLARE_CNNOBJ already did part of the job for us. + DECLARE_CNNOBJ + gp = REMMINA_PROTOCOL_WIDGET(cnnobj->proto); + + // Ask the plugin if it can give us a screenshot + if (remmina_protocol_widget_plugin_screenshot(gp, &rpsd)) { + // Good, we have a screenshot from the plugin ! + + remmina_log_printf("Screenshot from plugin: w=%d h=%d bpp=%d bytespp=%d\n", + rpsd.width, rpsd.height, rpsd.bitsPerPixel, rpsd.bytesPerPixel); + + width = rpsd.width; + height = rpsd.height; + + if (rpsd.bitsPerPixel == 32) + cairo_format = CAIRO_FORMAT_ARGB32; + else + cairo_format = CAIRO_FORMAT_RGB16_565; + + stride = cairo_format_stride_for_width(cairo_format, width); + + srcsurface = cairo_image_surface_create_for_data(rpsd.buffer, cairo_format, width, height, stride); + + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); + cr = cairo_create(surface); + cairo_set_source_surface(cr, srcsurface, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_surface_destroy(srcsurface); + + free(rpsd.buffer); + + } else { + // The plugin is not releasing us a screenshot, just try to catch one via GTK + + /* Warn the user if image is distorted */ + if (cnnobj->plugin_can_scale && + remmina_protocol_widget_get_scale(gp)) { + dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + _("Warning: screenshot is scaled or distorted. Disable scaling to have better screenshot.")); + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); + gtk_widget_show(dialog); + } + + // Get the screenshot. + active_window = gtk_widget_get_window(GTK_WIDGET(gp)); + // width = gdk_window_get_width(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))); + width = gdk_window_get_width (active_window); + // height = gdk_window_get_height(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))); + height = gdk_window_get_height (active_window); + + screenshot = gdk_pixbuf_get_from_window (active_window, 0, 0, width, height); + if (screenshot == NULL) + g_print("gdk_pixbuf_get_from_window failed\n"); + + // Prepare the destination cairo surface. + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); + cr = cairo_create(surface); + + // Copy the source pixbuf to the surface and paint it. + gdk_cairo_set_source_pixbuf(cr, screenshot, 0, 0); + cairo_paint(cr); + + // Deallocate screenshot pixbuf + g_object_unref(screenshot); + + } + + remminafile = remmina_file_get_filename(cnnobj->remmina_file); + //imagedir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES); + /* TODO: Improve file name (DONE:8743571d) + give the user the option */ + pngdate = g_strdup_printf("%d-%d-%d-%d:%d:%f", + g_date_time_get_year (date), + g_date_time_get_month (date), + g_date_time_get_day_of_month (date), + g_date_time_get_hour (date), + g_date_time_get_minute (date), + g_date_time_get_seconds (date)); + + g_date_time_unref (date); + pngname = g_strdup_printf("%s/%s-%s.png", remmina_pref.screenshot_path, + g_path_get_basename(remminafile), pngdate); + + cairo_surface_write_to_png(surface, pngname); + + /* send a desktop notification */ + remmina_public_send_notification ("remmina-screenshot-is-ready-id", "Screenshot taken", pngname); + + //Clean up and return. + cairo_destroy(cr); + cairo_surface_destroy(surface); + + +} + static void remmina_connection_holder_toolbar_minimize(GtkWidget* widget, RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_holder_toolbar_minimize"); @@ -1566,11 +1688,11 @@ static void remmina_connection_holder_toolbar_grab(GtkWidget* widget, RemminaCon DECLARE_CNNOBJ remmina_file_set_int(cnnobj->remmina_file, "keyboard_grab", - gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget))); + gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget))); remmina_connection_holder_keyboard_grab(cnnhld); } -static GtkWidget* + static GtkWidget* remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint mode) { TRACE_CALL("remmina_connection_holder_create_toolbar"); @@ -1593,7 +1715,7 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m toolitem = gtk_tool_button_new(NULL, NULL); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem), "remmina-fit-window"); remmina_connection_holder_set_tooltip(GTK_WIDGET(toolitem), _("Resize the window to fit in remote resolution"), - remmina_pref.shortcutkey_autofit, 0); + remmina_pref.shortcutkey_autofit, 0); g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(remmina_connection_holder_toolbar_autofit), cnnhld); priv->toolitem_autofit = toolitem; gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); @@ -1603,7 +1725,7 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m toolitem = gtk_toggle_tool_button_new(); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem), "remmina-fullscreen"); remmina_connection_holder_set_tooltip(GTK_WIDGET(toolitem), _("Toggle fullscreen mode"), - remmina_pref.shortcutkey_fullscreen, 0); + remmina_pref.shortcutkey_fullscreen, 0); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); priv->toolitem_fullscreen = toolitem; @@ -1643,7 +1765,7 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m toolitem = gtk_toggle_tool_button_new(); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem), "remmina-switch-page"); remmina_connection_holder_set_tooltip(GTK_WIDGET(toolitem), _("Switch tab pages"), remmina_pref.shortcutkey_prevtab, - remmina_pref.shortcutkey_nexttab); + remmina_pref.shortcutkey_nexttab); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); g_signal_connect(G_OBJECT(toolitem), "toggled", G_CALLBACK(remmina_connection_holder_toolbar_switch_page), cnnhld); @@ -1690,7 +1812,7 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m toolitem = gtk_toggle_tool_button_new(); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(toolitem), "input-keyboard"); remmina_connection_holder_set_tooltip(GTK_WIDGET(toolitem), _("Grab all keyboard events"), - remmina_pref.shortcutkey_grab, 0); + remmina_pref.shortcutkey_grab, 0); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); g_signal_connect(G_OBJECT(toolitem), "toggled", G_CALLBACK(remmina_connection_holder_toolbar_grab), cnnhld); @@ -1717,6 +1839,13 @@ remmina_connection_holder_create_toolbar(RemminaConnectionHolder* cnnhld, gint m gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); gtk_widget_show(GTK_WIDGET(toolitem)); + toolitem = gtk_tool_button_new(NULL, "_Screenshot"); + gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON (toolitem), "camera-photo"); + remmina_connection_holder_set_tooltip(GTK_WIDGET(toolitem), _("Screenshot"), remmina_pref.shortcutkey_screenshot, 0); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1); + gtk_widget_show(GTK_WIDGET(toolitem)); + g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(remmina_connection_holder_toolbar_screenshot), cnnhld); + toolitem = gtk_tool_button_new(NULL, "_Bottom"); gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON (toolitem), "go-bottom"); remmina_connection_holder_set_tooltip(GTK_WIDGET(toolitem), _("Minimize window"), remmina_pref.shortcutkey_minimize, 0); @@ -1775,7 +1904,7 @@ static void remmina_connection_holder_update_toolbar(RemminaConnectionHolder* cn { TRACE_CALL("remmina_connection_holder_update_toolbar"); DECLARE_CNNOBJ - RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv; + RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv; GtkToolItem* toolitem; gboolean bval; gboolean test_floating_toolbar; @@ -1792,21 +1921,21 @@ static void remmina_connection_holder_update_toolbar(RemminaConnectionHolder* cn gtk_widget_set_sensitive(GTK_WIDGET(priv->scaler_option_button), bval); bval = remmina_protocol_widget_query_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); + REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval); toolitem = priv->toolitem_grab; gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolitem), - remmina_file_get_int(cnnobj->remmina_file, "keyboard_grab", FALSE)); + remmina_file_get_int(cnnobj->remmina_file, "keyboard_grab", FALSE)); toolitem = priv->toolitem_preferences; bval = remmina_protocol_widget_query_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - REMMINA_PROTOCOL_FEATURE_TYPE_PREF); + REMMINA_PROTOCOL_FEATURE_TYPE_PREF); gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval); toolitem = priv->toolitem_tools; bval = remmina_protocol_widget_query_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - REMMINA_PROTOCOL_FEATURE_TYPE_TOOL); + REMMINA_PROTOCOL_FEATURE_TYPE_TOOL); gtk_widget_set_sensitive(GTK_WIDGET(toolitem), bval); gtk_window_set_title(GTK_WINDOW(cnnhld->cnnwin), remmina_file_get_string(cnnobj->remmina_file, "name")); @@ -1819,7 +1948,7 @@ static void remmina_connection_holder_update_toolbar(RemminaConnectionHolder* cn if (test_floating_toolbar) { gtk_label_set_text(GTK_LABEL(priv->floating_toolbar_label), - remmina_file_get_string(cnnobj->remmina_file, "name")); + remmina_file_get_string(cnnobj->remmina_file, "name")); } } @@ -1834,8 +1963,8 @@ static void remmina_connection_holder_showhide_toolbar(RemminaConnectionHolder* if (priv->view_mode == SCROLLED_WINDOW_MODE) { if (resize - && (gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))) - & GDK_WINDOW_STATE_MAXIMIZED) == 0) + && (gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))) + & GDK_WINDOW_STATE_MAXIMIZED) == 0) { gtk_window_get_size(GTK_WINDOW(cnnhld->cnnwin), &width, &height); @@ -1866,7 +1995,7 @@ static void remmina_connection_holder_showhide_toolbar(RemminaConnectionHolder* } static gboolean remmina_connection_holder_floating_toolbar_on_enter(GtkWidget* widget, GdkEventCrossing* event, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_holder_floating_toolbar_on_enter"); remmina_connection_holder_floating_toolbar_show(cnnhld, TRUE); @@ -1874,7 +2003,7 @@ static gboolean remmina_connection_holder_floating_toolbar_on_enter(GtkWidget* w } static gboolean remmina_connection_object_enter_protocol_widget(GtkWidget* widget, GdkEventCrossing* event, - RemminaConnectionObject* cnnobj) + RemminaConnectionObject* cnnobj) { TRACE_CALL("remmina_connection_object_enter_protocol_widget"); RemminaConnectionHolder* cnnhld = cnnobj->cnnhld; @@ -1887,8 +2016,6 @@ static gboolean remmina_connection_object_enter_protocol_widget(GtkWidget* widge return FALSE; } - - static gboolean remmina_connection_window_focus_in(GtkWidget* widget, GdkEventFocus* event, RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_window_focus_in"); @@ -1906,9 +2033,9 @@ static gboolean remmina_connection_window_focus_in(GtkWidget* widget, GdkEventFo static gboolean remmina_connection_window_focus_out(GtkWidget* widget, GdkEventFocus* event, RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_window_focus_out"); - DECLARE_CNNOBJ_WITH_RETURN(FALSE) +DECLARE_CNNOBJ_WITH_RETURN(FALSE) #if !FLOATING_TOOLBAR_WIDGET - RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv; + RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv; #endif cnnhld->hostkey_activated = FALSE; @@ -1924,7 +2051,7 @@ static gboolean remmina_connection_window_focus_out(GtkWidget* widget, GdkEventF remmina_scrolled_viewport_remove_motion(REMMINA_SCROLLED_VIEWPORT(cnnobj->scrolled_container)); } remmina_protocol_widget_call_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS, 0); + REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS, 0); return FALSE; } @@ -1933,7 +2060,7 @@ static gboolean remmina_connection_window_on_enter(GtkWidget* widget, GdkEventCr { TRACE_CALL("remmina_connection_window_on_enter"); if (event->detail == GDK_NOTIFY_VIRTUAL || event->detail == GDK_NOTIFY_NONLINEAR - || event->detail == GDK_NOTIFY_NONLINEAR_VIRTUAL) + || event->detail == GDK_NOTIFY_NONLINEAR_VIRTUAL) { remmina_connection_holder_keyboard_grab(cnnhld); } @@ -1949,7 +2076,7 @@ static gboolean remmina_connection_window_on_leave(GtkWidget* widget, GdkEventCr GdkDevice *device = NULL; if (event->detail == GDK_NOTIFY_VIRTUAL || event->detail == GDK_NOTIFY_NONLINEAR - || event->detail == GDK_NOTIFY_NONLINEAR_VIRTUAL) + || event->detail == GDK_NOTIFY_NONLINEAR_VIRTUAL) { display = gtk_widget_get_display(widget); manager = gdk_display_get_device_manager(display); @@ -1967,7 +2094,7 @@ static gboolean remmina_connection_window_on_leave(GtkWidget* widget, GdkEventCr } static gboolean remmina_connection_holder_floating_toolbar_on_scroll(GtkWidget* widget, GdkEventScroll* event, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_holder_floating_toolbar_on_scroll"); DECLARE_CNNOBJ_WITH_RETURN(FALSE) @@ -1976,46 +2103,46 @@ static gboolean remmina_connection_holder_floating_toolbar_on_scroll(GtkWidget* opacity = remmina_file_get_int(cnnobj->remmina_file, "toolbar_opacity", 0); switch (event->direction) { - case GDK_SCROLL_UP: - if (opacity > 0) - { - remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity - 1); - remmina_connection_holder_update_toolbar_opacity(cnnhld); - return TRUE; - } - break; - case GDK_SCROLL_DOWN: - if (opacity < TOOLBAR_OPACITY_LEVEL) - { - remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity + 1); - remmina_connection_holder_update_toolbar_opacity(cnnhld); - return TRUE; - } - break; + case GDK_SCROLL_UP: + if (opacity > 0) + { + remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity - 1); + remmina_connection_holder_update_toolbar_opacity(cnnhld); + return TRUE; + } + break; + case GDK_SCROLL_DOWN: + if (opacity < TOOLBAR_OPACITY_LEVEL) + { + remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity + 1); + remmina_connection_holder_update_toolbar_opacity(cnnhld); + return TRUE; + } + break; #ifdef GDK_SCROLL_SMOOTH - case GDK_SCROLL_SMOOTH: - if (event->delta_y < 0 && opacity > 0) - { - remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity - 1); - remmina_connection_holder_update_toolbar_opacity(cnnhld); - return TRUE; - } - if (event->delta_y > 0 && opacity < TOOLBAR_OPACITY_LEVEL) - { - remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity + 1); - remmina_connection_holder_update_toolbar_opacity(cnnhld); - return TRUE; - } - break; + case GDK_SCROLL_SMOOTH: + if (event->delta_y < 0 && opacity > 0) + { + remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity - 1); + remmina_connection_holder_update_toolbar_opacity(cnnhld); + return TRUE; + } + if (event->delta_y > 0 && opacity < TOOLBAR_OPACITY_LEVEL) + { + remmina_file_set_int(cnnobj->remmina_file, "toolbar_opacity", opacity + 1); + remmina_connection_holder_update_toolbar_opacity(cnnhld); + return TRUE; + } + break; #endif - default: - break; + default: + break; } return FALSE; } static gboolean remmina_connection_window_on_configure(GtkWidget* widget, GdkEventConfigure* event, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_window_on_configure"); DECLARE_CNNOBJ_WITH_RETURN(FALSE) @@ -2027,7 +2154,7 @@ static gboolean remmina_connection_window_on_configure(GtkWidget* widget, GdkEve #endif if (cnnhld->cnnwin && gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin)) - && cnnhld->cnnwin->priv->view_mode == SCROLLED_WINDOW_MODE) + && cnnhld->cnnwin->priv->view_mode == SCROLLED_WINDOW_MODE) { /* Here we store the window state in real-time */ if ((gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(cnnhld->cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) == 0) @@ -2069,12 +2196,12 @@ static void remmina_connection_holder_update_pin(RemminaConnectionHolder* cnnhld if (cnnhld->cnnwin->priv->pin_down) { gtk_button_set_image(GTK_BUTTON(cnnhld->cnnwin->priv->pin_button), - gtk_image_new_from_icon_name("remmina-pin-down", GTK_ICON_SIZE_MENU)); + gtk_image_new_from_icon_name("remmina-pin-down", GTK_ICON_SIZE_MENU)); } else { gtk_button_set_image(GTK_BUTTON(cnnhld->cnnwin->priv->pin_button), - gtk_image_new_from_icon_name("remmina-pin-up", GTK_ICON_SIZE_MENU)); + gtk_image_new_from_icon_name("remmina-pin-up", GTK_ICON_SIZE_MENU)); } } @@ -2243,10 +2370,10 @@ static gboolean remmina_connection_window_state_event(GtkWidget* widget, GdkEven screen = gdk_screen_get_default(); if (remmina_pref.minimize_to_tray && (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) != 0 - && (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) != 0 - && remmina_public_get_current_workspace(screen) - == remmina_public_get_window_workspace(GTK_WINDOW(widget)) - && gdk_screen_get_number(screen) == gdk_screen_get_number(gtk_widget_get_screen(widget))) + && (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) != 0 + && remmina_public_get_current_workspace(screen) + == remmina_public_get_window_workspace(GTK_WINDOW(widget)) + && gdk_screen_get_number(screen) == gdk_screen_get_number(gtk_widget_get_screen(widget))) { gtk_widget_hide(widget); return TRUE; @@ -2255,7 +2382,7 @@ static gboolean remmina_connection_window_state_event(GtkWidget* widget, GdkEven return FALSE; // moved here because a function should return a value. Should be correct } -static GtkWidget* + static GtkWidget* remmina_connection_window_new_from_holder(RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_window_new_from_holder"); @@ -2289,15 +2416,15 @@ static void remmina_connection_window_update_tag(RemminaConnectionWindow* cnnwin switch (remmina_pref.tab_mode) { - case REMMINA_TAB_BY_GROUP: - tag = g_strdup(remmina_file_get_string(cnnobj->remmina_file, "group")); - break; - case REMMINA_TAB_BY_PROTOCOL: - tag = g_strdup(remmina_file_get_string(cnnobj->remmina_file, "protocol")); - break; - default: - tag = NULL; - break; + case REMMINA_TAB_BY_GROUP: + tag = g_strdup(remmina_file_get_string(cnnobj->remmina_file, "group")); + break; + case REMMINA_TAB_BY_PROTOCOL: + tag = g_strdup(remmina_file_get_string(cnnobj->remmina_file, "protocol")); + break; + default: + tag = NULL; + break; } g_object_set_data_full(G_OBJECT(cnnwin), "tag", tag, (GDestroyNotify) g_free); } @@ -2392,7 +2519,7 @@ static GtkWidget* remmina_connection_object_create_tab(RemminaConnectionObject* } static gint remmina_connection_object_append_page(RemminaConnectionObject* cnnobj, GtkNotebook* notebook, GtkWidget* tab, - gint view_mode) + gint view_mode) { TRACE_CALL("remmina_connection_object_append_page"); gint i; @@ -2407,7 +2534,7 @@ static gint remmina_connection_object_append_page(RemminaConnectionObject* cnnob } static void remmina_connection_window_initialize_notebook(GtkNotebook* to, GtkNotebook* from, RemminaConnectionObject* cnnobj, - gint view_mode) + gint view_mode) { TRACE_CALL("remmina_connection_window_initialize_notebook"); gint i, n, c; @@ -2440,14 +2567,14 @@ static void remmina_connection_window_initialize_notebook(GtkNotebook* to, GtkNo remmina_connection_object_append_page(cnnobj, to, tab, view_mode); G_GNUC_BEGIN_IGNORE_DEPRECATIONS - gtk_widget_reparent(cnnobj->viewport, cnnobj->scrolled_container); + gtk_widget_reparent(cnnobj->viewport, cnnobj->scrolled_container); G_GNUC_END_IGNORE_DEPRECATIONS - if (cnnobj->window) - { - gtk_widget_destroy(cnnobj->window); - cnnobj->window = NULL; - } + if (cnnobj->window) + { + gtk_widget_destroy(cnnobj->window); + cnnobj->window = NULL; + } } } else @@ -2467,7 +2594,7 @@ static void remmina_connection_window_initialize_notebook(GtkNotebook* to, GtkNo /* Reparent cnnobj->viewport */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS - gtk_widget_reparent(tc->viewport, tc->scrolled_container); + gtk_widget_reparent(tc->viewport, tc->scrolled_container); G_GNUC_END_IGNORE_DEPRECATIONS } gtk_notebook_set_current_page(to, c); @@ -2488,15 +2615,15 @@ static void remmina_connection_holder_update_notebook(RemminaConnectionHolder* c switch (cnnhld->cnnwin->priv->view_mode) { - case SCROLLED_WINDOW_MODE: - n = gtk_notebook_get_n_pages(notebook); - gtk_notebook_set_show_tabs(notebook, remmina_pref.always_show_tab ? TRUE : n > 1); - gtk_notebook_set_show_border(notebook, remmina_pref.always_show_tab ? TRUE : n > 1); - break; - default: - gtk_notebook_set_show_tabs(notebook, FALSE); - gtk_notebook_set_show_border(notebook, FALSE); - break; + case SCROLLED_WINDOW_MODE: + n = gtk_notebook_get_n_pages(notebook); + gtk_notebook_set_show_tabs(notebook, remmina_pref.always_show_tab ? TRUE : n > 1); + gtk_notebook_set_show_border(notebook, remmina_pref.always_show_tab ? TRUE : n > 1); + break; + default: + gtk_notebook_set_show_tabs(notebook, FALSE); + gtk_notebook_set_show_border(notebook, FALSE); + break; } } @@ -2520,7 +2647,7 @@ static gboolean remmina_connection_holder_on_switch_page_real(gpointer data) } static void remmina_connection_holder_on_switch_page(GtkNotebook* notebook, GtkWidget* page, guint page_num, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_holder_on_switch_page"); RemminaConnectionWindowPriv* priv = cnnhld->cnnwin->priv; @@ -2532,14 +2659,14 @@ static void remmina_connection_holder_on_switch_page(GtkNotebook* notebook, GtkW } static void remmina_connection_holder_on_page_added(GtkNotebook* notebook, GtkWidget* child, guint page_num, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook)) > 0) remmina_connection_holder_update_notebook(cnnhld); } static void remmina_connection_holder_on_page_removed(GtkNotebook* notebook, GtkWidget* child, guint page_num, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_holder_on_page_removed"); @@ -2554,7 +2681,7 @@ static void remmina_connection_holder_on_page_removed(GtkNotebook* notebook, Gtk } -GtkNotebook* + GtkNotebook* remmina_connection_holder_on_notebook_create_window(GtkNotebook* notebook, GtkWidget* page, gint x, gint y, gpointer data) { /* This signal callback is called by GTK when a detachable tab is dropped on the root window */ @@ -2601,12 +2728,12 @@ remmina_connection_holder_on_notebook_create_window(GtkNotebook* notebook, GtkWi } remmina_protocol_widget_set_hostkey_func(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - (RemminaHostkeyFunc) remmina_connection_window_hostkey_func, cnnobj->cnnhld); + (RemminaHostkeyFunc) remmina_connection_window_hostkey_func, cnnobj->cnnhld); return GTK_NOTEBOOK(cnnobj->cnnhld->cnnwin->priv->notebook); } -static GtkWidget* + static GtkWidget* remmina_connection_holder_create_notebook(RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_holder_create_notebook"); @@ -2618,7 +2745,7 @@ remmina_connection_holder_create_notebook(RemminaConnectionHolder* cnnhld) gtk_widget_show(notebook); g_signal_connect(G_OBJECT(notebook), "create-window", G_CALLBACK(remmina_connection_holder_on_notebook_create_window), - cnnhld); + cnnhld); g_signal_connect(G_OBJECT(notebook), "switch-page", G_CALLBACK(remmina_connection_holder_on_switch_page), cnnhld); g_signal_connect(G_OBJECT(notebook), "page-added", G_CALLBACK(remmina_connection_holder_on_page_added), cnnhld); g_signal_connect(G_OBJECT(notebook), "page-removed", G_CALLBACK(remmina_connection_holder_on_page_removed), cnnhld); @@ -2691,13 +2818,13 @@ static void remmina_connection_holder_create_scrolled(RemminaConnectionHolder* c /* Add drag capabilities to the toolbar */ gtk_drag_source_set(GTK_WIDGET(toolbar), GDK_BUTTON1_MASK, - dnd_targets_tb, sizeof dnd_targets_tb / sizeof *dnd_targets_tb, GDK_ACTION_MOVE); + dnd_targets_tb, sizeof dnd_targets_tb / sizeof *dnd_targets_tb, GDK_ACTION_MOVE); g_signal_connect_after(GTK_WIDGET(toolbar), "drag-begin", G_CALLBACK(remmina_connection_window_tb_drag_begin), cnnhld); g_signal_connect(GTK_WIDGET(toolbar), "drag-failed", G_CALLBACK(remmina_connection_window_tb_drag_failed), cnnhld); /* Add drop capabilities to the drop/dest target for the toolbar (the notebook) */ gtk_drag_dest_set(GTK_WIDGET(notebook), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT, - dnd_targets_tb, sizeof dnd_targets_tb / sizeof *dnd_targets_tb, GDK_ACTION_MOVE); + dnd_targets_tb, sizeof dnd_targets_tb / sizeof *dnd_targets_tb, GDK_ACTION_MOVE); gtk_drag_dest_set_track_motion(GTK_WIDGET(notebook), TRUE); g_signal_connect(GTK_WIDGET(notebook), "drag-drop", G_CALLBACK(remmina_connection_window_tb_drag_drop), cnnhld); @@ -2712,8 +2839,8 @@ static void remmina_connection_holder_create_scrolled(RemminaConnectionHolder* c gtk_widget_show(GTK_WIDGET(cnnhld->cnnwin)); remmina_connection_window_initialize_notebook(GTK_NOTEBOOK(notebook), - (oldwindow ? GTK_NOTEBOOK(REMMINA_CONNECTION_WINDOW(oldwindow)->priv->notebook) : NULL), cnnobj, - SCROLLED_WINDOW_MODE); + (oldwindow ? GTK_NOTEBOOK(REMMINA_CONNECTION_WINDOW(oldwindow)->priv->notebook) : NULL), cnnobj, + SCROLLED_WINDOW_MODE); if (cnnobj) { @@ -2840,13 +2967,13 @@ static void remmina_connection_holder_create_overlay_ftb_overlay(RemminaConnecti /* Add drag and drop capabilities to the source */ gtk_drag_source_set(GTK_WIDGET(priv->overlay_ftb_overlay), GDK_BUTTON1_MASK, - dnd_targets_ftb, sizeof dnd_targets_ftb / sizeof *dnd_targets_ftb, GDK_ACTION_MOVE); + dnd_targets_ftb, sizeof dnd_targets_ftb / sizeof *dnd_targets_ftb, GDK_ACTION_MOVE); g_signal_connect_after(GTK_WIDGET(priv->overlay_ftb_overlay), "drag-begin", G_CALLBACK(remmina_connection_window_ftb_drag_begin), cnnhld); } static gboolean remmina_connection_window_ftb_drag_drop(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint time, gpointer user_data) + gint x, gint y, guint time, gpointer user_data) { TRACE_CALL("remmina_connection_window_ftb_drag_drop"); GtkAllocation wa; @@ -2916,7 +3043,7 @@ static void remmina_connection_window_ftb_drag_begin(GtkWidget *widget, GdkDragC #endif static void remmina_connection_holder_create_fullscreen(RemminaConnectionHolder* cnnhld, RemminaConnectionObject* cnnobj, - gint view_mode) + gint view_mode) { TRACE_CALL("remmina_connection_holder_create_fullscreen"); GtkWidget* window; @@ -2953,8 +3080,8 @@ static void remmina_connection_holder_create_fullscreen(RemminaConnectionHolder* cnnhld->fullscreen_view_mode = view_mode; remmina_connection_window_initialize_notebook(GTK_NOTEBOOK(notebook), - (oldwindow ? GTK_NOTEBOOK(REMMINA_CONNECTION_WINDOW(oldwindow)->priv->notebook) : NULL), cnnobj, - view_mode); + (oldwindow ? GTK_NOTEBOOK(REMMINA_CONNECTION_WINDOW(oldwindow)->priv->notebook) : NULL), cnnobj, + view_mode); if (cnnobj) { @@ -2972,7 +3099,7 @@ static void remmina_connection_holder_create_fullscreen(RemminaConnectionHolder* remmina_connection_holder_create_overlay_ftb_overlay(cnnhld); /* Add drag and drop capabilities to the drop/dest target for floating toolbar */ gtk_drag_dest_set(GTK_WIDGET(priv->overlay), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT, - dnd_targets_ftb, sizeof dnd_targets_ftb / sizeof *dnd_targets_ftb, GDK_ACTION_MOVE); + dnd_targets_ftb, sizeof dnd_targets_ftb / sizeof *dnd_targets_ftb, GDK_ACTION_MOVE); gtk_drag_dest_set_track_motion(GTK_WIDGET(priv->notebook), TRUE); g_signal_connect(GTK_WIDGET(priv->overlay), "drag-drop", G_CALLBACK(remmina_connection_window_ftb_drag_drop), cnnhld); #else @@ -3001,7 +3128,7 @@ static void remmina_connection_holder_create_fullscreen(RemminaConnectionHolder* } static gboolean remmina_connection_window_hostkey_func(RemminaProtocolWidget* gp, guint keyval, gboolean release, - RemminaConnectionHolder* cnnhld) + RemminaConnectionHolder* cnnhld) { TRACE_CALL("remmina_connection_window_hostkey_func"); DECLARE_CNNOBJ_WITH_RETURN(FALSE); @@ -3049,19 +3176,19 @@ static gboolean remmina_connection_window_hostkey_func(RemminaProtocolWidget* gp { switch (priv->view_mode) { - case SCROLLED_WINDOW_MODE: - remmina_connection_holder_create_fullscreen( - cnnhld, - NULL, - cnnhld->fullscreen_view_mode ? - cnnhld->fullscreen_view_mode : VIEWPORT_FULLSCREEN_MODE); - break; - case SCROLLED_FULLSCREEN_MODE: - case VIEWPORT_FULLSCREEN_MODE: - remmina_connection_holder_create_scrolled(cnnhld, NULL); - break; - default: - break; + case SCROLLED_WINDOW_MODE: + remmina_connection_holder_create_fullscreen( + cnnhld, + NULL, + cnnhld->fullscreen_view_mode ? + cnnhld->fullscreen_view_mode : VIEWPORT_FULLSCREEN_MODE); + break; + case SCROLLED_FULLSCREEN_MODE: + case VIEWPORT_FULLSCREEN_MODE: + remmina_connection_holder_create_scrolled(cnnhld, NULL); + break; + default: + break; } } else if (keyval == remmina_pref.shortcutkey_autofit) @@ -3090,24 +3217,29 @@ static gboolean remmina_connection_window_hostkey_func(RemminaProtocolWidget* gp if (gtk_widget_is_sensitive(GTK_WIDGET(priv->toolitem_scale))) { gtk_toggle_tool_button_set_active( - GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), - !gtk_toggle_tool_button_get_active( - GTK_TOGGLE_TOOL_BUTTON( - priv->toolitem_scale))); + GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_scale), + !gtk_toggle_tool_button_get_active( + GTK_TOGGLE_TOOL_BUTTON( + priv->toolitem_scale))); } } else if (keyval == remmina_pref.shortcutkey_grab) { gtk_toggle_tool_button_set_active( - GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_grab), - !gtk_toggle_tool_button_get_active( - GTK_TOGGLE_TOOL_BUTTON( - priv->toolitem_grab))); + GTK_TOGGLE_TOOL_BUTTON(priv->toolitem_grab), + !gtk_toggle_tool_button_get_active( + GTK_TOGGLE_TOOL_BUTTON( + priv->toolitem_grab))); } else if (keyval == remmina_pref.shortcutkey_minimize) { remmina_connection_holder_toolbar_minimize(GTK_WIDGET(gp), - cnnhld); + cnnhld); + } + else if (keyval == remmina_pref.shortcutkey_screenshot) + { + remmina_connection_holder_toolbar_screenshot(GTK_WIDGET(gp), + cnnhld); } else if (keyval == remmina_pref.shortcutkey_disconnect) { @@ -3118,30 +3250,30 @@ static gboolean remmina_connection_window_hostkey_func(RemminaProtocolWidget* gp if (priv->view_mode == SCROLLED_WINDOW_MODE) { remmina_pref.hide_connection_toolbar = - !remmina_pref.hide_connection_toolbar; + !remmina_pref.hide_connection_toolbar; remmina_connection_holder_showhide_toolbar( - cnnhld, TRUE); + cnnhld, TRUE); } } else { for (feature = - remmina_protocol_widget_get_features( - REMMINA_PROTOCOL_WIDGET( - cnnobj->proto)); - feature && feature->type; - feature++) + remmina_protocol_widget_get_features( + REMMINA_PROTOCOL_WIDGET( + cnnobj->proto)); + feature && feature->type; + feature++) { if (feature->type - == REMMINA_PROTOCOL_FEATURE_TYPE_TOOL - && GPOINTER_TO_UINT( - feature->opt3) - == keyval) + == REMMINA_PROTOCOL_FEATURE_TYPE_TOOL + && GPOINTER_TO_UINT( + feature->opt3) + == keyval) { remmina_protocol_widget_call_feature_by_ref( - REMMINA_PROTOCOL_WIDGET( - cnnobj->proto), - feature); + REMMINA_PROTOCOL_WIDGET( + cnnobj->proto), + feature); break; } } @@ -3157,18 +3289,18 @@ static RemminaConnectionWindow* remmina_connection_window_find(RemminaFile* remm switch (remmina_pref.tab_mode) { - case REMMINA_TAB_BY_GROUP: - tag = remmina_file_get_string(remminafile, "group"); - break; - case REMMINA_TAB_BY_PROTOCOL: - tag = remmina_file_get_string(remminafile, "protocol"); - break; - case REMMINA_TAB_ALL: - tag = NULL; - break; - case REMMINA_TAB_NONE: - default: - return NULL; + case REMMINA_TAB_BY_GROUP: + tag = remmina_file_get_string(remminafile, "group"); + break; + case REMMINA_TAB_BY_PROTOCOL: + tag = remmina_file_get_string(remminafile, "protocol"); + break; + case REMMINA_TAB_ALL: + tag = NULL; + break; + case REMMINA_TAB_NONE: + default: + return NULL; } return REMMINA_CONNECTION_WINDOW(remmina_widget_pool_find(REMMINA_TYPE_CONNECTION_WINDOW, tag)); } @@ -3205,13 +3337,13 @@ static void remmina_connection_object_on_connect(RemminaProtocolWidget* gp, Remm cnnobj->connected = TRUE; remmina_protocol_widget_set_hostkey_func(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - (RemminaHostkeyFunc) remmina_connection_window_hostkey_func, cnnhld); + (RemminaHostkeyFunc) remmina_connection_window_hostkey_func, cnnhld); /* Remember recent list for quick connect */ if (remmina_file_get_filename(cnnobj->remmina_file) == NULL) { remmina_pref_add_recent(remmina_file_get_string(cnnobj->remmina_file, "protocol"), - remmina_file_get_string(cnnobj->remmina_file, "server")); + remmina_file_get_string(cnnobj->remmina_file, "server")); } /* Save credentials */ @@ -3222,26 +3354,26 @@ static void remmina_connection_object_on_connect(RemminaProtocolWidget* gp, Remm i = remmina_file_get_int(cnnobj->remmina_file, "viewmode", 0); switch (i) { - case SCROLLED_FULLSCREEN_MODE: - case VIEWPORT_FULLSCREEN_MODE: - remmina_connection_holder_create_fullscreen(cnnhld, cnnobj, i); - break; - case SCROLLED_WINDOW_MODE: - default: - remmina_connection_holder_create_scrolled(cnnhld, cnnobj); - break; + case SCROLLED_FULLSCREEN_MODE: + case VIEWPORT_FULLSCREEN_MODE: + remmina_connection_holder_create_fullscreen(cnnhld, cnnobj, i); + break; + case SCROLLED_WINDOW_MODE: + default: + remmina_connection_holder_create_scrolled(cnnhld, cnnobj); + break; } } else { tab = remmina_connection_object_create_tab(cnnobj); i = remmina_connection_object_append_page(cnnobj, GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), tab, - cnnhld->cnnwin->priv->view_mode); + cnnhld->cnnwin->priv->view_mode); G_GNUC_BEGIN_IGNORE_DEPRECATIONS - gtk_widget_reparent(cnnobj->viewport, cnnobj->scrolled_container); + gtk_widget_reparent(cnnobj->viewport, cnnobj->scrolled_container); G_GNUC_END_IGNORE_DEPRECATIONS - gtk_window_present(GTK_WINDOW(cnnhld->cnnwin)); + gtk_window_present(GTK_WINDOW(cnnhld->cnnwin)); gtk_notebook_set_current_page(GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), i); } @@ -3268,7 +3400,7 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, R /* Detach the protocol widget from the notebook now, or we risk that a * window delete will destroy cnnobj->proto before we complete disconnection. - */ + */ pparent = gtk_widget_get_parent(cnnobj->proto); if (pparent != NULL) { @@ -3297,7 +3429,7 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, R if (remmina_protocol_widget_has_error(gp)) { dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - remmina_protocol_widget_get_error_message(gp), NULL); + remmina_protocol_widget_get_error_message(gp), NULL); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show(dialog); remmina_widget_pool_register(dialog); @@ -3306,9 +3438,9 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, R if (cnnhld && cnnhld->cnnwin && cnnobj->scrolled_container) { gtk_notebook_remove_page( - GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), - gtk_notebook_page_num(GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), - cnnobj->scrolled_container)); + GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), + gtk_notebook_page_num(GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), + cnnobj->scrolled_container)); } cnnobj->remmina_file = NULL; @@ -3345,7 +3477,7 @@ gboolean remmina_connection_window_open_from_filename(const gchar* filename) else { dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _("File %s not found."), filename); + _("File %s not found."), filename); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show(dialog); remmina_widget_pool_register(dialog); @@ -3359,7 +3491,7 @@ void remmina_connection_window_open_from_file(RemminaFile* remminafile) remmina_connection_window_open_from_file_full(remminafile, NULL, NULL, NULL); } -GtkWidget* + GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafile, GCallback disconnect_cb, gpointer data, guint* handler) { TRACE_CALL("remmina_connection_window_open_from_file_full"); @@ -3395,9 +3527,9 @@ remmina_connection_window_open_from_file_full(RemminaFile* remminafile, GCallbac } g_signal_connect(G_OBJECT(cnnobj->proto), "disconnect", G_CALLBACK(remmina_connection_object_on_disconnect), cnnobj); g_signal_connect(G_OBJECT(cnnobj->proto), "desktop-resize", G_CALLBACK(remmina_connection_object_on_desktop_resize), - cnnobj); + cnnobj); g_signal_connect(G_OBJECT(cnnobj->proto), "update-align", G_CALLBACK(remmina_connection_object_on_update_align), - cnnobj); + cnnobj); /* Create the viewport to make the RemminaProtocolWidget scrollable */ cnnobj->viewport = gtk_viewport_new(NULL, NULL); @@ -3408,8 +3540,8 @@ remmina_connection_window_open_from_file_full(RemminaFile* remminafile, GCallbac /* Determine whether the plugin can scale or not. If the plugin can scale and we do * not want to expand, then we add a GtkAspectFrame to maintain aspect ratio during scaling */ cnnobj->plugin_can_scale = remmina_plugin_manager_query_feature_by_type(REMMINA_PLUGIN_TYPE_PROTOCOL, - remmina_file_get_string(remminafile, "protocol"), - REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); + remmina_file_get_string(remminafile, "protocol"), + REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); cnnobj->aspectframe = NULL; gtk_container_add(GTK_CONTAINER(cnnobj->viewport), cnnobj->proto); diff --git a/remmina/src/remmina_file_editor.c b/remmina/src/remmina_file_editor.c index aefee7fb4..3d8f3bd5b 100644 --- a/remmina/src/remmina_file_editor.c +++ b/remmina/src/remmina_file_editor.c @@ -101,6 +101,7 @@ struct _RemminaFileEditorPriv GtkWidget* save_button; GtkWidget* config_box; + GtkWidget* config_scrollable; GtkWidget* config_container; GtkWidget* server_combo; @@ -210,9 +211,18 @@ static void remmina_file_editor_create_notebook_container(RemminaFileEditor* gfe TRACE_CALL("remmina_file_editor_create_notebook_container"); /* Create the notebook */ gfe->priv->config_container = gtk_notebook_new(); - gtk_container_add(GTK_CONTAINER(gfe->priv->config_box), gfe->priv->config_container); - gtk_container_set_border_width(GTK_CONTAINER(gfe->priv->config_container), 4); + + gfe->priv->config_scrollable = gtk_scrolled_window_new (NULL, NULL); + gtk_container_set_border_width (GTK_CONTAINER (gfe->priv->config_scrollable), 2); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (gfe->priv->config_scrollable), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_widget_show (gfe->priv->config_scrollable); + + gtk_container_add (GTK_CONTAINER (gfe->priv->config_scrollable), gfe->priv->config_container); + gtk_container_set_border_width(GTK_CONTAINER(gfe->priv->config_container), 2); gtk_widget_show(gfe->priv->config_container); + + gtk_container_add(GTK_CONTAINER(gfe->priv->config_box), gfe->priv->config_scrollable); } static GtkWidget* remmina_file_editor_create_notebook_tab(RemminaFileEditor* gfe, @@ -971,6 +981,8 @@ static void remmina_file_editor_protocol_combo_on_changed(GtkComboBox* combo, Re { gtk_widget_destroy(priv->config_container); priv->config_container = NULL; + gtk_widget_destroy(priv->config_scrollable); + priv->config_scrollable = NULL; } priv->server_combo = NULL; @@ -1235,7 +1247,7 @@ static void remmina_file_editor_init(RemminaFileEditor* gfe) g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(remmina_file_editor_on_connect), gfe); gtk_dialog_set_default_response(GTK_DIALOG(gfe), GTK_RESPONSE_OK); - gtk_window_set_default_size(GTK_WINDOW(gfe), 450, 500); + gtk_window_set_default_size(GTK_WINDOW(gfe), 800, 600); g_signal_connect(G_OBJECT(gfe), "destroy", G_CALLBACK(remmina_file_editor_destroy), NULL); g_signal_connect(G_OBJECT(gfe), "realize", G_CALLBACK(remmina_file_editor_on_realize), NULL); @@ -1441,6 +1453,7 @@ GtkWidget* remmina_file_editor_new_from_file(RemminaFile* remminafile) priv->config_box = widget; priv->config_container = NULL; + priv->config_scrollable = NULL; remmina_file_editor_protocol_combo_on_changed(GTK_COMBO_BOX(priv->protocol_combo), gfe); diff --git a/remmina/src/remmina_pref.c b/remmina/src/remmina_pref.c index ef2a9372c..df0c7f4ea 100644 --- a/remmina/src/remmina_pref.c +++ b/remmina/src/remmina_pref.c @@ -391,6 +391,12 @@ void remmina_pref_init(void) else remmina_pref.ssh_loglevel = DEFAULT_SSH_LOGLEVEL; + if (g_key_file_has_key(gkeyfile, "remmina_pref", "screenshot_path", NULL)) { + remmina_pref.screenshot_path = g_key_file_get_string(gkeyfile, "remmina_pref", "screenshot_path", NULL); + }else{ + remmina_pref.screenshot_path = g_strdup(""); + } + if (g_key_file_has_key(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL)) remmina_pref.ssh_parseconfig = g_key_file_get_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", NULL); else @@ -504,11 +510,15 @@ void remmina_pref_init(void) remmina_pref.shortcutkey_grab = GDK_KEY_Control_R; if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL)) - remmina_pref.shortcutkey_minimize = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", - NULL); + remmina_pref.shortcutkey_minimize = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", NULL); else remmina_pref.shortcutkey_minimize = GDK_KEY_F9; + if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL)) + remmina_pref.shortcutkey_screenshot = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", NULL); + else + remmina_pref.shortcutkey_screenshot = GDK_KEY_F12; + if (g_key_file_has_key(gkeyfile, "remmina_pref", "shortcutkey_disconnect", NULL)) remmina_pref.shortcutkey_disconnect = g_key_file_get_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect", NULL); @@ -615,6 +625,7 @@ void remmina_pref_save(void) g_key_file_set_integer(gkeyfile, "remmina_pref", "default_action", remmina_pref.default_action); g_key_file_set_integer(gkeyfile, "remmina_pref", "scale_quality", remmina_pref.scale_quality); g_key_file_set_integer(gkeyfile, "remmina_pref", "ssh_loglevel", remmina_pref.ssh_loglevel); + g_key_file_set_string(gkeyfile, "remmina_pref", "screenshot_path", remmina_pref.screenshot_path); g_key_file_set_boolean(gkeyfile, "remmina_pref", "ssh_parseconfig", remmina_pref.ssh_parseconfig); g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_toolbar", remmina_pref.hide_toolbar); g_key_file_set_boolean(gkeyfile, "remmina_pref", "hide_statusbar", remmina_pref.hide_statusbar); @@ -649,6 +660,7 @@ void remmina_pref_save(void) g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_prevtab", remmina_pref.shortcutkey_prevtab); g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_scale", remmina_pref.shortcutkey_scale); g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_grab", remmina_pref.shortcutkey_grab); + g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_screenshot", remmina_pref.shortcutkey_screenshot); g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_minimize", remmina_pref.shortcutkey_minimize); g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_disconnect", remmina_pref.shortcutkey_disconnect); g_key_file_set_integer(gkeyfile, "remmina_pref", "shortcutkey_toolbar", remmina_pref.shortcutkey_toolbar); diff --git a/remmina/src/remmina_pref.h b/remmina/src/remmina_pref.h index 8e6f97d2d..bbaef281b 100644 --- a/remmina/src/remmina_pref.h +++ b/remmina/src/remmina_pref.h @@ -93,9 +93,7 @@ typedef struct _RemminaPref gboolean survey; gint default_action; gint scale_quality; - gint ssh_loglevel; - gboolean ssh_parseconfig; - gint sshtunnel_port; + gchar *screenshot_path; gint auto_scroll_step; gint recent_maximum; gchar *resolutions; @@ -112,6 +110,10 @@ typedef struct _RemminaPref gboolean applet_new_ontop; gboolean applet_hide_count; gboolean disable_tray_icon; + /* In RemminaPrefDialog SSH Option tab */ + gint ssh_loglevel; + gboolean ssh_parseconfig; + gint sshtunnel_port; /* In RemminaPrefDialog keyboard tab */ guint hostkey; guint shortcutkey_fullscreen; @@ -120,6 +122,7 @@ typedef struct _RemminaPref guint shortcutkey_nexttab; guint shortcutkey_scale; guint shortcutkey_grab; + guint shortcutkey_screenshot; guint shortcutkey_minimize; guint shortcutkey_disconnect; guint shortcutkey_toolbar; diff --git a/remmina/src/remmina_pref_dialog.c b/remmina/src/remmina_pref_dialog.c index fd43f1c56..3215208f9 100644 --- a/remmina/src/remmina_pref_dialog.c +++ b/remmina/src/remmina_pref_dialog.c @@ -136,9 +136,9 @@ void remmina_pref_on_dialog_destroy(GtkWidget *widget, gpointer user_data) remmina_pref.show_buttons_icons = gtk_combo_box_get_active(remmina_pref_dialog->comboboxtext_appearance_show_buttons_icons); remmina_pref.show_menu_icons = gtk_combo_box_get_active(remmina_pref_dialog->comboboxtext_appearance_show_menu_icons); remmina_pref.scale_quality = gtk_combo_box_get_active(remmina_pref_dialog->comboboxtext_options_scale_quality); + remmina_pref.screenshot_path = gtk_file_chooser_get_filename(remmina_pref_dialog->filechooserbutton_options_screenshots_path); remmina_pref.ssh_loglevel = gtk_combo_box_get_active(remmina_pref_dialog->comboboxtext_options_ssh_loglevel); remmina_pref.ssh_parseconfig = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(remmina_pref_dialog->checkbutton_options_ssh_parseconfig)); - remmina_pref.sshtunnel_port = atoi(gtk_entry_get_text(remmina_pref_dialog->entry_options_ssh_port)); if (remmina_pref.sshtunnel_port <= 0) remmina_pref.sshtunnel_port = DEFAULT_SSHTUNNEL_PORT; @@ -178,6 +178,7 @@ void remmina_pref_on_dialog_destroy(GtkWidget *widget, gpointer user_data) remmina_pref.shortcutkey_nexttab = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_switch_tab_right)); remmina_pref.shortcutkey_scale = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_scaled)); remmina_pref.shortcutkey_grab = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_grab_keyboard)); + remmina_pref.shortcutkey_screenshot = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_screenshot)); remmina_pref.shortcutkey_minimize = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_minimize)); remmina_pref.shortcutkey_disconnect = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_disconnect)); remmina_pref.shortcutkey_toolbar = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_toolbar)); @@ -307,6 +308,7 @@ static void remmina_pref_dialog_init(void) remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_switch_tab_right, remmina_pref.shortcutkey_nexttab); remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_scaled, remmina_pref.shortcutkey_scale); remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_grab_keyboard, remmina_pref.shortcutkey_grab); + remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_screenshot, remmina_pref.shortcutkey_screenshot); remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_minimize, remmina_pref.shortcutkey_minimize); remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_disconnect, remmina_pref.shortcutkey_disconnect); remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_toolbar, remmina_pref.shortcutkey_toolbar); @@ -355,6 +357,11 @@ static void remmina_pref_dialog_init(void) gtk_combo_box_set_active(remmina_pref_dialog->comboboxtext_appearance_show_menu_icons, remmina_pref.show_menu_icons); gtk_combo_box_set_active(remmina_pref_dialog->comboboxtext_options_scale_quality, remmina_pref.scale_quality); gtk_combo_box_set_active(remmina_pref_dialog->comboboxtext_options_ssh_loglevel, remmina_pref.ssh_loglevel); + if (remmina_pref.screenshot_path != NULL){ + gtk_file_chooser_set_filename(remmina_pref_dialog->filechooserbutton_options_screenshots_path, remmina_pref.screenshot_path); + }else{ + gtk_file_chooser_set_filename(remmina_pref_dialog->filechooserbutton_options_screenshots_path, g_get_home_dir()); + } gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(remmina_pref_dialog->checkbutton_options_ssh_parseconfig), remmina_pref.ssh_parseconfig); remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_copy, remmina_pref.vte_shortcutkey_copy); @@ -394,6 +401,7 @@ GtkDialog* remmina_pref_dialog_new(gint default_tab, GtkWindow *parent) remmina_pref_dialog->comboboxtext_options_scale_quality = GTK_COMBO_BOX(GET_OBJECT("comboboxtext_options_scale_quality")); remmina_pref_dialog->checkbutton_options_ssh_parseconfig = GTK_CHECK_BUTTON(GET_OBJECT("checkbutton_options_ssh_parseconfig")); remmina_pref_dialog->comboboxtext_options_ssh_loglevel = GTK_COMBO_BOX(GET_OBJECT("comboboxtext_options_ssh_loglevel")); + remmina_pref_dialog->filechooserbutton_options_screenshots_path = GTK_FILE_CHOOSER(GET_OBJECT("filechooserbutton_options_screenshots_path")); remmina_pref_dialog->entry_options_ssh_port = GTK_ENTRY(GET_OBJECT("entry_options_ssh_port")); remmina_pref_dialog->entry_options_scroll = GTK_ENTRY(GET_OBJECT("entry_options_scroll")); remmina_pref_dialog->entry_options_recent_items = GTK_ENTRY(GET_OBJECT("entry_options_recent_items")); @@ -411,6 +419,7 @@ GtkDialog* remmina_pref_dialog_new(gint default_tab, GtkWindow *parent) remmina_pref_dialog->button_keyboard_switch_tab_right = GTK_BUTTON(GET_OBJECT("button_keyboard_switch_tabright")); remmina_pref_dialog->button_keyboard_scaled = GTK_BUTTON(GET_OBJECT("button_keyboard_scaled")); remmina_pref_dialog->button_keyboard_grab_keyboard = GTK_BUTTON(GET_OBJECT("button_keyboard_grab_keyboard")); + remmina_pref_dialog->button_keyboard_screenshot = GTK_BUTTON(GET_OBJECT("button_keyboard_screenshot")); remmina_pref_dialog->button_keyboard_minimize = GTK_BUTTON(GET_OBJECT("button_keyboard_minimize")); remmina_pref_dialog->button_keyboard_disconnect = GTK_BUTTON(GET_OBJECT("button_keyboard_disconnect")); remmina_pref_dialog->button_keyboard_toolbar = GTK_BUTTON(GET_OBJECT("button_keyboard_toolbar")); diff --git a/remmina/src/remmina_pref_dialog.h b/remmina/src/remmina_pref_dialog.h index 3fd3c3629..cc00ecbe4 100644 --- a/remmina/src/remmina_pref_dialog.h +++ b/remmina/src/remmina_pref_dialog.h @@ -63,6 +63,7 @@ typedef struct _RemminaPrefDialog GtkComboBox *comboboxtext_appearance_show_menu_icons; GtkComboBox *comboboxtext_options_scale_quality; GtkComboBox *comboboxtext_options_ssh_loglevel; + GtkFileChooser *filechooserbutton_options_screenshots_path; GtkCheckButton *checkbutton_options_ssh_parseconfig; GtkEntry *entry_options_ssh_port; GtkEntry *entry_options_scroll; @@ -82,6 +83,7 @@ typedef struct _RemminaPrefDialog GtkButton *button_keyboard_switch_tab_right; GtkButton *button_keyboard_scaled; GtkButton *button_keyboard_grab_keyboard; + GtkButton *button_keyboard_screenshot; GtkButton *button_keyboard_minimize; GtkButton *button_keyboard_disconnect; GtkButton *button_keyboard_toolbar; diff --git a/remmina/src/remmina_protocol_widget.c b/remmina/src/remmina_protocol_widget.c index 32586b792..6c9d9544a 100644 --- a/remmina/src/remmina_protocol_widget.c +++ b/remmina/src/remmina_protocol_widget.c @@ -51,6 +51,7 @@ #include "remmina_protocol_widget.h" #include "remmina_public.h" #include "remmina_ssh.h" +#include "remmina_log.h" #include "remmina/remmina_trace_calls.h" struct _RemminaProtocolWidgetPriv @@ -437,6 +438,17 @@ void remmina_protocol_widget_send_keystrokes(RemminaProtocolWidget* gp, GtkMenuI return; } +gboolean remmina_protocol_widget_plugin_screenshot(RemminaProtocolWidget* gp, RemminaPluginScreenshotData *rpsd) +{ + if (!gp->priv->plugin->get_plugin_screenshot) { + remmina_log_printf("plugin screenshot function is not implemented\n"); + return FALSE; + } + + return gp->priv->plugin->get_plugin_screenshot(gp, rpsd); + +} + void remmina_protocol_widget_emit_signal(RemminaProtocolWidget* gp, const gchar* signal_name) { diff --git a/remmina/src/remmina_protocol_widget.h b/remmina/src/remmina_protocol_widget.h index 2b4213626..8519af483 100644 --- a/remmina/src/remmina_protocol_widget.h +++ b/remmina/src/remmina_protocol_widget.h @@ -148,6 +148,8 @@ void remmina_protocol_widget_send_keys_signals(GtkWidget *widget, const guint *k gboolean remmina_protocol_widget_plugin_receives_keystrokes(RemminaProtocolWidget* gp); /* Send to the plugin some keystrokes */ void remmina_protocol_widget_send_keystrokes(RemminaProtocolWidget* gp, GtkMenuItem *widget); +/* Take screenshot of plugin */ +gboolean remmina_protocol_widget_plugin_screenshot(RemminaProtocolWidget* gp, RemminaPluginScreenshotData *rpsd); G_END_DECLS diff --git a/remmina/src/remmina_public.c b/remmina/src/remmina_public.c index ace2f9512..d41f8250a 100644 --- a/remmina/src/remmina_public.c +++ b/remmina/src/remmina_public.c @@ -621,28 +621,6 @@ void remmina_public_gtk_widget_reparent(GtkWidget *widget, GtkContainer *contain g_object_unref(widget); } -/* Replaces all occurences of search in a new copy of string by replacement. */ -gchar* remmina_public_str_replace(const gchar *string, const gchar *search, const gchar *replacement) -{ - TRACE_CALL("remmina_public_str_replace") - gchar *str, **arr; - - g_return_val_if_fail (string != NULL, NULL); - g_return_val_if_fail (search != NULL, NULL); - - if (replacement == NULL) - replacement = ""; - - arr = g_strsplit (string, search, -1); - if (arr != NULL && arr[0] != NULL) - str = g_strjoinv (replacement, arr); - else - str = g_strdup (string); - - g_strfreev (arr); - return str; -} - /* Validate the inserted value for a new resolution */ gboolean remmina_public_resolution_validation_func(const gchar *new_str, gchar **error) { @@ -691,6 +669,40 @@ gboolean remmina_public_resolution_validation_func(const gchar *new_str, gchar * return result; } +/* Used to send desktop notifications */ +void remmina_public_send_notification (const gchar *notification_id, + const gchar *notification_title, const gchar *notification_message) +{ + TRACE_CALL("remmina_public_send_notification"); + + GNotification *notification = g_notification_new (notification_title); + g_notification_set_body (notification, notification_message); + g_application_send_notification (g_application_get_default (), notification_id, notification); + g_object_unref (notification); +} + +/* Replaces all occurences of search in a new copy of string by replacement. */ +gchar* remmina_public_str_replace(const gchar *string, const gchar *search, const gchar *replacement) +{ + TRACE_CALL("remmina_public_str_replace") + gchar *str, **arr; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (search != NULL, NULL); + + if (replacement == NULL) + replacement = ""; + + arr = g_strsplit (string, search, -1); + if (arr != NULL && arr[0] != NULL) + str = g_strjoinv (replacement, arr); + else + str = g_strdup (string); + + g_strfreev (arr); + return str; +} + /* Replaces all occurences of search in a new copy of string by replacement * and overwrites the original string */ gchar* remmina_public_str_replace_in_place(gchar *string, const gchar *search, const gchar *replacement) @@ -701,3 +713,4 @@ gchar* remmina_public_str_replace_in_place(gchar *string, const gchar *search, c string = g_strdup(new_string); return string; } + diff --git a/remmina/src/remmina_public.h b/remmina/src/remmina_public.h index eca102c8b..204d83d13 100644 --- a/remmina/src/remmina_public.h +++ b/remmina/src/remmina_public.h @@ -103,10 +103,13 @@ gboolean remmina_public_get_modifier_for_keycode(GdkKeymap *keymap, guint16 keyc GtkBuilder* remmina_public_gtk_builder_new_from_file(gchar *filename); /* Change parent container for a widget */ void remmina_public_gtk_widget_reparent(GtkWidget *widget, GtkContainer *container); -/* Replaces all occurences of search in a new copy of string by replacement. */ -gchar* remmina_public_str_replace(const gchar *string, const gchar *search, const gchar *replacement); +/* Used to send desktop notifications */ +void remmina_public_send_notification (const gchar *notification_id, + const gchar *notification_title, const gchar *notification_message); /* Validate the inserted value for a new resolution */ gboolean remmina_public_resolution_validation_func(const gchar *new_str, gchar **error); +/* Replaces all occurences of search in a new copy of string by replacement. */ +gchar* remmina_public_str_replace(const gchar *string, const gchar *search, const gchar *replacement); /* Replaces all occurences of search in a new copy of string by replacement * and overwrites the original string */ gchar* remmina_public_str_replace_in_place(gchar *string, const gchar *search, const gchar *replacement); diff --git a/remmina/ui/remmina_about.glade b/remmina/ui/remmina_about.glade index 3e3088218..dc47a5f12 100644 --- a/remmina/ui/remmina_about.glade +++ b/remmina/ui/remmina_about.glade @@ -29,6 +29,7 @@ Benjamin Podszun <benjamin.podszun@gmail.com> Ben Kohler <bkohler@gmail.com> Christopher Rawlings <chris.rawlings+git@gmail.com> Daniel M. Weeks <dan@danweeks.net> +Daniele Tieghi <notdisclosed> Dmitry Kubatkin <maelnor@gmail.com> dupondje <jean-louis@dupondje.be> Emmanuel Grognet <emmanuel@grognet.fr> @@ -46,6 +47,7 @@ Kirill MĂ¼ller <krlmlr@users.noreply.github.com> Kyle Sanderson <kyle.leet@gmail.com> Luca Falavigna <dktrkranz@debian.org> Marc-AndrĂ© Moreau <marcandre.moreau@gmail.com> +Michele Sartori <mik.thrasher@aol.com> Mike Dalessio <mike@csa.net> Mike Gilbert <floppym@gentoo.org> Fabio Castelli (muflone) <muflone@vbsimple.net> diff --git a/remmina/ui/remmina_preferences.glade b/remmina/ui/remmina_preferences.glade index b5234f605..4c08fc324 100644 --- a/remmina/ui/remmina_preferences.glade +++ b/remmina/ui/remmina_preferences.glade @@ -1,11 +1,38 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.18.3 --> +<!-- Generated with glade 3.18.3 + +Remmina Preferences Dialog - +Copyright (C) Antenore Gatta & Giovanni Panozzo 2014-2016 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Author: Antenore Gatta + +--> <interface> - <requires lib="gtk+" version="3.0"/> + <requires lib="gtk+" version="3.4"/> + <!-- interface-license-type gplv2 --> + <!-- interface-name Remmina Preferences Dialog --> + <!-- interface-copyright Antenore Gatta & Giovanni Panozzo 2014-2016 --> + <!-- interface-authors Antenore Gatta --> + <object class="GtkActionGroup" id="actiongroup1"/> <object class="GtkActionGroup" id="actiongroup_preferences"> <child> <object class="GtkAction" id="action_preferences_close"> <property name="label" translatable="yes">Close</property> + <property name="short_label" translatable="yes">Close</property> <signal name="activate" handler="remmina_pref_dialog_on_close_clicked" swapped="no"/> </object> </child> @@ -28,16 +55,18 @@ <property name="layout_style">end</property> <child> <object class="GtkButton" id="button_close"> + <property name="label" translatable="yes">Close</property> <property name="use_action_appearance">True</property> <property name="related_action">action_preferences_close</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_underline">True</property> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">0</property> </packing> </child> </object> @@ -100,8 +129,8 @@ <object class="GtkLabel" id="label_options_double_click"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Double-click action</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -128,8 +157,8 @@ <object class="GtkLabel" id="label_options_scale_quality"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Scale quality</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -155,39 +184,15 @@ </packing> </child> <child> - <object class="GtkLabel" id="label_options_ssh_port"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">SSH tunnel local port</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">5</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="entry_options_ssh_port"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="max_length">5</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">5</property> - <property name="width">2</property> - </packing> - </child> - <child> <object class="GtkLabel" id="label_options_scroll"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Auto scroll step size</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">9</property> + <property name="top_attach">7</property> </packing> </child> <child> @@ -198,7 +203,7 @@ </object> <packing> <property name="left_attach">1</property> - <property name="top_attach">9</property> + <property name="top_attach">7</property> <property name="width">2</property> </packing> </child> @@ -206,12 +211,12 @@ <object class="GtkLabel" id="label_options_recent_items"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Maximum recent items</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">8</property> + <property name="top_attach">6</property> </packing> </child> <child> @@ -223,7 +228,7 @@ </object> <packing> <property name="left_attach">1</property> - <property name="top_attach">8</property> + <property name="top_attach">6</property> </packing> </child> <child> @@ -232,23 +237,22 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_clear_recent" swapped="no"/> </object> <packing> <property name="left_attach">2</property> - <property name="top_attach">8</property> + <property name="top_attach">6</property> </packing> </child> <child> <object class="GtkLabel" id="label_options_resolutions"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Resolutions</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">10</property> + <property name="top_attach">8</property> </packing> </child> <child> @@ -257,11 +261,10 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_on_button_resolutions_clicked" swapped="no"/> </object> <packing> <property name="left_attach">1</property> - <property name="top_attach">10</property> + <property name="top_attach">8</property> <property name="width">2</property> </packing> </child> @@ -269,12 +272,12 @@ <object class="GtkLabel" id="label_options_keystrokes"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Keystrokes</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">11</property> + <property name="top_attach">9</property> </packing> </child> <child> @@ -283,17 +286,16 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_on_button_keystrokes_clicked" swapped="no"/> </object> <packing> <property name="left_attach">1</property> - <property name="top_attach">11</property> + <property name="top_attach">9</property> <property name="width">2</property> </packing> </child> <child> - <object class="GtkCheckButton" id="checkbutton_options_ssh_parseconfig"> - <property name="label" translatable="yes">Parse ~/.ssh/config</property> + <object class="GtkCheckButton" id="checkbutton_options_survey"> + <property name="label" translatable="yes">Activate survey dialog on startup</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> @@ -302,54 +304,35 @@ </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">7</property> + <property name="top_attach">2</property> <property name="width">3</property> </packing> </child> <child> - <object class="GtkComboBoxText" id="comboboxtext_options_ssh_loglevel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="hexpand">True</property> - <items> - <item id="0" translatable="yes">SSH_LOG_NOLOG</item> - <item id="1" translatable="yes">SSH_LOG_RARE</item> - <item id="2" translatable="yes">SSH_LOG_ENTRY</item> - <item id="3" translatable="yes">SSH_LOG_PACKET</item> - <item id="4" translatable="yes">SSH_LOG_FUNCTIONS</item> - </items> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">6</property> - <property name="width">2</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label_options_ssh_loglevel"> + <object class="GtkLabel" id="label_options_screenshot_folder"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="label" translatable="yes">Screenshots folder</property> <property name="xalign">0</property> - <property name="label" translatable="yes">SSH log level</property> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">6</property> + <property name="top_attach">5</property> </packing> </child> <child> - <object class="GtkCheckButton" id="checkbutton_options_survey"> - <property name="label" translatable="yes">Activate survey dialog on startup</property> + <object class="GtkFileChooserButton" id="filechooserbutton_options_screenshots_path"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> + <property name="can_focus">False</property> + <property name="tooltip_text" translatable="yes">Choose the directory where you want to save Remmina screenshots.</property> + <property name="hexpand">True</property> + <property name="action">select-folder</property> + <property name="title" translatable="yes">Select a Directory</property> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> - <property name="width">3</property> + <property name="left_attach">1</property> + <property name="top_attach">5</property> + <property name="width">2</property> </packing> </child> </object> @@ -429,8 +412,8 @@ <object class="GtkLabel" id="label_appearance_view_mode"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Default view mode</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -459,8 +442,8 @@ <object class="GtkLabel" id="label_appearance_tab_interface"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Tab interface</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -489,8 +472,8 @@ <object class="GtkLabel" id="label_appearance_show_buttons_icons"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Show buttons icons</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -519,8 +502,8 @@ <object class="GtkLabel" id="label_appearance_show_menu_icons"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Show menu icons</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -618,7 +601,6 @@ <property name="hexpand">True</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="remmina_pref_dialog_disable_tray_icon_on_toggled" swapped="no"/> </object> <packing> <property name="left_attach">0</property> @@ -679,8 +661,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Host key</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -694,7 +676,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -707,8 +688,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Toggle fullscreen mode</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -722,7 +703,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -735,8 +715,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Auto-fit window</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -750,7 +730,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -763,8 +742,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Switch tab pages</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -778,7 +757,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -792,7 +770,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">2</property> @@ -804,8 +781,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Toggle scaled mode</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -819,7 +796,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -832,8 +808,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Grab keyboard</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -847,7 +823,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -860,8 +835,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Minimize window</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -875,7 +850,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -888,8 +862,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Disconnect</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -903,7 +877,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -916,8 +889,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Show / hide toolbar</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -931,7 +904,6 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -939,6 +911,34 @@ <property name="width">2</property> </packing> </child> + <child> + <object class="GtkLabel" id="label_keyboard_screenshot"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="label" translatable="yes">Screenshot</property> + <property name="ellipsize">start</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">9</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button_keyboard_screenshot"> + <property name="label" translatable="yes">SCREENSHOT</property> + <property name="width_request">100</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">9</property> + <property name="width">2</property> + </packing> + </child> </object> </child> </object> @@ -958,6 +958,108 @@ </packing> </child> <child> + <object class="GtkAlignment" id="alignment_ssh"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="top_padding">4</property> + <property name="bottom_padding">7</property> + <property name="left_padding">7</property> + <property name="right_padding">7</property> + <child> + <object class="GtkGrid" id="grid_ssh"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">5</property> + <property name="column_spacing">7</property> + <child> + <object class="GtkLabel" id="label_options_ssh_port"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">SSH tunnel local port</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="entry_options_ssh_port"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="max_length">5</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="checkbutton_options_ssh_parseconfig"> + <property name="label" translatable="yes">Parse ~/.ssh/config</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">3</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="comboboxtext_options_ssh_loglevel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <items> + <item id="0" translatable="yes">SSH_LOG_NOLOG</item> + <item id="1" translatable="yes">SSH_LOG_RARE</item> + <item id="2" translatable="yes">SSH_LOG_ENTRY</item> + <item id="3" translatable="yes">SSH_LOG_PACKET</item> + <item id="4" translatable="yes">SSH_LOG_FUNCTIONS</item> + </items> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_options_ssh_loglevel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">SSH log level</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">4</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="label_tab_ssh"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">SSH Options</property> + </object> + <packing> + <property name="position">4</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> <object class="GtkAlignment" id="alignment_terminal"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -976,8 +1078,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Font</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -989,8 +1091,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Colors</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -1002,8 +1104,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Foreground color</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -1015,8 +1117,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Background color</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -1028,8 +1130,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Scrollback lines</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -1041,8 +1143,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Keyboard</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">0</property> @@ -1070,7 +1172,6 @@ <property name="hexpand">True</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="remmina_pref_dialog_vte_font_on_toggled" swapped="no"/> </object> <packing> <property name="left_attach">1</property> @@ -1191,8 +1292,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Copy</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> @@ -1218,7 +1319,6 @@ <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="hexpand">False</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">3</property> @@ -1230,8 +1330,8 @@ <property name="visible">True</property> <property name="can_focus">False</property> <property name="hexpand">True</property> - <property name="xalign">0</property> <property name="label" translatable="yes">Paste</property> + <property name="xalign">0</property> </object> <packing> <property name="left_attach">1</property> @@ -1257,7 +1357,6 @@ <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="hexpand">False</property> - <signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/> </object> <packing> <property name="left_attach">3</property> @@ -1268,7 +1367,7 @@ </child> </object> <packing> - <property name="position">4</property> + <property name="position">5</property> </packing> </child> <child type="tab"> @@ -1278,7 +1377,7 @@ <property name="label" translatable="yes">Terminal</property> </object> <packing> - <property name="position">4</property> + <property name="position">5</property> <property name="tab_fill">False</property> </packing> </child> |