1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:28: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); auto it = m_windows.find(window_id);
if (it == m_windows.end()) if (it == m_windows.end())
return -EBADWINDOW; return -EBADWINDOW;
auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
WSMessageLoop::the().post_message((*it).value.leakPtr(), move(message), true);
m_windows.remove(window_id); m_windows.remove(window_id);
return 0; return 0;
} }

View file

@ -9,6 +9,12 @@ int gui_create_window(const GUI_WindowParameters* params)
__RETURN_WITH_ERRNO(rc, rc, -1); __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 gui_invalidate_window(int window_id, const GUI_Rect* rect)
{ {
int rc = syscall(SC_gui_invalidate_window, window_id, rect); int rc = syscall(SC_gui_invalidate_window, window_id, rect);

View file

@ -6,6 +6,7 @@
__BEGIN_DECLS __BEGIN_DECLS
int gui_create_window(const GUI_WindowParameters*); 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_invalidate_window(int window_id, const GUI_Rect*);
int gui_notify_paint_finished(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*); int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);

View file

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

View file

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

View file

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

View file

@ -35,6 +35,8 @@ public:
bool is_visible() const; bool is_visible() const;
bool is_active() const { return m_is_active; } bool is_active() const { return m_is_active; }
void show();
void hide();
void close(); void close();
GWidget* main_widget() { return m_main_widget; } GWidget* main_widget() { return m_main_widget; }
@ -45,8 +47,6 @@ public:
const GWidget* focused_widget() const { return m_focused_widget; } const GWidget* focused_widget() const { return m_focused_widget; }
void set_focused_widget(GWidget*); void set_focused_widget(GWidget*);
void show();
void update(const Rect& = Rect()); void update(const Rect& = Rect());
void set_global_cursor_tracking_widget(GWidget*); void set_global_cursor_tracking_widget(GWidget*);
@ -55,10 +55,12 @@ public:
private: private:
RetainPtr<GraphicsBitmap> m_backing; RetainPtr<GraphicsBitmap> m_backing;
int m_window_id { -1 }; int m_window_id { 0 };
bool m_is_active { false }; bool m_is_active { false };
GWidget* m_main_widget { nullptr }; GWidget* m_main_widget { nullptr };
GWidget* m_focused_widget { nullptr }; GWidget* m_focused_widget { nullptr };
WeakPtr<GWidget> m_global_cursor_tracking_widget; 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; auto* window = new GWindow;
window->set_title("Launcher"); window->set_title("Launcher");
window->set_rect({ 100, 400, 100, 200 }); window->set_rect({ 100, 400, 100, 230 });
auto* widget = new GWidget; auto* widget = new GWidget;
window->set_main_widget(widget); 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); auto* label = new GLabel(widget);
label->set_relative_rect({ 0, 0, 100, 20 }); label->set_relative_rect({ 0, 0, 100, 20 });
@ -124,5 +124,12 @@ GWindow* make_launcher_window()
window->set_focused_widget(textbox); 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; return window;
} }