diff --git a/Makefile.in b/Makefile.in index 153886e..f7961a8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -121,8 +121,6 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -146,7 +144,6 @@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB2_CFLAGS = @GLIB2_CFLAGS@ GLIB2_LIBS = @GLIB2_LIBS@ -GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTK_API_VERSION = @GTK_API_VERSION@ @@ -161,8 +158,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ @@ -182,11 +177,9 @@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ MOZILLA_PLUGIN_CFLAGS = @MOZILLA_PLUGIN_CFLAGS@ MOZILLA_PLUGIN_LIBS = @MOZILLA_PLUGIN_LIBS@ MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -207,10 +200,6 @@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ diff --git a/NEWS b/NEWS index f25d574..177f975 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,13 @@ Virt Viewer News ================ + +0.4.1: Aug 4, 2011 +------------------- + + - Remove bogus use of AM_GLIB_GNU_GETTEXT macro to try to + facilitate BSD builds + - Support multiple monitors with SPICE and QXL drivers + - Don't hardcode SSH port to 22 when tunnelling 0.4.0: Jul 12, 2011 ------------------- diff --git a/aclocal.m4 b/aclocal.m4 index fd5b0eb..bb090aa 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -18,439 +18,6 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) - -# Copyright (C) 1995-2002 Free Software Foundation, Inc. -# Copyright (C) 2001-2003,2004 Red Hat, Inc. -# -# This file is free software, distributed under the terms of the GNU -# General Public License. As a special exception to the GNU General -# Public License, this file may be distributed as part of a program -# that contains a configuration script generated by Autoconf, under -# the same distribution terms as the rest of that program. -# -# This file can be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU Public License -# but which still want to provide support for the GNU gettext functionality. -# -# Macro to add for using GNU gettext. -# Ulrich Drepper , 1995, 1996 -# -# Modified to never use included libintl. -# Owen Taylor , 12/15/1998 -# -# Major rework to remove unused code -# Owen Taylor , 12/11/2002 -# -# Added better handling of ALL_LINGUAS from GNU gettext version -# written by Bruno Haible, Owen Taylor 5/30/3002 -# -# Modified to require ngettext -# Matthias Clasen 08/06/2004 -# -# We need this here as well, since someone might use autoconf-2.5x -# to configure GLib then an older version to configure a package -# using AM_GLIB_GNU_GETTEXT -AC_PREREQ(2.53) - -dnl -dnl We go to great lengths to make sure that aclocal won't -dnl try to pull in the installed version of these macros -dnl when running aclocal in the glib directory. -dnl -m4_copy([AC_DEFUN],[glib_DEFUN]) -m4_copy([AC_REQUIRE],[glib_REQUIRE]) -dnl -dnl At the end, if we're not within glib, we'll define the public -dnl definitions in terms of our private definitions. -dnl - -# GLIB_LC_MESSAGES -#-------------------- -glib_DEFUN([GLIB_LC_MESSAGES], - [AC_CHECK_HEADERS([locale.h]) - if test $ac_cv_header_locale_h = yes; then - AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, - [AC_TRY_LINK([#include ], [return LC_MESSAGES], - am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) - if test $am_cv_val_LC_MESSAGES = yes; then - AC_DEFINE(HAVE_LC_MESSAGES, 1, - [Define if your file defines LC_MESSAGES.]) - fi - fi]) - -# GLIB_PATH_PROG_WITH_TEST -#---------------------------- -dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, -dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) -glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], -[# Extract the first word of "$2", so it can be a program name with args. -set dummy $2; ac_word=[$]2 -AC_MSG_CHECKING([for $ac_word]) -AC_CACHE_VAL(ac_cv_path_$1, -[case "[$]$1" in - /*) - ac_cv_path_$1="[$]$1" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in ifelse([$5], , $PATH, [$5]); do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if [$3]; then - ac_cv_path_$1="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" -dnl If no 4th arg is given, leave the cache variable unset, -dnl so AC_PATH_PROGS will keep looking. -ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" -])dnl - ;; -esac])dnl -$1="$ac_cv_path_$1" -if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then - AC_MSG_RESULT([$]$1) -else - AC_MSG_RESULT(no) -fi -AC_SUBST($1)dnl -]) - -# GLIB_WITH_NLS -#----------------- -glib_DEFUN([GLIB_WITH_NLS], - dnl NLS is obligatory - [USE_NLS=yes - AC_SUBST(USE_NLS) - - gt_cv_have_gettext=no - - CATOBJEXT=NONE - XGETTEXT=: - INTLLIBS= - - AC_CHECK_HEADER(libintl.h, - [gt_cv_func_dgettext_libintl="no" - libintl_extra_libs="" - - # - # First check in libc - # - AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, - [AC_TRY_LINK([ -#include -], - [return !ngettext ("","", 1)], - gt_cv_func_ngettext_libc=yes, - gt_cv_func_ngettext_libc=no) - ]) - - if test "$gt_cv_func_ngettext_libc" = "yes" ; then - AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, - [AC_TRY_LINK([ -#include -], - [return !dgettext ("","")], - gt_cv_func_dgettext_libc=yes, - gt_cv_func_dgettext_libc=no) - ]) - fi - - if test "$gt_cv_func_ngettext_libc" = "yes" ; then - AC_CHECK_FUNCS(bind_textdomain_codeset) - fi - - # - # If we don't have everything we want, check in libintl - # - if test "$gt_cv_func_dgettext_libc" != "yes" \ - || test "$gt_cv_func_ngettext_libc" != "yes" \ - || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then - - AC_CHECK_LIB(intl, bindtextdomain, - [AC_CHECK_LIB(intl, ngettext, - [AC_CHECK_LIB(intl, dgettext, - gt_cv_func_dgettext_libintl=yes)])]) - - if test "$gt_cv_func_dgettext_libintl" != "yes" ; then - AC_MSG_CHECKING([if -liconv is needed to use gettext]) - AC_MSG_RESULT([]) - AC_CHECK_LIB(intl, ngettext, - [AC_CHECK_LIB(intl, dcgettext, - [gt_cv_func_dgettext_libintl=yes - libintl_extra_libs=-liconv], - :,-liconv)], - :,-liconv) - fi - - # - # If we found libintl, then check in it for bind_textdomain_codeset(); - # we'll prefer libc if neither have bind_textdomain_codeset(), - # and both have dgettext and ngettext - # - if test "$gt_cv_func_dgettext_libintl" = "yes" ; then - glib_save_LIBS="$LIBS" - LIBS="$LIBS -lintl $libintl_extra_libs" - unset ac_cv_func_bind_textdomain_codeset - AC_CHECK_FUNCS(bind_textdomain_codeset) - LIBS="$glib_save_LIBS" - - if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then - gt_cv_func_dgettext_libc=no - else - if test "$gt_cv_func_dgettext_libc" = "yes" \ - && test "$gt_cv_func_ngettext_libc" = "yes"; then - gt_cv_func_dgettext_libintl=no - fi - fi - fi - fi - - if test "$gt_cv_func_dgettext_libc" = "yes" \ - || test "$gt_cv_func_dgettext_libintl" = "yes"; then - gt_cv_have_gettext=yes - fi - - if test "$gt_cv_func_dgettext_libintl" = "yes"; then - INTLLIBS="-lintl $libintl_extra_libs" - fi - - if test "$gt_cv_have_gettext" = "yes"; then - AC_DEFINE(HAVE_GETTEXT,1, - [Define if the GNU gettext() function is already present or preinstalled.]) - GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, - [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl - if test "$MSGFMT" != "no"; then - glib_save_LIBS="$LIBS" - LIBS="$LIBS $INTLLIBS" - AC_CHECK_FUNCS(dcgettext) - MSGFMT_OPTS= - AC_MSG_CHECKING([if msgfmt accepts -c]) - GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Project-Id-Version: test 1.0\n" -"PO-Revision-Date: 2007-02-15 12:01+0100\n" -"Last-Translator: test \n" -"Language-Team: C \n" -"MIME-Version: 1.0\n" -"Content-Transfer-Encoding: 8bit\n" -], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) - AC_SUBST(MSGFMT_OPTS) - AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) - GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, - [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) - AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; - return _nl_msg_cat_cntr], - [CATOBJEXT=.gmo - DATADIRNAME=share], - [case $host in - *-*-solaris*) - dnl On Solaris, if bind_textdomain_codeset is in libc, - dnl GNU format message catalog is always supported, - dnl since both are added to the libc all together. - dnl Hence, we'd like to go with DATADIRNAME=share and - dnl and CATOBJEXT=.gmo in this case. - AC_CHECK_FUNC(bind_textdomain_codeset, - [CATOBJEXT=.gmo - DATADIRNAME=share], - [CATOBJEXT=.mo - DATADIRNAME=lib]) - ;; - *) - CATOBJEXT=.mo - DATADIRNAME=lib - ;; - esac]) - LIBS="$glib_save_LIBS" - INSTOBJEXT=.mo - else - gt_cv_have_gettext=no - fi - fi - ]) - - if test "$gt_cv_have_gettext" = "yes" ; then - AC_DEFINE(ENABLE_NLS, 1, - [always defined to indicate that i18n is enabled]) - fi - - dnl Test whether we really found GNU xgettext. - if test "$XGETTEXT" != ":"; then - dnl If it is not GNU xgettext we define it as : so that the - dnl Makefiles still can work. - if $XGETTEXT --omit-header /dev/null 2> /dev/null; then - : ; - else - AC_MSG_RESULT( - [found xgettext program is not GNU xgettext; ignore it]) - XGETTEXT=":" - fi - fi - - # We need to process the po/ directory. - POSUB=po - - AC_OUTPUT_COMMANDS( - [case "$CONFIG_FILES" in *po/Makefile.in*) - sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile - esac]) - - dnl These rules are solely for the distribution goal. While doing this - dnl we only have to keep exactly one list of the available catalogs - dnl in configure.ac. - for lang in $ALL_LINGUAS; do - GMOFILES="$GMOFILES $lang.gmo" - POFILES="$POFILES $lang.po" - done - - dnl Make all variables we use known to autoconf. - AC_SUBST(CATALOGS) - AC_SUBST(CATOBJEXT) - AC_SUBST(DATADIRNAME) - AC_SUBST(GMOFILES) - AC_SUBST(INSTOBJEXT) - AC_SUBST(INTLLIBS) - AC_SUBST(PO_IN_DATADIR_TRUE) - AC_SUBST(PO_IN_DATADIR_FALSE) - AC_SUBST(POFILES) - AC_SUBST(POSUB) - ]) - -# AM_GLIB_GNU_GETTEXT -# ------------------- -# Do checks necessary for use of gettext. If a suitable implementation -# of gettext is found in either in libintl or in the C library, -# it will set INTLLIBS to the libraries needed for use of gettext -# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable -# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() -# on various variables needed by the Makefile.in.in installed by -# glib-gettextize. -dnl -glib_DEFUN([GLIB_GNU_GETTEXT], - [AC_REQUIRE([AC_PROG_CC])dnl - AC_REQUIRE([AC_HEADER_STDC])dnl - - GLIB_LC_MESSAGES - GLIB_WITH_NLS - - if test "$gt_cv_have_gettext" = "yes"; then - if test "x$ALL_LINGUAS" = "x"; then - LINGUAS= - else - AC_MSG_CHECKING(for catalogs to be installed) - NEW_LINGUAS= - for presentlang in $ALL_LINGUAS; do - useit=no - if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then - desiredlanguages="$LINGUAS" - else - desiredlanguages="$ALL_LINGUAS" - fi - for desiredlang in $desiredlanguages; do - # Use the presentlang catalog if desiredlang is - # a. equal to presentlang, or - # b. a variant of presentlang (because in this case, - # presentlang can be used as a fallback for messages - # which are not translated in the desiredlang catalog). - case "$desiredlang" in - "$presentlang"*) useit=yes;; - esac - done - if test $useit = yes; then - NEW_LINGUAS="$NEW_LINGUAS $presentlang" - fi - done - LINGUAS=$NEW_LINGUAS - AC_MSG_RESULT($LINGUAS) - fi - - dnl Construct list of names of catalog files to be constructed. - if test -n "$LINGUAS"; then - for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done - fi - fi - - dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly - dnl find the mkinstalldirs script in another subdir but ($top_srcdir). - dnl Try to locate is. - MKINSTALLDIRS= - if test -n "$ac_aux_dir"; then - MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" - fi - if test -z "$MKINSTALLDIRS"; then - MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" - fi - AC_SUBST(MKINSTALLDIRS) - - dnl Generate list of files to be processed by xgettext which will - dnl be included in po/Makefile. - test -d po || mkdir po - if test "x$srcdir" != "x."; then - if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then - posrcprefix="$srcdir/" - else - posrcprefix="../$srcdir/" - fi - else - posrcprefix="../" - fi - rm -f po/POTFILES - sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ - < $srcdir/po/POTFILES.in > po/POTFILES - ]) - -# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) -# ------------------------------- -# Define VARIABLE to the location where catalog files will -# be installed by po/Makefile. -glib_DEFUN([GLIB_DEFINE_LOCALEDIR], -[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl -glib_save_prefix="$prefix" -glib_save_exec_prefix="$exec_prefix" -glib_save_datarootdir="$datarootdir" -test "x$prefix" = xNONE && prefix=$ac_default_prefix -test "x$exec_prefix" = xNONE && exec_prefix=$prefix -datarootdir=`eval echo "${datarootdir}"` -if test "x$CATOBJEXT" = "x.mo" ; then - localedir=`eval echo "${libdir}/locale"` -else - localedir=`eval echo "${datadir}/locale"` -fi -prefix="$glib_save_prefix" -exec_prefix="$glib_save_exec_prefix" -datarootdir="$glib_save_datarootdir" -AC_DEFINE_UNQUOTED($1, "$localedir", - [Define the location where the catalogs will be installed]) -]) - -dnl -dnl Now the definitions that aclocal will find -dnl -ifdef(glib_configure_ac,[],[ -AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) -AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) -])dnl - -# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) -# -# Create a temporary file with TEST-FILE as its contents and pass the -# file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with -# 0 and perform ACTION-IF-FAIL for any other exit status. -AC_DEFUN([GLIB_RUN_PROG], -[cat >conftest.foo <<_ACEOF -$2 -_ACEOF -if AC_RUN_LOG([$1 conftest.foo]); then - m4_ifval([$3], [$3], [:]) -m4_ifvaln([$4], [else $4])dnl -echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD -sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD -fi]) - dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) diff --git a/config.h.in b/config.h.in index fb803ec..9d0ff94 100644 --- a/config.h.in +++ b/config.h.in @@ -1,16 +1,7 @@ /* config.h.in. Generated from configure.ac by autoheader. */ - -/* always defined to indicate that i18n is enabled */ -#undef ENABLE_NLS /* GETTEXT package name */ #undef GETTEXT_PACKAGE - -/* Define to 1 if you have the `bind_textdomain_codeset' function. */ -#undef HAVE_BIND_TEXTDOMAIN_CODESET - -/* Define to 1 if you have the `dcgettext' function. */ -#undef HAVE_DCGETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H @@ -18,17 +9,8 @@ /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK -/* Define if the GNU gettext() function is already present or preinstalled. */ -#undef HAVE_GETTEXT - /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H - -/* Define if your file defines LC_MESSAGES. */ -#undef HAVE_LC_MESSAGES - -/* Define to 1 if you have the header file. */ -#undef HAVE_LOCALE_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H diff --git a/configure b/configure index 9799613..43f9b73 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for virt-viewer 0.4.0. +# Generated by GNU Autoconf 2.68 for virt-viewer 0.4.1. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -567,8 +567,8 @@ # Identity of this package. PACKAGE_NAME='virt-viewer' PACKAGE_TARNAME='virt-viewer' -PACKAGE_VERSION='0.4.0' -PACKAGE_STRING='virt-viewer 0.4.0' +PACKAGE_VERSION='0.4.1' +PACKAGE_STRING='virt-viewer 0.4.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -646,17 +646,6 @@ PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG -MKINSTALLDIRS -POSUB -POFILES -PO_IN_DATADIR_FALSE -PO_IN_DATADIR_TRUE -INTLLIBS -INSTOBJEXT -GMOFILES -CATOBJEXT -CATALOGS -MSGFMT_OPTS DATADIRNAME ALL_LINGUAS INTLTOOL_PERL @@ -1389,7 +1378,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures virt-viewer 0.4.0 to adapt to many kinds of systems. +\`configure' configures virt-viewer 0.4.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1459,7 +1448,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of virt-viewer 0.4.0:";; + short | recursive ) echo "Configuration of virt-viewer 0.4.1:";; esac cat <<\_ACEOF @@ -1605,7 +1594,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -virt-viewer configure 0.4.0 +virt-viewer configure 0.4.1 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1970,7 +1959,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by virt-viewer $as_me 0.4.0, which was +It was created by virt-viewer $as_me 0.4.1, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2788,7 +2777,7 @@ # Define the identity of the package. PACKAGE='virt-viewer' - VERSION='0.4.0' + VERSION='0.4.1' cat >>confdefs.h <<_ACEOF @@ -12165,710 +12154,6 @@ - for ac_header in locale.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" -if test "x$ac_cv_header_locale_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LOCALE_H 1 -_ACEOF - -fi - -done - - if test $ac_cv_header_locale_h = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 -$as_echo_n "checking for LC_MESSAGES... " >&6; } -if ${am_cv_val_LC_MESSAGES+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -return LC_MESSAGES - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - am_cv_val_LC_MESSAGES=yes -else - am_cv_val_LC_MESSAGES=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5 -$as_echo "$am_cv_val_LC_MESSAGES" >&6; } - if test $am_cv_val_LC_MESSAGES = yes; then - -$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h - - fi - fi - USE_NLS=yes - - - gt_cv_have_gettext=no - - CATOBJEXT=NONE - XGETTEXT=: - INTLLIBS= - - ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" -if test "x$ac_cv_header_libintl_h" = xyes; then : - gt_cv_func_dgettext_libintl="no" - libintl_extra_libs="" - - # - # First check in libc - # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in libc" >&5 -$as_echo_n "checking for ngettext in libc... " >&6; } -if ${gt_cv_func_ngettext_libc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include - -int -main () -{ -return !ngettext ("","", 1) - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - gt_cv_func_ngettext_libc=yes -else - gt_cv_func_ngettext_libc=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_ngettext_libc" >&5 -$as_echo "$gt_cv_func_ngettext_libc" >&6; } - - if test "$gt_cv_func_ngettext_libc" = "yes" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in libc" >&5 -$as_echo_n "checking for dgettext in libc... " >&6; } -if ${gt_cv_func_dgettext_libc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include - -int -main () -{ -return !dgettext ("","") - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - gt_cv_func_dgettext_libc=yes -else - gt_cv_func_dgettext_libc=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_dgettext_libc" >&5 -$as_echo "$gt_cv_func_dgettext_libc" >&6; } - fi - - if test "$gt_cv_func_ngettext_libc" = "yes" ; then - for ac_func in bind_textdomain_codeset -do : - ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" -if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_BIND_TEXTDOMAIN_CODESET 1 -_ACEOF - -fi -done - - fi - - # - # If we don't have everything we want, check in libintl - # - if test "$gt_cv_func_dgettext_libc" != "yes" \ - || test "$gt_cv_func_ngettext_libc" != "yes" \ - || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bindtextdomain in -lintl" >&5 -$as_echo_n "checking for bindtextdomain in -lintl... " >&6; } -if ${ac_cv_lib_intl_bindtextdomain+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lintl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char bindtextdomain (); -int -main () -{ -return bindtextdomain (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_intl_bindtextdomain=yes -else - ac_cv_lib_intl_bindtextdomain=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_bindtextdomain" >&5 -$as_echo "$ac_cv_lib_intl_bindtextdomain" >&6; } -if test "x$ac_cv_lib_intl_bindtextdomain" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 -$as_echo_n "checking for ngettext in -lintl... " >&6; } -if ${ac_cv_lib_intl_ngettext+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lintl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char ngettext (); -int -main () -{ -return ngettext (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_intl_ngettext=yes -else - ac_cv_lib_intl_ngettext=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 -$as_echo "$ac_cv_lib_intl_ngettext" >&6; } -if test "x$ac_cv_lib_intl_ngettext" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in -lintl" >&5 -$as_echo_n "checking for dgettext in -lintl... " >&6; } -if ${ac_cv_lib_intl_dgettext+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lintl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dgettext (); -int -main () -{ -return dgettext (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_intl_dgettext=yes -else - ac_cv_lib_intl_dgettext=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dgettext" >&5 -$as_echo "$ac_cv_lib_intl_dgettext" >&6; } -if test "x$ac_cv_lib_intl_dgettext" = xyes; then : - gt_cv_func_dgettext_libintl=yes -fi - -fi - -fi - - - if test "$gt_cv_func_dgettext_libintl" != "yes" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -liconv is needed to use gettext" >&5 -$as_echo_n "checking if -liconv is needed to use gettext... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 -$as_echo "" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 -$as_echo_n "checking for ngettext in -lintl... " >&6; } -if ${ac_cv_lib_intl_ngettext+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lintl -liconv $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char ngettext (); -int -main () -{ -return ngettext (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_intl_ngettext=yes -else - ac_cv_lib_intl_ngettext=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 -$as_echo "$ac_cv_lib_intl_ngettext" >&6; } -if test "x$ac_cv_lib_intl_ngettext" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dcgettext in -lintl" >&5 -$as_echo_n "checking for dcgettext in -lintl... " >&6; } -if ${ac_cv_lib_intl_dcgettext+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lintl -liconv $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dcgettext (); -int -main () -{ -return dcgettext (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_intl_dcgettext=yes -else - ac_cv_lib_intl_dcgettext=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dcgettext" >&5 -$as_echo "$ac_cv_lib_intl_dcgettext" >&6; } -if test "x$ac_cv_lib_intl_dcgettext" = xyes; then : - gt_cv_func_dgettext_libintl=yes - libintl_extra_libs=-liconv -else - : -fi - -else - : -fi - - fi - - # - # If we found libintl, then check in it for bind_textdomain_codeset(); - # we'll prefer libc if neither have bind_textdomain_codeset(), - # and both have dgettext and ngettext - # - if test "$gt_cv_func_dgettext_libintl" = "yes" ; then - glib_save_LIBS="$LIBS" - LIBS="$LIBS -lintl $libintl_extra_libs" - unset ac_cv_func_bind_textdomain_codeset - for ac_func in bind_textdomain_codeset -do : - ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" -if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_BIND_TEXTDOMAIN_CODESET 1 -_ACEOF - -fi -done - - LIBS="$glib_save_LIBS" - - if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then - gt_cv_func_dgettext_libc=no - else - if test "$gt_cv_func_dgettext_libc" = "yes" \ - && test "$gt_cv_func_ngettext_libc" = "yes"; then - gt_cv_func_dgettext_libintl=no - fi - fi - fi - fi - - if test "$gt_cv_func_dgettext_libc" = "yes" \ - || test "$gt_cv_func_dgettext_libintl" = "yes"; then - gt_cv_have_gettext=yes - fi - - if test "$gt_cv_func_dgettext_libintl" = "yes"; then - INTLLIBS="-lintl $libintl_extra_libs" - fi - - if test "$gt_cv_have_gettext" = "yes"; then - -$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h - - # Extract the first word of "msgfmt", so it can be a program name with args. -set dummy msgfmt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_MSGFMT+:} false; then : - $as_echo_n "(cached) " >&6 -else - case "$MSGFMT" in - /*) - ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then - ac_cv_path_MSGFMT="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" - ;; -esac -fi -MSGFMT="$ac_cv_path_MSGFMT" -if test "$MSGFMT" != "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 -$as_echo "$MSGFMT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - if test "$MSGFMT" != "no"; then - glib_save_LIBS="$LIBS" - LIBS="$LIBS $INTLLIBS" - for ac_func in dcgettext -do : - ac_fn_c_check_func "$LINENO" "dcgettext" "ac_cv_func_dcgettext" -if test "x$ac_cv_func_dcgettext" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DCGETTEXT 1 -_ACEOF - -fi -done - - MSGFMT_OPTS= - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if msgfmt accepts -c" >&5 -$as_echo_n "checking if msgfmt accepts -c... " >&6; } - cat >conftest.foo <<_ACEOF - -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Project-Id-Version: test 1.0\n" -"PO-Revision-Date: 2007-02-15 12:01+0100\n" -"Last-Translator: test \n" -"Language-Team: C \n" -"MIME-Version: 1.0\n" -"Content-Transfer-Encoding: 8bit\n" - -_ACEOF -if { { $as_echo "$as_me:${as_lineno-$LINENO}: \$MSGFMT -c -o /dev/null conftest.foo"; } >&5 - ($MSGFMT -c -o /dev/null conftest.foo) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - MSGFMT_OPTS=-c; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -echo "$as_me: failed input was:" >&5 -sed 's/^/| /' conftest.foo >&5 -fi - - # Extract the first word of "gmsgfmt", so it can be a program name with args. -set dummy gmsgfmt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_GMSGFMT+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $GMSGFMT in - [\\/]* | ?:[\\/]*) - ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" - ;; -esac -fi -GMSGFMT=$ac_cv_path_GMSGFMT -if test -n "$GMSGFMT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 -$as_echo "$GMSGFMT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - # Extract the first word of "xgettext", so it can be a program name with args. -set dummy xgettext; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_XGETTEXT+:} false; then : - $as_echo_n "(cached) " >&6 -else - case "$XGETTEXT" in - /*) - ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. - ;; - *) - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then - ac_cv_path_XGETTEXT="$ac_dir/$ac_word" - break - fi - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" - ;; -esac -fi -XGETTEXT="$ac_cv_path_XGETTEXT" -if test "$XGETTEXT" != ":"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 -$as_echo "$XGETTEXT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -extern int _nl_msg_cat_cntr; - return _nl_msg_cat_cntr - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - CATOBJEXT=.gmo - DATADIRNAME=share -else - case $host in - *-*-solaris*) - ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" -if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : - CATOBJEXT=.gmo - DATADIRNAME=share -else - CATOBJEXT=.mo - DATADIRNAME=lib -fi - - ;; - *) - CATOBJEXT=.mo - DATADIRNAME=lib - ;; - esac -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LIBS="$glib_save_LIBS" - INSTOBJEXT=.mo - else - gt_cv_have_gettext=no - fi - fi - -fi - - - - if test "$gt_cv_have_gettext" = "yes" ; then - -$as_echo "#define ENABLE_NLS 1" >>confdefs.h - - fi - - if test "$XGETTEXT" != ":"; then - if $XGETTEXT --omit-header /dev/null 2> /dev/null; then - : ; - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 -$as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } - XGETTEXT=":" - fi - fi - - # We need to process the po/ directory. - POSUB=po - - ac_config_commands="$ac_config_commands default-1" - - - for lang in $ALL_LINGUAS; do - GMOFILES="$GMOFILES $lang.gmo" - POFILES="$POFILES $lang.po" - done - - - - - - - - - - - - - - if test "$gt_cv_have_gettext" = "yes"; then - if test "x$ALL_LINGUAS" = "x"; then - LINGUAS= - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5 -$as_echo_n "checking for catalogs to be installed... " >&6; } - NEW_LINGUAS= - for presentlang in $ALL_LINGUAS; do - useit=no - if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then - desiredlanguages="$LINGUAS" - else - desiredlanguages="$ALL_LINGUAS" - fi - for desiredlang in $desiredlanguages; do - # Use the presentlang catalog if desiredlang is - # a. equal to presentlang, or - # b. a variant of presentlang (because in this case, - # presentlang can be used as a fallback for messages - # which are not translated in the desiredlang catalog). - case "$desiredlang" in - "$presentlang"*) useit=yes;; - esac - done - if test $useit = yes; then - NEW_LINGUAS="$NEW_LINGUAS $presentlang" - fi - done - LINGUAS=$NEW_LINGUAS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 -$as_echo "$LINGUAS" >&6; } - fi - - if test -n "$LINGUAS"; then - for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done - fi - fi - - MKINSTALLDIRS= - if test -n "$ac_aux_dir"; then - MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" - fi - if test -z "$MKINSTALLDIRS"; then - MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" - fi - - - test -d po || mkdir po - if test "x$srcdir" != "x."; then - if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then - posrcprefix="$srcdir/" - else - posrcprefix="../$srcdir/" - fi - else - posrcprefix="../" - fi - rm -f po/POTFILES - sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ - < $srcdir/po/POTFILES.in > po/POTFILES - - @@ -14550,7 +13835,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by virt-viewer $as_me 0.4.0, which was +This file was extended by virt-viewer $as_me 0.4.1, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14616,7 +13901,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -virt-viewer config.status 0.4.0 +virt-viewer config.status 0.4.1 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -15014,7 +14299,6 @@ - _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 @@ -15026,7 +14310,6 @@ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; - "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; @@ -16356,9 +15639,6 @@ chmod +x "$ofile" ;; - "default-1":C) case "$CONFIG_FILES" in *po/Makefile.in*) - sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile - esac ;; "po/stamp-it":C) if ! grep "^# INTLTOOL_MAKEFILE$" "po/Makefile.in" > /dev/null ; then as_fn_error $? "po/Makefile.in.in was not created by intltoolize." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index df7a93e..9c791e7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -AC_INIT(virt-viewer, 0.4.0) +AC_INIT(virt-viewer, 0.4.1) AC_CONFIG_SRCDIR(src/virt-viewer-main.c) AM_CONFIG_HEADER(config.h) dnl Make automake keep quiet about wildcards & other GNUmake-isms @@ -33,7 +33,6 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [GETTEXT package name]) IT_PROG_INTLTOOL([0.35.0]) -AM_GLIB_GNU_GETTEXT PKG_CHECK_MODULES(GLIB2, gmodule-export-2.0 >= $GLIB2_REQUIRED) diff --git a/man/Makefile.in b/man/Makefile.in index 9ecc5fc..5338cfb 100644 --- a/man/Makefile.in +++ b/man/Makefile.in @@ -89,8 +89,6 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -114,7 +112,6 @@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB2_CFLAGS = @GLIB2_CFLAGS@ GLIB2_LIBS = @GLIB2_LIBS@ -GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTK_API_VERSION = @GTK_API_VERSION@ @@ -129,8 +126,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ @@ -150,11 +145,9 @@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ MOZILLA_PLUGIN_CFLAGS = @MOZILLA_PLUGIN_CFLAGS@ MOZILLA_PLUGIN_LIBS = @MOZILLA_PLUGIN_LIBS@ MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -175,10 +168,6 @@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ diff --git a/plugin/Makefile.in b/plugin/Makefile.in index 9cb6c1d..3358f75 100644 --- a/plugin/Makefile.in +++ b/plugin/Makefile.in @@ -135,8 +135,6 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -160,7 +158,6 @@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB2_CFLAGS = @GLIB2_CFLAGS@ GLIB2_LIBS = @GLIB2_LIBS@ -GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTK_API_VERSION = @GTK_API_VERSION@ @@ -175,8 +172,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ @@ -196,11 +191,9 @@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ MOZILLA_PLUGIN_CFLAGS = @MOZILLA_PLUGIN_CFLAGS@ MOZILLA_PLUGIN_LIBS = @MOZILLA_PLUGIN_LIBS@ MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -221,10 +214,6 @@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ diff --git a/src/Makefile.am b/src/Makefile.am index 1145f4a..7e7a9c3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,14 +11,17 @@ virt_viewer_SOURCES = \ virt-viewer-main.c \ + virt-viewer.h virt-viewer.c \ virt-viewer-util.h virt-viewer-util.c \ virt-viewer-auth.h virt-viewer-auth.c \ virt-viewer-events.h virt-viewer-events.c \ - virt-viewer.h virt-viewer.c \ + virt-viewer-app.h virt-viewer-app.c \ virt-viewer-session.h virt-viewer-session.c \ virt-viewer-session-vnc.h virt-viewer-session-vnc.c \ virt-viewer-display.h virt-viewer-display.c \ virt-viewer-display-vnc.h virt-viewer-display-vnc.c \ + virt-viewer-notebook.h virt-viewer-notebook.c \ + virt-viewer-window.h virt-viewer-window.c \ view/autoDrawer.c \ view/autoDrawer.h \ view/drawer.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 11fda77..a66c511 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -55,28 +55,34 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(builderxmldir)" PROGRAMS = $(bin_PROGRAMS) -am__virt_viewer_SOURCES_DIST = virt-viewer-main.c virt-viewer-util.h \ - virt-viewer-util.c virt-viewer-auth.h virt-viewer-auth.c \ - virt-viewer-events.h virt-viewer-events.c virt-viewer.h \ - virt-viewer.c virt-viewer-session.h virt-viewer-session.c \ +am__virt_viewer_SOURCES_DIST = virt-viewer-main.c virt-viewer.h \ + virt-viewer.c virt-viewer-util.h virt-viewer-util.c \ + virt-viewer-auth.h virt-viewer-auth.c virt-viewer-events.h \ + virt-viewer-events.c virt-viewer-app.h virt-viewer-app.c \ + virt-viewer-session.h virt-viewer-session.c \ virt-viewer-session-vnc.h virt-viewer-session-vnc.c \ virt-viewer-display.h virt-viewer-display.c \ virt-viewer-display-vnc.h virt-viewer-display-vnc.c \ - view/autoDrawer.c view/autoDrawer.h view/drawer.c \ - view/drawer.h view/ovBox.c view/ovBox.h \ - virt-viewer-session-spice.h virt-viewer-session-spice.c \ - virt-viewer-display-spice.h virt-viewer-display-spice.c + virt-viewer-notebook.h virt-viewer-notebook.c \ + virt-viewer-window.h virt-viewer-window.c view/autoDrawer.c \ + view/autoDrawer.h view/drawer.c view/drawer.h view/ovBox.c \ + view/ovBox.h virt-viewer-session-spice.h \ + virt-viewer-session-spice.c virt-viewer-display-spice.h \ + virt-viewer-display-spice.c @HAVE_SPICE_GTK_TRUE@am__objects_1 = virt_viewer-virt-viewer-session-spice.$(OBJEXT) \ @HAVE_SPICE_GTK_TRUE@ virt_viewer-virt-viewer-display-spice.$(OBJEXT) am_virt_viewer_OBJECTS = virt_viewer-virt-viewer-main.$(OBJEXT) \ + virt_viewer-virt-viewer.$(OBJEXT) \ virt_viewer-virt-viewer-util.$(OBJEXT) \ virt_viewer-virt-viewer-auth.$(OBJEXT) \ virt_viewer-virt-viewer-events.$(OBJEXT) \ - virt_viewer-virt-viewer.$(OBJEXT) \ + virt_viewer-virt-viewer-app.$(OBJEXT) \ virt_viewer-virt-viewer-session.$(OBJEXT) \ virt_viewer-virt-viewer-session-vnc.$(OBJEXT) \ virt_viewer-virt-viewer-display.$(OBJEXT) \ virt_viewer-virt-viewer-display-vnc.$(OBJEXT) \ + virt_viewer-virt-viewer-notebook.$(OBJEXT) \ + virt_viewer-virt-viewer-window.$(OBJEXT) \ virt_viewer-autoDrawer.$(OBJEXT) virt_viewer-drawer.$(OBJEXT) \ virt_viewer-ovBox.$(OBJEXT) $(am__objects_1) virt_viewer_OBJECTS = $(am_virt_viewer_OBJECTS) @@ -149,8 +155,6 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -174,7 +178,6 @@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB2_CFLAGS = @GLIB2_CFLAGS@ GLIB2_LIBS = @GLIB2_LIBS@ -GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTK_API_VERSION = @GTK_API_VERSION@ @@ -189,8 +192,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ @@ -210,11 +211,9 @@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ MOZILLA_PLUGIN_CFLAGS = @MOZILLA_PLUGIN_CFLAGS@ MOZILLA_PLUGIN_LIBS = @MOZILLA_PLUGIN_LIBS@ MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -235,10 +234,6 @@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -309,15 +304,18 @@ virt-viewer-auth.xml EXTRA_DIST = $(builderxml_DATA) -virt_viewer_SOURCES = virt-viewer-main.c virt-viewer-util.h \ - virt-viewer-util.c virt-viewer-auth.h virt-viewer-auth.c \ - virt-viewer-events.h virt-viewer-events.c virt-viewer.h \ - virt-viewer.c virt-viewer-session.h virt-viewer-session.c \ - virt-viewer-session-vnc.h virt-viewer-session-vnc.c \ - virt-viewer-display.h virt-viewer-display.c \ - virt-viewer-display-vnc.h virt-viewer-display-vnc.c \ - view/autoDrawer.c view/autoDrawer.h view/drawer.c \ - view/drawer.h view/ovBox.c view/ovBox.h $(am__append_1) +virt_viewer_SOURCES = virt-viewer-main.c virt-viewer.h virt-viewer.c \ + virt-viewer-util.h virt-viewer-util.c virt-viewer-auth.h \ + virt-viewer-auth.c virt-viewer-events.h virt-viewer-events.c \ + virt-viewer-app.h virt-viewer-app.c virt-viewer-session.h \ + virt-viewer-session.c virt-viewer-session-vnc.h \ + virt-viewer-session-vnc.c virt-viewer-display.h \ + virt-viewer-display.c virt-viewer-display-vnc.h \ + virt-viewer-display-vnc.c virt-viewer-notebook.h \ + virt-viewer-notebook.c virt-viewer-window.h \ + virt-viewer-window.c view/autoDrawer.c view/autoDrawer.h \ + view/drawer.c view/drawer.h view/ovBox.c view/ovBox.h \ + $(am__append_1) virt_viewer_LDADD = \ @GTK_VNC_LIBS@ \ @SPICE_GTK_LIBS@ \ @@ -427,16 +425,19 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-autoDrawer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-drawer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-ovBox.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-app.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-auth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-display-spice.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-display-vnc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-display.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-events.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-notebook.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-session-spice.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-session-vnc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer-window.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_viewer-virt-viewer.Po@am__quote@ .c.o: @@ -479,6 +480,22 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-main.obj `if test -f 'virt-viewer-main.c'; then $(CYGPATH_W) 'virt-viewer-main.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-main.c'; fi` +virt_viewer-virt-viewer.o: virt-viewer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer.Tpo -c -o virt_viewer-virt-viewer.o `test -f 'virt-viewer.c' || echo '$(srcdir)/'`virt-viewer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer.Tpo $(DEPDIR)/virt_viewer-virt-viewer.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer.c' object='virt_viewer-virt-viewer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer.o `test -f 'virt-viewer.c' || echo '$(srcdir)/'`virt-viewer.c + +virt_viewer-virt-viewer.obj: virt-viewer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer.obj -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer.Tpo -c -o virt_viewer-virt-viewer.obj `if test -f 'virt-viewer.c'; then $(CYGPATH_W) 'virt-viewer.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer.Tpo $(DEPDIR)/virt_viewer-virt-viewer.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer.c' object='virt_viewer-virt-viewer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer.obj `if test -f 'virt-viewer.c'; then $(CYGPATH_W) 'virt-viewer.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer.c'; fi` + virt_viewer-virt-viewer-util.o: virt-viewer-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-util.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-util.Tpo -c -o virt_viewer-virt-viewer-util.o `test -f 'virt-viewer-util.c' || echo '$(srcdir)/'`virt-viewer-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-util.Tpo $(DEPDIR)/virt_viewer-virt-viewer-util.Po @@ -527,21 +544,21 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-events.obj `if test -f 'virt-viewer-events.c'; then $(CYGPATH_W) 'virt-viewer-events.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-events.c'; fi` -virt_viewer-virt-viewer.o: virt-viewer.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer.Tpo -c -o virt_viewer-virt-viewer.o `test -f 'virt-viewer.c' || echo '$(srcdir)/'`virt-viewer.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer.Tpo $(DEPDIR)/virt_viewer-virt-viewer.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer.c' object='virt_viewer-virt-viewer.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer.o `test -f 'virt-viewer.c' || echo '$(srcdir)/'`virt-viewer.c - -virt_viewer-virt-viewer.obj: virt-viewer.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer.obj -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer.Tpo -c -o virt_viewer-virt-viewer.obj `if test -f 'virt-viewer.c'; then $(CYGPATH_W) 'virt-viewer.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer.Tpo $(DEPDIR)/virt_viewer-virt-viewer.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer.c' object='virt_viewer-virt-viewer.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer.obj `if test -f 'virt-viewer.c'; then $(CYGPATH_W) 'virt-viewer.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer.c'; fi` +virt_viewer-virt-viewer-app.o: virt-viewer-app.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-app.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-app.Tpo -c -o virt_viewer-virt-viewer-app.o `test -f 'virt-viewer-app.c' || echo '$(srcdir)/'`virt-viewer-app.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-app.Tpo $(DEPDIR)/virt_viewer-virt-viewer-app.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-app.c' object='virt_viewer-virt-viewer-app.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-app.o `test -f 'virt-viewer-app.c' || echo '$(srcdir)/'`virt-viewer-app.c + +virt_viewer-virt-viewer-app.obj: virt-viewer-app.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-app.obj -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-app.Tpo -c -o virt_viewer-virt-viewer-app.obj `if test -f 'virt-viewer-app.c'; then $(CYGPATH_W) 'virt-viewer-app.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-app.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-app.Tpo $(DEPDIR)/virt_viewer-virt-viewer-app.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-app.c' object='virt_viewer-virt-viewer-app.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-app.obj `if test -f 'virt-viewer-app.c'; then $(CYGPATH_W) 'virt-viewer-app.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-app.c'; fi` virt_viewer-virt-viewer-session.o: virt-viewer-session.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-session.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-session.Tpo -c -o virt_viewer-virt-viewer-session.o `test -f 'virt-viewer-session.c' || echo '$(srcdir)/'`virt-viewer-session.c @@ -606,6 +623,38 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-display-vnc.c' object='virt_viewer-virt-viewer-display-vnc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-display-vnc.obj `if test -f 'virt-viewer-display-vnc.c'; then $(CYGPATH_W) 'virt-viewer-display-vnc.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-display-vnc.c'; fi` + +virt_viewer-virt-viewer-notebook.o: virt-viewer-notebook.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-notebook.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-notebook.Tpo -c -o virt_viewer-virt-viewer-notebook.o `test -f 'virt-viewer-notebook.c' || echo '$(srcdir)/'`virt-viewer-notebook.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-notebook.Tpo $(DEPDIR)/virt_viewer-virt-viewer-notebook.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-notebook.c' object='virt_viewer-virt-viewer-notebook.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-notebook.o `test -f 'virt-viewer-notebook.c' || echo '$(srcdir)/'`virt-viewer-notebook.c + +virt_viewer-virt-viewer-notebook.obj: virt-viewer-notebook.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-notebook.obj -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-notebook.Tpo -c -o virt_viewer-virt-viewer-notebook.obj `if test -f 'virt-viewer-notebook.c'; then $(CYGPATH_W) 'virt-viewer-notebook.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-notebook.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-notebook.Tpo $(DEPDIR)/virt_viewer-virt-viewer-notebook.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-notebook.c' object='virt_viewer-virt-viewer-notebook.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-notebook.obj `if test -f 'virt-viewer-notebook.c'; then $(CYGPATH_W) 'virt-viewer-notebook.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-notebook.c'; fi` + +virt_viewer-virt-viewer-window.o: virt-viewer-window.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-window.o -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-window.Tpo -c -o virt_viewer-virt-viewer-window.o `test -f 'virt-viewer-window.c' || echo '$(srcdir)/'`virt-viewer-window.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-window.Tpo $(DEPDIR)/virt_viewer-virt-viewer-window.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-window.c' object='virt_viewer-virt-viewer-window.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-window.o `test -f 'virt-viewer-window.c' || echo '$(srcdir)/'`virt-viewer-window.c + +virt_viewer-virt-viewer-window.obj: virt-viewer-window.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-virt-viewer-window.obj -MD -MP -MF $(DEPDIR)/virt_viewer-virt-viewer-window.Tpo -c -o virt_viewer-virt-viewer-window.obj `if test -f 'virt-viewer-window.c'; then $(CYGPATH_W) 'virt-viewer-window.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-window.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/virt_viewer-virt-viewer-window.Tpo $(DEPDIR)/virt_viewer-virt-viewer-window.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='virt-viewer-window.c' object='virt_viewer-virt-viewer-window.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -c -o virt_viewer-virt-viewer-window.obj `if test -f 'virt-viewer-window.c'; then $(CYGPATH_W) 'virt-viewer-window.c'; else $(CYGPATH_W) '$(srcdir)/virt-viewer-window.c'; fi` virt_viewer-autoDrawer.o: view/autoDrawer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_viewer_CFLAGS) $(CFLAGS) -MT virt_viewer-autoDrawer.o -MD -MP -MF $(DEPDIR)/virt_viewer-autoDrawer.Tpo -c -o virt_viewer-autoDrawer.o `test -f 'view/autoDrawer.c' || echo '$(srcdir)/'`view/autoDrawer.c diff --git a/src/virt-viewer-about.xml b/src/virt-viewer-about.xml index 603d9c7..01ac17c 100644 --- a/src/virt-viewer-about.xml +++ b/src/virt-viewer-about.xml @@ -9,9 +9,9 @@ center-on-parent dialog Virtual Machine Viewer - Copyright 2007-2008 Daniel P. Berrange -Copyright 2007-2008 Red Hat, Inc. - A remote desktop client built with GTK-VNC and libvirt + Copyright 2007-2011 Daniel P. Berrange +Copyright 2007-2011 Red Hat, Inc. + A remote desktop client built with GTK-VNC, SPICE-GTK and libvirt http://virt-manager.org/ virt-manager.org This program is free software; you can redistribute it and/or modify @@ -28,10 +28,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Daniel P. Berrange + Daniel P. Berrange +Marc-André Lureau + The Fedora Translation Team - - + + True diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c new file mode 100644 index 0000000..918e788 --- /dev/null +++ b/src/virt-viewer-app.c @@ -0,0 +1,1369 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2009 Red Hat, + * Copyright (C) 2009 Daniel P. Berrange + * Copyright (C) 2010 Marc-André Lureau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + +#include "virt-viewer-app.h" +#include "virt-viewer-auth.h" +#include "virt-viewer-window.h" +#include "virt-viewer-session.h" +#include "virt-viewer-session-vnc.h" +#ifdef HAVE_SPICE_GTK +#include "virt-viewer-session-spice.h" +#endif + +gboolean doDebug = FALSE; + +/* Signal handlers for about dialog */ +void virt_viewer_app_about_close(GtkWidget *dialog, VirtViewerApp *self); +void virt_viewer_app_about_delete(GtkWidget *dialog, void *dummy, VirtViewerApp *self); + + +/* Internal methods */ +static void virt_viewer_app_connected(VirtViewerSession *session, + VirtViewerApp *self); +static void virt_viewer_app_initialized(VirtViewerSession *session, + VirtViewerApp *self); +static void virt_viewer_app_disconnected(VirtViewerSession *session, + VirtViewerApp *self); +static void virt_viewer_app_auth_refused(VirtViewerSession *session, + const char *msg, + VirtViewerApp *self); +static void virt_viewer_app_auth_failed(VirtViewerSession *session, + const char *msg, + VirtViewerApp *self); + +static void virt_viewer_app_server_cut_text(VirtViewerSession *session, + const gchar *text, + VirtViewerApp *self); +static void virt_viewer_app_bell(VirtViewerSession *session, + VirtViewerApp *self); + +static void virt_viewer_app_channel_open(VirtViewerSession *session, + VirtViewerSessionChannel *channel, + VirtViewerApp *self); +static void virt_viewer_app_update_pretty_address(VirtViewerApp *self); +static void virt_viewer_app_set_fullscreen(VirtViewerApp *self, gboolean fullscreen); +static void virt_viewer_app_update_menu_displays(VirtViewerApp *self); + + +struct _VirtViewerAppPrivate { + VirtViewerWindow *main_window; + GtkWidget *main_notebook; + GtkWidget *container; + GHashTable *windows; + gchar *clipboard; + + gboolean direct; + gboolean verbose; + gboolean authretry; + gboolean started; + gboolean fullscreen; + + VirtViewerSession *session; + gboolean active; + gboolean connected; + guint reconnect_poll; /* source id */ + char *unixsock; + char *ghost; + char *gport; + char *host; /* ssh */ + int port;/* ssh */ + char *user; /* ssh */ + char *transport; + char *pretty_address; + gchar *guest_name; + gboolean grabbed; +}; + + +G_DEFINE_ABSTRACT_TYPE(VirtViewerApp, virt_viewer_app, G_TYPE_OBJECT) +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIRT_VIEWER_TYPE_APP, VirtViewerAppPrivate)) + +enum { + PROP_0, + PROP_VERBOSE, + PROP_CONTAINER, + PROP_SESSION, + PROP_GUEST_NAME, + PROP_FULLSCREEN, +}; + +void +virt_viewer_app_set_debug(gboolean debug) +{ + doDebug = debug; +} + +void +virt_viewer_app_simple_message_dialog(VirtViewerApp *self, + const char *fmt, ...) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + GtkWindow *window = GTK_WINDOW(virt_viewer_window_get_window(self->priv->main_window)); + GtkWidget *dialog; + char *msg; + va_list vargs; + + va_start(vargs, fmt); + + msg = g_strdup_vprintf(fmt, vargs); + + va_end(vargs); + + dialog = gtk_message_dialog_new(window, + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", + msg); + + gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); + + g_free(msg); +} + +void +virt_viewer_app_quit(VirtViewerApp *self) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + VirtViewerAppPrivate *priv = self->priv; + + if (priv->session) + virt_viewer_session_close(VIRT_VIEWER_SESSION(priv->session)); + gtk_main_quit(); +} + +static void count_window_visible(gpointer key G_GNUC_UNUSED, + gpointer value, + gpointer user_data) +{ + GtkWindow *win = virt_viewer_window_get_window(VIRT_VIEWER_WINDOW(value)); + guint *n = (guint*)user_data; + + if (gtk_widget_get_visible(GTK_WIDGET(win))) + *n += 1; +} + +static guint +virt_viewer_app_get_n_windows_visible(VirtViewerApp *self) +{ + guint n = 0; + g_hash_table_foreach(self->priv->windows, count_window_visible, &n); + return n; +} + +static guint +virt_viewer_app_get_n_windows(VirtViewerApp *self) +{ + return g_hash_table_size(self->priv->windows); +} + +gboolean +virt_viewer_app_window_set_visible(VirtViewerApp *self, + VirtViewerWindow *vwin, + gboolean visible) +{ + GtkWidget *window; + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), FALSE); + g_return_val_if_fail(VIRT_VIEWER_IS_WINDOW(vwin), FALSE); + + window = GTK_WIDGET(virt_viewer_window_get_window(vwin)); + if (visible) { + gtk_widget_show(window); + return TRUE; + } else { + if (virt_viewer_app_get_n_windows_visible(self) > 1) { + gtk_widget_hide(window); + return FALSE; + } else if (virt_viewer_app_get_n_windows(self) > 1) { + GtkWidget *dialog = + gtk_message_dialog_new (GTK_WINDOW(window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_OK_CANCEL, + _("This is the last visible display. Do you want to quit?")); + gint result = gtk_dialog_run (GTK_DIALOG (dialog)); + switch (result) { + case GTK_RESPONSE_OK: + virt_viewer_app_quit(self); + break; + default: + break; + } + gtk_widget_destroy(dialog); + return FALSE; + } else { + virt_viewer_app_quit(self); + return FALSE; + } + } + + g_warn_if_reached(); + return FALSE; +} + +void +virt_viewer_app_about_close(GtkWidget *dialog, + VirtViewerApp *self G_GNUC_UNUSED) +{ + gtk_widget_hide(dialog); + gtk_widget_destroy(dialog); +} + +void +virt_viewer_app_about_delete(GtkWidget *dialog, + void *dummy G_GNUC_UNUSED, + VirtViewerApp *self G_GNUC_UNUSED) +{ + gtk_widget_hide(dialog); + gtk_widget_destroy(dialog); +} + +#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) + +static int +virt_viewer_app_open_tunnel(const char **cmd) +{ + int fd[2]; + pid_t pid; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) < 0) + return -1; + + pid = fork(); + if (pid == -1) { + close(fd[0]); + close(fd[1]); + return -1; + } + + if (pid == 0) { /* child */ + close(fd[0]); + close(0); + close(1); + if (dup(fd[1]) < 0) + _exit(1); + if (dup(fd[1]) < 0) + _exit(1); + close(fd[1]); + execvp("ssh", (char *const*)cmd); + _exit(1); + } + close(fd[1]); + return fd[0]; +} + + +static int +virt_viewer_app_open_tunnel_ssh(const char *sshhost, + int sshport, + const char *sshuser, + const char *host, + const char *port, + const char *unixsock) +{ + const char *cmd[10]; + char portstr[50]; + int n = 0; + + cmd[n++] = "ssh"; + if (!sshport) { + cmd[n++] = "-p"; + sprintf(portstr, "%d", sshport); + cmd[n++] = portstr; + } + if (sshuser) { + cmd[n++] = "-l"; + cmd[n++] = sshuser; + } + cmd[n++] = sshhost; + cmd[n++] = "nc"; + if (port) { + cmd[n++] = host; + cmd[n++] = port; + } else { + cmd[n++] = "-U"; + cmd[n++] = unixsock; + } + cmd[n++] = NULL; + + return virt_viewer_app_open_tunnel(cmd); +} + +static int +virt_viewer_app_open_unix_sock(const char *unixsock) +{ + struct sockaddr_un addr; + int fd; + + memset(&addr, 0, sizeof addr); + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, unixsock); + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return -1; + + if (connect(fd, (struct sockaddr *)&addr, sizeof addr) < 0) { + close(fd); + return -1; + } + + return fd; +} + +#endif /* defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) */ + +void +virt_viewer_app_trace(VirtViewerApp *self, + const char *fmt, ...) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + va_list ap; + VirtViewerAppPrivate *priv = self->priv; + + if (doDebug) { + va_start(ap, fmt); + g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, fmt, ap); + va_end(ap); + } + + if (priv->verbose) { + va_start(ap, fmt); + g_vprintf(fmt, ap); + va_end(ap); + } +} + +static void update_title(gpointer key G_GNUC_UNUSED, + gpointer value, + gpointer user_data G_GNUC_UNUSED) +{ + virt_viewer_window_update_title(VIRT_VIEWER_WINDOW(value)); +} + +static void +virt_viewer_app_update_title(VirtViewerApp *self) +{ + g_hash_table_foreach(self->priv->windows, update_title, NULL); +} + +static VirtViewerWindow * +virt_viewer_app_get_nth_window(VirtViewerApp *self, gint nth) +{ + return g_hash_table_lookup(self->priv->windows, &nth); +} + +static gboolean +virt_viewer_app_remove_nth_window(VirtViewerApp *self, gint nth) +{ + gboolean removed; + + g_return_val_if_fail(nth != 0, FALSE); + removed = g_hash_table_remove(self->priv->windows, &nth); + g_warn_if_fail(removed); + + return removed; +} + +static void +virt_viewer_app_set_nth_window(VirtViewerApp *self, gint nth, VirtViewerWindow *win) +{ + gint *key; + + g_return_if_fail(virt_viewer_app_get_nth_window(self, nth) == NULL); + key = g_malloc(sizeof(gint)); + *key = nth; + g_hash_table_insert(self->priv->windows, key, win); +} + +static void +viewer_window_visible_cb(GtkWidget *widget G_GNUC_UNUSED, + gpointer user_data) +{ + virt_viewer_app_update_menu_displays(VIRT_VIEWER_APP(user_data)); +} + + +static VirtViewerWindow* +virt_viewer_app_window_new(VirtViewerApp *self, GtkWidget *container, gint nth) +{ + VirtViewerWindow* window; + GtkWindow *w; + + window = g_object_new(VIRT_VIEWER_TYPE_WINDOW, + "app", self, + "container", container, + NULL); + virt_viewer_app_set_nth_window(self, nth, window); + w = virt_viewer_window_get_window(window); + + /* this will set new window to fullscreen if necessary */ + virt_viewer_app_set_fullscreen(self, self->priv->fullscreen); + g_signal_connect(w, "hide", G_CALLBACK(viewer_window_visible_cb), self); + g_signal_connect(w, "show", G_CALLBACK(viewer_window_visible_cb), self); + return window; +} + +static void +display_show_hint(VirtViewerDisplay *display, + GParamSpec *pspec G_GNUC_UNUSED, + VirtViewerWindow *win) +{ + VirtViewerApp *self; + VirtViewerNotebook *nb = virt_viewer_window_get_notebook(win); + GtkWindow *w = virt_viewer_window_get_window(win); + gint nth, hint; + + g_object_get(win, + "app", &self, + NULL); + g_object_get(display, + "nth-display", &nth, + "show-hint", &hint, + NULL); + + if (hint == VIRT_VIEWER_DISPLAY_SHOW_HINT_HIDE) { + if (win != self->priv->main_window && + g_getenv("VIRT_VIEWER_HIDE")) + gtk_widget_hide(GTK_WIDGET(w)); + virt_viewer_notebook_show_status(nb, _("Waiting for display %d..."), nth + 1); + } else { + virt_viewer_notebook_show_display(nb); + gtk_widget_show(GTK_WIDGET(w)); + gtk_window_present(w); + } + + g_object_unref(self); +} + +static void +virt_viewer_app_display_added(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerDisplay *display, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + VirtViewerWindow *window; + gint nth; + + g_object_get(display, "nth-display", &nth, NULL); + if (nth == 0) { + window = priv->main_window; + } else { + if (priv->container) { + g_warning("multi-head not yet supported within container"); + return; + } + + g_return_if_fail(virt_viewer_app_get_nth_window(self, nth) == NULL); + window = virt_viewer_app_window_new(self, NULL, nth); + } + + virt_viewer_window_set_display(window, display); + g_signal_connect(display, "notify::show-hint", + G_CALLBACK(display_show_hint), window); + g_object_notify(G_OBJECT(display), "show-hint"); /* call display_show_hint */ +} + + +static void +virt_viewer_app_display_removed(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerDisplay *display, + VirtViewerApp *self) +{ + VirtViewerWindow *win = NULL; + gint nth; + + gtk_widget_hide(GTK_WIDGET(display)); + g_object_get(display, "nth-display", &nth, NULL); + win = virt_viewer_app_get_nth_window(self, nth); + virt_viewer_window_set_display(win, NULL); + + if (nth != 0) + virt_viewer_app_remove_nth_window(self, nth); +} + +int +virt_viewer_app_create_session(VirtViewerApp *self, const gchar *type) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), -1); + VirtViewerAppPrivate *priv = self->priv; + g_return_val_if_fail(priv->session == NULL, -1); + + if (g_strcasecmp(type, "vnc") == 0) { + virt_viewer_app_trace(self, "Guest %s has a %s display\n", + priv->guest_name, type); + priv->session = virt_viewer_session_vnc_new(); + } else +#ifdef HAVE_SPICE_GTK + if (g_strcasecmp(type, "spice") == 0) { + virt_viewer_app_trace(self, "Guest %s has a %s display\n", + priv->guest_name, type); + priv->session = virt_viewer_session_spice_new(); + } else +#endif + { + virt_viewer_app_trace(self, "Guest %s has unsupported %s display type\n", + priv->guest_name, type); + virt_viewer_app_simple_message_dialog(self, _("Unknown graphic type for the guest %s"), + priv->guest_name); + return -1; + } + + g_signal_connect(priv->session, "session-initialized", + G_CALLBACK(virt_viewer_app_initialized), self); + g_signal_connect(priv->session, "session-connected", + G_CALLBACK(virt_viewer_app_connected), self); + g_signal_connect(priv->session, "session-disconnected", + G_CALLBACK(virt_viewer_app_disconnected), self); + g_signal_connect(priv->session, "session-channel-open", + G_CALLBACK(virt_viewer_app_channel_open), self); + g_signal_connect(priv->session, "session-auth-refused", + G_CALLBACK(virt_viewer_app_auth_refused), self); + g_signal_connect(priv->session, "session-auth-failed", + G_CALLBACK(virt_viewer_app_auth_failed), self); + g_signal_connect(priv->session, "session-display-added", + G_CALLBACK(virt_viewer_app_display_added), self); + g_signal_connect(priv->session, "session-display-removed", + G_CALLBACK(virt_viewer_app_display_removed), self); + + g_signal_connect(priv->session, "session-cut-text", + G_CALLBACK(virt_viewer_app_server_cut_text), self); + g_signal_connect(priv->session, "session-bell", + G_CALLBACK(virt_viewer_app_bell), self); + + return 0; +} + +#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) +static void +virt_viewer_app_channel_open(VirtViewerSession *session, + VirtViewerSessionChannel *channel, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv; + int fd = -1; + + g_return_if_fail(self != NULL); + + priv = self->priv; + if (priv->transport && g_strcasecmp(priv->transport, "ssh") == 0 && + !priv->direct) { + if ((fd = virt_viewer_app_open_tunnel_ssh(priv->host, priv->port, priv->user, + priv->ghost, priv->gport, NULL)) < 0) + virt_viewer_app_simple_message_dialog(self, _("Connect to ssh failed.")); + } else { + virt_viewer_app_simple_message_dialog(self, _("Can't connect to channel, SSH only supported.")); + } + + if (fd >= 0) + virt_viewer_session_channel_open_fd(session, channel, fd); +} +#else +static void +virt_viewer_app_channel_open(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerSessionChannel *channel G_GNUC_UNUSED, + VirtViewerApp *self) +{ + virt_viewer_app_simple_message_dialog(self, _("Connect to channel unsupported.")); +} +#endif + +int +virt_viewer_app_activate(VirtViewerApp *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), -1); + VirtViewerAppPrivate *priv = self->priv; + int fd = -1; + int ret = -1; + + if (priv->active) + goto cleanup; + +#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) + if (priv->transport && + g_strcasecmp(priv->transport, "ssh") == 0 && + !priv->direct) { + if (priv->gport) { + virt_viewer_app_trace(self, "Opening indirect TCP connection to display at %s:%s\n", + priv->ghost, priv->gport); + } else { + virt_viewer_app_trace(self, "Opening indirect UNIX connection to display at %s\n", + priv->unixsock); + } + virt_viewer_app_trace(self, "Setting up SSH tunnel via %s@%s:%d\n", + priv->user, priv->host, priv->port ? priv->port : 22); + + if ((fd = virt_viewer_app_open_tunnel_ssh(priv->host, priv->port, + priv->user, priv->ghost, + priv->gport, priv->unixsock)) < 0) + return -1; + } else if (priv->unixsock) { + virt_viewer_app_trace(self, "Opening direct UNIX connection to display at %s", + priv->unixsock); + if ((fd = virt_viewer_app_open_unix_sock(priv->unixsock)) < 0) + return -1; + } +#endif + + if (fd >= 0) { + ret = virt_viewer_session_open_fd(VIRT_VIEWER_SESSION(priv->session), fd); + } else { + virt_viewer_app_trace(self, "Opening direct TCP connection to display at %s:%s\n", + priv->ghost, priv->gport); + ret = virt_viewer_session_open_host(VIRT_VIEWER_SESSION(priv->session), + priv->ghost, priv->gport); + } + + virt_viewer_app_show_status(self, _("Connecting to graphic server")); + + priv->connected = FALSE; + priv->active = TRUE; + priv->grabbed = FALSE; + virt_viewer_app_update_title(self); + + cleanup: + return ret; +} + +/* text was actually requested */ +static void +virt_viewer_app_clipboard_copy(GtkClipboard *clipboard G_GNUC_UNUSED, + GtkSelectionData *data, + guint info G_GNUC_UNUSED, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + gtk_selection_data_set_text(data, priv->clipboard, -1); +} + +static void +virt_viewer_app_server_cut_text(VirtViewerSession *session G_GNUC_UNUSED, + const gchar *text, + VirtViewerApp *self) +{ + GtkClipboard *cb; + gsize a, b; + VirtViewerAppPrivate *priv = self->priv; + GtkTargetEntry targets[] = { + {g_strdup("UTF8_STRING"), 0, 0}, + {g_strdup("COMPOUND_TEXT"), 0, 0}, + {g_strdup("TEXT"), 0, 0}, + {g_strdup("STRING"), 0, 0}, + }; + + if (!text) + return; + + g_free (priv->clipboard); + priv->clipboard = g_convert (text, -1, "utf-8", "iso8859-1", &a, &b, NULL); + + if (priv->clipboard) { + cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + + gtk_clipboard_set_with_owner (cb, + targets, + G_N_ELEMENTS(targets), + (GtkClipboardGetFunc)virt_viewer_app_clipboard_copy, + NULL, + G_OBJECT (self)); + } +} + + +static void virt_viewer_app_bell(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + gdk_window_beep(gtk_widget_get_window(GTK_WIDGET(virt_viewer_window_get_window(priv->main_window)))); +} + + +static int +virt_viewer_app_default_initial_connect(VirtViewerApp *self) +{ + return virt_viewer_app_activate(self); +} + +int +virt_viewer_app_initial_connect(VirtViewerApp *self) +{ + VirtViewerAppClass *klass; + + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), -1); + klass = VIRT_VIEWER_APP_GET_CLASS(self); + + return klass->initial_connect(self); +} + +static gboolean +virt_viewer_app_retryauth(gpointer opaque) +{ + VirtViewerApp *self = opaque; + + virt_viewer_app_initial_connect(self); + + return FALSE; +} + +static gboolean +virt_viewer_app_connect_timer(void *opaque) +{ + VirtViewerApp *self = opaque; + VirtViewerAppPrivate *priv = self->priv; + + DEBUG_LOG("Connect timer fired"); + + if (!priv->active && + virt_viewer_app_initial_connect(self) < 0) + gtk_main_quit(); + + if (priv->active) { + priv->reconnect_poll = 0; + return FALSE; + } + + return TRUE; +} + +void +virt_viewer_app_start_reconnect_poll(VirtViewerApp *self) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + VirtViewerAppPrivate *priv = self->priv; + + if (priv->reconnect_poll != 0) + return; + + priv->reconnect_poll = g_timeout_add(500, virt_viewer_app_connect_timer, self); +} + +static void +virt_viewer_app_default_deactivated(VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + virt_viewer_app_show_status(self, _("Guest domain has shutdown")); + virt_viewer_app_trace(self, "Guest %s display has disconnected, shutting down", + priv->guest_name); + gtk_main_quit(); +} + +static void +virt_viewer_app_deactivated(VirtViewerApp *self) +{ + VirtViewerAppClass *klass; + klass = VIRT_VIEWER_APP_GET_CLASS(self); + + klass->deactivated(self); +} + +static void +virt_viewer_app_deactivate(VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + if (!priv->active) + return; + + if (priv->session) + virt_viewer_session_close(VIRT_VIEWER_SESSION(priv->session)); + + priv->connected = FALSE; + priv->active = FALSE; +#if 0 + g_free(priv->pretty_address); + priv->pretty_address = NULL; +#endif + priv->grabbed = FALSE; + virt_viewer_app_update_title(self); + + if (priv->authretry) { + priv->authretry = FALSE; + g_idle_add(virt_viewer_app_retryauth, self); + } else + virt_viewer_app_deactivated(self); + +} + +static void +virt_viewer_app_connected(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + priv->connected = TRUE; + virt_viewer_app_show_status(self, _("Connected to graphic server")); +} + + + +static void +virt_viewer_app_initialized(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerApp *self) +{ + virt_viewer_app_update_title(self); +} + +static void +virt_viewer_app_disconnected(VirtViewerSession *session G_GNUC_UNUSED, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + if (!priv->connected) { + virt_viewer_app_simple_message_dialog(self, + _("Unable to connect to the graphic server %s"), + priv->pretty_address); + } + virt_viewer_app_deactivate(self); +} + + +static void virt_viewer_app_auth_refused(VirtViewerSession *session G_GNUC_UNUSED, + const char *msg, + VirtViewerApp *self) +{ + GtkWidget *dialog; + int ret; + VirtViewerAppPrivate *priv = self->priv; + + dialog = gtk_message_dialog_new(virt_viewer_window_get_window(priv->main_window), + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_YES_NO, + _("Unable to authenticate with remote desktop server at %s: %s\n" + "Retry connection again?"), + priv->pretty_address, msg); + + ret = gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); + + if (ret == GTK_RESPONSE_YES) + priv->authretry = TRUE; + else + priv->authretry = FALSE; +} + + +static void virt_viewer_app_auth_failed(VirtViewerSession *session G_GNUC_UNUSED, + const char *msg, + VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv = self->priv; + + virt_viewer_app_simple_message_dialog(self, + _("Unable to authenticate with remote desktop server at %s"), + priv->pretty_address, msg); +} + +static void +virt_viewer_app_get_property (GObject *object, guint property_id, + GValue *value G_GNUC_UNUSED, GParamSpec *pspec) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(object)); + VirtViewerApp *self = VIRT_VIEWER_APP(object); + VirtViewerAppPrivate *priv = self->priv; + + switch (property_id) { + case PROP_VERBOSE: + g_value_set_boolean(value, priv->verbose); + break; + + case PROP_CONTAINER: + g_value_set_object(value, priv->container); + break; + + case PROP_SESSION: + g_value_set_object(value, priv->session); + break; + + case PROP_GUEST_NAME: + g_value_set_string(value, priv->guest_name); + break; + + case PROP_FULLSCREEN: + g_value_set_boolean(value, priv->fullscreen); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_app_set_property (GObject *object, guint property_id, + const GValue *value G_GNUC_UNUSED, GParamSpec *pspec) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(object)); + VirtViewerApp *self = VIRT_VIEWER_APP(object); + VirtViewerAppPrivate *priv = self->priv; + + switch (property_id) { + case PROP_VERBOSE: + priv->verbose = g_value_get_boolean(value); + break; + + case PROP_CONTAINER: + g_return_if_fail(priv->container == NULL); + priv->container = g_value_dup_object(value); + break; + + case PROP_GUEST_NAME: + g_free(priv->guest_name); + priv->guest_name = g_value_dup_string(value); + break; + + case PROP_FULLSCREEN: + virt_viewer_app_set_fullscreen(self, g_value_get_boolean(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_app_dispose (GObject *object) +{ + VirtViewerApp *self = VIRT_VIEWER_APP(object); + VirtViewerAppPrivate *priv = self->priv; + + if (priv->windows) { + g_hash_table_unref(priv->windows); + priv->windows = NULL; + } + + if (priv->main_window) { + g_object_unref(priv->main_window); + priv->main_window = NULL; + } + + if (priv->container) { + g_object_unref(priv->container); + priv->container = NULL; + } + + virt_viewer_app_free_connect_info(self); + + G_OBJECT_CLASS (virt_viewer_app_parent_class)->dispose (object); +} + +static gboolean +virt_viewer_app_default_start(VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv; + GtkWindow *win; + priv = self->priv; + + win = virt_viewer_window_get_window(priv->main_window); + if (win) + gtk_widget_show(GTK_WIDGET(win)); + else { + gtk_box_pack_end(GTK_BOX(priv->container), priv->main_notebook, TRUE, TRUE, 0); + gtk_widget_show(GTK_WIDGET(priv->main_notebook)); + } + + return TRUE; +} + +gboolean virt_viewer_app_start(VirtViewerApp *self) +{ + VirtViewerAppClass *klass; + + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), FALSE); + klass = VIRT_VIEWER_APP_GET_CLASS(self); + + g_return_val_if_fail(!self->priv->started, TRUE); + + self->priv->started = klass->start(self); + return self->priv->started; +} + +static void +virt_viewer_app_init (VirtViewerApp *self) +{ + self->priv = GET_PRIVATE(self); + self->priv->windows = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_object_unref); +} + +static GObject * +virt_viewer_app_constructor (GType gtype, + guint n_properties, + GObjectConstructParam *properties) +{ + GObject *obj; + VirtViewerApp *self; + VirtViewerAppPrivate *priv; + + obj = G_OBJECT_CLASS (virt_viewer_app_parent_class)->constructor (gtype, n_properties, properties); + self = VIRT_VIEWER_APP(obj); + priv = self->priv; + + priv->main_window = virt_viewer_app_window_new(self, priv->container, 0); + priv->main_notebook = GTK_WIDGET(virt_viewer_window_get_notebook(priv->main_window)); + + return obj; +} + +static void +virt_viewer_app_class_init (VirtViewerAppClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (VirtViewerAppPrivate)); + + object_class->constructor = virt_viewer_app_constructor; + object_class->get_property = virt_viewer_app_get_property; + object_class->set_property = virt_viewer_app_set_property; + object_class->dispose = virt_viewer_app_dispose; + + klass->start = virt_viewer_app_default_start; + klass->initial_connect = virt_viewer_app_default_initial_connect; + klass->deactivated = virt_viewer_app_default_deactivated; + + g_object_class_install_property(object_class, + PROP_VERBOSE, + g_param_spec_boolean("verbose", + "Verbose", + "Verbose trace", + FALSE, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_CONTAINER, + g_param_spec_object("container", + "Container", + "Widget container", + GTK_TYPE_WIDGET, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_SESSION, + g_param_spec_object("session", + "Session", + "ViewerSession", + VIRT_VIEWER_TYPE_SESSION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_GUEST_NAME, + g_param_spec_string("guest-name", + "Guest name", + "Guest name", + "", + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_FULLSCREEN, + g_param_spec_boolean("fullscreen", + "Fullscreen", + "Fullscreen", + FALSE, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS)); +} + +void +virt_viewer_app_set_direct(VirtViewerApp *self, gboolean direct) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + + self->priv->direct = direct; +} + +gboolean +virt_viewer_app_is_active(VirtViewerApp *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), FALSE); + + return self->priv->active; +} + +gboolean +virt_viewer_app_has_session(VirtViewerApp *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), FALSE); + + return self->priv->session != NULL; +} + +static void +virt_viewer_app_update_pretty_address(VirtViewerApp *self) +{ + VirtViewerAppPrivate *priv; + + priv = self->priv; + g_free(priv->pretty_address); + if (priv->gport) + priv->pretty_address = g_strdup_printf("%s:%s", priv->ghost, priv->gport); + else + priv->pretty_address = g_strdup_printf("%s:%s", priv->host, priv->unixsock); +} + +typedef struct { + gboolean fullscreen; + gboolean move; +} FullscreenOptions; + +static void fullscreen_cb(gpointer key, + gpointer value, + gpointer user_data) +{ + gint nth = *(gint*)key; + FullscreenOptions *options = (FullscreenOptions *)user_data; + VirtViewerWindow *vwin = VIRT_VIEWER_WINDOW(value); + + DEBUG_LOG("fullscreen display %d: %d", nth, options->fullscreen); + if (options->fullscreen) { + GdkScreen *screen = gdk_screen_get_default (); + GdkRectangle mon; + + if (nth >= gdk_screen_get_n_monitors(screen)) { + DEBUG_LOG("skipping display %d", nth); + return; + } + gdk_screen_get_monitor_geometry(screen, nth, &mon); + virt_viewer_window_enter_fullscreen(vwin, options->move, mon.x, mon.y); + } else + virt_viewer_window_leave_fullscreen(vwin); +} + +static void +virt_viewer_app_set_fullscreen(VirtViewerApp *self, gboolean fullscreen) +{ + VirtViewerAppPrivate *priv = self->priv; + FullscreenOptions options = { + .fullscreen = fullscreen, + .move = virt_viewer_app_get_n_windows_visible(self) > 1, + }; + + /* we iterate unconditionnaly, even if it was set before to update new windows */ + priv->fullscreen = fullscreen; + g_hash_table_foreach(priv->windows, fullscreen_cb, &options); +} + +static void +menu_display_visible_toggled_cb(GtkCheckMenuItem *checkmenuitem, + VirtViewerWindow *vwin) +{ + VirtViewerApp *self; + gboolean visible; + static gboolean reentering = FALSE; + + if (reentering) /* do not reenter if I switch you back */ + return; + + reentering = TRUE; + g_object_get(vwin, "app", &self, NULL); + visible = virt_viewer_app_window_set_visible(self, vwin, + gtk_check_menu_item_get_active(checkmenuitem)); + gtk_check_menu_item_set_active(checkmenuitem, /* will be toggled again */ !visible); + g_object_unref(self); + reentering = FALSE; +} + +static gint +update_menu_displays_sort(gconstpointer a, gconstpointer b) +{ + const int *ai = a; + const int *bi = b; + + if (*ai > *bi) + return 1; + else if (*ai < *bi) + return -1; + else + return 0; +} + +static void +window_update_menu_displays_cb(gpointer key G_GNUC_UNUSED, + gpointer value, + gpointer user_data) +{ + VirtViewerApp *self = VIRT_VIEWER_APP(user_data); + VirtViewerWindow *window = VIRT_VIEWER_WINDOW(value); + GtkMenuShell *submenu = GTK_MENU_SHELL(gtk_menu_new()); + GtkMenuItem *menu = virt_viewer_window_get_menu_displays(window); + GList *keys = g_hash_table_get_keys(self->priv->windows); + GList *tmp; + + keys = g_list_sort(keys, update_menu_displays_sort); + + tmp = keys; + while (tmp) { + int *nth = tmp->data; + VirtViewerWindow *vwin = VIRT_VIEWER_WINDOW(g_hash_table_lookup(self->priv->windows, nth)); + GtkWidget *item; + gboolean visible; + + item = gtk_check_menu_item_new_with_label(g_strdup_printf("Display %d", *nth)); + visible = gtk_widget_get_visible(GTK_WIDGET(virt_viewer_window_get_window(vwin))); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), visible); + g_signal_connect(G_OBJECT(item), + "toggled", G_CALLBACK(menu_display_visible_toggled_cb), vwin); + gtk_menu_shell_append(submenu, item); + tmp = tmp->next; + } + + gtk_widget_show_all(GTK_WIDGET(submenu)); + gtk_menu_item_set_submenu(menu, GTK_WIDGET(submenu)); + g_list_free(keys); +} + +static void +virt_viewer_app_update_menu_displays(VirtViewerApp *self) +{ + g_hash_table_foreach(self->priv->windows, window_update_menu_displays_cb, self); +} + +void +virt_viewer_app_set_connect_info(VirtViewerApp *self, + const gchar *host, + const gchar *ghost, + const gchar *gport, + const gchar *transport, + const gchar *unixsock, + const gchar *user, + gint port) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + VirtViewerAppPrivate *priv = self->priv; + + DEBUG_LOG("Set connect info: %s,%s,%s,%s,%s,%s,%d", + host, ghost, gport, transport, unixsock, user, port); + + g_free(priv->host); + g_free(priv->ghost); + g_free(priv->gport); + g_free(priv->transport); + g_free(priv->unixsock); + g_free(priv->user); + + priv->host = g_strdup(host); + priv->ghost = g_strdup(ghost); + priv->gport = g_strdup(gport); + priv->transport = g_strdup(transport); + priv->unixsock = g_strdup(unixsock); + priv->user = g_strdup(user); + priv->port = 0; + + virt_viewer_app_update_pretty_address(self); +} + +void +virt_viewer_app_free_connect_info(VirtViewerApp *self) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + + virt_viewer_app_set_connect_info(self, NULL, NULL, NULL, NULL, NULL, NULL, 0); +} + +VirtViewerWindow* +virt_viewer_app_get_main_window(VirtViewerApp *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_APP(self), NULL); + + return self->priv->main_window; +} + +static void +show_status_cb(gpointer key G_GNUC_UNUSED, + gpointer value, + gpointer user_data) +{ + VirtViewerNotebook *nb = virt_viewer_window_get_notebook(VIRT_VIEWER_WINDOW(value)); + gchar *text = (gchar*)user_data; + + virt_viewer_notebook_show_status(nb, text); +} + +void +virt_viewer_app_show_status(VirtViewerApp *self, const gchar *fmt, ...) +{ + va_list args; + gchar *text; + + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + + va_start(args, fmt); + text = g_strdup_vprintf(fmt, args); + va_end(args); + + g_hash_table_foreach(self->priv->windows, show_status_cb, text); + g_free(text); +} + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/src/virt-viewer-app.h b/src/virt-viewer-app.h new file mode 100644 index 0000000..ad3a761 --- /dev/null +++ b/src/virt-viewer-app.h @@ -0,0 +1,84 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007 Red Hat, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ + +#ifndef VIRT_VIEWER_APP_H +#define VIRT_VIEWER_APP_H + +#include +#include "virt-viewer-util.h" +#include "virt-viewer-window.h" + +G_BEGIN_DECLS + +#define VIRT_VIEWER_TYPE_APP virt_viewer_app_get_type() +#define VIRT_VIEWER_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIRT_VIEWER_TYPE_APP, VirtViewerApp)) +#define VIRT_VIEWER_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_APP, VirtViewerAppClass)) +#define VIRT_VIEWER_IS_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_APP)) +#define VIRT_VIEWER_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_APP)) +#define VIRT_VIEWER_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_APP, VirtViewerAppClass)) + +typedef struct _VirtViewerAppPrivate VirtViewerAppPrivate; + +typedef struct { + GObject parent; + VirtViewerAppPrivate *priv; +} VirtViewerApp; + +typedef struct { + GObjectClass parent_class; + + gboolean (*start) (VirtViewerApp *self); + int (*initial_connect) (VirtViewerApp *self); + void (*deactivated) (VirtViewerApp *self); +} VirtViewerAppClass; + +GType virt_viewer_app_get_type (void); + +void virt_viewer_app_set_debug(gboolean debug); +gboolean virt_viewer_app_start(VirtViewerApp *app); +void virt_viewer_app_quit(VirtViewerApp *self); +VirtViewerWindow* virt_viewer_app_get_main_window(VirtViewerApp *self); +void virt_viewer_app_trace(VirtViewerApp *self, const char *fmt, ...); +void virt_viewer_app_simple_message_dialog(VirtViewerApp *self, const char *fmt, ...); +gboolean virt_viewer_app_is_active(VirtViewerApp *app); +void virt_viewer_app_free_connect_info(VirtViewerApp *self); +int virt_viewer_app_create_session(VirtViewerApp *self, const gchar *type); +int virt_viewer_app_activate(VirtViewerApp *self); +int virt_viewer_app_initial_connect(VirtViewerApp *self); +void virt_viewer_app_start_reconnect_poll(VirtViewerApp *self); +void virt_viewer_app_set_zoom_level(VirtViewerApp *self, gint zoom_level); +void virt_viewer_app_set_direct(VirtViewerApp *self, gboolean direct); +gboolean virt_viewer_app_has_session(VirtViewerApp *self); +void virt_viewer_app_set_connect_info(VirtViewerApp *self, + const gchar *host, + const gchar *ghost, + const gchar *gport, + const gchar *transport, + const gchar *unixsock, + const gchar *user, + gint port); +gboolean virt_viewer_app_window_set_visible(VirtViewerApp *self, VirtViewerWindow *window, gboolean visible); +void virt_viewer_app_show_status(VirtViewerApp *self, const gchar *fmt, ...); + +G_END_DECLS + +#endif /* VIRT_VIEWER_APP_H */ diff --git a/src/virt-viewer-auth.c b/src/virt-viewer-auth.c index 3d63dcd..811051f 100644 --- a/src/virt-viewer-auth.c +++ b/src/virt-viewer-auth.c @@ -63,7 +63,7 @@ message = g_strdup_printf("Authentication is required for the %s connection to:\n\n" "%s\n\n", type, - address ? address : "[unknown]"); + address); } else { message = g_strdup_printf("Authentication is required for the %s connection:\n", type); diff --git a/src/virt-viewer-display-spice.c b/src/virt-viewer-display-spice.c index 6d0e0a0..1a056f8 100644 --- a/src/virt-viewer-display-spice.c +++ b/src/virt-viewer-display-spice.c @@ -100,19 +100,29 @@ } static void -virt_viewer_display_spice_primary_create(SpiceChannel *channel G_GNUC_UNUSED, - gint format G_GNUC_UNUSED, - gint width, - gint height, - gint stride G_GNUC_UNUSED, - gint shmid G_GNUC_UNUSED, - gpointer imgdata G_GNUC_UNUSED, - VirtViewerDisplay *display) +display_mark(SpiceChannel *channel G_GNUC_UNUSED, + gint mark, + VirtViewerDisplay *display) { - DEBUG_LOG("desktop resize %dx%d", width, height); + DEBUG_LOG("display mark %d", mark); - virt_viewer_display_set_desktop_size(display, width, height); - g_signal_emit_by_name(display, "display-desktop-resize"); + virt_viewer_display_set_show_hint(display, mark); +} + +static void +primary_create(SpiceChannel *channel G_GNUC_UNUSED, + gint format G_GNUC_UNUSED, + gint width, + gint height, + gint stride G_GNUC_UNUSED, + gint shmid G_GNUC_UNUSED, + gpointer imgdata G_GNUC_UNUSED, + VirtViewerDisplay *display) +{ + DEBUG_LOG("spice desktop resize %dx%d", width, height); + + virt_viewer_display_set_desktop_size(display, width, height); + g_signal_emit_by_name(display, "display-desktop-resize"); } @@ -121,17 +131,23 @@ SpiceDisplay *display) { VirtViewerDisplaySpice *self; + gint channelid; - self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE, NULL); + g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL); + g_return_val_if_fail(SPICE_IS_DISPLAY(display), NULL); - self->priv->channel = channel; - self->priv->display = display; + g_object_get(channel, "channel-id", &channelid, NULL); - g_object_ref(channel); - g_object_ref(display); + self = g_object_new(VIRT_VIEWER_TYPE_DISPLAY_SPICE, + "nth-display", channelid, + NULL); + self->priv->channel = g_object_ref(channel); + self->priv->display = g_object_ref(display); g_signal_connect(channel, "display-primary-create", - G_CALLBACK(virt_viewer_display_spice_primary_create), self); + G_CALLBACK(primary_create), self); + g_signal_connect(channel, "display-mark", + G_CALLBACK(display_mark), self); gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(self->priv->display)); gtk_widget_show(GTK_WIDGET(self->priv->display)); diff --git a/src/virt-viewer-display-spice.h b/src/virt-viewer-display-spice.h index 23d75cc..90bd1d0 100644 --- a/src/virt-viewer-display-spice.h +++ b/src/virt-viewer-display-spice.h @@ -40,10 +40,10 @@ #define VIRT_VIEWER_DISPLAY_SPICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_DISPLAY_SPICE, VirtViewerDisplaySpiceClass)) -#define VIRT_IS_VIEWER_DISPLAY_SPICE(obj) \ +#define VIRT_VIEWER_IS_DISPLAY_SPICE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_DISPLAY_SPICE)) -#define VIRT_IS_VIEWER_DISPLAY_SPICE_CLASS(klass) \ +#define VIRT_VIEWER_IS_DISPLAY_SPICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_DISPLAY_SPICE)) #define VIRT_VIEWER_DISPLAY_SPICE_GET_CLASS(obj) \ diff --git a/src/virt-viewer-display-vnc.h b/src/virt-viewer-display-vnc.h index 5ca5d1b..ce9ec5f 100644 --- a/src/virt-viewer-display-vnc.h +++ b/src/virt-viewer-display-vnc.h @@ -39,10 +39,10 @@ #define VIRT_VIEWER_DISPLAY_VNC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_DISPLAY_VNC, VirtViewerDisplayVncClass)) -#define VIRT_IS_VIEWER_DISPLAY_VNC(obj) \ +#define VIRT_VIEWER_IS_DISPLAY_VNC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_DISPLAY_VNC)) -#define VIRT_IS_VIEWER_DISPLAY_VNC_CLASS(klass) \ +#define VIRT_VIEWER_IS_DISPLAY_VNC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_DISPLAY_VNC)) #define VIRT_VIEWER_DISPLAY_VNC_GET_CLASS(obj) \ diff --git a/src/virt-viewer-display.c b/src/virt-viewer-display.c index b4770f5..881a69e 100644 --- a/src/virt-viewer-display.c +++ b/src/virt-viewer-display.c @@ -38,6 +38,8 @@ guint desktopHeight; guint zoom_level; gboolean zoom; + gint nth_display; + gint show_hint; }; static void virt_viewer_display_size_request(GtkWidget *widget, @@ -68,8 +70,10 @@ PROP_DESKTOP_WIDTH, PROP_DESKTOP_HEIGHT, + PROP_NTH_DISPLAY, PROP_ZOOM, PROP_ZOOM_LEVEL, + PROP_SHOW_HINT, }; static void @@ -98,6 +102,7 @@ G_MAXINT32, 100, G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_DESKTOP_HEIGHT, g_param_spec_int("desktop-height", @@ -107,6 +112,7 @@ G_MAXINT32, 100, G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_ZOOM, g_param_spec_boolean("zoom", @@ -114,6 +120,7 @@ "Zoom", TRUE, G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_ZOOM_LEVEL, g_param_spec_int("zoom-level", @@ -124,6 +131,27 @@ 100, G_PARAM_READWRITE)); + g_object_class_install_property(object_class, + PROP_NTH_DISPLAY, + g_param_spec_int("nth-display", + "Nth display", + "Nth display", + 0, + G_MAXINT32, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property(object_class, + PROP_SHOW_HINT, + g_param_spec_int("show-hint", + "Show hint", + "Show state hint", + 0, + G_MAXINT32, + 0, + G_PARAM_READABLE)); + g_signal_new("display-pointer-grab", G_OBJECT_CLASS_TYPE(object_class), @@ -206,7 +234,7 @@ { VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(object); VirtViewerDisplayPrivate *priv = display->priv; - + switch (prop_id) { case PROP_DESKTOP_WIDTH: virt_viewer_display_set_desktop_size(display, @@ -218,7 +246,9 @@ priv->desktopWidth, g_value_get_int(value)); break; - + case PROP_NTH_DISPLAY: + priv->nth_display = g_value_get_int(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -233,7 +263,7 @@ { VirtViewerDisplay *display = VIRT_VIEWER_DISPLAY(object); VirtViewerDisplayPrivate *priv = display->priv; - + switch (prop_id) { case PROP_DESKTOP_WIDTH: g_value_set_int(value, priv->desktopWidth); @@ -241,7 +271,13 @@ case PROP_DESKTOP_HEIGHT: g_value_set_int(value, priv->desktopHeight); break; - + case PROP_NTH_DISPLAY: + g_value_set_int(value, priv->nth_display); + break; + case PROP_SHOW_HINT: + g_value_set_int(value, priv->show_hint); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -444,6 +480,19 @@ return VIRT_VIEWER_DISPLAY_GET_CLASS(display)->get_pixbuf(display); } +void virt_viewer_display_set_show_hint(VirtViewerDisplay *self, gint hint) +{ + VirtViewerDisplayPrivate *priv; + g_return_if_fail(VIRT_VIEWER_IS_DISPLAY(self)); + + priv = self->priv; + if (priv->show_hint == hint) + return; + + priv->show_hint = hint; + g_object_notify(G_OBJECT(self), "show-hint"); +} + /* * Local variables: * c-indent-level: 8 diff --git a/src/virt-viewer-display.h b/src/virt-viewer-display.h index 8d5a0df..d49dd67 100644 --- a/src/virt-viewer-display.h +++ b/src/virt-viewer-display.h @@ -51,6 +51,10 @@ typedef struct _VirtViewerDisplayChannel VirtViewerDisplayChannel; +enum { + VIRT_VIEWER_DISPLAY_SHOW_HINT_HIDE = 0, + VIRT_VIEWER_DISPLAY_SHOW_HINT_READY, +}; /* perhaps this become an interface, and be pushed in gtkvnc and spice? */ struct _VirtViewerDisplay { @@ -93,9 +97,10 @@ void virt_viewer_display_set_zoom(VirtViewerDisplay *display, gboolean zoom); -void virt_viewer_display_send_keys(VirtViewerDisplay* display, +void virt_viewer_display_send_keys(VirtViewerDisplay *display, const guint *keyvals, int nkeyvals); -GdkPixbuf* virt_viewer_display_get_pixbuf(VirtViewerDisplay* display); +GdkPixbuf* virt_viewer_display_get_pixbuf(VirtViewerDisplay *display); +void virt_viewer_display_set_show_hint(VirtViewerDisplay *display, gint hint); G_END_DECLS diff --git a/src/virt-viewer-main.c b/src/virt-viewer-main.c index 749365c..78d8d19 100644 --- a/src/virt-viewer-main.c +++ b/src/virt-viewer-main.c @@ -51,6 +51,7 @@ gboolean waitvm = FALSE; gboolean reconnect = FALSE; gboolean fullscreen = FALSE; + VirtViewer *viewer = NULL; const char *help_msg = N_("Run '" PACKAGE " --help' to see a full list of available command line options"); const GOptionEntry options [] = { { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, @@ -107,13 +108,23 @@ goto cleanup; } - ret = virt_viewer_start(uri, args[0], zoom, direct, waitvm, reconnect, verbose, debug, fullscreen, NULL); - if (ret != 0) - return ret; + virt_viewer_app_set_debug(debug); + + viewer = virt_viewer_new(uri, args[0], zoom, direct, waitvm, reconnect, verbose, NULL); + if (viewer == NULL) + goto cleanup; + + g_object_set(viewer, "fullscreen", fullscreen, NULL); + if (!virt_viewer_app_start(VIRT_VIEWER_APP(viewer))) + goto cleanup; gtk_main(); - cleanup: + ret = 0; + +cleanup: + if (viewer) + g_object_unref(viewer); g_free(uri); g_strfreev(args); diff --git a/src/virt-viewer-notebook.c b/src/virt-viewer-notebook.c new file mode 100644 index 0000000..fa28593 --- /dev/null +++ b/src/virt-viewer-notebook.c @@ -0,0 +1,148 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2009 Red Hat, + * Copyright (C) 2009 Daniel P. Berrange + * Copyright (C) 2010 Marc-André Lureau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ +#include "virt-viewer-notebook.h" +#include "virt-viewer-util.h" + +G_DEFINE_TYPE (VirtViewerNotebook, virt_viewer_notebook, GTK_TYPE_NOTEBOOK) + +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIRT_VIEWER_TYPE_NOTEBOOK, VirtViewerNotebookPrivate)) + +struct _VirtViewerNotebookPrivate { + GtkWidget *status; +}; + +static void +virt_viewer_notebook_get_property (GObject *object, guint property_id, + GValue *value G_GNUC_UNUSED, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_notebook_set_property (GObject *object, guint property_id, + const GValue *value G_GNUC_UNUSED, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_notebook_dispose (GObject *object) +{ + G_OBJECT_CLASS (virt_viewer_notebook_parent_class)->dispose (object); +} + +static void +virt_viewer_notebook_class_init (VirtViewerNotebookClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (VirtViewerNotebookPrivate)); + + object_class->get_property = virt_viewer_notebook_get_property; + object_class->set_property = virt_viewer_notebook_set_property; + object_class->dispose = virt_viewer_notebook_dispose; +} + +static void +virt_viewer_notebook_init (VirtViewerNotebook *self) +{ + VirtViewerNotebookPrivate *priv; + GdkColor color; + + self->priv = GET_PRIVATE(self); + priv = self->priv; + + priv->status = gtk_label_new(""); + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(self), FALSE); + gtk_notebook_set_show_border(GTK_NOTEBOOK(self), FALSE); + gtk_notebook_append_page(GTK_NOTEBOOK(self), priv->status, NULL); + gdk_color_parse("white", &color); + gtk_widget_modify_fg(priv->status, GTK_STATE_NORMAL, &color); +} + +void +virt_viewer_notebook_show_status_va(VirtViewerNotebook *self, const gchar *fmt, va_list args) +{ + VirtViewerNotebookPrivate *priv; + gchar *text; + + DEBUG_LOG("notebook show status %p", self); + g_return_if_fail(VIRT_VIEWER_IS_NOTEBOOK(self)); + + text = g_strdup_vprintf(fmt, args); + priv = self->priv; + gtk_label_set_text(GTK_LABEL(priv->status), text); + gtk_notebook_set_current_page(GTK_NOTEBOOK(self), 0); + gtk_widget_show_all(GTK_WIDGET(self)); + g_free(text); +} + +void +virt_viewer_notebook_show_status(VirtViewerNotebook *self, const gchar *fmt, ...) +{ + va_list args; + + g_return_if_fail(VIRT_VIEWER_IS_NOTEBOOK(self)); + + va_start(args, fmt); + virt_viewer_notebook_show_status_va(self, fmt, args); + va_end(args); +} + +void +virt_viewer_notebook_show_display(VirtViewerNotebook *self) +{ + GtkWidget *display; + + DEBUG_LOG("notebook show display %p", self); + g_return_if_fail(VIRT_VIEWER_IS_NOTEBOOK(self)); + + display = gtk_notebook_get_nth_page(GTK_NOTEBOOK(self), 1); + g_warn_if_fail(display != NULL); + + gtk_notebook_set_current_page(GTK_NOTEBOOK(self), 1); + gtk_widget_show_all(GTK_WIDGET(self)); +} + +VirtViewerNotebook* +virt_viewer_notebook_new (void) +{ + return g_object_new (VIRT_VIEWER_TYPE_NOTEBOOK, NULL); +} + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/src/virt-viewer-notebook.h b/src/virt-viewer-notebook.h new file mode 100644 index 0000000..0d2b0ce --- /dev/null +++ b/src/virt-viewer-notebook.h @@ -0,0 +1,78 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2009 Red Hat, + * Copyright (C) 2009 Daniel P. Berrange + * Copyright (C) 2010 Marc-André Lureau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ +#ifndef _VIRT_VIEWER_NOTEBOOK +#define _VIRT_VIEWER_NOTEBOOK + +#include +#include + +G_BEGIN_DECLS + +#define VIRT_VIEWER_TYPE_NOTEBOOK virt_viewer_notebook_get_type() + +#define VIRT_VIEWER_NOTEBOOK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIRT_VIEWER_TYPE_NOTEBOOK, VirtViewerNotebook)) + +#define VIRT_VIEWER_NOTEBOOK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_NOTEBOOK, VirtViewerNotebookClass)) + +#define VIRT_VIEWER_IS_NOTEBOOK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_NOTEBOOK)) + +#define VIRT_VIEWER_IS_NOTEBOOK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_NOTEBOOK)) + +#define VIRT_VIEWER_NOTEBOOK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_NOTEBOOK, VirtViewerNotebookClass)) + +typedef struct _VirtViewerNotebookPrivate VirtViewerNotebookPrivate; + +typedef struct { + GtkNotebook parent; + VirtViewerNotebookPrivate *priv; +} VirtViewerNotebook; + +typedef struct { + GtkNotebookClass parent_class; +} VirtViewerNotebookClass; + +GType virt_viewer_notebook_get_type (void); + +VirtViewerNotebook* virt_viewer_notebook_new (void); +void virt_viewer_notebook_show_status_va(VirtViewerNotebook *self, const gchar *fmt, va_list args); +void virt_viewer_notebook_show_status(VirtViewerNotebook *nb, const gchar *fmt, ...); +void virt_viewer_notebook_show_display(VirtViewerNotebook *nb); + +G_END_DECLS + +#endif /* _VIRT_VIEWER_NOTEBOOK */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c index 0b4b84b..011bbcc 100644 --- a/src/virt-viewer-session-spice.c +++ b/src/virt-viewer-session-spice.c @@ -233,8 +233,6 @@ if (SPICE_IS_DISPLAY_CHANNEL(channel)) { GtkWidget *display; - if (id != 0) - return; g_signal_emit_by_name(session, "session-connected"); diff --git a/src/virt-viewer-session-spice.h b/src/virt-viewer-session-spice.h index 6db8829..8926940 100644 --- a/src/virt-viewer-session-spice.h +++ b/src/virt-viewer-session-spice.h @@ -40,10 +40,10 @@ #define VIRT_VIEWER_SESSION_SPICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_SESSION_SPICE, VirtViewerSessionSpiceClass)) -#define VIRT_IS_VIEWER_SESSION_SPICE(obj) \ +#define VIRT_VIEWER_IS_SESSION_SPICE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_SESSION_SPICE)) -#define VIRT_IS_VIEWER_SESSION_SPICE_CLASS(klass) \ +#define VIRT_VIEWER_IS_SESSION_SPICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_SESSION_SPICE)) #define VIRT_VIEWER_SESSION_SPICE_GET_CLASS(obj) \ diff --git a/src/virt-viewer-session-vnc.c b/src/virt-viewer-session-vnc.c index dcfa764..ad3002a 100644 --- a/src/virt-viewer-session-vnc.c +++ b/src/virt-viewer-session-vnc.c @@ -86,6 +86,8 @@ { GtkWidget *display = virt_viewer_display_vnc_new(session->priv->vnc); g_signal_emit_by_name(session, "session-connected"); + virt_viewer_display_set_show_hint(VIRT_VIEWER_DISPLAY(display), + VIRT_VIEWER_DISPLAY_SHOW_HINT_READY); virt_viewer_session_add_display(VIRT_VIEWER_SESSION(session), VIRT_VIEWER_DISPLAY(display)); } @@ -95,6 +97,9 @@ VirtViewerSessionVnc *session) { g_signal_emit_by_name(session, "session-disconnected"); + /* TODO perhaps? */ + /* virt_viewer_display_set_show_hint(VIRT_VIEWER_DISPLAY(session->priv->vnc), */ + /* VIRT_VIEWER_DISPLAY_SHOW_HINT_HIDE); */ } static void diff --git a/src/virt-viewer-session-vnc.h b/src/virt-viewer-session-vnc.h index b23e432..2684e45 100644 --- a/src/virt-viewer-session-vnc.h +++ b/src/virt-viewer-session-vnc.h @@ -39,10 +39,10 @@ #define VIRT_VIEWER_SESSION_VNC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_SESSION_VNC, VirtViewerSessionVncClass)) -#define VIRT_IS_VIEWER_SESSION_VNC(obj) \ +#define VIRT_VIEWER_IS_SESSION_VNC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_SESSION_VNC)) -#define VIRT_IS_VIEWER_SESSION_VNC_CLASS(klass) \ +#define VIRT_VIEWER_IS_SESSION_VNC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_SESSION_VNC)) #define VIRT_VIEWER_SESSION_VNC_GET_CLASS(obj) \ diff --git a/src/virt-viewer-util.c b/src/virt-viewer-util.c index bda80a4..4be50d7 100644 --- a/src/virt-viewer-util.c +++ b/src/virt-viewer-util.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include "virt-viewer-util.h" @@ -51,6 +54,58 @@ return builder; } +int +virt_viewer_util_extract_host(const char *uristr, + char **scheme, + char **host, + char **transport, + char **user, + int *port) +{ + xmlURIPtr uri; + char *offset; + + if (uristr == NULL || + !g_strcasecmp(uristr, "xen")) + uristr = "xen:///"; + + uri = xmlParseURI(uristr); + if (host) { + if (!uri || !uri->server) + *host = g_strdup("localhost"); + else + *host = g_strdup(uri->server); + } + + if (user) { + if (uri->user) + *user = g_strdup(uri->user); + else + *user = NULL; + } + + if (port) + *port = uri->port; + + offset = strchr(uri->scheme, '+'); + + if (transport) { + if (offset) + *transport = g_strdup(offset+1); + else + *transport = NULL; + } + + if (scheme) { + if (offset) + *scheme = g_strndup(uri->scheme, offset - uri->scheme); + else + *scheme = g_strdup(uri->scheme); + } + + xmlFreeURI(uri); + return 0; +} /* * Local variables: diff --git a/src/virt-viewer-util.h b/src/virt-viewer-util.h index f2fec29..034ab8f 100644 --- a/src/virt-viewer-util.h +++ b/src/virt-viewer-util.h @@ -33,5 +33,11 @@ GtkBuilder *virt_viewer_util_load_ui(const char *name); +int virt_viewer_util_extract_host(const char *uristr, + char **scheme, + char **host, + char **transport, + char **user, + int *port); #endif diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c new file mode 100644 index 0000000..f80947e --- /dev/null +++ b/src/virt-viewer-window.c @@ -0,0 +1,899 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2009 Red Hat, + * Copyright (C) 2009 Daniel P. Berrange + * Copyright (C) 2010 Marc-André Lureau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-viewer-window.h" +#include "virt-viewer-app.h" +#include "virt-viewer-util.h" +#include "view/autoDrawer.h" + +/* Signal handlers for main window (move in a VirtViewerMainWindow?) */ +void virt_viewer_window_menu_view_zoom_out(GtkWidget *menu, VirtViewerWindow *self); +void virt_viewer_window_menu_view_zoom_in(GtkWidget *menu, VirtViewerWindow *self); +void virt_viewer_window_menu_view_zoom_reset(GtkWidget *menu, VirtViewerWindow *self); +gboolean virt_viewer_window_delete(GtkWidget *src, void *dummy, VirtViewerWindow *self); +void virt_viewer_window_menu_file_quit(GtkWidget *src, VirtViewerWindow *self); +void virt_viewer_window_menu_help_about(GtkWidget *menu, VirtViewerWindow *self); +void virt_viewer_window_menu_view_fullscreen(GtkWidget *menu, VirtViewerWindow *self); +void virt_viewer_window_menu_view_resize(GtkWidget *menu, VirtViewerWindow *self); +void virt_viewer_window_menu_send(GtkWidget *menu, VirtViewerWindow *self); +void virt_viewer_window_menu_file_screenshot(GtkWidget *menu, VirtViewerWindow *self); + +/* Internal methods */ +static void virt_viewer_window_enable_modifiers(VirtViewerWindow *self); +static void virt_viewer_window_disable_modifiers(VirtViewerWindow *self); +static void virt_viewer_window_resize(VirtViewerWindow *self); +static void virt_viewer_window_toolbar_setup(VirtViewerWindow *self); + +G_DEFINE_TYPE (VirtViewerWindow, virt_viewer_window, G_TYPE_OBJECT) + +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIRT_VIEWER_TYPE_WINDOW, VirtViewerWindowPrivate)) + +enum { + PROP_0, + PROP_WINDOW, + PROP_DISPLAY, + PROP_SUBTITLE, + PROP_CONTAINER, + PROP_APP, +}; + +enum menuNums { + FILE_MENU, + VIEW_MENU, + SEND_KEY_MENU, + HELP_MENU, + LAST_MENU // sentinel +}; + +struct _VirtViewerWindowPrivate { + VirtViewerApp *app; + GtkContainer *container; /* if any, then there is no window */ + + GtkBuilder *builder; + GtkWidget *window; + GtkWidget *layout; + GtkWidget *toolbar; + VirtViewerNotebook *notebook; + VirtViewerDisplay *display; + + gboolean accel_enabled; + GValue accel_setting; + GSList *accel_list; + int accel_menu_sig[LAST_MENU]; + gboolean grabbed; + gboolean before_saved; + GdkRectangle before_fullscreen; + + gint zoomlevel; + gboolean auto_resize; + gboolean fullscreen; + gchar *subtitle; +}; + +#if GTK_CHECK_VERSION(3, 0, 0) +#define GDK_Control_L GDK_KEY_Control_L +#define GDK_Alt_L GDK_KEY_Alt_L +#define GDK_Delete GDK_KEY_Delete +#define GDK_BackSpace GDK_KEY_BackSpace +#define GDK_Print GDK_KEY_Print +#define GDK_F1 GDK_KEY_F1 +#define GDK_F2 GDK_KEY_F2 +#define GDK_F3 GDK_KEY_F3 +#define GDK_F4 GDK_KEY_F4 +#define GDK_F5 GDK_KEY_F5 +#define GDK_F6 GDK_KEY_F6 +#define GDK_F7 GDK_KEY_F7 +#define GDK_F8 GDK_KEY_F8 +#define GDK_F9 GDK_KEY_F9 +#define GDK_F10 GDK_KEY_F10 +#define GDK_F11 GDK_KEY_F11 +#define GDK_F12 GDK_KEY_F12 +#endif + +static void +virt_viewer_window_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + VirtViewerWindowPrivate *priv = VIRT_VIEWER_WINDOW(object)->priv; + + switch (property_id) { + case PROP_SUBTITLE: + g_value_set_string(value, priv->subtitle); + break; + + case PROP_WINDOW: + g_value_set_object(value, priv->window); + break; + + case PROP_DISPLAY: + g_value_set_object(value, priv->display); + break; + + case PROP_CONTAINER: + g_value_set_object(value, priv->container); + break; + + case PROP_APP: + g_value_set_object(value, priv->app); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_window_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + VirtViewerWindowPrivate *priv = VIRT_VIEWER_WINDOW(object)->priv; + + switch (property_id) { + case PROP_SUBTITLE: + g_free(priv->subtitle); + priv->subtitle = g_value_dup_string(value); + break; + + case PROP_CONTAINER: + g_return_if_fail(priv->container == NULL); + priv->container = g_value_dup_object(value); + break; + + case PROP_APP: + g_return_if_fail(priv->app == NULL); + priv->app = g_value_dup_object(value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_window_dispose (GObject *object) +{ + VirtViewerWindowPrivate *priv = VIRT_VIEWER_WINDOW(object)->priv; + G_OBJECT_CLASS (virt_viewer_window_parent_class)->dispose (object); + + if (priv->display) { + g_object_unref(priv->display); + priv->display = NULL; + } + + if (priv->app) { + g_object_unref(priv->app); + priv->app = NULL; + } + + g_free(priv->subtitle); + priv->subtitle = NULL; +} + +static void +virt_viewer_window_class_init (VirtViewerWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (VirtViewerWindowPrivate)); + + object_class->get_property = virt_viewer_window_get_property; + object_class->set_property = virt_viewer_window_set_property; + object_class->dispose = virt_viewer_window_dispose; + + g_object_class_install_property(object_class, + PROP_SUBTITLE, + g_param_spec_string("subtitle", + "Subtitle", + "Window subtitle", + "", + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_WINDOW, + g_param_spec_object("window", + "Window", + "GtkWindow", + GTK_TYPE_WIDGET, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_DISPLAY, + g_param_spec_object("display", + "Display", + "VirtDisplay", + VIRT_VIEWER_TYPE_DISPLAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_CONTAINER, + g_param_spec_object("container", + "Container", + "Container widget", + VIRT_VIEWER_TYPE_DISPLAY, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(object_class, + PROP_APP, + g_param_spec_object("app", + "App", + "VirtViewerApp", + VIRT_VIEWER_TYPE_APP, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +virt_viewer_window_init (VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv; + GtkWidget *vbox; + GtkWidget *menu; + GdkColor color; + GSList *accels; + + self->priv = GET_PRIVATE(self); + priv = self->priv; + + priv->auto_resize = TRUE; + g_value_init(&priv->accel_setting, G_TYPE_STRING); + + priv->notebook = virt_viewer_notebook_new(); + priv->builder = virt_viewer_util_load_ui("virt-viewer.xml"); + + menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-view-resize")); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE); + + gtk_builder_connect_signals(priv->builder, self); + + vbox = GTK_WIDGET(gtk_builder_get_object(priv->builder, "viewer-box")); + virt_viewer_window_toolbar_setup(self); + + gtk_box_pack_end(GTK_BOX(vbox), priv->layout, TRUE, TRUE, 0); + gdk_color_parse("black", &color); + gtk_widget_modify_bg(priv->layout, GTK_STATE_NORMAL, &color); + + priv->window = GTK_WIDGET(gtk_builder_get_object(priv->builder, "viewer")); + + virt_viewer_window_update_title(self); + gtk_window_set_resizable(GTK_WINDOW(priv->window), TRUE); +#if GTK_CHECK_VERSION(3, 0, 0) + gtk_window_set_has_resize_grip(GTK_WINDOW(priv->window), FALSE); +#endif + priv->accel_enabled = TRUE; + + accels = gtk_accel_groups_from_object(G_OBJECT(priv->window)); + for ( ; accels ; accels = accels->next) { + priv->accel_list = g_slist_append(priv->accel_list, accels->data); + g_object_ref(G_OBJECT(accels->data)); + } +} + +static void +virt_viewer_window_desktop_resize(VirtViewerDisplay *display G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + if (priv->auto_resize && priv->window && !priv->fullscreen) + virt_viewer_window_resize(self); +} + + +void +virt_viewer_window_menu_view_zoom_out(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + + if (priv->zoomlevel > 10) + priv->zoomlevel -= 10; + + if (!priv->display) + return; + + gtk_window_resize(GTK_WINDOW(priv->window), 1, 1); + if (priv->display) + virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(priv->display), priv->zoomlevel); +} + +void +virt_viewer_window_menu_view_zoom_in(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + + if (priv->zoomlevel < 400) + priv->zoomlevel += 10; + + if (!priv->display) + return; + + gtk_window_resize(GTK_WINDOW(priv->window), 1, 1); + if (priv->display) + virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(priv->display), priv->zoomlevel); +} + +void +virt_viewer_window_menu_view_zoom_reset(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + gtk_window_resize(GTK_WINDOW(priv->window), 1, 1); + priv->zoomlevel = 100; + + if (priv->display) + virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(priv->display), priv->zoomlevel); +} + +/* + * This code attempts to resize the top level window to be large enough + * to contain the entire display desktop at 1:1 ratio. If the local desktop + * isn't large enough that it goes as large as possible and lets the display + * scale down to fit, maintaining aspect ratio + */ +static void +virt_viewer_window_resize(VirtViewerWindow *self) +{ + GdkRectangle fullscreen; + GdkScreen *screen; + int width, height; + double desktopAspect; + double screenAspect; + guint desktopWidth; + guint desktopHeight; + VirtViewerWindowPrivate *priv = self->priv; + + DEBUG_LOG("Preparing main window resize"); + if (!priv->display) { + DEBUG_LOG("Skipping inactive resize"); + return; + } + + gtk_window_resize(GTK_WINDOW(priv->window), 1, 1); + + virt_viewer_display_get_desktop_size(VIRT_VIEWER_DISPLAY(priv->display), + &desktopWidth, &desktopHeight); + + screen = gtk_widget_get_screen(priv->window); + gdk_screen_get_monitor_geometry(screen, + gdk_screen_get_monitor_at_window + (screen, gtk_widget_get_window(priv->window)), + &fullscreen); + + desktopAspect = (double)desktopWidth / (double)desktopHeight; + screenAspect = (double)(fullscreen.width - 128) / (double)(fullscreen.height - 128); + + if ((desktopWidth > (fullscreen.width - 128)) || + (desktopHeight > (fullscreen.height - 128))) { + /* Doesn't fit native res, so go as large as possible + maintaining aspect ratio */ + if (screenAspect > desktopAspect) { + width = desktopHeight * desktopAspect; + height = desktopHeight; + } else { + width = desktopWidth; + height = desktopWidth / desktopAspect; + } + } else { + width = desktopWidth; + height = desktopHeight; + } + + DEBUG_LOG("Decided todo %dx%d (desktop is %dx%d, fullscreen is %dx%d", + width, height, desktopWidth, desktopHeight, + fullscreen.width, fullscreen.height); + + virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(priv->display), + width, height); +} + +void +virt_viewer_window_leave_fullscreen(VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "top-menu")); + GtkCheckMenuItem *check = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(priv->builder, "menu-view-fullscreen")); + + if (!priv->fullscreen) + return; + + gtk_check_menu_item_set_active(check, FALSE); + priv->fullscreen = FALSE; + ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), FALSE); + gtk_widget_show(menu); + gtk_widget_hide(priv->toolbar); + gtk_window_unfullscreen(GTK_WINDOW(priv->window)); + + if (priv->before_saved) { + gtk_window_move(GTK_WINDOW(priv->window), + priv->before_fullscreen.x, + priv->before_fullscreen.y); + gtk_window_resize(GTK_WINDOW(priv->window), + priv->before_fullscreen.width, + priv->before_fullscreen.height); + priv->before_saved = FALSE; + } +} + +void +virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gboolean move, gint x, gint y) +{ + VirtViewerWindowPrivate *priv = self->priv; + GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "top-menu")); + GtkCheckMenuItem *check = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(priv->builder, "menu-view-fullscreen")); + + if (!priv->before_saved) { + gtk_window_get_position(GTK_WINDOW(priv->window), + &priv->before_fullscreen.x, + &priv->before_fullscreen.y); + gtk_window_get_size(GTK_WINDOW(priv->window), + &priv->before_fullscreen.width, + &priv->before_fullscreen.height); + priv->before_saved = TRUE; + } + + if (!priv->fullscreen) { + gtk_check_menu_item_set_active(check, TRUE); + priv->fullscreen = TRUE; + gtk_widget_hide(menu); + gtk_widget_show(priv->toolbar); + ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), TRUE); + ViewAutoDrawer_Close(VIEW_AUTODRAWER(priv->layout)); + } + + if (move) + gtk_window_move(GTK_WINDOW(priv->window), x, y); + + gtk_window_fullscreen(GTK_WINDOW(priv->window)); +} + +#define MAX_KEY_COMBO 3 +struct keyComboDef { + guint keys[MAX_KEY_COMBO]; + guint nkeys; + const char *label; +}; + +static const struct keyComboDef keyCombos[] = { + { { GDK_Control_L, GDK_Alt_L, GDK_Delete }, 3, "Ctrl+Alt+_Del"}, + { { GDK_Control_L, GDK_Alt_L, GDK_BackSpace }, 3, "Ctrl+Alt+_Backspace"}, + { {}, 0, "" }, + { { GDK_Control_L, GDK_Alt_L, GDK_F1 }, 3, "Ctrl+Alt+F_1"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F2 }, 3, "Ctrl+Alt+F_2"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F3 }, 3, "Ctrl+Alt+F_3"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F4 }, 3, "Ctrl+Alt+F_4"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F5 }, 3, "Ctrl+Alt+F_5"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F6 }, 3, "Ctrl+Alt+F_6"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F7 }, 3, "Ctrl+Alt+F_7"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F8 }, 3, "Ctrl+Alt+F_8"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F5 }, 3, "Ctrl+Alt+F_9"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F6 }, 3, "Ctrl+Alt+F1_0"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F7 }, 3, "Ctrl+Alt+F11"}, + { { GDK_Control_L, GDK_Alt_L, GDK_F8 }, 3, "Ctrl+Alt+F12"}, + { {}, 0, "" }, + { { GDK_Print }, 1, "_PrintScreen"}, +}; + +void +virt_viewer_window_menu_send(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + int i; + GtkWidget *label = gtk_bin_get_child(GTK_BIN(menu)); + const char *text = gtk_label_get_label(GTK_LABEL(label)); + VirtViewerWindowPrivate *priv = self->priv; + + for (i = 0 ; i < G_N_ELEMENTS(keyCombos) ; i++) { + if (!strcmp(text, keyCombos[i].label)) { + DEBUG_LOG("Sending key combo %s", gtk_label_get_text(GTK_LABEL(label))); + virt_viewer_display_send_keys(VIRT_VIEWER_DISPLAY(priv->display), + keyCombos[i].keys, + keyCombos[i].nkeys); + return; + } + } + DEBUG_LOG("Failed to find key combo %s", gtk_label_get_text(GTK_LABEL(label))); +} + +static gboolean +virt_viewer_window_ignore_accel(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self G_GNUC_UNUSED) +{ + /* ignore accelerator */ + return TRUE; +} + +static const char * const menuNames[LAST_MENU] = { + "menu-file", "menu-view", "menu-send", "menu-help" +}; + +void +virt_viewer_window_disable_modifiers(VirtViewerWindow *self) +{ + GtkSettings *settings = gtk_settings_get_default(); + VirtViewerWindowPrivate *priv = self->priv; + GValue empty; + GSList *accels; + int i; + + if (!priv->window) + return; + + if (!priv->accel_enabled) + return; + + /* This stops F10 activating menu bar */ + memset(&empty, 0, sizeof empty); + g_value_init(&empty, G_TYPE_STRING); + g_object_get_property(G_OBJECT(settings), "gtk-menu-bar-accel", &priv->accel_setting); + g_object_set_property(G_OBJECT(settings), "gtk-menu-bar-accel", &empty); + + /* This stops global accelerators like Ctrl+Q == Quit */ + for (accels = priv->accel_list ; accels ; accels = accels->next) { + gtk_window_remove_accel_group(GTK_WINDOW(priv->window), accels->data); + } + + /* This stops menu bar shortcuts like Alt+F == File */ + for (i = 0 ; i < LAST_MENU ; i++) { + GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, menuNames[i])); + priv->accel_menu_sig[i] = + g_signal_connect(menu, "mnemonic-activate", + G_CALLBACK(virt_viewer_window_ignore_accel), self); + } + + priv->accel_enabled = FALSE; +} + +void +virt_viewer_window_enable_modifiers(VirtViewerWindow *self) +{ + GtkSettings *settings = gtk_settings_get_default(); + VirtViewerWindowPrivate *priv = self->priv; + GSList *accels; + int i; + + if (!priv->window) + return; + + if (priv->accel_enabled) + return; + + /* This allows F10 activating menu bar */ + g_object_set_property(G_OBJECT(settings), "gtk-menu-bar-accel", &priv->accel_setting); + + /* This allows global accelerators like Ctrl+Q == Quit */ + for (accels = priv->accel_list ; accels ; accels = accels->next) { + gtk_window_add_accel_group(GTK_WINDOW(priv->window), accels->data); + } + + /* This allows menu bar shortcuts like Alt+F == File */ + for (i = 0 ; i < LAST_MENU ; i++) { + GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, menuNames[i])); + g_signal_handler_disconnect(menu, priv->accel_menu_sig[i]); + } + + priv->accel_enabled = TRUE; +} + + +gboolean +virt_viewer_window_delete(GtkWidget *src G_GNUC_UNUSED, + void *dummy G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + virt_viewer_app_window_set_visible(self->priv->app, self, FALSE); + return TRUE; +} + + +void +virt_viewer_window_menu_file_quit(GtkWidget *src G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + virt_viewer_app_quit(self->priv->app); +} + + +static void +virt_viewer_window_toolbar_leave_fullscreen(GtkWidget *button G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + g_object_set(self->priv->app, "fullscreen", FALSE, NULL); +} + + +void +virt_viewer_window_menu_view_fullscreen(GtkWidget *menu, + VirtViewerWindow *self) +{ + gboolean fullscreen = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu)); + + g_object_set(self->priv->app, "fullscreen", fullscreen, NULL); +} + +void +virt_viewer_window_menu_view_resize(GtkWidget *menu, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) { + priv->auto_resize = TRUE; + if (!priv->fullscreen) + virt_viewer_window_resize(self); + } else { + priv->auto_resize = FALSE; + } +} + +static void +virt_viewer_window_save_screenshot(VirtViewerWindow *self, + const char *file) +{ + VirtViewerWindowPrivate *priv = self->priv; + GdkPixbuf *pix = virt_viewer_display_get_pixbuf(VIRT_VIEWER_DISPLAY(priv->display)); + + gdk_pixbuf_save(pix, file, "png", NULL, + "tEXt::Generator App", PACKAGE, NULL); + gdk_pixbuf_unref(pix); +} + +void +virt_viewer_window_menu_file_screenshot(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + GtkWidget *dialog; + VirtViewerWindowPrivate *priv = self->priv; + + g_return_if_fail(priv->display != NULL); + + dialog = gtk_file_chooser_dialog_new ("Save screenshot", + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); + + //gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_folder_for_saving); + //gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "Screenshot"); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { + char *filename; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + virt_viewer_window_save_screenshot(self, filename); + g_free (filename); + } + + gtk_widget_destroy (dialog); +} + +void +virt_viewer_window_menu_help_about(GtkWidget *menu G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + GtkBuilder *about = virt_viewer_util_load_ui("virt-viewer-about.xml"); + + GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object(about, "about")); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), VERSION); + + gtk_builder_connect_signals(about, self); + + gtk_widget_show_all(dialog); + + g_object_unref(G_OBJECT(about)); +} + + +static void +virt_viewer_window_toolbar_setup(VirtViewerWindow *self) +{ + GtkWidget *button; + VirtViewerWindowPrivate *priv = self->priv; + + priv->toolbar = gtk_toolbar_new(); + gtk_toolbar_set_show_arrow(GTK_TOOLBAR(priv->toolbar), FALSE); + gtk_widget_set_no_show_all(priv->toolbar, TRUE); + gtk_toolbar_set_style(GTK_TOOLBAR(priv->toolbar), GTK_TOOLBAR_BOTH_HORIZ); + + /* Close connection */ + button = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_CLOSE)); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Disconnect")); + gtk_widget_show(GTK_WIDGET(button)); + gtk_toolbar_insert(GTK_TOOLBAR(priv->toolbar), GTK_TOOL_ITEM (button), 0); + g_signal_connect(button, "clicked", G_CALLBACK(gtk_main_quit), NULL); + + /* Leave fullscreen */ + button = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_LEAVE_FULLSCREEN)); + gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), _("Leave fullscreen")); + gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Leave fullscreen")); + gtk_tool_item_set_is_important(GTK_TOOL_ITEM(button), TRUE); + gtk_widget_show(GTK_WIDGET(button)); + gtk_toolbar_insert(GTK_TOOLBAR(priv->toolbar), GTK_TOOL_ITEM(button), 0); + g_signal_connect(button, "clicked", G_CALLBACK(virt_viewer_window_toolbar_leave_fullscreen), self); + + priv->layout = ViewAutoDrawer_New(); + + ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(priv->layout), FALSE); + ViewOvBox_SetOver(VIEW_OV_BOX(priv->layout), priv->toolbar); + ViewOvBox_SetUnder(VIEW_OV_BOX(priv->layout), GTK_WIDGET(priv->notebook)); + ViewAutoDrawer_SetOffset(VIEW_AUTODRAWER(priv->layout), -1); + ViewAutoDrawer_SetFill(VIEW_AUTODRAWER(priv->layout), FALSE); + ViewAutoDrawer_SetOverlapPixels(VIEW_AUTODRAWER(priv->layout), 1); + ViewAutoDrawer_SetNoOverlapPixels(VIEW_AUTODRAWER(priv->layout), 0); + gtk_widget_show(priv->layout); +} + +VirtViewerNotebook* +virt_viewer_window_get_notebook (VirtViewerWindow *self) +{ + return VIRT_VIEWER_NOTEBOOK(self->priv->notebook); +} + +GtkWindow* +virt_viewer_window_get_window (VirtViewerWindow *self) +{ + return GTK_WINDOW(self->priv->window); +} + +static void +virt_viewer_window_pointer_grab(VirtViewerDisplay *display G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + + priv->grabbed = TRUE; + virt_viewer_window_update_title(self); +} + +static void +virt_viewer_window_pointer_ungrab(VirtViewerDisplay *display G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + + priv->grabbed = FALSE; + virt_viewer_window_update_title(self); +} + +static void +virt_viewer_window_keyboard_grab(VirtViewerDisplay *display G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + virt_viewer_window_disable_modifiers(self); +} + +static void +virt_viewer_window_keyboard_ungrab(VirtViewerDisplay *display G_GNUC_UNUSED, + VirtViewerWindow *self) +{ + virt_viewer_window_enable_modifiers(self); +} + +void +virt_viewer_window_update_title(VirtViewerWindow *self) +{ + VirtViewerWindowPrivate *priv = self->priv; + char *title; + const char *subtitle; + + if (priv->grabbed) + subtitle = "(Press Ctrl+Alt to release pointer) "; + else + subtitle = ""; + + if (priv->subtitle) + title = g_strdup_printf("%s%s - Virt Viewer", + subtitle, priv->subtitle); + else + title = g_strdup("Virt Viewer"); + + gtk_window_set_title(GTK_WINDOW(priv->window), title); + + g_free(title); +} + +void +virt_viewer_window_set_display(VirtViewerWindow *self, VirtViewerDisplay *display) +{ + VirtViewerWindowPrivate *priv; + + g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self)); + g_return_if_fail(display == NULL || VIRT_VIEWER_IS_DISPLAY(display)); + + priv = self->priv; + if (priv->display) { + gtk_notebook_remove_page(GTK_NOTEBOOK(priv->notebook), 1); + g_object_unref(priv->display); + priv->display = NULL; + } + + if (display != NULL) { + priv->display = g_object_ref(display); + + gtk_notebook_append_page(GTK_NOTEBOOK(priv->notebook), GTK_WIDGET(display), NULL); + if (gtk_bin_get_child(GTK_BIN(display))) + gtk_widget_realize(GTK_WIDGET(gtk_bin_get_child(GTK_BIN(display)))); + gtk_widget_show_all(GTK_WIDGET(display)); + + g_signal_connect(display, "display-pointer-grab", + G_CALLBACK(virt_viewer_window_pointer_grab), self); + g_signal_connect(display, "display-pointer-ungrab", + G_CALLBACK(virt_viewer_window_pointer_ungrab), self); + g_signal_connect(display, "display-keyboard-grab", + G_CALLBACK(virt_viewer_window_keyboard_grab), self); + g_signal_connect(display, "display-keyboard-ungrab", + G_CALLBACK(virt_viewer_window_keyboard_ungrab), self); + g_signal_connect(display, "display-desktop-resize", + G_CALLBACK(virt_viewer_window_desktop_resize), self); + } +} + +void +virt_viewer_window_set_zoom_level(VirtViewerWindow *self, gint zoom_level) +{ + g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self)); + + /* FIXME: turn into a dynamic property */ + self->priv->zoomlevel = zoom_level; +} + +GtkMenuItem* +virt_viewer_window_get_menu_displays(VirtViewerWindow *self) +{ + g_return_val_if_fail(VIRT_VIEWER_IS_WINDOW(self), NULL); + return GTK_MENU_ITEM(gtk_builder_get_object(self->priv->builder, "menu-displays")); +} + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/src/virt-viewer-window.h b/src/virt-viewer-window.h new file mode 100644 index 0000000..d582d81 --- /dev/null +++ b/src/virt-viewer-window.h @@ -0,0 +1,82 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2009 Red Hat, + * Copyright (C) 2009 Daniel P. Berrange + * Copyright (C) 2010 Marc-André Lureau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ +#ifndef _VIRT_VIEWER_WINDOW +#define _VIRT_VIEWER_WINDOW + +#include +#include "virt-viewer-notebook.h" +#include "virt-viewer-display.h" + +G_BEGIN_DECLS + +#define VIRT_VIEWER_TYPE_WINDOW virt_viewer_window_get_type() + +#define VIRT_VIEWER_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIRT_VIEWER_TYPE_WINDOW, VirtViewerWindow)) + +#define VIRT_VIEWER_WINDOW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE_WINDOW, VirtViewerWindowClass)) + +#define VIRT_VIEWER_IS_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE_WINDOW)) + +#define VIRT_VIEWER_IS_WINDOW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE_WINDOW)) + +#define VIRT_VIEWER_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE_WINDOW, VirtViewerWindowClass)) + +typedef struct _VirtViewerWindowPrivate VirtViewerWindowPrivate; + +typedef struct { + GObject parent; + VirtViewerWindowPrivate *priv; +} VirtViewerWindow; + +typedef struct { + GObjectClass parent_class; +} VirtViewerWindowClass; + +GType virt_viewer_window_get_type (void); + +GtkWindow* virt_viewer_window_get_window (VirtViewerWindow* window); +VirtViewerNotebook* virt_viewer_window_get_notebook (VirtViewerWindow* window); +void virt_viewer_window_set_display(VirtViewerWindow *self, VirtViewerDisplay *display); +void virt_viewer_window_update_title(VirtViewerWindow *self); +void virt_viewer_window_set_zoom_level(VirtViewerWindow *self, gint zoom_level); +void virt_viewer_window_leave_fullscreen(VirtViewerWindow *self); +void virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gboolean move, gint x, gint y); +GtkMenuItem *virt_viewer_window_get_menu_displays(VirtViewerWindow *self); + +G_END_DECLS + +#endif /* _VIRT_VIEWER_WINDOW */ +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/src/virt-viewer.c b/src/virt-viewer.c index 5321580..364f30b 100644 --- a/src/virt-viewer.c +++ b/src/virt-viewer.c @@ -40,640 +40,96 @@ #include #include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#ifdef HAVE_SYS_UN_H -#include -#endif - -#ifdef HAVE_WINDOWS_H -#include -#endif - #include "virt-viewer.h" +#include "virt-viewer-app.h" #include "virt-viewer-events.h" #include "virt-viewer-auth.h" -#include "virt-viewer-session-vnc.h" - -#ifdef HAVE_SPICE_GTK -#include "virt-viewer-session-spice.h" -#endif - -#include "view/autoDrawer.h" - -gboolean doDebug = FALSE; - -/* Signal handlers for main window */ -void virt_viewer_menu_view_zoom_out(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_menu_view_zoom_in(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_menu_view_zoom_reset(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_delete(GtkWidget *src, void *dummy, VirtViewer *viewer); -void virt_viewer_menu_file_quit(GtkWidget *src, VirtViewer *viewer); -void virt_viewer_menu_help_about(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_menu_view_fullscreen(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_menu_view_resize(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_menu_send(GtkWidget *menu, VirtViewer *viewer); -void virt_viewer_menu_file_screenshot(GtkWidget *menu, VirtViewer *viewer); - -/* Signal handlers for about dialog */ -void virt_viewer_about_close(GtkWidget *dialog, VirtViewer *viewer); -void virt_viewer_about_delete(GtkWidget *dialog, void *dummy, VirtViewer *viewer); - - -/* Internal methods */ -static void virt_viewer_connected(VirtViewerSession *session, - VirtViewer *viewer); -static void virt_viewer_initialized(VirtViewerSession *session, - VirtViewer *viewer); -static void virt_viewer_disconnected(VirtViewerSession *session, - VirtViewer *viewer); -static void virt_viewer_auth_refused(VirtViewerSession *session, - const char *msg, - VirtViewer *viewer); -static void virt_viewer_auth_failed(VirtViewerSession *session, - const char *msg, - VirtViewer *viewer); - -static void virt_viewer_server_cut_text(VirtViewerSession *session, - const gchar *text, - VirtViewer *viewer); -static void virt_viewer_bell(VirtViewerSession *session, - VirtViewer *viewer); -static void virt_viewer_enable_modifiers(VirtViewer *viewer); -static void virt_viewer_disable_modifiers(VirtViewer *viewer); -static void virt_viewer_resize_main_window(VirtViewer *viewer); - -static void virt_viewer_set_status(VirtViewer *viewer, const char *text); -static void virt_viewer_set_title(VirtViewer *viewer, gboolean grabbed); -static void virt_viewer_channel_open(VirtViewerSession *session, - VirtViewerSessionChannel *channel, - VirtViewer *viewer); -static void virt_viewer_quit(VirtViewer *viewer); - -static void virt_viewer_simple_message_dialog(GtkWidget *window, const char *fmt, ...); - - -#if GTK_CHECK_VERSION(3, 0, 0) -#define GDK_Control_L GDK_KEY_Control_L -#define GDK_Alt_L GDK_KEY_Alt_L -#define GDK_Delete GDK_KEY_Delete -#define GDK_BackSpace GDK_KEY_BackSpace -#define GDK_Print GDK_KEY_Print -#define GDK_F1 GDK_KEY_F1 -#define GDK_F2 GDK_KEY_F2 -#define GDK_F3 GDK_KEY_F3 -#define GDK_F4 GDK_KEY_F4 -#define GDK_F5 GDK_KEY_F5 -#define GDK_F6 GDK_KEY_F6 -#define GDK_F7 GDK_KEY_F7 -#define GDK_F8 GDK_KEY_F8 -#define GDK_F9 GDK_KEY_F9 -#define GDK_F10 GDK_KEY_F10 -#define GDK_F11 GDK_KEY_F11 -#define GDK_F12 GDK_KEY_F12 -#endif - -enum menuNums { - FILE_MENU, - VIEW_MENU, - SEND_KEY_MENU, - HELP_MENU, - LAST_MENU // sentinel -}; - -struct _VirtViewer { + +struct _VirtViewerPrivate { char *uri; virConnectPtr conn; char *domkey; char *domtitle; - - GtkBuilder *builder; - GtkWidget *window; - GtkWidget *container; - - GtkWidget *notebook; - GtkWidget *status; - - GtkWidget *toolbar; - GtkWidget *layout; - - char *pretty_address; - - gboolean autoResize; - gboolean fullscreen; gboolean withEvents; - - gboolean active; - - gboolean accelEnabled; - GValue accelSetting; - GSList *accelList; - int accelMenuSig[LAST_MENU]; - gboolean waitvm; gboolean reconnect; - gboolean direct; - gboolean verbose; - gboolean authretry; - gboolean connected; - - gchar *clipboard; - - GtkWidget *display; - VirtViewerSession *session; - - gint zoomlevel; - - char *unixsock; - char *ghost; - char *gport; - char *host; - char *transport; - char *user; - int port; }; -static const char * const menuNames[LAST_MENU] = { - "menu-file", "menu-view", "menu-send", "menu-help" -}; - - -#define MAX_KEY_COMBO 3 -struct keyComboDef { - guint keys[MAX_KEY_COMBO]; - guint nkeys; - const char *label; -}; - -static const struct keyComboDef keyCombos[] = { - { { GDK_Control_L, GDK_Alt_L, GDK_Delete }, 3, "Ctrl+Alt+_Del"}, - { { GDK_Control_L, GDK_Alt_L, GDK_BackSpace }, 3, "Ctrl+Alt+_Backspace"}, - { {}, 0, "" }, - { { GDK_Control_L, GDK_Alt_L, GDK_F1 }, 3, "Ctrl+Alt+F_1"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F2 }, 3, "Ctrl+Alt+F_2"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F3 }, 3, "Ctrl+Alt+F_3"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F4 }, 3, "Ctrl+Alt+F_4"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F5 }, 3, "Ctrl+Alt+F_5"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F6 }, 3, "Ctrl+Alt+F_6"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F7 }, 3, "Ctrl+Alt+F_7"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F8 }, 3, "Ctrl+Alt+F_8"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F5 }, 3, "Ctrl+Alt+F_9"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F6 }, 3, "Ctrl+Alt+F1_0"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F7 }, 3, "Ctrl+Alt+F11"}, - { { GDK_Control_L, GDK_Alt_L, GDK_F8 }, 3, "Ctrl+Alt+F12"}, - { {}, 0, "" }, - { { GDK_Print }, 1, "_PrintScreen"}, -}; - - -static gboolean virt_viewer_connect_timer(void *opaque); -static int virt_viewer_initial_connect(VirtViewer *viewer); - - -void -virt_viewer_simple_message_dialog(GtkWidget *window, - const char *fmt, ...) -{ - GtkWidget *dialog; - char *msg; - va_list vargs; - - va_start(vargs, fmt); - - msg = g_strdup_vprintf(fmt, vargs); - - va_end(vargs); - - dialog = gtk_message_dialog_new(GTK_WINDOW(window), - GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", - msg); - - gtk_dialog_run(GTK_DIALOG(dialog)); - - gtk_widget_destroy(dialog); - - g_free(msg); -} - - -/* - * This code attempts to resize the top level window to be large enough - * to contain the entire display desktop at 1:1 ratio. If the local desktop - * isn't large enough that it goes as large as possible and lets the display - * scale down to fit, maintaining aspect ratio - */ -static void -virt_viewer_resize_main_window(VirtViewer *viewer) -{ - GdkRectangle fullscreen; - GdkScreen *screen; - int width, height; - double desktopAspect; - double screenAspect; - guint desktopWidth; - guint desktopHeight; - - DEBUG_LOG("Preparing main window resize"); - if (!viewer->active) { - DEBUG_LOG("Skipping inactive resize"); - return; - } - - gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1); - - virt_viewer_display_get_desktop_size(VIRT_VIEWER_DISPLAY(viewer->display), - &desktopWidth, &desktopHeight); - - screen = gtk_widget_get_screen(viewer->window); - gdk_screen_get_monitor_geometry(screen, - gdk_screen_get_monitor_at_window - (screen, gtk_widget_get_window(viewer->window)), - &fullscreen); - - desktopAspect = (double)desktopWidth / (double)desktopHeight; - screenAspect = (double)(fullscreen.width - 128) / (double)(fullscreen.height - 128); - - if ((desktopWidth > (fullscreen.width - 128)) || - (desktopHeight > (fullscreen.height - 128))) { - /* Doesn't fit native res, so go as large as possible - maintaining aspect ratio */ - if (screenAspect > desktopAspect) { - width = desktopHeight * desktopAspect; - height = desktopHeight; - } else { - width = desktopWidth; - height = desktopWidth / desktopAspect; +G_DEFINE_TYPE (VirtViewer, virt_viewer, VIRT_VIEWER_TYPE_APP) +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIRT_VIEWER_TYPE, VirtViewerPrivate)) + +static int virt_viewer_initial_connect(VirtViewerApp *self); +static void virt_viewer_deactivated(VirtViewerApp *self); +static gboolean virt_viewer_start(VirtViewerApp *self); + +static void +virt_viewer_get_property (GObject *object, guint property_id, + GValue *value G_GNUC_UNUSED, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_set_property (GObject *object, guint property_id, + const GValue *value G_GNUC_UNUSED, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +virt_viewer_dispose (GObject *object) +{ + G_OBJECT_CLASS(virt_viewer_parent_class)->dispose (object); +} + +static void +virt_viewer_class_init (VirtViewerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + VirtViewerAppClass *app_class = VIRT_VIEWER_APP_CLASS (klass); + + g_type_class_add_private (klass, sizeof (VirtViewerPrivate)); + + object_class->get_property = virt_viewer_get_property; + object_class->set_property = virt_viewer_set_property; + object_class->dispose = virt_viewer_dispose; + + app_class->initial_connect = virt_viewer_initial_connect; + app_class->deactivated = virt_viewer_deactivated; + app_class->start = virt_viewer_start; +} + +static void +virt_viewer_init(VirtViewer *self) +{ + self->priv = GET_PRIVATE(self); +} + +static void +virt_viewer_deactivated(VirtViewerApp *app) +{ + VirtViewer *self = VIRT_VIEWER(app); + VirtViewerPrivate *priv = self->priv; + + if (priv->reconnect) { + if (!priv->withEvents) { + DEBUG_LOG("No domain events, falling back to polling"); + virt_viewer_app_start_reconnect_poll(app); } + + virt_viewer_app_show_status(app, _("Waiting for guest domain to re-start")); + virt_viewer_app_trace(app, "Guest %s display has disconnected, waiting to reconnect", priv->domkey); } else { - width = desktopWidth; - height = desktopHeight; - } - - DEBUG_LOG("Decided todo %dx%d (desktop is %dx%d, fullscreen is %dx%d", - width, height, desktopWidth, desktopHeight, - fullscreen.width, fullscreen.height); - - virt_viewer_display_set_desktop_size(VIRT_VIEWER_DISPLAY(viewer->display), - width, height); -} - -static void -virt_viewer_desktop_resize(VirtViewerDisplay *display G_GNUC_UNUSED, - VirtViewer *viewer) -{ - if (viewer->autoResize && viewer->window && !viewer->fullscreen) - virt_viewer_resize_main_window(viewer); -} - - -void -virt_viewer_menu_view_zoom_out(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer) -{ - gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1); - if (viewer->zoomlevel > 10) - viewer->zoomlevel -= 10; - - if (viewer->display) - virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(viewer->display), viewer->zoomlevel); -} - -void -virt_viewer_menu_view_zoom_in(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer) -{ - gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1); - if (viewer->zoomlevel < 400) - viewer->zoomlevel += 10; - - if (viewer->display) - virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(viewer->display), viewer->zoomlevel); -} - -void -virt_viewer_menu_view_zoom_reset(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer) -{ - gtk_window_resize(GTK_WINDOW(viewer->window), 1, 1); - viewer->zoomlevel = 100; - - if (viewer->display) - virt_viewer_display_set_zoom_level(VIRT_VIEWER_DISPLAY(viewer->display), viewer->zoomlevel); -} - -void -virt_viewer_set_title(VirtViewer *viewer, - gboolean grabbed) -{ - char *title; - const char *subtitle; - - if (!viewer->window) - return; - - if (grabbed) - subtitle = "(Press Ctrl+Alt to release pointer) "; - else - subtitle = ""; - - if (viewer->domtitle) - title = g_strdup_printf("%s%s - Virt Viewer", - subtitle, viewer->domtitle); - else - title = g_strdup("Virt Viewer"); - - gtk_window_set_title(GTK_WINDOW(viewer->window), title); - - g_free(title); -} - -static gboolean -virt_viewer_ignore_accel(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer G_GNUC_UNUSED) -{ - /* ignore accelerator */ - return TRUE; -} - - -void -virt_viewer_disable_modifiers(VirtViewer *viewer) -{ - GtkSettings *settings = gtk_settings_get_default(); - GValue empty; - GSList *accels; - int i; - - if (!viewer->window) - return; - - if (!viewer->accelEnabled) - return; - - /* This stops F10 activating menu bar */ - memset(&empty, 0, sizeof empty); - g_value_init(&empty, G_TYPE_STRING); - g_object_get_property(G_OBJECT(settings), "gtk-menu-bar-accel", &viewer->accelSetting); - g_object_set_property(G_OBJECT(settings), "gtk-menu-bar-accel", &empty); - - /* This stops global accelerators like Ctrl+Q == Quit */ - for (accels = viewer->accelList ; accels ; accels = accels->next) { - gtk_window_remove_accel_group(GTK_WINDOW(viewer->window), accels->data); - } - - /* This stops menu bar shortcuts like Alt+F == File */ - for (i = 0 ; i < LAST_MENU ; i++) { - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(viewer->builder, menuNames[i])); - viewer->accelMenuSig[i] = - g_signal_connect(menu, "mnemonic-activate", - G_CALLBACK(virt_viewer_ignore_accel), viewer); - } - - viewer->accelEnabled = FALSE; -} - - -void -virt_viewer_enable_modifiers(VirtViewer *viewer) -{ - GtkSettings *settings = gtk_settings_get_default(); - GSList *accels; - int i; - - if (!viewer->window) - return; - - if (viewer->accelEnabled) - return; - - /* This allows F10 activating menu bar */ - g_object_set_property(G_OBJECT(settings), "gtk-menu-bar-accel", &viewer->accelSetting); - - /* This allows global accelerators like Ctrl+Q == Quit */ - for (accels = viewer->accelList ; accels ; accels = accels->next) { - gtk_window_add_accel_group(GTK_WINDOW(viewer->window), accels->data); - } - - /* This allows menu bar shortcuts like Alt+F == File */ - for (i = 0 ; i < LAST_MENU ; i++) { - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(viewer->builder, menuNames[i])); - g_signal_handler_disconnect(menu, viewer->accelMenuSig[i]); - } - - viewer->accelEnabled = TRUE; -} - -void -virt_viewer_quit(VirtViewer *viewer) -{ - g_return_if_fail(viewer != NULL); - - if (viewer->session) - virt_viewer_session_close(VIRT_VIEWER_SESSION(viewer->session)); - gtk_main_quit(); -} - -void -virt_viewer_delete(GtkWidget *src G_GNUC_UNUSED, - void *dummy G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_quit(viewer); -} - -void -virt_viewer_menu_file_quit(GtkWidget *src G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_quit(viewer); -} - - -static void -virt_viewer_leave_fullscreen(VirtViewer *viewer) -{ - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "top-menu")); - if (!viewer->fullscreen) - return; - viewer->fullscreen = FALSE; - ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(viewer->layout), FALSE); - gtk_widget_show(menu); - gtk_widget_hide(viewer->toolbar); - gtk_window_unfullscreen(GTK_WINDOW(viewer->window)); - if (viewer->autoResize) - virt_viewer_resize_main_window(viewer); -} - -static void -virt_viewer_enter_fullscreen(VirtViewer *viewer) -{ - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "top-menu")); - if (viewer->fullscreen) - return; - viewer->fullscreen = TRUE; - gtk_widget_hide(menu); - gtk_window_fullscreen(GTK_WINDOW(viewer->window)); - gtk_widget_show(viewer->toolbar); - ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(viewer->layout), TRUE); -} - -static gboolean -window_state_cb(GtkWidget *widget G_GNUC_UNUSED, GdkEventWindowState *event, - gpointer data) -{ - VirtViewer *viewer = data; - - if (!(event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)) - return TRUE; - - if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) - virt_viewer_enter_fullscreen(viewer); - else - virt_viewer_leave_fullscreen(viewer); - - return TRUE; -} - -static void -virt_viewer_toolbar_leave_fullscreen(GtkWidget *button G_GNUC_UNUSED, - VirtViewer *viewer) -{ - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "menu-view-fullscreen")); - - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE); - virt_viewer_leave_fullscreen(viewer); -} - - -void -virt_viewer_menu_view_fullscreen(GtkWidget *menu, - VirtViewer *viewer) -{ - if (!viewer->window) - return; - - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) { - virt_viewer_enter_fullscreen(viewer); - } else { - virt_viewer_leave_fullscreen(viewer); - } -} - -void -virt_viewer_menu_view_resize(GtkWidget *menu, - VirtViewer *viewer) -{ - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) { - viewer->autoResize = TRUE; - if (!viewer->fullscreen) - virt_viewer_resize_main_window(viewer); - } else { - viewer->autoResize = FALSE; - } -} - -void -virt_viewer_menu_send(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer) -{ - int i; - GtkWidget *label = gtk_bin_get_child(GTK_BIN(menu)); - const char *text = gtk_label_get_label(GTK_LABEL(label)); - - for (i = 0 ; i < G_N_ELEMENTS(keyCombos) ; i++) { - if (!strcmp(text, keyCombos[i].label)) { - DEBUG_LOG("Sending key combo %s", gtk_label_get_text(GTK_LABEL(label))); - virt_viewer_display_send_keys(VIRT_VIEWER_DISPLAY(viewer->display), - keyCombos[i].keys, - keyCombos[i].nkeys); - return; - } - } - DEBUG_LOG("Failed to find key combo %s", gtk_label_get_text(GTK_LABEL(label))); -} - - -static void -virt_viewer_save_screenshot(VirtViewer *viewer, - const char *file) -{ - GdkPixbuf *pix = virt_viewer_display_get_pixbuf(VIRT_VIEWER_DISPLAY(viewer->display)); - gdk_pixbuf_save(pix, file, "png", NULL, - "tEXt::Generator App", PACKAGE, NULL); - gdk_pixbuf_unref(pix); -} - - -void -virt_viewer_menu_file_screenshot(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer) -{ - GtkWidget *dialog; - - g_return_if_fail(viewer->display != NULL); - - dialog = gtk_file_chooser_dialog_new ("Save screenshot", - NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); - - //gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_folder_for_saving); - //gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "Screenshot"); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - char *filename; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); - virt_viewer_save_screenshot(viewer, filename); - g_free (filename); - } - - gtk_widget_destroy (dialog); -} - -void -virt_viewer_about_close(GtkWidget *dialog, - VirtViewer *viewer G_GNUC_UNUSED) -{ - gtk_widget_hide(dialog); - gtk_widget_destroy(dialog); -} - -void -virt_viewer_about_delete(GtkWidget *dialog, - void *dummy G_GNUC_UNUSED, - VirtViewer *viewer G_GNUC_UNUSED) -{ - gtk_widget_hide(dialog); - gtk_widget_destroy(dialog); -} - -void -virt_viewer_menu_help_about(GtkWidget *menu G_GNUC_UNUSED, - VirtViewer *viewer) -{ - GtkBuilder *about = virt_viewer_util_load_ui("virt-viewer-about.xml"); - - GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object(about, "about")); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), VERSION); - - gtk_builder_connect_signals(about, viewer); - - gtk_widget_show_all(dialog); - - g_object_unref(G_OBJECT(about)); -} - + VIRT_VIEWER_APP_CLASS(virt_viewer_parent_class)->deactivated(app); + } +} static int virt_viewer_parse_uuid(const char *name, @@ -719,32 +175,34 @@ static virDomainPtr -virt_viewer_lookup_domain(VirtViewer *viewer) +virt_viewer_lookup_domain(VirtViewer *self) { char *end; - int id = strtol(viewer->domkey, &end, 10); + VirtViewerPrivate *priv = self->priv; + int id = strtol(priv->domkey, &end, 10); virDomainPtr dom = NULL; unsigned char uuid[16]; if (id >= 0 && end && !*end) { - dom = virDomainLookupByID(viewer->conn, id); - } - if (!dom && virt_viewer_parse_uuid(viewer->domkey, uuid) == 0) { - dom = virDomainLookupByUUID(viewer->conn, uuid); + dom = virDomainLookupByID(priv->conn, id); + } + if (!dom && virt_viewer_parse_uuid(priv->domkey, uuid) == 0) { + dom = virDomainLookupByUUID(priv->conn, uuid); } if (!dom) { - dom = virDomainLookupByName(viewer->conn, viewer->domkey); + dom = virDomainLookupByName(priv->conn, priv->domkey); } return dom; } static int -virt_viewer_matches_domain(VirtViewer *viewer, +virt_viewer_matches_domain(VirtViewer *self, virDomainPtr dom) { char *end; const char *name; - int id = strtol(viewer->domkey, &end, 10); + VirtViewerPrivate *priv = self->priv; + int id = strtol(priv->domkey, &end, 10); unsigned char wantuuid[16]; unsigned char domuuid[16]; @@ -752,14 +210,14 @@ if (virDomainGetID(dom) == id) return 1; } - if (virt_viewer_parse_uuid(viewer->domkey, wantuuid) == 0) { + if (virt_viewer_parse_uuid(priv->domkey, wantuuid) == 0) { virDomainGetUUID(dom, domuuid); if (memcmp(wantuuid, domuuid, VIR_UUID_BUFLEN) == 0) return 1; } name = virDomainGetName(dom); - if (strcmp(name, viewer->domkey) == 0) + if (strcmp(name, priv->domkey) == 0) return 1; return 0; @@ -811,625 +269,96 @@ return port; } - -static int -virt_viewer_extract_host(const char *uristr, - char **host, - char **transport, - char **user, - int *port) -{ - xmlURIPtr uri; - char *offset; - - *host = NULL; - *transport = NULL; - *user = NULL; - - if (uristr == NULL || - !g_strcasecmp(uristr, "xen")) - uristr = "xen:///"; - - uri = xmlParseURI(uristr); - if (!uri || !uri->server) { - *host = g_strdup("localhost"); - } else { - *host = g_strdup(uri->server); - } - - if (uri->user) - *user = g_strdup(uri->user); - *port = uri->port; - - offset = strchr(uri->scheme, '+'); - if (offset) - *transport = g_strdup(offset+1); - - xmlFreeURI(uri); - return 0; -} - -#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) - -static int -virt_viewer_open_tunnel(const char **cmd) -{ - int fd[2]; - pid_t pid; - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) < 0) - return -1; - - pid = fork(); - if (pid == -1) { - close(fd[0]); - close(fd[1]); - return -1; - } - - if (pid == 0) { /* child */ - close(fd[0]); - close(0); - close(1); - if (dup(fd[1]) < 0) - _exit(1); - if (dup(fd[1]) < 0) - _exit(1); - close(fd[1]); - execvp("ssh", (char *const*)cmd); - _exit(1); - } - close(fd[1]); - return fd[0]; -} - - -static int -virt_viewer_open_tunnel_ssh(const char *sshhost, - int sshport, - const char *sshuser, - const char *host, - const char *port, - const char *unixsock) -{ - const char *cmd[10]; - char portstr[50]; - int n = 0; - - if (!sshport) - sshport = 22; - - sprintf(portstr, "%d", sshport); - - cmd[n++] = "ssh"; - cmd[n++] = "-p"; - cmd[n++] = portstr; - if (sshuser) { - cmd[n++] = "-l"; - cmd[n++] = sshuser; - } - cmd[n++] = sshhost; - cmd[n++] = "nc"; - if (port) { - cmd[n++] = host; - cmd[n++] = port; - } else { - cmd[n++] = "-U"; - cmd[n++] = unixsock; - } - cmd[n++] = NULL; - - return virt_viewer_open_tunnel(cmd); -} - -static int -virt_viewer_open_unix_sock(const char *unixsock) -{ - struct sockaddr_un addr; - int fd; - - memset(&addr, 0, sizeof addr); - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, unixsock); - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return -1; - - if (connect(fd, (struct sockaddr *)&addr, sizeof addr) < 0) { - close(fd); - return -1; - } - - return fd; -} - -#endif /* defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) */ - -static void -virt_viewer_trace(VirtViewer *viewer, - const char *fmt, ...) -{ - va_list ap; - - if (doDebug) { - va_start(ap, fmt); - g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, fmt, ap); - va_end(ap); - } - - if (viewer->verbose) { - va_start(ap, fmt); - g_vprintf(fmt, ap); - va_end(ap); - } -} - - -void -virt_viewer_set_status(VirtViewer *viewer, - const char *text) -{ - gtk_notebook_set_current_page(GTK_NOTEBOOK(viewer->notebook), 0); - gtk_label_set_text(GTK_LABEL(viewer->status), text); -} - - -static void -virt_viewer_show_display(VirtViewer *viewer) -{ - g_return_if_fail(viewer != NULL); - g_return_if_fail(viewer->display != NULL); - - gtk_widget_grab_focus(gtk_bin_get_child(GTK_BIN(viewer->display))); - gtk_notebook_set_current_page(GTK_NOTEBOOK(viewer->notebook), 1); -} - -static void -virt_viewer_pointer_grab(VirtViewerDisplay *display G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_set_title(viewer, TRUE); -} - -static void -virt_viewer_pointer_ungrab(VirtViewerDisplay *display G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_set_title(viewer, FALSE); -} - -static void -virt_viewer_keyboard_grab(VirtViewerDisplay *display G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_disable_modifiers(viewer); -} - -static void -virt_viewer_keyboard_ungrab(VirtViewerDisplay *display G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_enable_modifiers(viewer); -} - - -static void -virt_viewer_display_added(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewerDisplay *display, - VirtViewer *viewer) -{ - /* XXX multihead */ - if (viewer->display) - return; - viewer->display = GTK_WIDGET(display); - - g_signal_connect(viewer->display, "display-pointer-grab", - G_CALLBACK(virt_viewer_pointer_grab), viewer); - g_signal_connect(viewer->display, "display-pointer-ungrab", - G_CALLBACK(virt_viewer_pointer_ungrab), viewer); - g_signal_connect(viewer->display, "display-keyboard-grab", - G_CALLBACK(virt_viewer_keyboard_grab), viewer); - g_signal_connect(viewer->display, "display-keyboard-ungrab", - G_CALLBACK(virt_viewer_keyboard_ungrab), viewer); - - g_signal_connect(viewer->display, "display-desktop-resize", - G_CALLBACK(virt_viewer_desktop_resize), viewer); - - gtk_notebook_append_page(GTK_NOTEBOOK(viewer->notebook), viewer->display, NULL); - if (gtk_bin_get_child(GTK_BIN(viewer->display))) - gtk_widget_realize(GTK_WIDGET(gtk_bin_get_child(GTK_BIN(viewer->display)))); - gtk_widget_show_all(viewer->display); -} - -static void -virt_viewer_display_removed(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewerDisplay *display, - VirtViewer *viewer) -{ - /* XXX multihead */ - if (viewer->display != GTK_WIDGET(display)) - return; - - gtk_widget_hide(GTK_WIDGET(display)); - gtk_notebook_remove_page(GTK_NOTEBOOK(viewer->notebook), 1); - viewer->display = NULL; -} - -static void -virt_viewer_connect_info_free(VirtViewer *viewer) -{ - free(viewer->host); - free(viewer->ghost); - free(viewer->gport); - free(viewer->transport); - free(viewer->user); - free(viewer->unixsock); - - viewer->host = NULL; - viewer->ghost = NULL; - viewer->gport = NULL; - viewer->transport = NULL; - viewer->user = NULL; - viewer->unixsock = NULL; - viewer->port = 0; -} - static gboolean -virt_viewer_extract_connect_info(VirtViewer *viewer, +virt_viewer_extract_connect_info(VirtViewer *self, virDomainPtr dom) { char *type = NULL; char *xpath = NULL; gboolean retval = FALSE; char *xmldesc = virDomainGetXMLDesc(dom, 0); - - virt_viewer_connect_info_free(viewer); + VirtViewerPrivate *priv = self->priv; + VirtViewerApp *app = VIRT_VIEWER_APP(self); + gchar *gport = NULL; + gchar *ghost = NULL; + gchar *unixsock = NULL; + gchar *host = NULL; + gchar *transport = NULL; + gchar *user = NULL; + gint port = 0; + + virt_viewer_app_free_connect_info(app); if ((type = virt_viewer_extract_xpath_string(xmldesc, "string(/domain/devices/graphics/@type)")) == NULL) { - virt_viewer_simple_message_dialog(viewer->window, _("Cannot determine the graphic type for the guest %s"), - viewer->domkey); + virt_viewer_app_simple_message_dialog(app, _("Cannot determine the graphic type for the guest %s"), + priv->domkey); goto cleanup; } - if (g_strcasecmp(type, "vnc") == 0) { - virt_viewer_trace(viewer, "Guest %s has a %s display\n", - viewer->domkey, type); - viewer->session = virt_viewer_session_vnc_new(); -#ifdef HAVE_SPICE_GTK - } else if (g_strcasecmp(type, "spice") == 0) { - virt_viewer_trace(viewer, "Guest %s has a %s display\n", - viewer->domkey, type); - viewer->session = virt_viewer_session_spice_new(); -#endif - } else { - virt_viewer_trace(viewer, "Guest %s has unsupported %s display type\n", - viewer->domkey, type); - virt_viewer_simple_message_dialog(viewer->window, _("Unknown graphic type for the guest %s"), - viewer->domkey); + if (virt_viewer_app_create_session(app, type) < 0) goto cleanup; - } - - g_signal_connect(viewer->session, "session-initialized", - G_CALLBACK(virt_viewer_initialized), viewer); - g_signal_connect(viewer->session, "session-connected", - G_CALLBACK(virt_viewer_connected), viewer); - g_signal_connect(viewer->session, "session-disconnected", - G_CALLBACK(virt_viewer_disconnected), viewer); - g_signal_connect(viewer->session, "session-channel-open", - G_CALLBACK(virt_viewer_channel_open), viewer); - g_signal_connect(viewer->session, "session-auth-refused", - G_CALLBACK(virt_viewer_auth_refused), viewer); - g_signal_connect(viewer->session, "session-auth-failed", - G_CALLBACK(virt_viewer_auth_failed), viewer); - g_signal_connect(viewer->session, "session-display-added", - G_CALLBACK(virt_viewer_display_added), viewer); - g_signal_connect(viewer->session, "session-display-removed", - G_CALLBACK(virt_viewer_display_removed), viewer); - - g_signal_connect(viewer->session, "session-cut-text", - G_CALLBACK(virt_viewer_server_cut_text), viewer); - g_signal_connect(viewer->session, "session-bell", - G_CALLBACK(virt_viewer_bell), viewer); xpath = g_strdup_printf("string(/domain/devices/graphics[@type='%s']/@port)", type); - if ((viewer->gport = virt_viewer_extract_xpath_string(xmldesc, xpath)) == NULL) { + if ((gport = virt_viewer_extract_xpath_string(xmldesc, xpath)) == NULL) { free(xpath); xpath = g_strdup_printf("string(/domain/devices/graphics[@type='%s']/@socket)", type); - if ((viewer->unixsock = virt_viewer_extract_xpath_string(xmldesc, xpath)) == NULL) { - virt_viewer_simple_message_dialog(viewer->window, _("Cannot determine the graphic address for the guest %s"), - viewer->domkey); + if ((unixsock = virt_viewer_extract_xpath_string(xmldesc, xpath)) == NULL) { + virt_viewer_app_simple_message_dialog(app, _("Cannot determine the graphic address for the guest %s"), + priv->domkey); goto cleanup; } } else { free(xpath); xpath = g_strdup_printf("string(/domain/devices/graphics[@type='%s']/@listen)", type); - viewer->ghost = virt_viewer_extract_xpath_string(xmldesc, xpath); - if (viewer->ghost == NULL) - viewer->ghost = g_strdup("localhost"); - } - - if (viewer->gport) - DEBUG_LOG("Guest graphics address is %s:%s", viewer->ghost, viewer->gport); + ghost = virt_viewer_extract_xpath_string(xmldesc, xpath); + if (ghost == NULL) + ghost = g_strdup("localhost"); + } + + if (gport) + DEBUG_LOG("Guest graphics address is %s:%s", ghost, gport); else - DEBUG_LOG("Guest graphics address is %s", viewer->unixsock); - - if (virt_viewer_extract_host(viewer->uri, &viewer->host, &viewer->transport, &viewer->user, &viewer->port) < 0) { - virt_viewer_simple_message_dialog(viewer->window, _("Cannot determine the host for the guest %s"), - viewer->domkey); + DEBUG_LOG("Guest graphics address is %s", unixsock); + + if (virt_viewer_util_extract_host(priv->uri, NULL, &host, &transport, &user, &port) < 0) { + virt_viewer_app_simple_message_dialog(app, _("Cannot determine the host for the guest %s"), + priv->domkey); goto cleanup; } + virt_viewer_app_set_connect_info(app, host, ghost, gport, transport, unixsock, user, port); + retval = TRUE; -cleanup: + cleanup: + g_free(gport); + g_free(ghost); + g_free(unixsock); + g_free(host); + g_free(transport); + g_free(user); g_free(type); g_free(xpath); g_free(xmldesc); return retval; } -#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) -static void -virt_viewer_channel_open(VirtViewerSession *session, - VirtViewerSessionChannel *channel, - VirtViewer *viewer) -{ - int fd = -1; - - g_return_if_fail(viewer != NULL); - - if (viewer->transport && g_strcasecmp(viewer->transport, "ssh") == 0 && - !viewer->direct) { - if ((fd = virt_viewer_open_tunnel_ssh(viewer->host, viewer->port, viewer->user, - viewer->ghost, viewer->gport, NULL)) < 0) - virt_viewer_simple_message_dialog(viewer->window, _("Connect to ssh failed.")); - } else { - virt_viewer_simple_message_dialog(viewer->window, _("Can't connect to channel, SSH only supported.")); - } - - if (fd >= 0) - virt_viewer_session_channel_open_fd(session, channel, fd); -} -#else -static void -virt_viewer_channel_open(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewerSessionChannel *channel G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_simple_message_dialog(viewer->window, _("Connect to channel unsupported.")); -} -#endif - static int -virt_viewer_activate(VirtViewer *viewer, - virDomainPtr dom) -{ - int fd = -1; - int ret = -1; - - if (viewer->active) - goto cleanup; - - virt_viewer_trace(viewer, "Guest %s is running, determining display\n", - viewer->domkey); - if (viewer->session == NULL) { - if (!virt_viewer_extract_connect_info(viewer, dom)) - goto cleanup; - - if (viewer->gport) - viewer->pretty_address = g_strdup_printf("%s:%s", viewer->ghost, viewer->gport); - else - viewer->pretty_address = g_strdup_printf("%s:%s", viewer->host, viewer->unixsock); - } - -#if defined(HAVE_SOCKETPAIR) && defined(HAVE_FORK) - if (viewer->transport && - g_strcasecmp(viewer->transport, "ssh") == 0 && - !viewer->direct) { - if (viewer->gport) { - virt_viewer_trace(viewer, "Opening indirect TCP connection to display at %s:%s\n", - viewer->ghost, viewer->gport); - } else { - virt_viewer_trace(viewer, "Opening indirect UNIX connection to display at %s\n", - viewer->unixsock); - } - virt_viewer_trace(viewer, "Setting up SSH tunnel via %s@%s:%d\n", - viewer->user, viewer->host, viewer->port ? viewer->port : 22); - - if ((fd = virt_viewer_open_tunnel_ssh(viewer->host, viewer->port, - viewer->user, viewer->ghost, - viewer->gport, viewer->unixsock)) < 0) +virt_viewer_update_display(VirtViewer *self, virDomainPtr dom) +{ + VirtViewerPrivate *priv = self->priv; + VirtViewerApp *app = VIRT_VIEWER_APP(self); + + virt_viewer_app_trace(app, "Guest %s is running, determining display\n", + priv->domkey); + + if (!virt_viewer_app_has_session(app)) { + if (!virt_viewer_extract_connect_info(self, dom)) return -1; - } else if (viewer->unixsock) { - virt_viewer_trace(viewer, "Opening direct UNIX connection to display at %s", - viewer->unixsock); - if ((fd = virt_viewer_open_unix_sock(viewer->unixsock)) < 0) - return -1; - } -#endif - - if (fd >= 0) { - ret = virt_viewer_session_open_fd(VIRT_VIEWER_SESSION(viewer->session), fd); - } else { - virt_viewer_trace(viewer, "Opening direct TCP connection to display at %s:%s\n", - viewer->ghost, viewer->gport); - ret = virt_viewer_session_open_host(VIRT_VIEWER_SESSION(viewer->session), - viewer->ghost, viewer->gport); - } - - virt_viewer_set_status(viewer, "Connecting to graphic server"); - - viewer->connected = FALSE; - viewer->active = TRUE; - virt_viewer_set_title(viewer, FALSE); - -cleanup: - return ret; -} - -/* text was actually requested */ -static void -virt_viewer_clipboard_copy(GtkClipboard *clipboard G_GNUC_UNUSED, - GtkSelectionData *data, - guint info G_GNUC_UNUSED, - VirtViewer *viewer) -{ - gtk_selection_data_set_text(data, viewer->clipboard, -1); -} - -static void -virt_viewer_server_cut_text(VirtViewerSession *session G_GNUC_UNUSED, - const gchar *text, - VirtViewer *viewer) -{ - GtkClipboard *cb; - gsize a, b; - GtkTargetEntry targets[] = { - {g_strdup("UTF8_STRING"), 0, 0}, - {g_strdup("COMPOUND_TEXT"), 0, 0}, - {g_strdup("TEXT"), 0, 0}, - {g_strdup("STRING"), 0, 0}, - }; - - if (!text) - return; - - g_free (viewer->clipboard); - viewer->clipboard = g_convert (text, -1, "utf-8", "iso8859-1", &a, &b, NULL); - - if (viewer->clipboard) { - cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - - gtk_clipboard_set_with_owner (cb, - targets, - G_N_ELEMENTS(targets), - (GtkClipboardGetFunc)virt_viewer_clipboard_copy, - NULL, - G_OBJECT (viewer)); - } -} - - -static void virt_viewer_bell(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewer *viewer) -{ - gdk_window_beep(gtk_widget_get_window(GTK_WIDGET(viewer->window))); -} - - -static gboolean -virt_viewer_retryauth(gpointer opaque) -{ - VirtViewer *viewer = opaque; - virt_viewer_initial_connect(viewer); - - return FALSE; -} - -static void -virt_viewer_deactivate(VirtViewer *viewer) -{ - if (!viewer->active) - return; - - if (viewer->session) - virt_viewer_session_close(VIRT_VIEWER_SESSION(viewer->session)); - - viewer->connected = FALSE; - viewer->active = FALSE; -#if 0 - g_free(viewer->pretty_address); - viewer->pretty_address = NULL; -#endif - virt_viewer_set_title(viewer, FALSE); - - if (viewer->authretry) { - viewer->authretry = FALSE; - g_idle_add(virt_viewer_retryauth, viewer); - } else if (viewer->reconnect) { - if (!viewer->withEvents) { - DEBUG_LOG("No domain events, falling back to polling"); - g_timeout_add(500, - virt_viewer_connect_timer, - viewer); - } - - virt_viewer_set_status(viewer, "Waiting for guest domain to re-start"); - virt_viewer_trace(viewer, "Guest %s display has disconnected, waiting to reconnect", - viewer->domkey); - } else { - virt_viewer_set_status(viewer, "Guest domain has shutdown"); - virt_viewer_trace(viewer, "Guest %s display has disconnected, shutting down", - viewer->domkey); - gtk_main_quit(); - } -} - -static void -virt_viewer_connected(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewer *viewer) -{ - viewer->connected = TRUE; - virt_viewer_set_status(viewer, "Connected to graphic server"); -} - -static void -virt_viewer_initialized(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewer *viewer) -{ - virt_viewer_show_display(viewer); - virt_viewer_set_title(viewer, FALSE); -} - -static void -virt_viewer_disconnected(VirtViewerSession *session G_GNUC_UNUSED, - VirtViewer *viewer) -{ - if (!viewer->connected) { - virt_viewer_simple_message_dialog(viewer->window, - _("Unable to connect to the graphic server %s"), - viewer->pretty_address); - } - virt_viewer_deactivate(viewer); -} - - -static void virt_viewer_auth_refused(VirtViewerSession *session G_GNUC_UNUSED, - const char *msg, - VirtViewer *viewer) -{ - GtkWidget *dialog; - int ret; - - dialog = gtk_message_dialog_new(GTK_WINDOW(viewer->window), - GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_YES_NO, - _("Unable to authenticate with remote desktop server at %s: %s\n" - "Retry connection again?"), - viewer->pretty_address, msg); - - ret = gtk_dialog_run(GTK_DIALOG(dialog)); - - gtk_widget_destroy(dialog); - - if (ret == GTK_RESPONSE_YES) - viewer->authretry = TRUE; - else - viewer->authretry = FALSE; -} - - -static void virt_viewer_auth_failed(VirtViewerSession *session G_GNUC_UNUSED, - const char *msg, - VirtViewer *viewer) -{ - virt_viewer_simple_message_dialog(viewer->window, - _("Unable to authenticate with remote desktop server at %s"), - viewer->pretty_address, msg); -} - + } + + return 0; +} static int virt_viewer_domain_event(virConnectPtr conn G_GNUC_UNUSED, @@ -1438,68 +367,73 @@ int detail G_GNUC_UNUSED, void *opaque) { - VirtViewer *viewer = opaque; + VirtViewer *self = opaque; + VirtViewerApp *app = VIRT_VIEWER_APP(self); DEBUG_LOG("Got domain event %d %d", event, detail); - if (!virt_viewer_matches_domain(viewer, dom)) + if (!virt_viewer_matches_domain(self, dom)) return 0; - + switch (event) { case VIR_DOMAIN_EVENT_STOPPED: - //virt_viewer_deactivate(viewer); + //virt_viewer_deactivate(self); break; case VIR_DOMAIN_EVENT_STARTED: - virt_viewer_activate(viewer, dom); + virt_viewer_update_display(self, dom); + virt_viewer_app_activate(app); break; } return 0; } - static int -virt_viewer_initial_connect(VirtViewer *viewer) +virt_viewer_initial_connect(VirtViewerApp *app) { virDomainPtr dom = NULL; virDomainInfo info; int ret = -1; - - virt_viewer_set_status(viewer, "Finding guest domain"); - dom = virt_viewer_lookup_domain(viewer); + VirtViewer *self = VIRT_VIEWER(app); + VirtViewerPrivate *priv = self->priv; + + virt_viewer_app_show_status(app, _("Finding guest domain")); + dom = virt_viewer_lookup_domain(self); if (!dom) { - if (viewer->waitvm) { - virt_viewer_set_status(viewer, "Waiting for guest domain to be created"); - virt_viewer_trace(viewer, "Guest %s does not yet exist, waiting for it to be created\n", - viewer->domkey); + if (priv->waitvm) { + virt_viewer_app_show_status(app, _("Waiting for guest domain to be created")); + virt_viewer_app_trace(app, "Guest %s does not yet exist, waiting for it to be created\n", + priv->domkey); goto done; } else { - virt_viewer_simple_message_dialog(viewer->window, _("Cannot find guest domain %s"), - viewer->domkey); - DEBUG_LOG("Cannot find guest %s", viewer->domkey); + virt_viewer_app_simple_message_dialog(app, _("Cannot find guest domain %s"), + priv->domkey); + DEBUG_LOG("Cannot find guest %s", priv->domkey); goto cleanup; } } - free(viewer->domtitle); - viewer->domtitle = g_strdup(virDomainGetName(dom)); - - virt_viewer_set_status(viewer, "Checking guest domain status"); + free(priv->domtitle); + priv->domtitle = g_strdup(virDomainGetName(dom)); + + virt_viewer_app_show_status(app, _("Checking guest domain status")); if (virDomainGetInfo(dom, &info) < 0) { DEBUG_LOG("Cannot get guest state"); goto cleanup; } if (info.state == VIR_DOMAIN_SHUTOFF) { - virt_viewer_set_status(viewer, "Waiting for guest domain to start"); + virt_viewer_app_show_status(app, _("Waiting for guest domain to start")); } else { - ret = virt_viewer_activate(viewer, dom); + ret = virt_viewer_update_display(self, dom); + if (ret >= 0) + ret = VIRT_VIEWER_APP_CLASS(virt_viewer_parent_class)->initial_connect(app); if (ret < 0) { - if (viewer->waitvm) { - virt_viewer_set_status(viewer, "Waiting for guest domain to start server"); - virt_viewer_trace(viewer, "Guest %s has not activated its display yet, waiting for it to start\n", - viewer->domkey); + if (priv->waitvm) { + virt_viewer_app_show_status(app, _("Waiting for guest domain to start server")); + virt_viewer_app_trace(app, "Guest %s has not activated its display yet, waiting for it to start\n", + priv->domkey); } else { DEBUG_LOG("Failed to activate viewer"); goto cleanup; @@ -1519,61 +453,6 @@ return ret; } -static gboolean -virt_viewer_connect_timer(void *opaque) -{ - VirtViewer *viewer = opaque; - - DEBUG_LOG("Connect timer fired"); - - if (!viewer->active && - virt_viewer_initial_connect(viewer) < 0) - gtk_main_quit(); - - if (viewer->active) - return FALSE; - - return TRUE; -} - -static void -virt_viewer_toolbar_setup(VirtViewer *viewer) -{ - GtkWidget *button; - - viewer->toolbar = gtk_toolbar_new(); - gtk_toolbar_set_show_arrow(GTK_TOOLBAR(viewer->toolbar), FALSE); - gtk_widget_set_no_show_all(viewer->toolbar, TRUE); - gtk_toolbar_set_style(GTK_TOOLBAR(viewer->toolbar), GTK_TOOLBAR_BOTH_HORIZ); - - /* Close connection */ - button = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_CLOSE)); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Disconnect")); - gtk_widget_show(GTK_WIDGET(button)); - gtk_toolbar_insert(GTK_TOOLBAR(viewer->toolbar), GTK_TOOL_ITEM (button), 0); - g_signal_connect(button, "clicked", G_CALLBACK(gtk_main_quit), NULL); - - /* Leave fullscreen */ - button = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_LEAVE_FULLSCREEN)); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), _("Leave fullscreen")); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Leave fullscreen")); - gtk_tool_item_set_is_important(GTK_TOOL_ITEM(button), TRUE); - gtk_widget_show(GTK_WIDGET(button)); - gtk_toolbar_insert(GTK_TOOLBAR(viewer->toolbar), GTK_TOOL_ITEM(button), 0); - g_signal_connect(button, "clicked", G_CALLBACK(virt_viewer_toolbar_leave_fullscreen), viewer); - - viewer->layout = ViewAutoDrawer_New(); - - ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(viewer->layout), FALSE); - ViewOvBox_SetOver(VIEW_OV_BOX(viewer->layout), viewer->toolbar); - ViewOvBox_SetUnder(VIEW_OV_BOX(viewer->layout), viewer->notebook); - ViewAutoDrawer_SetOffset(VIEW_AUTODRAWER(viewer->layout), -1); - ViewAutoDrawer_SetFill(VIEW_AUTODRAWER(viewer->layout), FALSE); - ViewAutoDrawer_SetOverlapPixels(VIEW_AUTODRAWER(viewer->layout), 1); - ViewAutoDrawer_SetNoOverlapPixels(VIEW_AUTODRAWER(viewer->layout), 0); -} - - static void virt_viewer_error_func (void *data G_GNUC_UNUSED, virErrorPtr error G_GNUC_UNUSED) @@ -1581,137 +460,88 @@ /* nada */ } -int -virt_viewer_start(const char *uri, - const char *name, - gint zoom, - gboolean direct, - gboolean waitvm, - gboolean reconnect, - gboolean verbose, - gboolean debug, - gboolean fullscreen, - GtkWidget *container) -{ - VirtViewer *viewer; - GtkWidget *menu; +static gboolean +virt_viewer_start(VirtViewerApp *app) +{ + VirtViewer *self = VIRT_VIEWER(app); + VirtViewerPrivate *priv = self->priv; int cred_types[] = { VIR_CRED_AUTHNAME, VIR_CRED_PASSPHRASE }; virConnectAuth auth_libvirt = { .credtype = cred_types, .ncredtype = ARRAY_CARDINALITY(cred_types), .cb = virt_viewer_auth_libvirt_credentials, - .cbdata = (void *)uri, + .cbdata = (void *)priv->uri, }; - GdkColor color; - doDebug = debug; - - viewer = g_new0(VirtViewer, 1); - - viewer->active = FALSE; - viewer->autoResize = TRUE; - viewer->direct = direct; - viewer->waitvm = waitvm; - viewer->reconnect = reconnect; - viewer->verbose = verbose; - viewer->domkey = g_strdup(name); - viewer->uri = g_strdup(uri); - - g_value_init(&viewer->accelSetting, G_TYPE_STRING); virt_viewer_events_register(); virSetErrorFunc(NULL, virt_viewer_error_func); - virt_viewer_trace(viewer, "Opening connection to libvirt with URI %s\n", - uri ? uri : ""); - viewer->conn = virConnectOpenAuth(uri, - //virConnectAuthPtrDefault, - &auth_libvirt, - VIR_CONNECT_RO); - if (!viewer->conn) { - virt_viewer_simple_message_dialog(NULL, _("Unable to connect to libvirt with URI %s"), - uri ? uri : _("[none]")); - return -1; - } - - if (!container) { - viewer->builder = virt_viewer_util_load_ui("virt-viewer.xml"); - - menu = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "menu-view-resize")); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE); - - gtk_builder_connect_signals(viewer->builder, viewer); - } - - viewer->status = gtk_label_new(""); - - viewer->zoomlevel = zoom; - - viewer->notebook = gtk_notebook_new(); - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(viewer->notebook), FALSE); - gtk_notebook_set_show_border(GTK_NOTEBOOK(viewer->notebook), FALSE); - - gtk_notebook_append_page(GTK_NOTEBOOK(viewer->notebook), viewer->status, NULL); - - if (container) { - viewer->container = container; - - gtk_box_pack_end(GTK_BOX(container), viewer->notebook, TRUE, TRUE, 0); - gtk_widget_show_all(GTK_WIDGET(container)); - } else { - GtkWidget *vbox = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "viewer-box")); - virt_viewer_toolbar_setup(viewer); - - gtk_box_pack_end(GTK_BOX(vbox), viewer->layout, TRUE, TRUE, 0); - gdk_color_parse("black", &color); - gtk_widget_modify_bg(viewer->layout, GTK_STATE_NORMAL, &color); - gdk_color_parse("white", &color); - gtk_widget_modify_fg(viewer->status, GTK_STATE_NORMAL, &color); - - GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(viewer->builder, "viewer")); - GSList *accels; - viewer->container = window; - viewer->window = window; - virt_viewer_set_title(viewer, FALSE); - gtk_window_set_resizable(GTK_WINDOW(window), TRUE); -#if GTK_CHECK_VERSION(3, 0, 0) - gtk_window_set_has_resize_grip(GTK_WINDOW(window), FALSE); -#endif - viewer->accelEnabled = TRUE; - accels = gtk_accel_groups_from_object(G_OBJECT(window)); - for ( ; accels ; accels = accels->next) { - viewer->accelList = g_slist_append(viewer->accelList, accels->data); - g_object_ref(G_OBJECT(accels->data)); - } - g_signal_connect(G_OBJECT(window), "window-state-event", G_CALLBACK(window_state_cb), viewer); - if (fullscreen) - gtk_window_fullscreen(GTK_WINDOW(window)); - gtk_widget_show_all(viewer->window); - } - - if (virt_viewer_initial_connect(viewer) < 0) - return -1; - - if (virConnectDomainEventRegister(viewer->conn, + virt_viewer_app_trace(app, "Opening connection to libvirt with URI %s\n", + priv->uri ? priv->uri : ""); + priv->conn = virConnectOpenAuth(priv->uri, + //virConnectAuthPtrDefault, + &auth_libvirt, + VIR_CONNECT_RO); + if (!priv->conn) { + virt_viewer_app_simple_message_dialog(app, _("Unable to connect to libvirt with URI %s"), + priv->uri ? priv->uri : _("[none]")); + return FALSE; + } + + if (virt_viewer_app_initial_connect(app) < 0) + return FALSE; + + if (virConnectDomainEventRegister(priv->conn, virt_viewer_domain_event, - viewer, + self, NULL) < 0) - viewer->withEvents = FALSE; + priv->withEvents = FALSE; else - viewer->withEvents = TRUE; - - if (!viewer->withEvents && - !viewer->active) { + priv->withEvents = TRUE; + + if (!priv->withEvents && + !virt_viewer_app_is_active(app)) { DEBUG_LOG("No domain events, falling back to polling"); - g_timeout_add(500, - virt_viewer_connect_timer, - viewer); - } - - return 0; -} - + virt_viewer_app_start_reconnect_poll(app); + } + + return VIRT_VIEWER_APP_CLASS(virt_viewer_parent_class)->start(app); +} + +VirtViewer * +virt_viewer_new(const char *uri, + const char *name, + gint zoom, + gboolean direct, + gboolean waitvm, + gboolean reconnect, + gboolean verbose, + GtkWidget *container) +{ + VirtViewer *self; + VirtViewerApp *app; + VirtViewerPrivate *priv; + + self = g_object_new(VIRT_VIEWER_TYPE, + "container", container, + "verbose", verbose, + NULL); + app = VIRT_VIEWER_APP(self); + priv = self->priv; + + virt_viewer_window_set_zoom_level(virt_viewer_app_get_main_window(app), zoom); + virt_viewer_app_set_direct(app, direct); + + /* should probably be properties instead */ + priv->uri = g_strdup(uri); + priv->domkey = g_strdup(name); + priv->waitvm = waitvm; + priv->reconnect = reconnect; + + return self; +} /* * Local variables: diff --git a/src/virt-viewer.h b/src/virt-viewer.h index 28784fc..886a0f3 100644 --- a/src/virt-viewer.h +++ b/src/virt-viewer.h @@ -23,19 +23,41 @@ #ifndef VIRT_VIEWER_H #define VIRT_VIEWER_H -#include "virt-viewer-util.h" +#include +#include "virt-viewer-app.h" -typedef struct _VirtViewer VirtViewer; +G_BEGIN_DECLS -extern int virt_viewer_start(const char *uri, - const char *name, - gint zoom, - gboolean direct, - gboolean waitvm, - gboolean reconnect, - gboolean verbose, - gboolean debug, - gboolean fullscreen, - GtkWidget *container); +#define VIRT_VIEWER_TYPE virt_viewer_get_type() +#define VIRT_VIEWER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIRT_VIEWER_TYPE, VirtViewer)) +#define VIRT_VIEWER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIRT_VIEWER_TYPE, VirtViewerClass)) +#define VIRT_VIEWER_IS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIRT_VIEWER_TYPE)) +#define VIRT_VIEWER_IS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIRT_VIEWER_TYPE)) +#define VIRT_VIEWER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VIRT_VIEWER_TYPE, VirtViewerClass)) + +typedef struct _VirtViewerPrivate VirtViewerPrivate; + +typedef struct { + VirtViewerApp parent; + VirtViewerPrivate *priv; +} VirtViewer; + +typedef struct { + VirtViewerAppClass parent_class; +} VirtViewerClass; + +GType virt_viewer_get_type (void); + +VirtViewer * +virt_viewer_new(const char *uri, + const char *name, + gint zoom, + gboolean direct, + gboolean waitvm, + gboolean reconnect, + gboolean verbose, + GtkWidget *container); + +G_END_DECLS #endif /* VIRT_VIEWER_H */ diff --git a/src/virt-viewer.xml b/src/virt-viewer.xml index 783313c..b701c2c 100644 --- a/src/virt-viewer.xml +++ b/src/virt-viewer.xml @@ -1,47 +1,56 @@ - + - + False 400 400 - + True - vertical + False True + False True + False + False _File True True + False True + False + False Screenshot True - + True + False gtk-quit True + False + False True True - - + + @@ -51,61 +60,76 @@ True + False + False _View True True + False True + False + False Full screen True - + True + False + False _Zoom True True + False + gtk-zoom-in True - gtk-zoom-in + False + False True True - + + gtk-zoom-out True - gtk-zoom-out + False + False True True - + True + False + gtk-zoom-100 True - gtk-zoom-100 + False + False True True - + @@ -115,9 +139,20 @@ True + False + False Automatically resize True - + + + + + + True + False + False + Displays + True @@ -127,139 +162,174 @@ True + False + False _Send key True True + False True + False + False Ctrl+Alt+_Del True - + True + False + False Ctrl+Alt+_Backspace True - + True + False True + False + False Ctrl+Alt+F_1 True - + True + False + False Ctrl+Alt+F_2 True - + True + False + False Ctrl+Alt+F_3 True - + True + False + False Ctrl+Alt+F_4 True - + True + False + False Ctrl+Alt+F_5 True - + True + False + False Ctrl+Alt+F_6 True - + True + False + False Ctrl+Alt+F_7 True - + True + False + False Ctrl+Alt+F_8 True - + True + False + False Ctrl+Alt+F_9 True - + True + False + False Ctrl+Alt+F1_0 True - + True + False + False Ctrl+Alt+F11 True - + True + False + False Ctrl+Alt+F12 True - + True + False True + False + False _PrintScreen True - + @@ -269,18 +339,23 @@ True + False + False _Help True True + False gtk-about True + False + False True True - + @@ -290,6 +365,7 @@ False + True 0 diff --git a/virt-viewer.spec b/virt-viewer.spec index d8a02fd..a759e14 100644 --- a/virt-viewer.spec +++ b/virt-viewer.spec @@ -20,7 +20,7 @@ %endif Name: virt-viewer -Version: 0.4.0 +Version: 0.4.1 Release: 1%{?dist}%{?extra_release} Summary: Virtual Machine Viewer Group: Applications/System