mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:27:35 +00:00
WindowServer: Change window geometry label to use the Overlay class
This enables flicker-free rendering.
This commit is contained in:
parent
8b26debda1
commit
84cab29c59
7 changed files with 93 additions and 50 deletions
|
@ -157,13 +157,8 @@ void Compositor::compose()
|
||||||
|
|
||||||
auto dirty_screen_rects = move(m_dirty_screen_rects);
|
auto dirty_screen_rects = move(m_dirty_screen_rects);
|
||||||
auto* dnd_client = wm.dnd_client();
|
auto* dnd_client = wm.dnd_client();
|
||||||
if (!m_last_geometry_label_damage_rect.is_empty() || !m_last_dnd_rect.is_empty() || (m_invalidated_cursor && dnd_client)) {
|
if (!m_last_dnd_rect.is_empty() || (m_invalidated_cursor && dnd_client)) {
|
||||||
Screen::for_each([&](auto& screen) {
|
Screen::for_each([&](auto& screen) {
|
||||||
if (!m_last_geometry_label_damage_rect.is_empty()) {
|
|
||||||
auto rect = m_last_geometry_label_damage_rect.intersected(screen.rect());
|
|
||||||
if (!rect.is_empty())
|
|
||||||
dirty_screen_rects.add(rect);
|
|
||||||
}
|
|
||||||
if (!m_last_dnd_rect.is_empty()) {
|
if (!m_last_dnd_rect.is_empty()) {
|
||||||
auto rect = m_last_dnd_rect.intersected(screen.rect());
|
auto rect = m_last_dnd_rect.intersected(screen.rect());
|
||||||
if (!rect.is_empty())
|
if (!rect.is_empty())
|
||||||
|
@ -542,8 +537,6 @@ void Compositor::compose()
|
||||||
screen_data.m_back_painter->blit(rect.location(), *screen_data.m_temp_bitmap, rect.translated(-screen_rect.location()));
|
screen_data.m_back_painter->blit(rect.location(), *screen_data.m_temp_bitmap, rect.translated(-screen_rect.location()));
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
|
||||||
draw_geometry_label(cursor_screen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_invalidated_any = false;
|
m_invalidated_any = false;
|
||||||
|
@ -869,46 +862,6 @@ void Compositor::invalidate_cursor(bool compose_immediately)
|
||||||
start_compose_async_timer();
|
start_compose_async_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compositor::draw_geometry_label(Screen& screen)
|
|
||||||
{
|
|
||||||
auto& wm = WindowManager::the();
|
|
||||||
auto* window_being_moved_or_resized = wm.m_move_window ? wm.m_move_window.ptr() : (wm.m_resize_window ? wm.m_resize_window.ptr() : nullptr);
|
|
||||||
if (!window_being_moved_or_resized) {
|
|
||||||
m_last_geometry_label_damage_rect = {};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto geometry_string = window_being_moved_or_resized->rect().to_string();
|
|
||||||
if (!window_being_moved_or_resized->size_increment().is_null()) {
|
|
||||||
int width_steps = (window_being_moved_or_resized->width() - window_being_moved_or_resized->base_size().width()) / window_being_moved_or_resized->size_increment().width();
|
|
||||||
int height_steps = (window_being_moved_or_resized->height() - window_being_moved_or_resized->base_size().height()) / window_being_moved_or_resized->size_increment().height();
|
|
||||||
geometry_string = String::formatted("{} ({}x{})", geometry_string, width_steps, height_steps);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto geometry_label_rect = Gfx::IntRect { 0, 0, wm.font().width(geometry_string) + 16, wm.font().glyph_height() + 10 };
|
|
||||||
geometry_label_rect.center_within(window_being_moved_or_resized->rect());
|
|
||||||
auto desktop_rect = wm.desktop_rect(screen);
|
|
||||||
if (geometry_label_rect.left() < desktop_rect.left())
|
|
||||||
geometry_label_rect.set_left(desktop_rect.left());
|
|
||||||
if (geometry_label_rect.top() < desktop_rect.top())
|
|
||||||
geometry_label_rect.set_top(desktop_rect.top());
|
|
||||||
if (geometry_label_rect.right() > desktop_rect.right())
|
|
||||||
geometry_label_rect.set_right_without_resize(desktop_rect.right());
|
|
||||||
if (geometry_label_rect.bottom() > desktop_rect.bottom())
|
|
||||||
geometry_label_rect.set_bottom_without_resize(desktop_rect.bottom());
|
|
||||||
|
|
||||||
auto& screen_data = m_screen_data[screen.index()];
|
|
||||||
auto& back_painter = *screen_data.m_back_painter;
|
|
||||||
auto geometry_label_damage_rect = geometry_label_rect.inflated(2, 2);
|
|
||||||
Gfx::PainterStateSaver saver(back_painter);
|
|
||||||
back_painter.add_clip_rect(geometry_label_damage_rect);
|
|
||||||
|
|
||||||
back_painter.fill_rect(geometry_label_rect.translated(1, 1), Color(Color::Black).with_alpha(80));
|
|
||||||
Gfx::StylePainter::paint_button(back_painter, geometry_label_rect.translated(-1, -1), wm.palette(), Gfx::ButtonStyle::Normal, false);
|
|
||||||
back_painter.draw_text(geometry_label_rect.translated(-1, -1), geometry_string, Gfx::TextAlignment::Center, wm.palette().window_text());
|
|
||||||
|
|
||||||
m_last_geometry_label_damage_rect = geometry_label_damage_rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Compositor::change_cursor(const Cursor* cursor)
|
void Compositor::change_cursor(const Cursor* cursor)
|
||||||
{
|
{
|
||||||
if (m_current_cursor == cursor)
|
if (m_current_cursor == cursor)
|
||||||
|
@ -1103,6 +1056,7 @@ void Compositor::overlay_rects_changed()
|
||||||
{
|
{
|
||||||
if (m_overlay_rects_changed)
|
if (m_overlay_rects_changed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_overlay_rects_changed = true;
|
m_overlay_rects_changed = true;
|
||||||
m_invalidated_any = true;
|
m_invalidated_any = true;
|
||||||
invalidate_occlusions();
|
invalidate_occlusions();
|
||||||
|
|
|
@ -113,7 +113,6 @@ private:
|
||||||
void recompute_occlusions();
|
void recompute_occlusions();
|
||||||
bool any_opaque_window_above_this_one_contains_rect(const Window&, const Gfx::IntRect&);
|
bool any_opaque_window_above_this_one_contains_rect(const Window&, const Gfx::IntRect&);
|
||||||
void change_cursor(const Cursor*);
|
void change_cursor(const Cursor*);
|
||||||
void draw_geometry_label(Screen&);
|
|
||||||
void flush(Screen&);
|
void flush(Screen&);
|
||||||
|
|
||||||
RefPtr<Core::Timer> m_compose_timer;
|
RefPtr<Core::Timer> m_compose_timer;
|
||||||
|
@ -183,7 +182,6 @@ private:
|
||||||
Gfx::DisjointRectSet m_opaque_wallpaper_rects;
|
Gfx::DisjointRectSet m_opaque_wallpaper_rects;
|
||||||
|
|
||||||
Gfx::IntRect m_last_dnd_rect;
|
Gfx::IntRect m_last_dnd_rect;
|
||||||
Gfx::IntRect m_last_geometry_label_damage_rect;
|
|
||||||
|
|
||||||
String m_wallpaper_path { "" };
|
String m_wallpaper_path { "" };
|
||||||
WallpaperMode m_wallpaper_mode { WallpaperMode::Unchecked };
|
WallpaperMode m_wallpaper_mode { WallpaperMode::Unchecked };
|
||||||
|
|
|
@ -205,4 +205,52 @@ Gfx::IntRect ScreenNumberOverlay::calculate_content_rect_for_screen(Screen& scre
|
||||||
return calculate_frame_rect(content_rect);
|
return calculate_frame_rect(content_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowGeometryOverlay::WindowGeometryOverlay(Window& window)
|
||||||
|
: m_window(window)
|
||||||
|
{
|
||||||
|
update_rect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowGeometryOverlay::update_rect()
|
||||||
|
{
|
||||||
|
if (auto* window = m_window.ptr()) {
|
||||||
|
auto& wm = WindowManager::the();
|
||||||
|
if (!window->size_increment().is_null()) {
|
||||||
|
int width_steps = (window->width() - window->base_size().width()) / window->size_increment().width();
|
||||||
|
int height_steps = (window->height() - window->base_size().height()) / window->size_increment().height();
|
||||||
|
m_label = String::formatted("{} ({}x{})", window->rect(), width_steps, height_steps);
|
||||||
|
} else {
|
||||||
|
m_label = window->rect().to_string();
|
||||||
|
}
|
||||||
|
m_label_rect = Gfx::IntRect { 0, 0, wm.font().width(m_label) + 16, wm.font().glyph_height() + 10 };
|
||||||
|
|
||||||
|
auto rect = calculate_frame_rect(m_label_rect);
|
||||||
|
rect.center_within(window->frame().rect());
|
||||||
|
auto desktop_rect = wm.desktop_rect(ScreenInput::the().cursor_location_screen());
|
||||||
|
if (rect.left() < desktop_rect.left())
|
||||||
|
rect.set_left(desktop_rect.left());
|
||||||
|
if (rect.top() < desktop_rect.top())
|
||||||
|
rect.set_top(desktop_rect.top());
|
||||||
|
if (rect.right() > desktop_rect.right())
|
||||||
|
rect.set_right_without_resize(desktop_rect.right());
|
||||||
|
if (rect.bottom() > desktop_rect.bottom())
|
||||||
|
rect.set_bottom_without_resize(desktop_rect.bottom());
|
||||||
|
|
||||||
|
set_rect(rect);
|
||||||
|
} else {
|
||||||
|
set_enabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowGeometryOverlay::render_overlay_bitmap(Gfx::Painter& painter)
|
||||||
|
{
|
||||||
|
painter.draw_text({ {}, rect().size() }, m_label, WindowManager::the().font(), Gfx::TextAlignment::Center, Color::White);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowGeometryOverlay::window_rect_changed()
|
||||||
|
{
|
||||||
|
update_rect();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/IntrusiveList.h>
|
#include <AK/IntrusiveList.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <AK/WeakPtr.h>
|
||||||
#include <LibGfx/Painter.h>
|
#include <LibGfx/Painter.h>
|
||||||
#include <WindowServer/MultiScaleBitmaps.h>
|
#include <WindowServer/MultiScaleBitmaps.h>
|
||||||
#include <WindowServer/Screen.h>
|
#include <WindowServer/Screen.h>
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
class Screen;
|
class Screen;
|
||||||
|
class Window;
|
||||||
|
|
||||||
class Overlay {
|
class Overlay {
|
||||||
friend class Compositor;
|
friend class Compositor;
|
||||||
|
@ -124,4 +126,21 @@ private:
|
||||||
static Gfx::Font const* s_font;
|
static Gfx::Font const* s_font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WindowGeometryOverlay : public RectangularOverlay {
|
||||||
|
public:
|
||||||
|
WindowGeometryOverlay(Window&);
|
||||||
|
|
||||||
|
void window_rect_changed();
|
||||||
|
|
||||||
|
virtual ZOrder zorder() const override { return ZOrder::WindowGeometry; }
|
||||||
|
virtual void render_overlay_bitmap(Gfx::Painter&) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_rect();
|
||||||
|
|
||||||
|
WeakPtr<Window> m_window;
|
||||||
|
String m_label;
|
||||||
|
Gfx::IntRect m_label_rect;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,6 +502,8 @@ void Window::set_visible(bool b)
|
||||||
return;
|
return;
|
||||||
m_visible = b;
|
m_visible = b;
|
||||||
|
|
||||||
|
if (!m_visible)
|
||||||
|
WindowManager::the().check_hide_geometry_overlay(*this);
|
||||||
Compositor::the().invalidate_occlusions();
|
Compositor::the().invalidate_occlusions();
|
||||||
if (m_visible)
|
if (m_visible)
|
||||||
invalidate(true);
|
invalidate(true);
|
||||||
|
|
|
@ -256,6 +256,8 @@ void WindowManager::do_move_to_front(Window& window, bool make_active, bool make
|
||||||
|
|
||||||
void WindowManager::remove_window(Window& window)
|
void WindowManager::remove_window(Window& window)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
check_hide_geometry_overlay(window);
|
||||||
m_window_stack.remove(window);
|
m_window_stack.remove(window);
|
||||||
auto* active = active_window();
|
auto* active = active_window();
|
||||||
auto* active_input = active_input_window();
|
auto* active_input = active_input_window();
|
||||||
|
@ -481,6 +483,12 @@ bool WindowManager::pick_new_active_window(Window* previous_active)
|
||||||
return new_window_picked;
|
return new_window_picked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::check_hide_geometry_overlay(Window& window)
|
||||||
|
{
|
||||||
|
if (&window == m_move_window.ptr() || &window == m_resize_window.ptr())
|
||||||
|
m_geometry_overlay = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::start_window_move(Window& window, Gfx::IntPoint const& origin)
|
void WindowManager::start_window_move(Window& window, Gfx::IntPoint const& origin)
|
||||||
{
|
{
|
||||||
MenuManager::the().close_everyone();
|
MenuManager::the().close_everyone();
|
||||||
|
@ -492,6 +500,8 @@ void WindowManager::start_window_move(Window& window, Gfx::IntPoint const& origi
|
||||||
m_move_window->set_default_positioned(false);
|
m_move_window->set_default_positioned(false);
|
||||||
m_move_origin = origin;
|
m_move_origin = origin;
|
||||||
m_move_window_origin = window.position();
|
m_move_window_origin = window.position();
|
||||||
|
m_geometry_overlay = Compositor::the().create_overlay<WindowGeometryOverlay>(window);
|
||||||
|
m_geometry_overlay->set_enabled(true);
|
||||||
window.invalidate(true, true);
|
window.invalidate(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +541,8 @@ void WindowManager::start_window_resize(Window& window, Gfx::IntPoint const& pos
|
||||||
m_resize_window = window;
|
m_resize_window = window;
|
||||||
m_resize_origin = position;
|
m_resize_origin = position;
|
||||||
m_resize_window_original_rect = window.rect();
|
m_resize_window_original_rect = window.rect();
|
||||||
|
m_geometry_overlay = Compositor::the().create_overlay<WindowGeometryOverlay>(window);
|
||||||
|
m_geometry_overlay->set_enabled(true);
|
||||||
|
|
||||||
m_active_input_tracking_window = nullptr;
|
m_active_input_tracking_window = nullptr;
|
||||||
|
|
||||||
|
@ -563,6 +575,7 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_move_window = nullptr;
|
m_move_window = nullptr;
|
||||||
|
m_geometry_overlay = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (event.type() == Event::MouseMove) {
|
if (event.type() == Event::MouseMove) {
|
||||||
|
@ -623,6 +636,8 @@ bool WindowManager::process_ongoing_window_move(MouseEvent& event)
|
||||||
m_move_window_origin = m_move_window->position();
|
m_move_window_origin = m_move_window->position();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_geometry_overlay->window_rect_changed();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -640,6 +655,7 @@ bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
|
||||||
dbgln_if(RESIZE_DEBUG, "Should Maximize vertically");
|
dbgln_if(RESIZE_DEBUG, "Should Maximize vertically");
|
||||||
m_resize_window->set_vertically_maximized();
|
m_resize_window->set_vertically_maximized();
|
||||||
m_resize_window = nullptr;
|
m_resize_window = nullptr;
|
||||||
|
m_geometry_overlay = nullptr;
|
||||||
m_resizing_mouse_button = MouseButton::None;
|
m_resizing_mouse_button = MouseButton::None;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -647,6 +663,7 @@ bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
|
||||||
Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(m_resize_window->rect()));
|
Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(m_resize_window->rect()));
|
||||||
m_resize_window->invalidate(true, true);
|
m_resize_window->invalidate(true, true);
|
||||||
m_resize_window = nullptr;
|
m_resize_window = nullptr;
|
||||||
|
m_geometry_overlay = nullptr;
|
||||||
m_resizing_mouse_button = MouseButton::None;
|
m_resizing_mouse_button = MouseButton::None;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -748,6 +765,7 @@ bool WindowManager::process_ongoing_window_resize(MouseEvent const& event)
|
||||||
dbgln_if(RESIZE_DEBUG, "[WM] Resizing, original: {}, now: {}", m_resize_window_original_rect, new_rect);
|
dbgln_if(RESIZE_DEBUG, "[WM] Resizing, original: {}, now: {}", m_resize_window_original_rect, new_rect);
|
||||||
|
|
||||||
m_resize_window->set_rect(new_rect);
|
m_resize_window->set_rect(new_rect);
|
||||||
|
m_geometry_overlay->window_rect_changed();
|
||||||
Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(new_rect));
|
Core::EventLoop::current().post_event(*m_resize_window, make<ResizeEvent>(new_rect));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ class Window;
|
||||||
class ClientConnection;
|
class ClientConnection;
|
||||||
class WindowSwitcher;
|
class WindowSwitcher;
|
||||||
class Button;
|
class Button;
|
||||||
|
class WindowGeometryOverlay;
|
||||||
|
|
||||||
enum class ResizeDirection {
|
enum class ResizeDirection {
|
||||||
None,
|
None,
|
||||||
|
@ -160,6 +161,8 @@ public:
|
||||||
|
|
||||||
bool is_active_window_or_accessory(Window&) const;
|
bool is_active_window_or_accessory(Window&) const;
|
||||||
|
|
||||||
|
void check_hide_geometry_overlay(Window&);
|
||||||
|
|
||||||
void start_window_resize(Window&, Gfx::IntPoint const&, MouseButton);
|
void start_window_resize(Window&, Gfx::IntPoint const&, MouseButton);
|
||||||
void start_window_resize(Window&, MouseEvent const&);
|
void start_window_resize(Window&, MouseEvent const&);
|
||||||
void start_window_move(Window&, MouseEvent const&);
|
void start_window_move(Window&, MouseEvent const&);
|
||||||
|
@ -319,6 +322,7 @@ private:
|
||||||
WeakPtr<Window> m_active_input_tracking_window;
|
WeakPtr<Window> m_active_input_tracking_window;
|
||||||
WeakPtr<Window> m_window_with_active_menu;
|
WeakPtr<Window> m_window_with_active_menu;
|
||||||
|
|
||||||
|
OwnPtr<WindowGeometryOverlay> m_geometry_overlay;
|
||||||
WeakPtr<Window> m_move_window;
|
WeakPtr<Window> m_move_window;
|
||||||
Gfx::IntPoint m_move_origin;
|
Gfx::IntPoint m_move_origin;
|
||||||
Gfx::IntPoint m_move_window_origin;
|
Gfx::IntPoint m_move_window_origin;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue