summaryrefslogtreecommitdiffstats
path: root/client/foreign_menu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'client/foreign_menu.cpp')
-rw-r--r--client/foreign_menu.cpp50
1 files changed, 40 insertions, 10 deletions
diff --git a/client/foreign_menu.cpp b/client/foreign_menu.cpp
index db0badec..3298d638 100644
--- a/client/foreign_menu.cpp
+++ b/client/foreign_menu.cpp
@@ -51,9 +51,9 @@ ForeignMenu::ForeignMenu(ForeignMenuInterface *handler)
ForeignMenu::~ForeignMenu()
{
- _handler = NULL;
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) {
@@ -87,6 +87,14 @@ void ForeignMenu::remove_connection(NamedPipe::ConnectionRef 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];
@@ -144,8 +152,11 @@ ForeignMenuConnection::~ForeignMenuConnection()
if (_opaque != NamedPipe::INVALID_CONNECTION) {
NamedPipe::destroy_connection(_opaque);
}
- if (_parent.handler_attached()) {
- _handler->delete_foreign_menu(_opaque, _sub_menu);
+ 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();
@@ -175,7 +186,7 @@ bool ForeignMenuConnection::read_msgs()
size_t nread = _read_pos - _read_buf;
int32_t size;
- ASSERT(_handler != NULL);
+ ASSERT(_handler);
ASSERT(_opaque != NamedPipe::INVALID_CONNECTION);
size = NamedPipe::read(_opaque, (uint8_t*)_read_pos, sizeof(_read_buf) - nread);
if (size == 0) {
@@ -231,18 +242,24 @@ bool ForeignMenuConnection::read_msgs()
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_pending + len > sizeof(_write_buf)) {
- DBG(0, "Dropping msg due to pending write %d", _write_pending);
+ if ((_write_pos + _write_pending + len > _write_buf + sizeof(_write_buf)) &&
+ !write_msg(_write_pos, _write_pending)) {
return false;
}
- memcpy(_write_buf + _write_pending, buf, len);
- _write_pending += len;
- return true;
+ 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) {
@@ -271,6 +288,7 @@ bool ForeignMenuConnection::handle_init(FrgMenuInit *init)
{
std::string title = "Untitled";
+ ASSERT(_handler);
if (_sub_menu) {
LOG_ERROR("Foreign menu already initialized");
return false;
@@ -284,13 +302,23 @@ bool ForeignMenuConnection::handle_init(FrgMenuInit *init)
title = (char*)init->title;
}
_sub_menu = new Menu((CommandTarget&)*_handler, title);
- _handler->add_foreign_menu(_opaque, _sub_menu);
+ 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';
@@ -306,10 +334,12 @@ bool ForeignMenuConnection::handle_message(FrgMenuMsg *hdr)
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: