1 diff -urN gtk-vnc-0.3.7/bootstrap gtk-vnc-0.3.7.mingw/bootstrap
2 --- gtk-vnc-0.3.7/bootstrap 1970-01-01 01:00:00.000000000 +0100
3 +++ gtk-vnc-0.3.7.mingw/bootstrap 2008-10-09 12:19:03.000000000 +0100
6 +# Run this after autogen.sh, to pull in all of the gnulib-related bits.
7 +# It's important to run *after* autogen.sh, since it updates some of
8 +# the same files autogen.sh does, yet those from gnulib are newer,
9 +# and match the tests. So if a gnulib bug has been fixed since the
10 +# snapshot taken for whatever gettext release you're using, yet you
11 +# run "make check" against the wrong version, the corresponding unit
12 +# test in gl-tests/ may well fail.
16 +Usage: $0 [OPTION]...
17 +Bootstrap this package from the checked-out sources.
20 + --gnulib-srcdir=DIRNAME Specify the local directory where gnulib
21 + sources reside. Use this if you already
22 + have gnulib sources on your machine, and
23 + do not want to waste your bandwidth downloading
26 +If the file bootstrap.conf exists in the current working directory, its
27 +contents are read as shell variables to configure the bootstrap.
29 +Running without arguments will suffice in most cases.
40 + GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
42 + echo >&2 "$0: $option: unknown option"
53 +case ${GNULIB_SRCDIR--} in
55 + if [ ! -d .gnulib ]; then
56 + echo "$0: getting gnulib files..."
58 + trap cleanup_gnulib 1 2 13 15
60 + git clone --depth 1 git://git.sv.gnu.org/gnulib .gnulib ||
65 + GNULIB_SRCDIR=.gnulib
68 +gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
69 +<$gnulib_tool || exit
78 +# put *.m4 files in new gnulib/m4/ dir
79 +# put *.[ch] files in new gnulib/lib/ dir.
84 + --m4-base=gnulib/m4 \
85 + --source-base=gnulib/lib \
86 + --tests-base=gnulib/tests \
89 diff -urN gtk-vnc-0.3.7/configure.ac gtk-vnc-0.3.7.mingw/configure.ac
90 --- gtk-vnc-0.3.7/configure.ac 2008-09-05 13:32:15.000000000 +0100
91 +++ gtk-vnc-0.3.7.mingw/configure.ac 2008-10-09 12:19:03.000000000 +0100
94 AC_CONFIG_HEADERS([config.h:config.hin])
99 AM_INIT_AUTOMAKE(gtk-vnc, 0.3.7)
102 +dnl gl_INIT uses m4_foreach_w, yet that is not defined in autoconf-2.59.
103 +dnl In order to accommodate developers with such old tools, here's a
104 +dnl replacement definition.
105 +m4_ifndef([m4_foreach_w],
106 + [m4_define([m4_foreach_w],
107 + [m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])])])
114 +AC_LIBTOOL_WIN32_DLL
118 +AC_CHECK_HEADERS([pwd.h winsock2.h])
121 [ --with-python build python bindings],
122 [case "${withval}" in
127 + gnulib/lib/Makefile
128 + gnulib/tests/Makefile
132 diff -urN gtk-vnc-0.3.7/Makefile.am gtk-vnc-0.3.7.mingw/Makefile.am
133 --- gtk-vnc-0.3.7/Makefile.am 2008-09-05 13:32:15.000000000 +0100
134 +++ gtk-vnc-0.3.7.mingw/Makefile.am 2008-10-09 12:19:01.000000000 +0100
137 -SUBDIRS = src examples plugin
138 +SUBDIRS = gnulib/lib src examples plugin gnulib/tests
140 +ACLOCAL_AMFLAGS = -I gnulib/m4
144 pkgconfig_DATA = @PACKAGE@-1.0.pc
145 pkgconfigdir = $(libdir)/pkgconfig
146 diff -urN gtk-vnc-0.3.7/src/continuation.c gtk-vnc-0.3.7.mingw/src/continuation.c
147 --- gtk-vnc-0.3.7/src/continuation.c 2008-09-05 13:32:16.000000000 +0100
148 +++ gtk-vnc-0.3.7.mingw/src/continuation.c 2008-10-09 12:19:03.000000000 +0100
155 #include "continuation.h"
158 diff -urN gtk-vnc-0.3.7/src/coroutine_gthread.c gtk-vnc-0.3.7.mingw/src/coroutine_gthread.c
159 --- gtk-vnc-0.3.7/src/coroutine_gthread.c 2008-09-05 13:32:16.000000000 +0100
160 +++ gtk-vnc-0.3.7.mingw/src/coroutine_gthread.c 2008-10-09 12:19:03.000000000 +0100
167 #include "coroutine.h"
171 static struct coroutine *current;
172 static struct coroutine leader;
175 +#define CO_DEBUG(OP) fprintf(stderr, "%s %p %s %d\n", OP, g_thread_self(), __FUNCTION__, __LINE__)
177 +#define CO_DEBUG(OP)
180 static void coroutine_system_init(void)
182 - if (!g_thread_supported())
183 + if (!g_thread_supported()) {
189 run_cond = g_cond_new();
190 run_lock = g_mutex_new();
192 + g_mutex_lock(run_lock);
194 /* The thread that creates the first coroutine is the system coroutine
195 * so let's fill out a structure for it */
197 static gpointer coroutine_thread(gpointer opaque)
199 struct coroutine *co = opaque;
202 g_mutex_lock(run_lock);
203 - while (!co->runnable)
204 + while (!co->runnable) {
206 g_cond_wait(run_cond, run_lock);
209 + CO_DEBUG("RUNNABLE");
211 co->data = co->entry(co->data);
214 co->caller->runnable = TRUE;
215 + CO_DEBUG("BROADCAST");
216 g_cond_broadcast(run_cond);
217 + CO_DEBUG("UNLOCK");
218 g_mutex_unlock(run_lock);
223 if (run_cond == NULL)
224 coroutine_system_init();
228 co->thread = g_thread_create_full(coroutine_thread, co, co->stack_size,
230 G_THREAD_PRIORITY_NORMAL,
235 + CO_DEBUG("BROADCAST");
236 g_cond_broadcast(run_cond);
237 + CO_DEBUG("UNLOCK");
238 g_mutex_unlock(run_lock);
241 g_mutex_lock(run_lock);
242 - while (!from->runnable)
243 + while (!from->runnable) {
245 g_cond_wait(run_cond, run_lock);
250 + CO_DEBUG("SWAPPED");
255 fprintf(stderr, "Co-routine is re-entering itself\n");
259 return coroutine_swap(coroutine_self(), to, arg);
263 fprintf(stderr, "Co-routine is yielding to no one\n");
268 coroutine_self()->caller = NULL;
269 return coroutine_swap(coroutine_self(), to, arg);
271 diff -urN gtk-vnc-0.3.7/src/coroutine_ucontext.c gtk-vnc-0.3.7.mingw/src/coroutine_ucontext.c
272 --- gtk-vnc-0.3.7/src/coroutine_ucontext.c 2008-09-05 13:32:16.000000000 +0100
273 +++ gtk-vnc-0.3.7.mingw/src/coroutine_ucontext.c 2008-10-09 12:19:03.000000000 +0100
280 #include <sys/types.h>
281 #include <sys/mman.h>
283 diff -urN gtk-vnc-0.3.7/src/gvnc.c gtk-vnc-0.3.7.mingw/src/gvnc.c
284 --- gtk-vnc-0.3.7/src/gvnc.c 2008-09-05 13:32:16.000000000 +0100
285 +++ gtk-vnc-0.3.7.mingw/src/gvnc.c 2008-10-09 12:19:03.000000000 +0100
293 -#include <sys/socket.h>
294 -#include <netinet/in.h>
295 -#include <arpa/inet.h>
303 #include <gdk/gdkkeysyms.h>
305 #include "vnc_keycodes.h"
306 +#include "socketcompat.h"
307 +#include "getaddrinfo.h"
309 +/* AI_ADDRCONFIG is missing on some systems and gnulib won't provide it
310 + even if its emulated getaddrinfo() for us . */
311 +#ifndef AI_ADDRCONFIG
312 +# define AI_ADDRCONFIG 0
320 g_io_add_watch(channel, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, g_io_wait_helper, coroutine_self());
321 ret = coroutine_yield(NULL);
328 /* inflate as much as possible */
329 err = inflate(gvnc->strm, Z_SYNC_FLUSH);
337 gvnc->uncompressed_length = (uint8_t *)gvnc->strm->next_out - gvnc->uncompressed_buffer;
338 gvnc->compressed_length -= (uint8_t *)gvnc->strm->next_in - gvnc->compressed_buffer;
342 if (gvnc->has_error) return -EINVAL;
345 while (offset < len) {
348 @@ -352,10 +355,10 @@
349 * so we must by-pass it */
350 if (gvnc_use_compression(gvnc)) {
351 int ret = gvnc_zread(gvnc, data + offset, len);
354 GVNC_DEBUG("Closing the connection: gvnc_read() - gvnc_zread() failed\n");
355 gvnc->has_error = TRUE;
361 @@ -366,17 +369,19 @@
362 ret = gnutls_read(gvnc->tls_session, gvnc->read_buffer, 4096);
364 if (ret == GNUTLS_E_AGAIN)
373 - ret = read(fd, gvnc->read_buffer, 4096);
375 + ret = recv(fd, gvnc->read_buffer, 4096, 0);
377 + ret = socket_errno() * -1;
384 + switch (ret * -1) {
386 if (gvnc->wait_interruptable) {
387 if (!g_io_wait_interruptable(&gvnc->wait,
388 gvnc->channel, G_IO_IN))
393 - GVNC_DEBUG("Closing the connection: gvnc_read() - ret=-1\n");
394 + GVNC_DEBUG("Closing the connection: gvnc_read() - ret=%d\n", ret);
395 gvnc->has_error = TRUE;
401 @@ -425,23 +430,25 @@
402 gvnc->write_offset-offset);
404 if (ret == GNUTLS_E_AGAIN)
414 - gvnc->write_buffer+offset,
415 - gvnc->write_offset-offset);
421 + gvnc->write_buffer+offset,
422 + gvnc->write_offset-offset, 0);
424 + ret = socket_errno() * -1;
427 + switch (ret * -1) {
429 g_io_wait(gvnc->channel, G_IO_OUT);
433 - GVNC_DEBUG("Closing the connection: gvnc_flush\n");
434 + GVNC_DEBUG("Closing the connection: gvnc_flush %d\n", ret);
435 gvnc->has_error = TRUE;
440 ret = write(fd, data, len);
442 - if (errno == EINTR)
443 + if (socket_errno() == EINTR)
449 ret = read(fd, data, len);
451 - if (errno == EINTR)
452 + if (socket_errno() == EINTR)
456 @@ -2802,12 +2809,12 @@
457 if (gvnc_has_error(gvnc))
460 - if (!gvnc->fmt.true_color_flag && gvnc->ops.get_preferred_pixel_format)
461 + if (!gvnc->fmt.true_color_flag && gvnc->ops.get_preferred_pixel_format) {
462 if (gvnc->ops.get_preferred_pixel_format(gvnc->ops_data, &gvnc->fmt))
463 gvnc_set_pixel_format(gvnc, &gvnc->fmt);
468 memset(&gvnc->strm, 0, sizeof(gvnc->strm));
469 /* FIXME what level? */
470 for (i = 0; i < 5; i++)
471 @@ -2822,15 +2829,16 @@
472 return !gvnc_has_error(gvnc);
475 -gboolean gvnc_open_fd(struct gvnc *gvnc, int fd)
476 +static gboolean gvnc_set_nonblock(int fd)
479 - if (gvnc_is_open(gvnc)) {
480 - GVNC_DEBUG ("Error: already connected?\n");
482 + unsigned long flags = 1;
483 + if (ioctlsocket(fd, FIONBIO, &flags) < 0) {
484 + GVNC_DEBUG ("Failed to set nonblocking flag\n");
488 - GVNC_DEBUG("Connecting to FD %d\n", fd);
491 if ((flags = fcntl(fd, F_GETFL)) < 0) {
492 GVNC_DEBUG ("Failed to fcntl()\n");
494 @@ -2840,6 +2848,21 @@
495 GVNC_DEBUG ("Failed to fcntl()\n");
502 +gboolean gvnc_open_fd(struct gvnc *gvnc, int fd)
504 + if (gvnc_is_open(gvnc)) {
505 + GVNC_DEBUG ("Error: already connected?\n");
509 + GVNC_DEBUG("Connecting to FD %d\n", fd);
511 + if (!gvnc_set_nonblock(fd))
514 if (!(gvnc->channel = g_io_channel_unix_new(fd))) {
515 GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
516 @@ -2873,7 +2896,7 @@
519 while (runp != NULL) {
524 if ((fd = socket(runp->ai_family, runp->ai_socktype,
525 @@ -2883,17 +2906,8 @@
528 GVNC_DEBUG("Trying socket %d\n", fd);
529 - if ((flags = fcntl(fd, F_GETFL)) < 0) {
531 - GVNC_DEBUG ("Failed to fcntl()\n");
534 - flags |= O_NONBLOCK;
535 - if (fcntl(fd, F_SETFL, flags) < 0) {
537 - GVNC_DEBUG ("Failed to fcntl()\n");
540 + if (!gvnc_set_nonblock(fd))
543 if (!(chan = g_io_channel_unix_new(fd))) {
545 @@ -2904,21 +2918,22 @@
547 /* FIXME: Better handle EINPROGRESS/EISCONN return values,
548 as explained in connect(2) man page */
549 - if ( (connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) || errno == EISCONN) {
550 + if ((connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) ||
551 + socket_errno() == EISCONN) {
552 gvnc->channel = chan;
555 return !gvnc_has_error(gvnc);
558 - if (errno == EINPROGRESS) {
559 + if (socket_errno() == EINPROGRESS ||
560 + socket_errno() == EWOULDBLOCK) {
561 g_io_wait(chan, G_IO_OUT|G_IO_ERR|G_IO_HUP);
563 - } else if (errno != ECONNREFUSED &&
564 - errno != EHOSTUNREACH) {
565 + } else if (socket_errno() != ECONNREFUSED &&
566 + socket_errno() != EHOSTUNREACH) {
567 g_io_channel_unref(chan);
569 - GVNC_DEBUG ("Failed with errno = %d\n", errno);
570 + GVNC_DEBUG ("Failed with errno = %d\n", socket_errno());
574 diff -urN gtk-vnc-0.3.7/src/Makefile.am gtk-vnc-0.3.7.mingw/src/Makefile.am
575 --- gtk-vnc-0.3.7/src/Makefile.am 2008-09-05 13:32:15.000000000 +0100
576 +++ gtk-vnc-0.3.7.mingw/src/Makefile.am 2008-10-09 12:19:03.000000000 +0100
578 lib_LTLIBRARIES = libgtk-vnc-1.0.la
580 libgtk_vnc_1_0_la_LIBADD = @GTK_LIBS@ @GTKGLEXT_LIBS@ @GNUTLS_LIBS@ \
583 + ../gnulib/lib/libgnu.la
584 libgtk_vnc_1_0_la_CFLAGS = @GTK_CFLAGS@ @GTKGLEXT_CFLAGS@ @GNUTLS_CFLAGS@ \
585 @GTHREAD_CFLAGS@ @WARNING_CFLAGS@ \
586 -DSYSCONFDIR=\""$(sysconfdir)"\" \
587 - -DG_LOG_DOMAIN=\"gtk-vnc\"
588 + -DG_LOG_DOMAIN=\"gtk-vnc\" \
589 + -I$(top_srcdir)gnulib/lib -I../gnulib/lib
590 libgtk_vnc_1_0_la_LDFLAGS = -Wl, @LD_VERSION_SCRIPT_SUPPORT@ \
591 - -version-info 0:1:0
592 + -version-info 0:1:0 -no-undefined
594 gtk_vnc_includedir = $(includedir)/gtk-vnc-1.0/
595 gtk_vnc_include_HEADERS = vncdisplay.h
597 vncdisplay.h vncdisplay.c \
598 vncmarshal.h vncmarshal.c \
599 x_keymap.h x_keymap.c vnc_keycodes.h \
601 + utils.h socketcompat.h
604 libgtk_vnc_1_0_la_SOURCES += continuation.h continuation.c coroutine_ucontext.c
605 diff -urN gtk-vnc-0.3.7/src/socketcompat.h gtk-vnc-0.3.7.mingw/src/socketcompat.h
606 --- gtk-vnc-0.3.7/src/socketcompat.h 1970-01-01 01:00:00.000000000 +0100
607 +++ gtk-vnc-0.3.7.mingw/src/socketcompat.h 2008-10-09 12:19:03.000000000 +0100
610 + * socketcompat.h: Socket compatibility for Windows, making it slightly
611 + * less painful to use.
613 + * Use this header under the following circumstances:
614 + * (a) Instead of including any of: <net/if.h>, <netinet/in.h>,
615 + * <sys/socket.h>, <netdb.h>, <netinet/tcp.h>, AND
616 + * (b) The file will be part of what is built on Windows (basically
617 + * just remote client stuff).
619 + * You need to use socket_errno() instead of errno to get socket
622 + * Copyright (C) 2008 Red Hat, Inc.
624 + * See COPYING.LIB for the License of this software
626 + * Richard W.M. Jones <rjones@redhat.com>
629 +#ifndef __SOCKETCOMPAT_H__
630 +#define __SOCKETCOMPAT_H__
636 +#ifndef HAVE_WINSOCK2_H /* Unix & Cygwin. */
638 +#include <sys/socket.h>
641 +#include <netinet/in.h>
642 +#include <netinet/tcp.h>
650 +#else /* MinGW & Win32 */
652 +#include <winsock2.h>
654 +/* Socket functions in Windows don't set errno. Instead of using errno
655 + * to test for socket errors, call this function to get the errno.
660 + return WSAGetLastError ();
663 +/* Compatibility. */
664 +#define EWOULDBLOCK WSAEWOULDBLOCK
665 +#define ECONNREFUSED WSAECONNREFUSED
666 +#define EINPROGRESS WSAEINPROGRESS
667 +#define EHOSTUNREACH WSAEHOSTUNREACH
668 +#define EISCONN WSAEISCONN
670 +#endif /* HAVE_WINSOCK2_H */
672 +#endif /* __WINSOCKWRAPPER_H__ */
673 diff -urN gtk-vnc-0.3.7/src/vncdisplay.c gtk-vnc-0.3.7.mingw/src/vncdisplay.c
674 --- gtk-vnc-0.3.7/src/vncdisplay.c 2008-10-09 12:16:42.000000000 +0100
675 +++ gtk-vnc-0.3.7.mingw/src/vncdisplay.c 2008-10-09 12:19:03.000000000 +0100
682 #include "vncdisplay.h"
683 #include "coroutine.h"
686 #include <sys/types.h>
687 #include <sys/stat.h>
694 #include <gtk/gtkgl.h>
695 @@ -2191,33 +2195,44 @@
697 static int vnc_display_set_x509_credential(VncDisplay *obj, const char *name)
699 - char sysdir[PATH_MAX], userdir[PATH_MAX];
702 + char sysdir[PATH_MAX];
704 + char userdir[PATH_MAX];
706 char *dirs[] = { sysdir, userdir };
708 + char *dirs[] = { sysdir };
711 strncpy(sysdir, SYSCONFDIR "/pki", PATH_MAX-1);
712 sysdir[PATH_MAX-1] = '\0';
715 if (!(pw = getpwuid(getuid())))
718 snprintf(userdir, PATH_MAX-1, "%s/.pki", pw->pw_dir);
719 userdir[PATH_MAX-1] = '\0';
722 - if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem", dirs, 2) < 0)
723 + if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem",
724 + dirs, sizeof(dirs)/sizeof(dirs[0])) < 0)
726 gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
728 /* Don't mind failures of CRL */
729 - if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem", dirs, 2) == 0)
730 + if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem",
731 + dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
732 gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
734 /* Set client key & cert if we have them. Server will reject auth
735 * if it decides it requires them*/
736 - if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem", dirs, 2) == 0)
737 + if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem",
738 + dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
739 gvnc_set_credential_x509_key(obj->priv->gvnc, file);
740 - if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem", dirs, 2) == 0)
741 + if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem",
742 + dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
743 gvnc_set_credential_x509_cert(obj->priv->gvnc, file);
746 diff -urN gtk-vnc-0.3.7/src/vncdisplay.c.orig gtk-vnc-0.3.7.mingw/src/vncdisplay.c.orig
747 --- gtk-vnc-0.3.7/src/vncdisplay.c.orig 2008-09-05 13:32:16.000000000 +0100
748 +++ gtk-vnc-0.3.7.mingw/src/vncdisplay.c.orig 1970-01-01 01:00:00.000000000 +0100
751 - * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
753 - * This program is free software; you can redistribute it and/or modify
754 - * it under the terms of the GNU Lesser General Public License version 2 or
755 - * later as published by the Free Software Foundation.
760 -#include "vncdisplay.h"
761 -#include "coroutine.h"
764 -#include "vncmarshal.h"
766 -#include "x_keymap.h"
768 -#include <gtk/gtk.h>
771 -#include <gdk/gdkkeysyms.h>
772 -#include <gdk-pixbuf/gdk-pixbuf.h>
773 -#include <sys/types.h>
774 -#include <sys/stat.h>
779 -#include <gtk/gtkgl.h>
783 -#define VNC_DISPLAY_GET_PRIVATE(obj) \
784 - (G_TYPE_INSTANCE_GET_PRIVATE((obj), VNC_TYPE_DISPLAY, VncDisplayPrivate))
786 -struct _VncDisplayPrivate
793 - GdkCursor *null_cursor;
794 - GdkCursor *remote_cursor;
798 - GdkGLConfig *gl_config;
799 - GdkGLDrawable *gl_drawable;
800 - GdkGLContext *gl_context;
801 - uint8_t *gl_tex_data;
802 - int gl_texture_width;
803 - int gl_texture_height;
809 - struct gvnc_framebuffer fb;
810 - struct coroutine coroutine;
815 - gboolean in_pointer_grab;
816 - gboolean in_keyboard_grab;
818 - guint down_keyval[16];
819 - guint down_scancode[16];
827 - gboolean grab_pointer;
828 - gboolean grab_keyboard;
829 - gboolean local_pointer;
830 - gboolean read_only;
831 - gboolean allow_lossy;
832 - gboolean allow_scaling;
833 - gboolean shared_flag;
834 - gboolean force_size;
836 - GSList *preferable_auths;
839 -/* Delayed signal emission.
841 - * We want signals to be delivered in the system coroutine. This helps avoid
842 - * confusing applications. This is particularly important when using
843 - * GThread based coroutines since GTK gets very upset if a signal handler is
844 - * run in a different thread from the main loop if that signal handler isn't
845 - * written to use explicit locking.
850 - struct coroutine *caller;
853 - GValueArray *cred_list;
857 - unsigned int auth_type;
861 -G_DEFINE_TYPE(VncDisplay, vnc_display, GTK_TYPE_DRAWING_AREA)
867 - PROP_POINTER_LOCAL,
869 - PROP_KEYBOARD_GRAB,
874 - PROP_LOSSY_ENCODING,
884 - VNC_POINTER_UNGRAB,
886 - VNC_KEYBOARD_UNGRAB,
891 - VNC_AUTH_CREDENTIAL,
893 - VNC_DESKTOP_RESIZE,
896 - VNC_AUTH_UNSUPPORTED,
898 - VNC_SERVER_CUT_TEXT,
902 -} vnc_display_signals;
904 -static guint signals[LAST_SIGNAL] = { 0, 0, 0, 0,
907 -static GParamSpec *signalCredParam;
908 -gboolean debug_enabled = FALSE;
910 -static const GOptionEntry gtk_vnc_args[] =
912 - { "gtk-vnc-debug", 0, 0, G_OPTION_ARG_NONE, &debug_enabled, "Enables debug output", 0 },
913 - { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, 0 }
918 -vnc_display_get_property (GObject *object,
923 - VncDisplay *vnc = VNC_DISPLAY (object);
927 - case PROP_POINTER_LOCAL:
928 - g_value_set_boolean (value, vnc->priv->local_pointer);
930 - case PROP_POINTER_GRAB:
931 - g_value_set_boolean (value, vnc->priv->grab_pointer);
933 - case PROP_KEYBOARD_GRAB:
934 - g_value_set_boolean (value, vnc->priv->grab_keyboard);
936 - case PROP_READ_ONLY:
937 - g_value_set_boolean (value, vnc->priv->read_only);
940 - g_value_set_int (value, vnc_display_get_width (vnc));
943 - g_value_set_int (value, vnc_display_get_height (vnc));
946 - g_value_set_string (value, vnc_display_get_name (vnc));
948 - case PROP_LOSSY_ENCODING:
949 - g_value_set_boolean (value, vnc->priv->allow_lossy);
952 - g_value_set_boolean (value, vnc->priv->allow_scaling);
954 - case PROP_SHARED_FLAG:
955 - g_value_set_boolean (value, vnc->priv->shared_flag);
957 - case PROP_FORCE_SIZE:
958 - g_value_set_boolean (value, vnc->priv->force_size);
961 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
967 -vnc_display_set_property (GObject *object,
969 - const GValue *value,
972 - VncDisplay *vnc = VNC_DISPLAY (object);
976 - case PROP_POINTER_LOCAL:
977 - vnc_display_set_pointer_local (vnc, g_value_get_boolean (value));
979 - case PROP_POINTER_GRAB:
980 - vnc_display_set_pointer_grab (vnc, g_value_get_boolean (value));
982 - case PROP_KEYBOARD_GRAB:
983 - vnc_display_set_keyboard_grab (vnc, g_value_get_boolean (value));
985 - case PROP_READ_ONLY:
986 - vnc_display_set_read_only (vnc, g_value_get_boolean (value));
988 - case PROP_LOSSY_ENCODING:
989 - vnc_display_set_lossy_encoding (vnc, g_value_get_boolean (value));
992 - vnc_display_set_scaling (vnc, g_value_get_boolean (value));
994 - case PROP_SHARED_FLAG:
995 - vnc_display_set_shared_flag (vnc, g_value_get_boolean (value));
997 - case PROP_FORCE_SIZE:
998 - vnc_display_set_force_size (vnc, g_value_get_boolean (value));
1001 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1006 -GtkWidget *vnc_display_new(void)
1008 - return GTK_WIDGET(g_object_new(VNC_TYPE_DISPLAY, NULL));
1011 -static GdkCursor *create_null_cursor(void)
1014 - gchar data[4] = {0};
1015 - GdkColor fg = { 0, 0, 0, 0 };
1016 - GdkCursor *cursor;
1018 - image = gdk_bitmap_create_from_data(NULL, data, 1, 1);
1020 - cursor = gdk_cursor_new_from_pixmap(GDK_PIXMAP(image),
1021 - GDK_PIXMAP(image),
1023 - gdk_bitmap_unref(image);
1028 -static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose)
1030 - VncDisplay *obj = VNC_DISPLAY(widget);
1031 - VncDisplayPrivate *priv = obj->priv;
1033 - GdkRectangle drawn;
1034 - GdkRegion *clear, *copy;
1036 - GVNC_DEBUG("Expose %dx%d @ %d,%d\n",
1039 - expose->area.width,
1040 - expose->area.height);
1042 - if (priv->image == NULL) {
1044 - if (priv->gl_tex_data == NULL)
1047 - GdkGC *gc = gdk_gc_new(widget->window);
1048 - gdk_draw_rectangle(widget->window, gc, TRUE,
1049 - expose->area.x, expose->area.y,
1050 - expose->area.width,
1051 - expose->area.height);
1052 - g_object_unref(gc);
1058 - if (priv->gl_enabled) {
1060 - int wx = 0, wy = 0;
1061 - int ww = priv->gl_width, wh = priv->gl_height;
1062 - double scale_x, scale_y;
1064 - scale_x = (double)priv->gl_width / priv->fb.width;
1065 - scale_y = (double)priv->gl_height / priv->fb.height;
1067 - x = expose->area.x / scale_x;
1068 - y = expose->area.y / scale_y;
1069 - w = expose->area.width / scale_x;
1070 - h = expose->area.height / scale_y;
1082 - x = MIN(x, priv->fb.width);
1083 - y = MIN(y, priv->fb.height);
1084 - w = MIN(x + w, priv->fb.width);
1085 - h = MIN(y + h, priv->fb.height);
1089 - gdk_gl_drawable_gl_begin(priv->gl_drawable, priv->gl_context);
1090 - glBindTexture(GL_TEXTURE_2D, priv->gl_tex);
1091 - glPixelStorei(GL_UNPACK_ROW_LENGTH, priv->fb.width);
1092 - glTexSubImage2D(GL_TEXTURE_2D, 0,
1096 - priv->gl_tex_data +
1097 - y * 4 * priv->fb.width +
1099 - rx = (float)priv->fb.width / priv->gl_texture_width;
1100 - ry = (float)priv->fb.height / priv->gl_texture_height;
1102 - glEnable(GL_TEXTURE_2D);
1103 - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1104 - glBegin(GL_QUADS);
1105 - glTexCoord2f(0,ry); glVertex3f(wx, wy, 0);
1106 - glTexCoord2f(0,0); glVertex3f(wx, wy+wh, 0);
1107 - glTexCoord2f(rx,0); glVertex3f(wx+ww, wy+wh, 0);
1108 - glTexCoord2f(rx,ry); glVertex3f(wx+ww, wy, 0);
1110 - glDisable(GL_TEXTURE_2D);
1112 - gdk_gl_drawable_gl_end(priv->gl_drawable);
1116 - int mx = 0, my = 0;
1119 - gdk_drawable_get_size(widget->window, &ww, &wh);
1120 - if (ww > priv->fb.width)
1121 - mx = (ww - priv->fb.width) / 2;
1122 - if (wh > priv->fb.height)
1123 - my = (wh - priv->fb.height) / 2;
1125 - x = MIN(expose->area.x - mx, priv->fb.width);
1126 - y = MIN(expose->area.y - my, priv->fb.height);
1127 - w = MIN(expose->area.x + expose->area.width - mx, priv->fb.width);
1128 - h = MIN(expose->area.y + expose->area.height - my, priv->fb.height);
1142 - clear = gdk_region_rectangle(&expose->area);
1143 - copy = gdk_region_rectangle(&drawn);
1144 - gdk_region_subtract(clear, copy);
1146 - gdk_gc_set_clip_region(priv->gc, copy);
1147 - gdk_draw_image(widget->window, priv->gc, priv->image,
1148 - x, y, x + mx, y + my, w, h);
1150 - gdk_gc_set_clip_region(priv->gc, clear);
1151 - gdk_draw_rectangle(widget->window, priv->gc, TRUE, expose->area.x, expose->area.y,
1152 - expose->area.width, expose->area.height);
1154 - gdk_region_destroy(clear);
1155 - gdk_region_destroy(copy);
1161 -static void do_keyboard_grab(VncDisplay *obj, gboolean quiet)
1163 - VncDisplayPrivate *priv = obj->priv;
1165 - gdk_keyboard_grab(GTK_WIDGET(obj)->window,
1167 - GDK_CURRENT_TIME);
1168 - priv->in_keyboard_grab = TRUE;
1170 - g_signal_emit(obj, signals[VNC_KEYBOARD_GRAB], 0);
1174 -static void do_keyboard_ungrab(VncDisplay *obj, gboolean quiet)
1176 - VncDisplayPrivate *priv = obj->priv;
1178 - gdk_keyboard_ungrab(GDK_CURRENT_TIME);
1179 - priv->in_keyboard_grab = FALSE;
1181 - g_signal_emit(obj, signals[VNC_KEYBOARD_UNGRAB], 0);
1184 -static void do_pointer_hide(VncDisplay *obj)
1186 - VncDisplayPrivate *priv = obj->priv;
1187 - gdk_window_set_cursor(GTK_WIDGET(obj)->window,
1188 - priv->remote_cursor ? priv->remote_cursor : priv->null_cursor);
1191 -static void do_pointer_show(VncDisplay *obj)
1193 - VncDisplayPrivate *priv = obj->priv;
1194 - gdk_window_set_cursor(GTK_WIDGET(obj)->window,
1195 - priv->remote_cursor);
1198 -static void do_pointer_grab(VncDisplay *obj, gboolean quiet)
1200 - VncDisplayPrivate *priv = obj->priv;
1202 - /* If we're not already grabbing keyboard, grab it now */
1203 - if (!priv->grab_keyboard)
1204 - do_keyboard_grab(obj, quiet);
1206 - gdk_pointer_grab(GTK_WIDGET(obj)->window,
1208 - GDK_POINTER_MOTION_MASK |
1209 - GDK_BUTTON_PRESS_MASK |
1210 - GDK_BUTTON_RELEASE_MASK |
1211 - GDK_BUTTON_MOTION_MASK |
1213 - GTK_WIDGET(obj)->window,
1214 - priv->remote_cursor ? priv->remote_cursor : priv->null_cursor,
1215 - GDK_CURRENT_TIME);
1216 - priv->in_pointer_grab = TRUE;
1218 - g_signal_emit(obj, signals[VNC_POINTER_GRAB], 0);
1221 -static void do_pointer_ungrab(VncDisplay *obj, gboolean quiet)
1223 - VncDisplayPrivate *priv = obj->priv;
1225 - /* If we grabbed keyboard upon pointer grab, then ungrab it now */
1226 - if (!priv->grab_keyboard)
1227 - do_keyboard_ungrab(obj, quiet);
1229 - gdk_pointer_ungrab(GDK_CURRENT_TIME);
1230 - priv->in_pointer_grab = FALSE;
1232 - if (priv->absolute)
1233 - do_pointer_hide(obj);
1236 - g_signal_emit(obj, signals[VNC_POINTER_UNGRAB], 0);
1239 -void vnc_display_force_grab(VncDisplay *obj, gboolean enable)
1242 - do_pointer_grab(obj, FALSE);
1244 - do_pointer_ungrab(obj, FALSE);
1247 -static gboolean button_event(GtkWidget *widget, GdkEventButton *button)
1249 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1252 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1255 - if (priv->read_only)
1258 - gtk_widget_grab_focus (widget);
1260 - if (priv->grab_pointer && !priv->absolute && !priv->in_pointer_grab &&
1261 - button->button == 1 && button->type == GDK_BUTTON_PRESS)
1262 - do_pointer_grab(VNC_DISPLAY(widget), FALSE);
1264 - n = 1 << (button->button - 1);
1265 - if (button->type == GDK_BUTTON_PRESS)
1266 - priv->button_mask |= n;
1267 - else if (button->type == GDK_BUTTON_RELEASE)
1268 - priv->button_mask &= ~n;
1270 - if (priv->absolute) {
1271 - gvnc_pointer_event(priv->gvnc, priv->button_mask,
1272 - priv->last_x, priv->last_y);
1274 - gvnc_pointer_event(priv->gvnc, priv->button_mask,
1281 -static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *scroll)
1283 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1286 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1289 - if (priv->read_only)
1292 - if (scroll->direction == GDK_SCROLL_UP)
1294 - else if (scroll->direction == GDK_SCROLL_DOWN)
1296 - else if (scroll->direction == GDK_SCROLL_LEFT)
1298 - else if (scroll->direction == GDK_SCROLL_RIGHT)
1303 - if (priv->absolute) {
1304 - gvnc_pointer_event(priv->gvnc, priv->button_mask | mask,
1305 - priv->last_x, priv->last_y);
1306 - gvnc_pointer_event(priv->gvnc, priv->button_mask,
1307 - priv->last_x, priv->last_y);
1309 - gvnc_pointer_event(priv->gvnc, priv->button_mask | mask,
1311 - gvnc_pointer_event(priv->gvnc, priv->button_mask,
1318 -static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
1320 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1323 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1326 - if (!priv->absolute && !priv->in_pointer_grab)
1329 - if (priv->read_only)
1333 - if (priv->gl_enabled) {
1334 - motion->x *= priv->fb.width;
1335 - motion->x /= priv->gl_width;
1336 - motion->y *= priv->fb.height;
1337 - motion->y /= priv->gl_height;
1342 - int mw = 0, mh = 0;
1344 - gdk_drawable_get_size(widget->window, &ww, &wh);
1345 - if (ww > priv->fb.width)
1346 - mw = (ww - priv->fb.width) / 2;
1347 - if (wh > priv->fb.height)
1348 - mh = (wh - priv->fb.height) / 2;
1353 - if (motion->x < 0 || motion->x >= priv->fb.width ||
1354 - motion->y < 0 || motion->y >= priv->fb.height)
1358 - if (!priv->absolute && priv->in_pointer_grab) {
1359 - GdkDrawable *drawable = GDK_DRAWABLE(widget->window);
1360 - GdkDisplay *display = gdk_drawable_get_display(drawable);
1361 - GdkScreen *screen = gdk_drawable_get_screen(drawable);
1362 - int x = (int)motion->x_root;
1363 - int y = (int)motion->y_root;
1365 - if (x == 0) x += 200;
1366 - if (y == 0) y += 200;
1367 - if (x == (gdk_screen_get_width(screen) - 1)) x -= 200;
1368 - if (y == (gdk_screen_get_height(screen) - 1)) y -= 200;
1370 - if (x != (int)motion->x_root || y != (int)motion->y_root) {
1371 - gdk_display_warp_pointer(display, screen, x, y);
1372 - priv->last_x = -1;
1373 - priv->last_y = -1;
1378 - if (priv->last_x != -1) {
1379 - if (priv->absolute) {
1380 - dx = (int)motion->x;
1381 - dy = (int)motion->y;
1383 - dx = (int)motion->x + 0x7FFF - priv->last_x;
1384 - dy = (int)motion->y + 0x7FFF - priv->last_y;
1387 - gvnc_pointer_event(priv->gvnc, priv->button_mask, dx, dy);
1390 - priv->last_x = (int)motion->x;
1391 - priv->last_y = (int)motion->y;
1396 -static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
1398 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1400 - gint group, level;
1401 - GdkModifierType consumed;
1403 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1406 - if (priv->read_only)
1410 - * Key handling in VNC is screwy. The event.keyval from GTK is
1411 - * interpreted relative to modifier state. This really messes
1412 - * up with VNC which has no concept of modifiers - it just sees
1413 - * key up & down events - the remote end interprets modifiers
1414 - * itself. So if we interpret at the client end you can end up
1415 - * with 'Alt' key press generating Alt_L, and key release generating
1416 - * ISO_Prev_Group. This really really confuses the VNC server
1417 - * with 'Alt' getting stuck on.
1419 - * So we have to redo GTK's keycode -> keyval translation
1420 - * using only the SHIFT modifier which the RFB explicitly
1421 - * requires to be interpreted at client end.
1425 - gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
1426 - key->hardware_keycode,
1427 - key->state & (GDK_SHIFT_MASK | GDK_LOCK_MASK),
1434 - keyval = x_keymap_get_keyval_from_keycode(key->hardware_keycode, keyval);
1437 - * More VNC suckiness with key state & modifiers in particular
1439 - * Because VNC has no concept of modifiers, we have to track what keys are
1440 - * pressed and when the widget looses focus send fake key up events for all
1441 - * keys current held down. This is because upon gaining focus any keys held
1442 - * down are no longer likely to be down. This would thus result in keys
1443 - * being 'stuck on' in the remote server. eg upon Alt-Tab to switch window
1444 - * focus you'd never see key up for the Alt or Tab keys without this :-(
1446 - * This is mostly a problem with modifier keys, but its best to just track
1447 - * all key presses regardless. There's a limit to how many keys a user can
1448 - * press at once due to a max of 10 fingers (normally :-), so down_key_vals
1449 - * is only storing upto 16 for now. Should be plenty...
1453 - if (key->type == GDK_KEY_PRESS) {
1455 - for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
1456 - if (priv->down_scancode[i] == 0) {
1457 - priv->down_keyval[i] = keyval;
1458 - priv->down_scancode[i] = key->hardware_keycode;
1459 - /* Send the actual key event we're dealing with */
1460 - gvnc_key_event(priv->gvnc, 1, keyval, key->hardware_keycode);
1462 - } else if (priv->down_scancode[i] == key->hardware_keycode) {
1463 - /* Got an press when we're already pressed ! Why ... ?
1465 - * Well, GTK merges sequential press+release pairs of the same
1466 - * key so instead of press+release,press+release,press+release
1467 - * we only get press+press+press+press+press+release. This
1468 - * really annoys some VNC servers, so we have to un-merge
1469 - * them into a sensible stream of press+release pairs
1471 - /* Fake an up event for the previous down event */
1472 - gvnc_key_event(priv->gvnc, 0, keyval, key->hardware_keycode);
1473 - /* Now send our actual ldown event */
1474 - gvnc_key_event(priv->gvnc, 1, keyval, key->hardware_keycode);
1480 - for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
1481 - /* We were pressed, and now we're released, so... */
1482 - if (priv->down_scancode[i] == key->hardware_keycode) {
1483 - priv->down_keyval[i] = 0;
1484 - priv->down_scancode[i] = 0;
1485 - /* ..send the key release event we're dealing with */
1486 - gvnc_key_event(priv->gvnc, 0, keyval, key->hardware_keycode);
1492 - if ((!priv->grab_keyboard || !priv->absolute) &&
1493 - key->type == GDK_KEY_PRESS &&
1494 - ((keyval == GDK_Control_L && (key->state & GDK_MOD1_MASK)) ||
1495 - (keyval == GDK_Alt_L && (key->state & GDK_CONTROL_MASK)))) {
1496 - if (priv->in_pointer_grab)
1497 - do_pointer_ungrab(VNC_DISPLAY(widget), FALSE);
1499 - do_pointer_grab(VNC_DISPLAY(widget), FALSE);
1505 -static gboolean enter_event(GtkWidget *widget, GdkEventCrossing *crossing)
1507 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1509 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1512 - if (crossing->mode != GDK_CROSSING_NORMAL)
1515 - if (priv->grab_keyboard)
1516 - do_keyboard_grab(VNC_DISPLAY(widget), FALSE);
1521 -static gboolean leave_event(GtkWidget *widget, GdkEventCrossing *crossing)
1523 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1525 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1528 - if (crossing->mode != GDK_CROSSING_NORMAL)
1531 - if (priv->grab_keyboard)
1532 - do_keyboard_ungrab(VNC_DISPLAY(widget), FALSE);
1534 - if (priv->grab_pointer)
1535 - do_pointer_ungrab(VNC_DISPLAY(widget), FALSE);
1541 -static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSED)
1543 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1546 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1549 - for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
1550 - /* We are currently pressed so... */
1551 - if (priv->down_scancode[i] != 0) {
1552 - /* ..send the fake key release event to match */
1553 - gvnc_key_event(priv->gvnc, 0,
1554 - priv->down_keyval[i], priv->down_scancode[i]);
1555 - priv->down_keyval[i] = 0;
1556 - priv->down_scancode[i] = 0;
1564 -static void realize_event(GtkWidget *widget)
1566 - VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
1568 - GTK_WIDGET_CLASS (vnc_display_parent_class)->realize(widget);
1570 - if (priv->gl_config == NULL)
1573 - priv->gl_drawable = gtk_widget_get_gl_drawable(widget);
1574 - priv->gl_context = gtk_widget_get_gl_context(widget);
1578 -static gboolean on_update(void *opaque, int x, int y, int w, int h)
1580 - GtkWidget *widget = GTK_WIDGET(opaque);
1581 - VncDisplay *obj = VNC_DISPLAY(widget);
1582 - VncDisplayPrivate *priv = obj->priv;
1585 - if (priv->gl_enabled) {
1586 - double scale_x, scale_y;
1588 - scale_x = (double)priv->gl_width / priv->fb.width;
1589 - scale_y = (double)priv->gl_height / priv->fb.height;
1599 - int mw = 0, mh = 0;
1601 - gdk_drawable_get_size(widget->window, &ww, &wh);
1602 - if (ww > priv->fb.width)
1603 - mw = (ww - priv->fb.width) / 2;
1604 - if (wh > priv->fb.height)
1605 - mh = (wh - priv->fb.height) / 2;
1611 - gtk_widget_queue_draw_area(widget, x, y, w, h);
1616 -static void setup_gdk_image(VncDisplay *obj, gint width, gint height)
1618 - VncDisplayPrivate *priv = obj->priv;
1619 - GdkVisual *visual;
1621 - visual = gdk_drawable_get_visual(GTK_WIDGET(obj)->window);
1623 - priv->image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
1624 - GVNC_DEBUG("Visual mask: %3d %3d %3d\n shift: %3d %3d %3d\n",
1626 - visual->green_mask,
1627 - visual->blue_mask,
1628 - visual->red_shift,
1629 - visual->green_shift,
1630 - visual->blue_shift);
1632 - priv->fb.red_mask = visual->red_mask >> visual->red_shift;
1633 - priv->fb.green_mask = visual->green_mask >> visual->green_shift;
1634 - priv->fb.blue_mask = visual->blue_mask >> visual->blue_shift;
1635 - priv->fb.red_shift = visual->red_shift;
1636 - priv->fb.green_shift = visual->green_shift;
1637 - priv->fb.blue_shift = visual->blue_shift;
1638 - priv->fb.depth = priv->image->depth;
1639 - priv->fb.bpp = priv->image->bpp;
1640 - priv->fb.width = priv->image->width;
1641 - priv->fb.height = priv->image->height;
1642 - priv->fb.linesize = priv->image->bpl;
1643 - priv->fb.data = (uint8_t *)priv->image->mem;
1644 - priv->fb.byte_order = priv->image->byte_order == GDK_LSB_FIRST ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
1646 - if (priv->force_size)
1647 - gtk_widget_set_size_request(GTK_WIDGET(obj), width, height);
1651 -static int pow_of_2(int value)
1654 - for (i = 0; value >= (1 << i); i++);
1658 -static void setup_gl_image(VncDisplay *obj, gint width, gint height)
1660 - VncDisplayPrivate *priv = VNC_DISPLAY(obj)->priv;
1663 - priv->gl_texture_width = pow_of_2(width);
1664 - priv->gl_texture_height = pow_of_2(height);
1666 - gdk_gl_drawable_gl_begin(priv->gl_drawable, priv->gl_context);
1668 - glGenTextures(1, &priv->gl_tex);
1669 - glBindTexture(GL_TEXTURE_2D, priv->gl_tex);
1670 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1671 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1673 - dummy = g_malloc(priv->gl_texture_width*priv->gl_texture_height*4);
1674 - memset(dummy, 0, priv->gl_texture_width*priv->gl_texture_height*4);
1675 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1676 - priv->gl_texture_width, priv->gl_texture_height, 0,
1677 - GL_RGB, GL_UNSIGNED_BYTE,
1681 - gdk_gl_drawable_gl_end(priv->gl_drawable);
1683 - priv->gl_tex_data = g_malloc(width * height * 4);
1685 - priv->fb.red_mask = 0xFF;
1686 - priv->fb.green_mask = 0xFF;
1687 - priv->fb.blue_mask = 0xFF;
1688 - priv->fb.red_shift = 16;
1689 - priv->fb.green_shift = 8;
1690 - priv->fb.blue_shift = 0;
1691 - priv->fb.depth = 32;
1693 - priv->fb.width = width;
1694 - priv->fb.height = height;
1695 - priv->fb.linesize = priv->fb.width * priv->fb.bpp;
1696 - priv->fb.data = (uint8_t *)priv->gl_tex_data;
1700 -static gboolean emit_signal_auth_cred(gpointer opaque)
1702 - struct signal_data *s = opaque;
1704 - switch (s->signum) {
1705 - case VNC_AUTH_CREDENTIAL:
1706 - g_signal_emit(G_OBJECT(s->obj),
1707 - signals[VNC_AUTH_CREDENTIAL],
1711 - case VNC_DESKTOP_RESIZE:
1712 - g_signal_emit(G_OBJECT(s->obj),
1713 - signals[VNC_DESKTOP_RESIZE],
1715 - s->width, s->height);
1717 - case VNC_AUTH_FAILURE:
1718 - g_signal_emit(G_OBJECT(s->obj),
1719 - signals[VNC_AUTH_FAILURE],
1723 - case VNC_AUTH_UNSUPPORTED:
1724 - g_signal_emit(G_OBJECT(s->obj),
1725 - signals[VNC_AUTH_UNSUPPORTED],
1729 - case VNC_SERVER_CUT_TEXT:
1730 - g_signal_emit(G_OBJECT(s->obj),
1731 - signals[VNC_SERVER_CUT_TEXT],
1736 - case VNC_CONNECTED:
1737 - case VNC_INITIALIZED:
1738 - case VNC_DISCONNECTED:
1739 - g_signal_emit(G_OBJECT(s->obj),
1740 - signals[s->signum],
1745 - coroutine_yieldto(s->caller, NULL);
1750 -/* This function should be used to emit signals from gvnc callbacks */
1751 -static void emit_signal_delayed(VncDisplay *obj, int signum,
1752 - struct signal_data *data)
1755 - data->caller = coroutine_self();
1756 - data->signum = signum;
1757 - g_idle_add(emit_signal_auth_cred, data);
1758 - coroutine_yield(NULL);
1761 -static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
1763 - VncDisplay *obj = VNC_DISPLAY(opaque);
1764 - VncDisplayPrivate *priv = obj->priv;
1765 - struct signal_data s;
1767 - if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
1770 - if (priv->image) {
1771 - g_object_unref(priv->image);
1772 - priv->image = NULL;
1776 - if (priv->gl_tex_data) {
1777 - gdk_gl_drawable_gl_begin(priv->gl_drawable,
1778 - priv->gl_context);
1779 - glDeleteTextures(1, &priv->gl_tex);
1780 - gdk_gl_drawable_gl_end(priv->gl_drawable);
1781 - g_free(priv->gl_tex_data);
1782 - priv->gl_tex_data = NULL;
1786 - if (priv->gc == NULL) {
1787 - priv->null_cursor = create_null_cursor();
1788 - if (priv->local_pointer)
1789 - do_pointer_show(obj);
1790 - else if (priv->in_pointer_grab || priv->absolute)
1791 - do_pointer_hide(obj);
1792 - priv->gc = gdk_gc_new(GTK_WIDGET(obj)->window);
1796 - if (priv->gl_enabled)
1797 - setup_gl_image(obj, width, height);
1800 - setup_gdk_image(obj, width, height);
1802 - gvnc_set_local(priv->gvnc, &priv->fb);
1806 - s.height = height;
1807 - emit_signal_delayed(obj, VNC_DESKTOP_RESIZE, &s);
1813 -static gboolean on_resize(void *opaque, int width, int height)
1815 - return do_resize(opaque, width, height, FALSE);
1818 -static gboolean on_pixel_format(void *opaque,
1819 - struct gvnc_pixel_format *fmt G_GNUC_UNUSED)
1821 - VncDisplay *obj = VNC_DISPLAY(opaque);
1822 - VncDisplayPrivate *priv = obj->priv;
1824 - return do_resize(opaque, priv->fb.width, priv->fb.height, TRUE);
1827 -static gboolean on_get_preferred_pixel_format(void *opaque,
1828 - struct gvnc_pixel_format *fmt)
1830 - VncDisplay *obj = VNC_DISPLAY(opaque);
1831 - GdkVisual *v = gdk_drawable_get_visual(GTK_WIDGET(obj)->window);
1833 - GVNC_DEBUG("Setting pixel format to true color\n");
1835 - fmt->true_color_flag = 1;
1836 - fmt->depth = v->depth;
1837 - fmt->bits_per_pixel = v->depth > 16 ? 32 : v->depth;
1838 - fmt->red_max = v->red_mask >> v->red_shift;
1839 - fmt->green_max = v->green_mask >> v->green_shift;
1840 - fmt->blue_max = v->blue_mask >> v->blue_shift;
1841 - fmt->red_shift = v->red_shift;
1842 - fmt->green_shift = v->green_shift;
1843 - fmt->blue_shift = v->blue_shift;
1844 - fmt->byte_order = v->byte_order == GDK_LSB_FIRST ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
1850 -static void build_gl_image_from_gdk(uint32_t *data, GdkImage *image)
1852 - GdkVisual *visual;
1856 - visual = image->visual;
1858 - for (j = 0; j < image->height; j++) {
1859 - uint8_t *src = row;
1860 - for (i = 0; i < image->width; i++) {
1861 - uint32_t pixel = 0;
1862 - switch (image->bpp) {
1864 - pixel = *(uint8_t *)src;
1867 - pixel = *(uint16_t *)src;
1870 - pixel = *(uint32_t *)src;
1873 - *data = ((pixel & visual->red_mask) >> visual->red_shift) << (24 - visual->red_prec) |
1874 - ((pixel & visual->green_mask) >> visual->green_shift) << (16 - visual->green_prec) |
1875 - ((pixel & visual->blue_mask) >> visual->blue_shift) << (8 - visual->blue_prec);
1876 - src += image->bpp;
1879 - row += image->bpl;
1884 -static void build_gdk_image_from_gl(GdkImage *image, uint32_t *data)
1886 - GdkVisual *visual;
1890 - visual = image->visual;
1892 - for (j = 0; j < image->height; j++) {
1893 - uint8_t *dst = row;
1894 - for (i = 0; i < image->width; i++) {
1897 - pixel = (((*data >> (24 - visual->red_prec)) << visual->red_shift) & visual->red_mask) |
1898 - (((*data >> (16 - visual->green_prec)) << visual->green_shift) & visual->green_mask) |
1899 - (((*data >> (8 - visual->blue_prec)) << visual->blue_shift) & visual->blue_mask);
1901 - switch (image->bpp) {
1903 - *(uint8_t *)dst = pixel;
1906 - *(uint16_t *)dst = pixel;
1909 - *(uint32_t *)dst = pixel;
1912 - dst += image->bpp;
1915 - row += image->bpl;
1919 -static void scale_display(VncDisplay *obj, gint width, gint height)
1921 - VncDisplayPrivate *priv = VNC_DISPLAY(obj)->priv;
1923 - if (priv->gl_drawable == NULL)
1926 - if (priv->gl_enabled == 0) {
1929 - priv->gl_enabled = 1;
1931 - image = priv->image;
1932 - priv->image = NULL;
1934 - do_resize(obj, priv->fb.width, priv->fb.height, TRUE);
1935 - build_gl_image_from_gdk((uint32_t *)priv->fb.data, image);
1937 - g_object_unref(image);
1940 - priv->gl_width = width;
1941 - priv->gl_height = height;
1943 - gdk_gl_drawable_gl_begin(priv->gl_drawable, priv->gl_context);
1944 - glClearColor (0.0, 0.0, 0.0, 0.0);
1945 - glShadeModel(GL_FLAT);
1946 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1948 - glViewport(0, 0, priv->gl_width, priv->gl_height);
1949 - glMatrixMode(GL_PROJECTION);
1951 - glOrtho(0.0, priv->gl_width, 0.0, priv->gl_height, -1, 1);
1952 - glMatrixMode(GL_MODELVIEW);
1954 - gdk_gl_drawable_gl_end(priv->gl_drawable);
1957 -static void rescale_display(VncDisplay *obj, gint width, gint height)
1959 - VncDisplayPrivate *priv = obj->priv;
1961 - if (priv->allow_scaling &&
1962 - (priv->fb.width != width ||
1963 - priv->fb.height != height))
1964 - scale_display(obj, width, height);
1965 - else if (priv->gl_enabled) {
1967 - priv->gl_enabled = 0;
1969 - data = priv->gl_tex_data;
1970 - priv->gl_tex_data = NULL;
1972 - do_resize(GTK_WIDGET(obj), priv->fb.width, priv->fb.height, TRUE);
1974 - build_gdk_image_from_gl(priv->image, (uint32_t *)data);
1975 - gdk_gl_drawable_gl_begin(priv->gl_drawable,
1976 - priv->gl_context);
1977 - glDeleteTextures(1, &priv->gl_tex);
1978 - gdk_gl_drawable_gl_end(priv->gl_drawable);
1983 -static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *configure)
1985 - VncDisplay *obj = VNC_DISPLAY(widget);
1986 - VncDisplayPrivate *priv = obj->priv;
1988 - if (priv->fb.data == NULL)
1991 - rescale_display(VNC_DISPLAY(widget),
1992 - configure->width, configure->height);
1998 -static gboolean on_pointer_type_change(void *opaque, int absolute)
2000 - VncDisplay *obj = VNC_DISPLAY(opaque);
2001 - VncDisplayPrivate *priv = obj->priv;
2003 - if (absolute && priv->in_pointer_grab && !priv->grab_pointer)
2004 - do_pointer_ungrab(obj, FALSE);
2006 - priv->absolute = absolute;
2008 - if (!priv->in_pointer_grab && !priv->absolute)
2009 - do_pointer_show(obj);
2014 -static gboolean on_auth_cred(void *opaque)
2016 - VncDisplay *obj = VNC_DISPLAY(opaque);
2017 - GValueArray *cred_list;
2018 - GValue username, password, clientname;
2019 - struct signal_data s;
2021 - memset(&username, 0, sizeof(username));
2022 - memset(&password, 0, sizeof(password));
2023 - memset(&clientname, 0, sizeof(clientname));
2025 - cred_list = g_value_array_new(0);
2026 - if (gvnc_wants_credential_username(obj->priv->gvnc)) {
2027 - g_value_init(&username, G_PARAM_SPEC_VALUE_TYPE(signalCredParam));
2028 - g_value_set_enum(&username, VNC_DISPLAY_CREDENTIAL_USERNAME);
2029 - cred_list = g_value_array_append(cred_list, &username);
2031 - if (gvnc_wants_credential_password(obj->priv->gvnc)) {
2032 - g_value_init(&password, G_PARAM_SPEC_VALUE_TYPE(signalCredParam));
2033 - g_value_set_enum(&password, VNC_DISPLAY_CREDENTIAL_PASSWORD);
2034 - cred_list = g_value_array_append(cred_list, &password);
2036 - if (gvnc_wants_credential_x509(obj->priv->gvnc)) {
2037 - g_value_init(&clientname, G_PARAM_SPEC_VALUE_TYPE(signalCredParam));
2038 - g_value_set_enum(&clientname, VNC_DISPLAY_CREDENTIAL_CLIENTNAME);
2039 - cred_list = g_value_array_append(cred_list, &clientname);
2042 - s.cred_list = cred_list;
2043 - emit_signal_delayed(obj, VNC_AUTH_CREDENTIAL, &s);
2045 - g_value_array_free(cred_list);
2050 -static gboolean on_auth_type(void *opaque, unsigned int ntype, unsigned int *types)
2052 - VncDisplay *obj = VNC_DISPLAY(opaque);
2053 - VncDisplayPrivate *priv = obj->priv;
2060 - for (l = priv->preferable_auths; l; l=l->next) {
2061 - gvnc_auth pref = GPOINTER_TO_UINT (l->data);
2063 - for (i=0; i<ntype; i++) {
2064 - if (pref == types[i]) {
2065 - gvnc_set_auth_type(priv->gvnc, types[i]);
2071 - gvnc_set_auth_type(priv->gvnc, types[0]);
2075 -static gboolean on_auth_subtype(void *opaque, unsigned int ntype, unsigned int *types)
2077 - VncDisplay *obj = VNC_DISPLAY(opaque);
2078 - VncDisplayPrivate *priv = obj->priv;
2086 - for (l = priv->preferable_auths; l; l=l->next) {
2087 - gvnc_auth pref = GPOINTER_TO_UINT (l->data);
2089 - for (i=0; i<ntype; i++) {
2090 - if (pref == types[i]) {
2091 - gvnc_set_auth_subtype(priv->gvnc, types[i]);
2097 - gvnc_set_auth_subtype(priv->gvnc, types[0]);
2101 -static gboolean on_auth_failure(void *opaque, const char *msg)
2103 - VncDisplay *obj = VNC_DISPLAY(opaque);
2104 - struct signal_data s;
2107 - emit_signal_delayed(obj, VNC_AUTH_FAILURE, &s);
2112 -static gboolean on_auth_unsupported(void *opaque, unsigned int auth_type)
2114 - VncDisplay *obj = VNC_DISPLAY(opaque);
2115 - struct signal_data s;
2117 - s.auth_type = auth_type;
2118 - emit_signal_delayed(obj, VNC_AUTH_UNSUPPORTED, &s);
2123 -static gboolean on_server_cut_text(void *opaque, const void* text, size_t len)
2125 - VncDisplay *obj = VNC_DISPLAY(opaque);
2126 - GString *str = g_string_new_len ((const gchar *)text, len);
2127 - struct signal_data s;
2130 - emit_signal_delayed(obj, VNC_SERVER_CUT_TEXT, &s);
2132 - g_string_free (str, TRUE);
2136 -static gboolean on_bell(void *opaque)
2138 - VncDisplay *obj = VNC_DISPLAY(opaque);
2139 - struct signal_data s;
2141 - emit_signal_delayed(obj, VNC_BELL, &s);
2146 -static gboolean on_local_cursor(void *opaque, int x, int y, int width, int height, uint8_t *image)
2148 - VncDisplay *obj = VNC_DISPLAY(opaque);
2149 - VncDisplayPrivate *priv = obj->priv;
2151 - if (priv->remote_cursor) {
2152 - gdk_cursor_unref(priv->remote_cursor);
2153 - priv->remote_cursor = NULL;
2156 - if (width && height) {
2157 - GdkDisplay *display = gdk_drawable_get_display(GDK_DRAWABLE(GTK_WIDGET(obj)->window));
2158 - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(image, GDK_COLORSPACE_RGB,
2159 - TRUE, 8, width, height,
2160 - width * 4, NULL, NULL);
2161 - priv->remote_cursor = gdk_cursor_new_from_pixbuf(display,
2164 - gdk_pixbuf_unref(pixbuf);
2167 - if (priv->in_pointer_grab) {
2168 - do_pointer_ungrab(obj, TRUE);
2169 - do_pointer_grab(obj, TRUE);
2170 - } else if (priv->absolute) {
2171 - do_pointer_hide(obj);
2177 -static gboolean check_pixbuf_support(const char *name)
2181 - list = gdk_pixbuf_get_formats();
2183 - for (i = list; i; i = i->next) {
2184 - GdkPixbufFormat *fmt = i->data;
2185 - if (!strcmp(gdk_pixbuf_format_get_name(fmt), name))
2189 - g_slist_free(list);
2194 -static gboolean on_render_jpeg(void *opaque G_GNUC_UNUSED,
2195 - rgb24_render_func *render, void *render_opaque,
2196 - int x, int y, int w, int h,
2197 - uint8_t *data, int size)
2199 - GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
2203 - if (!gdk_pixbuf_loader_write(loader, data, size, NULL))
2206 - gdk_pixbuf_loader_close(loader, NULL);
2208 - p = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
2209 - g_object_unref(loader);
2211 - pixels = gdk_pixbuf_get_pixels(p);
2213 - render(render_opaque, x, y, w, h,
2214 - gdk_pixbuf_get_pixels(p),
2215 - gdk_pixbuf_get_rowstride(p));
2217 - gdk_pixbuf_unref(p);
2222 -static const struct gvnc_ops vnc_display_ops = {
2223 - .auth_cred = on_auth_cred,
2224 - .auth_type = on_auth_type,
2225 - .auth_subtype = on_auth_subtype,
2226 - .auth_failure = on_auth_failure,
2227 - .update = on_update,
2228 - .resize = on_resize,
2229 - .pixel_format = on_pixel_format,
2230 - .pointer_type_change = on_pointer_type_change,
2231 - .local_cursor = on_local_cursor,
2232 - .auth_unsupported = on_auth_unsupported,
2233 - .server_cut_text = on_server_cut_text,
2235 - .render_jpeg = on_render_jpeg,
2236 - .get_preferred_pixel_format = on_get_preferred_pixel_format
2239 -/* we use an idle function to allow the coroutine to exit before we actually
2240 - * unref the object since the coroutine's state is part of the object */
2241 -static gboolean delayed_unref_object(gpointer data)
2243 - VncDisplay *obj = VNC_DISPLAY(data);
2245 - g_assert(obj->priv->coroutine.exited == TRUE);
2247 - if (obj->priv->image) {
2248 - g_object_unref(obj->priv->image);
2249 - obj->priv->image = NULL;
2253 - if (obj->priv->gl_tex_data)
2254 - g_free(obj->priv->gl_tex_data);
2255 - obj->priv->gl_tex_data = NULL;
2256 - obj->priv->gl_enabled = 0;
2259 - g_object_unref(G_OBJECT(data));
2263 -static void *vnc_coroutine(void *opaque)
2265 - VncDisplay *obj = VNC_DISPLAY(opaque);
2266 - VncDisplayPrivate *priv = obj->priv;
2268 - /* this order is extremely important! */
2269 - int32_t encodings[] = { GVNC_ENCODING_TIGHT_JPEG5,
2270 - GVNC_ENCODING_TIGHT,
2271 - GVNC_ENCODING_EXT_KEY_EVENT,
2272 - GVNC_ENCODING_DESKTOP_RESIZE,
2273 - GVNC_ENCODING_WMVi,
2274 - GVNC_ENCODING_RICH_CURSOR,
2275 - GVNC_ENCODING_XCURSOR,
2276 - GVNC_ENCODING_POINTER_CHANGE,
2277 - GVNC_ENCODING_ZRLE,
2278 - GVNC_ENCODING_HEXTILE,
2279 - GVNC_ENCODING_RRE,
2280 - GVNC_ENCODING_COPY_RECT,
2281 - GVNC_ENCODING_RAW };
2282 - int32_t *encodingsp;
2285 - struct signal_data s;
2287 - if (priv->gvnc == NULL || gvnc_is_open(priv->gvnc)) {
2288 - g_idle_add(delayed_unref_object, obj);
2292 - GVNC_DEBUG("Started background coroutine\n");
2293 - x_keymap_set_keymap_entries();
2295 - if (priv->fd != -1) {
2296 - if (!gvnc_open_fd(priv->gvnc, priv->fd))
2299 - if (!gvnc_open_host(priv->gvnc, priv->host, priv->port))
2303 - emit_signal_delayed(obj, VNC_CONNECTED, &s);
2305 - GVNC_DEBUG("Protocol initialization\n");
2306 - if (!gvnc_initialize(priv->gvnc, priv->shared_flag))
2309 - emit_signal_delayed(obj, VNC_INITIALIZED, &s);
2311 - encodingsp = encodings;
2312 - n_encodings = G_N_ELEMENTS(encodings);
2314 - if (check_pixbuf_support("jpeg")) {
2315 - if (!priv->allow_lossy) {
2324 - if (!gvnc_set_encodings(priv->gvnc, n_encodings, encodingsp))
2327 - if (!gvnc_framebuffer_update_request(priv->gvnc, 0, 0, 0, priv->fb.width, priv->fb.height))
2330 - GVNC_DEBUG("Running main loop\n");
2331 - while ((ret = gvnc_server_message(priv->gvnc))) {
2332 - if (!gvnc_framebuffer_update_request(priv->gvnc, 1, 0, 0,
2333 - priv->fb.width, priv->fb.height))
2338 - GVNC_DEBUG("Doing final VNC cleanup\n");
2339 - gvnc_close(priv->gvnc);
2340 - emit_signal_delayed(obj, VNC_DISCONNECTED, &s);
2341 - g_idle_add(delayed_unref_object, obj);
2342 - x_keymap_free_keymap_entries();
2343 - /* Co-routine exits now - the VncDisplay object may no longer exist,
2344 - so don't do anything else now unless you like SEGVs */
2348 -static gboolean do_vnc_display_open(gpointer data)
2350 - VncDisplay *obj = VNC_DISPLAY(data);
2351 - struct coroutine *co;
2353 - if (obj->priv->gvnc == NULL || gvnc_is_open(obj->priv->gvnc)) {
2354 - g_object_unref(G_OBJECT(obj));
2358 - obj->priv->open_id = 0;
2360 - co = &obj->priv->coroutine;
2362 - co->stack_size = 16 << 20;
2363 - co->entry = vnc_coroutine;
2364 - co->release = NULL;
2366 - coroutine_init(co);
2367 - coroutine_yieldto(co, obj);
2372 -gboolean vnc_display_open_fd(VncDisplay *obj, int fd)
2374 - if (obj->priv->gvnc == NULL || gvnc_is_open(obj->priv->gvnc))
2377 - obj->priv->fd = fd;
2378 - obj->priv->host = NULL;
2379 - obj->priv->port = NULL;
2381 - g_object_ref(G_OBJECT(obj)); /* Unref'd when co-routine exits */
2382 - obj->priv->open_id = g_idle_add(do_vnc_display_open, obj);
2387 -gboolean vnc_display_open_host(VncDisplay *obj, const char *host, const char *port)
2389 - if (obj->priv->gvnc == NULL || gvnc_is_open(obj->priv->gvnc))
2392 - obj->priv->host = g_strdup(host);
2393 - if (!obj->priv->host) {
2396 - obj->priv->port = g_strdup(port);
2397 - if (!obj->priv->port) {
2398 - g_free(obj->priv->host);
2399 - obj->priv->host = NULL;
2403 - g_object_ref(G_OBJECT(obj)); /* Unref'd when co-routine exits */
2404 - obj->priv->open_id = g_idle_add(do_vnc_display_open, obj);
2408 -gboolean vnc_display_is_open(VncDisplay *obj)
2410 - if (obj->priv->gvnc == NULL)
2412 - return gvnc_is_open(obj->priv->gvnc);
2415 -void vnc_display_close(VncDisplay *obj)
2417 - VncDisplayPrivate *priv = obj->priv;
2418 - GtkWidget *widget = GTK_WIDGET(obj);
2420 - if (priv->open_id) {
2421 - g_source_remove(priv->open_id);
2422 - obj->priv->open_id = 0;
2425 - if (priv->gvnc == NULL)
2428 - if (gvnc_is_open(priv->gvnc)) {
2429 - GVNC_DEBUG("Requesting graceful shutdown of connection\n");
2430 - gvnc_shutdown(priv->gvnc);
2434 - if (priv->gl_tex_data) {
2435 - gdk_gl_drawable_gl_begin(priv->gl_drawable,
2436 - priv->gl_context);
2437 - glDeleteTextures(1, &priv->gl_tex);
2438 - gdk_gl_drawable_gl_end(priv->gl_drawable);
2442 - if (widget->window) {
2443 - gint width, height;
2445 - gdk_drawable_get_size(widget->window, &width, &height);
2446 - gtk_widget_queue_draw_area(widget, 0, 0, width, height);
2451 -void vnc_display_send_keys(VncDisplay *obj, const guint *keyvals, int nkeyvals)
2453 - vnc_display_send_keys_ex(obj, keyvals,
2454 - nkeyvals, VNC_DISPLAY_KEY_EVENT_CLICK);
2457 -static guint get_keycode_from_keyval(guint keyval)
2459 - guint keycode = 0;
2460 - GdkKeymapKey *keys = NULL;
2463 - if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(),
2464 - keyval, &keys, &n_keys)) {
2465 - /* FIXME what about levels? */
2466 - keycode = keys[0].keycode;
2473 -void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
2474 - int nkeyvals, VncDisplayKeyEvent kind)
2478 - if (obj->priv->gvnc == NULL || !gvnc_is_open(obj->priv->gvnc))
2481 - if (kind & VNC_DISPLAY_KEY_EVENT_PRESS) {
2482 - for (i = 0 ; i < nkeyvals ; i++)
2483 - gvnc_key_event(obj->priv->gvnc, 1, keyvals[i],
2484 - get_keycode_from_keyval(keyvals[i]));
2487 - if (kind & VNC_DISPLAY_KEY_EVENT_RELEASE) {
2488 - for (i = (nkeyvals-1) ; i >= 0 ; i--)
2489 - gvnc_key_event(obj->priv->gvnc, 0, keyvals[i],
2490 - get_keycode_from_keyval(keyvals[i]));
2494 -void vnc_display_send_pointer(VncDisplay *obj, gint x, gint y, int button_mask)
2496 - VncDisplayPrivate *priv = obj->priv;
2498 - if (priv->gvnc == NULL || !gvnc_is_open(obj->priv->gvnc))
2501 - if (priv->absolute) {
2502 - priv->button_mask = button_mask;
2505 - gvnc_pointer_event(priv->gvnc, priv->button_mask, x, y);
2509 -static void vnc_display_destroy (GtkObject *obj)
2511 - VncDisplay *display = VNC_DISPLAY (obj);
2512 - GVNC_DEBUG("Requesting that VNC close\n");
2513 - vnc_display_close(display);
2514 - GTK_OBJECT_CLASS (vnc_display_parent_class)->destroy (obj);
2518 -static void vnc_display_finalize (GObject *obj)
2520 - VncDisplay *display = VNC_DISPLAY (obj);
2521 - VncDisplayPrivate *priv = display->priv;
2523 - GVNC_DEBUG("Releasing VNC widget\n");
2524 - if (gvnc_is_open(priv->gvnc)) {
2525 - g_warning("VNC widget finalized before the connection finished shutting down\n");
2527 - gvnc_free(priv->gvnc);
2528 - display->priv->gvnc = NULL;
2531 - if (priv->gl_enabled) {
2532 - gdk_gl_drawable_gl_begin(priv->gl_drawable,
2533 - priv->gl_context);
2534 - glDeleteTextures(1, &priv->gl_tex);
2535 - gdk_gl_drawable_gl_end(priv->gl_drawable);
2536 - if (priv->gl_tex_data) {
2537 - g_free(priv->gl_tex_data);
2538 - priv->gl_tex_data = NULL;
2542 - if (priv->gl_config) {
2543 - g_object_unref(G_OBJECT(priv->gl_config));
2544 - priv->gl_config = NULL;
2548 - if (priv->image) {
2549 - g_object_unref(priv->image);
2550 - priv->image = NULL;
2553 - g_slist_free (priv->preferable_auths);
2555 - G_OBJECT_CLASS (vnc_display_parent_class)->finalize (obj);
2558 -static void vnc_display_class_init(VncDisplayClass *klass)
2560 - GObjectClass *object_class = G_OBJECT_CLASS (klass);
2561 - GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
2562 - GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
2564 - gtkwidget_class->expose_event = expose_event;
2565 - gtkwidget_class->motion_notify_event = motion_event;
2566 - gtkwidget_class->button_press_event = button_event;
2567 - gtkwidget_class->button_release_event = button_event;
2568 - gtkwidget_class->scroll_event = scroll_event;
2569 - gtkwidget_class->key_press_event = key_event;
2570 - gtkwidget_class->key_release_event = key_event;
2571 - gtkwidget_class->enter_notify_event = enter_event;
2572 - gtkwidget_class->leave_notify_event = leave_event;
2573 - gtkwidget_class->focus_out_event = focus_event;
2575 - gtkwidget_class->realize = realize_event;
2576 - gtkwidget_class->configure_event = configure_event;
2580 - object_class->finalize = vnc_display_finalize;
2581 - object_class->get_property = vnc_display_get_property;
2582 - object_class->set_property = vnc_display_set_property;
2584 - gtkobject_class->destroy = vnc_display_destroy;
2586 - g_object_class_install_property (object_class,
2587 - PROP_POINTER_LOCAL,
2588 - g_param_spec_boolean ( "local-pointer",
2590 - "Whether we should use the local pointer",
2592 - G_PARAM_READWRITE |
2593 - G_PARAM_CONSTRUCT |
2594 - G_PARAM_STATIC_NAME |
2595 - G_PARAM_STATIC_NICK |
2596 - G_PARAM_STATIC_BLURB));
2597 - g_object_class_install_property (object_class,
2598 - PROP_POINTER_GRAB,
2599 - g_param_spec_boolean ( "grab-pointer",
2601 - "Whether we should grab the pointer",
2603 - G_PARAM_READWRITE |
2604 - G_PARAM_CONSTRUCT |
2605 - G_PARAM_STATIC_NAME |
2606 - G_PARAM_STATIC_NICK |
2607 - G_PARAM_STATIC_BLURB));
2608 - g_object_class_install_property (object_class,
2609 - PROP_KEYBOARD_GRAB,
2610 - g_param_spec_boolean ( "grab-keyboard",
2612 - "Whether we should grab the keyboard",
2614 - G_PARAM_READWRITE |
2615 - G_PARAM_CONSTRUCT |
2616 - G_PARAM_STATIC_NAME |
2617 - G_PARAM_STATIC_NICK |
2618 - G_PARAM_STATIC_BLURB));
2619 - g_object_class_install_property (object_class,
2621 - g_param_spec_boolean ( "read-only",
2623 - "Whether this connection is read-only mode",
2625 - G_PARAM_READWRITE |
2626 - G_PARAM_CONSTRUCT |
2627 - G_PARAM_STATIC_NAME |
2628 - G_PARAM_STATIC_NICK |
2629 - G_PARAM_STATIC_BLURB));
2630 - g_object_class_install_property (object_class,
2632 - g_param_spec_int ( "width",
2634 - "The width of the remote screen",
2638 - G_PARAM_READABLE |
2639 - G_PARAM_STATIC_NAME |
2640 - G_PARAM_STATIC_NICK |
2641 - G_PARAM_STATIC_BLURB));
2642 - g_object_class_install_property (object_class,
2644 - g_param_spec_int ( "height",
2646 - "The height of the remote screen",
2650 - G_PARAM_READABLE |
2651 - G_PARAM_STATIC_NAME |
2652 - G_PARAM_STATIC_NICK |
2653 - G_PARAM_STATIC_BLURB));
2654 - g_object_class_install_property (object_class,
2656 - g_param_spec_string ( "name",
2658 - "The screen name of the remote connection",
2660 - G_PARAM_READABLE |
2661 - G_PARAM_STATIC_NAME |
2662 - G_PARAM_STATIC_NICK |
2663 - G_PARAM_STATIC_BLURB));
2664 - g_object_class_install_property (object_class,
2665 - PROP_LOSSY_ENCODING,
2666 - g_param_spec_boolean ( "lossy-encoding",
2668 - "Whether we should use a lossy encoding",
2670 - G_PARAM_READWRITE |
2671 - G_PARAM_CONSTRUCT |
2672 - G_PARAM_STATIC_NAME |
2673 - G_PARAM_STATIC_NICK |
2674 - G_PARAM_STATIC_BLURB));
2675 - g_object_class_install_property (object_class,
2677 - g_param_spec_boolean ( "scaling",
2679 - "Whether we should use scaling",
2681 - G_PARAM_READWRITE |
2682 - G_PARAM_CONSTRUCT |
2683 - G_PARAM_STATIC_NAME |
2684 - G_PARAM_STATIC_NICK |
2685 - G_PARAM_STATIC_BLURB));
2686 - g_object_class_install_property (object_class,
2688 - g_param_spec_boolean ( "shared-flag",
2690 - "Whether we should leave other clients connected to the server",
2692 - G_PARAM_READWRITE |
2693 - G_PARAM_CONSTRUCT |
2694 - G_PARAM_STATIC_NAME |
2695 - G_PARAM_STATIC_NICK |
2696 - G_PARAM_STATIC_BLURB));
2697 - g_object_class_install_property (object_class,
2699 - g_param_spec_boolean ( "force-size",
2700 - "Force widget size",
2701 - "Whether we should define the widget size",
2703 - G_PARAM_READWRITE |
2704 - G_PARAM_CONSTRUCT |
2705 - G_PARAM_STATIC_NAME |
2706 - G_PARAM_STATIC_NICK |
2707 - G_PARAM_STATIC_BLURB));
2709 - signalCredParam = g_param_spec_enum("credential",
2712 - vnc_display_credential_get_type(),
2714 - G_PARAM_READABLE);
2716 - signals[VNC_CONNECTED] =
2717 - g_signal_new ("vnc-connected",
2718 - G_OBJECT_CLASS_TYPE (object_class),
2719 - G_SIGNAL_RUN_FIRST,
2720 - G_STRUCT_OFFSET (VncDisplayClass, vnc_connected),
2722 - g_cclosure_marshal_VOID__VOID,
2726 - signals[VNC_INITIALIZED] =
2727 - g_signal_new ("vnc-initialized",
2728 - G_OBJECT_CLASS_TYPE (object_class),
2729 - G_SIGNAL_RUN_FIRST,
2730 - G_STRUCT_OFFSET (VncDisplayClass, vnc_initialized),
2732 - g_cclosure_marshal_VOID__VOID,
2736 - signals[VNC_DISCONNECTED] =
2737 - g_signal_new ("vnc-disconnected",
2738 - G_OBJECT_CLASS_TYPE (object_class),
2739 - G_SIGNAL_RUN_FIRST,
2740 - G_STRUCT_OFFSET (VncDisplayClass, vnc_disconnected),
2742 - g_cclosure_marshal_VOID__VOID,
2746 - signals[VNC_AUTH_CREDENTIAL] =
2747 - g_signal_new ("vnc-auth-credential",
2748 - G_OBJECT_CLASS_TYPE (object_class),
2749 - G_SIGNAL_RUN_FIRST,
2750 - G_STRUCT_OFFSET (VncDisplayClass, vnc_auth_credential),
2752 - g_cclosure_marshal_VOID__BOXED,
2755 - G_TYPE_VALUE_ARRAY);
2758 - signals[VNC_POINTER_GRAB] =
2759 - g_signal_new("vnc-pointer-grab",
2760 - G_TYPE_FROM_CLASS(klass),
2761 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2765 - g_cclosure_marshal_VOID__VOID,
2769 - signals[VNC_POINTER_UNGRAB] =
2770 - g_signal_new("vnc-pointer-ungrab",
2771 - G_TYPE_FROM_CLASS(klass),
2772 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2776 - g_cclosure_marshal_VOID__VOID,
2780 - signals[VNC_KEYBOARD_GRAB] =
2781 - g_signal_new("vnc-keyboard-grab",
2782 - G_TYPE_FROM_CLASS(klass),
2783 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2787 - g_cclosure_marshal_VOID__VOID,
2791 - signals[VNC_KEYBOARD_UNGRAB] =
2792 - g_signal_new("vnc-keyboard-ungrab",
2793 - G_TYPE_FROM_CLASS(klass),
2794 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2798 - g_cclosure_marshal_VOID__VOID,
2803 - signals[VNC_DESKTOP_RESIZE] =
2804 - g_signal_new("vnc-desktop-resize",
2805 - G_TYPE_FROM_CLASS(klass),
2806 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2810 - g_cclosure_user_marshal_VOID__INT_INT,
2813 - G_TYPE_INT, G_TYPE_INT);
2815 - signals[VNC_AUTH_FAILURE] =
2816 - g_signal_new("vnc-auth-failure",
2817 - G_TYPE_FROM_CLASS(klass),
2818 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2822 - g_cclosure_marshal_VOID__STRING,
2827 - signals[VNC_AUTH_UNSUPPORTED] =
2828 - g_signal_new("vnc-auth-unsupported",
2829 - G_TYPE_FROM_CLASS(klass),
2830 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2834 - g_cclosure_marshal_VOID__UINT,
2839 - signals[VNC_SERVER_CUT_TEXT] =
2840 - g_signal_new("vnc-server-cut-text",
2841 - G_TYPE_FROM_CLASS(klass),
2842 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2846 - g_cclosure_marshal_VOID__STRING,
2851 - signals[VNC_BELL] =
2852 - g_signal_new("vnc-bell",
2853 - G_TYPE_FROM_CLASS(klass),
2854 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_HOOKS,
2858 - g_cclosure_marshal_VOID__VOID,
2862 - g_type_class_add_private(klass, sizeof(VncDisplayPrivate));
2865 -static void vnc_display_init(VncDisplay *display)
2867 - GtkObject *obj = GTK_OBJECT(display);
2868 - GtkWidget *widget = GTK_WIDGET(display);
2869 - VncDisplayPrivate *priv;
2871 - GTK_WIDGET_SET_FLAGS(obj, GTK_CAN_FOCUS);
2873 - gtk_widget_add_events(widget,
2874 - GDK_POINTER_MOTION_MASK |
2875 - GDK_BUTTON_PRESS_MASK |
2876 - GDK_BUTTON_RELEASE_MASK |
2877 - GDK_BUTTON_MOTION_MASK |
2878 - GDK_ENTER_NOTIFY_MASK |
2879 - GDK_LEAVE_NOTIFY_MASK |
2881 - GDK_KEY_PRESS_MASK);
2882 - gtk_widget_set_double_buffered(widget, FALSE);
2884 - priv = display->priv = VNC_DISPLAY_GET_PRIVATE(display);
2885 - memset(priv, 0, sizeof(VncDisplayPrivate));
2886 - priv->last_x = -1;
2887 - priv->last_y = -1;
2888 - priv->absolute = 1;
2890 - priv->read_only = FALSE;
2891 - priv->allow_lossy = FALSE;
2892 - priv->allow_scaling = FALSE;
2893 - priv->grab_pointer = FALSE;
2894 - priv->grab_keyboard = FALSE;
2895 - priv->local_pointer = FALSE;
2896 - priv->shared_flag = FALSE;
2897 - priv->force_size = TRUE;
2899 - priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_VENCRYPT));
2900 - priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_TLS));
2901 - priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_VNC));
2902 - priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_NONE));
2905 - if (gtk_gl_init_check(NULL, NULL)) {
2906 - priv->gl_config = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB |
2907 - GDK_GL_MODE_DEPTH);
2908 - if (!gtk_widget_set_gl_capability(widget,
2912 - GDK_GL_RGBA_TYPE)) {
2913 - g_warning("Could not enable OpenGL");
2914 - g_object_unref(G_OBJECT(priv->gl_config));
2915 - priv->gl_config = NULL;
2918 - priv->gl_config = NULL;
2921 - priv->gvnc = gvnc_new(&vnc_display_ops, obj);
2924 -static int vnc_display_best_path(char *buf,
2926 - const char *basedir,
2927 - const char *basefile,
2929 - unsigned int ndirs)
2932 - for (i = 0 ; i < ndirs ; i++) {
2934 - snprintf(buf, buflen-1, "%s/%s/%s", dirs[i], basedir, basefile);
2935 - buf[buflen-1] = '\0';
2936 - if (stat(buf, &sb) == 0)
2942 -static int vnc_display_set_x509_credential(VncDisplay *obj, const char *name)
2944 - char sysdir[PATH_MAX], userdir[PATH_MAX];
2945 - struct passwd *pw;
2946 - char file[PATH_MAX];
2947 - char *dirs[] = { sysdir, userdir };
2949 - strncpy(sysdir, SYSCONFDIR "/pki", PATH_MAX-1);
2950 - sysdir[PATH_MAX-1] = '\0';
2952 - if (!(pw = getpwuid(getuid())))
2955 - snprintf(userdir, PATH_MAX-1, "%s/.pki", pw->pw_dir);
2956 - userdir[PATH_MAX-1] = '\0';
2958 - if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem", dirs, 2) < 0)
2960 - gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
2962 - /* Don't mind failures of CRL */
2963 - if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem", dirs, 2) == 0)
2964 - gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
2966 - /* Set client key & cert if we have them. Server will reject auth
2967 - * if it decides it requires them*/
2968 - if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem", dirs, 2) == 0)
2969 - gvnc_set_credential_x509_key(obj->priv->gvnc, file);
2970 - if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem", dirs, 2) == 0)
2971 - gvnc_set_credential_x509_cert(obj->priv->gvnc, file);
2976 -gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data)
2979 - case VNC_DISPLAY_CREDENTIAL_PASSWORD:
2980 - if (gvnc_set_credential_password(obj->priv->gvnc, data))
2984 - case VNC_DISPLAY_CREDENTIAL_USERNAME:
2985 - if (gvnc_set_credential_username(obj->priv->gvnc, data))
2989 - case VNC_DISPLAY_CREDENTIAL_CLIENTNAME:
2990 - return vnc_display_set_x509_credential(obj, data);
2996 -void vnc_display_set_pointer_local(VncDisplay *obj, gboolean enable)
2998 - if (obj->priv->gc) {
3000 - do_pointer_show(obj);
3001 - else if (obj->priv->in_pointer_grab || obj->priv->absolute)
3002 - do_pointer_hide(obj);
3004 - obj->priv->local_pointer = enable;
3007 -void vnc_display_set_pointer_grab(VncDisplay *obj, gboolean enable)
3009 - VncDisplayPrivate *priv = obj->priv;
3011 - priv->grab_pointer = enable;
3012 - if (!enable && priv->absolute && priv->in_pointer_grab)
3013 - do_pointer_ungrab(obj, FALSE);
3016 -void vnc_display_set_keyboard_grab(VncDisplay *obj, gboolean enable)
3018 - VncDisplayPrivate *priv = obj->priv;
3020 - priv->grab_keyboard = enable;
3021 - if (!enable && priv->in_keyboard_grab && !priv->in_pointer_grab)
3022 - do_keyboard_ungrab(obj, FALSE);
3025 -void vnc_display_set_read_only(VncDisplay *obj, gboolean enable)
3027 - obj->priv->read_only = enable;
3030 -GType vnc_display_credential_get_type(void)
3032 - static GType etype = 0;
3035 - static const GEnumValue values[] = {
3036 - { VNC_DISPLAY_CREDENTIAL_PASSWORD, "VNC_DISPLAY_CREDENTIAL_PASSWORD", "password" },
3037 - { VNC_DISPLAY_CREDENTIAL_USERNAME, "VNC_DISPLAY_CREDENTIAL_USERNAME", "username" },
3038 - { VNC_DISPLAY_CREDENTIAL_CLIENTNAME, "VNC_DISPLAY_CREDENTIAL_CLIENTNAME", "clientname" },
3041 - etype = g_enum_register_static ("VncDisplayCredentialType", values );
3047 -GType vnc_display_key_event_get_type(void)
3049 - static GType etype = 0;
3052 - static const GEnumValue values[] = {
3053 - { VNC_DISPLAY_KEY_EVENT_PRESS, "VNC_DISPLAY_KEY_EVENT_PRESS", "press" },
3054 - { VNC_DISPLAY_KEY_EVENT_RELEASE, "VNC_DISPLAY_KEY_EVENT_RELEASE", "release" },
3055 - { VNC_DISPLAY_KEY_EVENT_CLICK, "VNC_DISPLAY_KEY_EVENT_CLICK", "click" },
3058 - etype = g_enum_register_static ("VncDisplayKeyEvents", values );
3064 -GdkPixbuf *vnc_display_get_pixbuf(VncDisplay *obj)
3066 - VncDisplayPrivate *priv = obj->priv;
3067 - GdkPixbuf *pixbuf;
3069 - if (!priv->gvnc ||
3070 - !gvnc_is_initialized(priv->gvnc))
3073 - pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
3074 - priv->image->width, priv->image->height);
3076 - if (!gdk_pixbuf_get_from_image(pixbuf,
3078 - gdk_colormap_get_system(),
3080 - priv->image->width,
3081 - priv->image->height))
3088 -int vnc_display_get_width(VncDisplay *obj)
3090 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), -1);
3092 - return gvnc_get_width (obj->priv->gvnc);
3095 -int vnc_display_get_height(VncDisplay *obj)
3097 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), -1);
3099 - return gvnc_get_height (obj->priv->gvnc);
3102 -const char * vnc_display_get_name(VncDisplay *obj)
3104 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), NULL);
3106 - return gvnc_get_name (obj->priv->gvnc);
3109 -void vnc_display_client_cut_text(VncDisplay *obj, const gchar *text)
3111 - g_return_if_fail (VNC_IS_DISPLAY (obj));
3113 - gvnc_client_cut_text(obj->priv->gvnc, text, strlen (text));
3116 -void vnc_display_set_lossy_encoding(VncDisplay *obj, gboolean enable)
3118 - g_return_if_fail (VNC_IS_DISPLAY (obj));
3119 - obj->priv->allow_lossy = enable;
3122 -void vnc_display_set_shared_flag(VncDisplay *obj, gboolean shared)
3124 - g_return_if_fail (VNC_IS_DISPLAY (obj));
3125 - obj->priv->shared_flag = shared;
3129 -gboolean vnc_display_set_scaling(VncDisplay *obj, gboolean enable)
3131 - GtkWidget *widget = GTK_WIDGET(obj);
3132 - gint width, height;
3134 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3135 - if (obj->priv->gl_config == NULL)
3138 - obj->priv->allow_scaling = enable;
3139 - if (gvnc_is_open(obj->priv->gvnc) && widget->window) {
3140 - gdk_drawable_get_size(widget->window, &width, &height);
3141 - rescale_display(obj, width, height);
3142 - gtk_widget_queue_draw_area(widget, 0, 0, width, height);
3148 -gboolean vnc_display_set_scaling(VncDisplay *obj G_GNUC_UNUSED,
3149 - gboolean enable G_GNUC_UNUSED)
3155 -void vnc_display_set_force_size(VncDisplay *obj, gboolean enabled)
3157 - g_return_if_fail (VNC_IS_DISPLAY (obj));
3158 - obj->priv->force_size = enabled;
3161 -gboolean vnc_display_get_force_size(VncDisplay *obj)
3163 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3165 - return obj->priv->force_size;
3168 -gboolean vnc_display_get_scaling(VncDisplay *obj)
3170 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3172 - return obj->priv->allow_scaling;
3175 -gboolean vnc_display_get_lossy_encoding(VncDisplay *obj)
3177 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3179 - return obj->priv->allow_lossy;
3182 -gboolean vnc_display_get_shared_flag(VncDisplay *obj)
3184 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3186 - return obj->priv->shared_flag;
3189 -gboolean vnc_display_get_pointer_local(VncDisplay *obj)
3191 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3193 - return obj->priv->local_pointer;
3196 -gboolean vnc_display_get_pointer_grab(VncDisplay *obj)
3198 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3200 - return obj->priv->grab_pointer;
3203 -gboolean vnc_display_get_keyboard_grab(VncDisplay *obj)
3205 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3207 - return obj->priv->grab_keyboard;
3210 -gboolean vnc_display_get_read_only(VncDisplay *obj)
3212 - g_return_val_if_fail (VNC_IS_DISPLAY (obj), FALSE);
3214 - return obj->priv->read_only;
3217 -gboolean vnc_display_is_pointer_absolute(VncDisplay *obj)
3219 - return obj->priv->absolute;
3223 -vnc_display_get_option_group (void)
3225 - GOptionGroup *group;
3227 - group = g_option_group_new ("gtk-vnc", "GTK-VNC Options", "Show GTK-VNC Options", NULL, NULL);
3229 - g_option_group_add_entries (group, gtk_vnc_args);
3235 - * Local variables:
3236 - * c-indent-level: 8
3237 - * c-basic-offset: 8
3241 diff -urN gtk-vnc-0.3.7/vc-list-files gtk-vnc-0.3.7.mingw/vc-list-files
3242 --- gtk-vnc-0.3.7/vc-list-files 1970-01-01 01:00:00.000000000 +0100
3243 +++ gtk-vnc-0.3.7.mingw/vc-list-files 2008-10-09 12:19:03.000000000 +0100
3246 +# List version-controlled file names.
3248 +# Print a version string.
3249 +scriptversion=2008-07-11.19
3251 +# Copyright (C) 2006-2008 Free Software Foundation, Inc.
3253 +# This program is free software: you can redistribute it and/or modify
3254 +# it under the terms of the GNU General Public License as published by
3255 +# the Free Software Foundation, either version 3 of the License, or
3256 +# (at your option) any later version.
3258 +# This program is distributed in the hope that it will be useful,
3259 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
3260 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3261 +# GNU General Public License for more details.
3263 +# You should have received a copy of the GNU General Public License
3264 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
3267 +# List the specified version-controlled files.
3268 +# With no argument, list them all. With a single DIRECTORY argument,
3269 +# list the version-controlled files in that directory.
3271 +# If there's an argument, it must be a single, "."-relative directory name.
3272 +# cvsu is part of the cvsutils package: http://www.red-bean.com/cvsutils/
3277 +Usage: $0 [-C SRCDIR] [DIR]
3279 +Output a list of version-controlled files in DIR (default .), relative to
3280 +SRCDIR (default .). SRCDIR must be the top directory of a checkout.
3283 + --help print this help, then exit
3284 + --version print version number, then exit
3285 + -C SRCDIR change directory to SRCDIR before generating list
3287 +Report bugs and patches to <bug-gnulib@gnu.org>.
3292 + year=`echo "$scriptversion" | sed 's/[^0-9].*//'`
3294 +vc-list-files $scriptversion
3295 +Copyright (C) $year Free Software Foundation, Inc,
3296 +License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
3297 +This is free software: you are free to change and redistribute it.
3298 +There is NO WARRANTY, to the extent permitted by law.
3303 + test "$2" = . || postprocess="| sed 's|^|$2/|'"
3312 + *) echo "$0: too many arguments" 1>&2
3313 + echo "Usage: $0 [-C srcdir] [DIR]" 1>&2; exit 1;;
3316 +test "x$dir" = x && dir=.
3318 +if test -d .git; then
3319 + eval exec git ls-files '"$dir"' $postprocess
3320 +elif test -d .hg; then
3321 + eval exec hg locate '"$dir/*"' $postprocess
3322 +elif test -d .bzr; then
3323 + test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
3324 + eval exec bzr ls --versioned '"$dir"' $postprocess
3325 +elif test -d CVS; then
3326 + test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
3327 + if test -x build-aux/cvsu; then
3328 + eval build-aux/cvsu --find --types=AFGM '"$dir"' $postprocess
3329 + elif (cvsu --help) >/dev/null 2>&1; then
3330 + eval cvsu --find --types=AFGM '"$dir"' $postprocess
3332 + eval awk -F/ \''{ \
3333 + if (!$1 && $3 !~ /^-/) { \
3335 + if (f ~ /CVS\/Entries$/) \
3336 + f = substr(f, 0, length(f)-11); \
3339 + `find "$dir" -name Entries -print` /dev/null' $postprocess
3342 + echo "$0: Failed to determine type of version control used in `pwd`" 1>&2
3347 +# eval: (add-hook 'write-file-hooks 'time-stamp)
3348 +# time-stamp-start: "scriptversion="
3349 +# time-stamp-format: "%:y-%02m-%02d.%02H"
3350 +# time-stamp-end: "$"