[gtk-vnc] Add APIs for configurable key grab sequences
- From: Daniel P. Berrange <dberrange src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk-vnc] Add APIs for configurable key grab sequences
- Date: Tue, 22 Jun 2010 18:09:14 +0000 (UTC)
commit 378721ec1ccdbe5bc79ee18bca04a49918e75df2
Author: Michal Novotny <minovotn redhat com>
Date: Wed Jun 16 22:36:14 2010 +0100
Add APIs for configurable key grab sequences
Allow the key grab sequence to be configured by applications.
The grab sequence is represented by a new boxed data object
VncGrabSequence
This can be created from an array of keysyms
guint keys[] = { GDK_Control_L, GDK_Alt_L };
guint len = sizeof(keys)/sizeof(keys[0]);
vnc_grab_sequence_new(len, keys);
Or from a string format
vnc_grab_sequence_new_from_string("Control_L+Alt_L");
The gvncviewer.c example program shows a user interface for
configuring key sequences. The gvncviewer.py example program
demonstrates access from the python binding.
This patch is heavily based on the original proposal from
Michal Novotny
examples/gvncviewer.c | 182 +++++++++++++++++++++++++++++++++++++++++---
examples/gvncviewer.py | 14 +++-
src/Makefile.am | 3 +
src/libgtk-vnc_sym.version | 10 +++
src/vnc.override | 57 ++++++++++++++
src/vncdisplay.c | 82 +++++++++++++++++++-
src/vncdisplay.h | 3 +
src/vncgrabsequence.c | 121 +++++++++++++++++++++++++++++
src/vncgrabsequence.h | 58 ++++++++++++++
9 files changed, 515 insertions(+), 15 deletions(-)
---
diff --git a/examples/gvncviewer.c b/examples/gvncviewer.c
index c3fbd74..1799e32 100644
--- a/examples/gvncviewer.c
+++ b/examples/gvncviewer.c
@@ -43,23 +43,33 @@ static const GOptionEntry options [] =
static GtkWidget *vnc;
+typedef struct {
+ GtkWidget *label;
+ guint curkeys;
+ guint numkeys;
+ guint *keysyms;
+ gboolean set;
+} VncGrabDefs;
+
static void set_title(VncDisplay *vncdisplay, GtkWidget *window,
gboolean grabbed)
{
- const char *name;
- char title[1024];
- const char *subtitle;
+ 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)
- subtitle = "(Press Ctrl+Alt to release pointer) ";
+ title = g_strdup_printf("(Press %s to release pointer) %s - GVncViewer",
+ seqstr, name);
else
- subtitle = "";
-
- name = vnc_display_get_name(VNC_DISPLAY(vncdisplay));
- snprintf(title, sizeof(title), "%s%s - GVncViewer",
- subtitle, name);
+ title = g_strdup_printf("%s - GVncViewer",
+ name);
gtk_window_set_title(GTK_WINDOW(window), title);
+
+ g_free(seqstr);
+ g_free(title);
}
static gboolean vnc_screenshot(GtkWidget *window G_GNUC_UNUSED,
@@ -216,6 +226,145 @@ static void do_scaling(GtkWidget *menu, GtkWidget *vncdisplay)
vnc_display_set_scaling(VNC_DISPLAY(vncdisplay), FALSE);
}
+static void dialog_update_keysyms(GtkWidget *window, guint *keysyms, guint numsyms)
+{
+ gchar *keys;
+ int 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_Return:
+ case GDK_Escape:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean dialog_key_press(GtkWidget *window G_GNUC_UNUSED,
+ GdkEvent *ev, VncGrabDefs *defs)
+{
+ gboolean keySymExists;
+ int 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)
+{
+ int i;
+
+ if (dialog_key_ignore(ev->key.keyval))
+ return FALSE;
+
+ if (defs->set) {
+ if (defs->curkeys == 0)
+ defs->set = FALSE;
+ if (defs->curkeys)
+ 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_dialog_new_with_buttons ("Key recorder",
+ GTK_WINDOW(window),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT,
+ NULL);
+
+ label = gtk_label_new("Please press desired grab key combination");
+ 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);
+ gtk_widget_set_size_request(dialog, 300, 100);
+ content_area = gtk_dialog_get_content_area( GTK_DIALOG(dialog) );
+ 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;
@@ -353,7 +502,7 @@ int main(int argc, char **argv)
GtkWidget *window;
GtkWidget *layout;
GtkWidget *menubar;
- GtkWidget *sendkey, *view;
+ GtkWidget *sendkey, *view, *settings;
GtkWidget *submenu;
GtkWidget *caf1;
GtkWidget *caf2;
@@ -367,6 +516,7 @@ int main(int argc, char **argv)
GtkWidget *cab;
GtkWidget *fullscreen;
GtkWidget *scaling;
+ GtkWidget *showgrabkeydlg;
const char *help_msg = "Run 'gvncviewer --help' to see a full list of available command line options";
/* Setup command line options */
@@ -441,6 +591,16 @@ int main(int argc, char **argv)
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);
+
#if WITH_LIBVIEW
ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(layout), FALSE);
ViewOvBox_SetOver(VIEW_OV_BOX(layout), menubar);
@@ -516,6 +676,8 @@ int main(int argc, char **argv)
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",
diff --git a/examples/gvncviewer.py b/examples/gvncviewer.py
index 9a74268..c5769f3 100644
--- a/examples/gvncviewer.py
+++ b/examples/gvncviewer.py
@@ -28,8 +28,15 @@ if len(sys.argv) != 2 and len(sys.argv) != 3:
def set_title(vnc, window, grabbed):
name = vnc.get_name()
+ keys = vnc.get_grab_keys()
+ keystr = None
+ for k in keys:
+ if keystr is None:
+ keystr = gtk.gdk.keyval_name(k)
+ else:
+ keystr = keystr + "+" + gtk.gdk.keyval_name(k)
if grabbed:
- subtitle = "(Press Ctrl+Alt to release pointer) "
+ subtitle = "(Press %s to release pointer) " % keystr
else:
subtitle = ""
@@ -173,6 +180,11 @@ layout.add(vnc)
vnc.realize()
vnc.set_pointer_grab(True)
vnc.set_keyboard_grab(True)
+
+# Example to change grab key combination to Ctrl+Alt+g
+grab_keys = [ gtk.keysyms.Control_L, gtk.keysyms.Alt_L, gtk.keysyms.g ]
+vnc.set_grab_keys(grab_keys)
+
#v.set_pointer_local(True)
if len(sys.argv) == 3:
diff --git a/src/Makefile.am b/src/Makefile.am
index 393d76a..745ca99 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,7 @@ gtk_vnc_includedir = $(includedir)/gtk-vnc-1.0/
gtk_vnc_include_HEADERS = \
vncdisplay.h \
vncdisplayenums.h \
+ vncgrabsequence.h \
vncimageframebuffer.h
libgtk_vnc_1_0_la_SOURCES = \
@@ -92,6 +93,7 @@ libgtk_vnc_1_0_la_SOURCES = \
vncdisplay.h vncdisplay.c \
vncdisplayenums.h vncdisplayenums.c \
vncdisplaykeymap.h vncdisplaykeymap.c \
+ vncgrabsequence.h vncgrabsequence.c \
vncmarshal.h vncmarshal.c
vncdisplayenums.c: vncdisplay.h
@@ -204,6 +206,7 @@ GVNC_INTROSPECTION_SRCS = \
GTK_VNC_INTROSPECTION_SRCS = \
$(srcdir)/vncimageframebuffer.h $(srcdir)/vncimageframebuffer.c \
$(srcdir)/vncdisplay.h $(srcdir)/vncdisplay.c \
+ $(srcdir)/vncgrabsequence.h $(srcdir)/vncgrabsequence.c \
$(builddir)/vncdisplayenums.h $(builddir)/vncdisplayenums.c
GVnc-1.0.gir: libgvnc-1.0.la $(G_IR_SCANNER) Makefile.am
diff --git a/src/libgtk-vnc_sym.version b/src/libgtk-vnc_sym.version
index b6f5347..dc219d4 100644
--- a/src/libgtk-vnc_sym.version
+++ b/src/libgtk-vnc_sym.version
@@ -68,6 +68,16 @@
vnc_image_framebuffer_new;
vnc_image_framebuffer_get_image;
+# grab key settings support
+ vnc_display_set_grab_keys;
+ vnc_display_get_grab_keys;
+ vnc_grab_sequence_new;
+ vnc_grab_sequence_new_from_string;
+ vnc_grab_sequence_copy;
+ vnc_grab_sequence_free;
+ vnc_grab_sequence_as_string;
+ vnc_grab_sequence_get_type;
+
local:
*;
};
diff --git a/src/vnc.override b/src/vnc.override
index dfc346e..2098358 100644
--- a/src/vnc.override
+++ b/src/vnc.override
@@ -52,3 +52,60 @@ _wrap_vnc_display_send_keys(PyGObject *self,
Py_INCREF(Py_None);
return Py_None;
}
+%%
+override vnc_display_get_grab_keys kwargs
+static PyObject*
+_wrap_vnc_display_get_grab_keys(PyGObject *self,
+ PyObject *args, PyObject *kwargs)
+{
+ VncGrabSequence *seq;
+ PyObject *keyList;
+ int i;
+
+ seq = vnc_display_get_grab_keys(VNC_DISPLAY(self->obj));
+
+ keyList = PyList_New(0);
+ for (i = 0 ; i < seq->nkeysyms ; i++)
+ PyList_Append(keyList, PyInt_FromLong(seq->keysyms[i]));
+
+ return keyList;
+}
+%%
+override vnc_display_set_grab_keys kwargs
+static PyObject*
+_wrap_vnc_display_set_grab_keys(PyGObject *self,
+ PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = {"keys", NULL};
+ PyObject *keyList;
+ int i;
+ guint nkeysyms;
+ guint *keysyms;
+ VncGrabSequence *seq;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O|I:VncDisplay.set_grab_keys", kwlist,
+ &keyList))
+ return NULL;
+
+ if (!PyList_Check(keyList))
+ return NULL;
+
+ nkeysyms = PyList_Size(keyList);
+ keysyms = g_new0(guint, nkeysyms);
+
+ for (i = 0 ; i < nkeysyms ; i++) {
+ PyObject *val = PyList_GetItem(keyList, i);
+ keysyms[i] = (guint)PyInt_AsLong(val);
+ }
+
+ seq = vnc_grab_sequence_new(nkeysyms, keysyms);
+ g_free(keysyms);
+
+ vnc_display_set_grab_keys(VNC_DISPLAY(self->obj), seq);
+
+ vnc_grab_sequence_free(seq);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 71e158b..8eeb243 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -85,6 +85,9 @@ struct _VncDisplayPrivate
GSList *preferable_auths;
const guint8 const *keycode_map;
+
+ VncGrabSequence *vncgrabseq; /* the configured key sequence */
+ gboolean *vncactiveseq; /* the currently pressed keys */
};
G_DEFINE_TYPE(VncDisplay, vnc_display, GTK_TYPE_DRAWING_AREA)
@@ -104,7 +107,8 @@ enum
PROP_SCALING,
PROP_SHARED_FLAG,
PROP_FORCE_SIZE,
- PROP_DEPTH
+ PROP_DEPTH,
+ PROP_GRAB_KEYS,
};
/* Signals */
@@ -198,6 +202,9 @@ vnc_display_get_property (GObject *object,
case PROP_DEPTH:
g_value_set_enum (value, vnc->priv->depth);
break;
+ case PROP_GRAB_KEYS:
+ g_value_set_boxed(value, vnc->priv->vncgrabseq);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -241,6 +248,9 @@ vnc_display_set_property (GObject *object,
case PROP_DEPTH:
vnc_display_set_depth (vnc, g_value_get_enum (value));
break;
+ case PROP_GRAB_KEYS:
+ vnc_display_set_grab_keys(vnc, g_value_get_boxed(value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -673,6 +683,37 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
return TRUE;
}
+
+static gboolean check_for_grab_key(GtkWidget *widget, int type, int keyval)
+{
+ VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
+ int i;
+
+ if (!priv->vncgrabseq->nkeysyms)
+ return FALSE;
+
+ if (type == GDK_KEY_RELEASE) {
+ /* Any key release resets the whole grab sequence */
+ memset(priv->vncactiveseq, 0,
+ sizeof(gboolean)*priv->vncgrabseq->nkeysyms);
+
+ return FALSE;
+ } else {
+ /* Record the new key press */
+ for (i = 0 ; i < priv->vncgrabseq->nkeysyms ; i++)
+ if (priv->vncgrabseq->keysyms[i] == keyval)
+ priv->vncactiveseq[i] = TRUE;
+
+ /* Return if any key is not pressed */
+ for (i = 0 ; i < priv->vncgrabseq->nkeysyms ; i++)
+ if (priv->vncactiveseq[i] == FALSE)
+ return FALSE;
+
+ return TRUE;
+ }
+}
+
+
static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
{
VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
@@ -752,9 +793,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
}
}
- if (key->type == GDK_KEY_PRESS &&
- ((keyval == GDK_Control_L && (key->state & GDK_MOD1_MASK)) ||
- (keyval == GDK_Alt_L && (key->state & GDK_CONTROL_MASK)))) {
+ if (check_for_grab_key(widget, key->type, key->keyval)) {
if (priv->in_pointer_grab)
do_pointer_ungrab(VNC_DISPLAY(widget), FALSE);
else if (!priv->grab_keyboard || !priv->absolute)
@@ -1472,6 +1511,10 @@ static void vnc_display_finalize (GObject *obj)
g_object_unref (priv->gc);
priv->gc = NULL;
}
+ if (priv->vncgrabseq) {
+ vnc_grab_sequence_free(priv->vncgrabseq);
+ priv->vncgrabseq = NULL;
+ }
g_slist_free (priv->preferable_auths);
@@ -1640,6 +1683,17 @@ static void vnc_display_class_init(VncDisplayClass *klass)
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (object_class,
+ PROP_GRAB_KEYS,
+ g_param_spec_boxed( "grab-keys",
+ "Grab keys",
+ "The key grab sequence",
+ VNC_TYPE_GRAB_SEQUENCE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
signals[VNC_CONNECTED] =
g_signal_new ("vnc-connected",
@@ -1823,6 +1877,8 @@ static void vnc_display_init(VncDisplay *display)
priv->local_pointer = FALSE;
priv->shared_flag = FALSE;
priv->force_size = TRUE;
+ priv->vncgrabseq = vnc_grab_sequence_new_from_string("Control_L+Alt_L");
+ priv->vncactiveseq = g_new0(gboolean, priv->vncgrabseq->nkeysyms);
/*
* Both these two provide TLS based auth, and can layer
@@ -1905,6 +1961,24 @@ void vnc_display_set_pointer_grab(VncDisplay *obj, gboolean enable)
do_pointer_ungrab(obj, FALSE);
}
+void vnc_display_set_grab_keys(VncDisplay *obj, VncGrabSequence *seq)
+{
+ if (obj->priv->vncgrabseq) {
+ vnc_grab_sequence_free(obj->priv->vncgrabseq);
+ g_free(obj->priv->vncactiveseq);
+ }
+ if (seq)
+ obj->priv->vncgrabseq = vnc_grab_sequence_copy(seq);
+ else
+ obj->priv->vncgrabseq = vnc_grab_sequence_new_from_string("Control_L+Alt_L");
+ obj->priv->vncactiveseq = g_new0(gboolean, obj->priv->vncgrabseq->nkeysyms);
+}
+
+VncGrabSequence *vnc_display_get_grab_keys(VncDisplay *obj)
+{
+ return obj->priv->vncgrabseq;
+}
+
void vnc_display_set_keyboard_grab(VncDisplay *obj, gboolean enable)
{
VncDisplayPrivate *priv = obj->priv;
diff --git a/src/vncdisplay.h b/src/vncdisplay.h
index 1b5b297..dc043d1 100644
--- a/src/vncdisplay.h
+++ b/src/vncdisplay.h
@@ -24,6 +24,7 @@
#include <gtk/gtkdrawingarea.h>
#include <glib.h>
+#include <vncgrabsequence.h>
G_BEGIN_DECLS
@@ -94,6 +95,8 @@ void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
int nkeyvals, VncDisplayKeyEvent kind);
void vnc_display_send_pointer(VncDisplay *obj, gint x, gint y, int button_mask);
+void vnc_display_set_grab_keys(VncDisplay *obj, VncGrabSequence *seq);
+VncGrabSequence *vnc_display_get_grab_keys(VncDisplay *obj);
gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data);
diff --git a/src/vncgrabsequence.c b/src/vncgrabsequence.c
new file mode 100644
index 0000000..6e23ed2
--- /dev/null
+++ b/src/vncgrabsequence.c
@@ -0,0 +1,121 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2010 Daniel P. Berrange <dan berrange com>
+ *
+ * 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 <config.h>
+
+#include <string.h>
+#include <gdk/gdk.h>
+
+#include "vncgrabsequence.h"
+
+GType vnc_grab_sequence_get_type(void)
+{
+ static GType grab_sequence_type = 0;
+
+ if (G_UNLIKELY(grab_sequence_type == 0)) {
+ grab_sequence_type = g_boxed_type_register_static
+ ("VncGrabSequence",
+ (GBoxedCopyFunc)vnc_grab_sequence_copy,
+ (GBoxedFreeFunc)vnc_grab_sequence_free);
+ }
+
+ return grab_sequence_type;
+}
+
+
+VncGrabSequence *vnc_grab_sequence_new(guint nkeysyms, guint *keysyms)
+{
+ VncGrabSequence *sequence;
+
+ sequence = g_slice_new0(VncGrabSequence);
+ sequence->nkeysyms = nkeysyms;
+ sequence->keysyms = g_new0(guint, nkeysyms);
+ memcpy(sequence->keysyms, keysyms, sizeof(guint)*nkeysyms);
+
+ return sequence;
+}
+
+
+VncGrabSequence *vnc_grab_sequence_new_from_string(const gchar *str)
+{
+ gchar **keysymstr;
+ int i;
+ VncGrabSequence *sequence;
+
+ sequence = g_slice_new0(VncGrabSequence);
+
+ keysymstr = g_strsplit(str, "+", 5);
+
+ sequence->nkeysyms = 0;
+ while (keysymstr[sequence->nkeysyms])
+ sequence->nkeysyms++;
+
+ sequence->keysyms = g_new0(guint, sequence->nkeysyms);
+ for (i = 0 ; i < sequence->nkeysyms ; i++)
+ sequence->keysyms[i] =
+ (guint)gdk_keyval_from_name(keysymstr[i]);
+
+ return sequence;
+
+}
+
+
+VncGrabSequence *vnc_grab_sequence_copy(VncGrabSequence *srcSequence)
+{
+ VncGrabSequence *sequence;
+
+ sequence = g_slice_dup(VncGrabSequence, srcSequence);
+ sequence->keysyms = g_new0(guint, srcSequence->nkeysyms);
+ memcpy(sequence->keysyms, srcSequence->keysyms,
+ sizeof(guint) * sequence->nkeysyms);
+
+ return sequence;
+}
+
+
+void vnc_grab_sequence_free(VncGrabSequence *sequence)
+{
+ g_slice_free(VncGrabSequence, sequence);
+}
+
+
+gchar *vnc_grab_sequence_as_string(VncGrabSequence *sequence)
+{
+ GString *str = g_string_new("");
+ int i;
+
+ for (i = 0 ; i < sequence->nkeysyms ; i++) {
+ if (i > 0)
+ g_string_append_c(str, '+');
+ g_string_append(str, gdk_keyval_name(sequence->keysyms[i]));
+ }
+
+ return g_string_free(str, FALSE);
+
+}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/vncgrabsequence.h b/src/vncgrabsequence.h
new file mode 100644
index 0000000..94007ef
--- /dev/null
+++ b/src/vncgrabsequence.h
@@ -0,0 +1,58 @@
+/*
+ * GTK VNC Widget
+ *
+ * Copyright (C) 2006 Anthony Liguori <anthony codemonkey ws>
+ * Copyright (C) 2009-2010 Daniel P. Berrange <dan berrange com>
+ *
+ * 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
+ */
+
+#ifndef VNC_GRAB_SEQUENCE_H
+#define VNC_GRAB_SEQUENCE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define VNC_TYPE_GRAB_SEQUENCE (vnc_grab_sequence_get_type ())
+
+typedef struct _VncGrabSequence VncGrabSequence;
+
+struct _VncGrabSequence {
+ guint nkeysyms;
+ guint *keysyms;
+};
+
+GType vnc_grab_sequence_get_type(void);
+
+VncGrabSequence *vnc_grab_sequence_new(guint nkeysyms, guint *keysyms);
+VncGrabSequence *vnc_grab_sequence_new_from_string(const gchar *str);
+VncGrabSequence *vnc_grab_sequence_copy(VncGrabSequence *sequence);
+void vnc_grab_sequence_free(VncGrabSequence *sequence);
+gchar *vnc_grab_sequence_as_string(VncGrabSequence *sequence);
+
+
+G_END_DECLS
+
+#endif /* VNC_GRAB_SEQUENCE_H */
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]