summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2010-07-19 09:36:07 +0300
committerYonit Halperin <yhalperi@redhat.com>2010-07-19 09:40:11 +0300
commit9877e7ae8405965463a67171b7408871f949f66f (patch)
tree4733494cfeb3e5e3fe625d9b1e53dd24523875cb
parent7df548358ca44b2c2194b4ee0bfada04475f4e49 (diff)
downloadspice-9877e7ae8405965463a67171b7408871f949f66f.tar.gz
spice-9877e7ae8405965463a67171b7408871f949f66f.tar.xz
spice-9877e7ae8405965463a67171b7408871f949f66f.zip
client: command line arguments for setting windows guest monitors'
color depth and disabling some display options (helpful on WAN)
-rw-r--r--client/application.cpp57
-rw-r--r--client/application.h2
-rw-r--r--client/red_client.cpp80
-rw-r--r--client/red_client.h25
4 files changed, 157 insertions, 7 deletions
diff --git a/client/application.cpp b/client/application.cpp
index af37ae02..14ac7433 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -1896,6 +1896,36 @@ bool Application::set_enable_channels(CmdLineParser& parser, bool enable, char *
return true;
}
+bool Application::set_disabled_display_effects(CmdLineParser& parser, char *val, const char* arg0,
+ DisplaySetting& disp_setting)
+{
+ if (!strcmp(val, "all")) {
+ if ((val = parser.next_argument())) {
+ Platform::term_printf("%s: \"all\" is exclusive\n", arg0);
+ _exit_code = SPICEC_ERROR_CODE_INVALID_ARG;
+ return false;
+ }
+ disp_setting._disable_wallpaper = true;
+ disp_setting._disable_font_smooth = true;
+ disp_setting._disable_animation = true;
+ return true;
+ }
+
+ do {
+ if (!strcmp(val, "wallpaper")) {
+ disp_setting._disable_wallpaper = true;
+ } else if (!strcmp(val, "font-smooth")) {
+ disp_setting._disable_font_smooth = true;
+ } else if (!strcmp(val, "animation")) {
+ disp_setting._disable_animation = true;
+ } else {
+ Platform::term_printf("%s: bad display effect type \"%s\"\n", arg0, val);
+ }
+ } while ((val = parser.next_argument()));
+
+ return true;
+}
+
void Application::on_cmd_line_invalid_arg(const char* arg0, const char* what, const char* val)
{
Platform::term_printf("%s: invalid %s value %s\n", arg0, what, val);
@@ -1939,6 +1969,7 @@ bool Application::process_cmd_line(int argc, char** argv)
bool auto_display_res = false;
bool full_screen = false;
std::string password;
+ DisplaySetting display_setting;
enum {
SPICE_OPT_HOST = CmdLineParser::OPTION_FIRST_AVILABLE,
@@ -1954,6 +1985,8 @@ bool Application::process_cmd_line(int argc, char** argv)
SPICE_OPT_ENABLE_CHANNELS,
SPICE_OPT_DISABLE_CHANNELS,
SPICE_OPT_CANVAS_TYPE,
+ SPICE_OPT_DISPLAY_COLOR_DEPTH,
+ SPICE_OPT_DISABLE_DISPLAY_EFFECTS,
};
#ifdef USE_GUI
@@ -2004,6 +2037,13 @@ bool Application::process_cmd_line(int argc, char** argv)
parser.add(SPICE_OPT_CANVAS_TYPE, "canvas-type", "set rendering canvas", "canvas_type", true);
parser.set_multi(SPICE_OPT_CANVAS_TYPE, ',');
+ parser.add(SPICE_OPT_DISPLAY_COLOR_DEPTH, "color-depth", "guest display color depth",
+ "16/32", true);
+
+ parser.add(SPICE_OPT_DISABLE_DISPLAY_EFFECTS, "disable-effects",
+ "disable guest display effects", "wallpaper/font-smooth/animation/all", true);
+ parser.set_multi(SPICE_OPT_DISABLE_DISPLAY_EFFECTS, ',');
+
for (int i = SPICE_CHANNEL_MAIN; i < SPICE_END_CHANNEL; i++) {
_peer_con_opt[i] = RedPeer::ConnectionOptions::CON_OP_INVALID;
}
@@ -2084,6 +2124,22 @@ bool Application::process_cmd_line(int argc, char** argv)
return false;
}
break;
+ case SPICE_OPT_DISPLAY_COLOR_DEPTH:
+ display_setting._set_color_depth = true;
+ if (!strcmp(val, "16")) {
+ display_setting._color_depth = 16;
+ } else if (!strcmp(val, "32")) {
+ display_setting._color_depth = 32;
+ } else {
+ on_cmd_line_invalid_arg(argv[0], "color depth", val);
+ return false;
+ }
+ break;
+ case SPICE_OPT_DISABLE_DISPLAY_EFFECTS:
+ if (!set_disabled_display_effects(parser, val, argv[0], display_setting)) {
+ return false;
+ }
+ break;
case CmdLineParser::OPTION_HELP:
parser.show_help();
return false;
@@ -2136,6 +2192,7 @@ bool Application::process_cmd_line(int argc, char** argv)
_client.set_target(host, port, sport);
_client.set_password(password);
_client.set_auto_display_res(auto_display_res);
+ _client.set_display_setting(display_setting);
if (full_screen) {
enter_full_screen();
diff --git a/client/application.h b/client/application.h
index 01ef517d..74efed4d 100644
--- a/client/application.h
+++ b/client/application.h
@@ -246,6 +246,8 @@ private:
bool set_host_cert_subject(const char* subject, const char* arg0);
bool set_enable_channels(CmdLineParser& parser, bool enable, char *val, const char* arg0);
bool set_canvas_option(CmdLineParser& parser, char *val, const char* arg0);
+ bool set_disabled_display_effects(CmdLineParser& parser, char *val, const char* arg0,
+ DisplaySetting& disp_setting);
void on_cmd_line_invalid_arg(const char* arg0, const char* what, const char* val);
bool process_cmd_line(int argc, char** argv);
void register_channels();
diff --git a/client/red_client.cpp b/client/red_client.cpp
index c2be58c3..0268e754 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -312,9 +312,11 @@ RedClient::RedClient(Application& application)
, _mouse_mode (SPICE_MOUSE_MODE_SERVER)
, _notify_disconnect (false)
, _auto_display_res (false)
+ , _agent_reply_wait_type (-1)
, _aborting (false)
, _agent_connected (false)
, _agent_mon_config_sent (false)
+ , _agent_disp_config_sent (false)
, _agent_msg (new VDAgentMessage)
, _agent_msg_data (NULL)
, _agent_msg_pos (0)
@@ -395,7 +397,10 @@ void RedClient::on_disconnect()
_migrate.abort();
_connection_id = 0;
_application.deactivate_interval_timer(*_agent_timer);
+ // todo: if migration remains not seemless, we shouldn't
+ // resend monitors and display setting to the agent
_agent_mon_config_sent = false;
+ _agent_disp_config_sent = false;
delete[] _agent_msg_data;
_agent_msg_data = NULL;
_agent_msg_pos = 0;
@@ -625,6 +630,51 @@ void RedClient::send_agent_monitors_config()
_agent_tokens--;
post_message(message);
_agent_mon_config_sent = true;
+ _agent_reply_wait_type = VD_AGENT_MONITORS_CONFIG;
+}
+
+void RedClient::send_agent_display_config()
+{
+ Message* message = new Message(SPICE_MSGC_MAIN_AGENT_DATA);
+ VDAgentMessage* msg = (VDAgentMessage*)
+ spice_marshaller_reserve_space(message->marshaller(), sizeof(VDAgentMessage));
+ VDAgentDisplayConfig* disp_config;
+
+ DBG(0,"");
+ msg->protocol = VD_AGENT_PROTOCOL;
+ msg->type = VD_AGENT_DISPLAY_CONFIG;
+ msg->opaque = 0;
+ msg->size = sizeof(VDAgentDisplayConfig);
+
+ 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;
+ }
+
+ if (_display_setting._disable_font_smooth) {
+ disp_config->flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_FONT_SMOOTH;
+ }
+
+ if (_display_setting._disable_animation) {
+ disp_config->flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_DISABLE_ANIMATION;
+ }
+
+ if (_display_setting._set_color_depth) {
+ disp_config->flags |= VD_AGENT_DISPLAY_CONFIG_FLAG_SET_COLOR_DEPTH;
+ disp_config->depth = _display_setting._color_depth;
+ }
+
+ ASSERT(_agent_tokens)
+ _agent_tokens--;
+ post_message(message);
+ _agent_disp_config_sent = true;
+
+ if (!_display_setting.is_empty()) {
+ _agent_reply_wait_type = VD_AGENT_DISPLAY_CONFIG;
+ }
}
#define MIN_DISPLAY_PIXMAP_CACHE (1024 * 1024 * 20)
@@ -729,13 +779,20 @@ void RedClient::handle_init(RedPeer::InMessage* message)
_marshallers->msgc_main_agent_start(msg->marshaller(), &agent_start);
post_message(msg);
}
- if (_auto_display_res) {
- _application.activate_interval_timer(*_agent_timer, AGENT_TIMEOUT);
- if (_agent_connected) {
- send_agent_monitors_config();
+
+ if (_agent_connected) {
+ if (_auto_display_res) {
+ send_agent_monitors_config();
}
- } else {
+ // 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()) {
post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS));
+ } else {
+ _application.activate_interval_timer(*_agent_timer, AGENT_TIMEOUT);
}
}
@@ -772,6 +829,10 @@ void RedClient::handle_agent_connected(RedPeer::InMessage* message)
if (_auto_display_res && !_agent_mon_config_sent) {
send_agent_monitors_config();
}
+
+ if (!_agent_disp_config_sent) {
+ send_agent_display_config();
+ }
}
void RedClient::handle_agent_disconnected(RedPeer::InMessage* message)
@@ -782,6 +843,7 @@ void RedClient::handle_agent_disconnected(RedPeer::InMessage* message)
void RedClient::on_agent_reply(VDAgentReply* reply)
{
+ DBG(0, "agent reply type: %d", reply->type);
switch (reply->error) {
case VD_AGENT_SUCCESS:
break;
@@ -792,8 +854,12 @@ void RedClient::on_agent_reply(VDAgentReply* reply)
}
switch (reply->type) {
case VD_AGENT_MONITORS_CONFIG:
- post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS));
- _application.deactivate_interval_timer(*_agent_timer);
+ case VD_AGENT_DISPLAY_CONFIG:
+ if (_agent_reply_wait_type == reply->type) {
+ post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS));
+ _application.deactivate_interval_timer(*_agent_timer);
+ _agent_reply_wait_type = -1;
+ }
break;
default:
THROW("unexpected vdagent reply type");
diff --git a/client/red_client.h b/client/red_client.h
index 52a3456b..9603bfe7 100644
--- a/client/red_client.h
+++ b/client/red_client.h
@@ -125,6 +125,25 @@ public:
virtual bool operator() (RedChannel& channel) = 0;
};
+class DisplaySetting {
+public:
+ DisplaySetting() : _disable_wallpaper (false)
+ , _disable_font_smooth (false)
+ , _disable_animation (false)
+ , _set_color_depth (false)
+ {}
+
+ bool is_empty() {return !(_disable_wallpaper || _disable_font_smooth ||
+ _disable_animation || _set_color_depth);}
+
+public:
+ bool _disable_wallpaper;
+ bool _disable_font_smooth;
+ bool _disable_animation;
+ bool _set_color_depth;
+ uint32_t _color_depth;
+};
+
class RedClient: public RedChannel {
public:
friend class RedChannel;
@@ -148,6 +167,7 @@ public:
void set_target(const std::string&, int port, int sport);
void set_password(const std::string& password) { _password = password;}
void set_auto_display_res(bool auto_display_res) { _auto_display_res = auto_display_res;}
+ void set_display_setting(DisplaySetting& setting) { _display_setting = setting;}
const std::string& get_password() { return _password;}
const std::string& get_host() { return _host;}
int get_port() { return _port;}
@@ -184,6 +204,7 @@ private:
void on_channel_disconnected(RedChannel& channel);
void migrate_channel(RedChannel& channel);
void send_agent_monitors_config();
+ void send_agent_display_config();
void calc_pixmap_cach_and_glz_window_size(uint32_t display_channels_hint,
uint32_t pci_mem_hint);
void set_mouse_mode(uint32_t supported_modes, uint32_t current_mode);
@@ -221,10 +242,14 @@ private:
Mutex _notify_lock;
bool _notify_disconnect;
bool _auto_display_res;
+ DisplaySetting _display_setting;
+ int _agent_reply_wait_type;
+
bool _aborting;
bool _agent_connected;
bool _agent_mon_config_sent;
+ bool _agent_disp_config_sent;
VDAgentMessage* _agent_msg;
uint8_t* _agent_msg_data;
uint32_t _agent_msg_pos;