diff --git a/Libraries/LibGUI/GMenu.cpp b/Libraries/LibGUI/GMenu.cpp index 401b3672db..612e0b9ae0 100644 --- a/Libraries/LibGUI/GMenu.cpp +++ b/Libraries/LibGUI/GMenu.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -87,7 +88,7 @@ int GMenu::realize_menu() if (item.type() == GMenuItem::Submenu) { auto& submenu = *item.submenu(); submenu.realize_if_needed(); - GWindowServerConnection::the().send_sync(m_menu_id, i, submenu.menu_id(), submenu.name(), true, false, false, "", -1); + GWindowServerConnection::the().send_sync(m_menu_id, i, submenu.menu_id(), submenu.name(), true, false, false, "", -1, false); continue; } if (item.type() == GMenuItem::Action) { @@ -108,7 +109,8 @@ int GMenu::realize_menu() icon_buffer_id = action.icon()->shared_buffer_id(); } auto shortcut_text = action.shortcut().is_valid() ? action.shortcut().to_string() : String(); - GWindowServerConnection::the().send_sync(m_menu_id, i, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, shortcut_text, icon_buffer_id); + bool exclusive = action.group() && action.group()->is_exclusive() && action.is_checkable(); + GWindowServerConnection::the().send_sync(m_menu_id, i, -1, action.text(), action.is_enabled(), action.is_checkable(), action.is_checkable() ? action.is_checked() : false, shortcut_text, icon_buffer_id, exclusive); } } all_menus().set(m_menu_id, this); diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index 3094f29cf8..c62a56852c 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -167,6 +167,7 @@ OwnPtr WSClientConnection::handle(const Windo menu_item->set_icon(shared_icon); } menu_item->set_submenu_id(message.submenu_id()); + menu_item->set_exclusive(message.exclusive()); menu.add_item(move(menu_item)); return make(); } diff --git a/Servers/WindowServer/WSMenu.cpp b/Servers/WindowServer/WSMenu.cpp index 9c0ea38bbb..0bc6ebdc77 100644 --- a/Servers/WindowServer/WSMenu.cpp +++ b/Servers/WindowServer/WSMenu.cpp @@ -164,13 +164,19 @@ void WSMenu::draw() } Rect text_rect = item.rect().translated(stripe_rect.width() + 6, 0); if (item.is_checkable()) { - Rect checkmark_rect { item.rect().x() + 7, 0, s_checked_bitmap_width, s_checked_bitmap_height }; - checkmark_rect.center_vertically_within(text_rect); - Rect checkbox_rect = checkmark_rect.inflated(4, 4); - painter.fill_rect(checkbox_rect, palette.base()); - StylePainter::paint_frame(painter, checkbox_rect, palette, FrameShape::Container, FrameShadow::Sunken, 2); - if (item.is_checked()) { - painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, palette.button_text()); + if (item.is_exclusive()) { + Rect radio_rect { item.rect().x() + 5, 0, 12, 12 }; + radio_rect.center_vertically_within(text_rect); + StylePainter::paint_radio_button(painter, radio_rect, palette, item.is_checked(), false); + } else { + Rect checkmark_rect { item.rect().x() + 7, 0, s_checked_bitmap_width, s_checked_bitmap_height }; + checkmark_rect.center_vertically_within(text_rect); + Rect checkbox_rect = checkmark_rect.inflated(4, 4); + painter.fill_rect(checkbox_rect, palette.base()); + StylePainter::paint_frame(painter, checkbox_rect, palette, FrameShape::Container, FrameShadow::Sunken, 2); + if (item.is_checked()) { + painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, palette.button_text()); + } } } else if (item.icon()) { Rect icon_rect { item.rect().x() + 3, 0, s_item_icon_width, s_item_icon_width }; diff --git a/Servers/WindowServer/WSMenuItem.h b/Servers/WindowServer/WSMenuItem.h index 14711e4927..3e2cf1b2f4 100644 --- a/Servers/WindowServer/WSMenuItem.h +++ b/Servers/WindowServer/WSMenuItem.h @@ -50,6 +50,9 @@ public: WSMenu* submenu(); + bool is_exclusive() const { return m_exclusive; } + void set_exclusive(bool exclusive) { m_exclusive = exclusive; } + private: WSMenu& m_menu; Type m_type { None }; @@ -62,4 +65,5 @@ private: Rect m_rect; RefPtr m_icon; int m_submenu_id { -1 }; + bool m_exclusive { false }; }; diff --git a/Servers/WindowServer/WindowServer.ipc b/Servers/WindowServer/WindowServer.ipc index da99f4067c..5f9e9a0068 100644 --- a/Servers/WindowServer/WindowServer.ipc +++ b/Servers/WindowServer/WindowServer.ipc @@ -11,7 +11,18 @@ endpoint WindowServer = 2 AddMenuToMenubar(i32 menubar_id, i32 menu_id) => () SetApplicationMenubar(i32 menubar_id) => () - AddMenuItem(i32 menu_id, i32 identifier, i32 submenu_id, String text, bool enabled, bool checkable, bool checked, String shortcut, i32 icon_buffer_id) => () + AddMenuItem( + i32 menu_id, + i32 identifier, + i32 submenu_id, + String text, + bool enabled, + bool checkable, + bool checked, + String shortcut, + i32 icon_buffer_id, + bool exclusive) => () + AddMenuSeparator(i32 menu_id) => () UpdateMenuItem(i32 menu_id, i32 identifier, i32 submenu_id, String text, bool enabled, bool checkable, bool checked, String shortcut) => ()