Initial version, --vnc option only working.
[virt-click.git] / vnc.c
1 /* virt-click
2  * Copyright (C) 2011 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * Parts are derived from 'gvnccapture':
19  *
20  * Vnc Image Capture
21  *
22  * Copyright (C) 2010 Daniel P. Berrange <dan@berrange.com>
23  *
24  * This library is free software; you can redistribute it and/or
25  * modify it under the terms of the GNU Lesser General Public
26  * License as published by the Free Software Foundation; either
27  * version 2.0 of the License, or (at your option) any later version.
28  *
29  * This library is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32  * Lesser General Public License for more details.
33  *
34  * You should have received a copy of the GNU Lesser General Public
35  * License along with this library; if not, write to the Free Software
36  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
37  */
38
39 #include <config.h>
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #include <glib/gi18n.h>
47 #include <vncconnection.h>
48 #include <vncbaseframebuffer.h>
49
50 #include "click.h"
51
52 static void initialized (VncConnection *conn, gpointer opaque);
53 static void disconnected (VncConnection *conn, gpointer opaque);
54 static int click (struct self_t *self, int x, int y, unsigned mask);
55 static void shutdown (self_t *self);
56
57 static callbacks_t callbacks = {
58   .click = click,
59   .shutdown = shutdown,
60 };
61
62 void
63 vc_vnc_setup (self_t *self, gchar *vnc)
64 {
65   gchar *display;
66   gchar *port;
67
68   if (verbose)
69     vnc_util_set_debug (TRUE);
70
71   if (vnc[0] == ':') {
72     self->host = g_strdup ("localhost");
73     display = vnc;
74   } else {
75     self->host = g_strdup (vnc);
76     display = strchr (self->host, ':');
77   }
78   if (display) {
79     *display = 0;
80     display++;
81     self->port = 5900 + atoi (display);
82   } else
83     self->port = 5900;
84
85   self->conn = vnc_connection_new ();
86
87   g_signal_connect (self->conn, "vnc-initialized",
88                     G_CALLBACK(initialized), self);
89   g_signal_connect (self->conn, "vnc-disconnected",
90                     G_CALLBACK(disconnected), self);
91   g_signal_connect (self->conn, "vnc-auth-choose-type",
92                     G_CALLBACK(vc_vnc_auth_choose_type), self);
93   g_signal_connect (self->conn, "vnc-auth-choose-subtype",
94                     G_CALLBACK(vc_vnc_auth_choose_type), self);
95   g_signal_connect (self->conn, "vnc-auth-credential",
96                     G_CALLBACK(vc_vnc_auth_credential), self);
97
98   port = g_strdup_printf ("%d", self->port);
99   vnc_connection_open_host (self->conn, self->host, port);
100
101   self->callbacks = &callbacks;
102 }
103
104 static void
105 initialized (VncConnection *conn,
106              gpointer opaque)
107 {
108   self_t *self = opaque;
109   gint32 encodings[] = {  VNC_CONNECTION_ENCODING_DESKTOP_RESIZE,
110                           VNC_CONNECTION_ENCODING_ZRLE,
111                           VNC_CONNECTION_ENCODING_HEXTILE,
112                           VNC_CONNECTION_ENCODING_RRE,
113                           VNC_CONNECTION_ENCODING_COPY_RECT,
114                           VNC_CONNECTION_ENCODING_RAW };
115   gint32 *encodingsp;
116   int n_encodings;
117
118   if (verbose)
119     fprintf (stderr, "Connected to %s:%d\n", self->host, self->port - 5900);
120
121   /* Remember that we managed to connect. */
122   self->connected = TRUE;
123
124   /* Send encodings.
125    * NB: Although this step is useless, you *MUST* send encodings otherwise
126    * qemu's internal VNC server refuses to parse any other events.
127    */
128   encodingsp = encodings;
129   n_encodings = G_N_ELEMENTS(encodings);
130
131   if (!vnc_connection_set_encodings(conn, n_encodings, encodingsp)) {
132     self->ret = EXIT_FAILURE;
133     vnc_connection_shutdown (self->conn);
134     return;
135   }
136
137   /* Issue the command. */
138   vc_issue_command (self);
139 }
140
141 static void
142 disconnected (VncConnection *conn G_GNUC_UNUSED,
143               gpointer opaque)
144 {
145   self_t *self = opaque;
146
147   if (self->connected) {
148     self->ret = EXIT_SUCCESS;
149     if (verbose)
150       fprintf (stderr, "Disconnected from %s:%d\n",
151                self->host, self->port - 5900);
152   } else {
153     fprintf (stderr, "vnc: unable to connect to %s:%d\n",
154              self->host, self->port - 5900);
155     self->ret = EXIT_FAILURE;
156   }
157
158   g_main_quit(self->loop);
159 }
160
161 static void
162 shutdown (self_t *self)
163 {
164   vnc_connection_shutdown (self->conn);
165   g_object_unref (self->conn);
166   g_free(self->host);
167 }
168
169 /* To perform a button press in VNC we have to send the button press
170  * event, wait a short period, then send a button release event (ie.
171  * no buttons pressed).
172  */
173 static gboolean click_release (gpointer opaque);
174
175 static int
176 click (struct self_t *self, int x, int y, unsigned mask)
177 {
178   if (!vnc_connection_pointer_event (self->conn, mask, x, y))
179     return -1;
180
181   g_timeout_add (100, click_release, self);
182 }
183
184 static gboolean
185 click_release (gpointer opaque)
186 {
187   self_t *self = opaque;
188
189   vnc_connection_pointer_event (self->conn, 0,
190                                 self->command.click.x, self->command.click.y);
191
192   vnc_connection_shutdown (self->conn);
193
194   return FALSE;
195 }