diff --git a/Applications/Terminal/main.cpp b/Applications/Terminal/main.cpp index c539a882f2..2710fa24ac 100644 --- a/Applications/Terminal/main.cpp +++ b/Applications/Terminal/main.cpp @@ -76,22 +76,29 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("Terminal"); - app_menu->add_item(1, "Quit"); + app_menu->add_item(0, "Quit"); + app_menu->on_item_activation = [] (unsigned identifier) { + if (identifier == 0) { + dbgprintf("Terminal: Quit menu activated!\n"); + GApplication::the().exit(0); + return; + } + }; menubar->add_menu(move(app_menu)); auto font_menu = make("Font"); - font_menu->add_item(30, "Liza Thin"); - font_menu->add_item(31, "Liza Regular"); - font_menu->add_item(32, "Liza Bold"); + font_menu->add_item(0, "Liza Thin"); + font_menu->add_item(1, "Liza Regular"); + font_menu->add_item(2, "Liza Bold"); font_menu->on_item_activation = [&terminal] (unsigned identifier) { switch (identifier) { - case 30: + case 0: terminal.set_font(Font::load_from_file("/res/fonts/Liza8x10.font")); break; - case 31: + case 1: terminal.set_font(Font::load_from_file("/res/fonts/LizaRegular8x10.font")); break; - case 32: + case 2: terminal.set_font(Font::load_from_file("/res/fonts/LizaBold8x10.font")); break; } @@ -100,7 +107,7 @@ int main(int argc, char** argv) menubar->add_menu(move(font_menu)); auto help_menu = make("Help"); - help_menu->add_item(2, "About"); + help_menu->add_item(0, "About"); menubar->add_menu(move(help_menu)); app.set_menubar(move(menubar)); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fb904d6ec8..cf8a4e8532 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2133,6 +2133,7 @@ void Process::finalize() { ASSERT(current == g_finalizer); + destroy_all_menus(); destroy_all_windows(); m_fds.clear(); m_tty = nullptr; diff --git a/Kernel/Process.h b/Kernel/Process.h index b219cb6adb..e7dfebf6b4 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -244,6 +244,7 @@ public: static void initialize(); static void initialize_gui_statics(); int make_window_id(); + void destroy_all_menus(); void destroy_all_windows(); void crash() NORETURN; @@ -419,6 +420,7 @@ private: Vector m_gui_events; Lock m_gui_events_lock; int m_next_window_id { 1 }; + bool m_has_created_menus { false }; dword m_wakeup_requested { false }; bool m_has_used_fpu { false }; diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index e97cf956c1..cc32ffc7d2 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -257,6 +257,13 @@ int Process::gui$set_global_cursor_tracking_enabled(int window_id, bool enabled) return 0; } +void Process::destroy_all_menus() +{ + if (!m_has_created_menus) + return; + WSWindowManager::the().destroy_all_menus(*this); +} + void Process::destroy_all_windows() { for (auto& it : m_windows) { @@ -267,7 +274,6 @@ void Process::destroy_all_windows() m_windows.clear(); } - DisplayInfo Process::set_video_resolution(int width, int height) { DisplayInfo info; @@ -288,6 +294,7 @@ DisplayInfo Process::set_video_resolution(int width, int height) int Process::gui$menubar_create() { + m_has_created_menus = true; return WSWindowManager::the().api$menubar_create(); } @@ -305,6 +312,7 @@ int Process::gui$menu_create(const char* name) { if (!validate_read_str(name)) return -EFAULT; + m_has_created_menus = true; return WSWindowManager::the().api$menu_create(String(name)); } diff --git a/LibGUI/GMenuBar.cpp b/LibGUI/GMenuBar.cpp index 25381e77cd..18c08f1a62 100644 --- a/LibGUI/GMenuBar.cpp +++ b/LibGUI/GMenuBar.cpp @@ -7,6 +7,10 @@ GMenuBar::GMenuBar() GMenuBar::~GMenuBar() { + if (m_menubar_id) { + gui_menubar_destroy(m_menubar_id); + m_menubar_id = 0; + } } void GMenuBar::add_menu(OwnPtr&& menu) diff --git a/WindowServer/WSMenu.h b/WindowServer/WSMenu.h index 26f64bb5c4..24a03587f0 100644 --- a/WindowServer/WSMenu.h +++ b/WindowServer/WSMenu.h @@ -18,6 +18,7 @@ public: ~WSMenu(); int menu_id() const { return m_menu_id; } + const Process* process() const { return m_process.ptr(); } WSMenuBar* menu_bar() { return m_menubar; } const WSMenuBar* menu_bar() const { return m_menubar; } diff --git a/WindowServer/WSMenuBar.cpp b/WindowServer/WSMenuBar.cpp index f8aa83dff8..a2d93ae8c0 100644 --- a/WindowServer/WSMenuBar.cpp +++ b/WindowServer/WSMenuBar.cpp @@ -3,8 +3,9 @@ #include "WSMenuItem.h" #include -WSMenuBar::WSMenuBar(Process& process) - : m_process(process.make_weak_ptr()) +WSMenuBar::WSMenuBar(int menubar_id, Process& process) + : m_menubar_id(menubar_id) + , m_process(process.make_weak_ptr()) { } diff --git a/WindowServer/WSMenuBar.h b/WindowServer/WSMenuBar.h index 0701412486..2aec358889 100644 --- a/WindowServer/WSMenuBar.h +++ b/WindowServer/WSMenuBar.h @@ -8,9 +8,11 @@ class Process; class WSMenuBar { public: - explicit WSMenuBar(Process&); + WSMenuBar(int menubar_id, Process&); ~WSMenuBar(); + int menubar_id() const { return m_menubar_id; } + const Process* process() const { return m_process.ptr(); } void add_menu(WSMenu* menu) { m_menus.append(menu); } template @@ -23,6 +25,7 @@ public: } private: + int m_menubar_id { 0 }; WeakPtr m_process; Vector m_menus; }; diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index cd8c7cc634..5931a1899f 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -761,8 +761,8 @@ void WSWindowManager::flush(const Rect& a_rect) void WSWindowManager::close_menu(WSMenu& menu) { LOCKER(m_lock); - ASSERT(m_current_menu == &menu); - close_current_menu(); + if (m_current_menu == &menu) + close_current_menu(); } WSMenu& WSWindowManager::create_menu(String&& name) @@ -779,8 +779,8 @@ WSMenu& WSWindowManager::create_menu(String&& name) int WSWindowManager::api$menubar_create() { LOCKER(m_lock); - auto menubar = make(*current); int menubar_id = m_next_menubar_id++; + auto menubar = make(menubar_id, *current); m_menubars.set(menubar_id, move(menubar)); return menubar_id; } @@ -793,7 +793,7 @@ int WSWindowManager::api$menubar_destroy(int menubar_id) return -EBADMENUBAR; auto& menubar = *(*it).value; if (&menubar == m_current_menubar) - ASSERT_NOT_REACHED(); + set_current_menubar(nullptr); m_menubars.remove(it); return 0; } @@ -827,6 +827,8 @@ int WSWindowManager::api$menu_destroy(int menu_id) auto it = m_menus.find(menu_id); if (it == m_menus.end()) return -EBADMENU; + auto& menu = *(*it).value; + close_menu(menu); m_menus.remove(it); return 0; } @@ -868,3 +870,33 @@ int WSWindowManager::api$app_set_menubar(int menubar_id) invalidate(); return 0; } + +void WSWindowManager::destroy_all_menus(Process& process) +{ + LOCKER(m_lock); + Vector menu_ids; + bool should_close_current_menu = false; + for (auto& it : m_menus) { + if (it.value->process() == &process) + menu_ids.append(it.value->menu_id()); + if (m_current_menu == it.value.ptr()) + should_close_current_menu = true; + } + if (should_close_current_menu) + close_current_menu(); + for (int menu_id : menu_ids) + m_menus.remove(menu_id); + + Vector menubar_ids; + bool should_close_current_menubar = false; + for (auto& it : m_menubars) { + if (it.value->process() == &process) + menubar_ids.append(it.value->menubar_id()); + if (m_current_menubar == it.value.ptr()) + should_close_current_menubar = true; + } + if (should_close_current_menubar) + set_current_menubar(nullptr); + for (int menubar_id : menubar_ids) + m_menubars.remove(menubar_id); +} diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index cb6949ae66..3a3adb2ecd 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -62,6 +62,7 @@ public: 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); + void destroy_all_menus(Process&); private: WSWindowManager();