mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:37:34 +00:00
WindowServer: Add locking and fix coalesced invalidation race.
WSWindowManager::invalidate() had a bug where it would mark the entire screen rect as dirty, but it wouldn't scheduled a deferred recompose. This would cause any subsequent calls to invalidate(Rect) to be coalesced with the pending compose, but the pending compose never happened.
This commit is contained in:
parent
431e7bf085
commit
9c1c885483
4 changed files with 13 additions and 9 deletions
|
@ -327,6 +327,5 @@ int Process::gui$menu_add_item(int menu_id, unsigned identifier, const char* tex
|
||||||
|
|
||||||
int Process::gui$set_menubar(int menubar_id)
|
int Process::gui$set_menubar(int menubar_id)
|
||||||
{
|
{
|
||||||
kprintf("gui$set_menubar %d\n", menubar_id);
|
|
||||||
return WSWindowManager::the().api$app_set_menubar(menubar_id);
|
return WSWindowManager::the().api$app_set_menubar(menubar_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ WSWindow& WSMenu::ensure_menu_window()
|
||||||
}
|
}
|
||||||
|
|
||||||
auto window = make<WSWindow>(*this);
|
auto window = make<WSWindow>(*this);
|
||||||
|
WSWindowLocker locker(*window);
|
||||||
window->set_rect(0, 0, width(), height());
|
window->set_rect(0, 0, width(), height());
|
||||||
m_menu_window = move(window);
|
m_menu_window = move(window);
|
||||||
draw();
|
draw();
|
||||||
|
@ -78,6 +79,7 @@ WSWindow& WSMenu::ensure_menu_window()
|
||||||
void WSMenu::draw()
|
void WSMenu::draw()
|
||||||
{
|
{
|
||||||
ASSERT(menu_window());
|
ASSERT(menu_window());
|
||||||
|
WSWindowLocker locker(*menu_window());
|
||||||
ASSERT(menu_window()->backing());
|
ASSERT(menu_window()->backing());
|
||||||
Painter painter(*menu_window()->backing());
|
Painter painter(*menu_window()->backing());
|
||||||
|
|
||||||
|
@ -103,6 +105,7 @@ void WSMenu::draw()
|
||||||
|
|
||||||
void WSMenu::on_window_message(WSMessage& message)
|
void WSMenu::on_window_message(WSMessage& message)
|
||||||
{
|
{
|
||||||
|
WSWindowLocker locker(*menu_window());
|
||||||
ASSERT(menu_window());
|
ASSERT(menu_window());
|
||||||
if (message.type() == WSMessage::MouseMove) {
|
if (message.type() == WSMessage::MouseMove) {
|
||||||
auto* item = item_at(static_cast<WSMouseEvent&>(message).position());
|
auto* item = item_at(static_cast<WSMouseEvent&>(message).position());
|
||||||
|
|
|
@ -54,7 +54,7 @@ int WSMessageLoop::exec()
|
||||||
auto* receiver = queued_message.receiver;
|
auto* receiver = queued_message.receiver;
|
||||||
auto& message = *queued_message.message;
|
auto& message = *queued_message.message;
|
||||||
#ifdef WSEVENTLOOP_DEBUG
|
#ifdef WSEVENTLOOP_DEBUG
|
||||||
dbgprintf("WSMessageLoop: receiver{%p} message %u (%s)\n", receiver, (unsigned)event.type(), event.name());
|
dbgprintf("WSMessageLoop: receiver{%p} message %u\n", receiver, (unsigned)message.type());
|
||||||
#endif
|
#endif
|
||||||
if (!receiver) {
|
if (!receiver) {
|
||||||
dbgprintf("WSMessage type %u with no receiver :(\n", message.type());
|
dbgprintf("WSMessage type %u with no receiver :(\n", message.type());
|
||||||
|
@ -71,7 +71,7 @@ void WSMessageLoop::post_message(WSMessageReceiver* receiver, OwnPtr<WSMessage>&
|
||||||
{
|
{
|
||||||
LOCKER(m_lock);
|
LOCKER(m_lock);
|
||||||
#ifdef WSEVENTLOOP_DEBUG
|
#ifdef WSEVENTLOOP_DEBUG
|
||||||
dbgprintf("WSMessageLoop::post_message: {%u} << receiver=%p, message=%p\n", m_queued_messages.size(), receiver, message.ptr());
|
dbgprintf("WSMessageLoop::post_message: {%u} << receiver=%p, message=%p (type=%u)\n", m_queued_messages.size(), receiver, message.ptr(), message->type());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (message->type() == WSMessage::WM_ClientFinishedPaint) {
|
if (message->type() == WSMessage::WM_ClientFinishedPaint) {
|
||||||
|
@ -127,6 +127,7 @@ void WSMessageLoop::wait_for_message()
|
||||||
params.timeout = nullptr;
|
params.timeout = nullptr;
|
||||||
else
|
else
|
||||||
params.timeout = &timeout;
|
params.timeout = &timeout;
|
||||||
|
|
||||||
int rc = m_server_process->sys$select(¶ms);
|
int rc = m_server_process->sys$select(¶ms);
|
||||||
memory_barrier();
|
memory_barrier();
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
|
|
@ -197,6 +197,9 @@ WSWindowManager::WSWindowManager()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: This ensures that the system menu has the correct dimensions.
|
||||||
|
set_current_menubar(nullptr);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
compose();
|
compose();
|
||||||
}
|
}
|
||||||
|
@ -209,15 +212,15 @@ template<typename Callback>
|
||||||
void WSWindowManager::for_each_active_menubar_menu(Callback callback)
|
void WSWindowManager::for_each_active_menubar_menu(Callback callback)
|
||||||
{
|
{
|
||||||
callback(*m_system_menu);
|
callback(*m_system_menu);
|
||||||
m_current_menubar->for_each_menu(move(callback));
|
if (m_current_menubar)
|
||||||
|
m_current_menubar->for_each_menu(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
|
void WSWindowManager::set_current_menubar(WSMenuBar* menubar)
|
||||||
{
|
{
|
||||||
LOCKER(m_lock);
|
LOCKER(m_lock);
|
||||||
if (m_current_menubar == menubar)
|
|
||||||
return;
|
|
||||||
m_current_menubar = menubar;
|
m_current_menubar = menubar;
|
||||||
|
dbgprintf("[WM] Current menubar is now %p\n", menubar);
|
||||||
int menu_margin = 16;
|
int menu_margin = 16;
|
||||||
Point next_menu_location { menu_margin / 2, 3 };
|
Point next_menu_location { menu_margin / 2, 3 };
|
||||||
for_each_active_menubar_menu([&] (WSMenu& menu) {
|
for_each_active_menubar_menu([&] (WSMenu& menu) {
|
||||||
|
@ -613,8 +616,6 @@ Rect WSWindowManager::menubar_rect() const
|
||||||
|
|
||||||
void WSWindowManager::draw_menubar()
|
void WSWindowManager::draw_menubar()
|
||||||
{
|
{
|
||||||
if (!m_current_menubar)
|
|
||||||
return;
|
|
||||||
m_back_painter->fill_rect(menubar_rect(), Color::LightGray);
|
m_back_painter->fill_rect(menubar_rect(), Color::LightGray);
|
||||||
m_back_painter->draw_line({ 0, menubar_rect().bottom() }, { menubar_rect().right(), menubar_rect().bottom() }, Color::White);
|
m_back_painter->draw_line({ 0, menubar_rect().bottom() }, { menubar_rect().right(), menubar_rect().bottom() }, Color::White);
|
||||||
for_each_active_menubar_menu([&] (WSMenu& menu) {
|
for_each_active_menubar_menu([&] (WSMenu& menu) {
|
||||||
|
@ -685,7 +686,7 @@ void WSWindowManager::invalidate()
|
||||||
{
|
{
|
||||||
LOCKER(m_lock);
|
LOCKER(m_lock);
|
||||||
m_dirty_rects.clear_with_capacity();
|
m_dirty_rects.clear_with_capacity();
|
||||||
m_dirty_rects.append(m_screen_rect);
|
invalidate(m_screen_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowManager::invalidate(const Rect& a_rect)
|
void WSWindowManager::invalidate(const Rect& a_rect)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue