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:
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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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*);
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue