diff --git a/userspace/libraries/LibGUI/Window.cpp b/userspace/libraries/LibGUI/Window.cpp index 0b3339e8..a5661961 100644 --- a/userspace/libraries/LibGUI/Window.cpp +++ b/userspace/libraries/LibGUI/Window.cpp @@ -295,6 +295,10 @@ namespace LibGUI m_resize_window_event_callback(); break; } + case PacketType::WindowShownEvent: + if (m_window_shown_event_callback) + m_window_shown_event_callback(TRY_OR_BREAK(EventPacket::WindowShownEvent::deserialize(packet_data.span())).event); + break; case PacketType::KeyEvent: if (m_key_event_callback) m_key_event_callback(TRY_OR_BREAK(EventPacket::KeyEvent::deserialize(packet_data.span())).event); diff --git a/userspace/libraries/LibGUI/include/LibGUI/Packet.h b/userspace/libraries/LibGUI/include/LibGUI/Packet.h index 59cb5206..0ba2e5b8 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Packet.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Packet.h @@ -172,6 +172,7 @@ namespace LibGUI DestroyWindowEvent, CloseWindowEvent, ResizeWindowEvent, + WindowShownEvent, KeyEvent, MouseButtonEvent, MouseMoveEvent, @@ -189,6 +190,7 @@ namespace LibGUI bool rounded_corners; bool alpha_channel; bool resizable; + bool shown; }; DEFINE_PACKET( @@ -271,6 +273,14 @@ namespace LibGUI long, smo_key ); + DEFINE_PACKET_EXTRA( + WindowShownEvent, + struct event_t { + bool shown; + }, + event_t, event + ); + DEFINE_PACKET_EXTRA( KeyEvent, using event_t = LibInput::KeyEvent, diff --git a/userspace/libraries/LibGUI/include/LibGUI/Window.h b/userspace/libraries/LibGUI/include/LibGUI/Window.h index 4ac478a5..c73f9dda 100644 --- a/userspace/libraries/LibGUI/include/LibGUI/Window.h +++ b/userspace/libraries/LibGUI/include/LibGUI/Window.h @@ -24,6 +24,7 @@ namespace LibGUI .rounded_corners = true, .alpha_channel = false, .resizable = false, + .shown = true, }; public: @@ -66,6 +67,7 @@ namespace LibGUI void set_mouse_button_event_callback(BAN::Function callback) { m_mouse_button_event_callback = callback; } void set_mouse_move_event_callback(BAN::Function callback) { m_mouse_move_event_callback = callback; } void set_mouse_scroll_event_callback(BAN::Function callback) { m_mouse_scroll_event_callback = callback; } + void set_window_shown_event_callback(BAN::Function callback) { m_window_shown_event_callback = callback; } int server_fd() const { return m_server_fd; } @@ -96,6 +98,7 @@ namespace LibGUI BAN::Function m_socket_error_callback; BAN::Function m_close_window_event_callback; BAN::Function m_resize_window_event_callback; + BAN::Function m_window_shown_event_callback; BAN::Function m_key_event_callback; BAN::Function m_mouse_button_event_callback; BAN::Function m_mouse_move_event_callback; diff --git a/userspace/programs/WindowServer/WindowServer.cpp b/userspace/programs/WindowServer/WindowServer.cpp index 56103af6..8fc12804 100644 --- a/userspace/programs/WindowServer/WindowServer.cpp +++ b/userspace/programs/WindowServer/WindowServer.cpp @@ -108,21 +108,16 @@ void WindowServer::on_window_invalidate(int fd, const LibGUI::WindowPacket::Wind return; } - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to invalidate window while not owning a window"); return; } + if (!target_window->get_attributes().shown) + return; + invalidate({ target_window->client_x() + static_cast(packet.x), target_window->client_y() + static_cast(packet.y), @@ -140,15 +135,7 @@ void WindowServer::on_window_set_position(int fd, const LibGUI::WindowPacket::Wi return; } - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window position while not owning a window"); @@ -160,44 +147,56 @@ void WindowServer::on_window_set_position(int fd, const LibGUI::WindowPacket::Wi .x = packet.x, .y = packet.y, }); + + if (!target_window->get_attributes().shown) + return; + const auto new_client_area = target_window->full_area(); invalidate(new_client_area.get_bounding_box(old_client_area)); } void WindowServer::on_window_set_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes& packet) { - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window attributes while not owning a window"); return; } + const bool send_shown_event = target_window->get_attributes().shown != packet.attributes.shown; + const auto old_client_area = target_window->full_area(); target_window->set_attributes(packet.attributes); const auto new_client_area = target_window->full_area(); invalidate(new_client_area.get_bounding_box(old_client_area)); - if (!packet.attributes.focusable && m_focused_window == target_window) + if ((!packet.attributes.focusable || !packet.attributes.shown) && m_focused_window == target_window) { m_focused_window = nullptr; + if (m_state == State::Moving || m_state == State::Resizing) + m_state = State::Normal; for (size_t i = m_client_windows.size(); i > 0; i--) { - if (auto& window = m_client_windows[i - 1]; window->get_attributes().focusable) + auto& window = m_client_windows[i - 1]; + if (auto attributes = window->get_attributes(); attributes.focusable && attributes.shown) { set_focused_window(window); break; } } } + + if (!send_shown_event) + return; + + auto event_packet = LibGUI::EventPacket::WindowShownEvent { + .event = { + .shown = target_window->get_attributes().shown, + }, + }; + if (auto ret = event_packet.send_serialized(target_window->client_fd()); ret.is_error()) + dwarnln("could not send window shown event: {}", ret.error()); } void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture& packet) @@ -210,20 +209,17 @@ void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacke return; } - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set mouse capture while not owning a window"); return; } + if (!target_window->get_attributes().shown) + { + dwarnln("client tried to set mouse capture while hidden window"); + return; + } if (packet.captured == m_is_mouse_captured) return; @@ -235,15 +231,7 @@ void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacke void WindowServer::on_window_set_size(int fd, const LibGUI::WindowPacket::WindowSetSize& packet) { - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window size while not owning a window"); @@ -258,20 +246,15 @@ void WindowServer::on_window_set_size(int fd, const LibGUI::WindowPacket::Window if (!resize_window(target_window, width, height)) return; + if (!target_window->get_attributes().shown) + return; + invalidate(target_window->full_area().get_bounding_box(old_area)); } void WindowServer::on_window_set_min_size(int fd, const LibGUI::WindowPacket::WindowSetMinSize& packet) { - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window min size while not owning a window"); @@ -284,15 +267,7 @@ void WindowServer::on_window_set_min_size(int fd, const LibGUI::WindowPacket::Wi void WindowServer::on_window_set_max_size(int fd, const LibGUI::WindowPacket::WindowSetMaxSize& packet) { - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window max size while not owning a window"); @@ -328,20 +303,17 @@ void WindowServer::on_window_set_fullscreen(int fd, const LibGUI::WindowPacket:: if (!packet.fullscreen) return; - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window fullscreen while not owning a window"); return; } + if (!target_window->get_attributes().shown) + { + dwarnln("client tried to set a hidden window fullscreen"); + return; + } if (target_window->get_attributes().resizable) { @@ -359,15 +331,7 @@ void WindowServer::on_window_set_fullscreen(int fd, const LibGUI::WindowPacket:: void WindowServer::on_window_set_title(int fd, const LibGUI::WindowPacket::WindowSetTitle& packet) { - BAN::RefPtr target_window; - for (auto& window : m_client_windows) - { - if (window->client_fd() != fd) - continue; - target_window = window; - break; - } - + auto target_window = find_window_with_fd(fd); if (!target_window) { dwarnln("client tried to set window title while not owning a window"); @@ -380,6 +344,9 @@ void WindowServer::on_window_set_title(int fd, const LibGUI::WindowPacket::Windo return; } + if (!target_window->get_attributes().shown) + return; + invalidate(target_window->title_bar_area()); } @@ -508,7 +475,7 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event) if (!event.pressed) target_window = m_mouse_button_windows[button_idx]; for (size_t i = m_client_windows.size(); i > 0 && !target_window; i--) - if (m_client_windows[i - 1]->full_area().contains(m_cursor)) + if (m_client_windows[i - 1]->full_area().contains(m_cursor) && m_client_windows[i - 1]->get_attributes().shown) target_window = m_client_windows[i - 1]; switch (m_state) @@ -652,6 +619,8 @@ void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event) // TODO: Really no need to loop over every window for (auto& window : m_client_windows) { + if (!window->get_attributes().shown) + continue; auto title_bar = window->title_bar_area(); if (title_bar.get_overlap(old_cursor).has_value() || title_bar.get_overlap(new_cursor).has_value()) invalidate(title_bar); @@ -895,6 +864,8 @@ void WindowServer::invalidate(Rectangle area) for (auto& pwindow : m_client_windows) { auto& window = *pwindow; + if (!window.get_attributes().shown) + continue; const Rectangle fast_areas[] { { @@ -1269,6 +1240,17 @@ Rectangle WindowServer::resize_area(Position cursor) const }; } +BAN::RefPtr WindowServer::find_window_with_fd(int fd) +{ + for (auto window : m_client_windows) + { + if (window->client_fd() != fd) + continue; + return window; + } + return {}; +} + bool WindowServer::resize_window(BAN::RefPtr window, uint32_t width, uint32_t height) const { if (auto ret = window->resize(width, height); ret.is_error()) diff --git a/userspace/programs/WindowServer/WindowServer.h b/userspace/programs/WindowServer/WindowServer.h index e3a385e5..745ab3fc 100644 --- a/userspace/programs/WindowServer/WindowServer.h +++ b/userspace/programs/WindowServer/WindowServer.h @@ -66,6 +66,8 @@ private: bool resize_window(BAN::RefPtr window, uint32_t width, uint32_t height) const; + BAN::RefPtr find_window_with_fd(int fd); + private: struct RangeList {