~ubuntu-branches/ubuntu/raring/remmina/raring

« back to all changes in this revision

Viewing changes to src/remminaconnectionwindow.c

  • Committer: Package Import Robot
  • Author(s): Luca Falavigna
  • Date: 2012-02-11 17:28:48 UTC
  • mfrom: (1.2.8)
  • Revision ID: package-import@ubuntu.com-20120211172848-rh3ffi7075qyobuq
Tags: 1.0.0-1
* New upstream release.
  - Compatible with FreeRDP 1.0 (Closes: #658363).
  - Ported to GTK3, this also fixes an incompatibility with
    GTK2 and recent Avahi with GTK3 support, which lead to
    crashes when scanning network services (Closes: #626499).
* debian/patches/libvncserver.patch:
  - Do not use convenience copy of libvncserver.
* debian/patches/g_thread_init.patch:
  - Do not use deprecated g_thread_init function.
* debian/patches/REMMINA_COMMAND_NONE.patch:
  - Removed, obsoleted by GApplication port.
* debian/clean:
  - Remove spurious files created at build-time.
* debian/compat:
  - Bump compatibility level to 9.
* debian/control:
  - Refresh build-dependencies to match new structure.
  - Drop remmina-dev package, no longer used.
  - Build packages once provided by remmina-plugins.
  - Provide remmina-common package.
  - Provide remmina-plugin-gnome package.
* debian/copyright:
  - Refresh copyright information.
* debian/docs:
  - Documentation is no longer accurate, do not ship it anymore.
* debian/remmina-dev.install:
  - Drop remmina-dev package, no longer used.
* debian/remmina-plugin-telepathy.install:
  - Adjust location for Remmina.client.
  - Disable D-BUS support for now.
* debian/rules:
  - Compile with -DWITH_APPINDICATOR=OFF.
  - Do not treat plugins as shared libraries.
* debian/watch:
  - Adjust watch file to match new download location.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Remmina - The GTK+ Remote Desktop Client
3
 
 * Copyright (C) 2009-2010 Vic Lee 
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place, Suite 330, 
18
 
 * Boston, MA 02111-1307, USA.
19
 
 */
20
 
 
21
 
#include <gtk/gtk.h>
22
 
#include <gdk/gdkkeysyms.h>
23
 
#include <glib/gi18n.h>
24
 
#include <stdlib.h>
25
 
#include "config.h"
26
 
#include "remminapublic.h"
27
 
#include "remminafile.h"
28
 
#include "remminafilemanager.h"
29
 
#include "remminainitdialog.h"
30
 
#include "remminaprotocolwidget.h"
31
 
#include "remminapref.h"
32
 
#include "remminascrolledviewport.h"
33
 
#include "remminascaler.h"
34
 
#include "remminawidgetpool.h"
35
 
#include "remminaconnectionwindow.h"
36
 
 
37
 
G_DEFINE_TYPE (RemminaConnectionWindow, remmina_connection_window, GTK_TYPE_WINDOW)
38
 
 
39
 
#define MOTION_TIME 100
40
 
 
41
 
/* One process can only have one option popup at a time */
42
 
static GtkWidget *scale_option_window = NULL;
43
 
 
44
 
typedef struct _RemminaConnectionHolder RemminaConnectionHolder;
45
 
 
46
 
struct _RemminaConnectionWindowPriv
47
 
{
48
 
    RemminaConnectionHolder *cnnhld;
49
 
 
50
 
    GtkWidget *notebook;
51
 
 
52
 
    guint switch_page_handler;
53
 
 
54
 
    GtkWidget *floating_toolbar;
55
 
    GtkWidget *floating_toolbar_label;
56
 
    gdouble floating_toolbar_opacity;
57
 
    /* To avoid strange event-loop */
58
 
    guint floating_toolbar_motion_handler;
59
 
 
60
 
    gboolean floating_toolbar_motion_show;
61
 
    gboolean floating_toolbar_motion_visible;
62
 
 
63
 
    GtkWidget *toolbar;
64
 
 
65
 
    /* Toolitems that need to be handled */
66
 
    GtkToolItem *toolitem_autofit;
67
 
    GtkToolItem *toolitem_fullscreen;
68
 
    GtkToolItem *toolitem_switch_page;
69
 
    GtkToolItem *toolitem_scale;
70
 
    GtkToolItem *toolitem_grab;
71
 
    GtkToolItem *toolitem_preferences;
72
 
    GtkToolItem *toolitem_tools;
73
 
    GtkWidget *scale_option_button;
74
 
    GtkWidget *fullscreen_option_button;
75
 
 
76
 
    GtkWidget *pin_button;
77
 
    gboolean pin_down;
78
 
 
79
 
    gboolean sticky;
80
 
 
81
 
    gint view_mode;
82
 
};
83
 
 
84
 
typedef struct _RemminaConnectionObject
85
 
{
86
 
    RemminaConnectionHolder *cnnhld;
87
 
 
88
 
    RemminaFile *remmina_file;
89
 
 
90
 
    /* A dummy window which will be realized as a container during initialize, before reparent to the real window */
91
 
    GtkWidget *window;
92
 
 
93
 
    /* Containers for RemminaProtocolWidget: RemminaProtocolWidget->alignment->viewport...->window */
94
 
    GtkWidget *proto;
95
 
    GtkWidget *alignment;
96
 
    GtkWidget *viewport;
97
 
 
98
 
    /* Scrolled containers */
99
 
    GtkWidget *scrolled_container;
100
 
 
101
 
    gboolean connected;
102
 
} RemminaConnectionObject;
103
 
 
104
 
struct _RemminaConnectionHolder
105
 
{
106
 
    RemminaConnectionWindow *cnnwin;
107
 
    gint fullscreen_view_mode;
108
 
 
109
 
    gboolean hostkey_activated;
110
 
    gboolean hostkey_used;
111
 
};
112
 
 
113
 
#define DECLARE_CNNOBJ \
114
 
    if (!cnnhld || !cnnhld->cnnwin || gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) < 0) return; \
115
 
    RemminaConnectionObject *cnnobj = (RemminaConnectionObject*) g_object_get_data ( \
116
 
        G_OBJECT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), \
117
 
        gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)))), "cnnobj");
118
 
 
119
 
#define DECLARE_CNNOBJ_WITH_RETURN(r) \
120
 
    if (!cnnhld || !cnnhld->cnnwin || gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) < 0) return r; \
121
 
    RemminaConnectionObject *cnnobj = (RemminaConnectionObject*) g_object_get_data ( \
122
 
        G_OBJECT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), \
123
 
        gtk_notebook_get_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)))), "cnnobj");
124
 
 
125
 
static void remmina_connection_holder_create_scrolled (RemminaConnectionHolder *cnnhld, RemminaConnectionObject *cnnobj);
126
 
static void remmina_connection_holder_create_fullscreen (RemminaConnectionHolder *cnnhld, RemminaConnectionObject *cnnobj, gint view_mode);
127
 
 
128
 
static void
129
 
remmina_connection_window_class_init (RemminaConnectionWindowClass *klass)
130
 
{
131
 
    gtk_rc_parse_string (
132
 
        "style \"remmina-small-button-style\"\n"
133
 
        "{\n"
134
 
        "  GtkWidget::focus-padding = 0\n"
135
 
        "  GtkWidget::focus-line-width = 0\n"
136
 
        "  xthickness = 0\n"
137
 
        "  ythickness = 0\n"
138
 
        "}\n"
139
 
        "widget \"*.remmina-small-button\" style \"remmina-small-button-style\"");
140
 
}
141
 
 
142
 
static void
143
 
remmina_connection_holder_disconnect (RemminaConnectionHolder *cnnhld)
144
 
{
145
 
    DECLARE_CNNOBJ
146
 
 
147
 
    /* Notify the RemminaProtocolWidget to disconnect, but not to close the window here.
148
 
       The window will be destroyed in RemminaProtocolWidget "disconnect" signal */
149
 
    remmina_protocol_widget_close_connection (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
150
 
}
151
 
 
152
 
static void
153
 
remmina_connection_holder_keyboard_grab (RemminaConnectionHolder *cnnhld)
154
 
{
155
 
    DECLARE_CNNOBJ
156
 
 
157
 
    if (remmina_file_get_int (cnnobj->remmina_file, "keyboard_grab", FALSE))
158
 
    {
159
 
        gdk_keyboard_grab (gtk_widget_get_window (GTK_WIDGET (cnnhld->cnnwin)), TRUE, GDK_CURRENT_TIME);
160
 
    }
161
 
    else
162
 
    {
163
 
        gdk_keyboard_ungrab (GDK_CURRENT_TIME);
164
 
    }
165
 
}
166
 
 
167
 
static gboolean
168
 
remmina_connection_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
169
 
{
170
 
    RemminaConnectionHolder *cnnhld = (RemminaConnectionHolder*) data;
171
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
172
 
    RemminaConnectionObject *cnnobj;
173
 
    GtkNotebook *notebook = GTK_NOTEBOOK (priv->notebook);
174
 
    GtkWidget *dialog;
175
 
    GtkWidget *w;
176
 
    gint i, n;
177
 
 
178
 
    n = gtk_notebook_get_n_pages (notebook);
179
 
    if (n > 1)
180
 
    {
181
 
        dialog = gtk_message_dialog_new (GTK_WINDOW (cnnhld->cnnwin),
182
 
            GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
183
 
            _("There are %i active connections in the current window. Are you sure to close?"), n);
184
 
        i = gtk_dialog_run (GTK_DIALOG (dialog));
185
 
        gtk_widget_destroy (dialog);
186
 
        if (i != GTK_RESPONSE_YES) return TRUE;
187
 
    }
188
 
    /* Just in case the connection already closed by the server before clicking yes */
189
 
    if (GTK_IS_WIDGET (notebook))
190
 
    {
191
 
        n = gtk_notebook_get_n_pages (notebook);
192
 
        for (i = n - 1; i >= 0; i--)
193
 
        {
194
 
            w = gtk_notebook_get_nth_page (notebook, i);
195
 
            cnnobj = (RemminaConnectionObject*) g_object_get_data (G_OBJECT (w), "cnnobj");
196
 
            remmina_protocol_widget_close_connection (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
197
 
        }
198
 
    }
199
 
    return TRUE;
200
 
}
201
 
 
202
 
static void
203
 
remmina_connection_window_destroy (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
204
 
{
205
 
    RemminaConnectionWindowPriv *priv = REMMINA_CONNECTION_WINDOW (widget)->priv;
206
 
 
207
 
    if (priv->floating_toolbar_motion_handler)
208
 
    {
209
 
        g_source_remove (priv->floating_toolbar_motion_handler);
210
 
        priv->floating_toolbar_motion_handler = 0;
211
 
    }
212
 
    if (priv->floating_toolbar != NULL)
213
 
    {
214
 
        gtk_widget_destroy (priv->floating_toolbar);
215
 
        priv->floating_toolbar = NULL;
216
 
    }
217
 
    if (priv->switch_page_handler)
218
 
    {
219
 
        g_source_remove (priv->switch_page_handler);
220
 
        priv->switch_page_handler = 0;
221
 
    }
222
 
    g_free (priv);
223
 
}
224
 
 
225
 
static void
226
 
remmina_connection_holder_update_toolbar_opacity (RemminaConnectionHolder *cnnhld)
227
 
{
228
 
    DECLARE_CNNOBJ
229
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
230
 
 
231
 
    priv->floating_toolbar_opacity = (1.0 - TOOLBAR_OPACITY_MIN) / ((gdouble) TOOLBAR_OPACITY_LEVEL)
232
 
        * ((gdouble) (TOOLBAR_OPACITY_LEVEL - remmina_file_get_int (cnnobj->remmina_file, "toolbar_opacity", 0)))
233
 
        + TOOLBAR_OPACITY_MIN;
234
 
 
235
 
    if (priv->floating_toolbar)
236
 
    {
237
 
        gtk_window_set_opacity (GTK_WINDOW (priv->floating_toolbar), priv->floating_toolbar_opacity);
238
 
    }
239
 
}
240
 
 
241
 
static gboolean
242
 
remmina_connection_holder_floating_toolbar_motion (RemminaConnectionHolder *cnnhld)
243
 
{
244
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
245
 
    GtkRequisition req;
246
 
    gint x, y, t;
247
 
 
248
 
    if (priv->floating_toolbar == NULL)
249
 
    {
250
 
        priv->floating_toolbar_motion_handler = 0;
251
 
        return FALSE;
252
 
    }
253
 
 
254
 
    gtk_widget_size_request (priv->floating_toolbar, &req);
255
 
    gtk_window_get_position (GTK_WINDOW (priv->floating_toolbar), &x, &y);
256
 
 
257
 
    if (priv->floating_toolbar_motion_show || priv->floating_toolbar_motion_visible)
258
 
    {
259
 
        if (priv->floating_toolbar_motion_show) y += 2; else y -= 2;
260
 
        t = (priv->pin_down ? 18 : 2) - req.height;
261
 
        if (y > 0) y = 0;
262
 
        if (y < t) y = t;
263
 
 
264
 
        gtk_window_move (GTK_WINDOW (priv->floating_toolbar), x, y);
265
 
        if (remmina_pref.invisible_toolbar && !priv->pin_down)
266
 
        {
267
 
            gtk_window_set_opacity (GTK_WINDOW (priv->floating_toolbar), (gdouble)(y - t) / (gdouble)(-t)
268
 
                * priv->floating_toolbar_opacity);
269
 
        }
270
 
        if ((priv->floating_toolbar_motion_show && y >= 0) ||
271
 
            (!priv->floating_toolbar_motion_show && y <= t))
272
 
        {
273
 
            priv->floating_toolbar_motion_handler = 0;
274
 
            return FALSE;
275
 
        }
276
 
    }
277
 
    else
278
 
    {
279
 
        gtk_window_move (GTK_WINDOW (priv->floating_toolbar), x, -20 - req.height);
280
 
        priv->floating_toolbar_motion_handler = 0;
281
 
        return FALSE;
282
 
    }
283
 
    return TRUE;
284
 
}
285
 
 
286
 
static void
287
 
remmina_connection_holder_floating_toolbar_update (RemminaConnectionHolder *cnnhld)
288
 
{
289
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
290
 
 
291
 
    if (priv->floating_toolbar_motion_show || priv->floating_toolbar_motion_visible)
292
 
    {
293
 
        if (priv->floating_toolbar_motion_handler) g_source_remove (priv->floating_toolbar_motion_handler);
294
 
        priv->floating_toolbar_motion_handler = g_idle_add (
295
 
            (GSourceFunc) remmina_connection_holder_floating_toolbar_motion, cnnhld);
296
 
    }
297
 
    else
298
 
    {
299
 
        if (priv->floating_toolbar_motion_handler == 0)
300
 
        {
301
 
            priv->floating_toolbar_motion_handler = g_timeout_add (MOTION_TIME,
302
 
                (GSourceFunc) remmina_connection_holder_floating_toolbar_motion, cnnhld);
303
 
        }
304
 
    }
305
 
}
306
 
 
307
 
static void
308
 
remmina_connection_holder_floating_toolbar_show (RemminaConnectionHolder *cnnhld, gboolean show)
309
 
{
310
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
311
 
 
312
 
    if (priv->floating_toolbar == NULL) return;
313
 
 
314
 
    priv->floating_toolbar_motion_show = show;
315
 
 
316
 
    remmina_connection_holder_floating_toolbar_update (cnnhld);
317
 
}
318
 
 
319
 
static void
320
 
remmina_connection_holder_floating_toolbar_visible (RemminaConnectionHolder *cnnhld, gboolean visible)
321
 
{
322
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
323
 
 
324
 
    if (priv->floating_toolbar == NULL) return;
325
 
 
326
 
    priv->floating_toolbar_motion_visible = visible;
327
 
 
328
 
    remmina_connection_holder_floating_toolbar_update (cnnhld);
329
 
}
330
 
 
331
 
static void
332
 
remmina_connection_holder_get_desktop_size (RemminaConnectionHolder* cnnhld, gint *width, gint *height, gboolean expand)
333
 
{
334
 
    DECLARE_CNNOBJ
335
 
    RemminaFile *remminafile = cnnobj->remmina_file;
336
 
    RemminaProtocolWidget *gp = REMMINA_PROTOCOL_WIDGET (cnnobj->proto);
337
 
    gboolean scale;
338
 
 
339
 
    scale = remmina_protocol_widget_get_scale (gp);
340
 
    *width = remmina_protocol_widget_get_width (gp);
341
 
    if (scale)
342
 
    {
343
 
        if (remmina_file_get_int (remminafile, "hscale", 0) > 0)
344
 
        {
345
 
            *width = (*width) * remmina_file_get_int (remminafile, "hscale", 0) / 100;
346
 
        }
347
 
        else if (!expand)
348
 
        {
349
 
            *width = 1;
350
 
        }
351
 
    }
352
 
    *height = remmina_protocol_widget_get_height (gp);
353
 
    if (scale)
354
 
    {
355
 
        if (remmina_file_get_int (remminafile, "vscale", 0) > 0)
356
 
        {
357
 
            *height = (*height) * remmina_file_get_int (remminafile, "vscale", 0) / 100;
358
 
        }
359
 
        else if (!expand)
360
 
        {
361
 
            *height = 1;
362
 
        }
363
 
    }
364
 
}
365
 
 
366
 
static void
367
 
remmina_connection_object_set_scrolled_policy (RemminaConnectionObject *cnnobj, GtkScrolledWindow *scrolled_window)
368
 
{
369
 
    gboolean expand;
370
 
 
371
 
    expand = remmina_protocol_widget_get_expand (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
372
 
    gtk_scrolled_window_set_policy (scrolled_window,
373
 
        expand ? GTK_POLICY_NEVER : GTK_POLICY_AUTOMATIC,
374
 
        expand ? GTK_POLICY_NEVER : GTK_POLICY_AUTOMATIC);
375
 
}
376
 
 
377
 
static gboolean
378
 
remmina_connection_holder_toolbar_autofit_restore (RemminaConnectionHolder* cnnhld)
379
 
{
380
 
    DECLARE_CNNOBJ_WITH_RETURN (FALSE)
381
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
382
 
    gint width, height;
383
 
 
384
 
    if (cnnobj->connected && GTK_IS_SCROLLED_WINDOW (cnnobj->scrolled_container))
385
 
    {
386
 
        remmina_connection_holder_get_desktop_size (cnnhld, &width, &height, TRUE);
387
 
        gtk_window_resize (GTK_WINDOW (cnnhld->cnnwin),
388
 
            MAX (1, width +
389
 
            priv->notebook->allocation.width - cnnobj->scrolled_container->allocation.width),
390
 
            MAX (1, height + priv->toolbar->allocation.height +
391
 
            priv->notebook->allocation.height - cnnobj->scrolled_container->allocation.height));
392
 
        gtk_container_check_resize (GTK_CONTAINER (cnnhld->cnnwin));
393
 
    }
394
 
    if (GTK_IS_SCROLLED_WINDOW (cnnobj->scrolled_container))
395
 
    {
396
 
        remmina_connection_object_set_scrolled_policy (cnnobj, GTK_SCROLLED_WINDOW (cnnobj->scrolled_container));
397
 
    }
398
 
    return FALSE;
399
 
}
400
 
 
401
 
static void
402
 
remmina_connection_holder_toolbar_autofit (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
403
 
{
404
 
    DECLARE_CNNOBJ
405
 
 
406
 
    if (GTK_IS_SCROLLED_WINDOW (cnnobj->scrolled_container))
407
 
    {
408
 
        if ((gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (cnnhld->cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) != 0)
409
 
        {
410
 
            gtk_window_unmaximize (GTK_WINDOW (cnnhld->cnnwin));
411
 
        }
412
 
 
413
 
        /* It's tricky to make the toolbars disappear automatically, while keeping scrollable.
414
 
           Please tell me if you know a better way to do this */
415
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cnnobj->scrolled_container),
416
 
            GTK_POLICY_NEVER, GTK_POLICY_NEVER);
417
 
 
418
 
        g_timeout_add (200, (GSourceFunc) remmina_connection_holder_toolbar_autofit_restore, cnnhld);
419
 
    }
420
 
 
421
 
}
422
 
 
423
 
static void
424
 
remmina_connection_object_init_adjustment (RemminaConnectionObject *cnnobj)
425
 
{
426
 
    GdkScreen *screen;
427
 
    GtkAdjustment *adj;
428
 
    gint screen_width, screen_height;
429
 
 
430
 
    screen = gdk_screen_get_default ();
431
 
    screen_width = gdk_screen_get_width (screen);
432
 
    screen_height = gdk_screen_get_height (screen);
433
 
 
434
 
    adj = gtk_viewport_get_hadjustment (GTK_VIEWPORT (cnnobj->viewport));
435
 
    gtk_adjustment_set_page_size (adj, screen_width);
436
 
    adj = gtk_viewport_get_vadjustment (GTK_VIEWPORT (cnnobj->viewport));
437
 
    gtk_adjustment_set_page_size (adj, screen_height);
438
 
}
439
 
 
440
 
static void
441
 
remmina_connection_holder_check_resize (RemminaConnectionHolder *cnnhld)
442
 
{
443
 
    DECLARE_CNNOBJ
444
 
    gboolean scroll_required = FALSE;
445
 
    GdkScreen *screen;
446
 
    gint screen_width, screen_height;
447
 
    gint server_width, server_height;
448
 
 
449
 
    remmina_connection_holder_get_desktop_size (cnnhld, &server_width, &server_height, FALSE);
450
 
    screen = gdk_screen_get_default ();
451
 
    screen_width = gdk_screen_get_width (screen);
452
 
    screen_height = gdk_screen_get_height (screen);
453
 
 
454
 
    if (!remmina_protocol_widget_get_expand (REMMINA_PROTOCOL_WIDGET (cnnobj->proto)) &&
455
 
        (server_width <= 0 || server_height <= 0 || screen_width < server_width || screen_height < server_height))
456
 
    {
457
 
        scroll_required = TRUE;
458
 
    }
459
 
 
460
 
    switch (cnnhld->cnnwin->priv->view_mode)
461
 
    {
462
 
 
463
 
    case SCROLLED_FULLSCREEN_MODE:
464
 
        gtk_window_resize (GTK_WINDOW (cnnhld->cnnwin), screen_width, screen_height);
465
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cnnobj->scrolled_container),
466
 
            (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER),
467
 
            (scroll_required ? GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER));
468
 
        break;
469
 
 
470
 
    case VIEWPORT_FULLSCREEN_MODE:
471
 
        gtk_window_resize (GTK_WINDOW (cnnhld->cnnwin), screen_width, screen_height);
472
 
        gtk_container_set_border_width (GTK_CONTAINER (cnnhld->cnnwin), scroll_required ? 1 : 0);
473
 
        break;
474
 
 
475
 
    case SCROLLED_WINDOW_MODE:
476
 
        if (remmina_file_get_int (cnnobj->remmina_file, "viewmode", AUTO_MODE) == AUTO_MODE)
477
 
        {
478
 
            gtk_window_set_default_size (GTK_WINDOW (cnnhld->cnnwin),
479
 
                MIN (server_width, screen_width), MIN (server_height, screen_height));
480
 
            if (server_width >= screen_width ||
481
 
                server_height >= screen_height)
482
 
            {
483
 
                gtk_window_maximize (GTK_WINDOW (cnnhld->cnnwin));
484
 
                remmina_file_set_int (cnnobj->remmina_file, "window_maximize", TRUE);
485
 
            }
486
 
            else
487
 
            {
488
 
                remmina_connection_holder_toolbar_autofit (NULL, cnnhld);
489
 
                remmina_file_set_int (cnnobj->remmina_file, "window_maximize", FALSE);
490
 
            }
491
 
        }
492
 
        else
493
 
        {
494
 
            gtk_window_set_default_size (GTK_WINDOW (cnnhld->cnnwin),
495
 
                remmina_file_get_int (cnnobj->remmina_file, "window_width", 640),
496
 
                remmina_file_get_int (cnnobj->remmina_file, "window_height", 480));
497
 
            if (remmina_file_get_int (cnnobj->remmina_file, "window_maximize", FALSE))
498
 
            {
499
 
                gtk_window_maximize (GTK_WINDOW (cnnhld->cnnwin));
500
 
            }
501
 
        }
502
 
        break;
503
 
 
504
 
    default:
505
 
        break;
506
 
    }
507
 
}
508
 
 
509
 
static void
510
 
remmina_connection_holder_toolbar_fullscreen (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
511
 
{
512
 
    if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget)))
513
 
    {
514
 
        remmina_connection_holder_create_fullscreen (cnnhld, NULL, cnnhld->fullscreen_view_mode);
515
 
    }
516
 
    else
517
 
    {
518
 
        remmina_connection_holder_create_scrolled (cnnhld, NULL);
519
 
    }
520
 
}
521
 
 
522
 
static void
523
 
remmina_connection_holder_viewport_fullscreen_mode (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
524
 
{
525
 
    if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) return;
526
 
    cnnhld->fullscreen_view_mode = VIEWPORT_FULLSCREEN_MODE;
527
 
    remmina_connection_holder_create_fullscreen (cnnhld, NULL, cnnhld->fullscreen_view_mode);
528
 
}
529
 
 
530
 
static void
531
 
remmina_connection_holder_scrolled_fullscreen_mode (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
532
 
{
533
 
    if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) return;
534
 
    cnnhld->fullscreen_view_mode = SCROLLED_FULLSCREEN_MODE;
535
 
    remmina_connection_holder_create_fullscreen (cnnhld, NULL, cnnhld->fullscreen_view_mode);
536
 
}
537
 
 
538
 
static void
539
 
remmina_connection_holder_fullscreen_option_popdown (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
540
 
{
541
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
542
 
 
543
 
    priv->sticky = FALSE;
544
 
 
545
 
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->fullscreen_option_button), FALSE);
546
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
547
 
}
548
 
 
549
 
static void
550
 
remmina_connection_holder_toolbar_fullscreen_option (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
551
 
{
552
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
553
 
    GtkWidget *menu;
554
 
    GtkWidget *menuitem;
555
 
    GSList *group;
556
 
  
557
 
    if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) return;
558
 
 
559
 
    priv->sticky = TRUE;
560
 
 
561
 
    menu = gtk_menu_new ();
562
 
 
563
 
    menuitem = gtk_radio_menu_item_new_with_label (NULL, _("Viewport fullscreen mode"));
564
 
    gtk_widget_show (menuitem);
565
 
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
566
 
    group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
567
 
    if (priv->view_mode == VIEWPORT_FULLSCREEN_MODE)
568
 
    {
569
 
        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
570
 
    }
571
 
    g_signal_connect (G_OBJECT (menuitem), "toggled",
572
 
        G_CALLBACK (remmina_connection_holder_viewport_fullscreen_mode), cnnhld);
573
 
 
574
 
    menuitem = gtk_radio_menu_item_new_with_label (group, _("Scrolled fullscreen mode"));
575
 
    gtk_widget_show (menuitem);
576
 
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
577
 
    if (priv->view_mode == SCROLLED_FULLSCREEN_MODE)
578
 
    {
579
 
        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
580
 
    }
581
 
    g_signal_connect (G_OBJECT (menuitem), "toggled",
582
 
        G_CALLBACK (remmina_connection_holder_scrolled_fullscreen_mode), cnnhld);
583
 
 
584
 
    g_signal_connect (G_OBJECT (menu), "deactivate",
585
 
        G_CALLBACK (remmina_connection_holder_fullscreen_option_popdown), cnnhld);
586
 
 
587
 
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
588
 
        remmina_public_popup_position, priv->toolitem_fullscreen,
589
 
        0, gtk_get_current_event_time());
590
 
}
591
 
 
592
 
static void
593
 
remmina_connection_holder_update_alignment (RemminaConnectionHolder* cnnhld)
594
 
{
595
 
    DECLARE_CNNOBJ
596
 
    RemminaProtocolWidget *gp = REMMINA_PROTOCOL_WIDGET (cnnobj->proto);
597
 
    RemminaFile *remminafile = cnnobj->remmina_file;
598
 
    gboolean scale, expand;
599
 
    gint gp_width, gp_height;
600
 
    gint width, height;
601
 
 
602
 
    scale = remmina_protocol_widget_get_scale (gp);
603
 
    expand = remmina_protocol_widget_get_expand (gp);
604
 
    gp_width = remmina_protocol_widget_get_width (gp);
605
 
    gp_height = remmina_protocol_widget_get_height (gp);
606
 
 
607
 
    if (scale &&
608
 
        remmina_file_get_int (remminafile, "aspectscale", FALSE) &&
609
 
        remmina_file_get_int (remminafile, "hscale", 0) == 0)
610
 
    {
611
 
        width = cnnobj->alignment->allocation.width;
612
 
        height = cnnobj->alignment->allocation.height;
613
 
        if (width > 1 && height > 1)
614
 
        {
615
 
            if (gp_width * height >= width * gp_height)
616
 
            {
617
 
                gtk_alignment_set (GTK_ALIGNMENT (cnnobj->alignment), 0.5, 0.5,
618
 
                    1.0,
619
 
                    (gfloat) (gp_height * width) / (gfloat) gp_width / (gfloat) height);
620
 
            }
621
 
            else
622
 
            {
623
 
                gtk_alignment_set (GTK_ALIGNMENT (cnnobj->alignment), 0.5, 0.5,
624
 
                    (gfloat) (gp_width * height) / (gfloat) gp_height / (gfloat) width,
625
 
                    1.0);
626
 
            }
627
 
        }
628
 
    }
629
 
    else
630
 
    {
631
 
        gtk_alignment_set (GTK_ALIGNMENT (cnnobj->alignment), 0.5, 0.5,
632
 
            ((scale && remmina_file_get_int (remminafile, "hscale", 0) == 0) || expand ? 1.0 : 0.0),
633
 
            ((scale && remmina_file_get_int (remminafile, "vscale", 0) == 0) || expand ? 1.0 : 0.0));
634
 
    }
635
 
}
636
 
 
637
 
static void
638
 
remmina_connection_holder_switch_page_activate (GtkMenuItem *menuitem, RemminaConnectionHolder *cnnhld)
639
 
{
640
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
641
 
    gint page_num;
642
 
 
643
 
    page_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "new-page-num"));
644
 
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), page_num);
645
 
}
646
 
 
647
 
static void
648
 
remmina_connection_holder_toolbar_switch_page_popdown (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
649
 
{
650
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
651
 
 
652
 
    priv->sticky = FALSE;
653
 
 
654
 
    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_switch_page), FALSE);
655
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
656
 
}
657
 
 
658
 
static void
659
 
remmina_connection_holder_toolbar_switch_page (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
660
 
{
661
 
    RemminaConnectionObject *cnnobj;
662
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
663
 
    GtkWidget *menu;
664
 
    GtkWidget *menuitem;
665
 
    GtkWidget *image;
666
 
    GtkWidget *page;
667
 
    gint i, n;
668
 
 
669
 
    if (!gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget))) return;
670
 
 
671
 
    priv->sticky = TRUE;
672
 
 
673
 
    menu = gtk_menu_new ();
674
 
 
675
 
    n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
676
 
    for (i = 0; i < n; i++)
677
 
    {
678
 
        page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), i);
679
 
        if (!page) break;
680
 
        cnnobj = (RemminaConnectionObject*) g_object_get_data (G_OBJECT (page), "cnnobj");
681
 
 
682
 
        menuitem = gtk_image_menu_item_new_with_label (remmina_file_get_string (cnnobj->remmina_file, "name"));
683
 
        gtk_widget_show (menuitem);
684
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
685
 
 
686
 
        image = gtk_image_new_from_icon_name (remmina_file_get_icon_name (cnnobj->remmina_file), GTK_ICON_SIZE_MENU);
687
 
        gtk_widget_show (image);
688
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
689
 
 
690
 
        g_object_set_data (G_OBJECT (menuitem), "new-page-num", GINT_TO_POINTER (i));
691
 
        g_signal_connect (G_OBJECT (menuitem), "activate",
692
 
            G_CALLBACK (remmina_connection_holder_switch_page_activate), cnnhld);
693
 
        if (i == gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)))
694
 
        {
695
 
            gtk_widget_set_sensitive (menuitem, FALSE);
696
 
        }
697
 
    }
698
 
 
699
 
    g_signal_connect (G_OBJECT (menu), "deactivate",
700
 
        G_CALLBACK (remmina_connection_holder_toolbar_switch_page_popdown), cnnhld);
701
 
 
702
 
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
703
 
        remmina_public_popup_position, widget,
704
 
        0, gtk_get_current_event_time());
705
 
}
706
 
 
707
 
static void
708
 
remmina_connection_holder_toolbar_scaled_mode (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
709
 
{
710
 
    DECLARE_CNNOBJ
711
 
    gboolean scale;
712
 
 
713
 
    remmina_connection_holder_update_alignment (cnnhld);
714
 
 
715
 
    scale = gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget));
716
 
    gtk_widget_set_sensitive (GTK_WIDGET (cnnhld->cnnwin->priv->scale_option_button), scale);
717
 
    remmina_protocol_widget_set_scale (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), scale);
718
 
    remmina_file_set_int (cnnobj->remmina_file, "scale", scale);
719
 
 
720
 
    remmina_protocol_widget_call_feature_by_type (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
721
 
        REMMINA_PROTOCOL_FEATURE_TYPE_SCALE, 0);
722
 
    if (cnnhld->cnnwin->priv->view_mode != SCROLLED_WINDOW_MODE)
723
 
    {
724
 
        remmina_connection_holder_check_resize (cnnhld);
725
 
    }
726
 
}
727
 
 
728
 
static void
729
 
remmina_connection_holder_scale_option_on_scaled (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
730
 
{
731
 
    DECLARE_CNNOBJ
732
 
 
733
 
    remmina_file_set_int (cnnobj->remmina_file, "hscale", REMMINA_SCALER (widget)->hscale);
734
 
    remmina_file_set_int (cnnobj->remmina_file, "vscale", REMMINA_SCALER (widget)->vscale);
735
 
    remmina_file_set_int (cnnobj->remmina_file, "aspectscale", REMMINA_SCALER (widget)->aspectscale);
736
 
    remmina_connection_holder_update_alignment (cnnhld);
737
 
    remmina_protocol_widget_call_feature_by_type (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
738
 
        REMMINA_PROTOCOL_FEATURE_TYPE_SCALE, 0);
739
 
    if (cnnhld->cnnwin->priv->view_mode != SCROLLED_WINDOW_MODE)
740
 
    {
741
 
        remmina_connection_holder_check_resize (cnnhld);
742
 
    }
743
 
}
744
 
 
745
 
static void
746
 
remmina_connection_holder_scale_option_popdown (RemminaConnectionHolder* cnnhld)
747
 
{
748
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
749
 
 
750
 
    priv->sticky = FALSE;
751
 
 
752
 
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->scale_option_button), FALSE);
753
 
 
754
 
    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
755
 
    gdk_pointer_ungrab (GDK_CURRENT_TIME);
756
 
    if (scale_option_window)
757
 
    {
758
 
        gtk_grab_remove (scale_option_window);
759
 
        gtk_widget_destroy (scale_option_window);
760
 
        scale_option_window = NULL;
761
 
    }
762
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
763
 
}
764
 
 
765
 
static gboolean
766
 
remmina_connection_holder_trap_on_button (GtkWidget *widget, GdkEventButton *event, gpointer data)
767
 
{
768
 
    return TRUE;
769
 
}
770
 
 
771
 
static gboolean
772
 
remmina_connection_holder_scale_option_on_key (GtkWidget *widget, GdkEventKey *event, RemminaConnectionHolder* cnnhld)
773
 
{
774
 
    switch (event->keyval)
775
 
    {
776
 
    case GDK_Escape:
777
 
        remmina_connection_holder_scale_option_popdown (cnnhld);
778
 
        return TRUE;
779
 
    }
780
 
    return FALSE;
781
 
}
782
 
 
783
 
static gboolean
784
 
remmina_connection_holder_scale_option_on_button (GtkWidget *widget, GdkEventButton *event, RemminaConnectionHolder* cnnhld)
785
 
{
786
 
    remmina_connection_holder_scale_option_popdown (cnnhld);
787
 
    return TRUE;
788
 
}
789
 
 
790
 
static void
791
 
remmina_connection_holder_toolbar_scale_option (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
792
 
{
793
 
    DECLARE_CNNOBJ
794
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
795
 
    RemminaFile *remminafile = cnnobj->remmina_file;
796
 
    GtkWidget *window;
797
 
    GtkWidget *eventbox;
798
 
    GtkWidget *frame;
799
 
    GtkWidget *scaler;
800
 
    gint x, y;
801
 
    gboolean pushin;
802
 
 
803
 
    if (scale_option_window)
804
 
    {
805
 
        remmina_connection_holder_scale_option_popdown (cnnhld);
806
 
    }
807
 
    else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
808
 
    {
809
 
        window = gtk_window_new (GTK_WINDOW_POPUP);
810
 
        gtk_container_set_border_width (GTK_CONTAINER (window), 0);
811
 
 
812
 
        /* Use an event-box to trap all button clicks events before sending up to the window */
813
 
        eventbox = gtk_event_box_new ();
814
 
        gtk_widget_show (eventbox);
815
 
        gtk_container_add (GTK_CONTAINER (window), eventbox);
816
 
        gtk_widget_add_events (eventbox, GDK_BUTTON_PRESS_MASK);
817
 
        g_signal_connect (G_OBJECT (eventbox), "button-press-event",
818
 
            G_CALLBACK (remmina_connection_holder_trap_on_button), NULL);
819
 
 
820
 
        frame = gtk_frame_new (NULL);
821
 
        gtk_widget_show (frame);
822
 
        gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
823
 
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
824
 
        gtk_container_add (GTK_CONTAINER (eventbox), frame);
825
 
 
826
 
        scaler = remmina_scaler_new ();
827
 
        gtk_widget_show (scaler);
828
 
        gtk_widget_set_size_request (scaler, 250, -1);
829
 
        gtk_container_set_border_width (GTK_CONTAINER (scaler), 4);
830
 
        remmina_scaler_set (REMMINA_SCALER (scaler),
831
 
            remmina_file_get_int (remminafile, "hscale", 0),
832
 
            remmina_file_get_int (remminafile, "vscale", 0),
833
 
            remmina_file_get_int (remminafile, "aspectscale", FALSE));
834
 
        remmina_scaler_set_draw_value (REMMINA_SCALER (scaler), FALSE);
835
 
        gtk_container_add (GTK_CONTAINER (frame), scaler);
836
 
        g_signal_connect (G_OBJECT (scaler), "scaled",
837
 
            G_CALLBACK (remmina_connection_holder_scale_option_on_scaled), cnnhld);
838
 
 
839
 
        g_signal_connect (G_OBJECT (window), "key-press-event",
840
 
            G_CALLBACK (remmina_connection_holder_scale_option_on_key), cnnhld);
841
 
        g_signal_connect (G_OBJECT (window), "button-press-event",
842
 
            G_CALLBACK (remmina_connection_holder_scale_option_on_button), cnnhld);
843
 
 
844
 
        gtk_widget_realize (window);
845
 
        remmina_public_popup_position (NULL, &x, &y, &pushin, priv->toolitem_scale);
846
 
        gtk_window_move (GTK_WINDOW (window), x, y);
847
 
        gtk_widget_show (window);
848
 
 
849
 
        gtk_grab_add (window);
850
 
        gdk_pointer_grab (window->window, TRUE,
851
 
            GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
852
 
            NULL, NULL, GDK_CURRENT_TIME);
853
 
        gdk_keyboard_grab (window->window, TRUE, GDK_CURRENT_TIME);
854
 
 
855
 
        scale_option_window = window;
856
 
        priv->sticky = TRUE;
857
 
    }
858
 
}
859
 
 
860
 
static void
861
 
remmina_connection_holder_toolbar_preferences_popdown (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
862
 
{
863
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
864
 
 
865
 
    priv->sticky = FALSE;
866
 
 
867
 
    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_preferences), FALSE);
868
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
869
 
}
870
 
 
871
 
static void
872
 
remmina_connection_holder_toolbar_tools_popdown (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
873
 
{
874
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
875
 
 
876
 
    priv->sticky = FALSE;
877
 
 
878
 
    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_tools), FALSE);
879
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
880
 
}
881
 
 
882
 
static void
883
 
remmina_connection_holder_call_protocol_feature_radio (GtkMenuItem *menuitem, RemminaConnectionHolder *cnnhld)
884
 
{
885
 
    DECLARE_CNNOBJ
886
 
    RemminaProtocolFeature *feature;
887
 
    gpointer value;
888
 
 
889
 
    if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)))
890
 
    {
891
 
        feature = (RemminaProtocolFeature*) g_object_get_data (G_OBJECT (menuitem), "feature-type");
892
 
        value = g_object_get_data (G_OBJECT (menuitem), "feature-value");
893
 
 
894
 
        remmina_file_set_string (cnnobj->remmina_file, (const gchar*) feature->opt2, (const gchar*) value);
895
 
        remmina_protocol_widget_call_feature_by_ref (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), feature);
896
 
    }
897
 
}
898
 
 
899
 
static void
900
 
remmina_connection_holder_call_protocol_feature_check (GtkMenuItem *menuitem, RemminaConnectionHolder *cnnhld)
901
 
{
902
 
    DECLARE_CNNOBJ
903
 
    RemminaProtocolFeature *feature;
904
 
    gboolean value;
905
 
 
906
 
    feature = (RemminaProtocolFeature*) g_object_get_data (G_OBJECT (menuitem), "feature-type");
907
 
    value = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem));
908
 
    remmina_file_set_int (cnnobj->remmina_file, (const gchar*) feature->opt2, value);
909
 
    remmina_protocol_widget_call_feature_by_ref (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), feature);
910
 
}
911
 
 
912
 
static void
913
 
remmina_connection_holder_call_protocol_feature_activate (GtkMenuItem *menuitem, RemminaConnectionHolder *cnnhld)
914
 
{
915
 
    DECLARE_CNNOBJ
916
 
    RemminaProtocolFeature *feature;
917
 
 
918
 
    feature = (RemminaProtocolFeature*) g_object_get_data (G_OBJECT (menuitem), "feature-type");
919
 
    remmina_protocol_widget_call_feature_by_ref (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), feature);
920
 
}
921
 
 
922
 
static void
923
 
remmina_connection_holder_toolbar_preferences_radio (RemminaConnectionHolder *cnnhld,
924
 
    RemminaFile *remminafile, GtkWidget *menu, const RemminaProtocolFeature *feature, const gchar *domain, gboolean enabled)
925
 
{
926
 
    GtkWidget *menuitem;
927
 
    GSList *group;
928
 
    gint i;
929
 
    const gchar **list;
930
 
    const gchar *value;
931
 
 
932
 
    group = NULL;
933
 
    value = remmina_file_get_string (remminafile, (const gchar*) feature->opt2);
934
 
    list = (const gchar**) feature->opt3;
935
 
    for (i = 0; list[i]; i += 2)
936
 
    {
937
 
        menuitem = gtk_radio_menu_item_new_with_label (group, g_dgettext (domain, list[i + 1]));
938
 
        group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
939
 
        gtk_widget_show (menuitem);
940
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
941
 
 
942
 
        if (enabled)
943
 
        {
944
 
            g_object_set_data (G_OBJECT (menuitem), "feature-type", (gpointer) feature);
945
 
            g_object_set_data (G_OBJECT (menuitem), "feature-value", (gpointer) list[i]);
946
 
 
947
 
            if (value && g_strcmp0 (list[i], value) == 0)
948
 
            {
949
 
                gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
950
 
            }
951
 
 
952
 
            g_signal_connect (G_OBJECT (menuitem), "toggled",
953
 
                G_CALLBACK (remmina_connection_holder_call_protocol_feature_radio), cnnhld);
954
 
        }
955
 
        else
956
 
        {
957
 
            gtk_widget_set_sensitive (menuitem, FALSE);
958
 
        }
959
 
    }
960
 
}
961
 
 
962
 
static void
963
 
remmina_connection_holder_toolbar_preferences_check (RemminaConnectionHolder *cnnhld,
964
 
    RemminaFile *remminafile, GtkWidget *menu, const RemminaProtocolFeature *feature, const gchar *domain, gboolean enabled)
965
 
{
966
 
    GtkWidget *menuitem;
967
 
 
968
 
    menuitem = gtk_check_menu_item_new_with_label (g_dgettext (domain, (const gchar*) feature->opt3));
969
 
    gtk_widget_show (menuitem);
970
 
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
971
 
 
972
 
    if (enabled)
973
 
    {
974
 
        g_object_set_data (G_OBJECT (menuitem), "feature-type", (gpointer) feature);
975
 
 
976
 
        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
977
 
            remmina_file_get_int (remminafile, (const gchar*) feature->opt2, FALSE));
978
 
 
979
 
        g_signal_connect (G_OBJECT (menuitem), "toggled",
980
 
            G_CALLBACK (remmina_connection_holder_call_protocol_feature_check), cnnhld);
981
 
    }
982
 
    else
983
 
    {
984
 
        gtk_widget_set_sensitive (menuitem, FALSE);
985
 
    }
986
 
}
987
 
 
988
 
static void
989
 
remmina_connection_holder_toolbar_preferences (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
990
 
{
991
 
    DECLARE_CNNOBJ
992
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
993
 
    const RemminaProtocolFeature *feature;
994
 
    GtkWidget *menu;
995
 
    GtkWidget *menuitem;
996
 
    gboolean separator;
997
 
    const gchar *domain;
998
 
    gboolean enabled;
999
 
 
1000
 
    if (!gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget))) return;
1001
 
 
1002
 
    priv->sticky = TRUE;
1003
 
 
1004
 
    separator = FALSE;
1005
 
 
1006
 
    domain = remmina_protocol_widget_get_domain (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
1007
 
    menu = gtk_menu_new ();
1008
 
    for (feature = remmina_protocol_widget_get_features (REMMINA_PROTOCOL_WIDGET (cnnobj->proto)); feature && feature->type; feature++)
1009
 
    {
1010
 
        if (feature->type != REMMINA_PROTOCOL_FEATURE_TYPE_PREF) continue;
1011
 
 
1012
 
        if (separator)
1013
 
        {
1014
 
            menuitem = gtk_separator_menu_item_new ();
1015
 
            gtk_widget_show (menuitem);
1016
 
            gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1017
 
            separator = FALSE;
1018
 
        }
1019
 
        enabled = remmina_protocol_widget_query_feature_by_ref (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), feature);
1020
 
        switch (GPOINTER_TO_INT (feature->opt1))
1021
 
        {
1022
 
        case REMMINA_PROTOCOL_FEATURE_PREF_RADIO:
1023
 
            remmina_connection_holder_toolbar_preferences_radio (cnnhld, cnnobj->remmina_file, menu, feature, domain, enabled);
1024
 
            separator = TRUE;
1025
 
            break;
1026
 
        case REMMINA_PROTOCOL_FEATURE_PREF_CHECK:
1027
 
            remmina_connection_holder_toolbar_preferences_check (cnnhld, cnnobj->remmina_file, menu, feature, domain, enabled);
1028
 
            break;
1029
 
        }
1030
 
    }
1031
 
 
1032
 
    g_signal_connect (G_OBJECT (menu), "deactivate",
1033
 
        G_CALLBACK (remmina_connection_holder_toolbar_preferences_popdown), cnnhld);
1034
 
 
1035
 
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1036
 
        remmina_public_popup_position, widget,
1037
 
        0, gtk_get_current_event_time ());
1038
 
}
1039
 
 
1040
 
static void
1041
 
remmina_connection_holder_toolbar_tools (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
1042
 
{
1043
 
    DECLARE_CNNOBJ
1044
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1045
 
    const RemminaProtocolFeature *feature;
1046
 
    GtkWidget *menu;
1047
 
    GtkWidget *menuitem;
1048
 
    GtkWidget *image;
1049
 
    const gchar *domain;
1050
 
    gboolean enabled;
1051
 
 
1052
 
    if (!gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget))) return;
1053
 
 
1054
 
    priv->sticky = TRUE;
1055
 
 
1056
 
    domain = remmina_protocol_widget_get_domain (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
1057
 
    menu = gtk_menu_new ();
1058
 
    for (feature = remmina_protocol_widget_get_features (REMMINA_PROTOCOL_WIDGET (cnnobj->proto)); feature && feature->type; feature++)
1059
 
    {
1060
 
        if (feature->type != REMMINA_PROTOCOL_FEATURE_TYPE_TOOL) continue;
1061
 
 
1062
 
        if (feature->opt1)
1063
 
        {
1064
 
            menuitem = gtk_image_menu_item_new_with_label (g_dgettext (domain, (const gchar*) feature->opt1));
1065
 
            if (feature->opt2)
1066
 
            {
1067
 
                image = gtk_image_new_from_icon_name ((const gchar*) feature->opt2, GTK_ICON_SIZE_MENU);
1068
 
                gtk_widget_show (image);
1069
 
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
1070
 
            }
1071
 
        }
1072
 
        else
1073
 
        {
1074
 
            menuitem = gtk_image_menu_item_new_from_stock ((const gchar*) feature->opt2, NULL);
1075
 
        }
1076
 
        gtk_widget_show (menuitem);
1077
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1078
 
 
1079
 
        enabled = remmina_protocol_widget_query_feature_by_ref (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), feature);
1080
 
        if (enabled)
1081
 
        {
1082
 
            g_object_set_data (G_OBJECT (menuitem), "feature-type", (gpointer) feature);
1083
 
 
1084
 
            g_signal_connect (G_OBJECT (menuitem), "activate",
1085
 
                G_CALLBACK (remmina_connection_holder_call_protocol_feature_activate), cnnhld);
1086
 
        }
1087
 
        else
1088
 
        {
1089
 
            gtk_widget_set_sensitive (menuitem, FALSE);
1090
 
        }
1091
 
    }
1092
 
 
1093
 
    g_signal_connect (G_OBJECT (menu), "deactivate",
1094
 
        G_CALLBACK (remmina_connection_holder_toolbar_tools_popdown), cnnhld);
1095
 
 
1096
 
    gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1097
 
        remmina_public_popup_position, widget,
1098
 
        0, gtk_get_current_event_time());
1099
 
}
1100
 
 
1101
 
static void
1102
 
remmina_connection_holder_toolbar_minimize (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
1103
 
{
1104
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
1105
 
    gtk_window_iconify (GTK_WINDOW (cnnhld->cnnwin));
1106
 
}
1107
 
 
1108
 
static void
1109
 
remmina_connection_holder_toolbar_disconnect (GtkWidget *widget, RemminaConnectionHolder* cnnhld)
1110
 
{
1111
 
    remmina_connection_holder_disconnect (cnnhld);
1112
 
}
1113
 
 
1114
 
static void
1115
 
remmina_connection_holder_toolbar_grab (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
1116
 
{
1117
 
    DECLARE_CNNOBJ
1118
 
 
1119
 
    remmina_file_set_int (cnnobj->remmina_file, "keyboard_grab",
1120
 
        gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget)));
1121
 
    remmina_connection_holder_keyboard_grab (cnnhld);
1122
 
}
1123
 
 
1124
 
static void
1125
 
remmina_connection_holder_set_tooltip (GtkToolItem *toolitem, const gchar *tip, guint key1, guint key2)
1126
 
{
1127
 
    gchar *s1, *s2;
1128
 
 
1129
 
    if (remmina_pref.hostkey && key1)
1130
 
    {
1131
 
        if (key2)
1132
 
        {
1133
 
            s1 = g_strdup_printf (" (%s + %s,%s)", gdk_keyval_name (remmina_pref.hostkey),
1134
 
                gdk_keyval_name (gdk_keyval_to_upper (key1)), gdk_keyval_name (gdk_keyval_to_upper (key2)));
1135
 
        }
1136
 
        else if (key1 == remmina_pref.hostkey)
1137
 
        {
1138
 
            s1 = g_strdup_printf (" (%s)", gdk_keyval_name (remmina_pref.hostkey));
1139
 
        }
1140
 
        else
1141
 
        {
1142
 
            s1 = g_strdup_printf (" (%s + %s)", gdk_keyval_name (remmina_pref.hostkey),
1143
 
                gdk_keyval_name (gdk_keyval_to_upper (key1)));
1144
 
        }
1145
 
    }
1146
 
    else
1147
 
    {
1148
 
        s1 = NULL;
1149
 
    }
1150
 
    s2 = g_strdup_printf ("%s%s", tip, s1 ? s1 : "");
1151
 
    gtk_tool_item_set_tooltip_text (toolitem, s2);
1152
 
    g_free (s2);
1153
 
    g_free (s1);
1154
 
}
1155
 
 
1156
 
static GtkWidget*
1157
 
remmina_connection_holder_create_toolbar (RemminaConnectionHolder *cnnhld, gint mode)
1158
 
{
1159
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1160
 
    GtkWidget *toolbar;
1161
 
    GtkToolItem *toolitem;
1162
 
    GtkWidget *widget;
1163
 
    GtkWidget *arrow;
1164
 
 
1165
 
    toolbar = gtk_toolbar_new ();
1166
 
    gtk_widget_show (toolbar);
1167
 
    gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
1168
 
    gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
1169
 
    if (remmina_pref.small_toolbutton)
1170
 
    {
1171
 
        gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
1172
 
    }
1173
 
 
1174
 
    /* Auto-Fit */
1175
 
    toolitem = gtk_tool_button_new (NULL, NULL);
1176
 
    gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (toolitem), "remmina-fit-window");
1177
 
    remmina_connection_holder_set_tooltip (toolitem, _("Resize the window to fit in remote resolution"),
1178
 
        remmina_pref.shortcutkey_autofit, 0);
1179
 
    g_signal_connect (G_OBJECT (toolitem), "clicked",
1180
 
        G_CALLBACK (remmina_connection_holder_toolbar_autofit), cnnhld);
1181
 
    priv->toolitem_autofit = toolitem;
1182
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1183
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1184
 
 
1185
 
    /* Fullscreen toggle */
1186
 
    toolitem = gtk_toggle_tool_button_new ();
1187
 
    gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (toolitem), "remmina-fullscreen");
1188
 
    remmina_connection_holder_set_tooltip (toolitem, _("Toggle fullscreen mode"),
1189
 
        remmina_pref.shortcutkey_fullscreen, 0);
1190
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1191
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1192
 
    priv->toolitem_fullscreen = toolitem;
1193
 
    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (toolitem),
1194
 
        mode != SCROLLED_WINDOW_MODE);
1195
 
    g_signal_connect (G_OBJECT (toolitem), "clicked",
1196
 
        G_CALLBACK (remmina_connection_holder_toolbar_fullscreen), cnnhld);
1197
 
 
1198
 
    /* Fullscreen drop-down options */
1199
 
    toolitem = gtk_tool_item_new ();
1200
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1201
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1202
 
 
1203
 
    widget = gtk_toggle_button_new ();
1204
 
    gtk_widget_show (widget);
1205
 
    gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
1206
 
    gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
1207
 
    gtk_button_set_focus_on_click (GTK_BUTTON (widget), FALSE);
1208
 
    if (remmina_pref.small_toolbutton)
1209
 
    {
1210
 
        gtk_widget_set_name (widget, "remmina-small-button");
1211
 
    }
1212
 
    gtk_container_add (GTK_CONTAINER (toolitem), widget);
1213
 
 
1214
 
    arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1215
 
    gtk_widget_show (arrow);
1216
 
    gtk_container_add (GTK_CONTAINER (widget), arrow);
1217
 
 
1218
 
    g_signal_connect (G_OBJECT (widget), "toggled",
1219
 
        G_CALLBACK(remmina_connection_holder_toolbar_fullscreen_option), cnnhld);
1220
 
    priv->fullscreen_option_button = widget;
1221
 
    if (mode == SCROLLED_WINDOW_MODE)
1222
 
    {
1223
 
        gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
1224
 
    }
1225
 
 
1226
 
    /* Switch tabs */
1227
 
    toolitem = gtk_toggle_tool_button_new ();
1228
 
    gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (toolitem), "remmina-switch-page");
1229
 
    remmina_connection_holder_set_tooltip (toolitem, _("Switch tab pages"),
1230
 
        remmina_pref.shortcutkey_prevtab, remmina_pref.shortcutkey_nexttab);
1231
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1232
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1233
 
    g_signal_connect (G_OBJECT (toolitem), "toggled",
1234
 
        G_CALLBACK (remmina_connection_holder_toolbar_switch_page), cnnhld);
1235
 
    priv->toolitem_switch_page = toolitem;
1236
 
 
1237
 
    toolitem = gtk_separator_tool_item_new ();
1238
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1239
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1240
 
 
1241
 
    toolitem = gtk_toggle_tool_button_new ();
1242
 
    gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (toolitem), "remmina-scale");
1243
 
    remmina_connection_holder_set_tooltip (toolitem, _("Toggle scaled mode"),
1244
 
        remmina_pref.shortcutkey_scale, 0);
1245
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1246
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1247
 
    g_signal_connect (G_OBJECT (toolitem), "toggled",
1248
 
        G_CALLBACK (remmina_connection_holder_toolbar_scaled_mode), cnnhld);
1249
 
    priv->toolitem_scale = toolitem;
1250
 
 
1251
 
    /* We need a toggle tool button with a popup arrow; and the popup is a window not a menu.
1252
 
       GTK+ support neither of them. We need some tricks here... */
1253
 
    toolitem = gtk_tool_item_new ();
1254
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1255
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1256
 
 
1257
 
    widget = gtk_toggle_button_new ();
1258
 
    gtk_widget_show (widget);
1259
 
    gtk_container_set_border_width (GTK_CONTAINER (widget), 0);
1260
 
    gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
1261
 
    gtk_button_set_focus_on_click (GTK_BUTTON (widget), FALSE);
1262
 
    if (remmina_pref.small_toolbutton)
1263
 
    {
1264
 
        gtk_widget_set_name (widget, "remmina-small-button");
1265
 
    }
1266
 
    gtk_container_add (GTK_CONTAINER (toolitem), widget);
1267
 
 
1268
 
    arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1269
 
    gtk_widget_show (arrow);
1270
 
    gtk_container_add (GTK_CONTAINER (widget), arrow);
1271
 
 
1272
 
    g_signal_connect (G_OBJECT (widget), "toggled",
1273
 
        G_CALLBACK(remmina_connection_holder_toolbar_scale_option), cnnhld);
1274
 
    priv->scale_option_button = widget;
1275
 
 
1276
 
    toolitem = gtk_toggle_tool_button_new ();
1277
 
    gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (toolitem), "input-keyboard");
1278
 
    remmina_connection_holder_set_tooltip (toolitem, _("Grab all keyboard events"),
1279
 
        remmina_pref.shortcutkey_grab, 0);
1280
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1281
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1282
 
    g_signal_connect (G_OBJECT (toolitem), "toggled",
1283
 
        G_CALLBACK (remmina_connection_holder_toolbar_grab), cnnhld);
1284
 
    priv->toolitem_grab = toolitem;
1285
 
 
1286
 
    toolitem = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_PREFERENCES);
1287
 
    gtk_tool_item_set_tooltip_text (toolitem, _("Preferences"));
1288
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1289
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1290
 
    g_signal_connect (G_OBJECT (toolitem), "toggled",
1291
 
        G_CALLBACK (remmina_connection_holder_toolbar_preferences), cnnhld);
1292
 
    priv->toolitem_preferences = toolitem;
1293
 
 
1294
 
    toolitem = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_EXECUTE);
1295
 
    gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Tools"));
1296
 
    gtk_tool_item_set_tooltip_text (toolitem, _("Tools"));
1297
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1298
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1299
 
    g_signal_connect (G_OBJECT (toolitem), "toggled",
1300
 
        G_CALLBACK (remmina_connection_holder_toolbar_tools), cnnhld);
1301
 
    priv->toolitem_tools = toolitem;
1302
 
 
1303
 
    toolitem = gtk_separator_tool_item_new ();
1304
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1305
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1306
 
 
1307
 
    toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GOTO_BOTTOM);
1308
 
    remmina_connection_holder_set_tooltip (toolitem, _("Minimize window"),
1309
 
        remmina_pref.shortcutkey_minimize, 0);
1310
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1311
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1312
 
    g_signal_connect (G_OBJECT (toolitem), "clicked",
1313
 
        G_CALLBACK (remmina_connection_holder_toolbar_minimize), cnnhld);
1314
 
 
1315
 
    toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DISCONNECT);
1316
 
    remmina_connection_holder_set_tooltip (toolitem, _("Disconnect"),
1317
 
        remmina_pref.shortcutkey_disconnect, 0);
1318
 
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1319
 
    gtk_widget_show (GTK_WIDGET (toolitem));
1320
 
    g_signal_connect (G_OBJECT (toolitem), "clicked",
1321
 
        G_CALLBACK (remmina_connection_holder_toolbar_disconnect), cnnhld);
1322
 
 
1323
 
    return toolbar;
1324
 
}
1325
 
 
1326
 
static void
1327
 
remmina_connection_holder_update_toolbar (RemminaConnectionHolder *cnnhld)
1328
 
{
1329
 
    DECLARE_CNNOBJ
1330
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1331
 
    GtkToolItem *toolitem;
1332
 
    gboolean bval;
1333
 
 
1334
 
    toolitem = priv->toolitem_autofit;
1335
 
    if (toolitem)
1336
 
    {
1337
 
        if (priv->view_mode != SCROLLED_WINDOW_MODE)
1338
 
        {
1339
 
            gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
1340
 
        }
1341
 
        else
1342
 
        {
1343
 
            bval = remmina_protocol_widget_get_expand (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
1344
 
            gtk_widget_set_sensitive (GTK_WIDGET (toolitem), !bval);
1345
 
        }
1346
 
    }
1347
 
 
1348
 
    toolitem = priv->toolitem_switch_page;
1349
 
    bval = (gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) > 1);
1350
 
    gtk_widget_set_sensitive (GTK_WIDGET (toolitem), bval);
1351
 
 
1352
 
    toolitem = priv->toolitem_scale;
1353
 
    bval = remmina_protocol_widget_get_scale (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
1354
 
    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (toolitem), bval);
1355
 
    gtk_widget_set_sensitive (GTK_WIDGET (priv->scale_option_button), bval);
1356
 
    bval = remmina_protocol_widget_query_feature_by_type (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
1357
 
        REMMINA_PROTOCOL_FEATURE_TYPE_SCALE);
1358
 
    gtk_widget_set_sensitive (GTK_WIDGET (toolitem), bval);
1359
 
 
1360
 
    toolitem = priv->toolitem_grab;
1361
 
    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (toolitem),
1362
 
        remmina_file_get_int (cnnobj->remmina_file, "keyboard_grab", FALSE));
1363
 
 
1364
 
    toolitem = priv->toolitem_preferences;
1365
 
    bval = remmina_protocol_widget_query_feature_by_type (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
1366
 
        REMMINA_PROTOCOL_FEATURE_TYPE_PREF);
1367
 
    gtk_widget_set_sensitive (GTK_WIDGET (toolitem), bval);
1368
 
 
1369
 
    toolitem = priv->toolitem_tools;
1370
 
    bval = remmina_protocol_widget_query_feature_by_type (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
1371
 
        REMMINA_PROTOCOL_FEATURE_TYPE_TOOL);
1372
 
    gtk_widget_set_sensitive (GTK_WIDGET (toolitem), bval);
1373
 
 
1374
 
    gtk_window_set_title (GTK_WINDOW (cnnhld->cnnwin), remmina_file_get_string (cnnobj->remmina_file, "name"));
1375
 
 
1376
 
    if (priv->floating_toolbar)
1377
 
    {
1378
 
        gtk_label_set_text (GTK_LABEL (priv->floating_toolbar_label),
1379
 
            remmina_file_get_string (cnnobj->remmina_file, "name"));
1380
 
    }
1381
 
}
1382
 
 
1383
 
static void
1384
 
remmina_connection_holder_showhide_toolbar (RemminaConnectionHolder *cnnhld, gboolean resize)
1385
 
{
1386
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1387
 
    GtkRequisition req;
1388
 
    gint width, height;
1389
 
 
1390
 
    if (priv->view_mode == SCROLLED_WINDOW_MODE)
1391
 
    {
1392
 
        if (resize &&
1393
 
            (gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (cnnhld->cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) == 0)
1394
 
        {
1395
 
            gtk_window_get_size (GTK_WINDOW (cnnhld->cnnwin), &width, &height);
1396
 
            gtk_widget_size_request (priv->toolbar, &req);
1397
 
            if (remmina_pref.hide_connection_toolbar)
1398
 
            {
1399
 
                gtk_widget_hide (priv->toolbar);
1400
 
                gtk_window_resize (GTK_WINDOW (cnnhld->cnnwin), width, height - req.height);
1401
 
            }
1402
 
            else
1403
 
            {
1404
 
                gtk_window_resize (GTK_WINDOW (cnnhld->cnnwin), width, height + req.height);
1405
 
                gtk_widget_show (priv->toolbar);
1406
 
            }
1407
 
        }
1408
 
        else
1409
 
        {
1410
 
            if (remmina_pref.hide_connection_toolbar)
1411
 
            {
1412
 
                gtk_widget_hide (priv->toolbar);
1413
 
            }
1414
 
            else
1415
 
            {
1416
 
                gtk_widget_show (priv->toolbar);
1417
 
            }
1418
 
        }
1419
 
    }
1420
 
}
1421
 
 
1422
 
static gboolean
1423
 
remmina_connection_holder_toolbar_enter (
1424
 
    GtkWidget *widget,
1425
 
    GdkEventCrossing *event,
1426
 
    RemminaConnectionHolder *cnnhld)
1427
 
{
1428
 
    remmina_connection_holder_floating_toolbar_show (cnnhld, TRUE);
1429
 
    return TRUE;
1430
 
}
1431
 
 
1432
 
static gboolean
1433
 
remmina_connection_holder_toolbar_leave (
1434
 
    GtkWidget *widget,
1435
 
    GdkEventCrossing *event,
1436
 
    RemminaConnectionHolder *cnnhld)
1437
 
{
1438
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1439
 
 
1440
 
    if (!priv->sticky && event->mode == GDK_CROSSING_NORMAL)
1441
 
    {
1442
 
        remmina_connection_holder_floating_toolbar_show (cnnhld, FALSE);
1443
 
        return TRUE;
1444
 
    }
1445
 
    return FALSE;
1446
 
}
1447
 
 
1448
 
static gboolean
1449
 
remmina_connection_window_focus_in (GtkWidget *widget, GdkEventFocus *event, RemminaConnectionHolder *cnnhld)
1450
 
{
1451
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1452
 
 
1453
 
    if (priv->floating_toolbar)
1454
 
    {
1455
 
        remmina_connection_holder_floating_toolbar_visible (cnnhld, TRUE);
1456
 
    }
1457
 
    return FALSE;
1458
 
}
1459
 
 
1460
 
static gboolean
1461
 
remmina_connection_window_focus_out (GtkWidget *widget, GdkEventFocus *event, RemminaConnectionHolder *cnnhld)
1462
 
{
1463
 
    DECLARE_CNNOBJ_WITH_RETURN (FALSE)
1464
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1465
 
 
1466
 
    cnnhld->hostkey_activated = FALSE;
1467
 
    if (!priv->sticky && priv->floating_toolbar)
1468
 
    {
1469
 
        remmina_connection_holder_floating_toolbar_visible (cnnhld, FALSE);
1470
 
    }
1471
 
    if (REMMINA_IS_SCROLLED_VIEWPORT (cnnobj->scrolled_container))
1472
 
    {
1473
 
        remmina_scrolled_viewport_remove_motion (REMMINA_SCROLLED_VIEWPORT (cnnobj->scrolled_container));
1474
 
    }
1475
 
    remmina_protocol_widget_call_feature_by_type (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
1476
 
        REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS, 0);
1477
 
    return FALSE;
1478
 
}
1479
 
 
1480
 
static gboolean
1481
 
remmina_connection_window_on_enter (
1482
 
    GtkWidget *widget,
1483
 
    GdkEventCrossing *event,
1484
 
    RemminaConnectionHolder *cnnhld)
1485
 
{
1486
 
    if (event->detail == GDK_NOTIFY_VIRTUAL ||
1487
 
        event->detail == GDK_NOTIFY_NONLINEAR ||
1488
 
        event->detail == GDK_NOTIFY_NONLINEAR_VIRTUAL)
1489
 
    {
1490
 
        remmina_connection_holder_keyboard_grab (cnnhld);
1491
 
    }
1492
 
    return FALSE;
1493
 
}
1494
 
 
1495
 
static gboolean
1496
 
remmina_connection_window_on_leave (
1497
 
    GtkWidget *widget,
1498
 
    GdkEventCrossing *event,
1499
 
    RemminaConnectionHolder *cnnhld)
1500
 
{
1501
 
    if (event->detail == GDK_NOTIFY_VIRTUAL ||
1502
 
        event->detail == GDK_NOTIFY_NONLINEAR ||
1503
 
        event->detail == GDK_NOTIFY_NONLINEAR_VIRTUAL)
1504
 
    {
1505
 
        gdk_keyboard_ungrab (GDK_CURRENT_TIME);
1506
 
    }
1507
 
    return FALSE;
1508
 
}
1509
 
 
1510
 
static gboolean
1511
 
remmina_connection_holder_toolbar_scroll (GtkWidget *widget, GdkEventScroll *event, RemminaConnectionHolder *cnnhld)
1512
 
{
1513
 
    DECLARE_CNNOBJ_WITH_RETURN (FALSE)
1514
 
    int opacity;
1515
 
 
1516
 
    opacity = remmina_file_get_int (cnnobj->remmina_file, "toolbar_opacity", 0); 
1517
 
    switch (event->direction)
1518
 
    {
1519
 
    case GDK_SCROLL_UP:
1520
 
        if (opacity > 0)
1521
 
        {
1522
 
            remmina_file_set_int (cnnobj->remmina_file, "toolbar_opacity", opacity - 1);
1523
 
            remmina_connection_holder_update_toolbar_opacity (cnnhld);
1524
 
            return TRUE;
1525
 
        }
1526
 
        break;
1527
 
    case GDK_SCROLL_DOWN:
1528
 
        if (opacity < TOOLBAR_OPACITY_LEVEL)
1529
 
        {
1530
 
            remmina_file_set_int (cnnobj->remmina_file, "toolbar_opacity", opacity + 1);
1531
 
            remmina_connection_holder_update_toolbar_opacity (cnnhld);
1532
 
            return TRUE;
1533
 
        }
1534
 
        break;
1535
 
    default:
1536
 
        break;
1537
 
    }
1538
 
    return FALSE;
1539
 
}
1540
 
 
1541
 
static void
1542
 
remmina_connection_object_alignment_on_allocate (GtkWidget *widget, GtkAllocation *allocation, RemminaConnectionObject *cnnobj)
1543
 
{
1544
 
    remmina_connection_holder_update_alignment (cnnobj->cnnhld);
1545
 
}
1546
 
 
1547
 
static gboolean
1548
 
remmina_connection_window_on_configure (GtkWidget *widget, GdkEventConfigure *event, RemminaConnectionHolder *cnnhld)
1549
 
{
1550
 
    DECLARE_CNNOBJ_WITH_RETURN (FALSE)
1551
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1552
 
    GtkRequisition req;
1553
 
    gint width, height;
1554
 
    gint y;
1555
 
 
1556
 
    if (cnnhld->cnnwin && gtk_widget_get_window (GTK_WIDGET (cnnhld->cnnwin)) &&
1557
 
        cnnhld->cnnwin->priv->view_mode == SCROLLED_WINDOW_MODE)
1558
 
    {
1559
 
        /* Here we store the window state in real-time */
1560
 
        if ((gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (cnnhld->cnnwin))) & GDK_WINDOW_STATE_MAXIMIZED) == 0)
1561
 
        {
1562
 
            gtk_window_get_size (GTK_WINDOW (cnnhld->cnnwin), &width, &height);
1563
 
            remmina_file_set_int (cnnobj->remmina_file, "window_width", width);
1564
 
            remmina_file_set_int (cnnobj->remmina_file, "window_height", height);
1565
 
            remmina_file_set_int (cnnobj->remmina_file, "window_maximize", FALSE);
1566
 
        }
1567
 
        else
1568
 
        {
1569
 
            remmina_file_set_int (cnnobj->remmina_file, "window_maximize", TRUE);
1570
 
        }
1571
 
    }
1572
 
 
1573
 
    if (priv->floating_toolbar)
1574
 
    {
1575
 
        gtk_widget_size_request (priv->floating_toolbar, &req);
1576
 
        gtk_window_get_position (GTK_WINDOW (priv->floating_toolbar), NULL, &y);
1577
 
        gtk_window_move (GTK_WINDOW (priv->floating_toolbar),
1578
 
            event->x + MAX (0, (event->width - req.width) / 2), y);
1579
 
 
1580
 
        remmina_connection_holder_floating_toolbar_update (cnnhld);
1581
 
    }
1582
 
    
1583
 
    if (cnnhld->cnnwin->priv->view_mode != SCROLLED_WINDOW_MODE)
1584
 
    {
1585
 
        /* Notify window of change so that scroll border can be hidden or shown if needed */
1586
 
        remmina_connection_holder_check_resize (cnnobj->cnnhld);
1587
 
    }
1588
 
    return FALSE;
1589
 
}
1590
 
 
1591
 
static void
1592
 
remmina_connection_holder_update_pin (RemminaConnectionHolder *cnnhld)
1593
 
{
1594
 
    if (cnnhld->cnnwin->priv->pin_down)
1595
 
    {
1596
 
        gtk_button_set_image (GTK_BUTTON (cnnhld->cnnwin->priv->pin_button),
1597
 
            gtk_image_new_from_icon_name ("remmina-pin-down", GTK_ICON_SIZE_MENU));
1598
 
    }
1599
 
    else
1600
 
    {
1601
 
        gtk_button_set_image (GTK_BUTTON (cnnhld->cnnwin->priv->pin_button),
1602
 
            gtk_image_new_from_icon_name ("remmina-pin-up", GTK_ICON_SIZE_MENU));
1603
 
    }
1604
 
}
1605
 
 
1606
 
static void
1607
 
remmina_connection_holder_toolbar_pin (GtkWidget *widget, RemminaConnectionHolder *cnnhld)
1608
 
{
1609
 
    cnnhld->cnnwin->priv->pin_down = !cnnhld->cnnwin->priv->pin_down;
1610
 
    remmina_connection_holder_update_pin (cnnhld);
1611
 
}
1612
 
 
1613
 
static void
1614
 
remmina_connection_holder_create_floating_toolbar (RemminaConnectionHolder *cnnhld, gint mode)
1615
 
{
1616
 
    DECLARE_CNNOBJ
1617
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1618
 
    GtkWidget *window;
1619
 
    GtkWidget *vbox;
1620
 
    GtkWidget *widget;
1621
 
    GtkWidget *eventbox;
1622
 
    GtkWidget *hbox;
1623
 
 
1624
 
    /* This has to be a popup window to become visible in fullscreen mode */
1625
 
    window = gtk_window_new (GTK_WINDOW_POPUP);
1626
 
 
1627
 
    vbox = gtk_vbox_new (FALSE, 0);
1628
 
    gtk_widget_show (vbox);
1629
 
    gtk_container_add (GTK_CONTAINER (window), vbox);
1630
 
 
1631
 
    widget = remmina_connection_holder_create_toolbar (cnnhld, mode);
1632
 
    gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
1633
 
 
1634
 
    hbox = gtk_hbox_new (FALSE, 0);
1635
 
    gtk_widget_show (hbox);
1636
 
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1637
 
 
1638
 
    /* The pin button */
1639
 
    widget = gtk_button_new ();
1640
 
    gtk_widget_show (widget);
1641
 
    gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1642
 
    gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
1643
 
    gtk_button_set_focus_on_click (GTK_BUTTON (widget), FALSE);
1644
 
    gtk_widget_set_name (widget, "remmina-small-button");
1645
 
    g_signal_connect (G_OBJECT (widget), "clicked",
1646
 
        G_CALLBACK (remmina_connection_holder_toolbar_pin), cnnhld);
1647
 
    priv->pin_button = widget;
1648
 
    priv->pin_down = remmina_pref.toolbar_pin_down;
1649
 
    remmina_connection_holder_update_pin (cnnhld);
1650
 
 
1651
 
    /* An event box is required to wrap the label to avoid infinite "leave-enter" event loop */
1652
 
    eventbox = gtk_event_box_new ();
1653
 
    gtk_widget_show (eventbox);
1654
 
    gtk_box_pack_start (GTK_BOX (hbox), eventbox, TRUE, TRUE, 0);
1655
 
    widget = gtk_label_new (remmina_file_get_string (cnnobj->remmina_file, "name"));
1656
 
    gtk_label_set_max_width_chars (GTK_LABEL (widget), 50);
1657
 
    gtk_widget_show (widget);
1658
 
    gtk_container_add (GTK_CONTAINER (eventbox), widget);
1659
 
    priv->floating_toolbar_label = widget;
1660
 
 
1661
 
    /* The position will be moved in configure event instead during maximizing. Just make it invisible here */
1662
 
    gtk_window_move (GTK_WINDOW (window), 0, -200);
1663
 
    gtk_window_set_accept_focus (GTK_WINDOW (window), FALSE);
1664
 
 
1665
 
    priv->floating_toolbar = window;
1666
 
 
1667
 
    remmina_connection_holder_update_toolbar_opacity (cnnhld);
1668
 
    if (remmina_pref.invisible_toolbar && !priv->pin_down)
1669
 
    {
1670
 
        gtk_window_set_opacity (GTK_WINDOW (window), 0.0);
1671
 
    }
1672
 
 
1673
 
    g_signal_connect (G_OBJECT (window), "enter-notify-event", 
1674
 
        G_CALLBACK (remmina_connection_holder_toolbar_enter), cnnhld);
1675
 
    g_signal_connect (G_OBJECT (window), "leave-notify-event", 
1676
 
        G_CALLBACK (remmina_connection_holder_toolbar_leave), cnnhld);
1677
 
    g_signal_connect (G_OBJECT (window), "scroll-event", 
1678
 
        G_CALLBACK (remmina_connection_holder_toolbar_scroll), cnnhld);
1679
 
 
1680
 
    if (cnnobj->connected) gtk_widget_show (window);
1681
 
}
1682
 
 
1683
 
static void
1684
 
remmina_connection_window_init (RemminaConnectionWindow *cnnwin)
1685
 
{
1686
 
    RemminaConnectionWindowPriv *priv;
1687
 
 
1688
 
    priv = g_new0 (RemminaConnectionWindowPriv, 1);
1689
 
    cnnwin->priv = priv;
1690
 
 
1691
 
    priv->view_mode = AUTO_MODE;
1692
 
    priv->floating_toolbar_opacity = 1.0;
1693
 
 
1694
 
    gtk_window_set_position (GTK_WINDOW (cnnwin), GTK_WIN_POS_CENTER);
1695
 
    gtk_container_set_border_width (GTK_CONTAINER (cnnwin), 0);
1696
 
 
1697
 
    remmina_widget_pool_register (GTK_WIDGET (cnnwin));
1698
 
}
1699
 
 
1700
 
static gboolean
1701
 
remmina_connection_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer user_data)
1702
 
{
1703
 
    GdkScreen *screen;
1704
 
 
1705
 
    screen = gdk_screen_get_default ();
1706
 
    if (remmina_pref.minimize_to_tray &&
1707
 
        (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) != 0 &&
1708
 
        (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) != 0 &&
1709
 
        remmina_public_get_current_workspace (screen) ==
1710
 
        remmina_public_get_window_workspace (GTK_WINDOW (widget)) &&
1711
 
        gdk_screen_get_number (screen) ==
1712
 
        gdk_screen_get_number (gtk_widget_get_screen (widget))
1713
 
    )
1714
 
    {
1715
 
        gtk_widget_hide (widget);
1716
 
        return TRUE;
1717
 
    }
1718
 
    return FALSE;
1719
 
}
1720
 
 
1721
 
static GtkWidget*
1722
 
remmina_connection_window_new_from_holder (RemminaConnectionHolder *cnnhld)
1723
 
{
1724
 
    RemminaConnectionWindow *cnnwin;
1725
 
 
1726
 
    cnnwin = REMMINA_CONNECTION_WINDOW (g_object_new (REMMINA_TYPE_CONNECTION_WINDOW, NULL));
1727
 
    cnnwin->priv->cnnhld = cnnhld;
1728
 
 
1729
 
    g_signal_connect (G_OBJECT (cnnwin), "delete-event",
1730
 
        G_CALLBACK (remmina_connection_window_delete_event), cnnhld);
1731
 
    g_signal_connect (G_OBJECT (cnnwin), "destroy",
1732
 
        G_CALLBACK (remmina_connection_window_destroy), cnnhld);
1733
 
    g_signal_connect (G_OBJECT (cnnwin), "window-state-event",
1734
 
        G_CALLBACK (remmina_connection_window_state_event), cnnhld);
1735
 
 
1736
 
    g_signal_connect (G_OBJECT (cnnwin), "focus-in-event",
1737
 
        G_CALLBACK (remmina_connection_window_focus_in), cnnhld);
1738
 
    g_signal_connect (G_OBJECT (cnnwin), "focus-out-event",
1739
 
        G_CALLBACK (remmina_connection_window_focus_out), cnnhld);
1740
 
 
1741
 
    g_signal_connect (G_OBJECT (cnnwin), "enter-notify-event",
1742
 
        G_CALLBACK (remmina_connection_window_on_enter), cnnhld);
1743
 
    g_signal_connect (G_OBJECT (cnnwin), "leave-notify-event",
1744
 
        G_CALLBACK (remmina_connection_window_on_leave), cnnhld);
1745
 
 
1746
 
    g_signal_connect (G_OBJECT (cnnwin), "configure_event",
1747
 
        G_CALLBACK (remmina_connection_window_on_configure), cnnhld);
1748
 
 
1749
 
    return GTK_WIDGET (cnnwin);
1750
 
}
1751
 
 
1752
 
/* This function will be called for the first connection. A tag is set to the window so that
1753
 
 * other connections can determine if whether a new tab should be append to the same window
1754
 
 */
1755
 
static void
1756
 
remmina_connection_window_update_tag (RemminaConnectionWindow *cnnwin, RemminaConnectionObject *cnnobj)
1757
 
{
1758
 
    gchar *tag;
1759
 
 
1760
 
    switch (remmina_pref.tab_mode)
1761
 
    {
1762
 
    case REMMINA_TAB_BY_GROUP:
1763
 
        tag = g_strdup (remmina_file_get_string (cnnobj->remmina_file, "group"));
1764
 
        break;
1765
 
    case REMMINA_TAB_BY_PROTOCOL:
1766
 
        tag = g_strdup (remmina_file_get_string (cnnobj->remmina_file, "protocol"));
1767
 
        break;
1768
 
    default:
1769
 
        tag = NULL;
1770
 
        break;
1771
 
    }
1772
 
    g_object_set_data_full (G_OBJECT (cnnwin), "tag", tag, (GDestroyNotify) g_free);
1773
 
}
1774
 
 
1775
 
static void
1776
 
remmina_connection_object_create_scrolled_container (RemminaConnectionObject *cnnobj, gint view_mode)
1777
 
{
1778
 
    GtkWidget *container;
1779
 
 
1780
 
    if (view_mode == VIEWPORT_FULLSCREEN_MODE)
1781
 
    {
1782
 
        container = remmina_scrolled_viewport_new ();
1783
 
    }
1784
 
    else
1785
 
    {
1786
 
        container = gtk_scrolled_window_new (NULL, NULL);
1787
 
        remmina_connection_object_set_scrolled_policy (cnnobj, GTK_SCROLLED_WINDOW (container));
1788
 
        gtk_container_set_border_width (GTK_CONTAINER (container), 0);
1789
 
        GTK_WIDGET_UNSET_FLAGS (container, GTK_CAN_FOCUS);
1790
 
    }
1791
 
    g_object_set_data (G_OBJECT (container), "cnnobj", cnnobj);
1792
 
    gtk_widget_show (container);
1793
 
    cnnobj->scrolled_container = container;
1794
 
}
1795
 
 
1796
 
static gboolean
1797
 
remmina_connection_holder_grab_focus (gpointer data)
1798
 
{
1799
 
    RemminaConnectionObject *cnnobj;
1800
 
    GtkNotebook *notebook;
1801
 
    GtkWidget *child;
1802
 
 
1803
 
    if (GTK_IS_WIDGET (data))
1804
 
    {
1805
 
        notebook = GTK_NOTEBOOK (data);
1806
 
        child = gtk_notebook_get_nth_page (notebook, gtk_notebook_get_current_page (notebook));
1807
 
        cnnobj = g_object_get_data (G_OBJECT (child), "cnnobj");
1808
 
        if (GTK_IS_WIDGET (cnnobj->proto))
1809
 
        {
1810
 
            remmina_protocol_widget_grab_focus (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
1811
 
        }
1812
 
    }
1813
 
    return FALSE;
1814
 
}
1815
 
 
1816
 
static void
1817
 
remmina_connection_object_on_close_button_clicked (GtkButton *button, RemminaConnectionObject *cnnobj)
1818
 
{
1819
 
    if (REMMINA_IS_PROTOCOL_WIDGET (cnnobj->proto))
1820
 
    {
1821
 
        remmina_protocol_widget_close_connection (REMMINA_PROTOCOL_WIDGET (cnnobj->proto));
1822
 
    }
1823
 
}
1824
 
 
1825
 
static GtkWidget*
1826
 
remmina_connection_object_create_tab (RemminaConnectionObject *cnnobj)
1827
 
{
1828
 
    GtkWidget *hbox;
1829
 
    GtkWidget *widget;
1830
 
    GtkWidget *button;
1831
 
 
1832
 
    hbox = gtk_hbox_new (FALSE, 4);
1833
 
    gtk_widget_show (hbox);
1834
 
 
1835
 
    widget = gtk_image_new_from_icon_name (remmina_file_get_icon_name (cnnobj->remmina_file), GTK_ICON_SIZE_MENU);
1836
 
    gtk_widget_show (widget);
1837
 
    gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1838
 
 
1839
 
    widget = gtk_label_new  (remmina_file_get_string (cnnobj->remmina_file, "name"));
1840
 
    gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
1841
 
    gtk_widget_show (widget);
1842
 
    gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
1843
 
 
1844
 
    button = gtk_button_new ();
1845
 
    gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
1846
 
    gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
1847
 
    gtk_widget_set_name (button, "remmina-small-button");
1848
 
    gtk_widget_show (button);
1849
 
 
1850
 
    widget = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
1851
 
    gtk_widget_show (widget);
1852
 
    gtk_container_add (GTK_CONTAINER (button), widget);
1853
 
 
1854
 
    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1855
 
 
1856
 
    g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (remmina_connection_object_on_close_button_clicked), cnnobj);
1857
 
 
1858
 
    return hbox;
1859
 
}
1860
 
 
1861
 
static gint
1862
 
remmina_connection_object_append_page (RemminaConnectionObject *cnnobj, GtkNotebook *notebook, GtkWidget *tab, gint view_mode)
1863
 
{
1864
 
    gint i;
1865
 
 
1866
 
    remmina_connection_object_create_scrolled_container (cnnobj, view_mode);
1867
 
    i = gtk_notebook_append_page (notebook, cnnobj->scrolled_container, tab);
1868
 
    gtk_notebook_set_tab_reorderable (notebook, cnnobj->scrolled_container, TRUE);
1869
 
    gtk_notebook_set_tab_detachable (notebook, cnnobj->scrolled_container, TRUE);
1870
 
    /* This trick prevents the tab label from being focused */
1871
 
    GTK_WIDGET_UNSET_FLAGS (gtk_widget_get_parent (tab), GTK_CAN_FOCUS);
1872
 
    return i;
1873
 
}
1874
 
 
1875
 
static void
1876
 
remmina_connection_window_initialize_notebook (GtkNotebook *to, GtkNotebook *from, RemminaConnectionObject *cnnobj, gint view_mode)
1877
 
{
1878
 
    gint i, n, c;
1879
 
    GtkWidget *tab;
1880
 
    GtkWidget *widget;
1881
 
 
1882
 
    if (cnnobj)
1883
 
    {
1884
 
        /* Initial connection for a newly created window */
1885
 
        tab = remmina_connection_object_create_tab (cnnobj);
1886
 
        remmina_connection_object_append_page (cnnobj, to, tab, view_mode);
1887
 
 
1888
 
        gtk_widget_reparent (cnnobj->viewport, cnnobj->scrolled_container);
1889
 
 
1890
 
        if (cnnobj->window)
1891
 
        {
1892
 
            gtk_widget_destroy (cnnobj->window);
1893
 
            cnnobj->window = NULL;
1894
 
        }
1895
 
    }
1896
 
    else
1897
 
    {
1898
 
        /* View mode changed. Migrate all existing connections to the new notebook */
1899
 
        c = gtk_notebook_get_current_page (from);
1900
 
        n = gtk_notebook_get_n_pages (from);
1901
 
        for (i = 0; i < n; i++)
1902
 
        {
1903
 
            widget = gtk_notebook_get_nth_page (from, i);
1904
 
            cnnobj = (RemminaConnectionObject*) g_object_get_data (G_OBJECT (widget), "cnnobj");
1905
 
 
1906
 
            tab = remmina_connection_object_create_tab (cnnobj);
1907
 
            remmina_connection_object_append_page (cnnobj, to, tab, view_mode);
1908
 
 
1909
 
            gtk_widget_reparent (cnnobj->viewport, cnnobj->scrolled_container);
1910
 
        }
1911
 
        gtk_notebook_set_current_page (to, c);
1912
 
    }
1913
 
}
1914
 
 
1915
 
static void
1916
 
remmina_connection_holder_update_notebook (RemminaConnectionHolder *cnnhld)
1917
 
{
1918
 
    GtkNotebook *notebook;
1919
 
    gint n;
1920
 
 
1921
 
    if (!cnnhld->cnnwin) return;
1922
 
 
1923
 
    notebook = GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook);
1924
 
 
1925
 
    switch (cnnhld->cnnwin->priv->view_mode)
1926
 
    {
1927
 
    case SCROLLED_WINDOW_MODE:
1928
 
        n = gtk_notebook_get_n_pages (notebook);
1929
 
        gtk_notebook_set_show_tabs (notebook, remmina_pref.always_show_tab ? TRUE : n > 1);
1930
 
        gtk_notebook_set_show_border (notebook, remmina_pref.always_show_tab ? TRUE : n > 1);
1931
 
        break;
1932
 
    default:
1933
 
        gtk_notebook_set_show_tabs (notebook, FALSE);
1934
 
        gtk_notebook_set_show_border (notebook, FALSE);
1935
 
        break;
1936
 
    }
1937
 
}
1938
 
 
1939
 
static gboolean
1940
 
remmina_connection_holder_on_switch_page_real (gpointer data)
1941
 
{
1942
 
    RemminaConnectionHolder *cnnhld = (RemminaConnectionHolder*) data;
1943
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1944
 
 
1945
 
    if (GTK_IS_WIDGET (cnnhld->cnnwin))
1946
 
    {
1947
 
        remmina_connection_holder_update_toolbar (cnnhld);
1948
 
        remmina_connection_holder_grab_focus (priv->notebook);
1949
 
        if (cnnhld->cnnwin->priv->view_mode != SCROLLED_WINDOW_MODE)
1950
 
        {
1951
 
            remmina_connection_holder_check_resize (cnnhld);
1952
 
        }
1953
 
    }
1954
 
    priv->switch_page_handler = 0;
1955
 
    return FALSE;
1956
 
}
1957
 
 
1958
 
static void
1959
 
remmina_connection_holder_on_switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, RemminaConnectionHolder *cnnhld)
1960
 
{
1961
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
1962
 
 
1963
 
    if (!priv->switch_page_handler)
1964
 
    {
1965
 
        priv->switch_page_handler = g_idle_add (remmina_connection_holder_on_switch_page_real, cnnhld);
1966
 
    }
1967
 
}
1968
 
 
1969
 
static void
1970
 
remmina_connection_holder_on_page_added (GtkNotebook *notebook, GtkWidget *child, guint page_num, RemminaConnectionHolder *cnnhld)
1971
 
{
1972
 
    if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook)) <= 0)
1973
 
    {
1974
 
        gtk_widget_destroy (GTK_WIDGET (cnnhld->cnnwin));
1975
 
        g_free (cnnhld);
1976
 
    }
1977
 
    else
1978
 
    {
1979
 
        remmina_connection_holder_update_notebook (cnnhld);
1980
 
    }
1981
 
}
1982
 
 
1983
 
GtkNotebook*
1984
 
remmina_connection_holder_create_notebook_func (GtkNotebook *source, GtkWidget *page, gint x, gint y, gpointer data)
1985
 
{
1986
 
    RemminaConnectionWindow *srccnnwin;
1987
 
    RemminaConnectionWindow *dstcnnwin;
1988
 
    RemminaConnectionObject *cnnobj;
1989
 
    gint srcpagenum;
1990
 
    GdkWindow *window;
1991
 
 
1992
 
    srccnnwin = REMMINA_CONNECTION_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (source)));
1993
 
    window = gdk_display_get_window_at_pointer (gdk_display_get_default (), &x, &y);
1994
 
    dstcnnwin = REMMINA_CONNECTION_WINDOW (remmina_widget_pool_find_by_window (REMMINA_TYPE_CONNECTION_WINDOW, window));
1995
 
 
1996
 
    if (srccnnwin == dstcnnwin) return NULL;
1997
 
 
1998
 
    if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (srccnnwin->priv->notebook)) == 1 && !dstcnnwin) return NULL;
1999
 
 
2000
 
    cnnobj = (RemminaConnectionObject*) g_object_get_data (G_OBJECT (page), "cnnobj");
2001
 
    srcpagenum = gtk_notebook_page_num (GTK_NOTEBOOK (srccnnwin->priv->notebook), cnnobj->scrolled_container);
2002
 
 
2003
 
    if (dstcnnwin)
2004
 
    {
2005
 
        cnnobj->cnnhld = dstcnnwin->priv->cnnhld;
2006
 
    }
2007
 
    else
2008
 
    {
2009
 
        cnnobj->cnnhld = g_new0 (RemminaConnectionHolder, 1);
2010
 
    }
2011
 
 
2012
 
    g_signal_emit_by_name (cnnobj->proto, "connect", cnnobj);
2013
 
    gtk_notebook_remove_page (GTK_NOTEBOOK (srccnnwin->priv->notebook), srcpagenum);
2014
 
 
2015
 
    return NULL;
2016
 
}
2017
 
 
2018
 
static GtkWidget*
2019
 
remmina_connection_holder_create_notebook (RemminaConnectionHolder *cnnhld)
2020
 
{
2021
 
    GtkWidget *notebook;
2022
 
 
2023
 
    gtk_notebook_set_window_creation_hook (remmina_connection_holder_create_notebook_func, NULL, NULL);
2024
 
 
2025
 
    notebook = gtk_notebook_new ();
2026
 
    gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
2027
 
    gtk_widget_show (notebook);
2028
 
    g_signal_connect (G_OBJECT (notebook), "switch-page",
2029
 
        G_CALLBACK (remmina_connection_holder_on_switch_page), cnnhld);
2030
 
    g_signal_connect (G_OBJECT (notebook), "page-added",
2031
 
        G_CALLBACK (remmina_connection_holder_on_page_added), cnnhld);
2032
 
    g_signal_connect (G_OBJECT (notebook), "page-removed",
2033
 
        G_CALLBACK (remmina_connection_holder_on_page_added), cnnhld);
2034
 
    GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
2035
 
 
2036
 
    return notebook;
2037
 
}
2038
 
 
2039
 
/* Create a scrolled window container */
2040
 
static void
2041
 
remmina_connection_holder_create_scrolled (RemminaConnectionHolder *cnnhld, RemminaConnectionObject *cnnobj)
2042
 
{
2043
 
    GtkWidget *window;
2044
 
    GtkWidget *oldwindow;
2045
 
    GtkWidget *vbox;
2046
 
    GtkWidget *toolbar;
2047
 
    GtkWidget *notebook;
2048
 
    gchar *tag;
2049
 
 
2050
 
    oldwindow = GTK_WIDGET (cnnhld->cnnwin);
2051
 
    window = remmina_connection_window_new_from_holder (cnnhld);
2052
 
    gtk_widget_realize (window);
2053
 
    cnnhld->cnnwin = REMMINA_CONNECTION_WINDOW (window);
2054
 
 
2055
 
    /* Create the vbox container */
2056
 
    vbox = gtk_vbox_new (FALSE, 0);
2057
 
    gtk_widget_show (vbox);
2058
 
    gtk_container_add (GTK_CONTAINER (window), vbox);
2059
 
 
2060
 
    /* Create the toolbar */
2061
 
    toolbar = remmina_connection_holder_create_toolbar (cnnhld, SCROLLED_WINDOW_MODE);
2062
 
    gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
2063
 
 
2064
 
    /* Create the notebook */
2065
 
    notebook = remmina_connection_holder_create_notebook (cnnhld);
2066
 
    gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
2067
 
    gtk_container_set_focus_chain (GTK_CONTAINER (vbox), g_list_append (NULL, notebook));
2068
 
 
2069
 
    cnnhld->cnnwin->priv->view_mode = SCROLLED_WINDOW_MODE;
2070
 
    cnnhld->cnnwin->priv->toolbar = toolbar;
2071
 
    cnnhld->cnnwin->priv->notebook = notebook;
2072
 
 
2073
 
    remmina_connection_window_initialize_notebook (GTK_NOTEBOOK (notebook),
2074
 
        (oldwindow ? GTK_NOTEBOOK (REMMINA_CONNECTION_WINDOW (oldwindow)->priv->notebook) : NULL), cnnobj,
2075
 
        SCROLLED_WINDOW_MODE);
2076
 
 
2077
 
    if (cnnobj)
2078
 
    {
2079
 
        remmina_connection_window_update_tag (cnnhld->cnnwin, cnnobj);
2080
 
        if (remmina_file_get_int (cnnobj->remmina_file, "window_maximize", FALSE))
2081
 
        {
2082
 
            gtk_window_maximize (GTK_WINDOW (cnnhld->cnnwin));
2083
 
        }
2084
 
    }
2085
 
 
2086
 
    if (oldwindow)
2087
 
    {
2088
 
        tag = g_strdup ((gchar*) g_object_get_data (G_OBJECT (oldwindow), "tag"));
2089
 
        g_object_set_data_full (G_OBJECT (cnnhld->cnnwin), "tag", tag, (GDestroyNotify) g_free);
2090
 
        gtk_widget_destroy (oldwindow);
2091
 
    }
2092
 
 
2093
 
    remmina_connection_holder_update_toolbar (cnnhld);
2094
 
    remmina_connection_holder_showhide_toolbar (cnnhld, FALSE);
2095
 
    remmina_connection_holder_check_resize (cnnhld);
2096
 
 
2097
 
    gtk_widget_show (GTK_WIDGET (cnnhld->cnnwin));
2098
 
}
2099
 
 
2100
 
static void
2101
 
remmina_connection_holder_create_fullscreen (RemminaConnectionHolder *cnnhld, RemminaConnectionObject *cnnobj, gint view_mode)
2102
 
{
2103
 
    GtkWidget *window;
2104
 
    GtkWidget *oldwindow;
2105
 
    GtkWidget *notebook;
2106
 
    GdkColor color;
2107
 
    gchar *tag;
2108
 
 
2109
 
    oldwindow = GTK_WIDGET (cnnhld->cnnwin);
2110
 
    window = remmina_connection_window_new_from_holder (cnnhld);
2111
 
    gtk_widget_realize (window);
2112
 
    cnnhld->cnnwin = REMMINA_CONNECTION_WINDOW (window);
2113
 
 
2114
 
    if (!view_mode) view_mode = VIEWPORT_FULLSCREEN_MODE;
2115
 
 
2116
 
    if (view_mode == VIEWPORT_FULLSCREEN_MODE)
2117
 
    {
2118
 
        gdk_color_parse ("black", &color);
2119
 
        gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &color);
2120
 
    }
2121
 
 
2122
 
    notebook = remmina_connection_holder_create_notebook (cnnhld);
2123
 
    gtk_container_add (GTK_CONTAINER (window), notebook);
2124
 
 
2125
 
    cnnhld->cnnwin->priv->notebook = notebook;
2126
 
    cnnhld->cnnwin->priv->view_mode = view_mode;
2127
 
    cnnhld->fullscreen_view_mode = view_mode;
2128
 
 
2129
 
    remmina_connection_window_initialize_notebook (GTK_NOTEBOOK (notebook),
2130
 
        (oldwindow ? GTK_NOTEBOOK (REMMINA_CONNECTION_WINDOW (oldwindow)->priv->notebook) : NULL), cnnobj,
2131
 
        view_mode);
2132
 
 
2133
 
    if (cnnobj)
2134
 
    {
2135
 
        remmina_connection_window_update_tag (cnnhld->cnnwin, cnnobj);
2136
 
    }
2137
 
    if (oldwindow)
2138
 
    {
2139
 
        tag = g_strdup ((gchar*) g_object_get_data (G_OBJECT (oldwindow), "tag"));
2140
 
        g_object_set_data_full (G_OBJECT (cnnhld->cnnwin), "tag", tag, (GDestroyNotify) g_free);
2141
 
        gtk_widget_destroy (oldwindow);
2142
 
    }
2143
 
 
2144
 
    /* Create the floating toolbar */
2145
 
    remmina_connection_holder_create_floating_toolbar (cnnhld, view_mode);
2146
 
    remmina_connection_holder_update_toolbar (cnnhld);
2147
 
 
2148
 
    gtk_window_fullscreen (GTK_WINDOW (window));
2149
 
    remmina_connection_holder_check_resize (cnnhld);
2150
 
 
2151
 
    gtk_widget_show (window);
2152
 
}
2153
 
 
2154
 
static gboolean
2155
 
remmina_connection_window_hostkey_func (RemminaProtocolWidget *gp, guint keyval, gboolean release, RemminaConnectionHolder *cnnhld)
2156
 
{
2157
 
    RemminaConnectionWindowPriv *priv = cnnhld->cnnwin->priv;
2158
 
    gint i;
2159
 
 
2160
 
    if (release)
2161
 
    {
2162
 
        if (remmina_pref.hostkey && keyval == remmina_pref.hostkey)
2163
 
        {
2164
 
            cnnhld->hostkey_activated = FALSE;
2165
 
            if (cnnhld->hostkey_used)
2166
 
            {
2167
 
                return TRUE;
2168
 
            }
2169
 
            /* If hostkey is released without pressing other keys, we should execute the
2170
 
             * shortcut key which is the same as hostkey. Be default, this is grab/ungrab
2171
 
             * keyboard */
2172
 
        }
2173
 
        else if (cnnhld->hostkey_activated)
2174
 
        {
2175
 
            /* Trap all key releases when hostkey is pressed */
2176
 
            return TRUE;
2177
 
        }
2178
 
        else
2179
 
        {
2180
 
            return FALSE;
2181
 
        }
2182
 
    }
2183
 
    else if (remmina_pref.hostkey && keyval == remmina_pref.hostkey)
2184
 
    {
2185
 
        cnnhld->hostkey_activated = TRUE;
2186
 
        cnnhld->hostkey_used = FALSE;
2187
 
        return TRUE;
2188
 
    }
2189
 
    else if (!cnnhld->hostkey_activated)
2190
 
    {
2191
 
        return FALSE;
2192
 
    }
2193
 
 
2194
 
    cnnhld->hostkey_used = TRUE;
2195
 
    keyval = gdk_keyval_to_lower (keyval);
2196
 
    if (keyval == remmina_pref.shortcutkey_fullscreen)
2197
 
    {
2198
 
        switch (priv->view_mode)
2199
 
        {
2200
 
            case SCROLLED_WINDOW_MODE:
2201
 
                remmina_connection_holder_create_fullscreen (cnnhld, NULL,
2202
 
                    cnnhld->fullscreen_view_mode ? cnnhld->fullscreen_view_mode : VIEWPORT_FULLSCREEN_MODE);
2203
 
                break;
2204
 
            case SCROLLED_FULLSCREEN_MODE:
2205
 
            case VIEWPORT_FULLSCREEN_MODE:
2206
 
                remmina_connection_holder_create_scrolled (cnnhld, NULL);
2207
 
                break;
2208
 
            default:
2209
 
                break;
2210
 
        }
2211
 
    }
2212
 
    else if (keyval == remmina_pref.shortcutkey_autofit)
2213
 
    {
2214
 
        if (priv->toolitem_autofit && GTK_WIDGET_IS_SENSITIVE (priv->toolitem_autofit))
2215
 
        {
2216
 
            remmina_connection_holder_toolbar_autofit (GTK_WIDGET (gp), cnnhld);
2217
 
        }
2218
 
    }
2219
 
    else if (keyval == remmina_pref.shortcutkey_nexttab)
2220
 
    {
2221
 
        i = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)) + 1;
2222
 
        if (i >= gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook))) i = 0;
2223
 
        gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), i);
2224
 
    }
2225
 
    else if (keyval == remmina_pref.shortcutkey_prevtab)
2226
 
    {
2227
 
        i = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)) - 1;
2228
 
        if (i < 0) i = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) - 1;
2229
 
        gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), i);
2230
 
    }
2231
 
    else if (keyval == remmina_pref.shortcutkey_scale)
2232
 
    {
2233
 
        if (GTK_WIDGET_IS_SENSITIVE (priv->toolitem_scale))
2234
 
        {
2235
 
            gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_scale),
2236
 
                !gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_scale)));
2237
 
        }
2238
 
    }
2239
 
    else if (keyval == remmina_pref.shortcutkey_grab)
2240
 
    {
2241
 
        gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_grab),
2242
 
            !gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (priv->toolitem_grab)));
2243
 
    }
2244
 
    else if (keyval == remmina_pref.shortcutkey_minimize)
2245
 
    {
2246
 
        remmina_connection_holder_toolbar_minimize (GTK_WIDGET (gp), cnnhld);
2247
 
    }
2248
 
    else if (keyval == remmina_pref.shortcutkey_disconnect)
2249
 
    {
2250
 
        remmina_connection_holder_disconnect (cnnhld);
2251
 
    }
2252
 
    else if (keyval == remmina_pref.shortcutkey_toolbar)
2253
 
    {
2254
 
        if (priv->view_mode == SCROLLED_WINDOW_MODE)
2255
 
        {
2256
 
            remmina_pref.hide_connection_toolbar = !remmina_pref.hide_connection_toolbar;
2257
 
            remmina_connection_holder_showhide_toolbar (cnnhld, TRUE);
2258
 
        }
2259
 
    }
2260
 
    /* Trap all key presses when hostkey is pressed */
2261
 
    return TRUE;
2262
 
}
2263
 
 
2264
 
static RemminaConnectionWindow*
2265
 
remmina_connection_window_find (RemminaFile *remminafile)
2266
 
{
2267
 
    const gchar *tag;
2268
 
 
2269
 
    switch (remmina_pref.tab_mode)
2270
 
    {
2271
 
    case REMMINA_TAB_BY_GROUP:
2272
 
        tag = remmina_file_get_string (remminafile, "group");
2273
 
        break;
2274
 
    case REMMINA_TAB_BY_PROTOCOL:
2275
 
        tag = remmina_file_get_string (remminafile, "protocol");
2276
 
        break;
2277
 
    case REMMINA_TAB_ALL:
2278
 
        tag = NULL;
2279
 
        break;
2280
 
    case REMMINA_TAB_NONE:
2281
 
    default:
2282
 
        return NULL;
2283
 
    }
2284
 
    return REMMINA_CONNECTION_WINDOW (remmina_widget_pool_find (REMMINA_TYPE_CONNECTION_WINDOW, tag));
2285
 
}
2286
 
 
2287
 
static void
2288
 
remmina_connection_object_on_connect (RemminaProtocolWidget *gp, RemminaConnectionObject *cnnobj)
2289
 
{
2290
 
    RemminaConnectionWindow *cnnwin;
2291
 
    RemminaConnectionHolder *cnnhld;
2292
 
    GtkWidget *tab;
2293
 
    gint i;
2294
 
 
2295
 
    cnnwin = remmina_connection_window_find (cnnobj->remmina_file);
2296
 
 
2297
 
    if (cnnwin)
2298
 
    {
2299
 
        cnnhld = cnnwin->priv->cnnhld;
2300
 
    }
2301
 
    else
2302
 
    {
2303
 
        cnnhld = g_new0 (RemminaConnectionHolder, 1);
2304
 
    }
2305
 
 
2306
 
    cnnobj->cnnhld = cnnhld;
2307
 
 
2308
 
    cnnobj->connected = TRUE;
2309
 
 
2310
 
    remmina_protocol_widget_set_hostkey_func (REMMINA_PROTOCOL_WIDGET (cnnobj->proto),
2311
 
        (RemminaHostkeyFunc) remmina_connection_window_hostkey_func, cnnhld);
2312
 
 
2313
 
    /* Remember recent list for quick connect */
2314
 
    if (remmina_file_get_filename (cnnobj->remmina_file) == NULL)
2315
 
    {
2316
 
        remmina_pref_add_recent (remmina_file_get_string (cnnobj->remmina_file, "protocol"),
2317
 
            remmina_file_get_string (cnnobj->remmina_file, "server"));
2318
 
    }
2319
 
 
2320
 
    if (!cnnhld->cnnwin)
2321
 
    {
2322
 
        i = remmina_file_get_int (cnnobj->remmina_file, "viewmode", 0);
2323
 
        switch (i)
2324
 
        {
2325
 
            case SCROLLED_FULLSCREEN_MODE:
2326
 
            case VIEWPORT_FULLSCREEN_MODE:
2327
 
                remmina_connection_holder_create_fullscreen (cnnhld, cnnobj, i);
2328
 
                break;
2329
 
 
2330
 
            case SCROLLED_WINDOW_MODE:
2331
 
            default:
2332
 
                remmina_connection_holder_create_scrolled (cnnhld, cnnobj);
2333
 
                break;
2334
 
        }
2335
 
    }
2336
 
    else
2337
 
    {
2338
 
        tab = remmina_connection_object_create_tab (cnnobj);
2339
 
        i = remmina_connection_object_append_page (cnnobj,
2340
 
            GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), tab, cnnhld->cnnwin->priv->view_mode);
2341
 
        gtk_widget_reparent (cnnobj->viewport, cnnobj->scrolled_container);
2342
 
        gtk_window_present (GTK_WINDOW (cnnhld->cnnwin));
2343
 
        gtk_notebook_set_current_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), i);
2344
 
    }
2345
 
    remmina_connection_object_init_adjustment (cnnobj);
2346
 
 
2347
 
    if (cnnhld->cnnwin->priv->floating_toolbar)
2348
 
    {
2349
 
        gtk_widget_show (cnnhld->cnnwin->priv->floating_toolbar);
2350
 
    }
2351
 
}
2352
 
 
2353
 
static void
2354
 
remmina_connection_object_on_disconnect (RemminaProtocolWidget *gp, RemminaConnectionObject *cnnobj)
2355
 
{
2356
 
    RemminaConnectionHolder *cnnhld = cnnobj->cnnhld;
2357
 
    GtkWidget *dialog;
2358
 
 
2359
 
    cnnobj->connected = FALSE;
2360
 
    if (scale_option_window)
2361
 
    {
2362
 
        gtk_widget_destroy (scale_option_window);
2363
 
        scale_option_window = NULL;
2364
 
    }
2365
 
 
2366
 
    if (cnnhld && remmina_pref.save_view_mode)
2367
 
    {
2368
 
        if (cnnhld->cnnwin)
2369
 
        {
2370
 
            remmina_file_set_int (cnnobj->remmina_file, "viewmode", cnnhld->cnnwin->priv->view_mode);
2371
 
        }
2372
 
        if (remmina_pref.save_when_connect)
2373
 
        {
2374
 
            remmina_file_save_all (cnnobj->remmina_file);
2375
 
        }
2376
 
        else
2377
 
        {
2378
 
            remmina_file_save_group (cnnobj->remmina_file, REMMINA_SETTING_GROUP_RUNTIME);
2379
 
        }
2380
 
        if (cnnhld->cnnwin && remmina_pref.toolbar_pin_down != cnnhld->cnnwin->priv->pin_down)
2381
 
        {
2382
 
            remmina_pref.toolbar_pin_down = cnnhld->cnnwin->priv->pin_down;
2383
 
            remmina_pref_save ();
2384
 
        }
2385
 
    }
2386
 
    remmina_file_free (cnnobj->remmina_file);
2387
 
 
2388
 
    if (remmina_protocol_widget_has_error (gp))
2389
 
    {
2390
 
        dialog = gtk_message_dialog_new (NULL,
2391
 
            GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
2392
 
            remmina_protocol_widget_get_error_message (gp), NULL);
2393
 
        g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
2394
 
        gtk_widget_show (dialog);
2395
 
        remmina_widget_pool_register (dialog);
2396
 
    }
2397
 
 
2398
 
    if (cnnobj->window)
2399
 
    {
2400
 
        gtk_widget_destroy (cnnobj->window);
2401
 
        cnnobj->window = NULL;
2402
 
    }
2403
 
 
2404
 
    if (cnnhld && cnnhld->cnnwin && cnnobj->scrolled_container)
2405
 
    {
2406
 
        gtk_notebook_remove_page (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook),
2407
 
            gtk_notebook_page_num (GTK_NOTEBOOK (cnnhld->cnnwin->priv->notebook), cnnobj->scrolled_container));
2408
 
    }
2409
 
    g_free (cnnobj);
2410
 
}
2411
 
 
2412
 
static void
2413
 
remmina_connection_object_on_desktop_resize (RemminaProtocolWidget *gp, RemminaConnectionObject *cnnobj)
2414
 
{
2415
 
    if (cnnobj->cnnhld &&
2416
 
        cnnobj->cnnhld->cnnwin &&
2417
 
        cnnobj->cnnhld->cnnwin->priv->view_mode != SCROLLED_WINDOW_MODE)
2418
 
    {
2419
 
        remmina_connection_holder_check_resize (cnnobj->cnnhld);
2420
 
    }
2421
 
}
2422
 
 
2423
 
gboolean
2424
 
remmina_connection_window_open_from_filename (const gchar *filename)
2425
 
{
2426
 
    RemminaFile *remminafile;
2427
 
    GtkWidget *dialog;
2428
 
 
2429
 
    remminafile = remmina_file_manager_load_file (filename);
2430
 
    if (remminafile)
2431
 
    {
2432
 
        remmina_connection_window_open_from_file (remminafile);
2433
 
        return TRUE;
2434
 
    }
2435
 
    else
2436
 
    {
2437
 
        dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
2438
 
            _("File %s not found."), filename);
2439
 
        g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
2440
 
        gtk_widget_show (dialog);
2441
 
        remmina_widget_pool_register (dialog);
2442
 
        return FALSE;
2443
 
    }
2444
 
}
2445
 
 
2446
 
void
2447
 
remmina_connection_window_open_from_file (RemminaFile *remminafile)
2448
 
{
2449
 
    remmina_connection_window_open_from_file_full (remminafile, NULL, NULL, NULL);
2450
 
}
2451
 
 
2452
 
GtkWidget*
2453
 
remmina_connection_window_open_from_file_full (RemminaFile *remminafile,
2454
 
    GCallback disconnect_cb, gpointer data, guint *handler)
2455
 
{
2456
 
    RemminaConnectionObject *cnnobj;
2457
 
    GdkColor color;
2458
 
 
2459
 
    remmina_file_update_screen_resolution (remminafile);
2460
 
 
2461
 
    cnnobj = g_new0 (RemminaConnectionObject, 1);
2462
 
    cnnobj->remmina_file = remminafile;
2463
 
 
2464
 
    /* Create the RemminaProtocolWidget */
2465
 
    cnnobj->proto = remmina_protocol_widget_new ();
2466
 
 
2467
 
    if (data)
2468
 
    {
2469
 
        g_object_set_data (G_OBJECT (cnnobj->proto), "user-data", data);
2470
 
    }
2471
 
 
2472
 
    gtk_widget_show (cnnobj->proto);
2473
 
    g_signal_connect (G_OBJECT (cnnobj->proto), "connect",
2474
 
        G_CALLBACK (remmina_connection_object_on_connect), cnnobj);
2475
 
    if (disconnect_cb)
2476
 
    {
2477
 
        *handler = g_signal_connect (G_OBJECT (cnnobj->proto), "disconnect",
2478
 
            disconnect_cb, data);
2479
 
    }
2480
 
    g_signal_connect (G_OBJECT (cnnobj->proto), "disconnect",
2481
 
        G_CALLBACK (remmina_connection_object_on_disconnect), cnnobj);
2482
 
    g_signal_connect (G_OBJECT (cnnobj->proto), "desktop-resize",
2483
 
        G_CALLBACK (remmina_connection_object_on_desktop_resize), cnnobj);
2484
 
 
2485
 
    /* Create the alignment to make the RemminaProtocolWidget centered */
2486
 
    cnnobj->alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
2487
 
    gtk_widget_show (cnnobj->alignment);
2488
 
    gtk_container_set_border_width (GTK_CONTAINER (cnnobj->alignment), 0);
2489
 
    gtk_container_add (GTK_CONTAINER (cnnobj->alignment), cnnobj->proto);
2490
 
    g_signal_connect (G_OBJECT (cnnobj->alignment), "size-allocate",
2491
 
        G_CALLBACK (remmina_connection_object_alignment_on_allocate), cnnobj);
2492
 
 
2493
 
    /* Create the viewport to make the RemminaProtocolWidget scrollable */
2494
 
    cnnobj->viewport = gtk_viewport_new (NULL, NULL);
2495
 
    gtk_widget_show (cnnobj->viewport);
2496
 
    gdk_color_parse ("black", &color);
2497
 
    gtk_widget_modify_bg (cnnobj->viewport, GTK_STATE_NORMAL, &color);
2498
 
    gtk_container_set_border_width (GTK_CONTAINER (cnnobj->viewport), 0);
2499
 
    gtk_viewport_set_shadow_type (GTK_VIEWPORT (cnnobj->viewport), GTK_SHADOW_NONE);
2500
 
    gtk_container_add (GTK_CONTAINER (cnnobj->viewport), cnnobj->alignment);
2501
 
 
2502
 
    cnnobj->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2503
 
    gtk_widget_realize (cnnobj->window);
2504
 
    gtk_container_add (GTK_CONTAINER (cnnobj->window), cnnobj->viewport);
2505
 
 
2506
 
    if (!remmina_pref.save_view_mode) remmina_file_set_int (cnnobj->remmina_file, "viewmode", remmina_pref.default_mode);
2507
 
 
2508
 
    remmina_protocol_widget_open_connection (REMMINA_PROTOCOL_WIDGET (cnnobj->proto), remminafile);
2509
 
 
2510
 
    return cnnobj->proto;
2511
 
}
2512