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(-) create mode 100644 src/vncgrabsequence.c create mode 100644 src/vncgrabsequence.h 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: + */ -- 1.7.0.1 -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Attachment:
signature.asc
Description: Digital signature