/* $Id$ */ static char const _copyright[] = "Copyright © 2006 Anthony Liguori \n" "Copyright © 2015-2020 Pierre Pronchery "; /* This file is part of DeforaOS Desktop VNCViewer */ static char const _license[] = "This software is originally based on the GTK VNC Widget library.\n" "\n" "Copyright © 2006 Anthony Liguori \n" "\n" "This library is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU Lesser General Public\n" "License as published by the Free Software Foundation; either\n" "version 2.0 of the License, or (at your option) any later version.\n" "\n" "This library is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" "Lesser General Public License for more details.\n" "\n" "You should have received a copy of the GNU Lesser General Public\n" "License along with this library; if not, write to the Free Software\n" "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA"; /* FIXME: * - disable grabbing mouse/keyboard on disconnect * - fix message dialog when the connection is already busy */ #include #include #ifdef HAVE_PULSEAUDIO #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_GIOUNIX #include #endif #if WITH_LIBVIEW #include #endif #include "vncviewer.h" #include "../config.h" #define _(string) gettext(string) /* constants */ #ifndef PROGNAME_VNCVIEWER # define PROGNAME_VNCVIEWER "vncviewer" #endif #ifdef HAVE_PULSEAUDIO static VncAudioPulse *pa = NULL; #endif static GtkWidget *vnc = NULL; static GtkWidget *status; static GtkWidget *statusbar; static char const * _authors[] = { "Anthony Liguori ", "Pierre Pronchery ", NULL }; typedef struct { GtkWidget *label; guint curkeys; guint numkeys; guint *keysyms; gboolean set; } VncGrabDefs; gboolean enable_mnemonics_save; GtkAccelGroup *accel_group; gboolean accel_enabled = TRUE; GValue accel_setting; GSList *accel_list; static void set_status(char const * format, ...) { va_list ap; guint id; gchar *status; va_start(ap, format); if (vnc != NULL) { id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), ""); status = g_strdup_vprintf(format, ap); gtk_statusbar_pop(GTK_STATUSBAR(statusbar), id); gtk_statusbar_push(GTK_STATUSBAR(statusbar), id, status); g_free(status); } else { fputs(PROGNAME_VNCVIEWER ": ", stderr); vfprintf(stderr, format, ap); fputc('\n', stderr); } va_end(ap); } static void set_title(VncDisplay *vncdisplay, GtkWidget *window, gboolean grabbed) { const gchar *name = vnc_display_get_name(VNC_DISPLAY(vncdisplay)); VncGrabSequence *seq = vnc_display_get_grab_keys(vncdisplay); gchar *seqstr = vnc_grab_sequence_as_string(seq); gchar *title; if (grabbed) { if (name != NULL) title = g_strdup_printf( _("%s - %s (Press %s to release pointer)"), PACKAGE, name, seqstr); else title = g_strdup_printf( _("%s (Press %s to release pointer)"), PACKAGE, seqstr); } else if(name != NULL) title = g_strdup_printf("%s - %s", PACKAGE, name); else title = g_strdup(PACKAGE); gtk_window_set_title(GTK_WINDOW(window), title); g_free(seqstr); g_free(title); } static void vnc_screenshot(GtkWidget *widget G_GNUC_UNUSED, gpointer data) { GtkWidget * vncdisplay = data; const char filename[] = "vncviewer.png"; GdkPixbuf * pix; if((pix = vnc_display_get_pixbuf(VNC_DISPLAY(vncdisplay))) != NULL) { gdk_pixbuf_save(pix, filename, "png", NULL, "tEXt::Generator App", "vncviewer", NULL); g_object_unref(pix); set_status(_("Screenshot saved to %s"), filename); } } static void vnc_disable_modifiers(GtkWindow *window) { GtkSettings *settings = gtk_settings_get_default(); GValue empty; GSList *accels; if (!accel_enabled) return; /* This stops F10 activating menu bar */ memset(&empty, 0, sizeof empty); g_value_init(&empty, G_TYPE_STRING); g_object_get_property(G_OBJECT(settings), "gtk-menu-bar-accel", &accel_setting); g_object_set_property(G_OBJECT(settings), "gtk-menu-bar-accel", &empty); /* This stops global accelerators like Ctrl+Q == Quit */ for (accels = accel_list ; accels ; accels = accels->next) { if (accel_group == accels->data) continue; gtk_window_remove_accel_group(GTK_WINDOW(window), accels->data); } /* This stops menu bar shortcuts like Alt+F == File */ g_object_get(settings, "gtk-enable-mnemonics", &enable_mnemonics_save, NULL); g_object_set(settings, "gtk-enable-mnemonics", FALSE, NULL); accel_enabled = FALSE; } static void vnc_enable_modifiers(GtkWindow *window) { GtkSettings *settings = gtk_settings_get_default(); GSList *accels; if (accel_enabled) return; /* This allows F10 activating menu bar */ g_object_set_property(G_OBJECT(settings), "gtk-menu-bar-accel", &accel_setting); /* This allows global accelerators like Ctrl+Q == Quit */ for (accels = accel_list ; accels ; accels = accels->next) { if (accel_group == accels->data) continue; gtk_window_add_accel_group(GTK_WINDOW(window), accels->data); } /* This allows menu bar shortcuts like Alt+F == File */ g_object_set(settings, "gtk-enable-mnemonics", enable_mnemonics_save, NULL); accel_enabled = TRUE; } static void vnc_key_grab(GtkWidget *vncdisplay G_GNUC_UNUSED, GtkWidget *window) { vnc_disable_modifiers(GTK_WINDOW(window)); } static void vnc_key_ungrab(GtkWidget *vncdisplay G_GNUC_UNUSED, GtkWidget *window) { vnc_enable_modifiers(GTK_WINDOW(window)); } static void vnc_mouse_grab(GtkWidget *vncdisplay, GtkWidget *window) { set_title(VNC_DISPLAY(vncdisplay), window, TRUE); } static void vnc_mouse_ungrab(GtkWidget *vncdisplay, GtkWidget *window) { set_title(VNC_DISPLAY(vncdisplay), window, FALSE); } static int connected = 0; static void vnc_connected(GtkWidget *vncdisplay G_GNUC_UNUSED) { set_status(_("Connected to server")); gtk_image_set_from_icon_name(GTK_IMAGE(status), "gtk-connect", GTK_ICON_SIZE_MENU); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(status, _("Connected")); #endif connected = 1; } static void vnc_initialized(GtkWidget *vncdisplay, GtkWidget *window) { set_status(_("Connection initialized")); set_title(VNC_DISPLAY(vncdisplay), window, FALSE); gtk_widget_show_all(window); #ifdef HAVE_PULSEAUDIO VncConnection *conn; VncAudioFormat format = { VNC_AUDIO_FORMAT_RAW_S32, 2, 44100, }; conn = vnc_display_get_connection(VNC_DISPLAY(vncdisplay)); vnc_connection_set_audio_format(conn, &format); vnc_connection_set_audio(conn, VNC_AUDIO(pa)); vnc_connection_audio_enable(conn); #endif } static void vnc_auth_failure(GtkWidget *vncdisplay G_GNUC_UNUSED, const char *msg) { set_status(_("Authentication failed '%s'"), msg ? msg : ""); } static void vnc_desktop_resize(GtkWidget *vncdisplay G_GNUC_UNUSED, int width, int height) { set_status(_("Remote desktop size changed to %dx%d"), width, height); } static void vnc_disconnected(GtkWidget *vncdisplay G_GNUC_UNUSED, GtkWidget *window) { if(connected) set_status(_("Disconnected from server")); else set_status(_("Failed to connect to server")); gtk_image_set_from_icon_name(GTK_IMAGE(status), "gtk-disconnect", GTK_ICON_SIZE_MENU); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(status, _("Disconnected")); #endif gtk_widget_show_all(window); connected = 0; } static void send_caf1(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F1 }; set_status(_("Sending Ctrl+Alt+F1")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf2(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F2 }; set_status(_("Sending Ctrl+Alt+F2")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf3(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F3 }; set_status(_("Sending Ctrl+Alt+F3")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf4(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F4 }; set_status(_("Sending Ctrl+Alt+F4")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf5(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F5 }; set_status(_("Sending Ctrl+Alt+F5")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf6(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F6 }; set_status(_("Sending Ctrl+Alt+F6")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf7(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F7 }; set_status(_("Sending Ctrl+Alt+F7")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_caf8(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F8 }; set_status(_("Sending Ctrl+Alt+F8")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_cad(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete }; set_status(_("Sending Ctrl+Alt+Delete")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void send_cab(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) { guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_BackSpace }; set_status(_("Sending Ctrl+Alt+Backspace")); vnc_display_send_keys(VNC_DISPLAY(vncdisplay), keys, sizeof(keys)/sizeof(keys[0])); } static void do_about(GtkWidget *menu, GtkWidget *window) { GtkWidget *dialog; (void) menu; dialog = gtk_about_dialog_new(); gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(window)); gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), _authors); gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("VNC client for the DeforaOS desktop")); gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), _copyright); gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "gnome-remote-desktop"); gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog), _license); #if GTK_CHECK_VERSION(2, 12, 0) gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), PACKAGE); #else gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog), PACKAGE); #endif gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), VERSION); gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "https://www.defora.org/"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } static void do_fullscreen(GtkWidget *menu, GtkWidget *window) { if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) { gtk_widget_hide(statusbar); gtk_window_fullscreen(GTK_WINDOW(window)); } else { gtk_window_unfullscreen(GTK_WINDOW(window)); gtk_widget_show(statusbar); } } static void do_scaling(GtkWidget *menu, GtkWidget *vncdisplay) { if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) vnc_display_set_scaling(VNC_DISPLAY(vncdisplay), TRUE); else vnc_display_set_scaling(VNC_DISPLAY(vncdisplay), FALSE); } static void dialog_update_keysyms(GtkWidget *window, guint *keysyms, guint numsyms) { gchar *keys; guint i; keys = g_strdup(""); for (i = 0; i < numsyms; i++) keys = g_strdup_printf("%s%s%s", keys, (strlen(keys) > 0) ? "+" : " ", gdk_keyval_name(keysyms[i])); gtk_label_set_text( GTK_LABEL(window), keys); } static gboolean dialog_key_ignore(int keyval) { switch (keyval) { case GDK_KEY_Return: case GDK_KEY_Escape: return TRUE; default: return FALSE; } } static gboolean dialog_key_press(GtkWidget *window G_GNUC_UNUSED, GdkEvent *ev, VncGrabDefs *defs) { gboolean keySymExists; guint i; if (dialog_key_ignore(ev->key.keyval)) return FALSE; if (defs->set && defs->curkeys) return FALSE; /* Check whether we already have keysym in array - i.e. it was handler by something else */ keySymExists = FALSE; for (i = 0; i < defs->curkeys; i++) { if (defs->keysyms[i] == ev->key.keyval) keySymExists = TRUE; } if (!keySymExists) { defs->keysyms = g_renew(guint, defs->keysyms, defs->curkeys + 1); defs->keysyms[defs->curkeys] = ev->key.keyval; defs->curkeys++; } dialog_update_keysyms(defs->label, defs->keysyms, defs->curkeys); if (!ev->key.is_modifier) { defs->set = TRUE; defs->numkeys = defs->curkeys; defs->curkeys--; } return FALSE; } static gboolean dialog_key_release(GtkWidget *window G_GNUC_UNUSED, GdkEvent *ev, VncGrabDefs *defs) { guint i; if (dialog_key_ignore(ev->key.keyval)) return FALSE; if (defs->set) { if (defs->curkeys == 0) defs->set = FALSE; else defs->curkeys--; return FALSE; } for (i = 0; i < defs->curkeys; i++) if (defs->keysyms[i] == ev->key.keyval) { defs->keysyms[i] = defs->keysyms[defs->curkeys - 1]; defs->curkeys--; defs->keysyms = g_renew(guint, defs->keysyms, defs->curkeys); } dialog_update_keysyms(defs->label, defs->keysyms, defs->curkeys); return FALSE; } static void do_set_grab_keys(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *window) { VncGrabDefs *defs; VncGrabSequence *seq; GtkWidget *dialog, *content_area, *label; gint result; dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, #if GTK_CHECK_VERSION(2, 6, 0) "%s", _("Key recorder")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), #endif _("Please press desired grab key combination")); #if GTK_CHECK_VERSION(2, 10, 0) gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog), gtk_image_new_from_icon_name("gtk-media-record", GTK_ICON_SIZE_DIALOG)); #endif gtk_window_set_title(GTK_WINDOW(dialog), _("Key recorder")); label = gtk_label_new(""); defs = g_new(VncGrabDefs, 1); defs->label = label; defs->keysyms = 0; defs->numkeys = 0; defs->curkeys = 0; defs->set = FALSE; g_signal_connect(dialog, "key-press-event", G_CALLBACK(dialog_key_press), defs); g_signal_connect(dialog, "key-release-event", G_CALLBACK(dialog_key_release), defs); #if GTK_CHECK_VERSION(2, 14, 0) content_area = gtk_dialog_get_content_area( GTK_DIALOG(dialog) ); #else content_area = dialog->vbox; #endif gtk_container_add( GTK_CONTAINER(content_area), label); gtk_widget_show_all(dialog); result = gtk_dialog_run(GTK_DIALOG(dialog)); if (result == GTK_RESPONSE_ACCEPT) { /* Accepted so we make a grab sequence from it */ seq = vnc_grab_sequence_new(defs->numkeys, defs->keysyms); vnc_display_set_grab_keys(VNC_DISPLAY(vnc), seq); set_title(VNC_DISPLAY(vnc), window, FALSE); vnc_grab_sequence_free(seq); } g_free(defs); gtk_widget_destroy(dialog); } static void vnc_credential(GtkWidget *vncdisplay, GValueArray *credList) { GtkWidget *dialog = NULL; int response; unsigned int i, prompt = 0; const char **data; set_status(_("Got credential request for %d credential(s)"), credList->n_values); data = g_new0(const char *, credList->n_values); for (i = 0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); switch (g_value_get_enum(cred)) { case VNC_DISPLAY_CREDENTIAL_USERNAME: case VNC_DISPLAY_CREDENTIAL_PASSWORD: prompt++; break; case VNC_DISPLAY_CREDENTIAL_CLIENTNAME: data[i] = PACKAGE; default: break; } } if (prompt) { GtkWidget **label, **entry, *box, *vbox; int row; dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, #if GTK_CHECK_VERSION(2, 6, 0) "%s", _("Authentication required")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), #endif ""); #if GTK_CHECK_VERSION(2, 10, 0) gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog), gtk_image_new_from_icon_name( "gtk-dialog-authentication", GTK_ICON_SIZE_DIALOG)); #endif gtk_window_set_title(GTK_WINDOW(dialog), _("Authentication required")); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); box = gtk_table_new(credList->n_values, 2, FALSE); label = g_new(GtkWidget *, prompt); entry = g_new(GtkWidget *, prompt); for (i = 0, row =0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); entry[row] = gtk_entry_new(); switch (g_value_get_enum(cred)) { case VNC_DISPLAY_CREDENTIAL_USERNAME: label[row] = gtk_label_new(_("Username: ")); break; case VNC_DISPLAY_CREDENTIAL_PASSWORD: label[row] = gtk_label_new(_("Password: ")); gtk_entry_set_activates_default(GTK_ENTRY(entry[row]), TRUE); break; default: continue; } if (g_value_get_enum (cred) == VNC_DISPLAY_CREDENTIAL_PASSWORD) gtk_entry_set_visibility (GTK_ENTRY (entry[row]), FALSE); gtk_table_attach(GTK_TABLE(box), label[i], 0, 1, row, row+1, GTK_SHRINK, GTK_SHRINK, 3, 3); gtk_table_attach(GTK_TABLE(box), entry[i], 1, 2, row, row+1, GTK_SHRINK, GTK_SHRINK, 3, 3); row++; } vbox = gtk_bin_get_child(GTK_BIN(dialog)); gtk_container_add(GTK_CONTAINER(vbox), box); gtk_widget_show_all(dialog); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide(GTK_WIDGET(dialog)); if (response == GTK_RESPONSE_OK) { for (i = 0, row = 0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); switch (g_value_get_enum(cred)) { case VNC_DISPLAY_CREDENTIAL_USERNAME: case VNC_DISPLAY_CREDENTIAL_PASSWORD: data[i] = gtk_entry_get_text(GTK_ENTRY(entry[row])); break; default: continue; } row++; } } } for (i = 0 ; i < credList->n_values ; i++) { GValue *cred = g_value_array_get_nth(credList, i); if (data[i]) { if (vnc_display_set_credential(VNC_DISPLAY(vncdisplay), g_value_get_enum(cred), data[i])) { set_status(_("Failed to set credential type %d"), g_value_get_enum(cred)); vnc_display_close(VNC_DISPLAY(vncdisplay)); } } else { set_status(_("Unsupported credential type %d"), g_value_get_enum(cred)); vnc_display_close(VNC_DISPLAY(vncdisplay)); } } g_free(data); if (dialog) gtk_widget_destroy(GTK_WIDGET(dialog)); } #if WITH_LIBVIEW static gboolean window_state_event(GtkWidget *widget, GdkEventWindowState *event, gpointer data) { ViewAutoDrawer *drawer = VIEW_AUTODRAWER(data); if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) { if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) { vnc_display_force_grab(VNC_DISPLAY(vnc), TRUE); ViewAutoDrawer_SetActive(drawer, TRUE); } else { vnc_display_force_grab(VNC_DISPLAY(vnc), FALSE); ViewAutoDrawer_SetActive(drawer, FALSE); } } return FALSE; } #endif int vncviewer(gchar ** args) { GtkWidget *window; GtkWidget *layout; GtkWidget *menubar; GtkWidget *file, *sendkey, *view, *settings, *help; GtkWidget *submenu; GtkWidget *screenshot; GtkWidget *menuitem; GtkWidget *close; GtkWidget *caf1; GtkWidget *caf2; GtkWidget *caf3; GtkWidget *caf4; GtkWidget *caf5; GtkWidget *caf6; GtkWidget *caf7; GtkWidget *caf8; GtkWidget *cad; GtkWidget *cab; GtkWidget *fullscreen; GtkWidget *scaling; GtkWidget *about; GtkWidget *showgrabkeydlg; GtkWidget *widget; GSList *accels; gchar *tmp; gchar *hostname; gchar *port; vnc = vnc_display_new(); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_icon_name(GTK_WINDOW(window), "gnome-remote-desktop"); #if WITH_LIBVIEW layout = ViewAutoDrawer_New(); #elif GTK_CHECK_VERSION(3, 0, 0) layout = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); #else layout = gtk_vbox_new(FALSE, 0); #endif menubar = gtk_menu_bar_new(); #ifdef HAVE_PULSEAUDIO pa = vnc_audio_pulse_new(); #endif gtk_window_set_resizable(GTK_WINDOW(window), TRUE); gtk_window_set_title(GTK_WINDOW(window), PACKAGE); file = gtk_menu_item_new_with_mnemonic(_("_File")); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file); submenu = gtk_menu_new(); screenshot = gtk_image_menu_item_new_with_mnemonic(_("Save _screenshot")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(screenshot), gtk_image_new_from_icon_name("gtk-save", GTK_ICON_SIZE_MENU)); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), screenshot); menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); close = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), close); gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), submenu); sendkey = gtk_menu_item_new_with_mnemonic(_("_Send Key")); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), sendkey); submenu = gtk_menu_new(); caf1 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_1")); caf2 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_2")); caf3 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_3")); caf4 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_4")); caf5 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_5")); caf6 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_6")); caf7 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_7")); caf8 = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+F_8")); cad = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+_Del")); cab = gtk_menu_item_new_with_mnemonic(_("Ctrl+Alt+_Backspace")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf1); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf2); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf3); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf4); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf5); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf6); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf7); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), caf8); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), cad); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), cab); gtk_menu_item_set_submenu(GTK_MENU_ITEM(sendkey), submenu); view = gtk_menu_item_new_with_mnemonic(_("_View")); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), view); submenu = gtk_menu_new(); fullscreen = gtk_check_menu_item_new_with_mnemonic(_("_Full Screen")); scaling = gtk_check_menu_item_new_with_mnemonic(_("Scaled display")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), fullscreen); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), scaling); gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), submenu); settings = gtk_menu_item_new_with_mnemonic(_("_Settings")); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), settings); submenu = gtk_menu_new(); showgrabkeydlg = gtk_menu_item_new_with_mnemonic(_("_Set grab keys")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), showgrabkeydlg); gtk_menu_item_set_submenu(GTK_MENU_ITEM(settings), submenu); help = gtk_menu_item_new_with_mnemonic(_("_Help")); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), help); submenu = gtk_menu_new(); about = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), about); gtk_menu_item_set_submenu(GTK_MENU_ITEM(help), submenu); #if GTK_CHECK_VERSION(3, 0, 0) widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); #else widget = gtk_hbox_new(FALSE, 4); #endif status = gtk_image_new_from_icon_name("gtk-disconnect", GTK_ICON_SIZE_MENU); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(status, _("Disconnected")); #endif gtk_box_pack_start(GTK_BOX(widget), status, FALSE, TRUE, 0); statusbar = gtk_statusbar_new(); #if !GTK_CHECK_VERSION(3, 0, 0) gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), TRUE); #endif gtk_box_pack_start(GTK_BOX(widget), statusbar, TRUE, TRUE, 0); #if WITH_LIBVIEW ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(layout), FALSE); ViewOvBox_SetOver(VIEW_OV_BOX(layout), menubar); ViewOvBox_SetUnder(VIEW_OV_BOX(layout), vnc); ViewOvBox_SetUnder(VIEW_OV_BOX(layout), widget); #else gtk_box_pack_start(GTK_BOX(layout), menubar, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(layout), vnc, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(layout), widget, FALSE, TRUE, 0); #endif gtk_container_add(GTK_CONTAINER(window), layout); gtk_widget_realize(vnc); g_value_init(&accel_setting, G_TYPE_STRING); accels = gtk_accel_groups_from_object(G_OBJECT(window)); for ( ; accels ; accels = accels->next) { accel_list = g_slist_append(accel_list, accels->data); g_object_ref(G_OBJECT(accels->data)); } #ifdef HAVE_GIOUNIX if (strchr(args[0], '/')) { GSocketAddress *addr = g_unix_socket_address_new_with_type (args[0], strlen(args[0]), G_UNIX_SOCKET_ADDRESS_PATH); vnc_display_open_addr(VNC_DISPLAY(vnc), addr, NULL); g_object_unref(addr); } else { #endif if (g_str_equal(args[0], "")) hostname = g_strdup("127.0.0.1"); else hostname = g_strdup(args[0]); tmp = strchr(hostname, ':'); if (tmp) { *tmp = '\0'; port = g_strdup_printf("%d", 5900 + atoi(tmp + 1)); } else { port = g_strdup("5900"); } vnc_display_open_host(VNC_DISPLAY(vnc), hostname, port); g_free(hostname); g_free(port); #ifdef HAVE_GIOUNIX } #endif vnc_display_set_keyboard_grab(VNC_DISPLAY(vnc), TRUE); vnc_display_set_pointer_grab(VNC_DISPLAY(vnc), TRUE); vnc_display_set_pointer_local(VNC_DISPLAY(vnc), TRUE); if (!gtk_widget_is_composited(window)) { vnc_display_set_scaling(VNC_DISPLAY(vnc), TRUE); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(scaling), TRUE); } g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(vnc, "vnc-connected", G_CALLBACK(vnc_connected), NULL); g_signal_connect(vnc, "vnc-initialized", G_CALLBACK(vnc_initialized), window); g_signal_connect(vnc, "vnc-disconnected", G_CALLBACK(vnc_disconnected), window); g_signal_connect(vnc, "vnc-auth-credential", G_CALLBACK(vnc_credential), NULL); g_signal_connect(vnc, "vnc-auth-failure", G_CALLBACK(vnc_auth_failure), NULL); g_signal_connect(vnc, "vnc-desktop-resize", G_CALLBACK(vnc_desktop_resize), NULL); g_signal_connect(vnc, "vnc-pointer-grab", G_CALLBACK(vnc_mouse_grab), window); g_signal_connect(vnc, "vnc-pointer-ungrab", G_CALLBACK(vnc_mouse_ungrab), window); g_signal_connect(vnc, "vnc-keyboard-grab", G_CALLBACK(vnc_key_grab), window); g_signal_connect(vnc, "vnc-keyboard-ungrab", G_CALLBACK(vnc_key_ungrab), window); g_signal_connect(screenshot, "activate", G_CALLBACK(vnc_screenshot), vnc); g_signal_connect(close, "activate", G_CALLBACK(gtk_main_quit), vnc); g_signal_connect(caf1, "activate", G_CALLBACK(send_caf1), vnc); g_signal_connect(caf2, "activate", G_CALLBACK(send_caf2), vnc); g_signal_connect(caf3, "activate", G_CALLBACK(send_caf3), vnc); g_signal_connect(caf4, "activate", G_CALLBACK(send_caf4), vnc); g_signal_connect(caf5, "activate", G_CALLBACK(send_caf5), vnc); g_signal_connect(caf6, "activate", G_CALLBACK(send_caf6), vnc); g_signal_connect(caf7, "activate", G_CALLBACK(send_caf7), vnc); g_signal_connect(caf8, "activate", G_CALLBACK(send_caf8), vnc); g_signal_connect(cad, "activate", G_CALLBACK(send_cad), vnc); g_signal_connect(cab, "activate", G_CALLBACK(send_cab), vnc); g_signal_connect(showgrabkeydlg, "activate", G_CALLBACK(do_set_grab_keys), window); g_signal_connect(fullscreen, "toggled", G_CALLBACK(do_fullscreen), window); g_signal_connect(scaling, "toggled", G_CALLBACK(do_scaling), vnc); g_signal_connect(about, "activate", G_CALLBACK(do_about), window); #if WITH_LIBVIEW g_signal_connect(window, "window-state-event", G_CALLBACK(window_state_event), layout); #endif return 0; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * indent-tabs-mode: nil * End: */