mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:48:11 +00:00
Plumb menu item activation events from WindowServer to clients.
GMenu now has an "on_item_activation" callback that fires whenever one of its items are activated. The menu item identifier is used to distinguish between items. Use this to implement font switching in Terminal. :^)
This commit is contained in:
parent
9c1c885483
commit
db98327bdc
10 changed files with 93 additions and 3 deletions
|
@ -749,3 +749,11 @@ void Terminal::flush_dirty_lines()
|
||||||
}
|
}
|
||||||
update(rect);
|
update(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Terminal::force_repaint()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_rows; ++i)
|
||||||
|
line(i).dirty = true;
|
||||||
|
m_need_full_flush = true;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ public:
|
||||||
void on_char(byte);
|
void on_char(byte);
|
||||||
|
|
||||||
void flush_dirty_lines();
|
void flush_dirty_lines();
|
||||||
|
void force_repaint();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void event(GEvent&) override;
|
virtual void event(GEvent&) override;
|
||||||
|
|
|
@ -80,9 +80,23 @@ int main(int argc, char** argv)
|
||||||
menubar->add_menu(move(app_menu));
|
menubar->add_menu(move(app_menu));
|
||||||
|
|
||||||
auto font_menu = make<GMenu>("Font");
|
auto font_menu = make<GMenu>("Font");
|
||||||
font_menu->add_item(30, "Liza 8x10");
|
font_menu->add_item(30, "Liza Thin");
|
||||||
font_menu->add_item(31, "LizaRegular 8x10");
|
font_menu->add_item(31, "Liza Regular");
|
||||||
font_menu->add_item(32, "LizaBold 8x10");
|
font_menu->add_item(32, "Liza Bold");
|
||||||
|
font_menu->on_item_activation = [&terminal] (unsigned identifier) {
|
||||||
|
switch (identifier) {
|
||||||
|
case 30:
|
||||||
|
terminal.set_font(Font::load_from_file("/res/fonts/Liza8x10.font"));
|
||||||
|
break;
|
||||||
|
case 31:
|
||||||
|
terminal.set_font(Font::load_from_file("/res/fonts/LizaRegular8x10.font"));
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
terminal.set_font(Font::load_from_file("/res/fonts/LizaBold8x10.font"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
terminal.force_repaint();
|
||||||
|
};
|
||||||
menubar->add_menu(move(font_menu));
|
menubar->add_menu(move(font_menu));
|
||||||
|
|
||||||
auto help_menu = make<GMenu>("Help");
|
auto help_menu = make<GMenu>("Help");
|
||||||
|
|
|
@ -67,6 +67,7 @@ struct GUI_Event {
|
||||||
WindowActivated,
|
WindowActivated,
|
||||||
WindowDeactivated,
|
WindowDeactivated,
|
||||||
WindowCloseRequest,
|
WindowCloseRequest,
|
||||||
|
MenuItemActivated,
|
||||||
};
|
};
|
||||||
Type type { Invalid };
|
Type type { Invalid };
|
||||||
int window_id { -1 };
|
int window_id { -1 };
|
||||||
|
@ -88,6 +89,10 @@ struct GUI_Event {
|
||||||
bool alt : 1;
|
bool alt : 1;
|
||||||
bool shift : 1;
|
bool shift : 1;
|
||||||
} key;
|
} key;
|
||||||
|
struct {
|
||||||
|
int menu_id;
|
||||||
|
unsigned identifier;
|
||||||
|
} menu;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "GObject.h"
|
#include "GObject.h"
|
||||||
#include "GWindow.h"
|
#include "GWindow.h"
|
||||||
#include <LibGUI/GNotifier.h>
|
#include <LibGUI/GNotifier.h>
|
||||||
|
#include <LibGUI/GMenu.h>
|
||||||
#include <LibC/unistd.h>
|
#include <LibC/unistd.h>
|
||||||
#include <LibC/stdio.h>
|
#include <LibC/stdio.h>
|
||||||
#include <LibC/fcntl.h>
|
#include <LibC/fcntl.h>
|
||||||
|
@ -147,6 +148,21 @@ void GEventLoop::handle_mouse_event(const GUI_Event& event, GWindow& window)
|
||||||
post_event(&window, make<GMouseEvent>(type, event.mouse.position, event.mouse.buttons, button));
|
post_event(&window, make<GMouseEvent>(type, event.mouse.position, event.mouse.buttons, button));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GEventLoop::handle_menu_event(const GUI_Event& event)
|
||||||
|
{
|
||||||
|
if (event.type == GUI_Event::Type::MenuItemActivated) {
|
||||||
|
auto* menu = GMenu::from_menu_id(event.menu.menu_id);
|
||||||
|
if (!menu) {
|
||||||
|
dbgprintf("GEventLoop received event for invalid window ID %d\n", event.window_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (menu->on_item_activation)
|
||||||
|
menu->on_item_activation(event.menu.identifier);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
void GEventLoop::wait_for_event()
|
void GEventLoop::wait_for_event()
|
||||||
{
|
{
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
|
@ -219,6 +235,13 @@ void GEventLoop::wait_for_event()
|
||||||
if (nread == 0)
|
if (nread == 0)
|
||||||
break;
|
break;
|
||||||
assert(nread == sizeof(event));
|
assert(nread == sizeof(event));
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case GUI_Event::MenuItemActivated:
|
||||||
|
handle_menu_event(event);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto* window = GWindow::from_window_id(event.window_id);
|
auto* window = GWindow::from_window_id(event.window_id);
|
||||||
if (!window) {
|
if (!window) {
|
||||||
dbgprintf("GEventLoop received event for invalid window ID %d\n", event.window_id);
|
dbgprintf("GEventLoop received event for invalid window ID %d\n", event.window_id);
|
||||||
|
@ -244,6 +267,8 @@ void GEventLoop::wait_for_event()
|
||||||
case GUI_Event::Type::KeyUp:
|
case GUI_Event::Type::KeyUp:
|
||||||
handle_key_event(event, *window);
|
handle_key_event(event, *window);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ private:
|
||||||
void handle_key_event(const GUI_Event&, GWindow&);
|
void handle_key_event(const GUI_Event&, GWindow&);
|
||||||
void handle_window_activation_event(const GUI_Event&, GWindow&);
|
void handle_window_activation_event(const GUI_Event&, GWindow&);
|
||||||
void handle_window_close_request_event(const GUI_Event&, GWindow&);
|
void handle_window_close_request_event(const GUI_Event&, GWindow&);
|
||||||
|
void handle_menu_event(const GUI_Event&);
|
||||||
|
|
||||||
void get_next_timer_expiration(timeval&);
|
void get_next_timer_expiration(timeval&);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
#include <LibGUI/GMenu.h>
|
#include <LibGUI/GMenu.h>
|
||||||
#include <LibC/gui.h>
|
#include <LibC/gui.h>
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
|
||||||
|
static HashMap<int, GMenu*>& all_menus()
|
||||||
|
{
|
||||||
|
static HashMap<int, GMenu*>* map;
|
||||||
|
if (!map)
|
||||||
|
map = new HashMap<int, GMenu*>();
|
||||||
|
return *map;
|
||||||
|
}
|
||||||
|
|
||||||
|
GMenu* GMenu::from_menu_id(int menu_id)
|
||||||
|
{
|
||||||
|
auto it = all_menus().find(menu_id);
|
||||||
|
if (it == all_menus().end())
|
||||||
|
return nullptr;
|
||||||
|
return (*it).value;
|
||||||
|
}
|
||||||
|
|
||||||
GMenu::GMenu(const String& name)
|
GMenu::GMenu(const String& name)
|
||||||
: m_name(name)
|
: m_name(name)
|
||||||
|
@ -9,6 +26,7 @@ GMenu::GMenu(const String& name)
|
||||||
GMenu::~GMenu()
|
GMenu::~GMenu()
|
||||||
{
|
{
|
||||||
if (m_menu_id) {
|
if (m_menu_id) {
|
||||||
|
all_menus().remove(m_menu_id);
|
||||||
gui_menu_destroy(m_menu_id);
|
gui_menu_destroy(m_menu_id);
|
||||||
m_menu_id = 0;
|
m_menu_id = 0;
|
||||||
}
|
}
|
||||||
|
@ -34,5 +52,6 @@ int GMenu::realize_menu()
|
||||||
else if (item.type() == GMenuItem::Text)
|
else if (item.type() == GMenuItem::Text)
|
||||||
gui_menu_add_item(m_menu_id, item.identifier(), item.text().characters());
|
gui_menu_add_item(m_menu_id, item.identifier(), item.text().characters());
|
||||||
}
|
}
|
||||||
|
all_menus().set(m_menu_id, this);
|
||||||
return m_menu_id;
|
return m_menu_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibGUI/GMenuItem.h>
|
#include <LibGUI/GMenuItem.h>
|
||||||
|
#include <AK/Function.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
|
||||||
class GMenu {
|
class GMenu {
|
||||||
|
@ -8,9 +9,13 @@ public:
|
||||||
explicit GMenu(const String& name);
|
explicit GMenu(const String& name);
|
||||||
~GMenu();
|
~GMenu();
|
||||||
|
|
||||||
|
static GMenu* from_menu_id(int);
|
||||||
|
|
||||||
void add_item(unsigned identifier, const String& text);
|
void add_item(unsigned identifier, const String& text);
|
||||||
void add_separator();
|
void add_separator();
|
||||||
|
|
||||||
|
Function<void(unsigned)> on_item_activation;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GMenuBar;
|
friend class GMenuBar;
|
||||||
int menu_id() const { return m_menu_id; }
|
int menu_id() const { return m_menu_id; }
|
||||||
|
|
|
@ -234,6 +234,7 @@ void GWidget::set_font(RetainPtr<Font>&& font)
|
||||||
m_font = Font::default_font();
|
m_font = Font::default_font();
|
||||||
else
|
else
|
||||||
m_font = move(font);
|
m_font = move(font);
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GWidget::set_global_cursor_tracking(bool enabled)
|
void GWidget::set_global_cursor_tracking(bool enabled)
|
||||||
|
|
|
@ -137,7 +137,18 @@ void WSMenu::did_activate(WSMenuItem& item)
|
||||||
{
|
{
|
||||||
if (on_item_activation)
|
if (on_item_activation)
|
||||||
on_item_activation(item);
|
on_item_activation(item);
|
||||||
|
|
||||||
close();
|
close();
|
||||||
|
|
||||||
|
GUI_Event gui_event;
|
||||||
|
gui_event.type = GUI_Event::Type::MenuItemActivated;
|
||||||
|
gui_event.menu.menu_id = m_menu_id;
|
||||||
|
gui_event.menu.identifier = item.identifier();
|
||||||
|
|
||||||
|
if (!m_process)
|
||||||
|
return;
|
||||||
|
LOCKER(m_process->gui_events_lock());
|
||||||
|
m_process->gui_events().append(move(gui_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
WSMenuItem* WSMenu::item_at(const Point& position)
|
WSMenuItem* WSMenu::item_at(const Point& position)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue