mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 12:07: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
|
@ -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;
|
||||
window.set_has_painted_since_last_resize(true);
|
||||
|
||||
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