[Spice-devel] [PATCH spice-gtk 2/3] Move gtk/ -> src/
Fabiano Fidencio
ffidenci at redhat.com
Mon Jun 8 08:22:47 PDT 2015
----- Original Message -----
> From: "Marc-André Lureau" <marcandre.lureau at redhat.com>
> To: spice-devel at lists.freedesktop.org
> Sent: Friday, June 5, 2015 6:29:43 PM
> Subject: [Spice-devel] [PATCH spice-gtk 2/3] Move gtk/ -> src/
>
> For historical reasons, the code was placed under gtk/ subdirectory.
> If it was always bugging you, bug no more!
Finally! ACK!
> ---
> Makefile.am | 2 +-
> configure.ac | 10 +-
> doc/reference/Makefile.am | 10 +-
> gtk/Makefile.am | 703 ------
> gtk/bio-gio.c | 114 -
> gtk/bio-gio.h | 30 -
> gtk/channel-base.c | 284 ---
> gtk/channel-cursor.c | 529 -----
> gtk/channel-cursor.h | 77 -
> gtk/channel-display-mjpeg.c | 156 --
> gtk/channel-display-priv.h | 113 -
> gtk/channel-display.c | 1789 ---------------
> gtk/channel-display.h | 102 -
> gtk/channel-inputs.c | 603 ------
> gtk/channel-inputs.h | 89 -
> gtk/channel-main.c | 2993
> --------------------------
> gtk/channel-main.h | 109 -
> gtk/channel-playback-priv.h | 24 -
> gtk/channel-playback.c | 496 -----
> gtk/channel-playback.h | 76 -
> gtk/channel-port.c | 361 ----
> gtk/channel-port.h | 76 -
> gtk/channel-record.c | 482 -----
> gtk/channel-record.h | 77 -
> gtk/channel-smartcard.c | 587 -----
> gtk/channel-smartcard.h | 68 -
> gtk/channel-usbredir-priv.h | 61 -
> gtk/channel-usbredir.c | 686 ------
> gtk/channel-usbredir.h | 71 -
> gtk/channel-webdav.c | 613 ------
> gtk/channel-webdav.h | 68 -
> gtk/client_sw_canvas.c | 20 -
> gtk/client_sw_canvas.h | 25 -
> gtk/continuation.c | 102 -
> gtk/continuation.h | 61 -
> gtk/controller/Makefile.am | 100 -
> gtk/controller/controller.vala | 286 ---
> gtk/controller/custom.h | 22 -
> gtk/controller/custom.vapi | 28 -
> gtk/controller/dump.c | 118 -
> gtk/controller/foreign-menu.vala | 197 --
> gtk/controller/gio-windows-2.0.vapi | 30 -
> gtk/controller/menu.vala | 108 -
> gtk/controller/namedpipe.c | 270 ---
> gtk/controller/namedpipe.h | 59 -
> gtk/controller/namedpipeconnection.c | 245 ---
> gtk/controller/namedpipeconnection.h | 56 -
> gtk/controller/namedpipelistener.c | 329 ---
> gtk/controller/namedpipelistener.h | 70 -
> gtk/controller/spice-controller-listener.c | 159 --
> gtk/controller/spice-controller-listener.h | 47 -
> gtk/controller/spice-foreign-menu-listener.c | 161 --
> gtk/controller/spice-foreign-menu-listener.h | 47 -
> gtk/controller/test.c | 292 ---
> gtk/controller/util.vala | 42 -
> gtk/controller/win32-util.c | 161 --
> gtk/controller/win32-util.h | 30 -
> gtk/coroutine.h | 83 -
> gtk/coroutine_gthread.c | 170 --
> gtk/coroutine_ucontext.c | 150 --
> gtk/coroutine_winfibers.c | 126 --
> gtk/decode-glz-tmpl.c | 336 ---
> gtk/decode-glz.c | 475 ----
> gtk/decode-jpeg.c | 191 --
> gtk/decode-zlib.c | 89 -
> gtk/decode.h | 44 -
> gtk/desktop-integration.c | 223 --
> gtk/desktop-integration.h | 64 -
> gtk/gio-coroutine.c | 275 ---
> gtk/gio-coroutine.h | 66 -
> gtk/giopipe.c | 484 -----
> gtk/giopipe.h | 29 -
> gtk/glib-compat.c | 79 -
> gtk/glib-compat.h | 68 -
> gtk/gtk-compat.h | 56 -
> gtk/keymap-gen.pl | 214 --
> gtk/keymaps.csv | 490 -----
> gtk/map-file | 139 --
> gtk/smartcard-manager-priv.h | 37 -
> gtk/smartcard-manager.c | 737 -------
> gtk/smartcard-manager.h | 80 -
> gtk/spice-audio-priv.h | 42 -
> gtk/spice-audio.c | 274 ---
> gtk/spice-audio.h | 109 -
> gtk/spice-channel-cache.h | 106 -
> gtk/spice-channel-enums.h | 7 -
> gtk/spice-channel-priv.h | 203 --
> gtk/spice-channel.c | 2960
> -------------------------
> gtk/spice-channel.h | 131 --
> gtk/spice-client-glib-usb-acl-helper.c | 372 ----
> gtk/spice-client-gtk-manual.defs | 117 -
> gtk/spice-client-gtk-module.c | 45 -
> gtk/spice-client-gtk.override | 171 --
> gtk/spice-client.c | 27 -
> gtk/spice-client.h | 79 -
> gtk/spice-cmdline.c | 98 -
> gtk/spice-cmdline.h | 29 -
> gtk/spice-common.h | 36 -
> gtk/spice-glib-sym-file | 111 -
> gtk/spice-grabsequence.c | 163 --
> gtk/spice-grabsequence.h | 61 -
> gtk/spice-gstaudio.c | 739 -------
> gtk/spice-gstaudio.h | 56 -
> gtk/spice-gtk-session-priv.h | 34 -
> gtk/spice-gtk-session.c | 1229 -----------
> gtk/spice-gtk-session.h | 65 -
> gtk/spice-gtk-sym-file | 23 -
> gtk/spice-marshal.txt | 14 -
> gtk/spice-option.c | 284 ---
> gtk/spice-option.h | 31 -
> gtk/spice-pulse.c | 1354 ------------
> gtk/spice-pulse.h | 57 -
> gtk/spice-session-priv.h | 104 -
> gtk/spice-session.c | 2728 -----------------------
> gtk/spice-session.h | 103 -
> gtk/spice-types.h | 35 -
> gtk/spice-uri-priv.h | 30 -
> gtk/spice-uri.c | 462 ----
> gtk/spice-uri.h | 52 -
> gtk/spice-util-priv.h | 52 -
> gtk/spice-util.c | 497 -----
> gtk/spice-util.h | 63 -
> gtk/spice-version.h.in | 70 -
> gtk/spice-widget-cairo.c | 160 --
> gtk/spice-widget-priv.h | 141 --
> gtk/spice-widget-x11.c | 280 ---
> gtk/spice-widget.c | 2642 -----------------------
> gtk/spice-widget.h | 92 -
> gtk/spicy-screenshot.c | 196 --
> gtk/spicy-stats.c | 144 --
> gtk/spicy.c | 1855 ----------------
> gtk/usb-acl-helper.c | 299 ---
> gtk/usb-acl-helper.h | 72 -
> gtk/usb-device-manager-priv.h | 48 -
> gtk/usb-device-manager.c | 1932 -----------------
> gtk/usb-device-manager.h | 122 --
> gtk/usb-device-widget.c | 554 -----
> gtk/usb-device-widget.h | 81 -
> gtk/usbutil.c | 323 ---
> gtk/usbutil.h | 39 -
> gtk/vmcstream.c | 535 -----
> gtk/vmcstream.h | 81 -
> gtk/vncdisplaykeymap.c | 323 ---
> gtk/vncdisplaykeymap.h | 36 -
> gtk/win-usb-clerk.h | 36 -
> gtk/win-usb-dev.c | 542 -----
> gtk/win-usb-dev.h | 110 -
> gtk/win-usb-driver-install.c | 398 ----
> gtk/win-usb-driver-install.h | 104 -
> gtk/wocky-http-proxy.c | 537 -----
> gtk/wocky-http-proxy.h | 56 -
> po/POTFILES.in | 22 +-
> po/POTFILES.skip | 3 +-
> src/Makefile.am | 703 ++++++
> src/bio-gio.c | 114 +
> src/bio-gio.h | 30 +
> src/channel-base.c | 284 +++
> src/channel-cursor.c | 529 +++++
> src/channel-cursor.h | 77 +
> src/channel-display-mjpeg.c | 156 ++
> src/channel-display-priv.h | 113 +
> src/channel-display.c | 1789 +++++++++++++++
> src/channel-display.h | 102 +
> src/channel-inputs.c | 603 ++++++
> src/channel-inputs.h | 89 +
> src/channel-main.c | 2993
> ++++++++++++++++++++++++++
> src/channel-main.h | 109 +
> src/channel-playback-priv.h | 24 +
> src/channel-playback.c | 496 +++++
> src/channel-playback.h | 76 +
> src/channel-port.c | 361 ++++
> src/channel-port.h | 76 +
> src/channel-record.c | 482 +++++
> src/channel-record.h | 77 +
> src/channel-smartcard.c | 587 +++++
> src/channel-smartcard.h | 68 +
> src/channel-usbredir-priv.h | 61 +
> src/channel-usbredir.c | 686 ++++++
> src/channel-usbredir.h | 71 +
> src/channel-webdav.c | 613 ++++++
> src/channel-webdav.h | 68 +
> src/client_sw_canvas.c | 20 +
> src/client_sw_canvas.h | 25 +
> src/continuation.c | 102 +
> src/continuation.h | 61 +
> src/controller/Makefile.am | 100 +
> src/controller/controller.vala | 286 +++
> src/controller/custom.h | 22 +
> src/controller/custom.vapi | 28 +
> src/controller/dump.c | 118 +
> src/controller/foreign-menu.vala | 197 ++
> src/controller/gio-windows-2.0.vapi | 30 +
> src/controller/menu.vala | 108 +
> src/controller/namedpipe.c | 270 +++
> src/controller/namedpipe.h | 59 +
> src/controller/namedpipeconnection.c | 245 +++
> src/controller/namedpipeconnection.h | 56 +
> src/controller/namedpipelistener.c | 329 +++
> src/controller/namedpipelistener.h | 70 +
> src/controller/spice-controller-listener.c | 159 ++
> src/controller/spice-controller-listener.h | 47 +
> src/controller/spice-foreign-menu-listener.c | 161 ++
> src/controller/spice-foreign-menu-listener.h | 47 +
> src/controller/test.c | 292 +++
> src/controller/util.vala | 42 +
> src/controller/win32-util.c | 161 ++
> src/controller/win32-util.h | 30 +
> src/coroutine.h | 83 +
> src/coroutine_gthread.c | 170 ++
> src/coroutine_ucontext.c | 150 ++
> src/coroutine_winfibers.c | 126 ++
> src/decode-glz-tmpl.c | 336 +++
> src/decode-glz.c | 475 ++++
> src/decode-jpeg.c | 191 ++
> src/decode-zlib.c | 89 +
> src/decode.h | 44 +
> src/desktop-integration.c | 223 ++
> src/desktop-integration.h | 64 +
> src/gio-coroutine.c | 275 +++
> src/gio-coroutine.h | 66 +
> src/giopipe.c | 484 +++++
> src/giopipe.h | 29 +
> src/glib-compat.c | 79 +
> src/glib-compat.h | 68 +
> src/gtk-compat.h | 56 +
> src/keymap-gen.pl | 214 ++
> src/keymaps.csv | 490 +++++
> src/map-file | 139 ++
> src/smartcard-manager-priv.h | 37 +
> src/smartcard-manager.c | 737 +++++++
> src/smartcard-manager.h | 80 +
> src/spice-audio-priv.h | 42 +
> src/spice-audio.c | 274 +++
> src/spice-audio.h | 109 +
> src/spice-channel-cache.h | 106 +
> src/spice-channel-enums.h | 7 +
> src/spice-channel-priv.h | 203 ++
> src/spice-channel.c | 2960
> +++++++++++++++++++++++++
> src/spice-channel.h | 131 ++
> src/spice-client-glib-usb-acl-helper.c | 372 ++++
> src/spice-client-gtk-manual.defs | 117 +
> src/spice-client-gtk-module.c | 45 +
> src/spice-client-gtk.override | 171 ++
> src/spice-client.c | 27 +
> src/spice-client.h | 79 +
> src/spice-cmdline.c | 98 +
> src/spice-cmdline.h | 29 +
> src/spice-common.h | 36 +
> src/spice-glib-sym-file | 111 +
> src/spice-grabsequence.c | 163 ++
> src/spice-grabsequence.h | 61 +
> src/spice-gstaudio.c | 739 +++++++
> src/spice-gstaudio.h | 56 +
> src/spice-gtk-session-priv.h | 34 +
> src/spice-gtk-session.c | 1229 +++++++++++
> src/spice-gtk-session.h | 65 +
> src/spice-gtk-sym-file | 23 +
> src/spice-marshal.txt | 14 +
> src/spice-option.c | 284 +++
> src/spice-option.h | 31 +
> src/spice-pulse.c | 1354 ++++++++++++
> src/spice-pulse.h | 57 +
> src/spice-session-priv.h | 104 +
> src/spice-session.c | 2728 +++++++++++++++++++++++
> src/spice-session.h | 103 +
> src/spice-types.h | 35 +
> src/spice-uri-priv.h | 30 +
> src/spice-uri.c | 462 ++++
> src/spice-uri.h | 52 +
> src/spice-util-priv.h | 52 +
> src/spice-util.c | 497 +++++
> src/spice-util.h | 63 +
> src/spice-version.h.in | 70 +
> src/spice-widget-cairo.c | 160 ++
> src/spice-widget-priv.h | 141 ++
> src/spice-widget-x11.c | 280 +++
> src/spice-widget.c | 2642 +++++++++++++++++++++++
> src/spice-widget.h | 92 +
> src/spicy-screenshot.c | 196 ++
> src/spicy-stats.c | 144 ++
> src/spicy.c | 1855 ++++++++++++++++
> src/usb-acl-helper.c | 299 +++
> src/usb-acl-helper.h | 72 +
> src/usb-device-manager-priv.h | 48 +
> src/usb-device-manager.c | 1932 +++++++++++++++++
> src/usb-device-manager.h | 122 ++
> src/usb-device-widget.c | 554 +++++
> src/usb-device-widget.h | 81 +
> src/usbutil.c | 323 +++
> src/usbutil.h | 39 +
> src/vmcstream.c | 535 +++++
> src/vmcstream.h | 81 +
> src/vncdisplaykeymap.c | 323 +++
> src/vncdisplaykeymap.h | 36 +
> src/win-usb-clerk.h | 36 +
> src/win-usb-dev.c | 542 +++++
> src/win-usb-dev.h | 110 +
> src/win-usb-driver-install.c | 398 ++++
> src/win-usb-driver-install.h | 104 +
> src/wocky-http-proxy.c | 537 +++++
> src/wocky-http-proxy.h | 56 +
> tests/Makefile.am | 6 +-
> vapi/Makefile.am | 6 +-
> 303 files changed, 44198 insertions(+), 44197 deletions(-)
> delete mode 100644 gtk/Makefile.am
> delete mode 100644 gtk/bio-gio.c
> delete mode 100644 gtk/bio-gio.h
> delete mode 100644 gtk/channel-base.c
> delete mode 100644 gtk/channel-cursor.c
> delete mode 100644 gtk/channel-cursor.h
> delete mode 100644 gtk/channel-display-mjpeg.c
> delete mode 100644 gtk/channel-display-priv.h
> delete mode 100644 gtk/channel-display.c
> delete mode 100644 gtk/channel-display.h
> delete mode 100644 gtk/channel-inputs.c
> delete mode 100644 gtk/channel-inputs.h
> delete mode 100644 gtk/channel-main.c
> delete mode 100644 gtk/channel-main.h
> delete mode 100644 gtk/channel-playback-priv.h
> delete mode 100644 gtk/channel-playback.c
> delete mode 100644 gtk/channel-playback.h
> delete mode 100644 gtk/channel-port.c
> delete mode 100644 gtk/channel-port.h
> delete mode 100644 gtk/channel-record.c
> delete mode 100644 gtk/channel-record.h
> delete mode 100644 gtk/channel-smartcard.c
> delete mode 100644 gtk/channel-smartcard.h
> delete mode 100644 gtk/channel-usbredir-priv.h
> delete mode 100644 gtk/channel-usbredir.c
> delete mode 100644 gtk/channel-usbredir.h
> delete mode 100644 gtk/channel-webdav.c
> delete mode 100644 gtk/channel-webdav.h
> delete mode 100644 gtk/client_sw_canvas.c
> delete mode 100644 gtk/client_sw_canvas.h
> delete mode 100644 gtk/continuation.c
> delete mode 100644 gtk/continuation.h
> delete mode 100644 gtk/controller/Makefile.am
> delete mode 100644 gtk/controller/controller.vala
> delete mode 100644 gtk/controller/custom.h
> delete mode 100644 gtk/controller/custom.vapi
> delete mode 100644 gtk/controller/dump.c
> delete mode 100644 gtk/controller/foreign-menu.vala
> delete mode 100644 gtk/controller/gio-windows-2.0.vapi
> delete mode 100644 gtk/controller/menu.vala
> delete mode 100644 gtk/controller/namedpipe.c
> delete mode 100644 gtk/controller/namedpipe.h
> delete mode 100644 gtk/controller/namedpipeconnection.c
> delete mode 100644 gtk/controller/namedpipeconnection.h
> delete mode 100644 gtk/controller/namedpipelistener.c
> delete mode 100644 gtk/controller/namedpipelistener.h
> delete mode 100644 gtk/controller/spice-controller-listener.c
> delete mode 100644 gtk/controller/spice-controller-listener.h
> delete mode 100644 gtk/controller/spice-foreign-menu-listener.c
> delete mode 100644 gtk/controller/spice-foreign-menu-listener.h
> delete mode 100644 gtk/controller/test.c
> delete mode 100644 gtk/controller/util.vala
> delete mode 100644 gtk/controller/win32-util.c
> delete mode 100644 gtk/controller/win32-util.h
> delete mode 100644 gtk/coroutine.h
> delete mode 100644 gtk/coroutine_gthread.c
> delete mode 100644 gtk/coroutine_ucontext.c
> delete mode 100644 gtk/coroutine_winfibers.c
> delete mode 100644 gtk/decode-glz-tmpl.c
> delete mode 100644 gtk/decode-glz.c
> delete mode 100644 gtk/decode-jpeg.c
> delete mode 100644 gtk/decode-zlib.c
> delete mode 100644 gtk/decode.h
> delete mode 100644 gtk/desktop-integration.c
> delete mode 100644 gtk/desktop-integration.h
> delete mode 100644 gtk/gio-coroutine.c
> delete mode 100644 gtk/gio-coroutine.h
> delete mode 100644 gtk/giopipe.c
> delete mode 100644 gtk/giopipe.h
> delete mode 100644 gtk/glib-compat.c
> delete mode 100644 gtk/glib-compat.h
> delete mode 100644 gtk/gtk-compat.h
> delete mode 100755 gtk/keymap-gen.pl
> delete mode 100644 gtk/keymaps.csv
> delete mode 100644 gtk/map-file
> delete mode 100644 gtk/smartcard-manager-priv.h
> delete mode 100644 gtk/smartcard-manager.c
> delete mode 100644 gtk/smartcard-manager.h
> delete mode 100644 gtk/spice-audio-priv.h
> delete mode 100644 gtk/spice-audio.c
> delete mode 100644 gtk/spice-audio.h
> delete mode 100644 gtk/spice-channel-cache.h
> delete mode 100644 gtk/spice-channel-enums.h
> delete mode 100644 gtk/spice-channel-priv.h
> delete mode 100644 gtk/spice-channel.c
> delete mode 100644 gtk/spice-channel.h
> delete mode 100644 gtk/spice-client-glib-usb-acl-helper.c
> delete mode 100644 gtk/spice-client-gtk-manual.defs
> delete mode 100644 gtk/spice-client-gtk-module.c
> delete mode 100644 gtk/spice-client-gtk.override
> delete mode 100644 gtk/spice-client.c
> delete mode 100644 gtk/spice-client.h
> delete mode 100644 gtk/spice-cmdline.c
> delete mode 100644 gtk/spice-cmdline.h
> delete mode 100644 gtk/spice-common.h
> delete mode 100644 gtk/spice-glib-sym-file
> delete mode 100644 gtk/spice-grabsequence.c
> delete mode 100644 gtk/spice-grabsequence.h
> delete mode 100644 gtk/spice-gstaudio.c
> delete mode 100644 gtk/spice-gstaudio.h
> delete mode 100644 gtk/spice-gtk-session-priv.h
> delete mode 100644 gtk/spice-gtk-session.c
> delete mode 100644 gtk/spice-gtk-session.h
> delete mode 100644 gtk/spice-gtk-sym-file
> delete mode 100644 gtk/spice-marshal.txt
> delete mode 100644 gtk/spice-option.c
> delete mode 100644 gtk/spice-option.h
> delete mode 100644 gtk/spice-pulse.c
> delete mode 100644 gtk/spice-pulse.h
> delete mode 100644 gtk/spice-session-priv.h
> delete mode 100644 gtk/spice-session.c
> delete mode 100644 gtk/spice-session.h
> delete mode 100644 gtk/spice-types.h
> delete mode 100644 gtk/spice-uri-priv.h
> delete mode 100644 gtk/spice-uri.c
> delete mode 100644 gtk/spice-uri.h
> delete mode 100644 gtk/spice-util-priv.h
> delete mode 100644 gtk/spice-util.c
> delete mode 100644 gtk/spice-util.h
> delete mode 100644 gtk/spice-version.h.in
> delete mode 100644 gtk/spice-widget-cairo.c
> delete mode 100644 gtk/spice-widget-priv.h
> delete mode 100644 gtk/spice-widget-x11.c
> delete mode 100644 gtk/spice-widget.c
> delete mode 100644 gtk/spice-widget.h
> delete mode 100644 gtk/spicy-screenshot.c
> delete mode 100644 gtk/spicy-stats.c
> delete mode 100644 gtk/spicy.c
> delete mode 100644 gtk/usb-acl-helper.c
> delete mode 100644 gtk/usb-acl-helper.h
> delete mode 100644 gtk/usb-device-manager-priv.h
> delete mode 100644 gtk/usb-device-manager.c
> delete mode 100644 gtk/usb-device-manager.h
> delete mode 100644 gtk/usb-device-widget.c
> delete mode 100644 gtk/usb-device-widget.h
> delete mode 100644 gtk/usbutil.c
> delete mode 100644 gtk/usbutil.h
> delete mode 100644 gtk/vmcstream.c
> delete mode 100644 gtk/vmcstream.h
> delete mode 100644 gtk/vncdisplaykeymap.c
> delete mode 100644 gtk/vncdisplaykeymap.h
> delete mode 100644 gtk/win-usb-clerk.h
> delete mode 100644 gtk/win-usb-dev.c
> delete mode 100644 gtk/win-usb-dev.h
> delete mode 100644 gtk/win-usb-driver-install.c
> delete mode 100644 gtk/win-usb-driver-install.h
> delete mode 100644 gtk/wocky-http-proxy.c
> delete mode 100644 gtk/wocky-http-proxy.h
> create mode 100644 src/Makefile.am
> create mode 100644 src/bio-gio.c
> create mode 100644 src/bio-gio.h
> create mode 100644 src/channel-base.c
> create mode 100644 src/channel-cursor.c
> create mode 100644 src/channel-cursor.h
> create mode 100644 src/channel-display-mjpeg.c
> create mode 100644 src/channel-display-priv.h
> create mode 100644 src/channel-display.c
> create mode 100644 src/channel-display.h
> create mode 100644 src/channel-inputs.c
> create mode 100644 src/channel-inputs.h
> create mode 100644 src/channel-main.c
> create mode 100644 src/channel-main.h
> create mode 100644 src/channel-playback-priv.h
> create mode 100644 src/channel-playback.c
> create mode 100644 src/channel-playback.h
> create mode 100644 src/channel-port.c
> create mode 100644 src/channel-port.h
> create mode 100644 src/channel-record.c
> create mode 100644 src/channel-record.h
> create mode 100644 src/channel-smartcard.c
> create mode 100644 src/channel-smartcard.h
> create mode 100644 src/channel-usbredir-priv.h
> create mode 100644 src/channel-usbredir.c
> create mode 100644 src/channel-usbredir.h
> create mode 100644 src/channel-webdav.c
> create mode 100644 src/channel-webdav.h
> create mode 100644 src/client_sw_canvas.c
> create mode 100644 src/client_sw_canvas.h
> create mode 100644 src/continuation.c
> create mode 100644 src/continuation.h
> create mode 100644 src/controller/Makefile.am
> create mode 100644 src/controller/controller.vala
> create mode 100644 src/controller/custom.h
> create mode 100644 src/controller/custom.vapi
> create mode 100644 src/controller/dump.c
> create mode 100644 src/controller/foreign-menu.vala
> create mode 100644 src/controller/gio-windows-2.0.vapi
> create mode 100644 src/controller/menu.vala
> create mode 100644 src/controller/namedpipe.c
> create mode 100644 src/controller/namedpipe.h
> create mode 100644 src/controller/namedpipeconnection.c
> create mode 100644 src/controller/namedpipeconnection.h
> create mode 100644 src/controller/namedpipelistener.c
> create mode 100644 src/controller/namedpipelistener.h
> create mode 100644 src/controller/spice-controller-listener.c
> create mode 100644 src/controller/spice-controller-listener.h
> create mode 100644 src/controller/spice-foreign-menu-listener.c
> create mode 100644 src/controller/spice-foreign-menu-listener.h
> create mode 100644 src/controller/test.c
> create mode 100644 src/controller/util.vala
> create mode 100644 src/controller/win32-util.c
> create mode 100644 src/controller/win32-util.h
> create mode 100644 src/coroutine.h
> create mode 100644 src/coroutine_gthread.c
> create mode 100644 src/coroutine_ucontext.c
> create mode 100644 src/coroutine_winfibers.c
> create mode 100644 src/decode-glz-tmpl.c
> create mode 100644 src/decode-glz.c
> create mode 100644 src/decode-jpeg.c
> create mode 100644 src/decode-zlib.c
> create mode 100644 src/decode.h
> create mode 100644 src/desktop-integration.c
> create mode 100644 src/desktop-integration.h
> create mode 100644 src/gio-coroutine.c
> create mode 100644 src/gio-coroutine.h
> create mode 100644 src/giopipe.c
> create mode 100644 src/giopipe.h
> create mode 100644 src/glib-compat.c
> create mode 100644 src/glib-compat.h
> create mode 100644 src/gtk-compat.h
> create mode 100755 src/keymap-gen.pl
> create mode 100644 src/keymaps.csv
> create mode 100644 src/map-file
> create mode 100644 src/smartcard-manager-priv.h
> create mode 100644 src/smartcard-manager.c
> create mode 100644 src/smartcard-manager.h
> create mode 100644 src/spice-audio-priv.h
> create mode 100644 src/spice-audio.c
> create mode 100644 src/spice-audio.h
> create mode 100644 src/spice-channel-cache.h
> create mode 100644 src/spice-channel-enums.h
> create mode 100644 src/spice-channel-priv.h
> create mode 100644 src/spice-channel.c
> create mode 100644 src/spice-channel.h
> create mode 100644 src/spice-client-glib-usb-acl-helper.c
> create mode 100644 src/spice-client-gtk-manual.defs
> create mode 100644 src/spice-client-gtk-module.c
> create mode 100644 src/spice-client-gtk.override
> create mode 100644 src/spice-client.c
> create mode 100644 src/spice-client.h
> create mode 100644 src/spice-cmdline.c
> create mode 100644 src/spice-cmdline.h
> create mode 100644 src/spice-common.h
> create mode 100644 src/spice-glib-sym-file
> create mode 100644 src/spice-grabsequence.c
> create mode 100644 src/spice-grabsequence.h
> create mode 100644 src/spice-gstaudio.c
> create mode 100644 src/spice-gstaudio.h
> create mode 100644 src/spice-gtk-session-priv.h
> create mode 100644 src/spice-gtk-session.c
> create mode 100644 src/spice-gtk-session.h
> create mode 100644 src/spice-gtk-sym-file
> create mode 100644 src/spice-marshal.txt
> create mode 100644 src/spice-option.c
> create mode 100644 src/spice-option.h
> create mode 100644 src/spice-pulse.c
> create mode 100644 src/spice-pulse.h
> create mode 100644 src/spice-session-priv.h
> create mode 100644 src/spice-session.c
> create mode 100644 src/spice-session.h
> create mode 100644 src/spice-types.h
> create mode 100644 src/spice-uri-priv.h
> create mode 100644 src/spice-uri.c
> create mode 100644 src/spice-uri.h
> create mode 100644 src/spice-util-priv.h
> create mode 100644 src/spice-util.c
> create mode 100644 src/spice-util.h
> create mode 100644 src/spice-version.h.in
> create mode 100644 src/spice-widget-cairo.c
> create mode 100644 src/spice-widget-priv.h
> create mode 100644 src/spice-widget-x11.c
> create mode 100644 src/spice-widget.c
> create mode 100644 src/spice-widget.h
> create mode 100644 src/spicy-screenshot.c
> create mode 100644 src/spicy-stats.c
> create mode 100644 src/spicy.c
> create mode 100644 src/usb-acl-helper.c
> create mode 100644 src/usb-acl-helper.h
> create mode 100644 src/usb-device-manager-priv.h
> create mode 100644 src/usb-device-manager.c
> create mode 100644 src/usb-device-manager.h
> create mode 100644 src/usb-device-widget.c
> create mode 100644 src/usb-device-widget.h
> create mode 100644 src/usbutil.c
> create mode 100644 src/usbutil.h
> create mode 100644 src/vmcstream.c
> create mode 100644 src/vmcstream.h
> create mode 100644 src/vncdisplaykeymap.c
> create mode 100644 src/vncdisplaykeymap.h
> create mode 100644 src/win-usb-clerk.h
> create mode 100644 src/win-usb-dev.c
> create mode 100644 src/win-usb-dev.h
> create mode 100644 src/win-usb-driver-install.c
> create mode 100644 src/win-usb-driver-install.h
> create mode 100644 src/wocky-http-proxy.c
> create mode 100644 src/wocky-http-proxy.h
>
> diff --git a/Makefile.am b/Makefile.am
> index e559c4d..3d7a174 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1,7 +1,7 @@
> ACLOCAL_AMFLAGS = -I m4
> NULL =
>
> -SUBDIRS = spice-common gtk man po doc data
> +SUBDIRS = spice-common src man po doc data
>
> if BUILD_TESTS
> SUBDIRS += tests
> diff --git a/configure.ac b/configure.ac
> index cf5a039..1d8f4d0 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -88,7 +88,7 @@ dnl
> =========================================================================
> dnl Chek optional features
>
> srcdir="$(dirname $0)"
> -if test ! -e "$srcdir/gtk/vncdisplaykeymap_osx2xtkbd.c"; then
> +if test ! -e "$srcdir/src/vncdisplaykeymap_osx2xtkbd.c"; then
> AC_MSG_CHECKING([for Text::CSV Perl module])
> perl -MText::CSV -e "" >/dev/null 2>&1
> if test $? -ne 0 ; then
> @@ -708,7 +708,7 @@ dnl
> ===========================================================================
> dnl check compiler flags
>
> # We want to enable these, but need to sort out the
> -# decl mess with gtk/generated_*.c
> +# decl mess with src/generated_*.c
> dontwarn="-Wmissing-prototypes -Wmissing-declarations"
>
> # We want to enable these, but Gtk+2.0 has a bad decl
> @@ -746,9 +746,9 @@ spice-controller.pc
> data/Makefile
> data/spicy.nsis
> po/Makefile.in
> -gtk/Makefile
> -gtk/spice-version.h
> -gtk/controller/Makefile
> +src/Makefile
> +src/spice-version.h
> +src/controller/Makefile
> doc/Makefile
> doc/reference/Makefile
> man/Makefile
> diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am
> index 76c7d34..0e4d5b3 100644
> --- a/doc/reference/Makefile.am
> +++ b/doc/reference/Makefile.am
> @@ -7,7 +7,7 @@ DOC_MODULE = spice-gtk
> DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml
>
> # Source code location
> -DOC_SOURCE_DIR = $(top_srcdir)/gtk
> +DOC_SOURCE_DIR = $(top_srcdir)/src
>
> # Extra options to supply to gtkdoc-scan.
> SCAN_OPTIONS = \
> @@ -18,8 +18,8 @@ SCAN_OPTIONS = \
> MKDB_OPTIONS = --xml-mode --output-format=xml
>
> # Used for dependencies. The docs will be rebuilt if any of these change.
> -HFILE_GLOB = $(top_srcdir)/gtk/*.h
> -CFILE_GLOB = $(top_srcdir)/gtk/*.c
> +HFILE_GLOB = $(top_srcdir)/src/*.h
> +CFILE_GLOB = $(top_srcdir)/src/*.c
>
> # Header files to ignore when scanning. Use base file name, no paths
> IGNORE_HFILES= \
> @@ -54,8 +54,8 @@ IGNORE_HFILES= \
> $(NULL)
>
> # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
> -GTKDOC_CFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/gtk
> -I$(top_builddir)/gtk $(SPICE_GLIB_CFLAGS) $(SPICE_GTK_CFLAGS)
> $(COMMON_CFLAGS)
> -GTKDOC_LIBS = $(top_builddir)/gtk/libspice-client-glib-2.0.la
> $(top_builddir)/gtk/libspice-client-gtk-$(SPICE_GTK_API_VERSION).la
> +GTKDOC_CFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_srcdir)/src
> -I$(top_builddir)/src $(SPICE_GLIB_CFLAGS) $(SPICE_GTK_CFLAGS)
> $(COMMON_CFLAGS)
> +GTKDOC_LIBS = $(top_builddir)/src/libspice-client-glib-2.0.la
> $(top_builddir)/src/libspice-client-gtk-$(SPICE_GTK_API_VERSION).la
>
> include $(top_srcdir)/gtk-doc.make
>
> diff --git a/gtk/Makefile.am b/gtk/Makefile.am
> deleted file mode 100644
> index 25e2255..0000000
> --- a/gtk/Makefile.am
> +++ /dev/null
> @@ -1,703 +0,0 @@
> -NULL =
> -SUBDIRS =
> -
> -if WITH_CONTROLLER
> -SUBDIRS += controller
> -endif
> -
> -# Avoid need for perl(Text::CSV) by end users
> -KEYMAPS = \
> - vncdisplaykeymap_xorgevdev2xtkbd.c \
> - vncdisplaykeymap_xorgkbd2xtkbd.c \
> - vncdisplaykeymap_xorgxquartz2xtkbd.c \
> - vncdisplaykeymap_xorgxwin2xtkbd.c \
> - vncdisplaykeymap_osx2xtkbd.c \
> - vncdisplaykeymap_win322xtkbd.c \
> - vncdisplaykeymap_x112xtkbd.c \
> - $(NULL)
> -
> -# End users build dependencies can be cleaned
> -GLIBGENS = \
> - spice-glib-enums.c \
> - spice-glib-enums.h \
> - spice-marshal.c \
> - spice-marshal.h \
> - spice-widget-enums.c \
> - spice-widget-enums.h \
> - $(NULL)
> -
> -CLEANFILES = $(GLIBGENS)
> -BUILT_SOURCES = $(GLIBGENS) $(KEYMAPS)
> -
> -EXTRA_DIST = \
> - $(KEYMAPS) \
> - decode-glz-tmpl.c \
> - keymap-gen.pl \
> - keymaps.csv \
> - map-file \
> - spice-glib-sym-file \
> - spice-gtk-sym-file \
> - spice-client-gtk-manual.defs \
> - spice-client-gtk.override \
> - spice-marshal.txt \
> - spice-version.h.in \
> - $(NULL)
> -
> -DISTCLEANFILES = spice-version.h
> -
> -bin_PROGRAMS = spicy-stats spicy-screenshot
> -if WITH_GTK
> -bin_PROGRAMS += spicy
> -endif
> -if WITH_POLKIT
> -acldir = $(ACL_HELPER_DIR)
> -acl_PROGRAMS = spice-client-glib-usb-acl-helper
> -endif
> -
> -lib_LTLIBRARIES = libspice-client-glib-2.0.la
> -
> -if WITH_GTK
> -if HAVE_GTK_2
> -lib_LTLIBRARIES += libspice-client-gtk-2.0.la
> -else
> -lib_LTLIBRARIES += libspice-client-gtk-3.0.la
> -endif
> -endif
> -
> -if HAVE_LD_VERSION_SCRIPT
> -GLIB_SYMBOLS_LDFLAGS = -Wl,--version-script=${srcdir}/map-file
> -GLIB_SYMBOLS_FILE = map-file
> -GTK_SYMBOLS_LDFLAGS = $(GLIB_SYMBOLS_LDFLAGS)
> -GTK_SYMBOLS_FILE = $(GLIB_SYMBOLS_FILE)
> -else
> -GLIB_SYMBOLS_LDFLAGS = -export-symbols ${srcdir}/spice-glib-sym-file
> -GLIB_SYMBOLS_FILE = spice-glib-sym-file
> -GTK_SYMBOLS_LDFLAGS = -export-symbols ${srcdir}/spice-gtk-sym-file
> -GTK_SYMBOLS_FILE = spice-gtk-sym-file
> -endif
> -
> -KEYMAP_GEN = $(srcdir)/keymap-gen.pl
> -
> -SPICE_COMMON_CPPFLAGS = \
> - -DG_LOG_DOMAIN=\"GSpice\" \
> - -DSPICE_NO_DEPRECATED \
> - -DSPICE_GTK_LOCALEDIR=\"${SPICE_GTK_LOCALEDIR}\" \
> - -DPNP_IDS=\""$(PNP_IDS)"\" \
> - -DUSB_IDS=\""$(USB_IDS)"\" \
> - -DSPICE_DISABLE_ABORT \
> - -I$(top_srcdir) \
> - $(COMMON_CFLAGS) \
> - $(PIXMAN_CFLAGS) \
> - $(PULSE_CFLAGS) \
> - $(GTK_CFLAGS) \
> - $(CAIRO_CFLAGS) \
> - $(GLIB2_CFLAGS) \
> - $(GIO_CFLAGS) \
> - $(GOBJECT2_CFLAGS) \
> - $(SSL_CFLAGS) \
> - $(SASL_CFLAGS) \
> - $(GST_CFLAGS) \
> - $(SMARTCARD_CFLAGS) \
> - $(USBREDIR_CFLAGS) \
> - $(GUDEV_CFLAGS) \
> - $(SOUP_CFLAGS) \
> - $(PHODAV_CFLAGS) \
> - $(LZ4_CFLAGS) \
> - $(NULL)
> -
> -AM_CPPFLAGS = \
> - $(SPICE_COMMON_CPPFLAGS) \
> - $(SPICE_CFLAGS) \
> - $(NULL)
> -
> -#
> http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
> -SPICE_GTK_LDFLAGS_COMMON = \
> - -version-info 4:0:0 \
> - -no-undefined \
> - $(GTK_SYMBOLS_LDFLAGS) \
> - $(NULL)
> -
> -SPICE_GTK_LIBADD_COMMON = \
> - libspice-client-glib-2.0.la \
> - $(GTK_LIBS) \
> - $(CAIRO_LIBS) \
> - $(XRANDR_LIBS) \
> - $(LIBM) \
> - $(NULL)
> -
> -SPICE_GTK_SOURCES_COMMON = \
> - glib-compat.h \
> - gtk-compat.h \
> - spice-util.c \
> - spice-util-priv.h \
> - spice-gtk-session.c \
> - spice-gtk-session-priv.h \
> - spice-widget.c \
> - spice-widget-priv.h \
> - vncdisplaykeymap.c \
> - vncdisplaykeymap.h \
> - spice-grabsequence.c \
> - spice-grabsequence.h \
> - desktop-integration.c \
> - desktop-integration.h \
> - usb-device-widget.c \
> - $(NULL)
> -
> -nodist_SPICE_GTK_SOURCES_COMMON = \
> - spice-widget-enums.c \
> - spice-marshal.c \
> - $(NULL)
> -
> -if WITH_X11
> -SPICE_GTK_SOURCES_COMMON += \
> - spice-widget-x11.c \
> - $(NULL)
> -else
> -SPICE_GTK_SOURCES_COMMON += \
> - spice-widget-cairo.c \
> - $(NULL)
> -endif
> -
> -if WITH_GTK
> -if HAVE_GTK_2
> -libspice_client_gtk_2_0_la_DEPEDENCIES = $(GTK_SYMBOLS_FILE)
> -libspice_client_gtk_2_0_la_LDFLAGS = $(SPICE_GTK_LDFLAGS_COMMON)
> -libspice_client_gtk_2_0_la_LIBADD = $(SPICE_GTK_LIBADD_COMMON)
> -libspice_client_gtk_2_0_la_SOURCES = $(SPICE_GTK_SOURCES_COMMON)
> -nodist_libspice_client_gtk_2_0_la_SOURCES =
> $(nodist_SPICE_GTK_SOURCES_COMMON)
> -else
> -libspice_client_gtk_3_0_la_DEPEDENCIES = $(GTK_SYMBOLS_FILE)
> -libspice_client_gtk_3_0_la_LDFLAGS = $(SPICE_GTK_LDFLAGS_COMMON)
> -libspice_client_gtk_3_0_la_LIBADD = $(SPICE_GTK_LIBADD_COMMON)
> -libspice_client_gtk_3_0_la_SOURCES = $(SPICE_GTK_SOURCES_COMMON)
> -nodist_libspice_client_gtk_3_0_la_SOURCES =
> $(nodist_SPICE_GTK_SOURCES_COMMON)
> -endif
> -
> -libspice_client_gtkincludedir =
> $(includedir)/spice-client-gtk-$(SPICE_GTK_API_VERSION)
> -libspice_client_gtkinclude_HEADERS = \
> - spice-gtk-session.h \
> - spice-widget.h \
> - spice-grabsequence.h \
> - usb-device-widget.h \
> - $(NULL)
> -
> -nodist_libspice_client_gtkinclude_HEADERS = \
> - spice-widget-enums.h \
> - $(NULL)
> -endif
> -
> -libspice_client_glib_2_0_la_DEPENDENCIES = $(GLIB_SYMBOLS_FILE)
> -
> -libspice_client_glib_2_0_la_LDFLAGS = \
> - -version-info 13:0:5 \
> - -no-undefined \
> - $(GLIB_SYMBOLS_LDFLAGS) \
> - $(NULL)
> -
> -libspice_client_glib_2_0_la_LIBADD = \
> - $(top_builddir)/spice-common/common/libspice-common.la \
> - $(top_builddir)/spice-common/common/libspice-common-client.la \
> - $(GLIB2_LIBS) \
> - $(SOUP_LIBS) \
> - $(GIO_LIBS) \
> - $(GOBJECT2_LIBS) \
> - $(JPEG_LIBS) \
> - $(Z_LIBS) \
> - $(LZ4_LIBS) \
> - $(PIXMAN_LIBS) \
> - $(SSL_LIBS) \
> - $(PULSE_LIBS) \
> - $(GST_LIBS) \
> - $(SASL_LIBS) \
> - $(SMARTCARD_LIBS) \
> - $(USBREDIR_LIBS) \
> - $(GUDEV_LIBS) \
> - $(PHODAV_LIBS) \
> - $(NULL)
> -
> -if WITH_POLKIT
> -USB_ACL_HELPER_SRCS = \
> - usb-acl-helper.c \
> - usb-acl-helper.h \
> - $(NULL)
> -AM_CPPFLAGS += -DACL_HELPER_PATH="\"$(ACL_HELPER_DIR)\""
> -else
> -USB_ACL_HELPER_SRCS =
> -endif
> -
> -libspice_client_glib_2_0_la_SOURCES = \
> - bio-gio.c \
> - bio-gio.h \
> - glib-compat.c \
> - glib-compat.h \
> - spice-audio.c \
> - spice-audio-priv.h \
> - spice-common.h \
> - spice-util.c \
> - spice-util-priv.h \
> - spice-option.h \
> - spice-option.c \
> - \
> - spice-client.c \
> - spice-session.c \
> - spice-session-priv.h \
> - spice-channel.c \
> - spice-channel-cache.h \
> - spice-channel-priv.h \
> - coroutine.h \
> - gio-coroutine.c \
> - gio-coroutine.h \
> - \
> - channel-base.c \
> - channel-webdav.c \
> - channel-cursor.c \
> - channel-display.c \
> - channel-display-priv.h \
> - channel-display-mjpeg.c \
> - channel-inputs.c \
> - channel-main.c \
> - channel-playback.c \
> - channel-playback-priv.h \
> - channel-port.c \
> - channel-record.c \
> - channel-smartcard.c \
> - channel-usbredir.c \
> - channel-usbredir-priv.h \
> - smartcard-manager.c \
> - smartcard-manager-priv.h \
> - spice-uri.c \
> - spice-uri-priv.h \
> - usb-device-manager.c \
> - usb-device-manager-priv.h \
> - usbutil.c \
> - usbutil.h \
> - $(USB_ACL_HELPER_SRCS) \
> - vmcstream.c \
> - vmcstream.h \
> - wocky-http-proxy.c \
> - wocky-http-proxy.h \
> - \
> - decode.h \
> - decode-glz.c \
> - decode-jpeg.c \
> - decode-zlib.c \
> - \
> - client_sw_canvas.c \
> - client_sw_canvas.h \
> - $(NULL)
> -
> -nodist_libspice_client_glib_2_0_la_SOURCES = \
> - spice-glib-enums.c \
> - spice-marshal.c \
> - spice-marshal.h \
> - $(NULL)
> -
> -libspice_client_glibincludedir = $(includedir)/spice-client-glib-2.0
> -libspice_client_glibinclude_HEADERS = \
> - spice-audio.h \
> - spice-client.h \
> - spice-uri.h \
> - spice-types.h \
> - spice-session.h \
> - spice-channel.h \
> - spice-util.h \
> - spice-option.h \
> - spice-version.h \
> - channel-cursor.h \
> - channel-display.h \
> - channel-inputs.h \
> - channel-main.h \
> - channel-playback.h \
> - channel-port.h \
> - channel-record.h \
> - channel-smartcard.h \
> - channel-usbredir.h \
> - channel-webdav.h \
> - usb-device-manager.h \
> - smartcard-manager.h \
> - $(NULL)
> -
> -nodist_libspice_client_glibinclude_HEADERS = \
> - spice-glib-enums.h \
> - $(NULL)
> -
> -# file for API compatibility, but we don't want warning during our
> compilation
> -dist_libspice_client_glibinclude_DATA = \
> - spice-channel-enums.h \
> - $(NULL)
> -
> -if WITH_PULSE
> -libspice_client_glib_2_0_la_SOURCES += \
> - spice-pulse.c \
> - spice-pulse.h \
> - $(NULL)
> -endif
> -
> -if WITH_GSTAUDIO
> -libspice_client_glib_2_0_la_SOURCES += \
> - spice-gstaudio.c \
> - spice-gstaudio.h \
> - $(NULL)
> -endif
> -
> -if WITH_PHODAV
> -libspice_client_glib_2_0_la_SOURCES += \
> - giopipe.c \
> - giopipe.h \
> - $(NULL)
> -endif
> -
> -if WITH_UCONTEXT
> -libspice_client_glib_2_0_la_SOURCES += continuation.h continuation.c
> coroutine_ucontext.c
> -endif
> -
> -if WITH_WINFIBER
> -libspice_client_glib_2_0_la_SOURCES += coroutine_winfibers.c
> -endif
> -
> -if WITH_GTHREAD
> -libspice_client_glib_2_0_la_SOURCES += coroutine_gthread.c
> -libspice_client_glib_2_0_la_LIBADD += $(GTHREAD_LIBS)
> -endif
> -
> -
> -WIN_USB_FILES= \
> - win-usb-dev.h \
> - win-usb-dev.c \
> - win-usb-clerk.h \
> - win-usb-driver-install.h \
> - win-usb-driver-install.c \
> - $(NULL)
> -
> -if OS_WIN32
> -if WITH_USBREDIR
> -libspice_client_glib_2_0_la_SOURCES += \
> - $(WIN_USB_FILES)
> -endif
> -libspice_client_glib_2_0_la_LIBADD += -lws2_32 -lgdi32
> -endif
> -
> -spicy_SOURCES = \
> - spicy.c \
> - spice-cmdline.h \
> - spice-cmdline.c \
> - $(NULL)
> -
> -spicy_LDADD = \
> - libspice-client-gtk-$(SPICE_GTK_API_VERSION).la \
> - libspice-client-glib-2.0.la \
> - $(XRANDR_LIBS) \
> - $(GTHREAD_LIBS) \
> - $(GTK_LIBS) \
> - $(LIBM) \
> - $(NULL)
> -
> -spicy_CPPFLAGS = \
> - $(AM_CPPFLAGS) \
> - $(XRANDR_CFLAGS) \
> - $(GTHREAD_CFLAGS) \
> - -DSPICE_DISABLE_DEPRECATED \
> - $(NULL)
> -
> -
> -if WITH_POLKIT
> -spice_client_glib_usb_acl_helper_SOURCES = \
> - glib-compat.c \
> - glib-compat.h \
> - spice-client-glib-usb-acl-helper.c \
> - $(NULL)
> -
> -spice_client_glib_usb_acl_helper_LDADD = \
> - $(GLIB2_LIBS) \
> - $(GIO_LIBS) \
> - $(POLKIT_LIBS) \
> - $(ACL_LIBS) \
> - $(PIE_LDFLAGS) \
> - $(NULL)
> -
> -spice_client_glib_usb_acl_helper_CPPFLAGS = \
> - $(SPICE_CFLAGS) \
> - $(GLIB2_CFLAGS) \
> - $(GIO_CFLAGS) \
> - $(POLKIT_CFLAGS) \
> - $(PIE_CFLAGS) \
> - $(NULL)
> -
> -install-data-hook:
> - -chown root $(DESTDIR)$(acldir)/spice-client-glib-usb-acl-helper
> - -chmod u+s $(DESTDIR)$(acldir)/spice-client-glib-usb-acl-helper
> -
> -endif
> -
> -
> -spicy_screenshot_SOURCES = \
> - spicy-screenshot.c \
> - spice-cmdline.h \
> - spice-cmdline.c \
> - $(NULL)
> -
> -spicy_screenshot_LDADD = \
> - libspice-client-glib-2.0.la \
> - $(GOBJECT2_LIBS) \
> - $(NULL)
> -
> -spicy_stats_SOURCES = \
> - spicy-stats.c \
> - spice-cmdline.h \
> - spice-cmdline.c \
> - $(NULL)
> -
> -spicy_stats_LDADD = \
> - libspice-client-glib-2.0.la \
> - $(GOBJECT2_LIBS) \
> - $(NULL)
> -
> -
> -
> -$(libspice_client_glib_2_0_la_SOURCES): spice-glib-enums.h spice-marshal.h
> -
> -if WITH_GTK
> -if HAVE_GTK_2
> -$(libspice_client_gtk_2_0_la_SOURCES): spice-glib-enums.h
> spice-widget-enums.h
> -else
> -$(libspice_client_gtk_3_0_la_SOURCES): spice-glib-enums.h
> spice-widget-enums.h
> -endif
> -endif
> -
> -spice-marshal.c: spice-marshal.h
> -spice-glib-enums.c: spice-glib-enums.h
> -spice-widget-enums.c: spice-widget-enums.h
> -
> -spice-marshal.c: spice-marshal.txt
> - $(AM_V_GEN)echo "#include \"config.h\"" > $@ && \
> - echo "#include \"spice-marshal.h\"" > $@ && \
> - glib-genmarshal --body $< >> $@ || (rm -f $@ && exit 1)
> -
> -spice-marshal.h: spice-marshal.txt
> - $(AM_V_GEN)glib-genmarshal --header $< > $@ || (rm -f $@ && exit 1)
> -
> -spice-glib-enums.c: spice-channel.h channel-inputs.h spice-session.h
> - $(AM_V_GEN)glib-mkenums --fhead "#include \"config.h\"\n\n" \
> - --fhead "#include <glib-object.h>\n" \
> - --fhead "#include \"spice-glib-enums.h\"\n\n" \
> - --fprod "\n#include \"spice-session.h\"\n" \
> - --fprod "\n#include \"spice-channel.h\"\n" \
> - --fprod "\n#include \"channel-inputs.h\"\n" \
> - --vhead "static const G at Type@Value _ at enum_name@_values[] = {" \
> - --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
> - --vtail " { 0, NULL, NULL }\n};\n\n" \
> - --vtail "GType\n at enum_name@_get_type (void)\n{\n" \
> - --vtail " static GType type = 0;\n" \
> - --vtail " static volatile gsize type_volatile = 0;\n\n" \
> - --vtail " if (g_once_init_enter(&type_volatile)) {\n" \
> - --vtail " type = g_ at type@_register_static (\"@EnumName@\",
> _ at enum_name@_values);\n" \
> - --vtail " g_once_init_leave(&type_volatile, type);\n" \
> - --vtail " }\n\n" \
> - --vtail " return type;\n}\n\n" \
> - $^ > $@
> -
> -spice-glib-enums.h: spice-channel.h channel-inputs.h spice-session.h
> - $(AM_V_GEN)glib-mkenums --fhead "#ifndef SPICE_GLIB_ENUMS_H\n" \
> - --fhead "#define SPICE_GLIB_ENUMS_H\n\n" \
> - --fhead "G_BEGIN_DECLS\n\n" \
> - --ftail "G_END_DECLS\n\n" \
> - --ftail "#endif /* SPICE_CHANNEL_ENUMS_H */\n" \
> - --eprod "#define SPICE_TYPE_ at ENUMSHORT@ @enum_name at _get_type()\n" \
> - --eprod "GType @enum_name at _get_type (void);\n" \
> - $^ > $@
> -
> -spice-widget-enums.c: spice-widget.h
> - $(AM_V_GEN)glib-mkenums --fhead "#include \"config.h\"\n\n" \
> - --fhead "#include <glib-object.h>\n" \
> - --fhead "#include \"spice-widget-enums.h\"\n\n" \
> - --fprod "\n#include \"spice-widget.h\"\n" \
> - --vhead "static const G at Type@Value _ at enum_name@_values[] = {" \
> - --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
> - --vtail " { 0, NULL, NULL }\n};\n\n" \
> - --vtail "GType\n at enum_name@_get_type (void)\n{\n" \
> - --vtail " static GType type = 0;\n" \
> - --vtail " static volatile gsize type_volatile = 0;\n\n" \
> - --vtail " if (g_once_init_enter(&type_volatile)) {\n" \
> - --vtail " type = g_ at type@_register_static (\"@EnumName@\",
> _ at enum_name@_values);\n" \
> - --vtail " g_once_init_leave(&type_volatile, type);\n" \
> - --vtail " }\n\n" \
> - --vtail " return type;\n}\n\n" \
> - $< > $@
> -
> -spice-widget-enums.h: spice-widget.h
> - $(AM_V_GEN)glib-mkenums --fhead "#ifndef SPICE_WIDGET_ENUMS_H\n" \
> - --fhead "#define SPICE_WIDGET_ENUMS_H\n\n" \
> - --fhead "G_BEGIN_DECLS\n\n" \
> - --ftail "G_END_DECLS\n\n" \
> - --ftail "#endif /* SPICE_WIDGET_ENUMS_H */\n" \
> - --eprod "#define SPICE_TYPE_ at ENUMSHORT@ @enum_name at _get_type()\n" \
> - --eprod "GType @enum_name at _get_type (void);\n" \
> - $< > $@
> -
> -
> -vncdisplaykeymap.c: $(KEYMAPS)
> -
> -$(KEYMAPS): $(KEYMAP_GEN) keymaps.csv
> -
> -# Note despite being autogenerated these are not part of CLEANFILES, they
> -# are actually a part of EXTRA_DIST to avoid the need for perl(Text::CSV) by
> -# end users
> -vncdisplaykeymap_xorgevdev2xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgevdev xtkbd > $@ || rm
> $@
> -
> -vncdisplaykeymap_xorgkbd2xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgkbd xtkbd > $@ || rm $@
> -
> -vncdisplaykeymap_xorgxquartz2xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxquartz xtkbd > $@ || rm
> $@
> -
> -vncdisplaykeymap_xorgxwin2xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxwin xtkbd > $@ || rm $@
> -
> -vncdisplaykeymap_osx2xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv osx xtkbd > $@ || rm $@
> -
> -vncdisplaykeymap_win322xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv win32 xtkbd > $@ || rm $@
> -
> -vncdisplaykeymap_x112xtkbd.c:
> - $(AM_V_GEN)$(KEYMAP_GEN) $(srcdir)/keymaps.csv x11 xtkbd > $@ || rm $@
> -
> -if WITH_PYTHON
> -pyexec_LTLIBRARIES = SpiceClientGtk.la
> -
> -# workaround for broken parallel install support in automake with
> LTLIBRARIES
> -# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328
> -install_pyexecLTLIBRARIES = install-pyexecLTLIBRARIES
> -$(install_pyexecLTLIBRARIES): install-libLTLIBRARIES
> -
> -SpiceClientGtk_la_LIBADD = libspice-client-gtk-2.0.la
> libspice-client-glib-2.0.la $(PYGTK_LIBS)
> -SpiceClientGtk_la_CFLAGS = $(GTK_CFLAGS) $(PYTHON_INCLUDES) $(PYGTK_CFLAGS)
> $(WARN_PYFLAGS)
> -SpiceClientGtk_la_LDFLAGS = -module -avoid-version -fPIC
> -SpiceClientGtk_la_SOURCES = spice-client-gtk-module.c
> -nodist_SpiceClientGtk_la_SOURCES = spice-client-gtk-module.defs.c
> -
> -CODEGENDIR = `pkg-config --variable=codegendir pygtk-2.0`
> -DEFSDIR = `pkg-config --variable=defsdir pygtk-2.0`
> -
> -spice-client-gtk.defs: $(libspice_client_gtkinclude_HEADERS)
> $(nodist_libspice_client_gtkinclude_HEADERS)
> $(libspice_client_glibinclude_HEADERS)
> $(nodist_libspice_client_glibinclude_HEADERS)
> - $(AM_V_GEN)$(PYTHON) $(CODEGENDIR)/h2def.py \
> - -f $(srcdir)/spice-client-gtk-manual.defs \
> - $^ > $@
> -
> -spice-client-gtk-module.defs.c: spice-client-gtk.override
> spice-client-gtk.defs spice-client-gtk-manual.defs
> - @cat spice-client-gtk.defs $(srcdir)/spice-client-gtk-manual.defs >
> tmp.defs
> - $(AM_V_GEN)pygobject-codegen-2.0 --prefix spice \
> - --register $(DEFSDIR)/gdk-types.defs \
> - --register $(DEFSDIR)/gtk-types.defs \
> - --override $(srcdir)/spice-client-gtk.override \
> - tmp.defs > $@
> - @rm tmp.defs
> -
> -CLEANFILES += spice-client-gtk-module.defs.c spice-client-gtk.defs
> -endif
> -
> --include $(INTROSPECTION_MAKEFILE)
> -
> -if G_IR_SCANNER_SYMBOL_PREFIX
> -PREFIX_ARGS = --symbol-prefix=spice --identifier-prefix=Spice
> -else
> -PREFIX_ARGS = --strip-prefix=Spice
> -endif
> -
> -INTROSPECTION_GIRS =
> -INTROSPECTION_SCANNER_ARGS = --warn-all --accept-unprefixed
> --add-include-path=$(builddir) $(PREFIX_ARGS)
> -INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir)
> -
> -if HAVE_INTROSPECTION
> -glib_introspection_files = \
> - $(libspice_client_glibinclude_HEADERS) \
> - $(nodist_libspice_client_glibinclude_HEADERS) \
> - spice-audio.c \
> - spice-client.c \
> - spice-session.c \
> - spice-channel.c \
> - spice-glib-enums.c \
> - spice-option.c \
> - spice-util.c \
> - channel-webdav.c \
> - channel-cursor.c \
> - channel-display.c \
> - channel-inputs.c \
> - channel-main.c \
> - channel-playback.c \
> - channel-port.c \
> - channel-record.c \
> - channel-smartcard.c \
> - channel-usbredir.c \
> - smartcard-manager.c \
> - usb-device-manager.c \
> - $(NULL)
> -
> -gtk_introspection_files = \
> - $(libspice_client_gtkinclude_HEADERS) \
> - $(nodist_libspice_client_gtkinclude_HEADERS) \
> - spice-gtk-session.c \
> - spice-widget.c \
> - spice-grabsequence.c \
> - usb-device-widget.c \
> - $(NULL)
> -
> -SpiceClientGLib-2.0.gir: libspice-client-glib-2.0.la
> -SpiceClientGLib_2_0_gir_INCLUDES = GObject-2.0 Gio-2.0
> -SpiceClientGLib_2_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS)
> -SpiceClientGLib_2_0_gir_LIBS = libspice-client-glib-2.0.la
> -SpiceClientGLib_2_0_gir_FILES = $(glib_introspection_files)
> -SpiceClientGLib_2_0_gir_EXPORT_PACKAGES = spice-client-glib-2.0
> -SpiceClientGLib_2_0_gir_SCANNERFLAGS = --c-include="spice-client.h"
> -INTROSPECTION_GIRS += SpiceClientGLib-2.0.gir
> -
> -if WITH_GTK
> -if HAVE_GTK_2
> -SpiceClientGtk-2.0.gir: libspice-client-gtk-2.0.la SpiceClientGLib-2.0.gir
> -SpiceClientGtk_2_0_gir_INCLUDES = GObject-2.0 Gtk-2.0 SpiceClientGLib-2.0
> -SpiceClientGtk_2_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS)
> -SpiceClientGtk_2_0_gir_LIBS = libspice-client-gtk-2.0.la
> libspice-client-glib-2.0.la
> -SpiceClientGtk_2_0_gir_FILES = $(gtk_introspection_files)
> -SpiceClientGtk_2_0_gir_EXPORT_PACKAGES = spice-client-gtk-2.0
> -SpiceClientGtk_2_0_gir_SCANNERFLAGS = --c-include="spice-widget.h"
> -else
> -SpiceClientGtk-3.0.gir: libspice-client-gtk-3.0.la SpiceClientGLib-2.0.gir
> -SpiceClientGtk_3_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 SpiceClientGLib-2.0
> -SpiceClientGtk_3_0_gir_CFLAGS = $(SPICE_COMMON_CPPFLAGS)
> -SpiceClientGtk_3_0_gir_LIBS = libspice-client-gtk-3.0.la
> libspice-client-glib-2.0.la
> -SpiceClientGtk_3_0_gir_FILES = $(gtk_introspection_files)
> -SpiceClientGtk_3_0_gir_EXPORT_PACKAGES = spice-client-gtk-3.0
> -SpiceClientGtk_3_0_gir_SCANNERFLAGS = --c-include="spice-widget.h"
> -endif
> -INTROSPECTION_GIRS += SpiceClientGtk-$(SPICE_GTK_API_VERSION).gir
> -endif
> -
> -girdir = $(datadir)/gir-1.0
> -gir_DATA = $(INTROSPECTION_GIRS)
> -
> -typelibsdir = $(libdir)/girepository-1.0
> -typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
> -
> -CLEANFILES += $(gir_DATA) $(typelibs_DATA)
> -endif
> -
> -update-map-file: $(libspice_client_gtkinclude_HEADERS)
> $(nodist_libspice_client_gtkinclude_HEADERS)
> $(libspice_client_glibinclude_HEADERS)
> $(nodist_libspice_client_glibinclude_HEADERS)
> - ( echo "SPICEGTK_1 {" ; \
> - echo "global:" ; \
> - ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1
> ";" }' | sort ; \
> - echo "local:" ; \
> - echo "*;" ; \
> - echo "};" ) > $(srcdir)/map-file
> -
> -update-glib-sym-file: $(libspice_client_glibinclude_HEADERS)
> $(nodist_libspice_client_glibinclude_HEADERS)
> - ( ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 }'
> | sort ; \
> - ) > $(srcdir)/spice-glib-sym-file
> -
> -update-gtk-sym-file: $(libspice_client_gtkinclude_HEADERS)
> $(nodist_libspice_client_gtkinclude_HEADERS)
> - ( ctags -f - -I G_GNUC_CONST --c-kinds=p $^ | awk '/^spice_/ { print $$1 }'
> | sort ; \
> - ) > $(srcdir)/spice-gtk-sym-file
> -
> -update-symbol-files: update-map-file update-glib-sym-file
> update-gtk-sym-file
> -
> --include $(top_srcdir)/git.mk
> diff --git a/gtk/bio-gio.c b/gtk/bio-gio.c
> deleted file mode 100644
> index 108ac1a..0000000
> --- a/gtk/bio-gio.c
> +++ /dev/null
> @@ -1,114 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2012 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#include <string.h>
> -#include <glib.h>
> -
> -#include "spice-util.h"
> -#include "bio-gio.h"
> -
> -typedef struct bio_gsocket_method {
> - BIO_METHOD method;
> - GIOStream *stream;
> -} bio_gsocket_method;
> -
> -#define BIO_GET_GSOCKET(bio) (((bio_gsocket_method*)bio->method)->gsocket)
> -#define BIO_GET_ISTREAM(bio)
> (g_io_stream_get_input_stream(((bio_gsocket_method*)bio->method)->stream))
> -#define BIO_GET_OSTREAM(bio)
> (g_io_stream_get_output_stream(((bio_gsocket_method*)bio->method)->stream))
> -
> -static int bio_gio_write(BIO *bio, const char *in, int inl)
> -{
> - gssize ret;
> - GError *error = NULL;
> -
> - ret =
> g_pollable_output_stream_write_nonblocking(G_POLLABLE_OUTPUT_STREAM(BIO_GET_OSTREAM(bio)),
> - in, inl, NULL, &error);
> - BIO_clear_retry_flags(bio);
> -
> - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
> - BIO_set_retry_write(bio);
> - if (error != NULL) {
> - g_warning("%s", error->message);
> - g_clear_error(&error);
> - }
> -
> - return ret;
> -}
> -
> -static int bio_gio_read(BIO *bio, char *out, int outl)
> -{
> - gssize ret;
> - GError *error = NULL;
> -
> - ret =
> g_pollable_input_stream_read_nonblocking(G_POLLABLE_INPUT_STREAM(BIO_GET_ISTREAM(bio)),
> - out, outl, NULL, &error);
> - BIO_clear_retry_flags(bio);
> -
> - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
> - BIO_set_retry_read(bio);
> - else if (error != NULL)
> - g_warning("%s", error->message);
> -
> - g_clear_error(&error);
> -
> - return ret;
> -}
> -
> -static int bio_gio_destroy(BIO *bio)
> -{
> - if (bio == NULL || bio->method == NULL)
> - return 0;
> -
> - SPICE_DEBUG("bio gsocket destroy");
> - g_free(bio->method);
> - bio->method = NULL;;
> -
> - return 1;
> -}
> -
> -static int bio_gio_puts(BIO *bio, const char *str)
> -{
> - int n, ret;
> -
> - n = strlen(str);
> - ret = bio_gio_write(bio, str, n);
> -
> - return ret;
> -}
> -
> -G_GNUC_INTERNAL
> -BIO* bio_new_giostream(GIOStream *stream)
> -{
> - // TODO: make an actual new BIO type, or just switch to GTls already...
> - BIO *bio = BIO_new_socket(-1, BIO_NOCLOSE);
> -
> - bio_gsocket_method *bio_method = g_new(bio_gsocket_method, 1);
> - bio_method->method = *bio->method;
> - bio_method->stream = stream;
> -
> - bio->method->destroy(bio);
> - bio->method = (BIO_METHOD*)bio_method;
> -
> - bio->method->bwrite = bio_gio_write;
> - bio->method->bread = bio_gio_read;
> - bio->method->bputs = bio_gio_puts;
> - bio->method->destroy = bio_gio_destroy;
> -
> - return bio;
> -}
> diff --git a/gtk/bio-gio.h b/gtk/bio-gio.h
> deleted file mode 100644
> index 31fd369..0000000
> --- a/gtk/bio-gio.h
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2012 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#ifndef BIO_GIO_H_
> -# define BIO_GIO_H_
> -
> -#include <openssl/bio.h>
> -#include <gio/gio.h>
> -
> -G_BEGIN_DECLS
> -
> -BIO* bio_new_giostream(GIOStream *stream);
> -
> -G_END_DECLS
> -
> -#endif /* !BIO_GIO_H_ */
> diff --git a/gtk/channel-base.c b/gtk/channel-base.c
> deleted file mode 100644
> index 77d339c..0000000
> --- a/gtk/channel-base.c
> +++ /dev/null
> @@ -1,284 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#include "spice-client.h"
> -#include "spice-common.h"
> -
> -#include "spice-session-priv.h"
> -#include "spice-channel-priv.h"
> -
> -/* coroutine context */
> -G_GNUC_INTERNAL
> -void spice_channel_handle_set_ack(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceChannelPrivate *c = channel->priv;
> - SpiceMsgSetAck* ack = spice_msg_in_parsed(in);
> - SpiceMsgOut *out = spice_msg_out_new(channel, SPICE_MSGC_ACK_SYNC);
> - SpiceMsgcAckSync sync = {
> - .generation = ack->generation,
> - };
> -
> - c->message_ack_window = c->message_ack_count = ack->window;
> - c->marshallers->msgc_ack_sync(out->marshaller, &sync);
> - spice_msg_out_send_internal(out);
> -}
> -
> -/* coroutine context */
> -G_GNUC_INTERNAL
> -void spice_channel_handle_ping(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceChannelPrivate *c = channel->priv;
> - SpiceMsgPing *ping = spice_msg_in_parsed(in);
> - SpiceMsgOut *pong = spice_msg_out_new(channel, SPICE_MSGC_PONG);
> -
> - c->marshallers->msgc_pong(pong->marshaller, ping);
> - spice_msg_out_send_internal(pong);
> -}
> -
> -/* coroutine context */
> -G_GNUC_INTERNAL
> -void spice_channel_handle_notify(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - static const char* severity_strings[] = {"info", "warn", "error"};
> - static const char* visibility_strings[] = {"!", "!!", "!!!"};
> -
> - SpiceMsgNotify *notify = spice_msg_in_parsed(in);
> - const char *severity = "?";
> - const char *visibility = "?";
> - const char *message_str = NULL;
> -
> - if (notify->severity <= SPICE_NOTIFY_SEVERITY_ERROR) {
> - severity = severity_strings[notify->severity];
> - }
> - if (notify->visibilty <= SPICE_NOTIFY_VISIBILITY_HIGH) {
> - visibility = visibility_strings[notify->visibilty];
> - }
> -
> - if (notify->message_len &&
> - notify->message_len <= in->dpos - sizeof(*notify)) {
> - message_str = (char*)notify->message;
> - }
> -
> - CHANNEL_DEBUG(channel, "%s -- %s%s #%u%s%.*s", __FUNCTION__,
> - severity, visibility, notify->what,
> - message_str ? ": " : "", notify->message_len,
> - message_str ? message_str : "");
> -}
> -
> -/* coroutine context */
> -G_GNUC_INTERNAL
> -void spice_channel_handle_disconnect(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisconnect *disconnect = spice_msg_in_parsed(in);
> -
> - CHANNEL_DEBUG(channel, "%s: ts: %" PRIu64", reason: %u", __FUNCTION__,
> - disconnect->time_stamp, disconnect->reason);
> -}
> -
> -typedef struct WaitForChannelData
> -{
> - SpiceWaitForChannel *wait;
> - SpiceChannel *channel;
> -} WaitForChannelData;
> -
> -/* coroutine and main context */
> -static gboolean wait_for_channel(gpointer data)
> -{
> - WaitForChannelData *wfc = data;
> - SpiceChannelPrivate *c = wfc->channel->priv;
> - SpiceChannel *wait_channel;
> -
> - wait_channel = spice_session_lookup_channel(c->session,
> wfc->wait->channel_id, wfc->wait->channel_type);
> - g_return_val_if_fail(wait_channel != NULL, TRUE);
> -
> - if (wait_channel->priv->last_message_serial >=
> wfc->wait->message_serial)
> - return TRUE;
> -
> - return FALSE;
> -}
> -
> -/* coroutine context */
> -G_GNUC_INTERNAL
> -void spice_channel_handle_wait_for_channels(SpiceChannel *channel,
> SpiceMsgIn *in)
> -{
> - SpiceChannelPrivate *c = channel->priv;
> - SpiceMsgWaitForChannels *wfc = spice_msg_in_parsed(in);
> - int i;
> -
> - for (i = 0; i < wfc->wait_count; ++i) {
> - WaitForChannelData data = {
> - .wait = wfc->wait_list + i,
> - .channel = channel
> - };
> -
> - CHANNEL_DEBUG(channel, "waiting for serial %" PRIu64 " (%d/%d)",
> data.wait->message_serial, i + 1, wfc->wait_count);
> - if (g_coroutine_condition_wait(&c->coroutine, wait_for_channel,
> &data))
> - CHANNEL_DEBUG(channel, "waiting for serial %" PRIu64 ", done",
> data.wait->message_serial);
> - else
> - CHANNEL_DEBUG(channel, "waiting for serial %" PRIu64 ",
> cancelled", data.wait->message_serial);
> - }
> -}
> -
> -static void
> -get_msg_handler(SpiceChannel *channel, SpiceMsgIn *in, gpointer data)
> -{
> - SpiceMsgIn **msg = data;
> -
> - g_return_if_fail(msg != NULL);
> - g_return_if_fail(*msg == NULL);
> -
> - spice_msg_in_ref(in);
> - *msg = in;
> -}
> -
> -/* coroutine context */
> -G_GNUC_INTERNAL
> -void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgOut *out;
> - SpiceMsgIn *data = NULL;
> - SpiceMsgMigrate *mig = spice_msg_in_parsed(in);
> - SpiceChannelPrivate *c = channel->priv;
> -
> - CHANNEL_DEBUG(channel, "%s: flags %u", __FUNCTION__, mig->flags);
> - if (mig->flags & SPICE_MIGRATE_NEED_FLUSH) {
> - /* if peer version > 1: pushing the mark msg before all other
> messgages and sending it,
> - * and only it */
> - if (c->peer_hdr.major_version == 1) {
> - /* iterate_write is blocking and flushing all pending write */
> - SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel);
> - }
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MIGRATE_FLUSH_MARK);
> - spice_msg_out_send_internal(out);
> - }
> - if (mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) {
> - spice_channel_recv_msg(channel, get_msg_handler, &data);
> - if (!data) {
> - g_critical("expected SPICE_MSG_MIGRATE_DATA, got empty
> message");
> - goto end;
> - } else if (spice_header_get_msg_type(data->header,
> c->use_mini_header) !=
> - SPICE_MSG_MIGRATE_DATA) {
> - g_critical("expected SPICE_MSG_MIGRATE_DATA, got %d",
> - spice_header_get_msg_type(data->header,
> c->use_mini_header));
> - goto end;
> - }
> - }
> -
> - /* swapping channels sockets */
> - spice_session_channel_migrate(c->session, channel);
> -
> - /* pushing the MIGRATE_DATA before all other pending messages */
> - if ((mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) && (data != NULL)) {
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MIGRATE_DATA);
> - spice_marshaller_add(out->marshaller, data->data,
> - spice_header_get_msg_size(data->header,
> c->use_mini_header));
> - spice_msg_out_send_internal(out);
> - }
> -
> -end:
> - if (data)
> - spice_msg_in_unref(data);
> -}
> -
> -
> -static void set_handlers(SpiceChannelClass *klass,
> - const spice_msg_handler* handlers, const int n)
> -{
> - int i;
> -
> - g_array_set_size(klass->handlers, MAX(klass->handlers->len, n));
> - for (i = 0; i < n; i++) {
> - if (handlers[i])
> - g_array_index(klass->handlers, spice_msg_handler, i) =
> handlers[i];
> - }
> -}
> -
> -static void spice_channel_add_base_handlers(SpiceChannelClass *klass)
> -{
> - static const spice_msg_handler handlers[] = {
> - [ SPICE_MSG_SET_ACK ] =
> spice_channel_handle_set_ack,
> - [ SPICE_MSG_PING ] = spice_channel_handle_ping,
> - [ SPICE_MSG_NOTIFY ] =
> spice_channel_handle_notify,
> - [ SPICE_MSG_DISCONNECTING ] =
> spice_channel_handle_disconnect,
> - [ SPICE_MSG_WAIT_FOR_CHANNELS ] =
> spice_channel_handle_wait_for_channels,
> - [ SPICE_MSG_MIGRATE ] =
> spice_channel_handle_migrate,
> - };
> -
> - set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
> -}
> -
> -G_GNUC_INTERNAL
> -void spice_channel_set_handlers(SpiceChannelClass *klass,
> - const spice_msg_handler* handlers, const int
> n)
> -{
> - /* FIXME: use class private (requires glib 2.24) */
> - g_return_if_fail(klass->handlers == NULL);
> - klass->handlers = g_array_sized_new(FALSE, TRUE,
> sizeof(spice_msg_handler), n);
> -
> - spice_channel_add_base_handlers(klass);
> - set_handlers(klass, handlers, n);
> -}
> -
> -static void
> -vmc_write_free_cb(uint8_t *data, void *user_data)
> -{
> - GSimpleAsyncResult *result = user_data;
> -
> - g_simple_async_result_complete_in_idle(result);
> - g_object_unref(result);
> -}
> -
> -G_GNUC_INTERNAL
> -void spice_vmc_write_async(SpiceChannel *self,
> - const void *buffer, gsize count,
> - GCancellable *cancellable,
> - GAsyncReadyCallback callback,
> - gpointer user_data)
> -{
> - SpiceMsgOut *msg;
> - GSimpleAsyncResult *simple;
> -
> - simple = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
> - spice_port_write_async);
> - g_simple_async_result_set_op_res_gssize(simple, count);
> -
> - msg = spice_msg_out_new(SPICE_CHANNEL(self), SPICE_MSGC_SPICEVMC_DATA);
> - spice_marshaller_add_ref_full(msg->marshaller, (uint8_t*)buffer, count,
> - vmc_write_free_cb, simple);
> - spice_msg_out_send(msg);
> -}
> -
> -G_GNUC_INTERNAL
> -gssize spice_vmc_write_finish(SpiceChannel *self,
> - GAsyncResult *result, GError **error)
> -{
> - GSimpleAsyncResult *simple;
> -
> - g_return_val_if_fail(result != NULL, -1);
> -
> - simple = (GSimpleAsyncResult *)result;
> -
> - if (g_simple_async_result_propagate_error(simple, error))
> - return -1;
> -
> - g_return_val_if_fail(g_simple_async_result_is_valid(result,
> G_OBJECT(self),
> -
> spice_port_write_async),
> -1);
> -
> - return g_simple_async_result_get_op_res_gssize(simple);
> -}
> diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c
> deleted file mode 100644
> index e6514a2..0000000
> --- a/gtk/channel-cursor.c
> +++ /dev/null
> @@ -1,529 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#include "glib-compat.h"
> -#include "spice-client.h"
> -#include "spice-common.h"
> -
> -#include "spice-channel-priv.h"
> -#include "spice-channel-cache.h"
> -#include "spice-marshal.h"
> -
> -/**
> - * SECTION:channel-cursor
> - * @short_description: update cursor shape and position
> - * @title: Cursor Channel
> - * @section_id:
> - * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay
> - * @stability: Stable
> - * @include: channel-cursor.h
> - *
> - * The Spice protocol defines a set of messages for controlling cursor
> - * shape and position on the remote display area. The cursor changes
> - * that should be reflected on the display are notified by
> - * signals. See for example #SpiceCursorChannel::cursor-set
> - * #SpiceCursorChannel::cursor-move signals.
> - */
> -
> -#define SPICE_CURSOR_CHANNEL_GET_PRIVATE(obj)
> \
> - (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_CURSOR_CHANNEL,
> SpiceCursorChannelPrivate))
> -
> -typedef struct display_cursor display_cursor;
> -
> -struct display_cursor {
> - SpiceCursorHeader hdr;
> - gboolean default_cursor;
> - int refcount;
> - guint32 data[];
> -};
> -
> -struct _SpiceCursorChannelPrivate {
> - display_cache *cursors;
> - gboolean init_done;
> -};
> -
> -enum {
> - SPICE_CURSOR_SET,
> - SPICE_CURSOR_MOVE,
> - SPICE_CURSOR_HIDE,
> - SPICE_CURSOR_RESET,
> -
> - SPICE_CURSOR_LAST_SIGNAL,
> -};
> -
> -static guint signals[SPICE_CURSOR_LAST_SIGNAL];
> -
> -static display_cursor * display_cursor_ref(display_cursor *cursor);
> -static void display_cursor_unref(display_cursor *cursor);
> -static void channel_set_handlers(SpiceChannelClass *klass);
> -
> -G_DEFINE_TYPE(SpiceCursorChannel, spice_cursor_channel, SPICE_TYPE_CHANNEL)
> -
> -/* ------------------------------------------------------------------ */
> -
> -static void spice_cursor_channel_init(SpiceCursorChannel *channel)
> -{
> - SpiceCursorChannelPrivate *c;
> -
> - c = channel->priv = SPICE_CURSOR_CHANNEL_GET_PRIVATE(channel);
> -
> - c->cursors = cache_new((GDestroyNotify)display_cursor_unref);
> -}
> -
> -static void spice_cursor_channel_finalize(GObject *obj)
> -{
> - SpiceCursorChannel *channel = SPICE_CURSOR_CHANNEL(obj);
> - SpiceCursorChannelPrivate *c = channel->priv;
> -
> - g_clear_pointer(&c->cursors, cache_unref);
> -
> - if (G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize)
> - G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize(obj);
> -}
> -
> -/* coroutine context */
> -static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean
> migrating)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - cache_clear(c->cursors);
> - c->init_done = FALSE;
> -
> -
> SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel,
> migrating);
> -}
> -
> -static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
> -{
> - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
> - SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
> -
> - gobject_class->finalize = spice_cursor_channel_finalize;
> - channel_class->channel_reset = spice_cursor_channel_reset;
> -
> - /**
> - * SpiceCursorChannel::cursor-set:
> - * @cursor: the #SpiceCursorChannel that emitted the signal
> - * @width: width of the shape
> - * @height: height of the shape
> - * @hot_x: horizontal offset of the 'hotspot' of the cursor
> - * @hot_y: vertical offset of the 'hotspot' of the cursor
> - * @rgba: 32bits shape data, or %NULL if default cursor. It might
> - * be freed after the signal is emitted, so make sure to copy it
> - * if you need it later!
> - *
> - * The #SpiceCursorChannel::cursor-set signal is emitted to modify
> - * cursor aspect and position on the display area.
> - **/
> - signals[SPICE_CURSOR_SET] =
> - g_signal_new("cursor-set",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_set),
> - NULL, NULL,
> - g_cclosure_user_marshal_VOID__INT_INT_INT_INT_POINTER,
> - G_TYPE_NONE,
> - 5,
> - G_TYPE_INT, G_TYPE_INT,
> - G_TYPE_INT, G_TYPE_INT,
> - G_TYPE_POINTER);
> -
> - /**
> - * SpiceCursorChannel::cursor-move:
> - * @cursor: the #SpiceCursorChannel that emitted the signal
> - * @x: x position
> - * @y: y position
> - *
> - * The #SpiceCursorChannel::cursor-move signal is emitted to update
> - * the cursor position on the display area.
> - **/
> - signals[SPICE_CURSOR_MOVE] =
> - g_signal_new("cursor-move",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_move),
> - NULL, NULL,
> - g_cclosure_user_marshal_VOID__INT_INT,
> - G_TYPE_NONE,
> - 2,
> - G_TYPE_INT, G_TYPE_INT);
> -
> - /**
> - * SpiceCursorChannel::cursor-hide:
> - * @cursor: the #SpiceCursorChannel that emitted the signal
> - *
> - * The #SpiceCursorChannel::cursor-hide signal is emitted to hide
> - * the cursor/pointer on the display area.
> - **/
> - signals[SPICE_CURSOR_HIDE] =
> - g_signal_new("cursor-hide",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_hide),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> -
> - /**
> - * SpiceCursorChannel::cursor-reset:
> - * @cursor: the #SpiceCursorChannel that emitted the signal
> - *
> - * The #SpiceCursorChannel::cursor-reset signal is emitted to
> - * reset the cursor to its default context.
> - **/
> - signals[SPICE_CURSOR_RESET] =
> - g_signal_new("cursor-reset",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceCursorChannelClass, cursor_reset),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> -
> - g_type_class_add_private(klass, sizeof(SpiceCursorChannelPrivate));
> - channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -#ifdef DEBUG_CURSOR
> -static void print_cursor(display_cursor *cursor, const guint8 *data)
> -{
> - int x, y, bpl;
> - const guint8 *xor, *and;
> -
> - bpl = (cursor->hdr.width + 7) / 8;
> - and = data;
> - xor = and + bpl * cursor->hdr.height;
> -
> - printf("data (%d x %d):\n", cursor->hdr.width, cursor->hdr.height);
> - for (y = 0 ; y < cursor->hdr.height; ++y) {
> - for (x = 0 ; x < cursor->hdr.width / 8; x++) {
> - printf("%02X", and[x]);
> - }
> - and += bpl;
> - printf("\n");
> - }
> - printf("xor:\n");
> - for (y = 0 ; y < cursor->hdr.height; ++y) {
> - for (x = 0 ; x < cursor->hdr.width / 8; ++x) {
> - printf("%02X", xor[x]);
> - }
> - xor += bpl;
> - printf("\n");
> - }
> -}
> -#endif
> -
> -static void mono_cursor(display_cursor *cursor, const guint8 *data)
> -{
> - int bpl = (cursor->hdr.width + 7) / 8;
> - const guint8 *xor, *and;
> - guint8 *dest;
> - dest = (uint8_t *)cursor->data;
> -
> -#ifdef DEBUG_CURSOR
> - print_cursor(cursor, data);
> -#endif
> - and = data;
> - xor = and + bpl * cursor->hdr.height;
> - spice_mono_edge_highlight(cursor->hdr.width, cursor->hdr.height,
> - and, xor, dest);
> -}
> -
> -static guint8 get_pix_mask(const guint8 *data, gint offset, gint pix_index)
> -{
> - return data[offset + (pix_index >> 3)] & (0x80 >> (pix_index % 8));
> -}
> -
> -static guint32 get_pix_hack(gint pix_index, gint width)
> -{
> - return (((pix_index % width) ^ (pix_index / width)) & 1) ? 0xc0303030 :
> 0x30505050;
> -}
> -
> -static display_cursor * display_cursor_ref(display_cursor *cursor)
> -{
> - g_return_val_if_fail(cursor != NULL, NULL);
> - g_return_val_if_fail(cursor->refcount > 0, NULL);
> -
> - cursor->refcount++;
> - return cursor;
> -}
> -
> -static void display_cursor_unref(display_cursor *cursor)
> -{
> - g_return_if_fail(cursor != NULL);
> - g_return_if_fail(cursor->refcount > 0);
> -
> - cursor->refcount--;
> - if (cursor->refcount == 0)
> - g_free(cursor);
> -}
> -
> -static const char *cursor_type_to_string(int type)
> -{
> - switch (type) {
> - case SPICE_CURSOR_TYPE_MONO:
> - return "mono";
> - case SPICE_CURSOR_TYPE_ALPHA:
> - return "alpha";
> - case SPICE_CURSOR_TYPE_COLOR32:
> - return "color32";
> - case SPICE_CURSOR_TYPE_COLOR16:
> - return "color16";
> - case SPICE_CURSOR_TYPE_COLOR4:
> - return "color4";
> - }
> - return "unknown";
> -}
> -
> -static display_cursor *set_cursor(SpiceChannel *channel, SpiceCursor
> *scursor)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> - SpiceCursorHeader *hdr = &scursor->header;
> - display_cursor *cursor;
> - size_t size;
> - gint i, pix_mask, pix;
> - const guint8* data;
> - guint8 *rgba;
> - guint8 val;
> -
> - CHANNEL_DEBUG(channel, "%s: flags %d, size %d", __FUNCTION__,
> - scursor->flags, scursor->data_size);
> -
> - if (scursor->flags & SPICE_CURSOR_FLAGS_NONE)
> - return NULL;
> -
> - CHANNEL_DEBUG(channel, "%s: type %s(%d), %" PRIx64 ", %dx%d",
> __FUNCTION__,
> - cursor_type_to_string(hdr->type), hdr->type, hdr->unique,
> - hdr->width, hdr->height);
> -
> - if (scursor->flags & SPICE_CURSOR_FLAGS_FROM_CACHE) {
> - cursor = cache_find(c->cursors, hdr->unique);
> - g_return_val_if_fail(cursor != NULL, NULL);
> - return display_cursor_ref(cursor);
> - }
> -
> - g_return_val_if_fail(scursor->data_size != 0, NULL);
> -
> - size = 4u * hdr->width * hdr->height;
> - cursor = g_malloc0(sizeof(*cursor) + size);
> - cursor->hdr = *hdr;
> - cursor->default_cursor = FALSE;
> - cursor->refcount = 1;
> - data = scursor->data;
> -
> - switch (hdr->type) {
> - case SPICE_CURSOR_TYPE_MONO:
> - mono_cursor(cursor, data);
> - break;
> - case SPICE_CURSOR_TYPE_ALPHA:
> - memcpy(cursor->data, data, size);
> - break;
> - case SPICE_CURSOR_TYPE_COLOR32:
> - memcpy(cursor->data, data, size);
> - for (i = 0; i < hdr->width * hdr->height; i++) {
> - pix_mask = get_pix_mask(data, size, i);
> - if (pix_mask && *((guint32*)data + i) == 0xffffff) {
> - cursor->data[i] = get_pix_hack(i, hdr->width);
> - } else {
> - cursor->data[i] |= (pix_mask ? 0 : 0xff000000);
> - }
> - }
> - break;
> - case SPICE_CURSOR_TYPE_COLOR16:
> - for (i = 0; i < hdr->width * hdr->height; i++) {
> - pix_mask = get_pix_mask(data, size, i);
> - pix = *((guint16*)data + i);
> - if (pix_mask && pix == 0x7fff) {
> - cursor->data[i] = get_pix_hack(i, hdr->width);
> - } else {
> - cursor->data[i] |= ((pix & 0x1f) << 3) | ((pix & 0x3e0) <<
> 6) |
> - ((pix & 0x7c00) << 9) | (pix_mask ? 0 : 0xff000000);
> - }
> - }
> - break;
> - case SPICE_CURSOR_TYPE_COLOR4:
> - size = ((unsigned int)(SPICE_ALIGN(hdr->width, 2) / 2)) *
> hdr->height;
> - for (i = 0; i < hdr->width * hdr->height; i++) {
> - pix_mask = get_pix_mask(data, size + (sizeof(uint32_t) << 4),
> i);
> - int idx = (i & 1) ? (data[i >> 1] & 0x0f) : ((data[i >> 1] &
> 0xf0) >> 4);
> - pix = *((uint32_t*)(data + size) + idx);
> - if (pix_mask && pix == 0xffffff) {
> - cursor->data[i] = get_pix_hack(i, hdr->width);
> - } else {
> - cursor->data[i] = pix | (pix_mask ? 0 : 0xff000000);
> - }
> - }
> -
> - break;
> - default:
> - g_warning("%s: unimplemented cursor type %d", __FUNCTION__,
> - hdr->type);
> - cursor->default_cursor = TRUE;
> - goto cache_add;
> - }
> -
> - rgba = (guint8*)cursor->data;
> - for (i = 0; i < hdr->width * hdr->height; i++) {
> - val = rgba[0];
> - rgba[0] = rgba[2];
> - rgba[2] = val;
> - rgba += 4;
> - }
> -
> -cache_add:
> - if (scursor->flags & SPICE_CURSOR_FLAGS_CACHE_ME) {
> - cache_add(c->cursors, hdr->unique, display_cursor_ref(cursor));
> - }
> -
> - return cursor;
> -}
> -
> -/* coroutine context */
> -static void emit_cursor_set(SpiceChannel *channel, display_cursor *cursor)
> -{
> - g_return_if_fail(cursor != NULL);
> - g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_SET], 0,
> - cursor->hdr.width, cursor->hdr.height,
> - cursor->hdr.hot_spot_x, cursor->hdr.hot_spot_y,
> - cursor->default_cursor ? NULL : cursor->data);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgCursorInit *init = spice_msg_in_parsed(in);
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> - display_cursor *cursor;
> -
> - g_return_if_fail(c->init_done == FALSE);
> -
> - cache_clear(c->cursors);
> - cursor = set_cursor(channel, &init->cursor);
> - c->init_done = TRUE;
> - if (cursor)
> - emit_cursor_set(channel, cursor);
> - if (!init->visible || !cursor)
> - g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0);
> - if (cursor)
> - display_cursor_unref(cursor);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_reset(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - CHANNEL_DEBUG(channel, "%s, init_done: %d", __FUNCTION__, c->init_done);
> -
> - cache_clear(c->cursors);
> - g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_RESET], 0);
> - c->init_done = FALSE;
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_set(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgCursorSet *set = spice_msg_in_parsed(in);
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> - display_cursor *cursor;
> -
> - g_return_if_fail(c->init_done == TRUE);
> -
> - cursor = set_cursor(channel, &set->cursor);
> - if (cursor)
> - emit_cursor_set(channel, cursor);
> - else
> - g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0);
> -
> -
> - if (cursor)
> - display_cursor_unref(cursor);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_move(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgCursorMove *move = spice_msg_in_parsed(in);
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - g_return_if_fail(c->init_done == TRUE);
> -
> - g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_MOVE], 0,
> - move->position.x, move->position.y);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_hide(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> -#ifdef EXTRA_CHECKS
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - g_return_if_fail(c->init_done == TRUE);
> -#endif
> -
> - g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_HIDE], 0);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_trail(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - g_return_if_fail(c->init_done == TRUE);
> -
> - g_warning("%s: TODO", __FUNCTION__);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_inval_one(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> - SpiceMsgDisplayInvalOne *zap = spice_msg_in_parsed(in);
> -
> - g_return_if_fail(c->init_done == TRUE);
> -
> - cache_remove(c->cursors, zap->id);
> -}
> -
> -/* coroutine context */
> -static void cursor_handle_inval_all(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv;
> -
> - cache_clear(c->cursors);
> -}
> -
> -static void channel_set_handlers(SpiceChannelClass *klass)
> -{
> - static const spice_msg_handler handlers[] = {
> - [ SPICE_MSG_CURSOR_INIT ] = cursor_handle_init,
> - [ SPICE_MSG_CURSOR_RESET ] = cursor_handle_reset,
> - [ SPICE_MSG_CURSOR_SET ] = cursor_handle_set,
> - [ SPICE_MSG_CURSOR_MOVE ] = cursor_handle_move,
> - [ SPICE_MSG_CURSOR_HIDE ] = cursor_handle_hide,
> - [ SPICE_MSG_CURSOR_TRAIL ] = cursor_handle_trail,
> - [ SPICE_MSG_CURSOR_INVAL_ONE ] = cursor_handle_inval_one,
> - [ SPICE_MSG_CURSOR_INVAL_ALL ] = cursor_handle_inval_all,
> - };
> -
> - spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
> -}
> diff --git a/gtk/channel-cursor.h b/gtk/channel-cursor.h
> deleted file mode 100644
> index 5b5ed47..0000000
> --- a/gtk/channel-cursor.h
> +++ /dev/null
> @@ -1,77 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#ifndef __SPICE_CLIENT_CURSOR_CHANNEL_H__
> -#define __SPICE_CLIENT_CURSOR_CHANNEL_H__
> -
> -#include "spice-client.h"
> -
> -G_BEGIN_DECLS
> -
> -#define SPICE_TYPE_CURSOR_CHANNEL
> (spice_cursor_channel_get_type())
> -#define SPICE_CURSOR_CHANNEL(obj)
> (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_CURSOR_CHANNEL,
> SpiceCursorChannel))
> -#define SPICE_CURSOR_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_CURSOR_CHANNEL,
> SpiceCursorChannelClass))
> -#define SPICE_IS_CURSOR_CHANNEL(obj)
> (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_CURSOR_CHANNEL))
> -#define SPICE_IS_CURSOR_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_CURSOR_CHANNEL))
> -#define SPICE_CURSOR_CHANNEL_GET_CLASS(obj)
> (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_CURSOR_CHANNEL,
> SpiceCursorChannelClass))
> -
> -typedef struct _SpiceCursorChannel SpiceCursorChannel;
> -typedef struct _SpiceCursorChannelClass SpiceCursorChannelClass;
> -typedef struct _SpiceCursorChannelPrivate SpiceCursorChannelPrivate;
> -
> -/**
> - * SpiceCursorChannel:
> - *
> - * The #SpiceCursorChannel struct is opaque and should not be accessed
> directly.
> - */
> -struct _SpiceCursorChannel {
> - SpiceChannel parent;
> -
> - /*< private >*/
> - SpiceCursorChannelPrivate *priv;
> - /* Do not add fields to this struct */
> -};
> -
> -/**
> - * SpiceCursorChannelClass:
> - * @parent_class: Parent class.
> - * @cursor_set: Signal class handler for the #SpiceCursorChannel::cursor-set
> signal.
> - * @cursor_move: Signal class handler for the
> #SpiceCursorChannel::cursor-move signal.
> - * @cursor_hide: Signal class handler for the
> #SpiceCursorChannel::cursor-hide signal.
> - * @cursor_reset: Signal class handler for the
> #SpiceCursorChannel::cursor-reset signal.
> - *
> - * Class structure for #SpiceCursorChannel.
> - */
> -struct _SpiceCursorChannelClass {
> - SpiceChannelClass parent_class;
> -
> - /* signals */
> - void (*cursor_set)(SpiceCursorChannel *channel, gint width, gint height,
> - gint hot_x, gint hot_y, gpointer rgba);
> - void (*cursor_move)(SpiceCursorChannel *channel, gint x, gint y);
> - void (*cursor_hide)(SpiceCursorChannel *channel);
> - void (*cursor_reset)(SpiceCursorChannel *channel);
> -
> - /*< private >*/
> - /* Do not add fields to this struct */
> -};
> -
> -GType spice_cursor_channel_get_type(void);
> -
> -G_END_DECLS
> -
> -#endif /* __SPICE_CLIENT_CURSOR_CHANNEL_H__ */
> diff --git a/gtk/channel-display-mjpeg.c b/gtk/channel-display-mjpeg.c
> deleted file mode 100644
> index 95d5b33..0000000
> --- a/gtk/channel-display-mjpeg.c
> +++ /dev/null
> @@ -1,156 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#include "spice-client.h"
> -#include "spice-common.h"
> -#include "spice-channel-priv.h"
> -
> -#include "channel-display-priv.h"
> -
> -static void mjpeg_src_init(struct jpeg_decompress_struct *cinfo)
> -{
> - display_stream *st = SPICE_CONTAINEROF(cinfo->src, display_stream,
> mjpeg_src);
> - uint8_t *data;
> -
> - cinfo->src->bytes_in_buffer = stream_get_current_frame(st, &data);
> - cinfo->src->next_input_byte = data;
> -}
> -
> -static boolean mjpeg_src_fill(struct jpeg_decompress_struct *cinfo)
> -{
> - g_critical("need more input data");
> - return 0;
> -}
> -
> -static void mjpeg_src_skip(struct jpeg_decompress_struct *cinfo,
> - long num_bytes)
> -{
> - cinfo->src->next_input_byte += num_bytes;
> -}
> -
> -static void mjpeg_src_term(struct jpeg_decompress_struct *cinfo)
> -{
> - /* nothing */
> -}
> -
> -G_GNUC_INTERNAL
> -void stream_mjpeg_init(display_stream *st)
> -{
> - st->mjpeg_cinfo.err = jpeg_std_error(&st->mjpeg_jerr);
> - jpeg_create_decompress(&st->mjpeg_cinfo);
> -
> - st->mjpeg_src.init_source = mjpeg_src_init;
> - st->mjpeg_src.fill_input_buffer = mjpeg_src_fill;
> - st->mjpeg_src.skip_input_data = mjpeg_src_skip;
> - st->mjpeg_src.resync_to_restart = jpeg_resync_to_restart;
> - st->mjpeg_src.term_source = mjpeg_src_term;
> - st->mjpeg_cinfo.src = &st->mjpeg_src;
> -}
> -
> -G_GNUC_INTERNAL
> -void stream_mjpeg_data(display_stream *st)
> -{
> - gboolean back_compat = st->channel->priv->peer_hdr.major_version == 1;
> - int width;
> - int height;
> - uint8_t *dest;
> - uint8_t *lines[4];
> -
> - stream_get_dimensions(st, &width, &height);
> - dest = g_malloc0(width * height * 4);
> -
> - g_free(st->out_frame);
> - st->out_frame = dest;
> -
> - jpeg_read_header(&st->mjpeg_cinfo, 1);
> -#ifdef JCS_EXTENSIONS
> - // requires jpeg-turbo
> - if (back_compat)
> - st->mjpeg_cinfo.out_color_space = JCS_EXT_RGBX;
> - else
> - st->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX;
> -#else
> -#warning "You should consider building with libjpeg-turbo"
> - st->mjpeg_cinfo.out_color_space = JCS_RGB;
> -#endif
> -
> -#ifndef SPICE_QUALITY
> - st->mjpeg_cinfo.dct_method = JDCT_IFAST;
> - st->mjpeg_cinfo.do_fancy_upsampling = FALSE;
> - st->mjpeg_cinfo.do_block_smoothing = FALSE;
> - st->mjpeg_cinfo.dither_mode = JDITHER_ORDERED;
> -#endif
> - // TODO: in theory should check cinfo.output_height match with our
> height
> - jpeg_start_decompress(&st->mjpeg_cinfo);
> - /* rec_outbuf_height is the recommended size of the output buffer we
> - * pass to libjpeg for optimum performance
> - */
> - if (st->mjpeg_cinfo.rec_outbuf_height > G_N_ELEMENTS(lines)) {
> - jpeg_abort_decompress(&st->mjpeg_cinfo);
> - g_return_if_reached();
> - }
> -
> - while (st->mjpeg_cinfo.output_scanline < st->mjpeg_cinfo.output_height)
> {
> - /* only used when JCS_EXTENSIONS is undefined */
> - G_GNUC_UNUSED unsigned int lines_read;
> -
> - for (unsigned int j = 0; j < st->mjpeg_cinfo.rec_outbuf_height; j++)
> {
> - lines[j] = dest;
> -#ifdef JCS_EXTENSIONS
> - dest += 4 * width;
> -#else
> - dest += 3 * width;
> -#endif
> - }
> - lines_read = jpeg_read_scanlines(&st->mjpeg_cinfo, lines,
> - st->mjpeg_cinfo.rec_outbuf_height);
> -#ifndef JCS_EXTENSIONS
> - {
> - uint8_t *s = lines[0];
> - uint32_t *d = (uint32_t *)s;
> -
> - if (back_compat) {
> - for (unsigned int j = lines_read * width; j > 0; ) {
> - j -= 1; // reverse order, bad for cache?
> - d[j] = s[j * 3 + 0] |
> - s[j * 3 + 1] << 8 |
> - s[j * 3 + 2] << 16;
> - }
> - } else {
> - for (unsigned int j = lines_read * width; j > 0; ) {
> - j -= 1; // reverse order, bad for cache?
> - d[j] = s[j * 3 + 0] << 16 |
> - s[j * 3 + 1] << 8 |
> - s[j * 3 + 2];
> - }
> - }
> - }
> -#endif
> - dest = &st->out_frame[st->mjpeg_cinfo.output_scanline * width * 4];
> - }
> - jpeg_finish_decompress(&st->mjpeg_cinfo);
> -}
> -
> -G_GNUC_INTERNAL
> -void stream_mjpeg_cleanup(display_stream *st)
> -{
> - jpeg_destroy_decompress(&st->mjpeg_cinfo);
> - g_free(st->out_frame);
> - st->out_frame = NULL;
> -}
> diff --git a/gtk/channel-display-priv.h b/gtk/channel-display-priv.h
> deleted file mode 100644
> index 71f5d17..0000000
> --- a/gtk/channel-display-priv.h
> +++ /dev/null
> @@ -1,113 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#ifndef CHANNEL_DISPLAY_PRIV_H_
> -# define CHANNEL_DISPLAY_PRIV_H_
> -
> -#include <pixman.h>
> -#ifdef WIN32
> -/* We need some hacks to avoid warnings from the jpeg headers */
> -#define HAVE_BOOLEAN
> -#define XMD_H
> -#endif
> -#include <jpeglib.h>
> -
> -#include "common/canvas_utils.h"
> -#include "client_sw_canvas.h"
> -#include "common/ring.h"
> -#include "common/quic.h"
> -#include "common/rop3.h"
> -
> -G_BEGIN_DECLS
> -
> -
> -typedef struct display_surface {
> - guint32 surface_id;
> - bool primary;
> - enum SpiceSurfaceFmt format;
> - int width, height, stride, size;
> - int shmid;
> - uint8_t *data;
> - SpiceCanvas *canvas;
> - SpiceGlzDecoder *glz_decoder;
> - SpiceZlibDecoder *zlib_decoder;
> - SpiceJpegDecoder *jpeg_decoder;
> -} display_surface;
> -
> -typedef struct drops_sequence_stats {
> - uint32_t len;
> - uint32_t start_mm_time;
> - uint32_t duration;
> -} drops_sequence_stats;
> -
> -typedef struct display_stream {
> - SpiceMsgIn *msg_create;
> - SpiceMsgIn *msg_clip;
> - SpiceMsgIn *msg_data;
> -
> - /* from messages */
> - display_surface *surface;
> - SpiceClip *clip;
> - QRegion region;
> - int have_region;
> - int codec;
> -
> - /* mjpeg decoder */
> - struct jpeg_source_mgr mjpeg_src;
> - struct jpeg_decompress_struct mjpeg_cinfo;
> - struct jpeg_error_mgr mjpeg_jerr;
> -
> - uint8_t *out_frame;
> - GQueue *msgq;
> - guint timeout;
> - SpiceChannel *channel;
> -
> - /* stats */
> - uint32_t first_frame_mm_time;
> - uint32_t num_drops_on_receive;
> - uint64_t arrive_late_time;
> - uint32_t num_drops_on_playback;
> - uint32_t num_input_frames;
> - drops_sequence_stats cur_drops_seq_stats;
> - GArray *drops_seqs_stats_arr;
> - uint32_t num_drops_seqs;
> -
> - uint32_t playback_sync_drops_seq_len;
> -
> - /* playback quality report to server */
> - gboolean report_is_active;
> - uint32_t report_id;
> - uint32_t report_max_window;
> - uint32_t report_timeout;
> - uint64_t report_start_time;
> - uint32_t report_start_frame_time;
> - uint32_t report_num_frames;
> - uint32_t report_num_drops;
> - uint32_t report_drops_seq_len;
> -} display_stream;
> -
> -void stream_get_dimensions(display_stream *st, int *width, int *height);
> -uint32_t stream_get_current_frame(display_stream *st, uint8_t **data);
> -
> -/* channel-display-mjpeg.c */
> -void stream_mjpeg_init(display_stream *st);
> -void stream_mjpeg_data(display_stream *st);
> -void stream_mjpeg_cleanup(display_stream *st);
> -
> -G_END_DECLS
> -
> -#endif // CHANNEL_DISPLAY_PRIV_H_
> diff --git a/gtk/channel-display.c b/gtk/channel-display.c
> deleted file mode 100644
> index efe2259..0000000
> --- a/gtk/channel-display.c
> +++ /dev/null
> @@ -1,1789 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#ifdef HAVE_SYS_TYPES_H
> -#include <sys/types.h>
> -#endif
> -
> -#ifdef HAVE_SYS_SHM_H
> -#include <sys/shm.h>
> -#endif
> -
> -#ifdef HAVE_SYS_IPC_H
> -#include <sys/ipc.h>
> -#endif
> -
> -#include "glib-compat.h"
> -#include "spice-client.h"
> -#include "spice-common.h"
> -
> -#include "spice-marshal.h"
> -#include "spice-channel-priv.h"
> -#include "spice-session-priv.h"
> -#include "channel-display-priv.h"
> -#include "decode.h"
> -
> -/**
> - * SECTION:channel-display
> - * @short_description: remote display area
> - * @title: Display Channel
> - * @section_id:
> - * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay
> - * @stability: Stable
> - * @include: channel-display.h
> - *
> - * A class that handles the rendering of the remote display and inform
> - * of its updates.
> - *
> - * The creation of the main graphic buffer is signaled with
> - * #SpiceDisplayChannel::display-primary-create.
> - *
> - * The update of regions is notified by
> - * #SpiceDisplayChannel::display-invalidate signals.
> - */
> -
> -#define SPICE_DISPLAY_CHANNEL_GET_PRIVATE(obj)
> \
> - (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_DISPLAY_CHANNEL,
> SpiceDisplayChannelPrivate))
> -
> -#define MONITORS_MAX 256
> -
> -struct _SpiceDisplayChannelPrivate {
> - GHashTable *surfaces;
> - display_surface *primary;
> - display_cache *images;
> - display_cache *palettes;
> - SpiceImageCache image_cache;
> - SpicePaletteCache palette_cache;
> - SpiceImageSurfaces image_surfaces;
> - SpiceGlzDecoderWindow *glz_window;
> - display_stream **streams;
> - int nstreams;
> - gboolean mark;
> - guint mark_false_event_id;
> - GArray *monitors;
> - guint monitors_max;
> - gboolean enable_adaptive_streaming;
> -#ifdef G_OS_WIN32
> - HDC dc;
> -#endif
> -};
> -
> -G_DEFINE_TYPE(SpiceDisplayChannel, spice_display_channel,
> SPICE_TYPE_CHANNEL)
> -
> -/* Properties */
> -enum {
> - PROP_0,
> - PROP_WIDTH,
> - PROP_HEIGHT,
> - PROP_MONITORS,
> - PROP_MONITORS_MAX
> -};
> -
> -enum {
> - SPICE_DISPLAY_PRIMARY_CREATE,
> - SPICE_DISPLAY_PRIMARY_DESTROY,
> - SPICE_DISPLAY_INVALIDATE,
> - SPICE_DISPLAY_MARK,
> -
> - SPICE_DISPLAY_LAST_SIGNAL,
> -};
> -
> -static guint signals[SPICE_DISPLAY_LAST_SIGNAL];
> -
> -static void spice_display_channel_up(SpiceChannel *channel);
> -static void channel_set_handlers(SpiceChannelClass *klass);
> -
> -static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary);
> -static void clear_streams(SpiceChannel *channel);
> -static display_surface *find_surface(SpiceDisplayChannelPrivate *c, guint32
> surface_id);
> -static gboolean display_stream_render(display_stream *st);
> -static void spice_display_channel_reset(SpiceChannel *channel, gboolean
> migrating);
> -static void spice_display_channel_reset_capabilities(SpiceChannel *channel);
> -static void destroy_canvas(display_surface *surface);
> -static void _msg_in_unref_func(gpointer data, gpointer user_data);
> -static void display_session_mm_time_reset_cb(SpiceSession *session, gpointer
> data);
> -
> -/* ------------------------------------------------------------------ */
> -
> -static void spice_display_channel_dispose(GObject *object)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv;
> -
> - if (c->mark_false_event_id != 0) {
> - g_source_remove(c->mark_false_event_id);
> - c->mark_false_event_id = 0;
> - }
> -
> - if (G_OBJECT_CLASS(spice_display_channel_parent_class)->dispose)
> - G_OBJECT_CLASS(spice_display_channel_parent_class)->dispose(object);
> -}
> -
> -static void spice_display_channel_finalize(GObject *object)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv;
> -
> - g_clear_pointer(&c->monitors, g_array_unref);
> - clear_surfaces(SPICE_CHANNEL(object), FALSE);
> - g_hash_table_unref(c->surfaces);
> - clear_streams(SPICE_CHANNEL(object));
> - g_clear_pointer(&c->palettes, cache_unref);
> -
> - if (G_OBJECT_CLASS(spice_display_channel_parent_class)->finalize)
> -
> G_OBJECT_CLASS(spice_display_channel_parent_class)->finalize(object);
> -}
> -
> -static void spice_display_channel_constructed(GObject *object)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv;
> - SpiceSession *s = spice_channel_get_session(SPICE_CHANNEL(object));
> -
> - g_return_if_fail(s != NULL);
> - spice_session_get_caches(s, &c->images, &c->glz_window);
> - c->palettes = cache_new(g_free);
> -
> - g_return_if_fail(c->glz_window != NULL);
> - g_return_if_fail(c->images != NULL);
> - g_return_if_fail(c->palettes != NULL);
> -
> - c->monitors = g_array_new(FALSE, TRUE,
> sizeof(SpiceDisplayMonitorConfig));
> - spice_g_signal_connect_object(s, "mm-time-reset",
> -
> G_CALLBACK(display_session_mm_time_reset_cb),
> - SPICE_CHANNEL(object), 0);
> -
> -
> - if (G_OBJECT_CLASS(spice_display_channel_parent_class)->constructed)
> -
> G_OBJECT_CLASS(spice_display_channel_parent_class)->constructed(object);
> -}
> -
> -
> -static void spice_display_get_property(GObject *object,
> - guint prop_id,
> - GValue *value,
> - GParamSpec *pspec)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv;
> -
> - switch (prop_id) {
> - case PROP_WIDTH: {
> - g_value_set_uint(value, c->primary ? c->primary->width : 0);
> - break;
> - }
> - case PROP_HEIGHT: {
> - g_value_set_uint(value, c->primary ? c->primary->height : 0);
> - break;
> - }
> - case PROP_MONITORS: {
> - g_value_set_boxed(value, c->monitors);
> - break;
> - }
> - case PROP_MONITORS_MAX: {
> - g_value_set_uint(value, c->monitors_max);
> - break;
> - }
> - default:
> - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
> - break;
> - }
> -}
> -
> -static void spice_display_set_property(GObject *object,
> - guint prop_id,
> - const GValue *value,
> - GParamSpec *pspec)
> -{
> - switch (prop_id) {
> - default:
> - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
> - break;
> - }
> -}
> -
> -/* main or coroutine context */
> -static void spice_display_channel_reset(SpiceChannel *channel, gboolean
> migrating)
> -{
> - /* palettes, images, and glz_window are cleared in the session */
> - clear_streams(channel);
> - clear_surfaces(channel, TRUE);
> -
> -
> SPICE_CHANNEL_CLASS(spice_display_channel_parent_class)->channel_reset(channel,
> migrating);
> -}
> -
> -static void spice_display_channel_class_init(SpiceDisplayChannelClass
> *klass)
> -{
> - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
> - SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
> -
> - gobject_class->finalize = spice_display_channel_finalize;
> - gobject_class->dispose = spice_display_channel_dispose;
> - gobject_class->get_property = spice_display_get_property;
> - gobject_class->set_property = spice_display_set_property;
> - gobject_class->constructed = spice_display_channel_constructed;
> -
> - channel_class->channel_up = spice_display_channel_up;
> - channel_class->channel_reset = spice_display_channel_reset;
> - channel_class->channel_reset_capabilities =
> spice_display_channel_reset_capabilities;
> -
> - g_object_class_install_property
> - (gobject_class, PROP_HEIGHT,
> - g_param_spec_uint("height",
> - "Display height",
> - "The primary surface height",
> - 0, G_MAXUINT, 0,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_STRINGS));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_WIDTH,
> - g_param_spec_uint("width",
> - "Display width",
> - "The primary surface width",
> - 0, G_MAXUINT, 0,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_STRINGS));
> -
> - /**
> - * SpiceDisplayChannel:monitors:
> - *
> - * Current monitors configuration.
> - *
> - * Since: 0.13
> - */
> - g_object_class_install_property
> - (gobject_class, PROP_MONITORS,
> - g_param_spec_boxed("monitors",
> - "Display monitors",
> - "The monitors configuration",
> - G_TYPE_ARRAY,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_STRINGS));
> -
> - /**
> - * SpiceDisplayChannel:monitors-max:
> - *
> - * The maximum number of monitors the server or guest supports.
> - * May change during client lifetime, for instance guest may
> - * reboot or dynamically adjust this.
> - *
> - * Since: 0.13
> - */
> - g_object_class_install_property
> - (gobject_class, PROP_MONITORS_MAX,
> - g_param_spec_uint("monitors-max",
> - "Max display monitors",
> - "The current maximum number of monitors",
> - 1, MONITORS_MAX, 1,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_STRINGS));
> -
> - /**
> - * SpiceDisplayChannel::display-primary-create:
> - * @display: the #SpiceDisplayChannel that emitted the signal
> - * @format: %SPICE_SURFACE_FMT_32_xRGB or %SPICE_SURFACE_FMT_16_555;
> - * @width: width resolution
> - * @height: height resolution
> - * @stride: the buffer stride ("width" padding)
> - * @shmid: identifier of the shared memory segment associated with
> - * the @imgdata, or -1 if not shm
> - * @imgdata: pointer to surface buffer
> - *
> - * The #SpiceDisplayChannel::display-primary-create signal
> - * provides main display buffer data.
> - **/
> - signals[SPICE_DISPLAY_PRIMARY_CREATE] =
> - g_signal_new("display-primary-create",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceDisplayChannelClass,
> - display_primary_create),
> - NULL, NULL,
> -
> g_cclosure_user_marshal_VOID__INT_INT_INT_INT_INT_POINTER,
> - G_TYPE_NONE,
> - 6,
> - G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
> - G_TYPE_INT, G_TYPE_INT, G_TYPE_POINTER);
> -
> - /**
> - * SpiceDisplayChannel::display-primary-destroy:
> - * @display: the #SpiceDisplayChannel that emitted the signal
> - *
> - * The #SpiceDisplayChannel::display-primary-destroy signal is
> - * emitted when the primary surface is freed and should not be
> - * accessed anymore.
> - **/
> - signals[SPICE_DISPLAY_PRIMARY_DESTROY] =
> - g_signal_new("display-primary-destroy",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceDisplayChannelClass,
> - display_primary_destroy),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> -
> - /**
> - * SpiceDisplayChannel::display-invalidate:
> - * @display: the #SpiceDisplayChannel that emitted the signal
> - * @x: x position
> - * @y: y position
> - * @width: width
> - * @height: height
> - *
> - * The #SpiceDisplayChannel::display-invalidate signal is emitted
> - * when the rectangular region x/y/w/h of the primary buffer is
> - * updated.
> - **/
> - signals[SPICE_DISPLAY_INVALIDATE] =
> - g_signal_new("display-invalidate",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceDisplayChannelClass,
> - display_invalidate),
> - NULL, NULL,
> - g_cclosure_user_marshal_VOID__INT_INT_INT_INT,
> - G_TYPE_NONE,
> - 4,
> - G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
> -
> - /**
> - * SpiceDisplayChannel::display-mark:
> - * @display: the #SpiceDisplayChannel that emitted the signal
> - * @mark: %TRUE when the display mark has been received
> - *
> - * The #SpiceDisplayChannel::display-mark signal is emitted when
> - * the %RED_DISPLAY_MARK command is received, and the display
> - * should be exposed.
> - **/
> - signals[SPICE_DISPLAY_MARK] =
> - g_signal_new("display-mark",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceDisplayChannelClass,
> - display_mark),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__INT,
> - G_TYPE_NONE,
> - 1,
> - G_TYPE_INT);
> -
> - g_type_class_add_private(klass, sizeof(SpiceDisplayChannelPrivate));
> -
> - sw_canvas_init();
> - quic_init();
> - rop3_init();
> - channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
> -}
> -
> -/**
> - * spice_display_get_primary:
> - * @channel:
> - * @surface_id:
> - * @primary:
> - *
> - * Retrieve primary display surface @surface_id.
> - *
> - * Returns: %TRUE if the primary surface was found and its details
> - * collected in @primary.
> - */
> -gboolean spice_display_get_primary(SpiceChannel *channel, guint32
> surface_id,
> - SpiceDisplayPrimary *primary)
> -{
> - g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), FALSE);
> - g_return_val_if_fail(primary != NULL, FALSE);
> -
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - display_surface *surface = find_surface(c, surface_id);
> -
> - if (surface == NULL)
> - return FALSE;
> -
> - g_return_val_if_fail(surface->primary, FALSE);
> -
> - primary->format = surface->format;
> - primary->width = surface->width;
> - primary->height = surface->height;
> - primary->stride = surface->stride;
> - primary->shmid = surface->shmid;
> - primary->data = surface->data;
> - primary->marked = c->mark;
> - CHANNEL_DEBUG(channel, "get primary %p", primary->data);
> -
> - return TRUE;
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -static void image_put(SpiceImageCache *cache, uint64_t id, pixman_image_t
> *image)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
> -
> - cache_add(c->images, id, pixman_image_ref(image));
> -}
> -
> -typedef struct _WaitImageData
> -{
> - gboolean lossy;
> - SpiceImageCache *cache;
> - uint64_t id;
> - pixman_image_t *image;
> -} WaitImageData;
> -
> -static gboolean wait_image(gpointer data)
> -{
> - gboolean lossy;
> - WaitImageData *wait = data;
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(wait->cache, SpiceDisplayChannelPrivate,
> image_cache);
> - pixman_image_t *image = cache_find_lossy(c->images, wait->id, &lossy);
> -
> - if (!image || (lossy && !wait->lossy))
> - return FALSE;
> -
> - wait->image = pixman_image_ref(image);
> -
> - return TRUE;
> -}
> -
> -static pixman_image_t *image_get(SpiceImageCache *cache, uint64_t id)
> -{
> - WaitImageData wait = {
> - .lossy = TRUE,
> - .cache = cache,
> - .id = id,
> - .image = NULL
> - };
> - if (!g_coroutine_condition_wait(g_coroutine_self(), wait_image, &wait))
> - SPICE_DEBUG("wait image got cancelled");
> -
> - return wait.image;
> -}
> -
> -static void palette_put(SpicePaletteCache *cache, SpicePalette *palette)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache);
> -
> - cache_add(c->palettes, palette->unique,
> - g_memdup(palette, sizeof(SpicePalette) +
> - palette->num_ents * sizeof(palette->ents[0])));
> -}
> -
> -static SpicePalette *palette_get(SpicePaletteCache *cache, uint64_t id)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache);
> -
> - /* here the returned pointer is weak, no ref given to caller. it
> - * seems spice canvas usage is exclusively temporary, so it's ok.
> - * palette_release is a noop. */
> - return cache_find(c->palettes, id);
> -}
> -
> -static void palette_remove(SpicePaletteCache *cache, uint64_t id)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, palette_cache);
> -
> - cache_remove(c->palettes, id);
> -}
> -
> -static void palette_release(SpicePaletteCache *cache, SpicePalette *palette)
> -{
> - /* there is no refcount of palette, see palette_get() */
> -}
> -
> -static void image_put_lossy(SpiceImageCache *cache, uint64_t id,
> - pixman_image_t *surface)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
> -
> -#ifndef NDEBUG
> - g_warn_if_fail(cache_find(c->images, id) == NULL);
> -#endif
> -
> - cache_add_lossy(c->images, id, pixman_image_ref(surface), TRUE);
> -}
> -
> -static void image_replace_lossy(SpiceImageCache *cache, uint64_t id,
> - pixman_image_t *surface)
> -{
> - image_put(cache, id, surface);
> -}
> -
> -static pixman_image_t* image_get_lossless(SpiceImageCache *cache, uint64_t
> id)
> -{
> - WaitImageData wait = {
> - .lossy = FALSE,
> - .cache = cache,
> - .id = id,
> - .image = NULL
> - };
> - if (!g_coroutine_condition_wait(g_coroutine_self(), wait_image, &wait))
> - SPICE_DEBUG("wait lossless got cancelled");
> -
> - return wait.image;
> -}
> -
> -static SpiceCanvas *surfaces_get(SpiceImageSurfaces *surfaces,
> - uint32_t surface_id)
> -{
> - SpiceDisplayChannelPrivate *c =
> - SPICE_CONTAINEROF(surfaces, SpiceDisplayChannelPrivate,
> image_surfaces);
> -
> - display_surface *s =
> - find_surface(c, surface_id);
> -
> - return s ? s->canvas : NULL;
> -}
> -
> -static SpiceImageCacheOps image_cache_ops = {
> - .put = image_put,
> - .get = image_get,
> -
> - .put_lossy = image_put_lossy,
> - .replace_lossy = image_replace_lossy,
> - .get_lossless = image_get_lossless,
> -};
> -
> -static SpicePaletteCacheOps palette_cache_ops = {
> - .put = palette_put,
> - .get = palette_get,
> - .release = palette_release,
> -};
> -
> -static SpiceImageSurfacesOps image_surfaces_ops = {
> - .get = surfaces_get
> -};
> -
> -#if defined(G_OS_WIN32)
> -static HDC create_compatible_dc(void)
> -{
> - HDC dc = CreateCompatibleDC(NULL);
> - if (!dc) {
> - g_warning("create compatible DC failed");
> - }
> - return dc;
> -}
> -#endif
> -
> -static void spice_display_channel_reset_capabilities(SpiceChannel *channel)
> -{
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_DISPLAY_CAP_SIZED_STREAM);
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_DISPLAY_CAP_MONITORS_CONFIG);
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_DISPLAY_CAP_COMPOSITE);
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_DISPLAY_CAP_A8_SURFACE);
> -#ifdef USE_LZ4
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_DISPLAY_CAP_LZ4_COMPRESSION);
> -#endif
> - if (SPICE_DISPLAY_CHANNEL(channel)->priv->enable_adaptive_streaming) {
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_DISPLAY_CAP_STREAM_REPORT);
> - }
> -}
> -
> -static void destroy_surface(gpointer data)
> -{
> - display_surface *surface = data;
> -
> - destroy_canvas(surface);
> - g_slice_free(display_surface, surface);
> -}
> -
> -static void spice_display_channel_init(SpiceDisplayChannel *channel)
> -{
> - SpiceDisplayChannelPrivate *c;
> -
> - c = channel->priv = SPICE_DISPLAY_CHANNEL_GET_PRIVATE(channel);
> -
> - c->surfaces = g_hash_table_new_full(NULL, NULL, NULL, destroy_surface);
> - c->image_cache.ops = &image_cache_ops;
> - c->palette_cache.ops = &palette_cache_ops;
> - c->image_surfaces.ops = &image_surfaces_ops;
> -#if defined(G_OS_WIN32)
> - c->dc = create_compatible_dc();
> -#endif
> - c->monitors_max = 1;
> -
> - if (g_getenv("SPICE_DISABLE_ADAPTIVE_STREAMING")) {
> - SPICE_DEBUG("adaptive video disabled");
> - c->enable_adaptive_streaming = FALSE;
> - } else {
> - c->enable_adaptive_streaming = TRUE;
> - }
> - spice_display_channel_reset_capabilities(SPICE_CHANNEL(channel));
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -static int create_canvas(SpiceChannel *channel, display_surface *surface)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> -
> - if (surface->primary) {
> - if (c->primary) {
> - if (c->primary->width == surface->width &&
> - c->primary->height == surface->height) {
> - CHANNEL_DEBUG(channel, "Reusing existing primary surface");
> - return 0;
> - }
> -
> - g_coroutine_signal_emit(channel,
> signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0);
> -
> - g_hash_table_remove(c->surfaces,
> GINT_TO_POINTER(c->primary->surface_id));
> - }
> -
> - CHANNEL_DEBUG(channel, "Create primary canvas");
> -#if defined(WITH_X11) && defined(HAVE_SYS_SHM_H)
> - surface->shmid = shmget(IPC_PRIVATE, surface->size, IPC_CREAT |
> 0777);
> - if (surface->shmid >= 0) {
> - surface->data = shmat(surface->shmid, 0, 0);
> - if (surface->data == NULL) {
> - shmctl(surface->shmid, IPC_RMID, 0);
> - surface->shmid = -1;
> - }
> - }
> -#else
> - surface->shmid = -1;
> -#endif
> - } else {
> - surface->shmid = -1;
> - }
> -
> - if (surface->shmid == -1)
> - surface->data = g_malloc0(surface->size);
> -
> - g_return_val_if_fail(c->glz_window, 0);
> -
> - g_warn_if_fail(surface->canvas == NULL);
> - g_warn_if_fail(surface->glz_decoder == NULL);
> - g_warn_if_fail(surface->zlib_decoder == NULL);
> - g_warn_if_fail(surface->jpeg_decoder == NULL);
> -
> - surface->glz_decoder = glz_decoder_new(c->glz_window);
> - surface->zlib_decoder = zlib_decoder_new();
> - surface->jpeg_decoder = jpeg_decoder_new();
> -
> - surface->canvas = canvas_create_for_data(surface->width,
> - surface->height,
> - surface->format,
> - surface->data,
> - surface->stride,
> - &c->image_cache,
> - &c->palette_cache,
> - &c->image_surfaces,
> - surface->glz_decoder,
> - surface->jpeg_decoder,
> - surface->zlib_decoder);
> -
> - g_return_val_if_fail(surface->canvas != NULL, 0);
> - g_hash_table_insert(c->surfaces, GINT_TO_POINTER(surface->surface_id),
> surface);
> -
> - if (surface->primary) {
> - g_warn_if_fail(c->primary == NULL);
> - c->primary = surface;
> - g_coroutine_signal_emit(channel,
> signals[SPICE_DISPLAY_PRIMARY_CREATE], 0,
> - surface->format, surface->width,
> surface->height,
> - surface->stride, surface->shmid,
> surface->data);
> -
> - if (!spice_channel_test_capability(channel,
> SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
> - g_array_set_size(c->monitors, 1);
> - SpiceDisplayMonitorConfig *config = &g_array_index(c->monitors,
> SpiceDisplayMonitorConfig, 0);
> - config->x = config->y = 0;
> - config->width = surface->width;
> - config->height = surface->height;
> - g_coroutine_object_notify(G_OBJECT(channel), "monitors");
> - }
> - }
> -
> - return 0;
> -}
> -
> -static void destroy_canvas(display_surface *surface)
> -{
> - if (surface == NULL)
> - return;
> -
> - glz_decoder_destroy(surface->glz_decoder);
> - zlib_decoder_destroy(surface->zlib_decoder);
> - jpeg_decoder_destroy(surface->jpeg_decoder);
> -
> - if (surface->shmid == -1) {
> - g_free(surface->data);
> - }
> -#ifdef HAVE_SYS_SHM_H
> - else {
> - shmdt(surface->data);
> - shmctl(surface->shmid, IPC_RMID, 0);
> - }
> -#endif
> - surface->shmid = -1;
> - surface->data = NULL;
> -
> - surface->canvas->ops->destroy(surface->canvas);
> - surface->canvas = NULL;
> -}
> -
> -static display_surface *find_surface(SpiceDisplayChannelPrivate *c, guint32
> surface_id)
> -{
> - if (c->primary && c->primary->surface_id == surface_id)
> - return c->primary;
> -
> - return g_hash_table_lookup(c->surfaces, GINT_TO_POINTER(surface_id));
> -}
> -
> -/* main or coroutine context */
> -static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - GHashTableIter iter;
> - display_surface *surface;
> -
> - if (!keep_primary) {
> - c->primary = NULL;
> - g_coroutine_signal_emit(channel,
> signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0);
> - }
> -
> - g_hash_table_iter_init(&iter, c->surfaces);
> - while (g_hash_table_iter_next(&iter, NULL, (gpointer*)&surface)) {
> -
> - if (keep_primary && surface->primary) {
> - CHANNEL_DEBUG(channel, "keeping existing primary surface,
> migration or reset");
> - continue;
> - }
> -
> - g_hash_table_iter_remove(&iter);
> - }
> -}
> -
> -/* coroutine context */
> -static void emit_invalidate(SpiceChannel *channel, SpiceRect *bbox)
> -{
> - g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_INVALIDATE], 0,
> - bbox->left, bbox->top,
> - bbox->right - bbox->left,
> - bbox->bottom - bbox->top);
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -/* coroutine context */
> -static void spice_display_channel_up(SpiceChannel *channel)
> -{
> - SpiceMsgOut *out;
> - SpiceSession *s = spice_channel_get_session(channel);
> - SpiceMsgcDisplayInit init;
> - int cache_size;
> - int glz_window_size;
> -
> - g_object_get(s,
> - "cache-size", &cache_size,
> - "glz-window-size", &glz_window_size,
> - NULL);
> - CHANNEL_DEBUG(channel, "%s: cache_size %d, glz_window_size %d (bytes)",
> __FUNCTION__,
> - cache_size, glz_window_size);
> - init.pixmap_cache_id = 1;
> - init.glz_dictionary_id = 1;
> - init.pixmap_cache_size = cache_size / 4; /* pixels */
> - init.glz_dictionary_window_size = glz_window_size / 4; /* pixels */
> - out = spice_msg_out_new(channel, SPICE_MSGC_DISPLAY_INIT);
> - out->marshallers->msgc_display_init(out->marshaller, &init);
> - spice_msg_out_send_internal(out);
> -
> - /* if we are not using monitors config, notify of existence of
> - this monitor */
> - if (channel->priv->channel_id != 0)
> - g_coroutine_object_notify(G_OBJECT(channel), "monitors");
> -}
> -
> -#define DRAW(type) { \
> - display_surface *surface = \
> - find_surface(SPICE_DISPLAY_CHANNEL(channel)->priv, \
> - op->base.surface_id); \
> - g_return_if_fail(surface != NULL); \
> - surface->canvas->ops->draw_##type(surface->canvas, &op->base.box, \
> - &op->base.clip, &op->data); \
> - if (surface->primary) { \
> - emit_invalidate(channel, &op->base.box); \
> - } \
> -}
> -
> -/* coroutine context */
> -static void display_handle_mode(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceMsgDisplayMode *mode = spice_msg_in_parsed(in);
> - display_surface *surface;
> -
> - g_warn_if_fail(c->mark == FALSE);
> -
> - surface = g_slice_new0(display_surface);
> - surface->format = mode->bits == 32 ?
> - SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555;
> - surface->width = mode->x_res;
> - surface->height = mode->y_res;
> - surface->stride = surface->width * 4;
> - surface->size = surface->height * surface->stride;
> - surface->primary = true;
> - create_canvas(channel, surface);
> -}
> -
> -/* coroutine context */
> -static void display_handle_mark(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> -
> - CHANNEL_DEBUG(channel, "%s", __FUNCTION__);
> - g_return_if_fail(c->primary != NULL);
> -#ifdef EXTRA_CHECKS
> - g_warn_if_fail(c->mark == FALSE);
> -#endif
> -
> - c->mark = TRUE;
> - g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, TRUE);
> -}
> -
> -/* coroutine context */
> -static void display_handle_reset(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - display_surface *surface = c->primary;
> -
> - CHANNEL_DEBUG(channel, "%s: TODO detach_from_screen", __FUNCTION__);
> -
> - if (surface != NULL)
> - surface->canvas->ops->clear(surface->canvas);
> -
> - cache_clear(c->palettes);
> -
> - c->mark = FALSE;
> - g_coroutine_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, FALSE);
> -}
> -
> -/* coroutine context */
> -static void display_handle_copy_bits(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayCopyBits *op = spice_msg_in_parsed(in);
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - display_surface *surface = find_surface(c, op->base.surface_id);
> -
> - g_return_if_fail(surface != NULL);
> - surface->canvas->ops->copy_bits(surface->canvas, &op->base.box,
> - &op->base.clip, &op->src_pos);
> - if (surface->primary) {
> - emit_invalidate(channel, &op->base.box);
> - }
> -}
> -
> -/* coroutine context */
> -static void display_handle_inv_list(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceResourceList *list = spice_msg_in_parsed(in);
> - int i;
> -
> - for (i = 0; i < list->count; i++) {
> - guint64 id = list->resources[i].id;
> -
> - switch (list->resources[i].type) {
> - case SPICE_RES_TYPE_PIXMAP:
> - if (!cache_remove(c->images, id))
> - SPICE_DEBUG("fail to remove image %" G_GUINT64_FORMAT, id);
> - break;
> - default:
> - g_return_if_reached();
> - break;
> - }
> - }
> -}
> -
> -/* coroutine context */
> -static void display_handle_inv_pixmap_all(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> -
> - spice_channel_handle_wait_for_channels(channel, in);
> - cache_clear(c->images);
> -}
> -
> -/* coroutine context */
> -static void display_handle_inv_palette(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceMsgDisplayInvalOne* op = spice_msg_in_parsed(in);
> -
> - palette_remove(&c->palette_cache, op->id);
> -}
> -
> -/* coroutine context */
> -static void display_handle_inv_palette_all(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> -
> - cache_clear(c->palettes);
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -static void display_update_stream_region(display_stream *st)
> -{
> - int i;
> -
> - switch (st->clip->type) {
> - case SPICE_CLIP_TYPE_RECTS:
> - region_clear(&st->region);
> - for (i = 0; i < st->clip->rects->num_rects; i++) {
> - region_add(&st->region, &st->clip->rects->rects[i]);
> - }
> - st->have_region = true;
> - break;
> - case SPICE_CLIP_TYPE_NONE:
> - default:
> - st->have_region = false;
> - break;
> - }
> -}
> -
> -/* coroutine context */
> -static void display_handle_stream_create(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceMsgDisplayStreamCreate *op = spice_msg_in_parsed(in);
> - display_stream *st;
> -
> - CHANNEL_DEBUG(channel, "%s: id %d", __FUNCTION__, op->id);
> -
> - if (op->id >= c->nstreams) {
> - int n = c->nstreams;
> - if (!c->nstreams) {
> - c->nstreams = 1;
> - }
> - while (op->id >= c->nstreams) {
> - c->nstreams *= 2;
> - }
> - c->streams = realloc(c->streams, c->nstreams *
> sizeof(c->streams[0]));
> - memset(c->streams + n, 0, (c->nstreams - n) *
> sizeof(c->streams[0]));
> - }
> - g_return_if_fail(c->streams[op->id] == NULL);
> - c->streams[op->id] = g_new0(display_stream, 1);
> - st = c->streams[op->id];
> -
> - st->msg_create = in;
> - spice_msg_in_ref(in);
> - st->clip = &op->clip;
> - st->codec = op->codec_type;
> - st->surface = find_surface(c, op->surface_id);
> - st->msgq = g_queue_new();
> - st->channel = channel;
> - st->drops_seqs_stats_arr = g_array_new(FALSE, FALSE,
> sizeof(drops_sequence_stats));
> -
> - region_init(&st->region);
> - display_update_stream_region(st);
> -
> - switch (st->codec) {
> - case SPICE_VIDEO_CODEC_TYPE_MJPEG:
> - stream_mjpeg_init(st);
> - break;
> - }
> -}
> -
> -/* coroutine or main context */
> -static gboolean display_stream_schedule(display_stream *st)
> -{
> - SpiceSession *session = spice_channel_get_session(st->channel);
> - guint32 time, d;
> - SpiceStreamDataHeader *op;
> - SpiceMsgIn *in;
> -
> - SPICE_DEBUG("%s", __FUNCTION__);
> - if (st->timeout || !session)
> - return TRUE;
> -
> - time = spice_session_get_mm_time(session);
> - in = g_queue_peek_head(st->msgq);
> -
> - if (in == NULL) {
> - return TRUE;
> - }
> -
> - op = spice_msg_in_parsed(in);
> - if (time < op->multi_media_time) {
> - d = op->multi_media_time - time;
> - SPICE_DEBUG("scheduling next stream render in %u ms", d);
> - st->timeout = g_timeout_add(d, (GSourceFunc)display_stream_render,
> st);
> - return TRUE;
> - } else {
> - SPICE_DEBUG("%s: rendering too late by %u ms (ts: %u, mmtime: %u),
> dropping ",
> - __FUNCTION__, time - op->multi_media_time,
> - op->multi_media_time, time);
> - in = g_queue_pop_head(st->msgq);
> - spice_msg_in_unref(in);
> - st->num_drops_on_playback++;
> - if (g_queue_get_length(st->msgq) == 0)
> - return TRUE;
> - }
> -
> - return FALSE;
> -}
> -
> -static SpiceRect *stream_get_dest(display_stream *st)
> -{
> - if (st->msg_data == NULL ||
> - spice_msg_in_type(st->msg_data) !=
> SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) {
> - SpiceMsgDisplayStreamCreate *info =
> spice_msg_in_parsed(st->msg_create);
> -
> - return &info->dest;
> - } else {
> - SpiceMsgDisplayStreamDataSized *op =
> spice_msg_in_parsed(st->msg_data);
> -
> - return &op->dest;
> - }
> -
> -}
> -
> -static uint32_t stream_get_flags(display_stream *st)
> -{
> - SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
> -
> - return info->flags;
> -}
> -
> -G_GNUC_INTERNAL
> -uint32_t stream_get_current_frame(display_stream *st, uint8_t **data)
> -{
> - if (st->msg_data == NULL) {
> - *data = NULL;
> - return 0;
> - }
> -
> - if (spice_msg_in_type(st->msg_data) == SPICE_MSG_DISPLAY_STREAM_DATA) {
> - SpiceMsgDisplayStreamData *op = spice_msg_in_parsed(st->msg_data);
> -
> - *data = op->data;
> - return op->data_size;
> - } else {
> - SpiceMsgDisplayStreamDataSized *op =
> spice_msg_in_parsed(st->msg_data);
> -
> - g_return_val_if_fail(spice_msg_in_type(st->msg_data) ==
> - SPICE_MSG_DISPLAY_STREAM_DATA_SIZED, 0);
> - *data = op->data;
> - return op->data_size;
> - }
> -
> -}
> -
> -G_GNUC_INTERNAL
> -void stream_get_dimensions(display_stream *st, int *width, int *height)
> -{
> - g_return_if_fail(width != NULL);
> - g_return_if_fail(height != NULL);
> -
> - if (st->msg_data == NULL ||
> - spice_msg_in_type(st->msg_data) !=
> SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) {
> - SpiceMsgDisplayStreamCreate *info =
> spice_msg_in_parsed(st->msg_create);
> -
> - *width = info->stream_width;
> - *height = info->stream_height;
> - } else {
> - SpiceMsgDisplayStreamDataSized *op =
> spice_msg_in_parsed(st->msg_data);
> -
> - *width = op->width;
> - *height = op->height;
> - }
> -}
> -
> -/* main context */
> -static gboolean display_stream_render(display_stream *st)
> -{
> - SpiceMsgIn *in;
> -
> - st->timeout = 0;
> - do {
> - in = g_queue_pop_head(st->msgq);
> -
> - g_return_val_if_fail(in != NULL, FALSE);
> -
> - st->msg_data = in;
> - switch (st->codec) {
> - case SPICE_VIDEO_CODEC_TYPE_MJPEG:
> - stream_mjpeg_data(st);
> - break;
> - }
> -
> - if (st->out_frame) {
> - int width;
> - int height;
> - SpiceRect *dest;
> - uint8_t *data;
> - int stride;
> -
> - stream_get_dimensions(st, &width, &height);
> - dest = stream_get_dest(st);
> -
> - data = st->out_frame;
> - stride = width * sizeof(uint32_t);
> - if (!(stream_get_flags(st) & SPICE_STREAM_FLAGS_TOP_DOWN)) {
> - data += stride * (height - 1);
> - stride = -stride;
> - }
> -
> - st->surface->canvas->ops->put_image(
> - st->surface->canvas,
> -#ifdef G_OS_WIN32
> - SPICE_DISPLAY_CHANNEL(st->channel)->priv->dc,
> -#endif
> - dest, data,
> - width, height, stride,
> - st->have_region ? &st->region : NULL);
> -
> - if (st->surface->primary)
> - g_signal_emit(st->channel,
> signals[SPICE_DISPLAY_INVALIDATE], 0,
> - dest->left, dest->top,
> - dest->right - dest->left,
> - dest->bottom - dest->top);
> - }
> -
> - st->msg_data = NULL;
> - spice_msg_in_unref(in);
> -
> - in = g_queue_peek_head(st->msgq);
> - if (in == NULL)
> - break;
> -
> - if (display_stream_schedule(st))
> - return FALSE;
> - } while (1);
> -
> - return FALSE;
> -}
> -/* after a sequence of 3 drops, push a report to the server, even
> - * if the report window is bigger */
> -#define STREAM_REPORT_DROP_SEQ_LEN_LIMIT 3
> -
> -static void display_update_stream_report(SpiceDisplayChannel *channel,
> uint32_t stream_id,
> - uint32_t frame_time, int32_t
> latency)
> -{
> - display_stream *st = channel->priv->streams[stream_id];
> - guint64 now;
> -
> - if (!st->report_is_active) {
> - return;
> - }
> - now = g_get_monotonic_time();
> -
> - if (st->report_num_frames == 0) {
> - st->report_start_frame_time = frame_time;
> - st->report_start_time = now;
> - }
> - st->report_num_frames++;
> -
> - if (latency < 0) { // drop
> - st->report_num_drops++;
> - st->report_drops_seq_len++;
> - } else {
> - st->report_drops_seq_len = 0;
> - }
> -
> - if (st->report_num_frames >= st->report_max_window ||
> - now - st->report_start_time >= st->report_timeout ||
> - st->report_drops_seq_len >= STREAM_REPORT_DROP_SEQ_LEN_LIMIT) {
> - SpiceMsgcDisplayStreamReport report;
> - SpiceSession *session =
> spice_channel_get_session(SPICE_CHANNEL(channel));
> - SpiceMsgOut *msg;
> -
> - report.stream_id = stream_id;
> - report.unique_id = st->report_id;
> - report.start_frame_mm_time = st->report_start_frame_time;
> - report.end_frame_mm_time = frame_time;
> - report.num_frames = st->report_num_frames;
> - report.num_drops = st-> report_num_drops;
> - report.last_frame_delay = latency;
> - if (spice_session_is_playback_active(session)) {
> - report.audio_delay =
> spice_session_get_playback_latency(session);
> - } else {
> - report.audio_delay = UINT_MAX;
> - }
> -
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_DISPLAY_STREAM_REPORT);
> - msg->marshallers->msgc_display_stream_report(msg->marshaller,
> &report);
> - spice_msg_out_send(msg);
> -
> - st->report_start_time = 0;
> - st->report_start_frame_time = 0;
> - st->report_num_frames = 0;
> - st->report_num_drops = 0;
> - st->report_drops_seq_len = 0;
> - }
> -}
> -
> -static void display_stream_reset_rendering_timer(display_stream *st)
> -{
> - SPICE_DEBUG("%s", __FUNCTION__);
> - if (st->timeout != 0) {
> - g_source_remove(st->timeout);
> - st->timeout = 0;
> - }
> - while (!display_stream_schedule(st)) {
> - }
> -}
> -
> -/*
> - * Migration can occur between 2 spice-servers with different mm-times.
> - * Then, the following cases can happen after migration completes:
> - * (We refer to src/dst-time as the mm-times on the src/dst servers):
> - *
> - * (case 1) Frames with time ~= dst-time arrive to the client before the
> - * playback-channel updates the session's mm-time (i.e., the
> mm_time
> - * of the session is still based on the src-time).
> - * (a) If src-time < dst-time:
> - * display_stream_schedule schedules the next rendering to
> - * ~(dst-time - src-time) milliseconds from now.
> - * Since we assume monotonic mm_time, display_stream_schedule,
> - * returns immediately when a rendering timeout
> - * has already been set, and doesn't update the timeout,
> - * even after the mm_time is updated.
> - * When src-time << dst-time, a significant video frames loss will
> occur.
> - * (b) If src-time > dst-time
> - * Frames will be dropped till the mm-time will be updated.
> - * (case 2) mm-time is synced with dst-time, but frames that were in the
> command
> - * ring during migration still arrive (such frames hold src-time).
> - * (a) If src-time < dst-time
> - * The frames that hold src-time will be dropped, since their
> - * mm_time < session-mm_time. But all the new frames that are
> generated in
> - * the driver after migration, will be rendered appropriately.
> - * (b) If src-time > dst-time
> - * Similar consequences as in 1 (a)
> - * case 2 is less likely, since at takes at least 20 frames till the
> dst-server re-identifies
> - * the video stream and starts sending stream data
> - *
> - * display_session_mm_time_reset_cb handles case 1.a, and
> - * display_stream_test_frames_mm_time_reset handles case 2.b
> - */
> -
> -/* main context */
> -static void display_session_mm_time_reset_cb(SpiceSession *session, gpointer
> data)
> -{
> - SpiceChannel *channel = data;
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - guint i;
> -
> - CHANNEL_DEBUG(channel, "%s", __FUNCTION__);
> -
> - for (i = 0; i < c->nstreams; i++) {
> - display_stream *st;
> -
> - if (c->streams[i] == NULL) {
> - continue;
> - }
> - SPICE_DEBUG("%s: stream-id %d", __FUNCTION__, i);
> - st = c->streams[i];
> - display_stream_reset_rendering_timer(st);
> - }
> -}
> -
> -/* coroutine context */
> -static void display_stream_test_frames_mm_time_reset(display_stream *st,
> - SpiceMsgIn
> *new_frame_msg,
> - guint32 mm_time)
> -{
> - SpiceStreamDataHeader *tail_op, *new_op;
> - SpiceMsgIn *tail_msg;
> -
> - SPICE_DEBUG("%s", __FUNCTION__);
> - g_return_if_fail(new_frame_msg != NULL);
> - tail_msg = g_queue_peek_tail(st->msgq);
> - if (!tail_msg) {
> - return;
> - }
> - tail_op = spice_msg_in_parsed(tail_msg);
> - new_op = spice_msg_in_parsed(new_frame_msg);
> -
> - if (new_op->multi_media_time < tail_op->multi_media_time) {
> - SPICE_DEBUG("new-frame-time < tail-frame-time (%u < %u):"
> - " reseting stream, id %d",
> - new_op->multi_media_time,
> - tail_op->multi_media_time,
> - new_op->id);
> - g_queue_foreach(st->msgq, _msg_in_unref_func, NULL);
> - g_queue_clear(st->msgq);
> - display_stream_reset_rendering_timer(st);
> - }
> -}
> -
> -#define STREAM_PLAYBACK_SYNC_DROP_SEQ_LEN_LIMIT 5
> -
> -/* coroutine context */
> -static void display_handle_stream_data(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceStreamDataHeader *op = spice_msg_in_parsed(in);
> - display_stream *st;
> - guint32 mmtime;
> - int32_t latency;
> -
> - g_return_if_fail(c != NULL);
> - g_return_if_fail(c->streams != NULL);
> - g_return_if_fail(c->nstreams > op->id);
> -
> - st = c->streams[op->id];
> - mmtime = spice_session_get_mm_time(spice_channel_get_session(channel));
> -
> - if (spice_msg_in_type(in) == SPICE_MSG_DISPLAY_STREAM_DATA_SIZED) {
> - CHANNEL_DEBUG(channel, "stream %d contains sized data", op->id);
> - }
> -
> - if (op->multi_media_time == 0) {
> - g_critical("Received frame with invalid 0 timestamp! perhaps wrong
> graphic driver?");
> - op->multi_media_time = mmtime + 100; /* workaround... */
> - }
> -
> - if (!st->num_input_frames) {
> - st->first_frame_mm_time = op->multi_media_time;
> - }
> - st->num_input_frames++;
> -
> - latency = op->multi_media_time - mmtime;
> - if (latency < 0) {
> - CHANNEL_DEBUG(channel, "stream data too late by %u ms (ts: %u,
> mmtime: %u), dropping",
> - mmtime - op->multi_media_time, op->multi_media_time,
> mmtime);
> - st->arrive_late_time += mmtime - op->multi_media_time;
> - st->num_drops_on_receive++;
> -
> - if (!st->cur_drops_seq_stats.len) {
> - st->cur_drops_seq_stats.start_mm_time = op->multi_media_time;
> - }
> - st->cur_drops_seq_stats.len++;
> - st->playback_sync_drops_seq_len++;
> - } else {
> - CHANNEL_DEBUG(channel, "video latency: %d", latency);
> - spice_msg_in_ref(in);
> - display_stream_test_frames_mm_time_reset(st, in, mmtime);
> - g_queue_push_tail(st->msgq, in);
> - while (!display_stream_schedule(st)) {
> - }
> - if (st->cur_drops_seq_stats.len) {
> - st->cur_drops_seq_stats.duration = op->multi_media_time -
> -
> st->cur_drops_seq_stats.start_mm_time;
> - g_array_append_val(st->drops_seqs_stats_arr,
> st->cur_drops_seq_stats);
> - memset(&st->cur_drops_seq_stats, 0,
> sizeof(st->cur_drops_seq_stats));
> - st->num_drops_seqs++;
> - }
> - st->playback_sync_drops_seq_len = 0;
> - }
> - if (c->enable_adaptive_streaming) {
> - display_update_stream_report(SPICE_DISPLAY_CHANNEL(channel), op->id,
> - op->multi_media_time, latency);
> - if (st->playback_sync_drops_seq_len >=
> STREAM_PLAYBACK_SYNC_DROP_SEQ_LEN_LIMIT) {
> -
> spice_session_sync_playback_latency(spice_channel_get_session(channel));
> - st->playback_sync_drops_seq_len = 0;
> - }
> - }
> -}
> -
> -/* coroutine context */
> -static void display_handle_stream_clip(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceMsgDisplayStreamClip *op = spice_msg_in_parsed(in);
> - display_stream *st;
> -
> - g_return_if_fail(c != NULL);
> - g_return_if_fail(c->streams != NULL);
> - g_return_if_fail(c->nstreams > op->id);
> -
> - st = c->streams[op->id];
> -
> - if (st->msg_clip) {
> - spice_msg_in_unref(st->msg_clip);
> - }
> - spice_msg_in_ref(in);
> - st->msg_clip = in;
> - st->clip = &op->clip;
> - display_update_stream_region(st);
> -}
> -
> -static void _msg_in_unref_func(gpointer data, gpointer user_data)
> -{
> - spice_msg_in_unref(data);
> -}
> -
> -static void destroy_stream(SpiceChannel *channel, int id)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - display_stream *st;
> - guint64 drops_duration_total = 0;
> - guint32 num_out_frames;
> - int i;
> -
> - g_return_if_fail(c != NULL);
> - g_return_if_fail(c->streams != NULL);
> - g_return_if_fail(c->nstreams > id);
> -
> - st = c->streams[id];
> - if (!st)
> - return;
> -
> - num_out_frames = st->num_input_frames - st->num_drops_on_receive -
> st->num_drops_on_playback;
> - CHANNEL_DEBUG(channel, "%s: id=%d #in-frames=%d out/in=%.2f "
> - "#drops-on-receive=%d avg-late-time(ms)=%.2f "
> - "#drops-on-playback=%d", __FUNCTION__,
> - id,
> - st->num_input_frames,
> - num_out_frames / (double)st->num_input_frames,
> - st->num_drops_on_receive,
> - st->num_drops_on_receive ? st->arrive_late_time /
> ((double)st->num_drops_on_receive): 0,
> - st->num_drops_on_playback);
> - if (st->num_drops_seqs) {
> - CHANNEL_DEBUG(channel, "%s: #drops-sequences=%u ==>", __FUNCTION__,
> st->num_drops_seqs);
> - }
> - for (i = 0; i < st->num_drops_seqs; i++) {
> - drops_sequence_stats *stats =
> &g_array_index(st->drops_seqs_stats_arr,
> -
> drops_sequence_stats,
> - i);
> - drops_duration_total += stats->duration;
> - CHANNEL_DEBUG(channel, "%s: \t len=%u start-ms=%u
> duration-ms=%u", __FUNCTION__,
> - stats->len,
> - stats->start_mm_time -
> st->first_frame_mm_time,
> - stats->duration);
> - }
> - if (st->num_drops_seqs) {
> - CHANNEL_DEBUG(channel, "%s: drops-total-duration=%"G_GUINT64_FORMAT"
> ==>", __FUNCTION__, drops_duration_total);
> - }
> -
> - g_array_free(st->drops_seqs_stats_arr, TRUE);
> -
> - switch (st->codec) {
> - case SPICE_VIDEO_CODEC_TYPE_MJPEG:
> - stream_mjpeg_cleanup(st);
> - break;
> - }
> -
> - if (st->msg_clip)
> - spice_msg_in_unref(st->msg_clip);
> - spice_msg_in_unref(st->msg_create);
> -
> - g_queue_foreach(st->msgq, _msg_in_unref_func, NULL);
> - g_queue_free(st->msgq);
> - if (st->timeout != 0)
> - g_source_remove(st->timeout);
> - g_free(st);
> - c->streams[id] = NULL;
> -}
> -
> -static void clear_streams(SpiceChannel *channel)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - int i;
> -
> - for (i = 0; i < c->nstreams; i++) {
> - destroy_stream(channel, i);
> - }
> - g_free(c->streams);
> - c->streams = NULL;
> - c->nstreams = 0;
> -}
> -
> -/* coroutine context */
> -static void display_handle_stream_destroy(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayStreamDestroy *op = spice_msg_in_parsed(in);
> -
> - g_return_if_fail(op != NULL);
> - CHANNEL_DEBUG(channel, "%s: id %d", __FUNCTION__, op->id);
> - destroy_stream(channel, op->id);
> -}
> -
> -/* coroutine context */
> -static void display_handle_stream_destroy_all(SpiceChannel *channel,
> SpiceMsgIn *in)
> -{
> - clear_streams(channel);
> -}
> -
> -/* coroutine context */
> -static void display_handle_stream_activate_report(SpiceChannel *channel,
> SpiceMsgIn *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceMsgDisplayStreamActivateReport *op = spice_msg_in_parsed(in);
> - display_stream *st;
> -
> - g_return_if_fail(c != NULL);
> - g_return_if_fail(c->streams != NULL);
> - g_return_if_fail(c->nstreams > op->stream_id);
> -
> - st = c->streams[op->stream_id];
> - g_return_if_fail(st != NULL);
> -
> - st->report_is_active = TRUE;
> - st->report_id = op->unique_id;
> - st->report_max_window = op->max_window_size;
> - st->report_timeout = op->timeout_ms * 1000;
> - st->report_start_time = 0;
> - st->report_start_frame_time = 0;
> - st->report_num_frames = 0;
> - st->report_num_drops = 0;
> - st->report_drops_seq_len = 0;
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -/* coroutine context */
> -static void display_handle_draw_fill(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawFill *op = spice_msg_in_parsed(in);
> - DRAW(fill);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_opaque(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayDrawOpaque *op = spice_msg_in_parsed(in);
> - DRAW(opaque);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_copy(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawCopy *op = spice_msg_in_parsed(in);
> - DRAW(copy);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_blend(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawBlend *op = spice_msg_in_parsed(in);
> - DRAW(blend);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_blackness(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayDrawBlackness *op = spice_msg_in_parsed(in);
> - DRAW(blackness);
> -}
> -
> -static void display_handle_draw_whiteness(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayDrawWhiteness *op = spice_msg_in_parsed(in);
> - DRAW(whiteness);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_invers(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayDrawInvers *op = spice_msg_in_parsed(in);
> - DRAW(invers);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_rop3(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawRop3 *op = spice_msg_in_parsed(in);
> - DRAW(rop3);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_stroke(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayDrawStroke *op = spice_msg_in_parsed(in);
> - DRAW(stroke);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_text(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawText *op = spice_msg_in_parsed(in);
> - DRAW(text);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_transparent(SpiceChannel *channel,
> SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawTransparent *op = spice_msg_in_parsed(in);
> - DRAW(transparent);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_alpha_blend(SpiceChannel *channel,
> SpiceMsgIn *in)
> -{
> - SpiceMsgDisplayDrawAlphaBlend *op = spice_msg_in_parsed(in);
> - DRAW(alpha_blend);
> -}
> -
> -/* coroutine context */
> -static void display_handle_draw_composite(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayDrawComposite *op = spice_msg_in_parsed(in);
> - DRAW(composite);
> -}
> -
> -/* coroutine context */
> -static void display_handle_surface_create(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - SpiceMsgSurfaceCreate *create = spice_msg_in_parsed(in);
> - display_surface *surface = g_slice_new0(display_surface);
> -
> - surface->surface_id = create->surface_id;
> - surface->format = create->format;
> - surface->width = create->width;
> - surface->height = create->height;
> - surface->stride = create->width * 4;
> - surface->size = surface->height * surface->stride;
> -
> - if (create->flags & SPICE_SURFACE_FLAGS_PRIMARY) {
> - SPICE_DEBUG("primary flags: %d", create->flags);
> - surface->primary = true;
> - create_canvas(channel, surface);
> - if (c->mark_false_event_id != 0) {
> - g_source_remove(c->mark_false_event_id);
> - c->mark_false_event_id = FALSE;
> - }
> - } else {
> - surface->primary = false;
> - create_canvas(channel, surface);
> - }
> -}
> -
> -static gboolean display_mark_false(gpointer data)
> -{
> - SpiceChannel *channel = data;
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> -
> - c->mark = FALSE;
> - g_signal_emit(channel, signals[SPICE_DISPLAY_MARK], 0, FALSE);
> -
> - c->mark_false_event_id = 0;
> - return FALSE;
> -}
> -
> -/* coroutine context */
> -static void display_handle_surface_destroy(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgSurfaceDestroy *destroy = spice_msg_in_parsed(in);
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - display_surface *surface;
> -
> - g_return_if_fail(destroy != NULL);
> -
> - surface = find_surface(c, destroy->surface_id);
> - if (surface == NULL) {
> - /* this is not a problem in spicec, it happens as well and returns..
> */
> - /* g_warn_if_reached(); */
> - return;
> - }
> - if (surface->primary) {
> - int id = spice_channel_get_channel_id(channel);
> - CHANNEL_DEBUG(channel, "%d: FIXME primary destroy, but is display
> really disabled?", id);
> - /* this is done with a timeout in spicec as well, it's *ugly* */
> - if (id != 0 && c->mark_false_event_id == 0) {
> - c->mark_false_event_id = g_timeout_add_seconds(1,
> display_mark_false, channel);
> - }
> - c->primary = NULL;
> - g_coroutine_signal_emit(channel,
> signals[SPICE_DISPLAY_PRIMARY_DESTROY], 0);
> - }
> -
> - g_hash_table_remove(c->surfaces, GINT_TO_POINTER(surface->surface_id));
> -}
> -
> -#define CLAMP_CHECK(x, low, high) (((x) > (high)) ? TRUE : (((x) < (low)) ?
> TRUE : FALSE))
> -
> -/* coroutine context */
> -static void display_handle_monitors_config(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - SpiceMsgDisplayMonitorsConfig *config = spice_msg_in_parsed(in);
> - SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
> - guint i;
> -
> - g_return_if_fail(config != NULL);
> - g_return_if_fail(config->count > 0);
> -
> - CHANNEL_DEBUG(channel, "monitors config: n: %d/%d", config->count,
> config->max_allowed);
> -
> - c->monitors_max = config->max_allowed;
> - if (CLAMP_CHECK(c->monitors_max, 1, MONITORS_MAX)) {
> - g_warning("MonitorConfig max_allowed is not within permitted range,
> clamping");
> - c->monitors_max = CLAMP(c->monitors_max, 1, MONITORS_MAX);
> - }
> -
> - if (CLAMP_CHECK(config->count, 1, c->monitors_max)) {
> - g_warning("MonitorConfig count is not within permitted range,
> clamping");
> - config->count = CLAMP(config->count, 1, c->monitors_max);
> - }
> -
> - c->monitors = g_array_set_size(c->monitors, config->count);
> -
> - for (i = 0; i < config->count; i++) {
> - SpiceDisplayMonitorConfig *mc = &g_array_index(c->monitors,
> SpiceDisplayMonitorConfig, i);
> - SpiceHead *head = &config->heads[i];
> - CHANNEL_DEBUG(channel, "monitor id: %u, surface id: %u,
> +%u+%u-%ux%u",
> - head->id, head->surface_id,
> - head->x, head->y, head->width, head->height);
> - mc->id = head->id;
> - mc->surface_id = head->surface_id;
> - mc->x = head->x;
> - mc->y = head->y;
> - mc->width = head->width;
> - mc->height = head->height;
> - }
> -
> - g_coroutine_object_notify(G_OBJECT(channel), "monitors");
> -}
> -
> -static void channel_set_handlers(SpiceChannelClass *klass)
> -{
> - static const spice_msg_handler handlers[] = {
> - [ SPICE_MSG_DISPLAY_MODE ] = display_handle_mode,
> - [ SPICE_MSG_DISPLAY_MARK ] = display_handle_mark,
> - [ SPICE_MSG_DISPLAY_RESET ] = display_handle_reset,
> - [ SPICE_MSG_DISPLAY_COPY_BITS ] = display_handle_copy_bits,
> - [ SPICE_MSG_DISPLAY_INVAL_LIST ] = display_handle_inv_list,
> - [ SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS ] =
> display_handle_inv_pixmap_all,
> - [ SPICE_MSG_DISPLAY_INVAL_PALETTE ] =
> display_handle_inv_palette,
> - [ SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES ] =
> display_handle_inv_palette_all,
> -
> - [ SPICE_MSG_DISPLAY_STREAM_CREATE ] =
> display_handle_stream_create,
> - [ SPICE_MSG_DISPLAY_STREAM_DATA ] =
> display_handle_stream_data,
> - [ SPICE_MSG_DISPLAY_STREAM_CLIP ] =
> display_handle_stream_clip,
> - [ SPICE_MSG_DISPLAY_STREAM_DESTROY ] =
> display_handle_stream_destroy,
> - [ SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL ] =
> display_handle_stream_destroy_all,
> - [ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED ] =
> display_handle_stream_data,
> - [ SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT ] =
> display_handle_stream_activate_report,
> -
> - [ SPICE_MSG_DISPLAY_DRAW_FILL ] = display_handle_draw_fill,
> - [ SPICE_MSG_DISPLAY_DRAW_OPAQUE ] =
> display_handle_draw_opaque,
> - [ SPICE_MSG_DISPLAY_DRAW_COPY ] = display_handle_draw_copy,
> - [ SPICE_MSG_DISPLAY_DRAW_BLEND ] =
> display_handle_draw_blend,
> - [ SPICE_MSG_DISPLAY_DRAW_BLACKNESS ] =
> display_handle_draw_blackness,
> - [ SPICE_MSG_DISPLAY_DRAW_WHITENESS ] =
> display_handle_draw_whiteness,
> - [ SPICE_MSG_DISPLAY_DRAW_INVERS ] =
> display_handle_draw_invers,
> - [ SPICE_MSG_DISPLAY_DRAW_ROP3 ] = display_handle_draw_rop3,
> - [ SPICE_MSG_DISPLAY_DRAW_STROKE ] =
> display_handle_draw_stroke,
> - [ SPICE_MSG_DISPLAY_DRAW_TEXT ] = display_handle_draw_text,
> - [ SPICE_MSG_DISPLAY_DRAW_TRANSPARENT ] =
> display_handle_draw_transparent,
> - [ SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND ] =
> display_handle_draw_alpha_blend,
> - [ SPICE_MSG_DISPLAY_DRAW_COMPOSITE ] =
> display_handle_draw_composite,
> -
> - [ SPICE_MSG_DISPLAY_SURFACE_CREATE ] =
> display_handle_surface_create,
> - [ SPICE_MSG_DISPLAY_SURFACE_DESTROY ] =
> display_handle_surface_destroy,
> -
> - [ SPICE_MSG_DISPLAY_MONITORS_CONFIG ] =
> display_handle_monitors_config,
> - };
> -
> - spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
> -}
> diff --git a/gtk/channel-display.h b/gtk/channel-display.h
> deleted file mode 100644
> index 88e60d9..0000000
> --- a/gtk/channel-display.h
> +++ /dev/null
> @@ -1,102 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#ifndef __SPICE_CLIENT_DISPLAY_CHANNEL_H__
> -#define __SPICE_CLIENT_DISPLAY_CHANNEL_H__
> -
> -#include "spice-client.h"
> -
> -G_BEGIN_DECLS
> -
> -#define SPICE_TYPE_DISPLAY_CHANNEL
> (spice_display_channel_get_type())
> -#define SPICE_DISPLAY_CHANNEL(obj)
> (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_DISPLAY_CHANNEL,
> SpiceDisplayChannel))
> -#define SPICE_DISPLAY_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_DISPLAY_CHANNEL,
> SpiceDisplayChannelClass))
> -#define SPICE_IS_DISPLAY_CHANNEL(obj)
> (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_DISPLAY_CHANNEL))
> -#define SPICE_IS_DISPLAY_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_DISPLAY_CHANNEL))
> -#define SPICE_DISPLAY_CHANNEL_GET_CLASS(obj)
> (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_DISPLAY_CHANNEL,
> SpiceDisplayChannelClass))
> -
> -typedef struct _SpiceDisplayChannel SpiceDisplayChannel;
> -typedef struct _SpiceDisplayChannelClass SpiceDisplayChannelClass;
> -typedef struct _SpiceDisplayChannelPrivate SpiceDisplayChannelPrivate;
> -
> -typedef struct _SpiceDisplayMonitorConfig SpiceDisplayMonitorConfig;
> -struct _SpiceDisplayMonitorConfig {
> - guint id;
> - guint surface_id;
> - guint x;
> - guint y;
> - guint width;
> - guint height;
> -};
> -
> -typedef struct _SpiceDisplayPrimary SpiceDisplayPrimary;
> -struct _SpiceDisplayPrimary {
> - enum SpiceSurfaceFmt format;
> - gint width;
> - gint height;
> - gint stride;
> - gint shmid;
> - guint8 *data;
> - gboolean marked;
> -};
> -
> -/**
> - * SpiceDisplayChannel:
> - *
> - * The #SpiceDisplayChannel struct is opaque and should not be accessed
> directly.
> - */
> -struct _SpiceDisplayChannel {
> - SpiceChannel parent;
> -
> - /*< private >*/
> - SpiceDisplayChannelPrivate *priv;
> - /* Do not add fields to this struct */
> -};
> -
> -/**
> - * SpiceDisplayChannelClass:
> - * @parent_class: Parent class.
> - * @display_primary_create: Signal class handler for the
> #SpiceDisplayChannel::display-primary-create signal.
> - * @display_primary_destroy: Signal class handler for the
> #SpiceDisplayChannel::display-primary-destroy signal.
> - * @display_invalidate: Signal class handler for the
> #SpiceDisplayChannel::display-invalidate signal.
> - * @display_mark: Signal class handler for the
> #SpiceDisplayChannel::display-mark signal.
> - *
> - * Class structure for #SpiceDisplayChannel.
> - */
> -struct _SpiceDisplayChannelClass {
> - SpiceChannelClass parent_class;
> -
> - /* signals */
> - void (*display_primary_create)(SpiceChannel *channel, gint format,
> - gint width, gint height, gint stride,
> - gint shmid, gpointer data);
> - void (*display_primary_destroy)(SpiceChannel *channel);
> - void (*display_invalidate)(SpiceChannel *channel,
> - gint x, gint y, gint w, gint h);
> - void (*display_mark)(SpiceChannel *channel,
> - gboolean mark);
> -
> - /*< private >*/
> -};
> -
> -GType spice_display_channel_get_type(void);
> -gboolean spice_display_get_primary(SpiceChannel *channel, guint32
> surface_id,
> - SpiceDisplayPrimary *primary);
> -
> -G_END_DECLS
> -
> -#endif /* __SPICE_CLIENT_DISPLAY_CHANNEL_H__ */
> diff --git a/gtk/channel-inputs.c b/gtk/channel-inputs.c
> deleted file mode 100644
> index df1ffe1..0000000
> --- a/gtk/channel-inputs.c
> +++ /dev/null
> @@ -1,603 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#include "spice-client.h"
> -#include "spice-common.h"
> -#include "spice-channel-priv.h"
> -
> -/**
> - * SECTION:channel-inputs
> - * @short_description: control the server mouse and keyboard
> - * @title: Inputs Channel
> - * @section_id:
> - * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay
> - * @stability: Stable
> - * @include: channel-inputs.h
> - *
> - * Spice supports sending keyboard key events and keyboard leds
> - * synchronization. The key events are sent using
> - * spice_inputs_key_press() and spice_inputs_key_release() using
> - * a modified variant of PC XT scancodes.
> - *
> - * Guest keyboard leds state can be manipulated with
> - * spice_inputs_set_key_locks(). When key lock change, a notification
> - * is emitted with #SpiceInputsChannel::inputs-modifiers signal.
> - */
> -
> -#define SPICE_INPUTS_CHANNEL_GET_PRIVATE(obj)
> \
> - (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_INPUTS_CHANNEL,
> SpiceInputsChannelPrivate))
> -
> -struct _SpiceInputsChannelPrivate {
> - int bs;
> - int dx, dy;
> - unsigned int x, y, dpy;
> - int motion_count;
> - int modifiers;
> - guint32 locks;
> -};
> -
> -G_DEFINE_TYPE(SpiceInputsChannel, spice_inputs_channel, SPICE_TYPE_CHANNEL)
> -
> -/* Properties */
> -enum {
> - PROP_0,
> - PROP_KEY_MODIFIERS,
> -};
> -
> -/* Signals */
> -enum {
> - SPICE_INPUTS_MODIFIERS,
> -
> - SPICE_INPUTS_LAST_SIGNAL,
> -};
> -
> -static guint signals[SPICE_INPUTS_LAST_SIGNAL];
> -
> -static void spice_inputs_channel_up(SpiceChannel *channel);
> -static void spice_inputs_channel_reset(SpiceChannel *channel, gboolean
> migrating);
> -static void channel_set_handlers(SpiceChannelClass *klass);
> -
> -/* ------------------------------------------------------------------ */
> -
> -static void spice_inputs_channel_init(SpiceInputsChannel *channel)
> -{
> - channel->priv = SPICE_INPUTS_CHANNEL_GET_PRIVATE(channel);
> -}
> -
> -static void spice_inputs_get_property(GObject *object,
> - guint prop_id,
> - GValue *value,
> - GParamSpec *pspec)
> -{
> - SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(object)->priv;
> -
> - switch (prop_id) {
> - case PROP_KEY_MODIFIERS:
> - g_value_set_int(value, c->modifiers);
> - break;
> - default:
> - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
> - break;
> - }
> -}
> -
> -static void spice_inputs_channel_finalize(GObject *obj)
> -{
> - if (G_OBJECT_CLASS(spice_inputs_channel_parent_class)->finalize)
> - G_OBJECT_CLASS(spice_inputs_channel_parent_class)->finalize(obj);
> -}
> -
> -static void spice_inputs_channel_class_init(SpiceInputsChannelClass *klass)
> -{
> - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
> - SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
> -
> - gobject_class->finalize = spice_inputs_channel_finalize;
> - gobject_class->get_property = spice_inputs_get_property;
> - channel_class->channel_up = spice_inputs_channel_up;
> - channel_class->channel_reset = spice_inputs_channel_reset;
> -
> - g_object_class_install_property
> - (gobject_class, PROP_KEY_MODIFIERS,
> - g_param_spec_int("key-modifiers",
> - "Key modifiers",
> - "Guest keyboard lock/led state",
> - 0, INT_MAX, 0,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_NAME |
> - G_PARAM_STATIC_NICK |
> - G_PARAM_STATIC_BLURB));
> -
> - /**
> - * SpiceInputsChannel::inputs-modifier:
> - * @display: the #SpiceInputsChannel that emitted the signal
> - *
> - * The #SpiceInputsChannel::inputs-modifier signal is emitted when
> - * the guest keyboard locks are changed. You can read the current
> - * state from #SpiceInputsChannel:key-modifiers property.
> - **/
> - /* TODO: use notify instead? */
> - signals[SPICE_INPUTS_MODIFIERS] =
> - g_signal_new("inputs-modifiers",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceInputsChannelClass,
> inputs_modifiers),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> -
> - g_type_class_add_private(klass, sizeof(SpiceInputsChannelPrivate));
> - channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -static SpiceMsgOut* mouse_motion(SpiceInputsChannel *channel)
> -{
> - SpiceInputsChannelPrivate *c = channel->priv;
> - SpiceMsgcMouseMotion motion;
> - SpiceMsgOut *msg;
> -
> - if (!c->dx && !c->dy)
> - return NULL;
> -
> - motion.buttons_state = c->bs;
> - motion.dx = c->dx;
> - motion.dy = c->dy;
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> - SPICE_MSGC_INPUTS_MOUSE_MOTION);
> - msg->marshallers->msgc_inputs_mouse_motion(msg->marshaller, &motion);
> -
> - c->motion_count++;
> - c->dx = 0;
> - c->dy = 0;
> -
> - return msg;
> -}
> -
> -static SpiceMsgOut* mouse_position(SpiceInputsChannel *channel)
> -{
> - SpiceInputsChannelPrivate *c = channel->priv;
> - SpiceMsgcMousePosition position;
> - SpiceMsgOut *msg;
> -
> - if (c->dpy == -1)
> - return NULL;
> -
> - /* CHANNEL_DEBUG(channel, "%s: +%d+%d", __FUNCTION__, c->x, c->y); */
> - position.buttons_state = c->bs;
> - position.x = c->x;
> - position.y = c->y;
> - position.display_id = c->dpy;
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> - SPICE_MSGC_INPUTS_MOUSE_POSITION);
> - msg->marshallers->msgc_inputs_mouse_position(msg->marshaller,
> &position);
> -
> - c->motion_count++;
> - c->dpy = -1;
> -
> - return msg;
> -}
> -
> -/* main context */
> -static void send_position(SpiceInputsChannel *channel)
> -{
> - SpiceMsgOut *msg;
> -
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - msg = mouse_position(channel);
> - if (!msg) /* if no motion */
> - return;
> -
> - spice_msg_out_send(msg);
> -}
> -
> -/* main context */
> -static void send_motion(SpiceInputsChannel *channel)
> -{
> - SpiceMsgOut *msg;
> -
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - msg = mouse_motion(channel);
> - if (!msg) /* if no motion */
> - return;
> -
> - spice_msg_out_send(msg);
> -}
> -
> -/* coroutine context */
> -static void inputs_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv;
> - SpiceMsgInputsInit *init = spice_msg_in_parsed(in);
> -
> - c->modifiers = init->keyboard_modifiers;
> - g_coroutine_signal_emit(channel, signals[SPICE_INPUTS_MODIFIERS], 0);
> -}
> -
> -/* coroutine context */
> -static void inputs_handle_modifiers(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv;
> - SpiceMsgInputsKeyModifiers *modifiers = spice_msg_in_parsed(in);
> -
> - c->modifiers = modifiers->modifiers;
> - g_coroutine_signal_emit(channel, signals[SPICE_INPUTS_MODIFIERS], 0);
> -}
> -
> -/* coroutine context */
> -static void inputs_handle_ack(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv;
> - SpiceMsgOut *msg;
> -
> - c->motion_count -= SPICE_INPUT_MOTION_ACK_BUNCH;
> -
> - msg = mouse_motion(SPICE_INPUTS_CHANNEL(channel));
> - if (msg) { /* if no motion, msg == NULL */
> - spice_msg_out_send_internal(msg);
> - }
> -
> - msg = mouse_position(SPICE_INPUTS_CHANNEL(channel));
> - if (msg) {
> - spice_msg_out_send_internal(msg);
> - }
> -}
> -
> -static void channel_set_handlers(SpiceChannelClass *klass)
> -{
> - static const spice_msg_handler handlers[] = {
> - [ SPICE_MSG_INPUTS_INIT ] = inputs_handle_init,
> - [ SPICE_MSG_INPUTS_KEY_MODIFIERS ] = inputs_handle_modifiers,
> - [ SPICE_MSG_INPUTS_MOUSE_MOTION_ACK ] = inputs_handle_ack,
> - };
> -
> - spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
> -}
> -
> -/**
> - * spice_inputs_motion:
> - * @channel:
> - * @dx: delta X mouse coordinates
> - * @dy: delta Y mouse coordinates
> - * @button_state: SPICE_MOUSE_BUTTON_MASK flags
> - *
> - * Change mouse position (used in SPICE_MOUSE_MODE_CLIENT).
> - **/
> -void spice_inputs_motion(SpiceInputsChannel *channel, gint dx, gint dy,
> - gint button_state)
> -{
> - SpiceInputsChannelPrivate *c;
> -
> - g_return_if_fail(channel != NULL);
> - g_return_if_fail(SPICE_CHANNEL(channel)->priv->state !=
> SPICE_CHANNEL_STATE_UNCONNECTED);
> - if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> -
> - if (dx == 0 && dy == 0)
> - return;
> -
> - c = channel->priv;
> - c->bs = button_state;
> - c->dx += dx;
> - c->dy += dy;
> -
> - if (c->motion_count < SPICE_INPUT_MOTION_ACK_BUNCH * 2) {
> - send_motion(channel);
> - }
> -}
> -
> -/**
> - * spice_inputs_position:
> - * @channel:
> - * @x: X mouse coordinates
> - * @y: Y mouse coordinates
> - * @display: display channel id
> - * @button_state: SPICE_MOUSE_BUTTON_MASK flags
> - *
> - * Change mouse position (used in SPICE_MOUSE_MODE_CLIENT).
> - **/
> -void spice_inputs_position(SpiceInputsChannel *channel, gint x, gint y,
> - gint display, gint button_state)
> -{
> - SpiceInputsChannelPrivate *c;
> -
> - g_return_if_fail(channel != NULL);
> -
> - if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> -
> - c = channel->priv;
> - c->bs = button_state;
> - c->x = x;
> - c->y = y;
> - c->dpy = display;
> -
> - if (c->motion_count < SPICE_INPUT_MOTION_ACK_BUNCH * 2) {
> - send_position(channel);
> - } else {
> - CHANNEL_DEBUG(channel, "over SPICE_INPUT_MOTION_ACK_BUNCH * 2,
> dropping");
> - }
> -}
> -
> -/**
> - * spice_inputs_button_press:
> - * @channel:
> - * @button: a SPICE_MOUSE_BUTTON
> - * @button_state: SPICE_MOUSE_BUTTON_MASK flags
> - *
> - * Press a mouse button.
> - **/
> -void spice_inputs_button_press(SpiceInputsChannel *channel, gint button,
> - gint button_state)
> -{
> - SpiceInputsChannelPrivate *c;
> - SpiceMsgcMousePress press;
> - SpiceMsgOut *msg;
> -
> - g_return_if_fail(channel != NULL);
> -
> - if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - c = channel->priv;
> - switch (button) {
> - case SPICE_MOUSE_BUTTON_LEFT:
> - button_state |= SPICE_MOUSE_BUTTON_MASK_LEFT;
> - break;
> - case SPICE_MOUSE_BUTTON_MIDDLE:
> - button_state |= SPICE_MOUSE_BUTTON_MASK_MIDDLE;
> - break;
> - case SPICE_MOUSE_BUTTON_RIGHT:
> - button_state |= SPICE_MOUSE_BUTTON_MASK_RIGHT;
> - break;
> - }
> -
> - c->bs = button_state;
> - send_motion(channel);
> - send_position(channel);
> -
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> - SPICE_MSGC_INPUTS_MOUSE_PRESS);
> - press.button = button;
> - press.buttons_state = button_state;
> - msg->marshallers->msgc_inputs_mouse_press(msg->marshaller, &press);
> - spice_msg_out_send(msg);
> -}
> -
> -/**
> - * spice_inputs_button_release:
> - * @channel:
> - * @button: a SPICE_MOUSE_BUTTON
> - * @button_state: SPICE_MOUSE_BUTTON_MASK flags
> - *
> - * Release a button.
> - **/
> -void spice_inputs_button_release(SpiceInputsChannel *channel, gint button,
> - gint button_state)
> -{
> - SpiceInputsChannelPrivate *c;
> - SpiceMsgcMouseRelease release;
> - SpiceMsgOut *msg;
> -
> - g_return_if_fail(channel != NULL);
> -
> - if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - c = channel->priv;
> - switch (button) {
> - case SPICE_MOUSE_BUTTON_LEFT:
> - button_state &= ~SPICE_MOUSE_BUTTON_MASK_LEFT;
> - break;
> - case SPICE_MOUSE_BUTTON_MIDDLE:
> - button_state &= ~SPICE_MOUSE_BUTTON_MASK_MIDDLE;
> - break;
> - case SPICE_MOUSE_BUTTON_RIGHT:
> - button_state &= ~SPICE_MOUSE_BUTTON_MASK_RIGHT;
> - break;
> - }
> -
> - c->bs = button_state;
> - send_motion(channel);
> - send_position(channel);
> -
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> - SPICE_MSGC_INPUTS_MOUSE_RELEASE);
> - release.button = button;
> - release.buttons_state = button_state;
> - msg->marshallers->msgc_inputs_mouse_release(msg->marshaller, &release);
> - spice_msg_out_send(msg);
> -}
> -
> -/**
> - * spice_inputs_key_press:
> - * @channel:
> - * @scancode: a PC XT (set 1) key scancode. For scancodes with an %0xe0
> - * prefix, drop the prefix and OR the scancode with %0x100.
> - *
> - * Press a key.
> - **/
> -void spice_inputs_key_press(SpiceInputsChannel *channel, guint scancode)
> -{
> - SpiceMsgcKeyDown down;
> - SpiceMsgOut *msg;
> -
> - g_return_if_fail(channel != NULL);
> - g_return_if_fail(SPICE_CHANNEL(channel)->priv->state !=
> SPICE_CHANNEL_STATE_UNCONNECTED);
> - if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - down.code = spice_make_scancode(scancode, FALSE);
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_INPUTS_KEY_DOWN);
> - msg->marshallers->msgc_inputs_key_down(msg->marshaller, &down);
> - spice_msg_out_send(msg);
> -}
> -
> -/**
> - * spice_inputs_key_release:
> - * @channel:
> - * @scancode: a PC XT (set 1) key scancode. For scancodes with an %0xe0
> - * prefix, drop the prefix and OR the scancode with %0x100.
> - *
> - * Release a key.
> - **/
> -void spice_inputs_key_release(SpiceInputsChannel *channel, guint scancode)
> -{
> - SpiceMsgcKeyUp up;
> - SpiceMsgOut *msg;
> -
> - g_return_if_fail(channel != NULL);
> - g_return_if_fail(SPICE_CHANNEL(channel)->priv->state !=
> SPICE_CHANNEL_STATE_UNCONNECTED);
> - if (SPICE_CHANNEL(channel)->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - up.code = spice_make_scancode(scancode, TRUE);
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_INPUTS_KEY_UP);
> - msg->marshallers->msgc_inputs_key_up(msg->marshaller, &up);
> - spice_msg_out_send(msg);
> -}
> -
> -/**
> - * spice_inputs_key_press_and_release:
> - * @channel:
> - * @scancode: a PC XT (set 1) key scancode. For scancodes with an %0xe0
> - * prefix, drop the prefix and OR the scancode with %0x100.
> - *
> - * Press and release a key event atomically (in the same message).
> - *
> - * Since: 0.13
> - **/
> -void spice_inputs_key_press_and_release(SpiceInputsChannel *input_channel,
> guint scancode)
> -{
> - SpiceChannel *channel = SPICE_CHANNEL(input_channel);
> -
> - g_return_if_fail(channel != NULL);
> - g_return_if_fail(channel->priv->state !=
> SPICE_CHANNEL_STATE_UNCONNECTED);
> -
> - if (channel->priv->state != SPICE_CHANNEL_STATE_READY)
> - return;
> - if (spice_channel_get_read_only(channel))
> - return;
> -
> - if (spice_channel_test_capability(channel,
> SPICE_INPUTS_CAP_KEY_SCANCODE)) {
> - SpiceMsgOut *msg;
> - guint16 code;
> - guint8 *buf;
> -
> - msg = spice_msg_out_new(channel, SPICE_MSGC_INPUTS_KEY_SCANCODE);
> - if (scancode < 0x100) {
> - buf = (guint8*)spice_marshaller_reserve_space(msg->marshaller,
> 2);
> - buf[0] = spice_make_scancode(scancode, FALSE);
> - buf[1] = spice_make_scancode(scancode, TRUE);
> - } else {
> - buf = (guint8*)spice_marshaller_reserve_space(msg->marshaller,
> 4);
> - code = spice_make_scancode(scancode, FALSE);
> - buf[0] = code & 0xff;
> - buf[1] = code >> 8;
> - code = spice_make_scancode(scancode, TRUE);
> - buf[2] = code & 0xff;
> - buf[3] = code >> 8;
> - }
> - spice_msg_out_send(msg);
> - } else {
> - CHANNEL_DEBUG(channel, "The server doesn't support atomic press and
> release");
> - spice_inputs_key_press(input_channel, scancode);
> - spice_inputs_key_release(input_channel, scancode);
> - }
> -}
> -
> -/* main or coroutine context */
> -static SpiceMsgOut* set_key_locks(SpiceInputsChannel *channel, guint locks)
> -{
> - SpiceMsgcKeyModifiers modifiers;
> - SpiceMsgOut *msg;
> - SpiceInputsChannelPrivate *ic;
> - SpiceChannelPrivate *c;
> -
> - g_return_val_if_fail(SPICE_IS_INPUTS_CHANNEL(channel), NULL);
> -
> - ic = channel->priv;
> - c = SPICE_CHANNEL(channel)->priv;
> -
> - ic->locks = locks;
> - if (c->state != SPICE_CHANNEL_STATE_READY)
> - return NULL;
> -
> - msg = spice_msg_out_new(SPICE_CHANNEL(channel),
> - SPICE_MSGC_INPUTS_KEY_MODIFIERS);
> - modifiers.modifiers = locks;
> - msg->marshallers->msgc_inputs_key_modifiers(msg->marshaller,
> &modifiers);
> - return msg;
> -}
> -
> -/**
> - * spice_inputs_set_key_locks:
> - * @channel:
> - * @locks: #SpiceInputsLock modifiers flags
> - *
> - * Set the keyboard locks on the guest (Caps, Num, Scroll..)
> - **/
> -void spice_inputs_set_key_locks(SpiceInputsChannel *channel, guint locks)
> -{
> - SpiceMsgOut *msg;
> -
> - if (spice_channel_get_read_only(SPICE_CHANNEL(channel)))
> - return;
> -
> - msg = set_key_locks(channel, locks);
> - if (!msg) /* you can set_key_locks() even if the channel is not ready */
> - return;
> -
> - spice_msg_out_send(msg); /* main -> coroutine */
> -}
> -
> -/* coroutine context */
> -static void spice_inputs_channel_up(SpiceChannel *channel)
> -{
> - SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv;
> - SpiceMsgOut *msg;
> -
> - if (spice_channel_get_read_only(channel))
> - return;
> -
> - msg = set_key_locks(SPICE_INPUTS_CHANNEL(channel), c->locks);
> - spice_msg_out_send_internal(msg);
> -}
> -
> -static void spice_inputs_channel_reset(SpiceChannel *channel, gboolean
> migrating)
> -{
> - SpiceInputsChannelPrivate *c = SPICE_INPUTS_CHANNEL(channel)->priv;
> - c->motion_count = 0;
> -
> -
> SPICE_CHANNEL_CLASS(spice_inputs_channel_parent_class)->channel_reset(channel,
> migrating);
> -}
> diff --git a/gtk/channel-inputs.h b/gtk/channel-inputs.h
> deleted file mode 100644
> index 3179a76..0000000
> --- a/gtk/channel-inputs.h
> +++ /dev/null
> @@ -1,89 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#ifndef __SPICE_CLIENT_INPUTS_CHANNEL_H__
> -#define __SPICE_CLIENT_INPUTS_CHANNEL_H__
> -
> -#include "spice-client.h"
> -
> -G_BEGIN_DECLS
> -
> -#define SPICE_TYPE_INPUTS_CHANNEL
> (spice_inputs_channel_get_type())
> -#define SPICE_INPUTS_CHANNEL(obj)
> (G_TYPE_CHECK_INSTANCE_CAST((obj), SPICE_TYPE_INPUTS_CHANNEL,
> SpiceInputsChannel))
> -#define SPICE_INPUTS_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_CAST((klass), SPICE_TYPE_INPUTS_CHANNEL,
> SpiceInputsChannelClass))
> -#define SPICE_IS_INPUTS_CHANNEL(obj)
> (G_TYPE_CHECK_INSTANCE_TYPE((obj), SPICE_TYPE_INPUTS_CHANNEL))
> -#define SPICE_IS_INPUTS_CHANNEL_CLASS(klass)
> (G_TYPE_CHECK_CLASS_TYPE((klass), SPICE_TYPE_INPUTS_CHANNEL))
> -#define SPICE_INPUTS_CHANNEL_GET_CLASS(obj)
> (G_TYPE_INSTANCE_GET_CLASS((obj), SPICE_TYPE_INPUTS_CHANNEL,
> SpiceInputsChannelClass))
> -
> -typedef struct _SpiceInputsChannel SpiceInputsChannel;
> -typedef struct _SpiceInputsChannelClass SpiceInputsChannelClass;
> -typedef struct _SpiceInputsChannelPrivate SpiceInputsChannelPrivate;
> -
> -typedef enum {
> - SPICE_INPUTS_SCROLL_LOCK = (1 << 0),
> - SPICE_INPUTS_NUM_LOCK = (1 << 1),
> - SPICE_INPUTS_CAPS_LOCK = (1 << 2)
> -} SpiceInputsLock;
> -
> -/**
> - * SpiceInputsChannel:
> - *
> - * The #SpiceInputsChannel struct is opaque and should not be accessed
> directly.
> - */
> -struct _SpiceInputsChannel {
> - SpiceChannel parent;
> -
> - /*< private >*/
> - SpiceInputsChannelPrivate *priv;
> - /* Do not add fields to this struct */
> -};
> -
> -/**
> - * SpiceInputsChannelClass:
> - * @parent_class: Parent class.
> - * @inputs_modifiers: Signal class handler for the
> #SpiceInputsChannel::inputs-modifiers signal.
> - *
> - * Class structure for #SpiceInputsChannel.
> - */
> -struct _SpiceInputsChannelClass {
> - SpiceChannelClass parent_class;
> -
> - /* signals */
> - void (*inputs_modifiers)(SpiceChannel *channel);
> -
> - /*< private >*/
> - /* Do not add fields to this struct */
> -};
> -
> -GType spice_inputs_channel_get_type(void);
> -
> -void spice_inputs_motion(SpiceInputsChannel *channel, gint dx, gint dy,
> - gint button_state);
> -void spice_inputs_position(SpiceInputsChannel *channel, gint x, gint y,
> - gint display, gint button_state);
> -void spice_inputs_button_press(SpiceInputsChannel *channel, gint button,
> - gint button_state);
> -void spice_inputs_button_release(SpiceInputsChannel *channel, gint button,
> - gint button_state);
> -void spice_inputs_key_press(SpiceInputsChannel *channel, guint scancode);
> -void spice_inputs_key_release(SpiceInputsChannel *channel, guint scancode);
> -void spice_inputs_set_key_locks(SpiceInputsChannel *channel, guint locks);
> -void spice_inputs_key_press_and_release(SpiceInputsChannel *channel, guint
> scancode);
> -
> -G_END_DECLS
> -
> -#endif /* __SPICE_CLIENT_INPUTS_CHANNEL_H__ */
> diff --git a/gtk/channel-main.c b/gtk/channel-main.c
> deleted file mode 100644
> index c55d097..0000000
> --- a/gtk/channel-main.c
> +++ /dev/null
> @@ -1,2993 +0,0 @@
> -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> -/*
> - Copyright (C) 2010 Red Hat, Inc.
> -
> - This library is free software; you can redistribute it and/or
> - modify it under the terms of the GNU Lesser General Public
> - License as published by the Free Software Foundation; either
> - version 2.1 of the License, or (at your option) any later version.
> -
> - This library is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - Lesser General Public License for more details.
> -
> - You should have received a copy of the GNU Lesser General Public
> - License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> -*/
> -#include "config.h"
> -
> -#include <math.h>
> -#include <spice/vd_agent.h>
> -#include <common/rect.h>
> -#include <glib/gstdio.h>
> -
> -#include "glib-compat.h"
> -#include "spice-client.h"
> -#include "spice-common.h"
> -#include "spice-marshal.h"
> -
> -#include "spice-util-priv.h"
> -#include "spice-channel-priv.h"
> -#include "spice-session-priv.h"
> -#include "spice-audio-priv.h"
> -
> -/**
> - * SECTION:channel-main
> - * @short_description: the main Spice channel
> - * @title: Main Channel
> - * @section_id:
> - * @see_also: #SpiceChannel, and the GTK widget #SpiceDisplay
> - * @stability: Stable
> - * @include: channel-main.h
> - *
> - * The main channel is the Spice session control channel. It handles
> - * communication initialization (channels list), migrations, mouse
> - * modes, multimedia time, and agent communication.
> - *
> - *
> - */
> -
> -#define SPICE_MAIN_CHANNEL_GET_PRIVATE(obj) \
> - (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_MAIN_CHANNEL,
> SpiceMainChannelPrivate))
> -
> -#define MAX_DISPLAY 16 /* Note must fit in a guint32, see monitors_align */
> -
> -typedef struct spice_migrate spice_migrate;
> -
> -#define FILE_XFER_CHUNK_SIZE (VD_AGENT_MAX_DATA_SIZE * 32)
> -typedef struct SpiceFileXferTask {
> - uint32_t id;
> - gboolean pending;
> - GFile *file;
> - SpiceMainChannel *channel;
> - GFileInputStream *file_stream;
> - GFileCopyFlags flags;
> - GCancellable *cancellable;
> - GFileProgressCallback progress_callback;
> - gpointer progress_callback_data;
> - GAsyncReadyCallback callback;
> - gpointer user_data;
> - char buffer[FILE_XFER_CHUNK_SIZE];
> - uint64_t read_bytes;
> - uint64_t file_size;
> - GError *error;
> -} SpiceFileXferTask;
> -
> -struct _SpiceMainChannelPrivate {
> - enum SpiceMouseMode mouse_mode;
> - bool agent_connected;
> - bool agent_caps_received;
> -
> - gboolean agent_display_config_sent;
> - guint8 display_color_depth;
> - gboolean display_disable_wallpaper:1;
> - gboolean display_disable_font_smooth:1;
> - gboolean display_disable_animation:1;
> - gboolean disable_display_position:1;
> - gboolean disable_display_align:1;
> -
> - int agent_tokens;
> - VDAgentMessage agent_msg; /* partial msg reconstruction */
> - guint8 *agent_msg_data;
> - guint agent_msg_pos;
> - uint8_t agent_msg_size;
> - uint32_t agent_caps[VD_AGENT_CAPS_SIZE];
> - struct {
> - int x;
> - int y;
> - int width;
> - int height;
> - gboolean enabled;
> - gboolean enabled_set;
> - } display[MAX_DISPLAY];
> - gint timer_id;
> - GQueue *agent_msg_queue;
> - GHashTable *file_xfer_tasks;
> - GSList *flushing;
> -
> - guint switch_host_delayed_id;
> - guint migrate_delayed_id;
> - spice_migrate *migrate_data;
> - int max_clipboard;
> -
> - gboolean agent_volume_playback_sync;
> - gboolean agent_volume_record_sync;
> - GCancellable *cancellable_volume_info;
> -};
> -
> -struct spice_migrate {
> - struct coroutine *from;
> - SpiceMigrationDstInfo *info;
> - SpiceSession *session;
> - guint nchannels;
> - SpiceChannel *src_channel;
> - SpiceChannel *dst_channel;
> - bool do_seamless; /* used as input and output for the seamless migration
> handshake.
> - input: whether to send to the dest
> SPICE_MSGC_MAIN_MIGRATE_DST_DO_SEAMLESS
> - output: whether the dest approved seamless
> migration
> - (SPICE_MSG_MAIN_MIGRATE_DST_SEAMLESS_ACK/NACK)
> - */
> - uint32_t src_mig_version;
> -};
> -
> -G_DEFINE_TYPE(SpiceMainChannel, spice_main_channel, SPICE_TYPE_CHANNEL)
> -
> -/* Properties */
> -enum {
> - PROP_0,
> - PROP_MOUSE_MODE,
> - PROP_AGENT_CONNECTED,
> - PROP_AGENT_CAPS_0,
> - PROP_DISPLAY_DISABLE_WALLPAPER,
> - PROP_DISPLAY_DISABLE_FONT_SMOOTH,
> - PROP_DISPLAY_DISABLE_ANIMATION,
> - PROP_DISPLAY_COLOR_DEPTH,
> - PROP_DISABLE_DISPLAY_POSITION,
> - PROP_DISABLE_DISPLAY_ALIGN,
> - PROP_MAX_CLIPBOARD,
> -};
> -
> -/* Signals */
> -enum {
> - SPICE_MAIN_MOUSE_UPDATE,
> - SPICE_MAIN_AGENT_UPDATE,
> - SPICE_MAIN_CLIPBOARD,
> - SPICE_MAIN_CLIPBOARD_GRAB,
> - SPICE_MAIN_CLIPBOARD_REQUEST,
> - SPICE_MAIN_CLIPBOARD_RELEASE,
> - SPICE_MAIN_CLIPBOARD_SELECTION,
> - SPICE_MAIN_CLIPBOARD_SELECTION_GRAB,
> - SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST,
> - SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE,
> - SPICE_MIGRATION_STARTED,
> - SPICE_MAIN_LAST_SIGNAL,
> -};
> -
> -static guint signals[SPICE_MAIN_LAST_SIGNAL];
> -
> -static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
> -static void channel_set_handlers(SpiceChannelClass *klass);
> -static void agent_send_msg_queue(SpiceMainChannel *channel);
> -static void agent_free_msg_queue(SpiceMainChannel *channel);
> -static void migrate_channel_event_cb(SpiceChannel *channel,
> SpiceChannelEvent event,
> - gpointer data);
> -static gboolean main_migrate_handshake_done(gpointer data);
> -static void spice_main_channel_send_migration_handshake(SpiceChannel
> *channel);
> -static void file_xfer_continue_read(SpiceFileXferTask *task);
> -static void file_xfer_completed(SpiceFileXferTask *task, GError *error);
> -static void file_xfer_flushed(SpiceMainChannel *channel, gboolean success);
> -static void spice_main_set_max_clipboard(SpiceMainChannel *self, gint max);
> -static void set_agent_connected(SpiceMainChannel *channel, gboolean
> connected);
> -
> -/* ------------------------------------------------------------------ */
> -
> -static const char *agent_msg_types[] = {
> - [ VD_AGENT_MOUSE_STATE ] = "mouse state",
> - [ VD_AGENT_MONITORS_CONFIG ] = "monitors config",
> - [ VD_AGENT_REPLY ] = "reply",
> - [ VD_AGENT_CLIPBOARD ] = "clipboard",
> - [ VD_AGENT_DISPLAY_CONFIG ] = "display config",
> - [ VD_AGENT_ANNOUNCE_CAPABILITIES ] = "announce caps",
> - [ VD_AGENT_CLIPBOARD_GRAB ] = "clipboard grab",
> - [ VD_AGENT_CLIPBOARD_REQUEST ] = "clipboard request",
> - [ VD_AGENT_CLIPBOARD_RELEASE ] = "clipboard release",
> - [ VD_AGENT_AUDIO_VOLUME_SYNC ] = "volume-sync",
> -};
> -
> -static const char *agent_caps[] = {
> - [ VD_AGENT_CAP_MOUSE_STATE ] = "mouse state",
> - [ VD_AGENT_CAP_MONITORS_CONFIG ] = "monitors config",
> - [ VD_AGENT_CAP_REPLY ] = "reply",
> - [ VD_AGENT_CAP_CLIPBOARD ] = "clipboard (old)",
> - [ VD_AGENT_CAP_DISPLAY_CONFIG ] = "display config",
> - [ VD_AGENT_CAP_CLIPBOARD_BY_DEMAND ] = "clipboard",
> - [ VD_AGENT_CAP_CLIPBOARD_SELECTION ] = "clipboard selection",
> - [ VD_AGENT_CAP_SPARSE_MONITORS_CONFIG ] = "sparse monitors",
> - [ VD_AGENT_CAP_GUEST_LINEEND_LF ] = "line-end lf",
> - [ VD_AGENT_CAP_GUEST_LINEEND_CRLF ] = "line-end crlf",
> - [ VD_AGENT_CAP_MAX_CLIPBOARD ] = "max-clipboard",
> - [ VD_AGENT_CAP_AUDIO_VOLUME_SYNC ] = "volume-sync",
> -};
> -#define NAME(_a, _i) ((_i) < SPICE_N_ELEMENTS(_a) ? (_a[(_i)] ?: "?") : "?")
> -
> -/* ------------------------------------------------------------------ */
> -
> -static gboolean test_agent_cap(SpiceMainChannel *channel, guint32 cap)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> -
> - if (!c->agent_caps_received)
> - return FALSE;
> -
> - return VD_AGENT_HAS_CAPABILITY(c->agent_caps,
> G_N_ELEMENTS(c->agent_caps), cap);
> -}
> -
> -static void spice_main_channel_reset_capabilties(SpiceChannel *channel)
> -{
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_MAIN_CAP_NAME_AND_UUID);
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS);
> - spice_channel_set_capability(SPICE_CHANNEL(channel),
> SPICE_MAIN_CAP_SEAMLESS_MIGRATE);
> -}
> -
> -static void spice_main_channel_init(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c;
> -
> - c = channel->priv = SPICE_MAIN_CHANNEL_GET_PRIVATE(channel);
> - c->agent_msg_queue = g_queue_new();
> - c->file_xfer_tasks = g_hash_table_new(g_direct_hash, g_direct_equal);
> - c->cancellable_volume_info = g_cancellable_new();
> -
> - spice_main_channel_reset_capabilties(SPICE_CHANNEL(channel));
> -}
> -
> -static gint spice_main_get_max_clipboard(SpiceMainChannel *self)
> -{
> - g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(self), 0);
> -
> - if (g_getenv("SPICE_MAX_CLIPBOARD"))
> - return atoi(g_getenv("SPICE_MAX_CLIPBOARD"));
> -
> - return self->priv->max_clipboard;
> -}
> -
> -static void spice_main_get_property(GObject *object,
> - guint prop_id,
> - GValue *value,
> - GParamSpec *pspec)
> -{
> - SpiceMainChannel *self = SPICE_MAIN_CHANNEL(object);
> - SpiceMainChannelPrivate *c = self->priv;
> -
> - switch (prop_id) {
> - case PROP_MOUSE_MODE:
> - g_value_set_int(value, c->mouse_mode);
> - break;
> - case PROP_AGENT_CONNECTED:
> - g_value_set_boolean(value, c->agent_connected);
> - break;
> - case PROP_AGENT_CAPS_0:
> - g_value_set_int(value, c->agent_caps[0]);
> - break;
> - case PROP_DISPLAY_DISABLE_WALLPAPER:
> - g_value_set_boolean(value, c->display_disable_wallpaper);
> - break;
> - case PROP_DISPLAY_DISABLE_FONT_SMOOTH:
> - g_value_set_boolean(value, c->display_disable_font_smooth);
> - break;
> - case PROP_DISPLAY_DISABLE_ANIMATION:
> - g_value_set_boolean(value, c->display_disable_animation);
> - break;
> - case PROP_DISPLAY_COLOR_DEPTH:
> - g_value_set_uint(value, c->display_color_depth);
> - break;
> - case PROP_DISABLE_DISPLAY_POSITION:
> - g_value_set_boolean(value, c->disable_display_position);
> - break;
> - case PROP_DISABLE_DISPLAY_ALIGN:
> - g_value_set_boolean(value, c->disable_display_align);
> - break;
> - case PROP_MAX_CLIPBOARD:
> - g_value_set_int(value, spice_main_get_max_clipboard(self));
> - break;
> - default:
> - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
> - break;
> - }
> -}
> -
> -static void spice_main_set_property(GObject *gobject, guint prop_id,
> - const GValue *value, GParamSpec *pspec)
> -{
> - SpiceMainChannel *self = SPICE_MAIN_CHANNEL(gobject);
> - SpiceMainChannelPrivate *c = self->priv;
> -
> - switch (prop_id) {
> - case PROP_DISPLAY_DISABLE_WALLPAPER:
> - c->display_disable_wallpaper = g_value_get_boolean(value);
> - break;
> - case PROP_DISPLAY_DISABLE_FONT_SMOOTH:
> - c->display_disable_font_smooth = g_value_get_boolean(value);
> - break;
> - case PROP_DISPLAY_DISABLE_ANIMATION:
> - c->display_disable_animation = g_value_get_boolean(value);
> - break;
> - case PROP_DISPLAY_COLOR_DEPTH: {
> - guint color_depth = g_value_get_uint(value);
> - g_return_if_fail(color_depth % 8 == 0);
> - c->display_color_depth = color_depth;
> - break;
> - }
> - case PROP_DISABLE_DISPLAY_POSITION:
> - c->disable_display_position = g_value_get_boolean(value);
> - break;
> - case PROP_DISABLE_DISPLAY_ALIGN:
> - c->disable_display_align = g_value_get_boolean(value);
> - break;
> - case PROP_MAX_CLIPBOARD:
> - spice_main_set_max_clipboard(self, g_value_get_int(value));
> - break;
> - default:
> - G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
> - break;
> - }
> -}
> -
> -static void spice_main_channel_dispose(GObject *obj)
> -{
> - SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(obj)->priv;
> -
> - if (c->timer_id) {
> - g_source_remove(c->timer_id);
> - c->timer_id = 0;
> - }
> -
> - if (c->switch_host_delayed_id) {
> - g_source_remove(c->switch_host_delayed_id);
> - c->switch_host_delayed_id = 0;
> - }
> -
> - if (c->migrate_delayed_id) {
> - g_source_remove(c->migrate_delayed_id);
> - c->migrate_delayed_id = 0;
> - }
> -
> - g_cancellable_cancel(c->cancellable_volume_info);
> - g_clear_object(&c->cancellable_volume_info);
> -
> - if (G_OBJECT_CLASS(spice_main_channel_parent_class)->dispose)
> - G_OBJECT_CLASS(spice_main_channel_parent_class)->dispose(obj);
> -}
> -
> -static void spice_main_channel_finalize(GObject *obj)
> -{
> - SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(obj)->priv;
> -
> - g_free(c->agent_msg_data);
> - agent_free_msg_queue(SPICE_MAIN_CHANNEL(obj));
> - if (c->file_xfer_tasks)
> - g_hash_table_unref(c->file_xfer_tasks);
> -
> - if (G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize)
> - G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize(obj);
> -}
> -
> -/* coroutine context */
> -static void spice_channel_iterate_write(SpiceChannel *channel)
> -{
> - agent_send_msg_queue(SPICE_MAIN_CHANNEL(channel));
> -
> - if (SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->iterate_write)
> -
> SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->iterate_write(channel);
> -}
> -
> -/* main or coroutine context */
> -static void spice_main_channel_reset_agent(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - GError *error;
> - GList *tasks;
> - GList *l;
> -
> - c->agent_connected = FALSE;
> - c->agent_caps_received = FALSE;
> - c->agent_display_config_sent = FALSE;
> - c->agent_msg_pos = 0;
> - g_free(c->agent_msg_data);
> - c->agent_msg_data = NULL;
> - c->agent_msg_size = 0;
> -
> - tasks = g_hash_table_get_values(c->file_xfer_tasks);
> - for (l = tasks; l != NULL; l = l->next) {
> - SpiceFileXferTask *task = (SpiceFileXferTask *)l->data;
> -
> - error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> - "Agent connection closed");
> - file_xfer_completed(task, error);
> - }
> - g_list_free(tasks);
> - file_xfer_flushed(channel, FALSE);
> -}
> -
> -/* main or coroutine context */
> -static void spice_main_channel_reset(SpiceChannel *channel, gboolean
> migrating)
> -{
> - SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
> -
> - /* This is not part of reset_agent, since the spice-server expects any
> - pending multi-chunk messages to be completed by the client, even
> after
> - it has send an agent-disconnected msg as that is what the original
> - spicec did. Also see the TODO in server/reds.c reds_reset_vdp() */
> - c->agent_tokens = 0;
> - agent_free_msg_queue(SPICE_MAIN_CHANNEL(channel));
> - c->agent_msg_queue = g_queue_new();
> -
> - c->agent_volume_playback_sync = FALSE;
> - c->agent_volume_record_sync = FALSE;
> -
> - set_agent_connected(SPICE_MAIN_CHANNEL(channel), FALSE);
> -
> -
> SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->channel_reset(channel,
> migrating);
> -}
> -
> -static void spice_main_constructed(GObject *object)
> -{
> - SpiceMainChannel *self = SPICE_MAIN_CHANNEL(object);
> - SpiceMainChannelPrivate *c = self->priv;
> -
> - /* update default value */
> - c->max_clipboard = spice_main_get_max_clipboard(self);
> -
> - if (G_OBJECT_CLASS(spice_main_channel_parent_class)->constructed)
> -
> G_OBJECT_CLASS(spice_main_channel_parent_class)->constructed(object);
> -}
> -
> -static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
> -{
> - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
> - SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
> -
> - gobject_class->dispose = spice_main_channel_dispose;
> - gobject_class->finalize = spice_main_channel_finalize;
> - gobject_class->get_property = spice_main_get_property;
> - gobject_class->set_property = spice_main_set_property;
> - gobject_class->constructed = spice_main_constructed;
> -
> - channel_class->handle_msg = spice_main_handle_msg;
> - channel_class->iterate_write = spice_channel_iterate_write;
> - channel_class->channel_reset = spice_main_channel_reset;
> - channel_class->channel_reset_capabilities =
> spice_main_channel_reset_capabilties;
> - channel_class->channel_send_migration_handshake =
> spice_main_channel_send_migration_handshake;
> -
> - /**
> - * SpiceMainChannel:mouse-mode:
> - *
> - * Spice protocol specifies two mouse modes, client mode and
> - * server mode. In client mode (%SPICE_MOUSE_MODE_CLIENT), the
> - * affective mouse is the client side mouse: the client sends
> - * mouse position within the display and the server sends mouse
> - * shape messages. In server mode (%SPICE_MOUSE_MODE_SERVER), the
> - * client sends relative mouse movements and the server sends
> - * position and shape commands.
> - **/
> - g_object_class_install_property
> - (gobject_class, PROP_MOUSE_MODE,
> - g_param_spec_int("mouse-mode",
> - "Mouse mode",
> - "Mouse mode",
> - 0, INT_MAX, 0,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_NAME |
> - G_PARAM_STATIC_NICK |
> - G_PARAM_STATIC_BLURB));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_AGENT_CONNECTED,
> - g_param_spec_boolean("agent-connected",
> - "Agent connected",
> - "Whether the agent is connected",
> - FALSE,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_NAME |
> - G_PARAM_STATIC_NICK |
> - G_PARAM_STATIC_BLURB));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_AGENT_CAPS_0,
> - g_param_spec_int("agent-caps-0",
> - "Agent caps 0",
> - "Agent capability bits 0 -> 31",
> - 0, INT_MAX, 0,
> - G_PARAM_READABLE |
> - G_PARAM_STATIC_NAME |
> - G_PARAM_STATIC_NICK |
> - G_PARAM_STATIC_BLURB));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_DISPLAY_DISABLE_WALLPAPER,
> - g_param_spec_boolean("disable-wallpaper",
> - "Disable guest wallpaper",
> - "Disable guest wallpaper",
> - FALSE,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_DISPLAY_DISABLE_FONT_SMOOTH,
> - g_param_spec_boolean("disable-font-smooth",
> - "Disable guest font smooth",
> - "Disable guest font smoothing",
> - FALSE,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_DISPLAY_DISABLE_ANIMATION,
> - g_param_spec_boolean("disable-animation",
> - "Disable guest animations",
> - "Disable guest animations",
> - FALSE,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_DISABLE_DISPLAY_POSITION,
> - g_param_spec_boolean("disable-display-position",
> - "Disable display position",
> - "Disable using display position when setting
> monitor config",
> - TRUE,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - g_object_class_install_property
> - (gobject_class, PROP_DISPLAY_COLOR_DEPTH,
> - g_param_spec_uint("color-depth",
> - "Color depth",
> - "Color depth", 0, 32, 0,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - /**
> - * SpiceMainChannel:disable-display-align:
> - *
> - * Disable automatic horizontal display position alignment.
> - *
> - * Since: 0.13
> - */
> - g_object_class_install_property
> - (gobject_class, PROP_DISABLE_DISPLAY_ALIGN,
> - g_param_spec_boolean("disable-display-align",
> - "Disable display align",
> - "Disable display position alignment",
> - FALSE,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - /**
> - * SpiceMainChannel:max-clipboard:
> - *
> - * Maximum size of clipboard operations in bytes (default 100MB,
> - * -1 for unlimited size);
> - *
> - * Since: 0.22
> - **/
> - g_object_class_install_property
> - (gobject_class, PROP_MAX_CLIPBOARD,
> - g_param_spec_int("max-clipboard",
> - "max clipboard",
> - "Maximum clipboard data size",
> - -1, G_MAXINT, 100 * 1024 * 1024,
> - G_PARAM_READWRITE |
> - G_PARAM_CONSTRUCT |
> - G_PARAM_STATIC_STRINGS));
> -
> - /* TODO use notify instead */
> - /**
> - * SpiceMainChannel::main-mouse-update:
> - * @main: the #SpiceMainChannel that emitted the signal
> - *
> - * Notify when the mouse mode has changed.
> - **/
> - signals[SPICE_MAIN_MOUSE_UPDATE] =
> - g_signal_new("main-mouse-update",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceMainChannelClass, mouse_update),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> -
> - /* TODO use notify instead */
> - /**
> - * SpiceMainChannel::main-agent-update:
> - * @main: the #SpiceMainChannel that emitted the signal
> - *
> - * Notify when the %SpiceMainChannel:agent-connected or
> - * %SpiceMainChannel:agent-caps-0 property change.
> - **/
> - signals[SPICE_MAIN_AGENT_UPDATE] =
> - g_signal_new("main-agent-update",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_FIRST,
> - G_STRUCT_OFFSET(SpiceMainChannelClass, agent_update),
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> - /**
> - * SpiceMainChannel::main-clipboard:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @type: the VD_AGENT_CLIPBOARD data type
> - * @data: clipboard data
> - * @size: size of @data in bytes
> - *
> - * Provides guest clipboard data requested by
> spice_main_clipboard_request().
> - *
> - * Deprecated: 0.6: use SpiceMainChannel::main-clipboard-selection
> instead.
> - **/
> - signals[SPICE_MAIN_CLIPBOARD] =
> - g_signal_new("main-clipboard",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
> - 0,
> - NULL, NULL,
> - g_cclosure_user_marshal_VOID__UINT_POINTER_UINT,
> - G_TYPE_NONE,
> - 3,
> - G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-selection:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard
> - * @type: the VD_AGENT_CLIPBOARD data type
> - * @data: clipboard data
> - * @size: size of @data in bytes
> - *
> - * Since: 0.6
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_SELECTION] =
> - g_signal_new("main-clipboard-selection",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST,
> - 0,
> - NULL, NULL,
> - g_cclosure_user_marshal_VOID__UINT_UINT_POINTER_UINT,
> - G_TYPE_NONE,
> - 4,
> - G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-grab:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @types: the VD_AGENT_CLIPBOARD data types
> - * @ntypes: the number of @types
> - *
> - * Inform when clipboard data is available from the guest, and for
> - * which @types.
> - *
> - * Deprecated: 0.6: use SpiceMainChannel::main-clipboard-selection-grab
> instead.
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_GRAB] =
> - g_signal_new("main-clipboard-grab",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
> - 0,
> - NULL, NULL,
> - g_cclosure_user_marshal_BOOLEAN__POINTER_UINT,
> - G_TYPE_BOOLEAN,
> - 2,
> - G_TYPE_POINTER, G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-selection-grab:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard
> - * @types: the VD_AGENT_CLIPBOARD data types
> - * @ntypes: the number of @types
> - *
> - * Inform when clipboard data is available from the guest, and for
> - * which @types.
> - *
> - * Since: 0.6
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_SELECTION_GRAB] =
> - g_signal_new("main-clipboard-selection-grab",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST,
> - 0,
> - NULL, NULL,
> - g_cclosure_user_marshal_BOOLEAN__UINT_POINTER_UINT,
> - G_TYPE_BOOLEAN,
> - 3,
> - G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-request:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @types: the VD_AGENT_CLIPBOARD request type
> - *
> - * Return value: %TRUE if the request is successful
> - *
> - * Request clipbard data from the client.
> - *
> - * Deprecated: 0.6: use
> SpiceMainChannel::main-clipboard-selection-request instead.
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_REQUEST] =
> - g_signal_new("main-clipboard-request",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
> - 0,
> - NULL, NULL,
> - g_cclosure_user_marshal_BOOLEAN__UINT,
> - G_TYPE_BOOLEAN,
> - 1,
> - G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-selection-request:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard
> - * @types: the VD_AGENT_CLIPBOARD request type
> - *
> - * Return value: %TRUE if the request is successful
> - *
> - * Request clipbard data from the client.
> - *
> - * Since: 0.6
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST] =
> - g_signal_new("main-clipboard-selection-request",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST,
> - 0,
> - NULL, NULL,
> - g_cclosure_user_marshal_BOOLEAN__UINT_UINT,
> - G_TYPE_BOOLEAN,
> - 2,
> - G_TYPE_UINT, G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-release:
> - * @main: the #SpiceMainChannel that emitted the signal
> - *
> - * Inform when the clipboard is released from the guest, when no
> - * clipboard data is available from the guest.
> - *
> - * Deprecated: 0.6: use
> SpiceMainChannel::main-clipboard-selection-release instead.
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_RELEASE] =
> - g_signal_new("main-clipboard-release",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
> - 0,
> - NULL, NULL,
> - g_cclosure_marshal_VOID__VOID,
> - G_TYPE_NONE,
> - 0);
> -
> - /**
> - * SpiceMainChannel::main-clipboard-selection-release:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @selection: a VD_AGENT_CLIPBOARD_SELECTION clipboard
> - *
> - * Inform when the clipboard is released from the guest, when no
> - * clipboard data is available from the guest.
> - *
> - * Since: 0.6
> - **/
> - signals[SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE] =
> - g_signal_new("main-clipboard-selection-release",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST,
> - 0,
> - NULL, NULL,
> - g_cclosure_marshal_VOID__UINT,
> - G_TYPE_NONE,
> - 1,
> - G_TYPE_UINT);
> -
> - /**
> - * SpiceMainChannel::migration-started:
> - * @main: the #SpiceMainChannel that emitted the signal
> - * @session: a migration #SpiceSession
> - *
> - * Inform when migration is starting. Application wishing to make
> - * connections themself can set the #SpiceSession:client-sockets
> - * to @TRUE, then follow #SpiceSession::channel-new creation, and
> - * use spice_channel_open_fd() once the socket is created.
> - *
> - **/
> - signals[SPICE_MIGRATION_STARTED] =
> - g_signal_new("migration-started",
> - G_OBJECT_CLASS_TYPE(gobject_class),
> - G_SIGNAL_RUN_LAST,
> - 0,
> - NULL, NULL,
> - g_cclosure_marshal_VOID__OBJECT,
> - G_TYPE_NONE,
> - 1,
> - G_TYPE_OBJECT);
> -
> - g_type_class_add_private(klass, sizeof(SpiceMainChannelPrivate));
> - channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
> -}
> -
> -/* ------------------------------------------------------------------ */
> -
> -
> -static void agent_free_msg_queue(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - SpiceMsgOut *out;
> -
> - if (!c->agent_msg_queue)
> - return;
> -
> - while (!g_queue_is_empty(c->agent_msg_queue)) {
> - out = g_queue_pop_head(c->agent_msg_queue);
> - spice_msg_out_unref(out);
> - }
> -
> - g_queue_free(c->agent_msg_queue);
> - c->agent_msg_queue = NULL;
> -}
> -
> -/* Here, flushing algorithm is stolen from spice-channel.c */
> -static void file_xfer_flushed(SpiceMainChannel *channel, gboolean success)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - GSList *l;
> -
> - for (l = c->flushing; l != NULL; l = l->next) {
> - GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(l->data);
> - g_simple_async_result_set_op_res_gboolean(result, success);
> - g_simple_async_result_complete_in_idle(result);
> - }
> -
> - g_slist_free_full(c->flushing, g_object_unref);
> - c->flushing = NULL;
> -}
> -
> -static void file_xfer_flush_async(SpiceMainChannel *channel, GCancellable
> *cancellable,
> - GAsyncReadyCallback callback, gpointer
> user_data)
> -{
> - GSimpleAsyncResult *simple;
> - SpiceMainChannelPrivate *c = channel->priv;
> - gboolean was_empty;
> -
> - simple = g_simple_async_result_new(G_OBJECT(channel), callback,
> user_data,
> - file_xfer_flush_async);
> -
> - was_empty = g_queue_is_empty(c->agent_msg_queue);
> - if (was_empty) {
> - g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> - g_simple_async_result_complete_in_idle(simple);
> - g_object_unref(simple);
> - return;
> - }
> -
> - c->flushing = g_slist_append(c->flushing, simple);
> -}
> -
> -static gboolean file_xfer_flush_finish(SpiceMainChannel *channel,
> GAsyncResult *result,
> - GError **error)
> -{
> - GSimpleAsyncResult *simple = (GSimpleAsyncResult *)result;
> -
> - g_return_val_if_fail(g_simple_async_result_is_valid(result,
> - G_OBJECT(channel), file_xfer_flush_async), FALSE);
> -
> - if (g_simple_async_result_propagate_error(simple, error)) {
> - return FALSE;
> - }
> -
> - CHANNEL_DEBUG(channel, "flushed finished!");
> - return g_simple_async_result_get_op_res_gboolean(simple);
> -}
> -
> -/* coroutine context */
> -static void agent_send_msg_queue(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - SpiceMsgOut *out;
> -
> - while (c->agent_tokens > 0 &&
> - !g_queue_is_empty(c->agent_msg_queue)) {
> - c->agent_tokens--;
> - out = g_queue_pop_head(c->agent_msg_queue);
> - spice_msg_out_send_internal(out);
> - }
> - if (g_queue_is_empty(c->agent_msg_queue) && c->flushing != NULL) {
> - file_xfer_flushed(channel, TRUE);
> - }
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue()
> -
> - expected arguments, pair of data/data_size to send terminated with NULL:
> - agent_msg_queue_many(main, VD_AGENT_...,
> - &foo, sizeof(Foo),
> - data, data_size, NULL);
> -*/
> -G_GNUC_NULL_TERMINATED
> -static void agent_msg_queue_many(SpiceMainChannel *channel, int type, const
> void *data, ...)
> -{
> - va_list args;
> - SpiceMainChannelPrivate *c = channel->priv;
> - SpiceMsgOut *out;
> - VDAgentMessage msg;
> - guint8 *payload;
> - gsize paysize, s, mins, size = 0;
> - const guint8 *d;
> -
> - G_STATIC_ASSERT(VD_AGENT_MAX_DATA_SIZE > sizeof(VDAgentMessage));
> -
> - va_start(args, data);
> - for (d = data; d != NULL; d = va_arg(args, void*)) {
> - size += va_arg(args, gsize);
> - }
> - va_end(args);
> -
> - msg.protocol = VD_AGENT_PROTOCOL;
> - msg.type = type;
> - msg.opaque = 0;
> - msg.size = size;
> -
> - paysize = MIN(VD_AGENT_MAX_DATA_SIZE, size + sizeof(VDAgentMessage));
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MAIN_AGENT_DATA);
> - payload = spice_marshaller_reserve_space(out->marshaller, paysize);
> - memcpy(payload, &msg, sizeof(VDAgentMessage));
> - payload += sizeof(VDAgentMessage);
> - paysize -= sizeof(VDAgentMessage);
> - if (paysize == 0) {
> - g_queue_push_tail(c->agent_msg_queue, out);
> - out = NULL;
> - }
> -
> - va_start(args, data);
> - for (d = data; size > 0; d = va_arg(args, void*)) {
> - s = va_arg(args, gsize);
> - while (s > 0) {
> - if (out == NULL) {
> - paysize = MIN(VD_AGENT_MAX_DATA_SIZE, size);
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MAIN_AGENT_DATA);
> - payload = spice_marshaller_reserve_space(out->marshaller,
> paysize);
> - }
> - mins = MIN(paysize, s);
> - memcpy(payload, d, mins);
> - d += mins;
> - payload += mins;
> - s -= mins;
> - size -= mins;
> - paysize -= mins;
> - if (paysize == 0) {
> - g_queue_push_tail(c->agent_msg_queue, out);
> - out = NULL;
> - }
> - }
> - }
> - va_end(args);
> - g_warn_if_fail(out == NULL);
> -}
> -
> -static int monitors_cmp(const void *p1, const void *p2, gpointer user_data)
> -{
> - const VDAgentMonConfig *m1 = p1;
> - const VDAgentMonConfig *m2 = p2;
> - double d1 = sqrt(m1->x * m1->x + m1->y * m1->y);
> - double d2 = sqrt(m2->x * m2->x + m2->y * m2->y);
> - int diff = d1 - d2;
> -
> - return diff == 0 ? (char*)p1 - (char*)p2 : diff;
> -}
> -
> -static void monitors_align(VDAgentMonConfig *monitors, int nmonitors)
> -{
> - gint i, j, x = 0;
> - guint32 used = 0;
> - VDAgentMonConfig *sorted_monitors;
> -
> - if (nmonitors == 0)
> - return;
> -
> - /* sort by distance from origin */
> - sorted_monitors = g_memdup(monitors, nmonitors *
> sizeof(VDAgentMonConfig));
> - g_qsort_with_data(sorted_monitors, nmonitors, sizeof(VDAgentMonConfig),
> monitors_cmp, NULL);
> -
> - /* super-KISS ltr alignment, feel free to improve */
> - for (i = 0; i < nmonitors; i++) {
> - /* Find where this monitor is in the sorted order */
> - for (j = 0; j < nmonitors; j++) {
> - /* Avoid using the same entry twice, this happens with older
> - virt-viewer versions which always set x and y to 0 */
> - if (used & (1 << j))
> - continue;
> - if (memcmp(&monitors[j], &sorted_monitors[i],
> - sizeof(VDAgentMonConfig)) == 0)
> - break;
> - }
> - used |= 1 << j;
> - monitors[j].x = x;
> - monitors[j].y = 0;
> - x += monitors[j].width;
> - if (monitors[j].width || monitors[j].height)
> - SPICE_DEBUG("#%d +%d+%d-%dx%d", j, monitors[j].x, monitors[j].y,
> - monitors[j].width, monitors[j].height);
> - }
> - g_free(sorted_monitors);
> -}
> -
> -
> -#define agent_msg_queue(Channel, Type, Size, Data) \
> - agent_msg_queue_many((Channel), (Type), (Data), (Size), NULL)
> -
> -/**
> - * spice_main_send_monitor_config:
> - * @channel:
> - *
> - * Send monitors configuration previously set with
> - * spice_main_set_display() and spice_main_set_display_enabled()
> - *
> - * Returns: %TRUE on success.
> - **/
> -gboolean spice_main_send_monitor_config(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c;
> - VDAgentMonitorsConfig *mon;
> - int i, j, monitors;
> - size_t size;
> -
> - g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
> - c = channel->priv;
> - g_return_val_if_fail(c->agent_connected, FALSE);
> -
> - if (spice_main_agent_test_capability(channel,
> - VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
> - monitors = SPICE_N_ELEMENTS(c->display);
> - } else {
> - monitors = 0;
> - for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
> - if (c->display[i].enabled)
> - monitors += 1;
> - }
> - }
> -
> - size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) *
> monitors;
> - mon = g_malloc0(size);
> -
> - mon->num_of_monitors = monitors;
> - if (c->disable_display_position == FALSE ||
> - c->disable_display_align == FALSE)
> - mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
> -
> - j = 0;
> - for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
> - if (!c->display[i].enabled) {
> - if (spice_main_agent_test_capability(channel,
> - VD_AGENT_CAP_SPARSE_MONITORS_CONFIG))
> - j++;
> - continue;
> - }
> - mon->monitors[j].depth = c->display_color_depth ?
> c->display_color_depth : 32;
> - mon->monitors[j].width = c->display[i].width;
> - mon->monitors[j].height = c->display[i].height;
> - mon->monitors[j].x = c->display[i].x;
> - mon->monitors[j].y = c->display[i].y;
> - CHANNEL_DEBUG(channel, "monitor config: #%d %dx%d+%d+%d @ %d bpp",
> j,
> - mon->monitors[j].width, mon->monitors[j].height,
> - mon->monitors[j].x, mon->monitors[j].y,
> - mon->monitors[j].depth);
> - j++;
> - }
> -
> - if (c->disable_display_align == FALSE)
> - monitors_align(mon->monitors, mon->num_of_monitors);
> -
> - agent_msg_queue(channel, VD_AGENT_MONITORS_CONFIG, size, mon);
> - g_free(mon);
> -
> - spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
> - if (c->timer_id != 0) {
> - g_source_remove(c->timer_id);
> - c->timer_id = 0;
> - }
> -
> - return TRUE;
> -}
> -
> -static void audio_playback_volume_info_cb(GObject *object, GAsyncResult
> *res, gpointer user_data)
> -{
> - SpiceMainChannel *main_channel = user_data;
> - SpiceSession *session =
> spice_channel_get_session(SPICE_CHANNEL(main_channel));
> - SpiceAudio *audio = spice_audio_get(session, NULL);
> - VDAgentAudioVolumeSync *avs;
> - guint16 *volume;
> - guint8 nchannels;
> - gboolean mute, ret;
> - gsize array_size;
> - GError *error = NULL;
> -
> - ret = spice_audio_get_playback_volume_info_finish(audio, res, &mute,
> &nchannels,
> - &volume, &error);
> - if (ret == FALSE || volume == NULL || nchannels == 0) {
> - if (error != NULL) {
> - spice_warning("Failed to get playback async volume info: %s",
> error->message);
> - g_error_free (error);
> - } else {
> - SPICE_DEBUG("Failed to get playback async volume info");
> - }
> - main_channel->priv->agent_volume_playback_sync = FALSE;
> - return;
> - }
> -
> - array_size = sizeof(uint16_t) * nchannels;
> - avs = g_malloc0(sizeof(VDAgentAudioVolumeSync) + array_size);
> - avs->is_playback = TRUE;
> - avs->mute = mute;
> - avs->nchannels = nchannels;
> - memcpy(avs->volume, volume, array_size);
> -
> - SPICE_DEBUG("%s mute=%s nchannels=%u volume[0]=%u",
> - __func__, spice_yes_no(mute), nchannels, volume[0]);
> - g_free(volume);
> - agent_msg_queue(main_channel, VD_AGENT_AUDIO_VOLUME_SYNC,
> - sizeof(VDAgentAudioVolumeSync) + array_size, avs);
> -}
> -
> -static void agent_sync_audio_playback(SpiceMainChannel *main_channel)
> -{
> - SpiceSession *session =
> spice_channel_get_session(SPICE_CHANNEL(main_channel));
> - SpiceAudio *audio = spice_audio_get(session, NULL);
> - SpiceMainChannelPrivate *c = main_channel->priv;
> -
> - if (!test_agent_cap(main_channel, VD_AGENT_CAP_AUDIO_VOLUME_SYNC) ||
> - c->agent_volume_playback_sync == TRUE) {
> - SPICE_DEBUG("%s - is not going to sync audio with guest", __func__);
> - return;
> - }
> - /* only one per connection */
> - g_cancellable_reset(c->cancellable_volume_info);
> - c->agent_volume_playback_sync = TRUE;
> - spice_audio_get_playback_volume_info_async(audio,
> c->cancellable_volume_info, main_channel,
> -
> audio_playback_volume_info_cb,
> main_channel);
> -}
> -
> -static void audio_record_volume_info_cb(GObject *object, GAsyncResult *res,
> gpointer user_data)
> -{
> - SpiceMainChannel *main_channel = user_data;
> - SpiceSession *session =
> spice_channel_get_session(SPICE_CHANNEL(main_channel));
> - SpiceAudio *audio = spice_audio_get(session, NULL);
> - VDAgentAudioVolumeSync *avs;
> - guint16 *volume;
> - guint8 nchannels;
> - gboolean ret, mute;
> - gsize array_size;
> - GError *error = NULL;
> -
> - ret = spice_audio_get_record_volume_info_finish(audio, res, &mute,
> &nchannels, &volume, &error);
> - if (ret == FALSE || volume == NULL || nchannels == 0) {
> - if (error != NULL) {
> - spice_warning ("Failed to get record async volume info: %s",
> error->message);
> - g_error_free (error);
> - } else {
> - SPICE_DEBUG("Failed to get record async volume info");
> - }
> - main_channel->priv->agent_volume_record_sync = FALSE;
> - return;
> - }
> -
> - array_size = sizeof(uint16_t) * nchannels;
> - avs = g_malloc0(sizeof(VDAgentAudioVolumeSync) + array_size);
> - avs->is_playback = FALSE;
> - avs->mute = mute;
> - avs->nchannels = nchannels;
> - memcpy(avs->volume, volume, array_size);
> -
> - SPICE_DEBUG("%s mute=%s nchannels=%u volume[0]=%u",
> - __func__, spice_yes_no(mute), nchannels, volume[0]);
> - g_free(volume);
> - agent_msg_queue(main_channel, VD_AGENT_AUDIO_VOLUME_SYNC,
> - sizeof(VDAgentAudioVolumeSync) + array_size, avs);
> -}
> -
> -static void agent_sync_audio_record(SpiceMainChannel *main_channel)
> -{
> - SpiceSession *session =
> spice_channel_get_session(SPICE_CHANNEL(main_channel));
> - SpiceAudio *audio = spice_audio_get(session, NULL);
> - SpiceMainChannelPrivate *c = main_channel->priv;
> -
> - if (!test_agent_cap(main_channel, VD_AGENT_CAP_AUDIO_VOLUME_SYNC) ||
> - c->agent_volume_record_sync == TRUE) {
> - SPICE_DEBUG("%s - is not going to sync audio with guest", __func__);
> - return;
> - }
> - /* only one per connection */
> - g_cancellable_reset(c->cancellable_volume_info);
> - c->agent_volume_record_sync = TRUE;
> - spice_audio_get_record_volume_info_async(audio,
> c->cancellable_volume_info, main_channel,
> - audio_record_volume_info_cb,
> main_channel);
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue() */
> -static void agent_display_config(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - VDAgentDisplayConfig config = { 0, };
> -
> - if (c->display_disable_wallpaper) {
> - config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_WALLPAPER;
> - }
> -
> - if (c->display_disable_font_smooth) {
> - config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_FONT_SMOOTH;
> - }
> -
> - if (c->display_disable_animation) {
> - config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_ANIMATION;
> - }
> -
> - if (c->display_color_depth != 0) {
> - config.flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_SET_COLOR_DEPTH;
> - config.depth = c->display_color_depth;
> - }
> -
> - CHANNEL_DEBUG(channel, "display_config: flags: %u, depth: %u",
> config.flags, config.depth);
> -
> - agent_msg_queue(channel, VD_AGENT_DISPLAY_CONFIG,
> sizeof(VDAgentDisplayConfig), &config);
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue() */
> -static void agent_announce_caps(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - VDAgentAnnounceCapabilities *caps;
> - size_t size;
> -
> - if (!c->agent_connected)
> - return;
> -
> - size = sizeof(VDAgentAnnounceCapabilities) + VD_AGENT_CAPS_BYTES;
> - caps = g_malloc0(size);
> - if (!c->agent_caps_received)
> - caps->request = 1;
> - VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE);
> - VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG);
> - VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY);
> - VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_DISPLAY_CONFIG);
> - VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
> - VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION);
> -
> - agent_msg_queue(channel, VD_AGENT_ANNOUNCE_CAPABILITIES, size, caps);
> - g_free(caps);
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue() */
> -static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection,
> - guint32 *types, int ntypes)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - guint8 *msg;
> - VDAgentClipboardGrab *grab;
> - size_t size;
> - int i;
> -
> - if (!c->agent_connected)
> - return;
> -
> - g_return_if_fail(test_agent_cap(channel,
> VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
> -
> - size = sizeof(VDAgentClipboardGrab) + sizeof(uint32_t) * ntypes;
> - if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - size += 4;
> - } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
> - CHANNEL_DEBUG(channel, "Ignoring clipboard grab");
> - return;
> - }
> -
> - msg = g_alloca(size);
> - memset(msg, 0, size);
> -
> - grab = (VDAgentClipboardGrab *)msg;
> -
> - if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - msg[0] = selection;
> - grab = (VDAgentClipboardGrab *)(msg + 4);
> - }
> -
> - for (i = 0; i < ntypes; i++) {
> - grab->types[i] = types[i];
> - }
> -
> - agent_msg_queue(channel, VD_AGENT_CLIPBOARD_GRAB, size, msg);
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue() */
> -static void agent_clipboard_notify(SpiceMainChannel *self, guint selection,
> - guint32 type, const guchar *data, size_t
> size)
> -{
> - SpiceMainChannelPrivate *c = self->priv;
> - VDAgentClipboard *cb;
> - guint8 *msg;
> - size_t msgsize;
> - gint max_clipboard = spice_main_get_max_clipboard(self);
> -
> - g_return_if_fail(c->agent_connected);
> - g_return_if_fail(test_agent_cap(self,
> VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
> - g_return_if_fail(max_clipboard == -1 || size < max_clipboard);
> -
> - msgsize = sizeof(VDAgentClipboard);
> - if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - msgsize += 4;
> - } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
> - CHANNEL_DEBUG(self, "Ignoring clipboard notify");
> - return;
> - }
> -
> - msg = g_alloca(msgsize);
> - memset(msg, 0, msgsize);
> -
> - cb = (VDAgentClipboard *)msg;
> -
> - if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - msg[0] = selection;
> - cb = (VDAgentClipboard *)(msg + 4);
> - }
> -
> - cb->type = type;
> - agent_msg_queue_many(self, VD_AGENT_CLIPBOARD, msg, msgsize, data, size,
> NULL);
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue() */
> -static void agent_clipboard_request(SpiceMainChannel *channel, guint
> selection, guint32 type)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - VDAgentClipboardRequest *request;
> - guint8 *msg;
> - size_t msgsize;
> -
> - g_return_if_fail(c->agent_connected);
> - g_return_if_fail(test_agent_cap(channel,
> VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
> -
> - msgsize = sizeof(VDAgentClipboardRequest);
> - if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - msgsize += 4;
> - } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
> - SPICE_DEBUG("Ignoring clipboard request");
> - return;
> - }
> -
> - msg = g_alloca(msgsize);
> - memset(msg, 0, msgsize);
> -
> - request = (VDAgentClipboardRequest *)msg;
> -
> - if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - msg[0] = selection;
> - request = (VDAgentClipboardRequest *)(msg + 4);
> - }
> -
> - request->type = type;
> -
> - agent_msg_queue(channel, VD_AGENT_CLIPBOARD_REQUEST, msgsize, msg);
> -}
> -
> -/* any context: the message is not flushed immediately,
> - you can wakeup() the channel coroutine or send_msg_queue() */
> -static void agent_clipboard_release(SpiceMainChannel *channel, guint
> selection)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - guint8 msg[4] = { 0, };
> - guint8 msgsize = 0;
> -
> - g_return_if_fail(c->agent_connected);
> - g_return_if_fail(test_agent_cap(channel,
> VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
> -
> - if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
> - msg[0] = selection;
> - msgsize += 4;
> - } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
> - SPICE_DEBUG("Ignoring clipboard release");
> - return;
> - }
> -
> - agent_msg_queue(channel, VD_AGENT_CLIPBOARD_RELEASE, msgsize, msg);
> -}
> -
> -/* main context*/
> -static gboolean timer_set_display(gpointer data)
> -{
> - SpiceMainChannel *channel = data;
> - SpiceMainChannelPrivate *c = channel->priv;
> - SpiceSession *session;
> - gint i;
> -
> - c->timer_id = 0;
> - if (!c->agent_connected)
> - return FALSE;
> -
> - session = spice_channel_get_session(SPICE_CHANNEL(channel));
> -
> - /* ensure we have an explicit monitor configuration at least for
> - number of display channels */
> - for (i = 0; i < spice_session_get_n_display_channels(session); i++)
> - if (!c->display[i].enabled_set) {
> - SPICE_DEBUG("Not sending monitors config, missing monitors");
> - return FALSE;
> - }
> -
> - spice_main_send_monitor_config(channel);
> -
> - return FALSE;
> -}
> -
> -/* any context */
> -static void update_display_timer(SpiceMainChannel *channel, guint seconds)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> -
> - if (c->timer_id)
> - g_source_remove(c->timer_id);
> -
> - c->timer_id = g_timeout_add_seconds(seconds, timer_set_display,
> channel);
> -}
> -
> -/* coroutine context */
> -static void set_agent_connected(SpiceMainChannel *channel, gboolean
> connected)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> -
> - SPICE_DEBUG("agent connected: %s", spice_yes_no(connected));
> - if (connected != c->agent_connected) {
> - c->agent_connected = connected;
> - g_coroutine_object_notify(G_OBJECT(channel), "agent-connected");
> - }
> - if (!connected)
> - spice_main_channel_reset_agent(SPICE_MAIN_CHANNEL(channel));
> -
> - g_coroutine_signal_emit(channel, signals[SPICE_MAIN_AGENT_UPDATE], 0);
> -}
> -
> -/* coroutine context */
> -static void agent_start(SpiceMainChannel *channel)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> - SpiceMsgcMainAgentStart agent_start = {
> - .num_tokens = ~0,
> - };
> - SpiceMsgOut *out;
> -
> - c->agent_volume_playback_sync = FALSE;
> - c->agent_volume_record_sync = FALSE;
> - c->agent_caps_received = false;
> - set_agent_connected(channel, TRUE);
> -
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MAIN_AGENT_START);
> - out->marshallers->msgc_main_agent_start(out->marshaller, &agent_start);
> - spice_msg_out_send_internal(out);
> -
> - if (c->agent_connected) {
> - agent_announce_caps(channel);
> - agent_send_msg_queue(channel);
> - }
> -}
> -
> -/* coroutine context */
> -static void agent_stopped(SpiceMainChannel *channel)
> -{
> - set_agent_connected(channel, FALSE);
> -}
> -
> -/* coroutine context */
> -static void set_mouse_mode(SpiceMainChannel *channel, uint32_t supported,
> uint32_t current)
> -{
> - SpiceMainChannelPrivate *c = channel->priv;
> -
> - if (c->mouse_mode != current) {
> - c->mouse_mode = current;
> - g_coroutine_signal_emit(channel, signals[SPICE_MAIN_MOUSE_UPDATE],
> 0);
> - g_coroutine_object_notify(G_OBJECT(channel), "mouse-mode");
> - }
> -
> - /* switch to client mode if possible */
> - if (!spice_channel_get_read_only(SPICE_CHANNEL(channel)) &&
> - supported & SPICE_MOUSE_MODE_CLIENT &&
> - current != SPICE_MOUSE_MODE_CLIENT) {
> - SpiceMsgcMainMouseModeRequest req = {
> - .mode = SPICE_MOUSE_MODE_CLIENT,
> - };
> - SpiceMsgOut *out;
> -
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST);
> - out->marshallers->msgc_main_mouse_mode_request(out->marshaller,
> &req);
> - spice_msg_out_send_internal(out);
> - }
> -}
> -
> -/* coroutine context */
> -static void main_handle_init(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
> - SpiceMsgMainInit *init = spice_msg_in_parsed(in);
> - SpiceSession *session;
> - SpiceMsgOut *out;
> -
> - session = spice_channel_get_session(channel);
> - spice_session_set_connection_id(session, init->session_id);
> -
> - set_mouse_mode(SPICE_MAIN_CHANNEL(channel), init->supported_mouse_modes,
> - init->current_mouse_mode);
> -
> - spice_session_set_mm_time(session, init->multi_media_time);
> - spice_session_set_caches_hints(session, init->ram_hint,
> init->display_channels_hint);
> -
> - c->agent_tokens = init->agent_tokens;
> - if (init->agent_connected)
> - agent_start(SPICE_MAIN_CHANNEL(channel));
> -
> - if (spice_session_migrate_after_main_init(session))
> - return;
> -
> - out = spice_msg_out_new(SPICE_CHANNEL(channel),
> SPICE_MSGC_MAIN_ATTACH_CHANNELS);
> - spice_msg_out_send_internal(out);
> -}
> -
> -/* coroutine context */
> -static void main_handle_name(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgMainName *name = spice_msg_in_parsed(in);
> - SpiceSession *session = spice_channel_get_session(channel);
> -
> - SPICE_DEBUG("server name: %s", name->name);
> - spice_session_set_name(session, (const gchar *)name->name);
> -}
> -
> -/* coroutine context */
> -static void main_handle_uuid(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgMainUuid *uuid = spice_msg_in_parsed(in);
> - SpiceSession *session = spice_channel_get_session(channel);
> - gchar *uuid_str = spice_uuid_to_string(uuid->uuid);
> -
> - SPICE_DEBUG("server uuid: %s", uuid_str);
> - spice_session_set_uuid(session, uuid->uuid);
> -
> - g_free(uuid_str);
> -}
> -
> -/* coroutine context */
> -static void main_handle_mm_time(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceSession *session;
> - SpiceMsgMainMultiMediaTime *msg = spice_msg_in_parsed(in);
> -
> - session = spice_channel_get_session(channel);
> - spice_session_set_mm_time(session, msg->time);
> -}
> -
> -typedef struct channel_new {
> - SpiceSession *session;
> - int type;
> - int id;
> -} channel_new_t;
> -
> -/* main context */
> -static gboolean _channel_new(channel_new_t *c)
> -{
> - g_return_val_if_fail(c != NULL, FALSE);
> -
> - spice_channel_new(c->session, c->type, c->id);
> -
> - g_object_unref(c->session);
> - g_free(c);
> -
> - return FALSE;
> -}
> -
> -/* coroutine context */
> -static void main_handle_channels_list(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgChannels *msg = spice_msg_in_parsed(in);
> - SpiceSession *session;
> - int i;
> -
> - session = spice_channel_get_session(channel);
> -
> - /* guarantee that uuid is notified before setting up the channels, even
> if
> - * the server is older and doesn't actually send the uuid */
> - g_coroutine_object_notify(G_OBJECT(session), "uuid");
> -
> - for (i = 0; i < msg->num_of_channels; i++) {
> - channel_new_t *c;
> -
> - c = g_new(channel_new_t, 1);
> - c->session = g_object_ref(session);
> - c->type = msg->channels[i].type;
> - c->id = msg->channels[i].id;
> - /* no need to explicitely switch to main context, since
> - synchronous call is not needed. */
> - /* no need to track idle, session is refed */
> - g_idle_add((GSourceFunc)_channel_new, c);
> - }
> -}
> -
> -/* coroutine context */
> -static void main_handle_mouse_mode(SpiceChannel *channel, SpiceMsgIn *in)
> -{
> - SpiceMsgMainMouseMode *msg = spice_msg_in_parsed(in);
> - set_mouse_mode(SPICE_MAIN_CHANNEL(channel), msg->supported_modes,
> msg->current_mode);
> -}
> -
> -/* coroutine context */
> -static void main_handle_agent_connected(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - agent_start(SPICE_MAIN_CHANNEL(channel));
> -}
> -
> -/* coroutine context */
> -static void main_handle_agent_connected_tokens(SpiceChannel *channel,
> SpiceMsgIn *in)
> -{
> - SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
> - SpiceMsgMainAgentConnectedTokens *msg = spice_msg_in_parsed(in);
> -
> - c->agent_tokens = msg->num_tokens;
> - agent_start(SPICE_MAIN_CHANNEL(channel));
> -}
> -
> -/* coroutine context */
> -static void main_handle_agent_disconnected(SpiceChannel *channel, SpiceMsgIn
> *in)
> -{
> - agent_stopped(SPICE_MAIN_CHANNEL(channel));
> -}
> -
> -static void file_xfer_task_free(SpiceFileXferTask *task)
> -{
> - SpiceMainChannelPrivate *c;
> -
> - g_return_if_fail(task != NULL);
> -
> - c = task->channel->priv;
> - g_hash_table_remove(c->file_xfer_tasks, GUINT_TO_POINTER(task->id));
> -
> - g_clear_object(&task->channel);
> - g_clear_object(&task->file);
> - g_clear_object(&task->file_stream);
> - g_free(task);
> -}
> -
> -/* main context */
> -static void file_xfer_close_cb(GObject *object,
> -
>
> [Message truncated]
>
>
More information about the Spice-devel
mailing list