mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	Rework the rendering model so that clients instantiate backing stores.
This makes interactive resizing work a lot better, althought it's still not perfect. There are still glitches and unpleasant flashes of zeroed memory.
This commit is contained in:
		
							parent
							
								
									e0b81ee4c9
								
							
						
					
					
						commit
						fa02d2a39b
					
				
					 17 changed files with 185 additions and 46 deletions
				
			
		|  | @ -760,3 +760,9 @@ void Terminal::force_repaint() | |||
|     m_need_full_flush = true; | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void Terminal::resize_event(GResizeEvent&) | ||||
| { | ||||
|     m_needs_background_fill = true; | ||||
|     force_repaint(); | ||||
| } | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ public: | |||
| private: | ||||
|     virtual void event(GEvent&) override; | ||||
|     virtual void paint_event(GPaintEvent&) override; | ||||
|     virtual void resize_event(GResizeEvent&) override; | ||||
|     virtual void keydown_event(GKeyEvent&) override; | ||||
|     virtual const char* class_name() const override { return "Terminal"; } | ||||
| 
 | ||||
|  |  | |||
|  | @ -78,8 +78,11 @@ int GEventLoop::exec() | |||
|     for (;;) { | ||||
|         if (m_exit_requested) | ||||
|             return m_exit_code; | ||||
|         if (m_queued_events.is_empty()) | ||||
|         process_unprocessed_messages(); | ||||
|         if (m_queued_events.is_empty()) { | ||||
|             wait_for_event(); | ||||
|             process_unprocessed_messages(); | ||||
|         } | ||||
|         Vector<QueuedEvent> events = move(m_queued_events); | ||||
|         for (auto& queued_event : events) { | ||||
|             auto* receiver = queued_event.receiver; | ||||
|  | @ -223,6 +226,7 @@ void GEventLoop::wait_for_event() | |||
|     struct timeval timeout = { 0, 0 }; | ||||
|     if (!m_timers.is_empty()) | ||||
|         get_next_timer_expiration(timeout); | ||||
|     ASSERT(m_unprocessed_messages.is_empty()); | ||||
|     int rc = select(max_fd + 1, &rfds, &wfds, nullptr, (m_queued_events.is_empty() && m_timers.is_empty()) ? nullptr : &timeout); | ||||
|     if (rc < 0) { | ||||
|         ASSERT_NOT_REACHED(); | ||||
|  | @ -260,9 +264,16 @@ void GEventLoop::wait_for_event() | |||
| 
 | ||||
|     bool success = drain_messages_from_server(); | ||||
|     ASSERT(success); | ||||
| } | ||||
| 
 | ||||
| void GEventLoop::process_unprocessed_messages() | ||||
| { | ||||
|     auto unprocessed_events = move(m_unprocessed_messages); | ||||
|     for (auto& event : unprocessed_events) { | ||||
|         if (event.type == WSAPI_ServerMessage::Type::Greeting) { | ||||
|             m_server_pid = event.greeting.server_pid; | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         if (event.type == WSAPI_ServerMessage::Error) { | ||||
|             dbgprintf("GEventLoop got error message from server\n"); | ||||
|  | @ -315,6 +326,9 @@ void GEventLoop::wait_for_event() | |||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (!m_unprocessed_messages.is_empty()) | ||||
|         process_unprocessed_messages(); | ||||
| } | ||||
| 
 | ||||
| bool GEventLoop::drain_messages_from_server() | ||||
|  |  | |||
|  | @ -39,9 +39,12 @@ public: | |||
| 
 | ||||
|     WSAPI_ServerMessage sync_request(const WSAPI_ClientMessage& request, WSAPI_ServerMessage::Type response_type); | ||||
| 
 | ||||
|     pid_t server_pid() const { return m_server_pid; } | ||||
| 
 | ||||
| private: | ||||
|     void wait_for_event(); | ||||
|     bool drain_messages_from_server(); | ||||
|     void process_unprocessed_messages(); | ||||
|     void handle_paint_event(const WSAPI_ServerMessage&, GWindow&); | ||||
|     void handle_resize_event(const WSAPI_ServerMessage&, GWindow&); | ||||
|     void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&); | ||||
|  | @ -64,8 +67,8 @@ private: | |||
|     bool m_running { false }; | ||||
|     bool m_exit_requested { false }; | ||||
|     int m_exit_code { 0 }; | ||||
| 
 | ||||
|     int m_next_timer_id { 1 }; | ||||
|     pid_t m_server_pid { 0 }; | ||||
| 
 | ||||
|     struct EventLoopTimer { | ||||
|         int timer_id { 0 }; | ||||
|  |  | |||
|  | @ -28,11 +28,14 @@ void GWidget::set_relative_rect(const Rect& rect) | |||
| { | ||||
|     if (rect == m_relative_rect) | ||||
|         return; | ||||
|     if (m_relative_rect.size() != rect.size()) { | ||||
|         auto event = make<GResizeEvent>(m_relative_rect.size(), rect.size()); | ||||
|         GEventLoop::main().post_event(this, move(event)); | ||||
|     } | ||||
|     bool size_changed = m_relative_rect.size() != rect.size(); | ||||
|     m_relative_rect = rect; | ||||
| 
 | ||||
|     if (size_changed) { | ||||
|         GResizeEvent resize_event(m_relative_rect.size(), rect.size()); | ||||
|         event(resize_event); | ||||
|     } | ||||
| 
 | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -169,9 +169,36 @@ void GWindow::event(GEvent& event) | |||
|             return; | ||||
|         auto& paint_event = static_cast<GPaintEvent&>(event); | ||||
|         auto rect = paint_event.rect(); | ||||
|         if (rect.is_empty()) | ||||
|         bool created_new_backing_store = !m_backing; | ||||
|         if (!m_backing) { | ||||
|             // NOTE: size() may change at any time since it's synchronously retrieved from the WindowServer.
 | ||||
|             ASSERT(GEventLoop::main().server_pid()); | ||||
|             Size new_backing_store_size = size(); | ||||
|             size_t size_in_bytes = new_backing_store_size.area() * sizeof(RGBA32); | ||||
|             void* buffer; | ||||
|             int shared_buffer_id = create_shared_buffer(GEventLoop::main().server_pid(), size_in_bytes, (void**)&buffer); | ||||
|             ASSERT(shared_buffer_id >= 0); | ||||
|             ASSERT(buffer); | ||||
|             ASSERT(buffer != (void*)-1); | ||||
|             m_backing = GraphicsBitmap::create_with_shared_buffer( | ||||
|                         m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32, | ||||
|                         shared_buffer_id, | ||||
|                         new_backing_store_size, (RGBA32*)buffer); | ||||
|         } | ||||
|         if (rect.is_empty() || created_new_backing_store) | ||||
|             rect = m_main_widget->rect(); | ||||
|         m_main_widget->event(*make<GPaintEvent>(rect)); | ||||
|         if (created_new_backing_store) { | ||||
|             WSAPI_ClientMessage message; | ||||
|             message.type = WSAPI_ClientMessage::Type::SetWindowBackingStore; | ||||
|             message.window_id = m_window_id; | ||||
|             message.backing.bpp = 32; | ||||
|             message.backing.pitch = m_backing->pitch(); | ||||
|             message.backing.shared_buffer_id = m_backing->shared_buffer_id(); | ||||
|             message.backing.has_alpha_channel = m_backing->has_alpha_channel(); | ||||
|             message.backing.size = m_backing->size(); | ||||
|             GEventLoop::main().post_message_to_server(message); | ||||
|         } | ||||
|         if (m_window_id) { | ||||
|             WSAPI_ClientMessage message; | ||||
|             message.type = WSAPI_ClientMessage::Type::DidFinishPainting; | ||||
|  | @ -210,6 +237,7 @@ void GWindow::event(GEvent& event) | |||
|     } | ||||
| 
 | ||||
|     if (event.type() == GEvent::Resize) { | ||||
|         m_backing = nullptr; | ||||
|         m_pending_paint_event_rects.clear(); | ||||
|         m_rect_when_windowless = { { }, static_cast<GResizeEvent&>(event).size() }; | ||||
|         m_main_widget->set_relative_rect({ { }, static_cast<GResizeEvent&>(event).size() }); | ||||
|  | @ -233,7 +261,7 @@ void GWindow::update(const Rect& a_rect) | |||
| #ifdef UPDATE_COALESCING_DEBUG | ||||
|             dbgprintf("Ignoring %s since it's contained by pending rect %s\n", a_rect.to_string().characters(), pending_rect.to_string().characters()); | ||||
| #endif | ||||
|             return; | ||||
|             //return;
 | ||||
|         } | ||||
|     } | ||||
|     m_pending_paint_event_rects.append(a_rect); | ||||
|  |  | |||
|  | @ -68,6 +68,8 @@ public: | |||
|     const GWidget* hovered_widget() const { return m_hovered_widget.ptr(); } | ||||
|     void set_hovered_widget(GWidget*); | ||||
| 
 | ||||
|     GraphicsBitmap* backing() { return m_backing.ptr(); } | ||||
| 
 | ||||
| private: | ||||
|     virtual const char* class_name() const override { return "GWindow"; } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,17 +25,9 @@ Painter::Painter(GraphicsBitmap& bitmap) | |||
| Painter::Painter(GWidget& widget) | ||||
|     : m_font(&widget.font()) | ||||
| { | ||||
|     WSAPI_ClientMessage request; | ||||
|     request.type = WSAPI_ClientMessage::Type::GetWindowBackingStore; | ||||
|     request.window_id = widget.window()->window_id(); | ||||
|     auto response = GEventLoop::main().sync_request(request, WSAPI_ServerMessage::DidGetWindowBackingStore); | ||||
| 
 | ||||
|     m_target = GraphicsBitmap::create_with_shared_buffer( | ||||
|                    response.backing.has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32, | ||||
|                    response.backing.shared_buffer_id, | ||||
|                    response.backing.size); | ||||
|     ASSERT(m_target); | ||||
|     m_window = widget.window(); | ||||
|     m_target = m_window->backing(); | ||||
|     ASSERT(m_target); | ||||
|     m_translation.move_by(widget.window_relative_rect().location()); | ||||
|     // NOTE: m_clip_rect is in Window coordinates since we are painting into its backing store.
 | ||||
|     m_clip_rect = widget.window_relative_rect(); | ||||
|  | @ -236,7 +228,8 @@ void Painter::blit_with_opacity(const Point& position, const GraphicsBitmap& sou | |||
| 
 | ||||
|     byte alpha = 255 * opacity; | ||||
| 
 | ||||
|     Rect dst_rect(position, src_rect.size()); | ||||
|     Rect safe_src_rect = Rect::intersection(src_rect, source.rect()); | ||||
|     Rect dst_rect(position, safe_src_rect.size()); | ||||
|     dst_rect.move_by(m_translation); | ||||
|     auto clipped_rect = Rect::intersection(dst_rect, m_clip_rect); | ||||
|     if (clipped_rect.is_empty()) | ||||
|  | @ -265,7 +258,8 @@ void Painter::blit_with_opacity(const Point& position, const GraphicsBitmap& sou | |||
| void Painter::blit_with_alpha(const Point& position, const GraphicsBitmap& source, const Rect& src_rect) | ||||
| { | ||||
|     ASSERT(source.has_alpha_channel()); | ||||
|     Rect dst_rect(position, src_rect.size()); | ||||
|     Rect safe_src_rect = Rect::intersection(src_rect, source.rect()); | ||||
|     Rect dst_rect(position, safe_src_rect.size()); | ||||
|     dst_rect.move_by(m_translation); | ||||
|     auto clipped_rect = Rect::intersection(dst_rect, m_clip_rect); | ||||
|     if (clipped_rect.is_empty()) | ||||
|  | @ -298,7 +292,9 @@ void Painter::blit(const Point& position, const GraphicsBitmap& source, const Re | |||
| { | ||||
|     if (source.has_alpha_channel()) | ||||
|         return blit_with_alpha(position, source, src_rect); | ||||
|     Rect dst_rect(position, src_rect.size()); | ||||
|     auto safe_src_rect = Rect::intersection(src_rect, source.rect()); | ||||
|     ASSERT(source.rect().contains(safe_src_rect)); | ||||
|     Rect dst_rect(position, safe_src_rect.size()); | ||||
|     dst_rect.move_by(m_translation); | ||||
|     auto clipped_rect = Rect::intersection(dst_rect, m_clip_rect); | ||||
|     if (clipped_rect.is_empty()) | ||||
|  |  | |||
|  | @ -84,6 +84,7 @@ struct WSAPI_ServerMessage { | |||
|         DidGetWindowTitle, | ||||
|         DidGetWindowRect, | ||||
|         DidGetWindowBackingStore, | ||||
|         Greeting, | ||||
|     }; | ||||
|     Type type { Invalid }; | ||||
|     int window_id { -1 }; | ||||
|  | @ -91,6 +92,9 @@ struct WSAPI_ServerMessage { | |||
|     char text[256]; | ||||
| 
 | ||||
|     union { | ||||
|         struct { | ||||
|             int server_pid; | ||||
|         } greeting; | ||||
|         struct { | ||||
|             WSAPI_Rect rect; | ||||
|             WSAPI_Rect old_rect; | ||||
|  | @ -148,6 +152,7 @@ struct WSAPI_ClientMessage { | |||
|         GetWindowBackingStore, | ||||
|         SetGlobalCursorTracking, | ||||
|         SetWindowOpacity, | ||||
|         SetWindowBackingStore, | ||||
|     }; | ||||
|     Type type { Invalid }; | ||||
|     int window_id { -1 }; | ||||
|  | @ -166,6 +171,13 @@ struct WSAPI_ClientMessage { | |||
|             bool has_alpha_channel; | ||||
|             float opacity; | ||||
|         } window; | ||||
|         struct { | ||||
|             WSAPI_Size size; | ||||
|             size_t bpp; | ||||
|             size_t pitch; | ||||
|             int shared_buffer_id; | ||||
|             bool has_alpha_channel; | ||||
|         } backing; | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -44,6 +44,11 @@ WSClientConnection::WSClientConnection(int fd) | |||
|     if (!s_connections) | ||||
|         s_connections = new HashMap<int, WSClientConnection*>; | ||||
|     s_connections->set(m_client_id, this); | ||||
| 
 | ||||
|     WSAPI_ServerMessage message; | ||||
|     message.type = WSAPI_ServerMessage::Type::Greeting; | ||||
|     message.greeting.server_pid = getpid(); | ||||
|     post_message(message); | ||||
| } | ||||
| 
 | ||||
| WSClientConnection::~WSClientConnection() | ||||
|  | @ -358,7 +363,13 @@ void WSClientConnection::handle_request(WSAPIDidFinishPaintingNotification& requ | |||
|         return; | ||||
|     } | ||||
|     auto& window = *(*it).value; | ||||
| 
 | ||||
|     if (!window.has_painted_since_last_resize()) { | ||||
|         if (window.last_lazy_resize_rect().size() == request.rect().size()) { | ||||
|             window.set_has_painted_since_last_resize(true); | ||||
|             WSMessageLoop::the().post_message(&window, make<WSResizeEvent>(window.last_lazy_resize_rect(), window.rect())); | ||||
|         } | ||||
|     } | ||||
|     WSWindowManager::the().invalidate(window, request.rect()); | ||||
| } | ||||
| 
 | ||||
|  | @ -371,7 +382,7 @@ void WSClientConnection::handle_request(WSAPIGetWindowBackingStoreRequest& reque | |||
|         return; | ||||
|     } | ||||
|     auto& window = *(*it).value; | ||||
|     auto* backing_store = window.backing(); | ||||
|     auto* backing_store = window.backing_store(); | ||||
| 
 | ||||
|     WSAPI_ServerMessage response; | ||||
|     response.type = WSAPI_ServerMessage::Type::DidGetWindowBackingStore; | ||||
|  | @ -384,6 +395,25 @@ void WSClientConnection::handle_request(WSAPIGetWindowBackingStoreRequest& reque | |||
|     post_message(response); | ||||
| } | ||||
| 
 | ||||
| void WSClientConnection::handle_request(WSAPISetWindowBackingStoreRequest& request) | ||||
| { | ||||
|     int window_id = request.window_id(); | ||||
|     auto it = m_windows.find(window_id); | ||||
|     if (it == m_windows.end()) { | ||||
|         post_error("Bad window ID"); | ||||
|         return; | ||||
|     } | ||||
|     auto& window = *(*it).value; | ||||
|     auto backing_store = GraphicsBitmap::create_with_shared_buffer( | ||||
|         request.has_alpha_channel() ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32, | ||||
|         request.shared_buffer_id(), | ||||
|         request.size()); | ||||
|     if (!backing_store) | ||||
|         return; | ||||
|     window.set_backing_store(move(backing_store)); | ||||
|     window.invalidate(); | ||||
| } | ||||
| 
 | ||||
| void WSClientConnection::handle_request(WSAPISetGlobalCursorTrackingRequest& request) | ||||
| { | ||||
|     int window_id = request.window_id(); | ||||
|  | @ -437,6 +467,8 @@ void WSClientConnection::on_request(WSAPIClientRequest& request) | |||
|         return handle_request(static_cast<WSAPISetGlobalCursorTrackingRequest&>(request)); | ||||
|     case WSMessage::APISetWindowOpacityRequest: | ||||
|         return handle_request(static_cast<WSAPISetWindowOpacityRequest&>(request)); | ||||
|     case WSMessage::APISetWindowBackingStoreRequest: | ||||
|         return handle_request(static_cast<WSAPISetWindowBackingStoreRequest&>(request)); | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|  |  | |||
|  | @ -51,6 +51,7 @@ private: | |||
|     void handle_request(WSAPIInvalidateRectRequest&); | ||||
|     void handle_request(WSAPIDidFinishPaintingNotification&); | ||||
|     void handle_request(WSAPIGetWindowBackingStoreRequest&); | ||||
|     void handle_request(WSAPISetWindowBackingStoreRequest&); | ||||
|     void handle_request(WSAPISetGlobalCursorTrackingRequest&); | ||||
|     void handle_request(WSAPISetWindowOpacityRequest&); | ||||
| 
 | ||||
|  |  | |||
|  | @ -76,8 +76,8 @@ WSWindow& WSMenu::ensure_menu_window() | |||
| void WSMenu::draw() | ||||
| { | ||||
|     ASSERT(menu_window()); | ||||
|     ASSERT(menu_window()->backing()); | ||||
|     Painter painter(*menu_window()->backing()); | ||||
|     ASSERT(menu_window()->backing_store()); | ||||
|     Painter painter(*menu_window()->backing_store()); | ||||
| 
 | ||||
|     Rect rect { { }, menu_window()->size() }; | ||||
|     painter.draw_rect(rect, Color::White); | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ public: | |||
|         APIGetWindowBackingStoreRequest, | ||||
|         APISetGlobalCursorTrackingRequest, | ||||
|         APISetWindowOpacityRequest, | ||||
|         APISetWindowBackingStoreRequest, | ||||
|         __End_API_Client_Requests, | ||||
|     }; | ||||
| 
 | ||||
|  | @ -277,6 +278,38 @@ private: | |||
|     float m_opacity { 0 }; | ||||
| }; | ||||
| 
 | ||||
| class WSAPISetWindowBackingStoreRequest final : public WSAPIClientRequest { | ||||
| public: | ||||
|     explicit WSAPISetWindowBackingStoreRequest(int client_id, int window_id, int shared_buffer_id, const Size& size, size_t bpp, size_t pitch, bool has_alpha_channel) | ||||
|         : WSAPIClientRequest(WSMessage::APISetWindowBackingStoreRequest, client_id) | ||||
|         , m_client_id(client_id) | ||||
|         , m_window_id(window_id) | ||||
|         , m_shared_buffer_id(shared_buffer_id) | ||||
|         , m_size(size) | ||||
|         , m_bpp(bpp) | ||||
|         , m_pitch(pitch) | ||||
|         , m_has_alpha_channel(has_alpha_channel) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     int client_id() const { return m_client_id; } | ||||
|     int window_id() const { return m_window_id; } | ||||
|     int shared_buffer_id() const { return m_shared_buffer_id; } | ||||
|     Size size() const { return m_size; } | ||||
|     size_t bpp() const { return m_bpp; } | ||||
|     size_t pitch() const { return m_pitch; } | ||||
|     bool has_alpha_channel() const { return m_has_alpha_channel; } | ||||
| 
 | ||||
| private: | ||||
|     int m_client_id { 0 }; | ||||
|     int m_window_id { 0 }; | ||||
|     int m_shared_buffer_id { 0 }; | ||||
|     Size m_size; | ||||
|     size_t m_bpp; | ||||
|     size_t m_pitch; | ||||
|     bool m_has_alpha_channel; | ||||
| }; | ||||
| 
 | ||||
| class WSAPISetWindowRectRequest final : public WSAPIClientRequest { | ||||
| public: | ||||
|     explicit WSAPISetWindowRectRequest(int client_id, int window_id, const Rect& rect) | ||||
|  |  | |||
|  | @ -330,6 +330,9 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess | |||
|     case WSAPI_ClientMessage::Type::GetWindowBackingStore: | ||||
|         post_message(client, make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id)); | ||||
|         break; | ||||
|     case WSAPI_ClientMessage::Type::SetWindowBackingStore: | ||||
|         post_message(client, make<WSAPISetWindowBackingStoreRequest>(client_id, message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel)); | ||||
|         break; | ||||
|     case WSAPI_ClientMessage::Type::SetGlobalCursorTracking: | ||||
|         post_message(client, make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.window_id, message.value)); | ||||
|         break; | ||||
|  |  | |||
|  | @ -36,18 +36,13 @@ void WSWindow::set_title(String&& title) | |||
| void WSWindow::set_rect(const Rect& rect) | ||||
| { | ||||
|     Rect old_rect; | ||||
|     if (!m_client && !m_menu) | ||||
|         return; | ||||
|     ASSERT(m_client || m_menu); | ||||
|     if (m_rect == rect) | ||||
|         return; | ||||
|     old_rect = m_rect; | ||||
|     m_rect = rect; | ||||
|     if (!m_backing || old_rect.size() != rect.size()) { | ||||
|         if (m_menu) | ||||
|             m_backing = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, m_rect.size()); | ||||
|         else if (m_client) { | ||||
|             m_backing = m_client->create_shared_bitmap(m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32, m_rect.size()); | ||||
|         } | ||||
|     if (m_menu && (!m_backing_store || old_rect.size() != rect.size())) { | ||||
|         m_backing_store = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, m_rect.size()); | ||||
|     } | ||||
|     WSWindowManager::the().notify_rect_changed(*this, old_rect, rect); | ||||
| } | ||||
|  |  | |||
|  | @ -55,7 +55,8 @@ public: | |||
| 
 | ||||
|     virtual void on_message(WSMessage&) override; | ||||
| 
 | ||||
|     GraphicsBitmap* backing() { return m_backing.ptr(); } | ||||
|     GraphicsBitmap* backing_store() { return m_backing_store.ptr(); } | ||||
|     void set_backing_store(RetainPtr<GraphicsBitmap>&& backing_store) { m_backing_store = move(backing_store); } | ||||
| 
 | ||||
|     void set_global_cursor_tracking_enabled(bool); | ||||
|     bool global_cursor_tracking() const { return m_global_cursor_tracking_enabled; } | ||||
|  | @ -63,8 +64,11 @@ public: | |||
|     bool has_alpha_channel() const { return m_has_alpha_channel; } | ||||
|     void set_has_alpha_channel(bool value) { m_has_alpha_channel = value; } | ||||
| 
 | ||||
|     void set_has_painted_since_last_resize(bool b) { m_has_painted_since_last_resize = b; } | ||||
|     void set_last_lazy_resize_rect(const Rect& rect) { m_last_lazy_resize_rect = rect; } | ||||
|     Rect last_lazy_resize_rect() const { return m_last_lazy_resize_rect; } | ||||
| 
 | ||||
|     bool has_painted_since_last_resize() const { return m_has_painted_since_last_resize; } | ||||
|     void set_has_painted_since_last_resize(bool b) { m_has_painted_since_last_resize = b; } | ||||
| 
 | ||||
|     // For InlineLinkedList.
 | ||||
|     // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
 | ||||
|  | @ -81,7 +85,8 @@ private: | |||
|     bool m_has_alpha_channel { false }; | ||||
|     bool m_has_painted_since_last_resize { false }; | ||||
|     WSMenu* m_menu { nullptr }; | ||||
|     RetainPtr<GraphicsBitmap> m_backing; | ||||
|     RetainPtr<GraphicsBitmap> m_backing_store; | ||||
|     int m_window_id { -1 }; | ||||
|     float m_opacity { 1 }; | ||||
|     Rect m_last_lazy_resize_rect; | ||||
| }; | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| //#define DEBUG_COUNTERS
 | ||||
| //#define DEBUG_WID_IN_TITLE_BAR
 | ||||
| #define RESIZE_DEBUG | ||||
| #define USE_WALLPAPER | ||||
| 
 | ||||
| static const int window_titlebar_height = 16; | ||||
| 
 | ||||
|  | @ -175,8 +176,10 @@ WSWindowManager::WSWindowManager() | |||
|     m_cursor_bitmap_inner = CharacterBitmap::create_from_ascii(cursor_bitmap_inner_ascii, 12, 17); | ||||
|     m_cursor_bitmap_outer = CharacterBitmap::create_from_ascii(cursor_bitmap_outer_ascii, 12, 17); | ||||
| 
 | ||||
| #ifdef USE_WALLPAPER | ||||
|     m_wallpaper_path = "/res/wallpapers/cool.rgb"; | ||||
|     m_wallpaper = GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, m_wallpaper_path, { 1024, 768 }); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef KERNEL | ||||
|     ProcFS::the().add_sys_bool("wm_flash_flush", m_flash_flush); | ||||
|  | @ -495,6 +498,7 @@ void WSWindowManager::start_window_resize(WSWindow& window, WSMouseEvent& event) | |||
|     m_resize_window = window.make_weak_ptr();; | ||||
|     m_resize_origin = event.position(); | ||||
|     m_resize_window_original_rect = window.rect(); | ||||
|     m_resize_window->set_has_painted_since_last_resize(true); | ||||
|     invalidate(window); | ||||
| } | ||||
| 
 | ||||
|  | @ -532,6 +536,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ | |||
|             printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr()); | ||||
| #endif | ||||
|             WSMessageLoop::the().post_message(m_resize_window.ptr(), make<WSResizeEvent>(m_resize_window->rect(), m_resize_window->rect())); | ||||
|             invalidate(*m_resize_window); | ||||
|             m_resize_window = nullptr; | ||||
|             return; | ||||
|         } | ||||
|  | @ -541,20 +546,20 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ | |||
|             int dx = event.x() - m_resize_origin.x(); | ||||
|             int dy = event.y() - m_resize_origin.y(); | ||||
|             auto new_rect = m_resize_window_original_rect; | ||||
|             new_rect.set_width(new_rect.width() + dx); | ||||
|             new_rect.set_height(new_rect.height() + dy); | ||||
|             new_rect.set_width(max(50, new_rect.width() + dx)); | ||||
|             new_rect.set_height(max(50, new_rect.height() + dy)); | ||||
|             if (m_resize_window->rect() == new_rect) | ||||
|                 return; | ||||
| #ifdef RESIZE_DEBUG | ||||
|             dbgprintf("[WM] Resizing [original: %s] now: %s\n", | ||||
|                 m_resize_window_original_rect.to_string().characters(), | ||||
|                 new_rect.to_string().characters()); | ||||
| #endif | ||||
|             if (new_rect.width() < 50) | ||||
|                 new_rect.set_width(50); | ||||
|             if (new_rect.height() < 50) | ||||
|                 new_rect.set_height(50); | ||||
|             m_resize_window->set_rect(new_rect); | ||||
|             if (m_resize_window->has_painted_since_last_resize()) { | ||||
|                 m_resize_window->set_has_painted_since_last_resize(false); | ||||
|                 dbgprintf("I'm gonna wait for %s\n", new_rect.to_string().characters()); | ||||
|                 m_resize_window->set_last_lazy_resize_rect(new_rect); | ||||
|                 WSMessageLoop::the().post_message(m_resize_window.ptr(), make<WSResizeEvent>(old_rect, new_rect)); | ||||
|             } | ||||
|             return; | ||||
|  | @ -709,8 +714,8 @@ void WSWindowManager::compose() | |||
|     } | ||||
| 
 | ||||
|     for_each_visible_window_from_back_to_front([&] (WSWindow& window) { | ||||
|         RetainPtr<GraphicsBitmap> backing = window.backing(); | ||||
|         if (!backing) | ||||
|         RetainPtr<GraphicsBitmap> backing_store = window.backing_store(); | ||||
|         if (!backing_store) | ||||
|             return IterationDecision::Continue; | ||||
|         if (!any_dirty_rect_intersects_window(window)) | ||||
|             return IterationDecision::Continue; | ||||
|  | @ -725,9 +730,9 @@ void WSWindowManager::compose() | |||
|             auto dst = window.position(); | ||||
|             dst.move_by(dirty_rect_in_window_coordinates.location()); | ||||
|             if (window.opacity() == 1.0f) | ||||
|                 m_back_painter->blit(dst, *backing, dirty_rect_in_window_coordinates); | ||||
|                 m_back_painter->blit(dst, *backing_store, dirty_rect_in_window_coordinates); | ||||
|             else | ||||
|                 m_back_painter->blit_with_opacity(dst, *backing, dirty_rect_in_window_coordinates, window.opacity()); | ||||
|                 m_back_painter->blit_with_opacity(dst, *backing_store, dirty_rect_in_window_coordinates, window.opacity()); | ||||
|             m_back_painter->clear_clip_rect(); | ||||
|         } | ||||
|         m_back_painter->clear_clip_rect(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling