diff options
-rw-r--r-- | client/Makefile.am | 2 | ||||
-rw-r--r-- | client/application.cpp | 74 | ||||
-rw-r--r-- | client/application.h | 26 | ||||
-rw-r--r-- | client/foreign_menu.cpp | 364 | ||||
-rw-r--r-- | client/foreign_menu.h | 98 | ||||
-rw-r--r-- | client/windows/redc.vcproj | 18 | ||||
-rw-r--r-- | client/x11/Makefile.am | 2 |
7 files changed, 574 insertions, 10 deletions
diff --git a/client/Makefile.am b/client/Makefile.am index 185518a9..09f11d5f 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -61,6 +61,8 @@ RED_COMMON_SRCS = \ debug.h \ display_channel.cpp \ display_channel.h \ + foreign_menu.cpp \ + foreign_menu.h \ glz_decoded_image.h \ glz_decoder_config.h \ glz_decoder.cpp \ diff --git a/client/application.cpp b/client/application.cpp index c5d34ff0..9a9a3f68 100644 --- a/client/application.cpp +++ b/client/application.cpp @@ -335,6 +335,8 @@ enum AppCommands { #ifdef USE_GUI APP_CMD_SHOW_GUI, #endif // USE_GUI + APP_CMD_EXTERNAL_BEGIN = 0x400, + APP_CMD_EXTERNAL_END = 0x800, }; Application::Application() @@ -586,6 +588,13 @@ void Application::switch_host(const std::string& host, int port, int sport, int Application::run() { + _exit_code = ProcessLoop::run(); + return _exit_code; +} + +void Application::on_start_running() +{ + _foreign_menu.reset(new ForeignMenu(this)); #ifdef USE_GUI if (_gui_mode != GUI_MODE_FULL) { connect(); @@ -595,8 +604,6 @@ int Application::run() #else connect(); #endif // HAVE_GUI - _exit_code = ProcessLoop::run(); - return _exit_code; } RedScreen* Application::find_screen(int id) @@ -974,6 +981,14 @@ void Application::do_command(int command) show_gui(); break; #endif // USE_GUI + default: + AppMenuItemMap::iterator iter = _app_menu_items.find(command); + ASSERT(iter != _app_menu_items.end()); + AppMenuItem* item = &(*iter).second; + if (item->type == APP_MENU_ITEM_TYPE_FOREIGN) { + ASSERT(*_foreign_menu); + (*_foreign_menu)->on_command(item->conn_ref, item->ext_id); + } } } @@ -1318,12 +1333,18 @@ void Application::on_app_activated() { _active = true; _key_handler->on_focus_in(); + if (*_foreign_menu) { + (*_foreign_menu)->on_activate(); + } } void Application::on_app_deactivated() { _active = false; _key_handler->on_focus_out(); + if (*_foreign_menu) { + (*_foreign_menu)->on_deactivate(); + } #ifdef WIN32 if (!_changing_screens) { exit_full_screen(); @@ -1573,7 +1594,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; @@ -1665,6 +1686,53 @@ void Application::send_hotkey_key_set(const HotkeySet& key_set) } } +int Application::get_menu_item_id(AppMenuItemType type, int32_t conn_ref, uint32_t ext_id) +{ + int free_id = APP_CMD_EXTERNAL_BEGIN; + AppMenuItem item = {type, conn_ref, ext_id}; + AppMenuItemMap::iterator iter = _app_menu_items.begin(); + for (; iter != _app_menu_items.end(); iter++) { + if (!memcmp(&(*iter).second, &item, sizeof(item))) { + return (*iter).first; + } else if (free_id == (*iter).first && ++free_id > APP_CMD_EXTERNAL_END) { + return APP_CMD_INVALID; + } + } + _app_menu_items[free_id] = item; + return free_id; +} + +void Application::clear_menu_items(int32_t opaque_conn_ref) +{ + AppMenuItemMap::iterator iter = _app_menu_items.begin(); + AppMenuItemMap::iterator curr; + + while (iter != _app_menu_items.end()) { + curr = iter++; + if (((*curr).second).conn_ref == opaque_conn_ref) { + _app_menu_items.erase(curr); + } + } +} + +void Application::remove_menu_item(int item_id) +{ + _app_menu_items.erase(item_id); +} + +int Application::get_foreign_menu_item_id(int32_t opaque_conn_ref, uint32_t msg_id) +{ + return get_menu_item_id(APP_MENU_ITEM_TYPE_FOREIGN, opaque_conn_ref, msg_id); +} + +void Application::update_menu() +{ + for (size_t i = 0; i < _screens.size(); ++i) { + if (_screens[i]) { + _screens[i]->update_menu(); + } + } +} //controller interface begin diff --git a/client/application.h b/client/application.h index 36ae86e8..d6355ca6 100644 --- a/client/application.h +++ b/client/application.h @@ -26,6 +26,7 @@ #include "menu.h" #include "hot_keys.h" #include "process_loop.h" +#include "foreign_menu.h" class RedScreen; class Application; @@ -138,10 +139,23 @@ typedef std::list<KeyHandler*> KeyHandlersStack; typedef std::list<GUIBarrier*> GUIBarriers; #endif // USE_GUI +enum AppMenuItemType { + APP_MENU_ITEM_TYPE_INVALID, + APP_MENU_ITEM_TYPE_FOREIGN, +}; + +typedef struct AppMenuItem { + AppMenuItemType type; + int32_t conn_ref; + uint32_t ext_id; +} AppMenuItem; + +typedef std::map<int, AppMenuItem> AppMenuItemMap; + class Application : public ProcessLoop, public Platform::EventListener, public Platform::DisplayModeListener, - public CommandTarget { + public ForeignMenuInterface { public: enum State { @@ -186,6 +200,7 @@ public: void on_activate_screen(RedScreen* screen); void on_start_screen_key_interception(RedScreen* screen); void on_stop_screen_key_interception(RedScreen* screen); + virtual void on_start_running(); virtual void on_app_activated(); virtual void on_app_deactivated(); virtual void on_monitors_change(); @@ -200,7 +215,7 @@ public: void exit_full_screen(); bool toggle_full_screen(); void minimize(); - void set_title(std::wstring& title); + void set_title(const std::wstring& title); void hide(); void show(); void external_show(); @@ -216,6 +231,10 @@ public: Menu* get_app_menu(); virtual void do_command(int command); + int get_foreign_menu_item_id(int32_t opaque_conn_ref, uint32_t msg_id); + void clear_menu_items(int32_t opaque_conn_ref); + void remove_menu_item(int item_id); + void update_menu(); //controller interface begin bool connect(const std::string& host, int port, int sport, const std::string& password); @@ -276,6 +295,7 @@ private: void send_command_hotkey(int command); void send_hotkey_key_set(const HotkeySet& key_set); void menu_item_callback(unsigned int item_id); + int get_menu_item_id(AppMenuItemType type, int32_t conn_ref, uint32_t ext_id); int get_hotkeys_commnad(); bool is_key_set_pressed(const HotkeySet& key_set); void do_on_key_up(RedKey key); @@ -341,6 +361,8 @@ private: StickyInfo _sticky_info; std::vector<int> _canvas_types; AutoRef<Menu> _app_menu; + AutoRef<ForeignMenu> _foreign_menu; + AppMenuItemMap _app_menu_items; #ifdef USE_GUI std::auto_ptr<GUI> _gui; AutoRef<GUITimer> _gui_timer; diff --git a/client/foreign_menu.cpp b/client/foreign_menu.cpp new file mode 100644 index 00000000..e5d7459d --- /dev/null +++ b/client/foreign_menu.cpp @@ -0,0 +1,364 @@ +/* + Copyright (C) 2009 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 "common.h" +#include "foreign_menu.h" +#include <spice/foreign_menu_prot.h> +#include "menu.h" +#include "utils.h" +#include "debug.h" +#include "platform.h" + +#define PIPE_NAME_MAX_LEN 50 + +#ifdef WIN32 +#define PIPE_NAME "SpiceForeignMenu-%lu" +#elif defined(__i386__) +#define PIPE_NAME "/tmp/SpiceForeignMenu-%llu.uds" +#else +#define PIPE_NAME "/tmp/SpiceForeignMenu-%lu.uds" +#endif + +ForeignMenu::ForeignMenu(ForeignMenuInterface *handler) + : _handler (handler) + , _active (false) + , _refs (1) +{ + char pipe_name[PIPE_NAME_MAX_LEN]; + + ASSERT(_handler != NULL); + snprintf(pipe_name, PIPE_NAME_MAX_LEN, PIPE_NAME, Platform::get_process_id()); + LOG_INFO("Creating a foreign menu connection %s", pipe_name); + _foreign_menu = NamedPipe::create(pipe_name, *this); + if (!_foreign_menu) { + LOG_ERROR("Failed to create a foreign menu connection"); + } +} + +ForeignMenu::~ForeignMenu() +{ + std::map<NamedPipe::ConnectionRef, ForeignMenuConnection*>::const_iterator conn; + for (conn = _connections.begin(); conn != _connections.end(); ++conn) { + conn->second->reset_handler(); + delete conn->second; + } + if (_foreign_menu) { + NamedPipe::destroy(_foreign_menu); + } +} + +NamedPipe::ConnectionInterface& ForeignMenu::create() +{ + ForeignMenuConnection *conn = new ForeignMenuConnection(_handler, *this); + + if (conn == NULL) { + throw Exception("Error allocating a new foreign menu connection"); + } + return *conn; +} + +void ForeignMenu::add_connection(NamedPipe::ConnectionRef conn_ref, ForeignMenuConnection *conn) +{ + _connections[conn_ref] = conn; + if (_active) { + send_active_state(conn, FOREIGN_MENU_APP_ACTIVATED); + } + conn->on_data(); +} + +void ForeignMenu::remove_connection(NamedPipe::ConnectionRef conn_ref) +{ + ForeignMenuConnection *conn = _connections[conn_ref]; + _connections.erase(conn_ref); + delete conn; +} + +void ForeignMenu::add_sub_menus() +{ + std::map<NamedPipe::ConnectionRef, ForeignMenuConnection*>::const_iterator conn; + for (conn = _connections.begin(); conn != _connections.end(); ++conn) { + conn->second->add_sub_menu(); + } +} + +void ForeignMenu::on_command(NamedPipe::ConnectionRef conn_ref, int32_t id) +{ + ForeignMenuConnection *conn = _connections[conn_ref]; + FrgMenuEvent msg; + + ASSERT(conn); + msg.base.id = FOREIGN_MENU_ITEM_EVENT; + msg.base.size = sizeof(FrgMenuEvent); + msg.id = id; + msg.action = FOREIGN_MENU_EVENT_CLICK; + conn->write_msg(&msg.base, msg.base.size); +} + +void ForeignMenu::on_activate() +{ + std::map<NamedPipe::ConnectionRef, ForeignMenuConnection*>::const_iterator conn; + _active = true; + for (conn = _connections.begin(); conn != _connections.end(); ++conn) { + send_active_state(conn->second, FOREIGN_MENU_APP_ACTIVATED); + } +} + +void ForeignMenu::on_deactivate() +{ + std::map<NamedPipe::ConnectionRef, ForeignMenuConnection*>::const_iterator conn; + _active = false; + for (conn = _connections.begin(); conn != _connections.end(); ++conn) { + send_active_state(conn->second, FOREIGN_MENU_APP_DEACTIVATED); + } +} + +void ForeignMenu::send_active_state(ForeignMenuConnection *conn, int32_t cmd) +{ + FrgMenuMsg msg; + + ASSERT(conn != NULL); + msg.id = cmd; + msg.size = sizeof(FrgMenuMsg); + conn->write_msg(&msg, msg.size); +} + +ForeignMenuConnection::ForeignMenuConnection(ForeignMenuInterface *handler, ForeignMenu& parent) + : _handler (handler) + , _parent (parent) + , _sub_menu (NULL) + , _initialized (false) + , _write_pending (0) + , _write_pos (_write_buf) + , _read_pos (_read_buf) +{ +} + +ForeignMenuConnection::~ForeignMenuConnection() +{ + if (_opaque != NamedPipe::INVALID_CONNECTION) { + NamedPipe::destroy_connection(_opaque); + } + if (_handler) { + AutoRef<Menu> app_menu(_handler->get_app_menu()); + (*app_menu)->remove_sub(_sub_menu); + _handler->update_menu(); + _handler->clear_menu_items(_opaque); + } + if (_sub_menu) { + _sub_menu->unref(); + } +} + +void ForeignMenuConnection::bind(NamedPipe::ConnectionRef conn_ref) +{ + _opaque = conn_ref; + _parent.add_connection(conn_ref, this); +} + +void ForeignMenuConnection::on_data() +{ + if (_write_pending) { + LOG_INFO("Resume pending write %d", _write_pending); + if (!write_msg(_write_pos, _write_pending)) { + return; + } + } + while (read_msgs()); +} + +bool ForeignMenuConnection::read_msgs() +{ + uint8_t *pos = _read_buf; + size_t nread = _read_pos - _read_buf; + int32_t size; + + ASSERT(_handler); + ASSERT(_opaque != NamedPipe::INVALID_CONNECTION); + size = NamedPipe::read(_opaque, (uint8_t*)_read_pos, sizeof(_read_buf) - nread); + if (size == 0) { + return false; + } else if (size < 0) { + LOG_ERROR("Error reading from named pipe %d", size); + _parent.remove_connection(_opaque); + return false; + } + nread += size; + while (nread > 0) { + if (!_initialized && nread >= sizeof(FrgMenuInitHeader)) { + FrgMenuInitHeader *init = (FrgMenuInitHeader *)pos; + if (init->magic != FOREIGN_MENU_MAGIC || init->version != FOREIGN_MENU_VERSION) { + LOG_ERROR("Bad foreign menu init, magic=0x%x version=%u", init->magic, + init->version); + _parent.remove_connection(_opaque); + return false; + } + if (nread < init->size) { + break; + } + if (!handle_init((FrgMenuInit*)init)) { + _parent.remove_connection(_opaque); + return false; + } + nread -= init->size; + pos += init->size; + _initialized = true; + } + if (!_initialized || nread < sizeof(FrgMenuMsg)) { + break; + } + FrgMenuMsg *hdr = (FrgMenuMsg *)pos; + if (hdr->size < sizeof(FrgMenuMsg)) { + LOG_ERROR("Bad foreign menu message, size=%u", hdr->size); + _parent.remove_connection(_opaque); + return false; + } + if (nread < hdr->size) { + break; + } + handle_message(hdr); + nread -= hdr->size; + pos += hdr->size; + } + if (nread > 0 && pos != _read_buf) { + memcpy(_read_buf, pos, nread); + } + _read_pos = _read_buf + nread; + return true; +} + +bool ForeignMenuConnection::write_msg(const void *buf, int len) +{ + RecurciveLock lock(_write_lock); + uint8_t *pos; + int32_t written = 0; + + ASSERT(_opaque != NamedPipe::INVALID_CONNECTION); + if (_write_pending && buf != _write_pos) { + if ((_write_pos + _write_pending + len > _write_buf + sizeof(_write_buf)) && + !write_msg(_write_pos, _write_pending)) { + return false; + } + if (_write_pending) { + if (_write_pos + _write_pending + len > _write_buf + sizeof(_write_buf)) { + DBG(0, "Dropping message, due to insufficient space in write buffer"); + return true; + } + memcpy(_write_pos + _write_pending, buf, len); + _write_pending += len; + } + } + pos = (uint8_t*)buf; + while (len && (written = NamedPipe::write(_opaque, pos, len)) > 0) { + pos += written; + len -= written; + } + if (len && written == 0) { + if (_write_pending) { + _write_pos = pos; + } else { + _write_pos = _write_buf; + memcpy(_write_buf, pos, len); + } + _write_pending = len; + } else if (written < 0) { + LOG_ERROR("Error writing to named pipe %d", written); + _parent.remove_connection(_opaque); + return false; + } else { + _write_pending = 0; + } + return true; +} + +bool ForeignMenuConnection::handle_init(FrgMenuInit *init) +{ + std::string title = "Untitled"; + + ASSERT(_handler); + if (_sub_menu) { + LOG_ERROR("Foreign menu already initialized"); + return false; + } + if (init->credentials != 0) { + LOG_ERROR("Foreign menu has wrong credentials 0x%x", init->credentials); + return false; + } + if (init->base.size > offsetof(FrgMenuInit, title)) { + ((char*)init)[init->base.size - 1] = '\0'; + title = (char*)init->title; + } + _sub_menu = new Menu((CommandTarget&)*_handler, title); + add_sub_menu(); + _handler->update_menu(); + return true; +} + +void ForeignMenuConnection::add_sub_menu() +{ + if (_sub_menu) { + AutoRef<Menu> app_menu(_handler->get_app_menu()); + (*app_menu)->add_sub(_sub_menu); + } +} + +bool ForeignMenuConnection::handle_message(FrgMenuMsg *hdr) +{ + ASSERT(_sub_menu); + ASSERT(_handler); + switch (hdr->id) { + case FOREIGN_MENU_SET_TITLE: + ((char*)hdr)[hdr->size - 1] = '\0'; + _sub_menu->set_name((char*)((FrgMenuSetTitle*)hdr)->string); + break; + case FOREIGN_MENU_ADD_ITEM: { + FrgMenuAddItem *msg = (FrgMenuAddItem*)hdr; + ((char*)hdr)[hdr->size - 1] = '\0'; + int id = _handler->get_foreign_menu_item_id(_opaque, msg->id); + _sub_menu->add_command((char*)msg->string, id, get_item_state(msg->type)); + break; + } + case FOREIGN_MENU_REMOVE_ITEM: { + int id = _handler->get_foreign_menu_item_id(_opaque, ((FrgMenuRmItem*)hdr)->id); + _sub_menu->remove_command(id); + _handler->remove_menu_item(id); + break; + } + case FOREIGN_MENU_CLEAR: + _sub_menu->clear(); + _handler->clear_menu_items(_opaque); + break; + case FOREIGN_MENU_MODIFY_ITEM: + default: + LOG_ERROR("Ignoring an unknown foreign menu identifier %u", hdr->id); + return false; + } + _handler->update_menu(); + return true; +} + +int ForeignMenuConnection::get_item_state(int item_type) +{ + int state = 0; + + if (item_type & FOREIGN_MENU_ITEM_TYPE_CHECKED) { + state |= Menu::MENU_ITEM_STATE_CHECKED; + } + if (item_type & FOREIGN_MENU_ITEM_TYPE_DIM) { + state |= Menu::MENU_ITEM_STATE_DIM; + } + return state; +} diff --git a/client/foreign_menu.h b/client/foreign_menu.h new file mode 100644 index 00000000..2fc4e535 --- /dev/null +++ b/client/foreign_menu.h @@ -0,0 +1,98 @@ +/* + Copyright (C) 2009 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 _H_FOREIGN_MENU +#define _H_FOREIGN_MENU + +#include "named_pipe.h" +#include "menu.h" + +class ForeignMenuConnection; +struct FrgMenuInit; +struct FrgMenuMsg; + +class ForeignMenuInterface : public CommandTarget { +public: + virtual ~ForeignMenuInterface() {} + + virtual int get_foreign_menu_item_id(int32_t opaque_conn_ref, uint32_t msg_id) = 0; + virtual void clear_menu_items(int32_t opaque_conn_ref) = 0; + virtual void remove_menu_item(int item_id) = 0; + virtual Menu* get_app_menu() = 0; + virtual void update_menu() = 0; +}; + +class ForeignMenu : public NamedPipe::ListenerInterface { +public: + ForeignMenu(ForeignMenuInterface *handler); + virtual ~ForeignMenu(); + + ForeignMenu* ref() { _refs++; return this;} + void unref() { if (!--_refs) delete this;} + + virtual NamedPipe::ConnectionInterface &create(); + void add_connection(NamedPipe::ConnectionRef conn_ref, ForeignMenuConnection *conn); + void remove_connection(NamedPipe::ConnectionRef conn_ref); + void add_sub_menus(); + void on_command(NamedPipe::ConnectionRef conn_ref, int32_t id); + void on_activate(); + void on_deactivate(); + +private: + void send_active_state(ForeignMenuConnection *conn, int32_t cmd); + +private: + ForeignMenuInterface *_handler; + std::map<NamedPipe::ConnectionRef, ForeignMenuConnection*> _connections; + NamedPipe::ListenerRef _foreign_menu; + bool _active; + int _refs; +}; + +#define FOREIGN_MENU_BUF_SIZE 4096 + +class ForeignMenuConnection : public NamedPipe::ConnectionInterface { +public: + ForeignMenuConnection(ForeignMenuInterface *handler, ForeignMenu& parent); + virtual ~ForeignMenuConnection(); + + virtual void bind(NamedPipe::ConnectionRef conn_ref); + virtual void on_data(); + bool write_msg(const void *buf, int len); + void reset_handler() { _handler = NULL;} + void add_sub_menu(); + +private: + bool read_msgs(); + bool handle_init(FrgMenuInit *init); + bool handle_message(FrgMenuMsg *hdr); + int get_item_state(int item_type); + +private: + ForeignMenuInterface *_handler; + ForeignMenu& _parent; + Menu* _sub_menu; + bool _initialized; + int _write_pending; + uint8_t *_write_pos; + uint8_t *_read_pos; + uint8_t _write_buf[FOREIGN_MENU_BUF_SIZE]; + uint8_t _read_buf[FOREIGN_MENU_BUF_SIZE]; + RecurciveMutex _write_lock; +}; + +#endif diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj index 6b5182c8..538d2cb5 100644 --- a/client/windows/redc.vcproj +++ b/client/windows/redc.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="windows-1255"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="9,00"
+ Version="9.00"
Name="redc"
ProjectGUID="{4F03BAF9-DFBC-4CA7-B860-8929555981AE}"
RootNamespace="redc"
@@ -228,6 +228,10 @@ >
</File>
<File
+ RelativePath="..\foreign_menu.cpp"
+ >
+ </File>
+ <File
RelativePath="..\gdi_canvas.cpp"
>
</File>
@@ -508,6 +512,10 @@ >
</File>
<File
+ RelativePath="..\foreign_menu.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\gdi_canvas.h"
>
</File>
@@ -711,7 +719,7 @@ <Tool
Name="VCCustomBuildTool"
Description="Generating demarshaller"
- CommandLine="generate.bat"
+ CommandLine="generate.bat
"
AdditionalDependencies=""
Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.cpp"
/>
@@ -722,7 +730,7 @@ <Tool
Name="VCCustomBuildTool"
Description="Generating demarshaller"
- CommandLine="generate.bat"
+ CommandLine="generate.bat
"
Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.cpp"
/>
</FileConfiguration>
@@ -736,7 +744,7 @@ <Tool
Name="VCCustomBuildTool"
Description="Generating old demarshaller"
- CommandLine="generate1.bat"
+ CommandLine="generate1.bat
"
AdditionalDependencies=""
Outputs="$(ProjectDir)/../generated_demarshallers1.cpp;$(ProjectDir)/../generated_marshallers1.cpp"
/>
@@ -747,7 +755,7 @@ <Tool
Name="VCCustomBuildTool"
Description="Generating old demarshaller"
- CommandLine="generate1.bat"
+ CommandLine="generate1.bat
"
Outputs="$(ProjectDir)/../generated_demarshallers1.cpp;$(ProjectDir)/../generated_marshallers1.cpp"
/>
</FileConfiguration>
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am index 02aa8eb2..f6e9fda7 100644 --- a/client/x11/Makefile.am +++ b/client/x11/Makefile.am @@ -61,6 +61,8 @@ RED_COMMON_SRCS = \ $(CLIENT_DIR)/debug.h \ $(CLIENT_DIR)/display_channel.cpp \ $(CLIENT_DIR)/display_channel.h \ + $(CLIENT_DIR)/foreign_menu.cpp \ + $(CLIENT_DIR)/foreign_menu.h \ $(CLIENT_DIR)/glz_decoded_image.h \ $(CLIENT_DIR)/glz_decoder_config.h \ $(CLIENT_DIR)/glz_decoder.cpp \ |