summaryrefslogtreecommitdiffstats
path: root/client/application.cpp
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2010-03-16 10:42:07 +0200
committerUri Lublin <uril@redhat.com>2010-03-24 18:35:05 +0200
commit45a786b85429ddc0a0aa9203fb3ffc3c4c4c73aa (patch)
tree59cac115aa3208681c34b4c9b97aed9e5a2efbe3 /client/application.cpp
parent52ecb3bc93f6a13c428138dc0fdd85eee019f775 (diff)
downloadspice-45a786b85429ddc0a0aa9203fb3ffc3c4c4c73aa.tar.gz
spice-45a786b85429ddc0a0aa9203fb3ffc3c4c4c73aa.tar.xz
spice-45a786b85429ddc0a0aa9203fb3ffc3c4c4c73aa.zip
spice: client: add controller #558247
Spice client controller enables external control (e.g., by XPI or ActiveX) of the client functionality. The controller protocol enables setting parameters (host, port, sport, pwd, secure channels, disabled channels, title, menus, hotkeys etc.), connecting the server, showing and hiding the client etc. The controller is rewritten from scratch, based on the cross-platform named pipe
Diffstat (limited to 'client/application.cpp')
-rw-r--r--client/application.cpp152
1 files changed, 129 insertions, 23 deletions
diff --git a/client/application.cpp b/client/application.cpp
index c7f19006..52b0be63 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -290,15 +290,16 @@ enum AppCommands {
APP_CMD_INVALID,
APP_CMD_SEND_CTL_ALT_DEL,
APP_CMD_TOGGLE_FULL_SCREEN,
- APP_CMD_RELEASE_CAPTURE,
APP_CMD_SEND_TOGGLE_KEYS,
APP_CMD_SEND_RELEASE_KEYS,
APP_CMD_SEND_CTL_ALT_END,
+ APP_CMD_RELEASE_CAPTURE,
#ifdef RED_DEBUG
APP_CMD_CONNECT,
APP_CMD_DISCONNECT,
#endif
APP_CMD_FOREIGN_MENU_MASK = 0x01000000,
+ APP_CMD_CONTROLLER_MENU_MASK = 0x02000000,
};
#define MENU_ID_MASK 0x000000ff
@@ -323,6 +324,7 @@ Application::Application()
, _splash_mode (true)
, _sys_key_intercept_mode (false)
, _during_host_switch(false)
+ , _enable_controller (false)
{
DBG(0, "");
Platform::set_process_loop(*this);
@@ -462,6 +464,10 @@ int Application::run()
void Application::on_start_running()
{
_foreign_menu.reset(new ForeignMenu(this));
+ if (_enable_controller) {
+ _controller.reset(new Controller(this));
+ return;
+ }
_client.connect();
}
@@ -819,6 +825,9 @@ void Application::do_command(int command)
if ((command & APP_CMD_FOREIGN_MENU_MASK) == APP_CMD_FOREIGN_MENU_MASK) {
ASSERT(*_foreign_menu);
(*_foreign_menu)->on_command(conn_ref, command & MENU_ID_MASK);
+ } else if ((command & APP_CMD_CONTROLLER_MENU_MASK) == APP_CMD_CONTROLLER_MENU_MASK) {
+ ASSERT(*_controller);
+ (*_controller)->on_command(conn_ref, command & MENU_ID_MASK);
}
}
}
@@ -852,6 +861,75 @@ void Application::update_menu()
}
}
+void Application::add_controller(int32_t opaque_conn_ref)
+{
+ _pipe_connections[opaque_conn_ref & MENU_CONN_MASK] = opaque_conn_ref;
+}
+
+void Application::delete_controller(int32_t opaque_conn_ref)
+{
+ _pipe_connections.erase(opaque_conn_ref & MENU_CONN_MASK);
+ delete_menu();
+}
+
+bool Application::connect(const std::string& host, int port, int sport, const std::string& password)
+{
+ _client.set_target(host, port, sport);
+ _client.set_password(password);
+ if (!set_channels_security(port, sport)) {
+ return false;
+ }
+ register_channels();
+ connect();
+ return true;
+}
+
+void Application::show_me(bool full_screen, bool auto_display_res)
+{
+ if (auto_display_res) {
+ Monitor* mon = find_monitor(0);
+ ASSERT(mon);
+ Point size = mon->get_size();
+ _main_screen->set_mode(size.x, size.y, 32);
+ }
+ if (full_screen) {
+ enter_full_screen();
+ } else {
+ _main_screen->show(true, NULL);
+ }
+}
+void Application::hide_me()
+{
+ if (_full_screen) {
+ exit_full_screen();
+ }
+ hide();
+}
+
+void Application::set_hotkeys(const std::string& hotkeys)
+{
+ std::auto_ptr<HotKeysParser> parser(new HotKeysParser(hotkeys, _commands_map));
+ _hot_keys = parser->get();
+}
+
+int Application::get_controller_menu_item_id(int32_t opaque_conn_ref, uint32_t msg_id)
+{
+ return APP_CMD_CONTROLLER_MENU_MASK | ((opaque_conn_ref & MENU_CONN_MASK) << MENU_CONN_SHIFT) |
+ (msg_id & MENU_ID_MASK);
+}
+
+void Application::set_menu(Menu* menu)
+{
+ _app_menu.reset(menu->ref());
+ update_menu();
+}
+
+void Application::delete_menu()
+{
+ init_menu();
+ update_menu();
+}
+
#ifdef REDKEY_DEBUG
static void show_red_key(RedKey key)
@@ -1454,7 +1532,7 @@ uint32_t Application::get_mouse_mode()
return _client.get_mouse_mode();
}
-void Application::set_title(std::wstring& title)
+void Application::set_title(const std::wstring& title)
{
_title = title;
@@ -1737,7 +1815,7 @@ void Application::on_cmd_line_invalid_arg(const char* arg0, const char* what, co
bool Application::process_cmd_line(int argc, char** argv)
{
- std::string host;
+ std::string host = "";
int sport = -1;
int port = -1;
bool auto_display_res = false;
@@ -1758,12 +1836,12 @@ bool Application::process_cmd_line(int argc, char** argv)
SPICE_OPT_ENABLE_CHANNELS,
SPICE_OPT_DISABLE_CHANNELS,
SPICE_OPT_CANVAS_TYPE,
+ SPICE_OPT_CONTROLLER,
};
CmdLineParser parser("Spice client", false);
parser.add(SPICE_OPT_HOST, "host", "spice server address", "host", true, 'h');
- parser.set_reqired(SPICE_OPT_HOST);
parser.add(SPICE_OPT_PORT, "port", "spice server port", "port", true, 'p');
parser.add(SPICE_OPT_SPORT, "secure-port", "spice server secure port", "port", true, 's');
parser.add(SPICE_OPT_SECURE_CHANNELS, "secure-channels",
@@ -1795,6 +1873,8 @@ 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_CONTROLLER, "controller", "enable external controller");
+
_peer_con_opt[RED_CHANNEL_MAIN] = RedPeer::ConnectionOptions::CON_OP_INVALID;
_peer_con_opt[RED_CHANNEL_DISPLAY] = RedPeer::ConnectionOptions::CON_OP_INVALID;
_peer_con_opt[RED_CHANNEL_INPUTS] = RedPeer::ConnectionOptions::CON_OP_INVALID;
@@ -1878,6 +1958,14 @@ bool Application::process_cmd_line(int argc, char** argv)
return false;
}
break;
+ case SPICE_OPT_CONTROLLER:
+ if (argc > 2) {
+ std::cout << "controller cannot be combined with other options\n";
+ _exit_code = SPICEC_ERROR_CODE_INVALID_ARG;
+ return false;
+ }
+ _enable_controller = true;
+ return true;
case CmdLineParser::OPTION_HELP:
parser.show_help();
return false;
@@ -1889,13 +1977,43 @@ bool Application::process_cmd_line(int argc, char** argv)
}
}
+ if (host.empty()) {
+ std::cout << "missing --host\n";
+ return false;
+ }
+
if (parser.is_set(SPICE_OPT_SECURE_CHANNELS) && !parser.is_set(SPICE_OPT_SPORT)) {
Platform::term_printf("%s: missing --secure-port\n", argv[0]);
_exit_code = SPICEC_ERROR_CODE_CMD_LINE_ERROR;
return false;
}
+ if (!set_channels_security(port, sport)) {
+ Platform::term_printf("%s: missing --port or --sport\n", argv[0]);
+ return false;
+ }
+ register_channels();
+
+ _client.init(host.c_str(), port, sport, password.c_str(), auto_display_res);
+ if (auto_display_res) {
+ Monitor* mon = find_monitor(0);
+ ASSERT(mon);
+ Point size = mon->get_size();
+ _main_screen->set_mode(size.x, size.y, 32);
+ }
+
+ if (full_screen) {
+ enter_full_screen();
+ } else {
+ _main_screen->show(true, NULL);
+ }
+ return true;
+}
+
+bool Application::set_channels_security(int port, int sport)
+{
PeerConnectionOptMap::iterator iter = _peer_con_opt.begin();
+
for (; iter != _peer_con_opt.end(); iter++) {
if ((*iter).second == RedPeer::ConnectionOptions::CON_OP_SECURE) {
continue;
@@ -1905,26 +2023,29 @@ bool Application::process_cmd_line(int argc, char** argv)
continue;
}
- if (parser.is_set(SPICE_OPT_PORT) && parser.is_set(SPICE_OPT_SPORT)) {
+ if (port != -1 && sport != -1) {
(*iter).second = RedPeer::ConnectionOptions::CON_OP_BOTH;
continue;
}
- if (parser.is_set(SPICE_OPT_PORT)) {
+ if (port != -1) {
(*iter).second = RedPeer::ConnectionOptions::CON_OP_UNSECURE;
continue;
}
- if (parser.is_set(SPICE_OPT_SPORT)) {
+ if (sport != -1) {
(*iter).second = RedPeer::ConnectionOptions::CON_OP_SECURE;
continue;
}
- Platform::term_printf("%s: missing --port or --sport\n", argv[0]);
_exit_code = SPICEC_ERROR_CODE_CMD_LINE_ERROR;
return false;
}
+ return true;
+}
+void Application::register_channels()
+{
if (_enabled_channels[RED_CHANNEL_DISPLAY]) {
_client.register_channel_factory(DisplayChannel::Factory());
}
@@ -1944,21 +2065,6 @@ bool Application::process_cmd_line(int argc, char** argv)
if (_enabled_channels[RED_CHANNEL_RECORD]) {
_client.register_channel_factory(RecordChannel::Factory());
}
-
- _client.init(host.c_str(), port, sport, password.c_str(), auto_display_res);
- if (auto_display_res) {
- Monitor* mon = find_monitor(0);
- ASSERT(mon);
- Point size = mon->get_size();
- _main_screen->set_mode(size.x, size.y, 32);
- }
-
- if (full_screen) {
- enter_full_screen();
- } else {
- _main_screen->show(true, NULL);
- }
- return true;
}
void Application::init_logger()