[Spice-devel] [PATCH v2 2/3] client: add announce_capabilities

Alon Levy alevy at redhat.com
Mon Aug 30 04:52:59 PDT 2010


diff --git a/client/red_client.cpp b/client/red_client.cpp
index b6a412e..0b0e7ab 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -328,6 +328,8 @@ RedClient::RedClient(Application& application)
     , _agent_out_msg_pos (0)
     , _agent_tokens (0)
     , _agent_timer (new AgentTimer())
+    , _agent_caps_size(0)
+    , _agent_caps(NULL)
     , _migrate (*this)
     , _glz_window (0, _glz_debug)
 {
@@ -639,6 +641,36 @@ void RedClient::send_agent_monitors_config()
     _agent_reply_wait_type = VD_AGENT_MONITORS_CONFIG;
 }
 
+void RedClient::send_agent_announce_capabilities(bool request)
+{
+    Message* message = new Message(SPICE_MSGC_MAIN_AGENT_DATA);
+    VDAgentMessage* msg = (VDAgentMessage*)
+        spice_marshaller_reserve_space(message->marshaller(),
+                                       sizeof(VDAgentMessage));
+    VDAgentAnnounceCapabilities* caps;
+
+    msg->protocol = VD_AGENT_PROTOCOL;
+    msg->type = VD_AGENT_ANNOUNCE_CAPABILITIES;
+    msg->opaque = 0;
+    msg->size = sizeof(VDAgentAnnounceCapabilities) + VD_AGENT_CAPS_BYTES;
+
+    caps = (VDAgentAnnounceCapabilities*)
+        spice_marshaller_reserve_space(message->marshaller(), msg->size);
+
+    caps->request = request;
+    caps->caps_size = VD_AGENT_CAPS_SIZE;
+    memset(caps->caps, 0, VD_AGENT_CAPS_BYTES);
+    VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_MOUSE_STATE);
+    VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_MONITORS_CONFIG);
+    VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_REPLY);
+    VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CLIPBOARD);
+    VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_DISPLAY_CONFIG);
+    VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_ANNOUNCE_CAPABILITIES);
+    ASSERT(_agent_tokens)
+    _agent_tokens--;
+    post_message(message);
+}
+
 void RedClient::send_agent_display_config()
 {
     Message* message = new Message(SPICE_MSGC_MAIN_AGENT_DATA);
@@ -654,7 +686,7 @@ void RedClient::send_agent_display_config()
 
     disp_config = (VDAgentDisplayConfig*)
         spice_marshaller_reserve_space(message->marshaller(), sizeof(VDAgentDisplayConfig));
-    
+
     disp_config->flags = 0;
     if (_display_setting._disable_wallpaper) {
         disp_config->flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_WALLPAPER;
@@ -872,12 +904,10 @@ void RedClient::handle_init(RedPeer::InMessage* message)
     }
 
     if (_agent_connected) {
+        send_agent_announce_capabilities(true);
         if (_auto_display_res) {
            send_agent_monitors_config();
         }
-        // not sending the color depth through send_agent_monitors_config, since
-        // it applies only for attached screens.
-        send_agent_display_config();
     }
 
     if (!_auto_display_res && _display_setting.is_empty()) {
@@ -917,6 +947,8 @@ void RedClient::handle_agent_connected(RedPeer::InMessage* message)
     agent_start.num_tokens = ~0;
     _marshallers->msgc_main_agent_start(msg->marshaller(), &agent_start);
     post_message(msg);
+    send_agent_announce_capabilities(false);
+
     if (_auto_display_res && !_agent_mon_config_sent) {
         send_agent_monitors_config();
     }
@@ -932,6 +964,31 @@ void RedClient::handle_agent_disconnected(RedPeer::InMessage* message)
     _agent_connected = false;
 }
 
+void RedClient::on_agent_announce_capabilities(
+    VDAgentAnnounceCapabilities* caps)
+{
+    if (_agent_caps_size != caps->caps_size) {
+        if (_agent_caps != NULL) {
+            delete[] _agent_caps;
+            _agent_caps = NULL;
+        }
+        _agent_caps = new uint32_t[caps->caps_size];
+        ASSERT(_agent_caps != NULL);
+        _agent_caps_size = caps->caps_size;
+    }
+    memcpy(_agent_caps, caps->caps, sizeof(_agent_caps[0]) * caps->caps_size);
+
+    if (VD_AGENT_HAS_CAPABILITY(caps->caps, caps->caps_size,
+        VD_AGENT_DISPLAY_CONFIG)) {
+        // not sending the color depth through send_agent_monitors_config, since
+        // it applies only for attached screens.
+        send_agent_display_config();
+    }
+    if (caps->request) {
+        send_agent_announce_capabilities(false);
+    }
+}
+
 void RedClient::on_agent_reply(VDAgentReply* reply)
 {
     DBG(0, "agent reply type: %d", reply->type);
@@ -990,6 +1047,11 @@ void RedClient::handle_agent_data(RedPeer::InMessage* message)
         if (_agent_msg_pos == sizeof(VDAgentMessage) + _agent_msg->size) {
             DBG(0, "agent msg end");
             switch (_agent_msg->type) {
+            case VD_AGENT_ANNOUNCE_CAPABILITIES: {
+                on_agent_announce_capabilities(
+                    (VDAgentAnnounceCapabilities*)_agent_msg_data);
+                break;
+            }
             case VD_AGENT_REPLY: {
                 on_agent_reply((VDAgentReply*)_agent_msg_data);
                 break;
diff --git a/client/red_client.h b/client/red_client.h
index 6b4d4ab..a1b5bc1 100644
--- a/client/red_client.h
+++ b/client/red_client.h
@@ -210,6 +210,7 @@ protected:
 private:
     void on_channel_disconnected(RedChannel& channel);
     void migrate_channel(RedChannel& channel);
+    void send_agent_announce_capabilities(bool request);
     void send_agent_monitors_config();
     void send_agent_display_config();
     void calc_pixmap_cach_and_glz_window_size(uint32_t display_channels_hint,
@@ -229,6 +230,7 @@ private:
     void handle_migrate_switch_host(RedPeer::InMessage* message);
 
     void on_agent_reply(VDAgentReply* reply);
+    void on_agent_announce_capabilities(VDAgentAnnounceCapabilities* caps);
     void on_agent_clipboard(VDAgentClipboard* clipboard, uint32_t size);
     void send_agent_clipboard();
     void do_send_agent_clipboard();
@@ -269,6 +271,8 @@ private:
     uint32_t _agent_out_msg_pos;
     uint32_t _agent_tokens;
     AutoRef<AgentTimer> _agent_timer;
+    uint32_t _agent_caps_size;
+    uint32_t *_agent_caps;
 
     PeerConnectionOptMap _con_opt_map;
     RedPeer::HostAuthOptions _host_auth_opt;


More information about the Spice-devel mailing list