----- Original Message ----- > From: "Marc-André Lureau" <marcandre.lureau@xxxxxxxxxx> > To: spice-devel@xxxxxxxxxxxxxxxxxxxxx > Sent: Friday, June 5, 2015 6:29:43 PM > Subject: [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@Type@Value _@enum_name@_values[] = {" \ > - --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ > - --vtail " { 0, NULL, NULL }\n};\n\n" \ > - --vtail "GType\n@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_@type@_register_static (\"@EnumName@\", > _@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_@ENUMSHORT@ @enum_name@_get_type()\n" \ > - --eprod "GType @enum_name@_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@Type@Value _@enum_name@_values[] = {" \ > - --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ > - --vtail " { 0, NULL, NULL }\n};\n\n" \ > - --vtail "GType\n@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_@type@_register_static (\"@EnumName@\", > _@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_@ENUMSHORT@ @enum_name@_get_type()\n" \ > - --eprod "GType @enum_name@_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] > > _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel