File keymap.diff of Package virt-viewer
Index: virt-viewer-0.0.3/src/keymap.c
===================================================================
--- /dev/null
+++ virt-viewer-0.0.3/src/keymap.c
@@ -0,0 +1,411 @@
+/*
+ * keymap.c: Reads keymap XML definition file populating keyComboDef
+ * structures
+ *
+ * Copyright (C) 2008 Novell,
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pat Campbell <plc@novell.com>
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <libxml/xpath.h>
+
+#include "viewer.h"
+
+#define ITEM_PATH "//keymap/item"
+#define ROOT "keymap"
+#define ITEM "item"
+#define TYPE "type"
+#define MENU "menu"
+#define SEP "separator"
+#define LABEL "label"
+#define KEYS "keys"
+#define KEY "key"
+#define DEFAULT_KEY_XML "/usr/share/virt-viewer/keymap.xml"
+
+static int verbose = 0;
+
+static int create_keyCombos(SendKeyItems * sendKeyItems, xmlXPathContextPtr ctxt)
+{
+ xmlXPathObjectPtr obj;
+ xmlNodePtr relnode;
+ SendKeyItems old_sendKeyItems;
+
+ if (ctxt == NULL) {
+ fprintf(stderr,"Invalid parser context to %s", __func__);
+ goto error;
+ }
+ relnode = ctxt->node;
+
+ /*
+ * Determine number of items
+ */
+ obj = xmlXPathEval((xmlChar *)ITEM_PATH, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_NODESET)) {
+ xmlXPathFreeObject(obj);
+ fprintf(stderr, "Error obj NULL or type not a NODESET");
+ goto error;
+ }
+ old_sendKeyItems.keyCombos = sendKeyItems->keyCombos;
+ old_sendKeyItems.cnt = sendKeyItems->cnt;
+
+ sendKeyItems->cnt = xmlXPathNodeSetGetLength(obj->nodesetval);
+ if (sendKeyItems->cnt) {
+ sendKeyItems->keyCombos = calloc(sendKeyItems->cnt, sizeof(struct keyComboDef *));
+ if (!sendKeyItems->keyCombos) {
+ sendKeyItems->keyCombos = old_sendKeyItems.keyCombos;
+ sendKeyItems->cnt = old_sendKeyItems.cnt;
+ }
+ else if (old_sendKeyItems.keyCombos) {
+ int i;
+ for (i = 0; i < old_sendKeyItems.cnt; i++) {
+ free(old_sendKeyItems.keyCombos[i]->keys);
+ free(old_sendKeyItems.keyCombos[i]->label);
+ }
+ free(old_sendKeyItems.keyCombos);
+ }
+ }
+ ctxt->node = relnode;
+ xmlXPathFreeObject(obj);
+error:
+ return(sendKeyItems->cnt);
+}
+
+static void build_keyComboDef(SendKeyItems *sendKeyItems, guint *keys, int cnt, const char * label)
+{
+ int i;
+ struct keyComboDef *kp;
+
+ kp = (struct keyComboDef*)calloc(sizeof(guint *) + sizeof(guint) + sizeof(char *), 1);
+ if (!kp)
+ return;
+
+ if (keys) {
+ kp->keys = (guint *)malloc((sizeof(guint) * cnt) );
+ if (!kp->keys) {
+ free(kp);
+ return;
+ }
+ for(i=0; i<cnt; i++) {
+ kp->keys[i] = keys[i];
+ }
+ }
+ if (label) {
+ kp->label = strdup(label);
+ }
+ else {
+ kp->label = strdup("Unknown");
+ }
+ kp->nkeys = cnt;
+
+ for (i = 0; i < sendKeyItems->cnt; i++) {
+ if ( sendKeyItems->keyCombos[i] == NULL) {
+ sendKeyItems->keyCombos[i] = kp;
+ break;
+ }
+ }
+}
+
+static char *trim(char *str)
+{
+ char * p = str;
+
+ p += strlen(str);
+
+ /* trim trailing */
+ while(p != str) {
+ if (*p == '\n' || *p == '\t' || *p == ' ' || *p == '\0') {
+ *p = '\0';
+ p--;
+ continue;
+ }
+ break;
+ }
+ /* trim leading */
+ p = str;
+ while(p != '\0') {
+ if (*p == '\n' || *p == '\t' || *p == ' ') {
+ p++;
+ continue;
+ }
+ break;
+ }
+ if (p != str) {
+ memcpy(str, p, strlen(p) + 1);
+ }
+ return(str);
+}
+
+static void process_keys(SendKeyItems *sendKeyItems, xmlDocPtr xml, xmlXPathContextPtr ctxt,
+ xmlNode * node, char *label)
+{
+ xmlNode *n;
+ int cnt = 0;
+ int i = 0;
+ guint * keys;
+ xmlXPathObjectPtr obj;
+ char *str;
+
+ if (!node || !node->children) return;
+
+ /*
+ * get number of keys
+ */
+ for(n=node->children; n; n=n->next) {
+ if (n->type != XML_ELEMENT_NODE) continue;
+ cnt++;
+ }
+
+ if (cnt) {
+ keys = malloc(sizeof(guint) * cnt);
+ if (keys) {
+ for(i = 0, n=node->children; n; n=n->next) {
+ if (n->type != XML_ELEMENT_NODE) continue;
+ obj = xmlXPathEval(xmlGetNodePath(n), ctxt);
+ str = (char *)xmlNodeListGetString(xml, obj->nodesetval->nodeTab[0]->xmlChildrenNode, 1);
+ trim(str);
+ keys[i] = gdk_keyval_from_name(str);
+ if (keys[i] == 0) {
+ if (verbose) {
+ fprintf(stderr, "virt-viewer: Could not get keyval for %s:%s, ignoring\n",
+ str, label);
+ }
+ free(keys);
+ sendKeyItems->cnt--;
+ return;
+ }
+ i++;
+ }
+ build_keyComboDef(sendKeyItems, keys, cnt, label);
+ }
+ }
+}
+
+static void process_item(SendKeyItems * sendKeyItems, xmlDocPtr xml,
+ xmlXPathContextPtr ctxt, xmlNode * node)
+{
+ xmlNode *n;
+ xmlXPathObjectPtr obj;
+ xmlChar *type;
+ char *label = NULL;
+
+ if (!node) return;
+
+ type = xmlGetProp(node, (xmlChar*)"type");
+ if (!type) return;
+
+ if (xmlStrncmp((const xmlChar*)MENU, type, strlen(MENU)) == 0) {
+ for(n=node->children; n; n=n->next) {
+ if (n->type != XML_ELEMENT_NODE) continue;
+ if (xmlStrncmp((const xmlChar*)LABEL, n->name, strlen(LABEL)) == 0) {
+ obj = xmlXPathEval(xmlGetNodePath(n), ctxt);
+ if (!obj) return;
+ label = (char *)xmlNodeListGetString(xml, obj->nodesetval->nodeTab[0]->xmlChildrenNode, 1);
+ }
+ else if (xmlStrncmp((const xmlChar*)KEYS, n->name, strlen(KEYS)) == 0) {
+ process_keys(sendKeyItems, xml, ctxt, n, label);
+ }
+ }
+ }
+ else if (xmlStrncmp((const xmlChar*)SEP, type, strlen(SEP)) == 0) {
+ build_keyComboDef(sendKeyItems, NULL, 0, "");
+ }
+}
+
+#define MAX_KEYS 3
+struct defaultKeyComboDef {
+ guint keys[MAX_KEYS];
+ guint nkeys;
+ const char *label;
+};
+static const struct defaultKeyComboDef defaultKeyCombos[] = {
+ { { GDK_Control_L, GDK_Alt_L, GDK_Delete }, 3, "Ctrl+Alt+_Del"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_BackSpace }, 3, "Ctrl+Alt+_Backspace"},
+ { {}, 0, "" },
+ { { GDK_Control_L, GDK_Alt_L, GDK_F1 }, 3, "Ctrl+Alt+F_1"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F2 }, 3, "Ctrl+Alt+F_2"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F3 }, 3, "Ctrl+Alt+F_3"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F4 }, 3, "Ctrl+Alt+F_4"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F5 }, 3, "Ctrl+Alt+F_5"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F6 }, 3, "Ctrl+Alt+F_6"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F7 }, 3, "Ctrl+Alt+F_7"},
+ { { GDK_Control_L, GDK_Alt_L, GDK_F8 }, 3, "Ctrl+Alt+F_8"},
+ { {}, 0, "" },
+ { { GDK_Print }, 1, "_PrintScreen"},
+};
+
+static void makeDefaultKeyCombos(SendKeyItems * sendKeyItems)
+{
+ int i;
+ guint *keys;
+
+ sendKeyItems->cnt = (sizeof(defaultKeyCombos)/sizeof(defaultKeyCombos[0]));
+ sendKeyItems->keyCombos = calloc(sendKeyItems->cnt, sizeof(struct keyComboDef *));
+ if (!sendKeyItems->keyCombos) {
+ sendKeyItems->cnt = 0;
+ return;
+ }
+
+ for (i = 0 ; i < (sizeof(defaultKeyCombos)/sizeof(defaultKeyCombos[0])) ; i++) {
+ keys = (guint *)defaultKeyCombos[i].keys;
+ build_keyComboDef(sendKeyItems, keys, defaultKeyCombos[i].nkeys, defaultKeyCombos[i].label);
+ }
+}
+
+
+int build_keyCombos(SendKeyItems * sendKeyItems, const char *filename, int set_verbose)
+{
+ xmlDocPtr xml = NULL;
+ xmlParserCtxtPtr pctxt = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNode *root_element = NULL;
+ xmlNode *node;
+ struct stat sbuf;
+
+ verbose = set_verbose;
+ pctxt = xmlNewParserCtxt();
+ if (!pctxt || !pctxt->sax)
+ goto error;
+
+ if (filename == NULL)
+ filename = DEFAULT_KEY_XML;
+
+ if(stat(filename, &sbuf) != 0) {
+ if (verbose)
+ fprintf(stderr, "%s(): could not stat file:%s \n", __FUNCTION__, filename);
+ goto error;
+ }
+
+ xml = xmlCtxtReadFile(pctxt, filename, NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xml) {
+ if (verbose)
+ fprintf(stderr, "%s(): could not read file:%s \n", __FUNCTION__, filename);
+ goto error;
+ }
+
+ ctxt = xmlXPathNewContext(xml);
+ if (!ctxt)
+ goto error;
+
+ root_element = xmlDocGetRootElement(xml);
+ if (!root_element) {
+ if (verbose)
+ fprintf(stderr, "%s(): could not locate root element\n", __FUNCTION__);
+ goto error;
+ }
+
+ if (!create_keyCombos(sendKeyItems, ctxt)) {
+ if (verbose)
+ fprintf(stderr, "%s(): could not create XML based keyCombos structure \n", __FUNCTION__);
+ goto error;
+ }
+
+ for (node=root_element; node; node=node->next) {
+ if (node->type != XML_ELEMENT_NODE) continue;
+ if (node->children)
+ {
+ xmlNode *n;
+ for(n=node->children; n; n=n->next) {
+ if (n->type != XML_ELEMENT_NODE) continue;
+ if (xmlStrncmp((const xmlChar*)ITEM, n->name, strlen(ITEM)) == 0) {
+ process_item(sendKeyItems, xml, ctxt, n);
+ }
+ }
+ }
+ }
+
+ error:
+ if (ctxt)
+ xmlXPathFreeContext(ctxt);
+ if (xml)
+ xmlFreeDoc(xml);
+ if (pctxt)
+ xmlFreeParserCtxt(pctxt);
+ if (sendKeyItems->keyCombos == NULL)
+ makeDefaultKeyCombos(sendKeyItems);
+ return(sendKeyItems->cnt);
+}
+
+int sendkey_xml_validate(const char * filename)
+{
+ xmlDocPtr doc = NULL;
+ xmlParserCtxtPtr pctxt = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNode *root_element = NULL;
+ int ret = -1;
+
+ pctxt = xmlNewParserCtxt();
+ if (!pctxt || !pctxt->sax) {
+ if (verbose)
+ fprintf(stderr, "%s(): failed to allocate parser context \n", __FUNCTION__);
+ goto error;
+ }
+
+ doc = xmlCtxtReadFile(pctxt, filename, NULL, XML_PARSE_DTDVALID);
+ if (!doc) {
+ if (verbose)
+ fprintf(stderr, "%s(): could not read file:%s \n", __FUNCTION__, filename);
+ goto error;
+ }
+ if (pctxt->valid == 0) {
+ if (verbose)
+ fprintf(stderr, "%s(): Failed to validate :%s \n", __FUNCTION__, filename);
+ goto error;
+ }
+
+ ctxt = xmlXPathNewContext(doc);
+ if (!ctxt) {
+ if (verbose)
+ fprintf(stderr, "%s(): Failed to allocate path context\n", __FUNCTION__);
+ goto error;
+ }
+
+ root_element = xmlDocGetRootElement(doc);
+ if (!root_element) {
+ if (verbose)
+ fprintf(stderr, "%s(): could not locate root element\n", __FUNCTION__);
+ goto error;
+ }
+
+ if (xmlStrncmp((const xmlChar*)ROOT, root_element->name, strlen(ROOT)) != 0) {
+ if (verbose)
+ fprintf(stderr, "%s(): Incorrect root element name:%s\n", __FUNCTION__,
+ root_element->name);
+ goto error;
+ }
+ ret = 0;
+
+error:
+ if (ctxt)
+ xmlXPathFreeContext(ctxt);
+ if (doc)
+ xmlFreeDoc(doc);
+ if (pctxt)
+ xmlFreeParserCtxt(pctxt);
+ return(ret);
+
+}
Index: virt-viewer-0.0.3/src/keymap.xml
===================================================================
--- /dev/null
+++ virt-viewer-0.0.3/src/keymap.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE keymap [
+<!ELEMENT keymap (item)*>
+<!ELEMENT item (label,keys)*>
+<!ELEMENT label (#PCDATA)>
+<!ELEMENT keys (key)+>
+<!ELEMENT key (#PCDATA)>
+<!ATTLIST keymap id CDATA #REQUIRED>
+<!ATTLIST item type (menu|separator) #REQUIRED>
+]>
+
+<keymap id="virt-viewer, Send Key menu keymap">
+ <!-- See /usr/include/gtk2.0/gdk/gdkkeysyms.h for valid key names -->
+ <item type="menu">
+ <label>Ctrl+Alt+_Del</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>Delete</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+_BackSpace</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>BackSpace</key>
+ </keys>
+ </item>
+ <item type="separator"/>
+ <item type="menu">
+ <label>Ctrl+Alt+F1</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F1</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+F2</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F2</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+F3</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F3</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+F4</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F4</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+F5</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F5</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+F6</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F6</key>
+ </keys>
+ </item>
+ <item type="menu">
+ <label>Ctrl+Alt+F7</label>
+ <keys>
+ <key>Control_L</key>
+ <key>Alt_L</key>
+ <key>F7</key>
+ </keys>
+ </item>
+ <item type="separator"/>
+ <item type="menu">
+ <label>_PrintScreen</label>
+ <keys>
+ <key>Print</key>
+ </keys>
+ </item>
+</keymap>
Index: virt-viewer-0.0.3/src/main.c
===================================================================
--- virt-viewer-0.0.3.orig/src/main.c
+++ virt-viewer-0.0.3/src/main.c
@@ -46,28 +46,9 @@
static char *domname = NULL;
static int verbose = 0;
-#define MAX_KEY_COMBO 3
-struct keyComboDef {
- guint keys[MAX_KEY_COMBO];
- guint nkeys;
- const char *label;
-};
-static const struct keyComboDef keyCombos[] = {
- { { GDK_Control_L, GDK_Alt_L, GDK_Delete }, 3, "Ctrl+Alt+_Del"},
- { { GDK_Control_L, GDK_Alt_L, GDK_BackSpace }, 3, "Ctrl+Alt+_Backspace"},
- { {}, 0, "" },
- { { GDK_Control_L, GDK_Alt_L, GDK_F1 }, 3, "Ctrl+Alt+F_1"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F2 }, 3, "Ctrl+Alt+F_2"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F3 }, 3, "Ctrl+Alt+F_3"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F4 }, 3, "Ctrl+Alt+F_4"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F5 }, 3, "Ctrl+Alt+F_5"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F6 }, 3, "Ctrl+Alt+F_6"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F7 }, 3, "Ctrl+Alt+F_7"},
- { { GDK_Control_L, GDK_Alt_L, GDK_F8 }, 3, "Ctrl+Alt+F_8"},
- { {}, 0, "" },
- { { GDK_Print }, 1, "_PrintScreen"},
-};
+SendKeyItems sendKeyItems;
+static GtkWidget *viewer_build_sendkey_menu(VncDisplay *vnc);
enum menuNums {
FILE_MENU,
@@ -79,18 +60,27 @@ enum menuNums {
struct menuItem {
guint menu;
+ GtkWidget *widget;
GtkWidget *label;
const char *ungrabbed_text;
const char *grabbed_text;
};
static struct menuItem menuItems[] = {
- { FILE_MENU, NULL, "_File", "File" },
- { VIEW_MENU, NULL, "_View", "View" },
- { SEND_KEY_MENU, NULL, "_Send Key", "Send Key" },
- { HELP_MENU, NULL, "_Help", "Help" }
+ { FILE_MENU, NULL, NULL, "_File", "File" },
+ { VIEW_MENU, NULL, NULL, "_View", "View" },
+ { SEND_KEY_MENU, NULL, NULL, "_Send Key", "Send Key" },
+ { HELP_MENU, NULL, NULL, "_Help", "Help" }
};
+typedef struct {
+ VncDisplay *vnc;
+ GtkWindow *window;
+ GtkWidget *menubar;
+}VirtViewer;
+
+static VirtViewer virtViewer;
+
static void viewer_set_title(VncDisplay *vnc G_GNUC_UNUSED, GtkWidget *window, gboolean grabbed)
{
char title[1024];
@@ -182,12 +172,13 @@ static void viewer_send_key(GtkWidget *m
GtkWidget *label = gtk_bin_get_child(GTK_BIN(menu));
const char *text = gtk_label_get_label(GTK_LABEL(label));
- for (i = 0 ; i < (sizeof(keyCombos)/sizeof(keyCombos[0])) ; i++) {
- if (!strcmp(text, keyCombos[i].label)) {
+ for (i = 0 ; i < sendKeyItems.cnt; i++) {
+ struct keyComboDef *kp = sendKeyItems.keyCombos[i];
+ if (!strcmp(text, kp->label)) {
DEBUG_LOG("Sending key combo %s\n", gtk_label_get_text(GTK_LABEL(label)));
vnc_display_send_keys(VNC_DISPLAY(vnc),
- keyCombos[i].keys,
- keyCombos[i].nkeys);
+ kp->keys,
+ kp->nkeys);
return;
}
}
@@ -229,6 +220,47 @@ static void viewer_screenshot(GtkWidget
gtk_widget_destroy (dialog);
}
+static void viewer_file_sendkey(GtkWidget *menu G_GNUC_UNUSED, VirtViewer *viewer)
+{
+ GtkWidget *dialog;
+ GtkWidget *sendkey;
+
+ dialog = gtk_file_chooser_dialog_new ("Load SendKey",
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+again:
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+ char *filename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ if (sendkey_xml_validate(filename) == -1) {
+ GtkWidget *msg_dialog = gtk_message_dialog_new (GTK_WINDOW(dialog),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "Invalid send key XML format: '%s'",
+ filename);
+ gtk_dialog_run (GTK_DIALOG (msg_dialog));
+ gtk_widget_destroy (msg_dialog);
+ g_free (filename);
+ goto again;
+ }
+ else {
+ build_keyCombos(&sendKeyItems, filename, verbose);
+ gtk_widget_destroy (menuItems[SEND_KEY_MENU].widget);
+ sendkey = viewer_build_sendkey_menu(viewer->vnc);
+ gtk_menu_bar_insert(GTK_MENU_BAR(viewer->menubar), sendkey, SEND_KEY_MENU);
+ gtk_widget_show_all(viewer->menubar);
+ }
+ g_free (filename);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
static void viewer_credential(GtkWidget *vnc, GValueArray *credList)
{
@@ -386,6 +418,7 @@ static GtkWidget *menu_item_new(int whic
gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), widget);
gtk_widget_show(label);
+ menuItems[which_menu].widget = widget;
menuItems[which_menu].label = label;
return widget;
@@ -397,6 +430,7 @@ static GtkWidget *viewer_build_file_menu
GtkWidget *filemenu;
GtkWidget *quit;
GtkWidget *screenshot;
+ GtkWidget *sendkey;
file = menu_item_new(FILE_MENU);
@@ -407,6 +441,10 @@ static GtkWidget *viewer_build_file_menu
gtk_menu_append(GTK_MENU(filemenu), screenshot);
g_signal_connect(screenshot, "activate", GTK_SIGNAL_FUNC(viewer_screenshot), vnc);
+ sendkey = gtk_menu_item_new_with_mnemonic("Send _Key");
+ gtk_menu_append(GTK_MENU(filemenu), sendkey);
+ g_signal_connect(sendkey, "activate", GTK_SIGNAL_FUNC(viewer_file_sendkey), &virtViewer);
+
gtk_menu_append(GTK_MENU(filemenu), gtk_separator_menu_item_new());
@@ -453,11 +491,12 @@ static GtkWidget *viewer_build_sendkey_m
sendkeymenu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(sendkey), sendkeymenu);
- for (i = 0 ; i < (sizeof(keyCombos)/sizeof(keyCombos[0])) ; i++) {
+ for (i = 0 ; i < sendKeyItems.cnt; i++) {
GtkWidget *key;
+ struct keyComboDef *kp = sendKeyItems.keyCombos[i];
- if (keyCombos[i].nkeys) {
- key = gtk_menu_item_new_with_mnemonic(keyCombos[i].label);
+ if (kp->nkeys) {
+ key = gtk_menu_item_new_with_mnemonic(kp->label);
gtk_menu_append(GTK_MENU(sendkeymenu), key);
g_signal_connect(key, "activate", GTK_SIGNAL_FUNC(viewer_send_key), vnc);
} else {
@@ -495,6 +534,7 @@ static GtkWidget *viewer_build_menu(VncD
GtkWidget *help;
menubar = gtk_menu_bar_new();
+ virtViewer.menubar = menubar;
file = viewer_build_file_menu(vnc);
view = viewer_build_view_menu(vnc, window, composited);
@@ -527,6 +567,9 @@ static GtkWidget *viewer_build_window(Vn
window = get_toplevel (data);
gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
+ virtViewer.vnc = vnc;
+ virtViewer.window = (GTK_WINDOW(window));
+
if (with_menubar) {
layout = gtk_vbox_new(FALSE, 3);
menubar = viewer_build_menu(vnc, window, gtk_widget_is_composited(window));
@@ -886,6 +929,7 @@ static void viewer_help(FILE *out, const
fprintf(out, " -d, --direct direct connection with no automatic tunnels\n");
fprintf(out, " -c URI, --connect URI connect to hypervisor URI\n");
fprintf(out, " -w, --wait wait for domain to start\n");
+ fprintf(out, " -k file, --keymap file menu key definition file\n");
fprintf(out, "\n");
}
@@ -894,7 +938,7 @@ int main(int argc, char **argv)
char *uri = NULL;
char *name = NULL;
int opt_ind;
- const char *sopts = "hVc:";
+ const char *sopts = "hvVdc:wk:";
static const struct option lopts[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
@@ -902,6 +946,7 @@ int main(int argc, char **argv)
{ "connect", 1, 0, 'c' },
{ "wait", 0, 0, 'w' },
{ "direct", 0, 0, 'd' },
+ { "keymap", 1, 0, 'k' },
{ 0, 0, 0, 0 }
};
int ch;
@@ -909,6 +954,7 @@ int main(int argc, char **argv)
int waitvnc = 0;
int set_verbose = 0;
int ret;
+ char *keymap_file = NULL;
while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
switch (ch) {
@@ -930,6 +976,9 @@ int main(int argc, char **argv)
case 'd':
direct = 1;
break;
+ case 'k':
+ keymap_file = strdup(optarg);
+ break;
case '?':
viewer_help(stderr, argv[0]);
return 1;
@@ -941,6 +990,8 @@ int main(int argc, char **argv)
return 1;
}
+ build_keyCombos(&sendKeyItems, keymap_file, set_verbose);
+
gtk_init(&argc, &argv);
name = argv[optind];
Index: virt-viewer-0.0.3/src/Makefile.am
===================================================================
--- virt-viewer-0.0.3.orig/src/Makefile.am
+++ virt-viewer-0.0.3/src/Makefile.am
@@ -1,6 +1,13 @@
bin_PROGRAMS = virt-viewer
-virt_viewer_SOURCES = main.c viewer.h
+virt_viewer_SOURCES = main.c keymap.c viewer.h
virt_viewer_LDADD = @GTKVNC_LIBS@ @GTK2_LIBS@ @LIBXML2_LIBS@ @LIBVIRT_LIBS@
virt_viewer_CFLAGS = @GTKVNC_CFLAGS@ @GTK2_CFLAGS@ @LIBXML2_CFLAGS@ @LIBVIRT_CFLAGS@ @WARN_CFLAGS@
+
+install-data-local:
+ mkdir -p $(DESTDIR)$(datadir)/virt-viewer
+ install keymap.xml $(DESTDIR)$(datadir)/virt-viewer
+
+install-data-am: install-data-local
+
Index: virt-viewer-0.0.3/src/Makefile.in
===================================================================
--- virt-viewer-0.0.3.orig/src/Makefile.in
+++ virt-viewer-0.0.3/src/Makefile.in
@@ -46,7 +46,7 @@ CONFIG_CLEAN_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
-am_virt_viewer_OBJECTS = virt_viewer-main.$(OBJEXT)
+am_virt_viewer_OBJECTS = virt_viewer-main.$(OBJEXT) virt_viewer-keymap.$(OBJEXT)
virt_viewer_OBJECTS = $(am_virt_viewer_OBJECTS)
virt_viewer_DEPENDENCIES =
virt_viewer_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -191,7 +191,7 @@ sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-virt_viewer_SOURCES = main.c viewer.h
+virt_viewer_SOURCES = main.c keymap.c viewer.h
virt_viewer_LDADD = @GTKVNC_LIBS@ @GTK2_LIBS@ @LIBXML2_LIBS@ @LIBVIRT_LIBS@
virt_viewer_CFLAGS = @GTKVNC_CFLAGS@ @GTK2_CFLAGS@ @LIBXML2_CFLAGS@ @LIBVIRT_CFLAGS@ @WARN_CFLAGS@
all: all-am
@@ -266,6 +266,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-keymap.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -295,6 +296,13 @@ virt_viewer-main.o: main.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+virt_viewer-keymap.o: keymap.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-keymap.o -MD -MP -MF $(DEPDIR)/virt_viewer-keymap.Tpo -c -o virt_viewer-keymap.o `test -f 'keymap.c' || echo '$(srcdir)/'`keymap.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/virt_viewer-keymap.Tpo $(DEPDIR)/virt_viewer-keymap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='keymap.c' object='virt_viewer-keymap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-keymap.o `test -f 'keymap.c' || echo '$(srcdir)/'`keymap.c
+
virt_viewer-main.obj: main.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-main.obj -MD -MP -MF $(DEPDIR)/virt_viewer-main.Tpo -c -o virt_viewer-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/virt_viewer-main.Tpo $(DEPDIR)/virt_viewer-main.Po
@@ -433,7 +441,7 @@ info: info-am
info-am:
-install-data-am:
+install-data-am: install-data-local
install-dvi: install-dvi-am
@@ -487,6 +495,10 @@ uninstall-am: uninstall-binPROGRAMS
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-binPROGRAMS
+install-data-local:
+ mkdir -p $(DESTDIR)$(datadir)/virt-viewer
+ install keymap.xml $(DESTDIR)$(datadir)/virt-viewer
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
Index: virt-viewer-0.0.3/src/viewer.h
===================================================================
--- virt-viewer-0.0.3.orig/src/viewer.h
+++ virt-viewer-0.0.3/src/viewer.h
@@ -25,4 +25,18 @@
extern int viewer_start (const char *uri, const char *name, int direct, int waitvnc, int set_verbose, GtkWidget *(*get_toplevel)(void *), void *data, int with_menubar);
+typedef struct keyComboDef {
+ guint *keys;
+ guint nkeys;
+ char *label;
+}KeyComboDef;
+
+typedef struct sendKeyItems {
+ int cnt;
+ struct keyComboDef **keyCombos;
+}SendKeyItems;
+
+int build_keyCombos(SendKeyItems *, const char *, int);
+int sendkey_xml_validate(const char * filename);
+
#endif /* VIEWER_H */