mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:17:35 +00:00
Add API's and plumbing for WindowServer clients to make menus.
This commit is contained in:
parent
bb31d961b4
commit
133706d697
17 changed files with 322 additions and 24 deletions
|
@ -7,8 +7,9 @@
|
|||
#include <SharedGraphics/Painter.h>
|
||||
#include <SharedGraphics/Font.h>
|
||||
|
||||
WSMenu::WSMenu(const String& name)
|
||||
: m_name(name)
|
||||
WSMenu::WSMenu(int menu_id, String&& name)
|
||||
: m_menu_id(menu_id)
|
||||
, m_name(move(name))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,11 @@ class Font;
|
|||
|
||||
class WSMenu {
|
||||
public:
|
||||
WSMenu(const String& name);
|
||||
WSMenu(int menu_id, String&& name);
|
||||
~WSMenu();
|
||||
|
||||
int menu_id() const { return m_menu_id; }
|
||||
|
||||
WSMenuBar* menu_bar() { return m_menubar; }
|
||||
const WSMenuBar* menu_bar() const { return m_menubar; }
|
||||
|
||||
|
@ -70,6 +72,7 @@ public:
|
|||
private:
|
||||
void did_activate(WSMenuItem&);
|
||||
|
||||
int m_menu_id { 0 };
|
||||
String m_name;
|
||||
Rect m_rect_in_menubar;
|
||||
Rect m_text_rect_in_menubar;
|
||||
|
|
|
@ -8,7 +8,7 @@ public:
|
|||
WSMenuBar();
|
||||
~WSMenuBar();
|
||||
|
||||
void add_menu(OwnPtr<WSMenu>&& menu) { m_menus.append(move(menu)); }
|
||||
void add_menu(WSMenu* menu) { m_menus.append(menu); }
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_menu(Callback callback)
|
||||
|
@ -20,5 +20,5 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Vector<OwnPtr<WSMenu>> m_menus;
|
||||
Vector<WSMenu*> m_menus;
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <SharedGraphics/CharacterBitmap.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <Kernel/BochsVGADevice.h>
|
||||
#include <LibC/errno_numbers.h>
|
||||
#include "WSMenu.h"
|
||||
#include "WSMenuBar.h"
|
||||
#include "WSMenuItem.h"
|
||||
|
@ -185,28 +186,28 @@ WSWindowManager::WSWindowManager()
|
|||
|
||||
{
|
||||
byte system_menu_name[] = { 0xfc, 0 };
|
||||
auto menu = make<WSMenu>(String((const char*)system_menu_name));
|
||||
menu->add_item(make<WSMenuItem>(0, "Launch Terminal"));
|
||||
menu->add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||
menu->add_item(make<WSMenuItem>(1, "Hello again"));
|
||||
menu->add_item(make<WSMenuItem>(2, "To all my friends"));
|
||||
menu->add_item(make<WSMenuItem>(3, "Together we can play some rock&roll"));
|
||||
menu->add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||
menu->add_item(make<WSMenuItem>(4, "About..."));
|
||||
menu->on_item_activation = [] (WSMenuItem& item) {
|
||||
auto& menu = create_menu(String((const char*)system_menu_name));
|
||||
menu.add_item(make<WSMenuItem>(0, "Launch Terminal"));
|
||||
menu.add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||
menu.add_item(make<WSMenuItem>(1, "Hello again"));
|
||||
menu.add_item(make<WSMenuItem>(2, "To all my friends"));
|
||||
menu.add_item(make<WSMenuItem>(3, "Together we can play some rock&roll"));
|
||||
menu.add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||
menu.add_item(make<WSMenuItem>(4, "About..."));
|
||||
menu.on_item_activation = [] (WSMenuItem& item) {
|
||||
kprintf("WSMenu 1 item activated: '%s'\n", item.text().characters());
|
||||
};
|
||||
menubar->add_menu(move(menu));
|
||||
menubar->add_menu(&menu);
|
||||
}
|
||||
{
|
||||
auto menu = make<WSMenu>("Dummy");
|
||||
menu->add_item(make<WSMenuItem>(5, "Foo."));
|
||||
menu->add_item(make<WSMenuItem>(6, "Bar?"));
|
||||
menu->add_item(make<WSMenuItem>(7, "Baz!"));
|
||||
menu->on_item_activation = [] (WSMenuItem& item) {
|
||||
auto& menu = create_menu("Dummy");
|
||||
menu.add_item(make<WSMenuItem>(5, "Foo."));
|
||||
menu.add_item(make<WSMenuItem>(6, "Bar?"));
|
||||
menu.add_item(make<WSMenuItem>(7, "Baz!"));
|
||||
menu.on_item_activation = [] (WSMenuItem& item) {
|
||||
kprintf("WSMenu 2 item activated: '%s'\n", item.text().characters());
|
||||
};
|
||||
menubar->add_menu(move(menu));
|
||||
menubar->add_menu(&menu);
|
||||
}
|
||||
|
||||
set_current_menubar(menubar.ptr());
|
||||
|
@ -223,11 +224,10 @@ WSWindowManager::~WSWindowManager()
|
|||
|
||||
void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
if (m_current_menubar == menubar)
|
||||
return;
|
||||
m_current_menubar = menubar;
|
||||
if (!m_current_menubar)
|
||||
return;
|
||||
int menu_margin = 16;
|
||||
Point next_menu_location { menu_margin / 2, 3 };
|
||||
m_current_menubar->for_each_menu([&] (WSMenu& menu) {
|
||||
|
@ -237,6 +237,7 @@ void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
|
|||
next_menu_location.move_by(menu.rect_in_menubar().width(), 0);
|
||||
return true;
|
||||
});
|
||||
invalidate();
|
||||
}
|
||||
|
||||
static const char* s_close_button_bitmap_data = {
|
||||
|
@ -445,6 +446,7 @@ void WSWindowManager::handle_close_button_mouse_event(WSWindow& window, WSMouseE
|
|||
|
||||
void WSWindowManager::process_mouse_event(WSMouseEvent& event)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
if (event.type() == WSMessage::MouseUp && event.button() == MouseButton::Left) {
|
||||
if (m_drag_window) {
|
||||
#ifdef DRAG_DEBUG
|
||||
|
@ -770,3 +772,106 @@ void WSWindowManager::close_menu(WSMenu& menu)
|
|||
ASSERT(m_current_menu == &menu);
|
||||
close_current_menu();
|
||||
}
|
||||
|
||||
WSMenu& WSWindowManager::create_menu(String&& name)
|
||||
{
|
||||
int menu_id = m_next_menu_id++;
|
||||
auto menu = make<WSMenu>(menu_id, move(name));
|
||||
auto* menu_ptr = menu.ptr();
|
||||
m_menus.set(menu_id, move(menu));
|
||||
return *menu_ptr;
|
||||
}
|
||||
|
||||
|
||||
int WSWindowManager::api$menubar_create()
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto menubar = make<WSMenuBar>();
|
||||
int menubar_id = m_next_menubar_id++;
|
||||
m_menubars.set(menubar_id, move(menubar));
|
||||
return menubar_id;
|
||||
}
|
||||
|
||||
int WSWindowManager::api$menubar_destroy(int menubar_id)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto it = m_menubars.find(menubar_id);
|
||||
if (it == m_menubars.end())
|
||||
return -EBADMENUBAR;
|
||||
auto& menubar = *(*it).value;
|
||||
if (&menubar == m_current_menubar)
|
||||
ASSERT_NOT_REACHED();
|
||||
m_menubars.remove(it);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WSWindowManager::api$menubar_add_menu(int menubar_id, int menu_id)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto it = m_menubars.find(menubar_id);
|
||||
if (it == m_menubars.end())
|
||||
return -EBADMENUBAR;
|
||||
auto& menubar = *(*it).value;
|
||||
|
||||
auto jt = m_menus.find(menu_id);
|
||||
if (jt == m_menus.end())
|
||||
return -EBADMENU;
|
||||
auto& menu = *(*jt).value;
|
||||
|
||||
menubar.add_menu(&menu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WSWindowManager::api$menu_create(String&& name)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
return create_menu(move(name)).menu_id();
|
||||
}
|
||||
|
||||
int WSWindowManager::api$menu_destroy(int menu_id)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto it = m_menus.find(menu_id);
|
||||
if (it == m_menus.end())
|
||||
return -EBADMENU;
|
||||
m_menus.remove(it);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WSWindowManager::api$menu_add_separator(int menu_id)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto it = m_menus.find(menu_id);
|
||||
if (it == m_menus.end())
|
||||
return -EBADMENU;
|
||||
auto& menu = *(*it).value;
|
||||
menu.add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WSWindowManager::api$menu_add_item(int menu_id, unsigned identifier, String&& text)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto it = m_menus.find(menu_id);
|
||||
if (it == m_menus.end())
|
||||
return -EBADMENU;
|
||||
auto& menu = *(*it).value;
|
||||
menu.add_item(make<WSMenuItem>(identifier, move(text)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WSWindowManager::api$app_set_menubar(int menubar_id)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto it = m_menubars.find(menubar_id);
|
||||
if (it == m_menubars.end())
|
||||
return -EBADMENUBAR;
|
||||
auto& menubar = *(*it).value;
|
||||
if (&menubar == m_current_menubar)
|
||||
return 0;
|
||||
set_current_menubar(&menubar);
|
||||
// FIXME: Maybe leave the system menu even if the app menu changes?
|
||||
close_current_menu();
|
||||
invalidate();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,15 @@ public:
|
|||
|
||||
void close_menu(WSMenu&);
|
||||
|
||||
int api$menubar_create();
|
||||
int api$menubar_destroy(int menubar_id);
|
||||
int api$menubar_add_menu(int menubar_id, int menu_id);
|
||||
int api$menu_create(String&&);
|
||||
int api$menu_destroy(int menu_id);
|
||||
int api$menu_add_separator(int menu_id);
|
||||
int api$menu_add_item(int menu_id, unsigned identifier, String&& text);
|
||||
int api$app_set_menubar(int menubar_id);
|
||||
|
||||
private:
|
||||
WSWindowManager();
|
||||
virtual ~WSWindowManager() override;
|
||||
|
@ -66,6 +75,7 @@ private:
|
|||
void set_active_window(WSWindow*);
|
||||
|
||||
void close_current_menu();
|
||||
WSMenu& create_menu(String&& name);
|
||||
|
||||
virtual void on_message(WSMessage&) override;
|
||||
|
||||
|
@ -128,7 +138,11 @@ private:
|
|||
Lockable<bool> m_flash_flush;
|
||||
bool m_buffers_are_flipped { false };
|
||||
|
||||
int m_next_menubar_id = 100;
|
||||
int m_next_menu_id = 900;
|
||||
|
||||
WSMenuBar* m_current_menubar { nullptr };
|
||||
WSMenu* m_current_menu { nullptr };
|
||||
HashMap<int, OwnPtr<WSMenuBar>> m_menubars;
|
||||
HashMap<int, OwnPtr<WSMenu>> m_menus;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue