/* 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. */ #include #include #include #include #include #include #include "click.h" static gboolean click_release (gpointer opaque); static int parse_click (self_t *self, gchar **args, guint nr_args) { int b; if (nr_args < 3 || nr_args > 4) return -1; if (sscanf (args[1], "%d", &self->command.click.x) != 1 || sscanf (args[2], "%d", &self->command.click.y) != 1) return -1; b = 1; if (nr_args == 4) { if (strcasecmp (args[3], "left") == 0) b = 1; else if (strcasecmp (args[3], "middle") == 0) b = 2; else if (strcasecmp (args[3], "right") == 0) b = 3; else if (strcasecmp (args[3], "up") == 0) b = 4; else if (strcasecmp (args[3], "down") == 0) b = 5; else if (strcasecmp (args[3], "scrollleft") == 0) b = 6; else if (strcasecmp (args[3], "scrollright") == 0) b = 7; else if (sscanf (args[3], "%d", &b) != 1) return -1; } self->command.click.b = b; self->command.cmd = CMD_CLICK; return 0; } int vc_parse_command (self_t *self, gchar **args, guint nr_args) { if (strcasecmp (args[0], "click") == 0) return parse_click (self, args, nr_args); return -1; } #define NOT_SUPPORTED(cmd) \ do { \ fprintf (stderr, "virt-click: %s: " \ "command is not implemented for this connection type\n", cmd); \ self->ret = EXIT_FAILURE; \ self->callbacks->shutdown (self); \ return; \ } while (0) void vc_issue_command (self_t *self) { int r = -1; switch (self->command.cmd) { case CMD_CLICK: if (verbose) fprintf (stderr, "click x=%d y=%d b=%d\n", self->command.click.x, self->command.click.y, self->command.click.b); if (!self->callbacks->click) NOT_SUPPORTED ("click"); r = self->callbacks->click (self, self->command.click.x, self->command.click.y, self->command.click.b); if (r == -1) goto out; g_timeout_add (100, click_release, self); break; } out: if (r == -1) { fprintf (stderr, "virt-click: error sending command to remote server\n"); self->ret = EXIT_FAILURE; self->callbacks->shutdown (self); } } /* 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) { self_t *self = opaque; if (verbose) fprintf (stderr, "click release x=%d y=%d\n", self->command.click.x, self->command.click.y); self->callbacks->click (self, self->command.click.x, self->command.click.y, 0); self->callbacks->shutdown (self); return FALSE; }