1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:58:11 +00:00

LibGUI: Implement destroying individual windows without exiting the process.

This commit is contained in:
Andreas Kling 2019-01-30 20:03:52 +01:00
parent 5c25f0c4db
commit 37ab7b7a8c
8 changed files with 85 additions and 30 deletions

View file

@ -80,6 +80,8 @@ int Process::gui$destroy_window(int window_id)
auto it = m_windows.find(window_id);
if (it == m_windows.end())
return -EBADWINDOW;
auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
WSMessageLoop::the().post_message((*it).value.leakPtr(), move(message), true);
m_windows.remove(window_id);
return 0;
}

View file

@ -9,6 +9,12 @@ int gui_create_window(const GUI_WindowParameters* params)
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int gui_destroy_window(int window_id)
{
int rc = syscall(SC_gui_destroy_window, window_id);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int gui_invalidate_window(int window_id, const GUI_Rect* rect)
{
int rc = syscall(SC_gui_invalidate_window, window_id, rect);

View file

@ -6,6 +6,7 @@
__BEGIN_DECLS
int gui_create_window(const GUI_WindowParameters*);
int gui_destroy_window(int window_id);
int gui_invalidate_window(int window_id, const GUI_Rect*);
int gui_notify_paint_finished(int window_id, const GUI_Rect*);
int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);

View file

@ -69,7 +69,7 @@ void GObject::stopTimer()
m_timerID = 0;
}
void GObject::deleteLater()
void GObject::delete_later()
{
GEventLoop::main().post_event(this, make<GEvent>(GEvent::DeferredDestroy));
}

View file

@ -27,7 +27,7 @@ public:
void addChild(GObject&);
void removeChild(GObject&);
void deleteLater();
void delete_later();
private:
virtual void timerEvent(GTimerEvent&);

View file

@ -29,10 +29,29 @@ GWindow* GWindow::from_window_id(int window_id)
GWindow::GWindow(GObject* parent)
: GObject(parent)
{
m_rect_when_windowless = { 100, 400, 140, 140 };
m_title_when_windowless = "GWindow";
}
GWindow::~GWindow()
{
hide();
}
void GWindow::close()
{
delete_later();
}
void GWindow::show()
{
if (m_window_id)
return;
GUI_WindowParameters wparams;
wparams.rect = { { 100, 400 }, { 140, 140 } };
wparams.rect = m_rect_when_windowless;
wparams.background_color = 0xffc0c0;
strcpy(wparams.title, "GWindow");
strcpy(wparams.title, m_title_when_windowless.characters());
m_window_id = gui_create_window(&wparams);
if (m_window_id < 0) {
perror("gui_create_window");
@ -40,34 +59,55 @@ GWindow::GWindow(GObject* parent)
}
windows().set(m_window_id, this);
update();
}
GWindow::~GWindow()
void GWindow::hide()
{
if (!m_window_id)
return;
windows().remove(m_window_id);
int rc = gui_destroy_window(m_window_id);
if (rc < 0) {
perror("gui_destroy_window");
exit(1);
}
}
void GWindow::set_title(String&& title)
{
dbgprintf("GWindow::set_title \"%s\"\n", title.characters());
m_title_when_windowless = title;
if (m_window_id) {
int rc = gui_set_window_title(m_window_id, title.characters(), title.length());
ASSERT(rc == 0);
if (rc < 0) {
perror("gui_set_window_title");
exit(1);
}
}
}
String GWindow::title() const
{
if (m_window_id) {
char buffer[256];
int rc = gui_get_window_title(m_window_id, buffer, sizeof(buffer));
ASSERT(rc >= 0);
return String(buffer, rc);
}
return m_title_when_windowless;
}
void GWindow::set_rect(const Rect& a_rect)
{
dbgprintf("GWindow::set_rect! %d,%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height());
m_rect_when_windowless = a_rect;
if (m_window_id) {
GUI_Rect rect = a_rect;
int rc = gui_set_window_rect(m_window_id, &rect);
ASSERT(rc == 0);
}
}
void GWindow::event(GEvent& event)
{
@ -99,9 +139,11 @@ void GWindow::event(GEvent& event)
if (rect.is_empty())
rect = m_main_widget->rect();
m_main_widget->event(*make<GPaintEvent>(rect));
if (m_window_id) {
GUI_Rect gui_rect = rect;
int rc = gui_notify_paint_finished(m_window_id, &gui_rect);
ASSERT(rc == 0);
}
return;
}
@ -126,16 +168,10 @@ bool GWindow::is_visible() const
return false;
}
void GWindow::close()
{
}
void GWindow::show()
{
}
void GWindow::update(const Rect& a_rect)
{
if (!m_window_id)
return;
GUI_Rect rect = a_rect;
int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
ASSERT(rc == 0);
@ -168,6 +204,7 @@ void GWindow::set_focused_widget(GWidget* widget)
void GWindow::set_global_cursor_tracking_widget(GWidget* widget)
{
ASSERT(m_window_id);
if (widget == m_global_cursor_tracking_widget.ptr())
return;
m_global_cursor_tracking_widget = widget ? widget->makeWeakPtr() : nullptr;

View file

@ -35,6 +35,8 @@ public:
bool is_visible() const;
bool is_active() const { return m_is_active; }
void show();
void hide();
void close();
GWidget* main_widget() { return m_main_widget; }
@ -45,8 +47,6 @@ public:
const GWidget* focused_widget() const { return m_focused_widget; }
void set_focused_widget(GWidget*);
void show();
void update(const Rect& = Rect());
void set_global_cursor_tracking_widget(GWidget*);
@ -55,10 +55,12 @@ public:
private:
RetainPtr<GraphicsBitmap> m_backing;
int m_window_id { -1 };
int m_window_id { 0 };
bool m_is_active { false };
GWidget* m_main_widget { nullptr };
GWidget* m_focused_widget { nullptr };
WeakPtr<GWidget> m_global_cursor_tracking_widget;
Rect m_rect_when_windowless;
String m_title_when_windowless;
};

View file

@ -63,11 +63,11 @@ GWindow* make_launcher_window()
{
auto* window = new GWindow;
window->set_title("Launcher");
window->set_rect({ 100, 400, 100, 200 });
window->set_rect({ 100, 400, 100, 230 });
auto* widget = new GWidget;
window->set_main_widget(widget);
widget->set_relative_rect({ 0, 0, 100, 200 });
widget->set_relative_rect({ 0, 0, 100, 230 });
auto* label = new GLabel(widget);
label->set_relative_rect({ 0, 0, 100, 20 });
@ -124,5 +124,12 @@ GWindow* make_launcher_window()
window->set_focused_widget(textbox);
auto* close_button = new GButton(widget);
close_button->set_relative_rect({ 5, 200, 90, 20 });
close_button->set_caption("Close");
close_button->on_click = [window] (GButton&) {
window->close();
};
return window;
}