mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 17:07:35 +00:00
IRC client setttings, Terminal settings, more WM settings
This commit is contained in:
parent
63486b8438
commit
e3f81bce49
13 changed files with 89 additions and 53 deletions
|
@ -52,12 +52,14 @@ void IRCAppWindow::setup_client()
|
||||||
m_client.join_channel("#test");
|
m_client.join_channel("#test");
|
||||||
};
|
};
|
||||||
|
|
||||||
GInputBox input_box("Enter server:", "Connect to server", this);
|
if (m_client.hostname() == "none") {
|
||||||
auto result = input_box.exec();
|
GInputBox input_box("Enter server:", "Connect to server", this);
|
||||||
if (result == GInputBox::ExecCancel)
|
auto result = input_box.exec();
|
||||||
::exit(0);
|
if (result == GInputBox::ExecCancel)
|
||||||
|
::exit(0);
|
||||||
|
|
||||||
m_client.set_server(input_box.text_value(), 6667);
|
m_client.set_server(input_box.text_value(), 6667);
|
||||||
|
}
|
||||||
update_title();
|
update_title();
|
||||||
bool success = m_client.connect();
|
bool success = m_client.connect();
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
|
|
|
@ -31,8 +31,12 @@ IRCClient::IRCClient()
|
||||||
: m_nickname("seren1ty")
|
: m_nickname("seren1ty")
|
||||||
, m_client_window_list_model(IRCWindowListModel::create(*this))
|
, m_client_window_list_model(IRCWindowListModel::create(*this))
|
||||||
, m_log(IRCLogBuffer::create())
|
, m_log(IRCLogBuffer::create())
|
||||||
|
, m_config(CConfigFile::get_for_app("IRCClient"))
|
||||||
{
|
{
|
||||||
m_socket = new CTCPSocket(this);
|
m_socket = new CTCPSocket(this);
|
||||||
|
m_nickname = m_config->read_entry("User", "Nickname", "seren1ty");
|
||||||
|
m_hostname = m_config->read_entry("Connection", "Server", "chat.freenode.net");
|
||||||
|
m_port = m_config->read_num_entry("Connection", "Port", 6667);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRCClient::~IRCClient()
|
IRCClient::~IRCClient()
|
||||||
|
@ -53,8 +57,16 @@ void IRCClient::on_socket_connected()
|
||||||
send_user();
|
send_user();
|
||||||
send_nick();
|
send_nick();
|
||||||
|
|
||||||
if (on_connect)
|
if (on_connect) {
|
||||||
|
auto channel_str = m_config->read_entry("Connection", "AutoJoinChannels", "#test");
|
||||||
|
dbgprintf("IRCClient: Channels to autojoin: %s\n", channel_str.characters());
|
||||||
|
auto channels = channel_str.split(',');
|
||||||
|
for (auto channel : channels) {
|
||||||
|
join_channel(channel);
|
||||||
|
dbgprintf("IRCClient: Auto joining channel: %s\n", channel.characters());
|
||||||
|
}
|
||||||
on_connect();
|
on_connect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRCClient::connect()
|
bool IRCClient::connect()
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <LibCore/CTCPSocket.h>
|
#include <LibCore/CTCPSocket.h>
|
||||||
|
#include <LibCore/CConfigFile.h>
|
||||||
#include "IRCLogBuffer.h"
|
#include "IRCLogBuffer.h"
|
||||||
#include "IRCWindow.h"
|
#include "IRCWindow.h"
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ private:
|
||||||
|
|
||||||
void on_socket_connected();
|
void on_socket_connected();
|
||||||
|
|
||||||
String m_hostname;
|
String m_hostname { "none" };
|
||||||
int m_port { 6667 };
|
int m_port { 6667 };
|
||||||
|
|
||||||
CTCPSocket* m_socket { nullptr };
|
CTCPSocket* m_socket { nullptr };
|
||||||
|
@ -127,4 +128,5 @@ private:
|
||||||
|
|
||||||
Retained<IRCWindowListModel> m_client_window_list_model;
|
Retained<IRCWindowListModel> m_client_window_list_model;
|
||||||
Retained<IRCLogBuffer> m_log;
|
Retained<IRCLogBuffer> m_log;
|
||||||
|
Retained<CConfigFile> m_config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,21 +17,30 @@
|
||||||
|
|
||||||
//#define TERMINAL_DEBUG
|
//#define TERMINAL_DEBUG
|
||||||
|
|
||||||
Terminal::Terminal(int ptm_fd)
|
Terminal::Terminal(int ptm_fd, RetainPtr<CConfigFile> config)
|
||||||
: m_ptm_fd(ptm_fd)
|
: m_ptm_fd(ptm_fd)
|
||||||
, m_notifier(ptm_fd, CNotifier::Read)
|
, m_notifier(ptm_fd, CNotifier::Read)
|
||||||
|
, m_config(config)
|
||||||
{
|
{
|
||||||
set_frame_shape(FrameShape::Container);
|
set_frame_shape(FrameShape::Container);
|
||||||
set_frame_shadow(FrameShadow::Sunken);
|
set_frame_shadow(FrameShadow::Sunken);
|
||||||
set_frame_thickness(2);
|
set_frame_thickness(2);
|
||||||
|
|
||||||
m_cursor_blink_timer.set_interval(500);
|
dbgprintf("Terminal: Load config file from %s\n", m_config->file_name().characters());
|
||||||
|
m_cursor_blink_timer.set_interval(m_config->read_num_entry("Text",
|
||||||
|
"CursorBlinkInterval",
|
||||||
|
500));
|
||||||
m_cursor_blink_timer.on_timeout = [this] {
|
m_cursor_blink_timer.on_timeout = [this] {
|
||||||
m_cursor_blink_state = !m_cursor_blink_state;
|
m_cursor_blink_state = !m_cursor_blink_state;
|
||||||
update_cursor();
|
update_cursor();
|
||||||
};
|
};
|
||||||
|
|
||||||
set_font(Font::default_fixed_width_font());
|
auto font_entry = m_config->read_entry("Text", "Font", "default");
|
||||||
|
if (font_entry == "default")
|
||||||
|
set_font(Font::default_fixed_width_font());
|
||||||
|
else
|
||||||
|
set_font(Font::load_from_file(font_entry));
|
||||||
|
|
||||||
m_notifier.on_ready_to_read = [this]{
|
m_notifier.on_ready_to_read = [this]{
|
||||||
byte buffer[BUFSIZ];
|
byte buffer[BUFSIZ];
|
||||||
ssize_t nread = read(m_ptm_fd, buffer, sizeof(buffer));
|
ssize_t nread = read(m_ptm_fd, buffer, sizeof(buffer));
|
||||||
|
@ -53,7 +62,8 @@ Terminal::Terminal(int ptm_fd)
|
||||||
|
|
||||||
m_line_height = font().glyph_height() + m_line_spacing;
|
m_line_height = font().glyph_height() + m_line_spacing;
|
||||||
|
|
||||||
set_size(80, 25);
|
set_size(m_config->read_num_entry("Window", "Width", 80),
|
||||||
|
m_config->read_num_entry("Window", "Height", 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal::Line::Line(word columns)
|
Terminal::Line::Line(word columns)
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
#include <LibGUI/GFrame.h>
|
#include <LibGUI/GFrame.h>
|
||||||
#include <LibCore/CNotifier.h>
|
#include <LibCore/CNotifier.h>
|
||||||
#include <LibCore/CTimer.h>
|
#include <LibCore/CTimer.h>
|
||||||
|
#include <LibCore/CConfigFile.h>
|
||||||
|
|
||||||
class Font;
|
class Font;
|
||||||
|
|
||||||
class Terminal final : public GFrame {
|
class Terminal final : public GFrame {
|
||||||
public:
|
public:
|
||||||
explicit Terminal(int ptm_fd);
|
explicit Terminal(int ptm_fd, RetainPtr<CConfigFile> config);
|
||||||
virtual ~Terminal() override;
|
virtual ~Terminal() override;
|
||||||
|
|
||||||
void create_window();
|
void create_window();
|
||||||
|
@ -26,6 +27,8 @@ public:
|
||||||
|
|
||||||
void set_opacity(float);
|
void set_opacity(float);
|
||||||
|
|
||||||
|
RetainPtr<CConfigFile> config() const { return m_config; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef Vector<unsigned, 4> ParamVector;
|
typedef Vector<unsigned, 4> ParamVector;
|
||||||
|
|
||||||
|
@ -42,6 +45,7 @@ private:
|
||||||
void invalidate_cursor();
|
void invalidate_cursor();
|
||||||
void set_window_title(const String&);
|
void set_window_title(const String&);
|
||||||
|
|
||||||
|
|
||||||
void inject_string(const String&);
|
void inject_string(const String&);
|
||||||
void unimplemented_escape();
|
void unimplemented_escape();
|
||||||
void unimplemented_xterm_escape();
|
void unimplemented_xterm_escape();
|
||||||
|
@ -165,4 +169,5 @@ private:
|
||||||
int m_glyph_width { 0 };
|
int m_glyph_width { 0 };
|
||||||
|
|
||||||
CTimer m_cursor_blink_timer;
|
CTimer m_cursor_blink_timer;
|
||||||
|
RetainPtr<CConfigFile> m_config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,7 +94,8 @@ int main(int argc, char** argv)
|
||||||
window->set_double_buffering_enabled(false);
|
window->set_double_buffering_enabled(false);
|
||||||
window->set_should_exit_event_loop_on_close(true);
|
window->set_should_exit_event_loop_on_close(true);
|
||||||
|
|
||||||
Terminal terminal(ptm_fd);
|
RetainPtr<CConfigFile> config = CConfigFile::get_for_app("Terminal");
|
||||||
|
Terminal terminal(ptm_fd, config);
|
||||||
window->set_has_alpha_channel(true);
|
window->set_has_alpha_channel(true);
|
||||||
window->set_main_widget(&terminal);
|
window->set_main_widget(&terminal);
|
||||||
window->move_to(300, 300);
|
window->move_to(300, 300);
|
||||||
|
@ -119,6 +120,9 @@ int main(int argc, char** argv)
|
||||||
slider->set_range(0, 100);
|
slider->set_range(0, 100);
|
||||||
slider->set_value(100);
|
slider->set_value(100);
|
||||||
|
|
||||||
|
auto new_opacity = config->read_num_entry("Window", "Opacity", 255);
|
||||||
|
terminal.set_opacity((float)new_opacity / 255.0);
|
||||||
|
|
||||||
auto menubar = make<GMenuBar>();
|
auto menubar = make<GMenuBar>();
|
||||||
|
|
||||||
auto app_menu = make<GMenu>("Terminal");
|
auto app_menu = make<GMenu>("Terminal");
|
||||||
|
@ -136,6 +140,9 @@ int main(int argc, char** argv)
|
||||||
GFontDatabase::the().for_each_fixed_width_font([&] (const String& font_name) {
|
GFontDatabase::the().for_each_fixed_width_font([&] (const String& font_name) {
|
||||||
font_menu->add_action(GAction::create(font_name, [&terminal] (const GAction& action) {
|
font_menu->add_action(GAction::create(font_name, [&terminal] (const GAction& action) {
|
||||||
terminal.set_font(GFontDatabase::the().get_by_name(action.text()));
|
terminal.set_font(GFontDatabase::the().get_by_name(action.text()));
|
||||||
|
auto metadata = GFontDatabase::the().get_metadata_by_name(action.text());
|
||||||
|
terminal.config()->write_entry("Text", "Font", metadata.path);
|
||||||
|
terminal.config()->sync();
|
||||||
terminal.force_repaint();
|
terminal.force_repaint();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -149,5 +156,6 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
app.set_menubar(move(menubar));
|
app.set_menubar(move(menubar));
|
||||||
|
|
||||||
|
config->sync();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
7
Base/home/anon/IRCClient.ini
Normal file
7
Base/home/anon/IRCClient.ini
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[User]
|
||||||
|
Nickname=anon_seren1ty
|
||||||
|
|
||||||
|
[Connection]
|
||||||
|
Server=chat.freenode.net
|
||||||
|
Port=6667
|
||||||
|
AutoJoinChannels=#serenityos
|
2
Base/home/anon/Terminal.ini
Normal file
2
Base/home/anon/Terminal.ini
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[Window]
|
||||||
|
Opacity=150
|
|
@ -31,3 +31,6 @@ HighlightWindowBorder2=250,187,187
|
||||||
HighlightWindowTitle=255,255,255
|
HighlightWindowTitle=255,255,255
|
||||||
|
|
||||||
MenuSelectionColor=132,53,26
|
MenuSelectionColor=132,53,26
|
||||||
|
|
||||||
|
[Input]
|
||||||
|
DoubleClickSpeed=250
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
|
|
||||||
class Font;
|
class Font;
|
||||||
|
|
||||||
|
struct Metadata {
|
||||||
|
String path;
|
||||||
|
bool is_fixed_width;
|
||||||
|
int glyph_height;
|
||||||
|
};
|
||||||
|
|
||||||
class GFontDatabase {
|
class GFontDatabase {
|
||||||
public:
|
public:
|
||||||
static GFontDatabase& the();
|
static GFontDatabase& the();
|
||||||
|
@ -14,15 +20,13 @@ public:
|
||||||
void for_each_font(Function<void(const String&)>);
|
void for_each_font(Function<void(const String&)>);
|
||||||
void for_each_fixed_width_font(Function<void(const String&)>);
|
void for_each_fixed_width_font(Function<void(const String&)>);
|
||||||
|
|
||||||
|
Metadata get_metadata_by_name(const String& name) const {
|
||||||
|
return m_name_to_metadata.get(name);
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GFontDatabase();
|
GFontDatabase();
|
||||||
~GFontDatabase();
|
~GFontDatabase();
|
||||||
|
|
||||||
struct Metadata {
|
|
||||||
String path;
|
|
||||||
bool is_fixed_width;
|
|
||||||
int glyph_height;
|
|
||||||
};
|
|
||||||
|
|
||||||
HashMap<String, Metadata> m_name_to_metadata;
|
HashMap<String, Metadata> m_name_to_metadata;
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,7 +77,8 @@ void WSCompositor::compose()
|
||||||
if (wm.any_opaque_window_contains_rect(dirty_rect))
|
if (wm.any_opaque_window_contains_rect(dirty_rect))
|
||||||
continue;
|
continue;
|
||||||
m_back_painter->fill_rect(dirty_rect, wm.m_background_color);
|
m_back_painter->fill_rect(dirty_rect, wm.m_background_color);
|
||||||
m_back_painter->blit(dirty_rect.location(), *m_wallpaper, dirty_rect);
|
if (m_wallpaper)
|
||||||
|
m_back_painter->blit(dirty_rect.location(), *m_wallpaper, dirty_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto compose_window = [&] (WSWindow& window) -> IterationDecision {
|
auto compose_window = [&] (WSWindow& window) -> IterationDecision {
|
||||||
|
|
|
@ -38,10 +38,9 @@ WSWindowManager::WSWindowManager()
|
||||||
{
|
{
|
||||||
s_the = this;
|
s_the = this;
|
||||||
|
|
||||||
|
|
||||||
m_username = getlogin();
|
m_username = getlogin();
|
||||||
|
|
||||||
reload_config();
|
reload_config(false);
|
||||||
|
|
||||||
struct AppMenuItem {
|
struct AppMenuItem {
|
||||||
const char *binary_name;
|
const char *binary_name;
|
||||||
|
@ -63,13 +62,7 @@ WSWindowManager::WSWindowManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, WSMenuItem::Separator));
|
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, WSMenuItem::Separator));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 100, "640x480"));
|
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 100, "Reload WM Config File"));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 101, "800x600"));
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 102, "1024x768"));
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 103, "1280x720"));
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 104, "1440x900"));
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 105, "1920x1080"));
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 106, "2560x1440"));
|
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, WSMenuItem::Separator));
|
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, WSMenuItem::Separator));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 200, "About..."));
|
m_system_menu->add_item(make<WSMenuItem>(*m_system_menu, 200, "About..."));
|
||||||
m_system_menu->on_item_activation = [this, apps] (WSMenuItem& item) {
|
m_system_menu->on_item_activation = [this, apps] (WSMenuItem& item) {
|
||||||
|
@ -82,25 +75,7 @@ WSWindowManager::WSWindowManager()
|
||||||
}
|
}
|
||||||
switch (item.identifier()) {
|
switch (item.identifier()) {
|
||||||
case 100:
|
case 100:
|
||||||
set_resolution(640, 480);
|
reload_config(true);
|
||||||
break;
|
|
||||||
case 101:
|
|
||||||
set_resolution(800, 600);
|
|
||||||
break;
|
|
||||||
case 102:
|
|
||||||
set_resolution(1024, 768);
|
|
||||||
break;
|
|
||||||
case 103:
|
|
||||||
set_resolution(1280, 720);
|
|
||||||
break;
|
|
||||||
case 104:
|
|
||||||
set_resolution(1440, 900);
|
|
||||||
break;
|
|
||||||
case 105:
|
|
||||||
set_resolution(1920, 1080);
|
|
||||||
break;
|
|
||||||
case 106:
|
|
||||||
set_resolution(2560, 1440);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (item.identifier() == 200) {
|
if (item.identifier() == 200) {
|
||||||
|
@ -137,10 +112,16 @@ WSWindowManager::~WSWindowManager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::reload_config()
|
void WSWindowManager::reload_config(bool set_screen)
|
||||||
{
|
{
|
||||||
m_wm_config = CConfigFile::get_for_app("WindowManager");
|
m_wm_config = CConfigFile::get_for_app("WindowManager");
|
||||||
|
|
||||||
|
m_double_click_speed = m_wm_config->read_num_entry("Input", "DoubleClickSpeed", 250);
|
||||||
|
|
||||||
|
if (set_screen)
|
||||||
|
set_resolution(m_wm_config->read_num_entry("Screen", "Width", 1920),
|
||||||
|
m_wm_config->read_num_entry("Screen", "Height", 1080));
|
||||||
|
|
||||||
m_arrow_cursor = WSCursor::create(*GraphicsBitmap::load_from_file(m_wm_config->read_entry("Cursor", "Arrow", "")), { 2, 2 });
|
m_arrow_cursor = WSCursor::create(*GraphicsBitmap::load_from_file(m_wm_config->read_entry("Cursor", "Arrow", "")), { 2, 2 });
|
||||||
m_resize_horizontally_cursor = WSCursor::create(*GraphicsBitmap::load_from_file(m_wm_config->read_entry("Cursor", "ResizeH", "")));
|
m_resize_horizontally_cursor = WSCursor::create(*GraphicsBitmap::load_from_file(m_wm_config->read_entry("Cursor", "ResizeH", "")));
|
||||||
m_resize_vertically_cursor = WSCursor::create(*GraphicsBitmap::load_from_file(m_wm_config->read_entry("Cursor", "ResizeV", "")));
|
m_resize_vertically_cursor = WSCursor::create(*GraphicsBitmap::load_from_file(m_wm_config->read_entry("Cursor", "ResizeV", "")));
|
||||||
|
@ -669,7 +650,7 @@ void WSWindowManager::process_event_for_doubleclick(WSWindow& window, WSMouseEve
|
||||||
|
|
||||||
// FIXME: It might be a sensible idea to also add a distance travel check.
|
// FIXME: It might be a sensible idea to also add a distance travel check.
|
||||||
// If the pointer moves too far, it's not a double click.
|
// If the pointer moves too far, it's not a double click.
|
||||||
if (elapsed_since_last_click < 250) {
|
if (elapsed_since_last_click < m_double_click_speed) {
|
||||||
#if defined(DOUBLECLICK_DEBUG)
|
#if defined(DOUBLECLICK_DEBUG)
|
||||||
dbgprintf("Transforming MouseUp to MouseDoubleClick!\n");
|
dbgprintf("Transforming MouseUp to MouseDoubleClick!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
virtual ~WSWindowManager() override;
|
virtual ~WSWindowManager() override;
|
||||||
|
|
||||||
RetainPtr<CConfigFile> wm_config() const { return m_wm_config; }
|
RetainPtr<CConfigFile> wm_config() const { return m_wm_config; }
|
||||||
void set_wm_config(Retained<CConfigFile> conf) { m_wm_config = conf; }
|
void reload_config(bool);
|
||||||
|
|
||||||
void add_window(WSWindow&);
|
void add_window(WSWindow&);
|
||||||
void remove_window(WSWindow&);
|
void remove_window(WSWindow&);
|
||||||
|
@ -156,8 +156,6 @@ private:
|
||||||
void tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow&);
|
void tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow&);
|
||||||
void pick_new_active_window();
|
void pick_new_active_window();
|
||||||
|
|
||||||
void reload_config();
|
|
||||||
|
|
||||||
RetainPtr<WSCursor> m_arrow_cursor;
|
RetainPtr<WSCursor> m_arrow_cursor;
|
||||||
RetainPtr<WSCursor> m_resize_horizontally_cursor;
|
RetainPtr<WSCursor> m_resize_horizontally_cursor;
|
||||||
RetainPtr<WSCursor> m_resize_vertically_cursor;
|
RetainPtr<WSCursor> m_resize_vertically_cursor;
|
||||||
|
@ -199,6 +197,7 @@ private:
|
||||||
CElapsedTimer m_middle_click_clock;
|
CElapsedTimer m_middle_click_clock;
|
||||||
};
|
};
|
||||||
DoubleClickInfo m_double_click_info;
|
DoubleClickInfo m_double_click_info;
|
||||||
|
unsigned int m_double_click_speed;
|
||||||
|
|
||||||
WeakPtr<WSWindow> m_active_window;
|
WeakPtr<WSWindow> m_active_window;
|
||||||
WeakPtr<WSWindow> m_hovered_window;
|
WeakPtr<WSWindow> m_hovered_window;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue