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:
parent
5c25f0c4db
commit
37ab7b7a8c
8 changed files with 85 additions and 30 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
void addChild(GObject&);
|
||||
void removeChild(GObject&);
|
||||
|
||||
void deleteLater();
|
||||
void delete_later();
|
||||
|
||||
private:
|
||||
virtual void timerEvent(GTimerEvent&);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue