mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:12:43 +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,33 +59,54 @@ 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
	
	 Andreas Kling
						Andreas Kling