/* virt-click * Copyright (C) 2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Parts are derived from 'gvnccapture': * * Vnc Image Capture * * Copyright (C) 2010 Daniel P. Berrange * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "click.h" static void initialized (VncConnection *conn, gpointer opaque); static void disconnected (VncConnection *conn, gpointer opaque); static int click (struct self_t *self, int x, int y, unsigned mask); static void shutdown (self_t *self); static callbacks_t callbacks = { .click = click, .shutdown = shutdown, }; void vc_vnc_setup (self_t *self, gchar *vnc) { gchar *display; gchar *port; if (verbose) vnc_util_set_debug (TRUE); if (vnc[0] == ':') { self->host = g_strdup ("localhost"); display = vnc; } else { self->host = g_strdup (vnc); display = strchr (self->host, ':'); } if (display) { *display = 0; display++; self->port = 5900 + atoi (display); } else self->port = 5900; self->conn = vnc_connection_new (); g_signal_connect (self->conn, "vnc-initialized", G_CALLBACK(initialized), self); g_signal_connect (self->conn, "vnc-disconnected", G_CALLBACK(disconnected), self); g_signal_connect (self->conn, "vnc-auth-choose-type", G_CALLBACK(vc_vnc_auth_choose_type), self); g_signal_connect (self->conn, "vnc-auth-choose-subtype", G_CALLBACK(vc_vnc_auth_choose_type), self); g_signal_connect (self->conn, "vnc-auth-credential", G_CALLBACK(vc_vnc_auth_credential), self); port = g_strdup_printf ("%d", self->port); vnc_connection_open_host (self->conn, self->host, port); self->callbacks = &callbacks; } static void initialized (VncConnection *conn, gpointer opaque) { self_t *self = opaque; gint32 encodings[] = { VNC_CONNECTION_ENCODING_DESKTOP_RESIZE, VNC_CONNECTION_ENCODING_ZRLE, VNC_CONNECTION_ENCODING_HEXTILE, VNC_CONNECTION_ENCODING_RRE, VNC_CONNECTION_ENCODING_COPY_RECT, VNC_CONNECTION_ENCODING_RAW }; gint32 *encodingsp; int n_encodings; if (verbose) fprintf (stderr, "Connected to %s:%d\n", self->host, self->port - 5900); /* Remember that we managed to connect. */ self->connected = TRUE; /* Send encodings. * NB: Although this step is useless, you *MUST* send encodings otherwise * qemu's internal VNC server refuses to parse any other events. */ encodingsp = encodings; n_encodings = G_N_ELEMENTS(encodings); if (!vnc_connection_set_encodings(conn, n_encodings, encodingsp)) { self->ret = EXIT_FAILURE; vnc_connection_shutdown (self->conn); return; } /* Issue the command. */ vc_issue_command (self); } static void disconnected (VncConnection *conn G_GNUC_UNUSED, gpointer opaque) { self_t *self = opaque; if (self->connected) { self->ret = EXIT_SUCCESS; if (verbose) fprintf (stderr, "Disconnected from %s:%d\n", self->host, self->port - 5900); } else { fprintf (stderr, "vnc: unable to connect to %s:%d\n", self->host, self->port - 5900); self->ret = EXIT_FAILURE; } g_main_quit(self->loop); } static void shutdown (self_t *self) { vnc_connection_shutdown (self->conn); g_object_unref (self->conn); g_free(self->host); } /* To perform a button press in VNC we have to send the button press * event, wait a short period, then send a button release event (ie. * no buttons pressed). */ static gboolean click_release (gpointer opaque); static int click (struct self_t *self, int x, int y, unsigned mask) { if (!vnc_connection_pointer_event (self->conn, mask, x, y)) return -1; g_timeout_add (100, click_release, self); } static gboolean click_release (gpointer opaque) { self_t *self = opaque; vnc_connection_pointer_event (self->conn, 0, self->command.click.x, self->command.click.y); vnc_connection_shutdown (self->conn); return FALSE; }