mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +00:00
WindowServer: Load multiple scaled versions of Bitmaps and Cursors
This enables rendering of mixed-scale screen layouts with e.g. high resolution cursors and window button icons on high-dpi screens while using lower resolution bitmaps on regular screens.
This commit is contained in:
parent
aa15bf81e4
commit
61af9d882e
15 changed files with 269 additions and 99 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include <LibGfx/StylePainter.h>
|
#include <LibGfx/StylePainter.h>
|
||||||
#include <WindowServer/Button.h>
|
#include <WindowServer/Button.h>
|
||||||
#include <WindowServer/Event.h>
|
#include <WindowServer/Event.h>
|
||||||
|
#include <WindowServer/Screen.h>
|
||||||
#include <WindowServer/WindowManager.h>
|
#include <WindowServer/WindowManager.h>
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
@ -23,7 +24,7 @@ Button::~Button()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::paint(Gfx::Painter& painter)
|
void Button::paint(Screen& screen, Gfx::Painter& painter)
|
||||||
{
|
{
|
||||||
auto palette = WindowManager::the().palette();
|
auto palette = WindowManager::the().palette();
|
||||||
Gfx::PainterStateSaver saver(painter);
|
Gfx::PainterStateSaver saver(painter);
|
||||||
|
@ -31,10 +32,11 @@ void Button::paint(Gfx::Painter& painter)
|
||||||
Gfx::StylePainter::paint_button(painter, rect(), palette, Gfx::ButtonStyle::Normal, m_pressed, m_hovered);
|
Gfx::StylePainter::paint_button(painter, rect(), palette, Gfx::ButtonStyle::Normal, m_pressed, m_hovered);
|
||||||
|
|
||||||
if (m_icon) {
|
if (m_icon) {
|
||||||
auto icon_location = rect().center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2));
|
auto& bitmap = m_icon->bitmap(screen.scale_factor());
|
||||||
|
auto icon_location = rect().center().translated(-(bitmap.width() / 2), -(bitmap.height() / 2));
|
||||||
if (m_pressed)
|
if (m_pressed)
|
||||||
painter.translate(1, 1);
|
painter.translate(1, 1);
|
||||||
painter.blit(icon_location, *m_icon, m_icon->rect());
|
painter.blit(icon_location, bitmap, bitmap.rect());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/Forward.h>
|
#include <LibGfx/Forward.h>
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
|
#include <WindowServer/MultiScaleBitmaps.h>
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
class MouseEvent;
|
class MouseEvent;
|
||||||
|
class Screen;
|
||||||
class WindowFrame;
|
class WindowFrame;
|
||||||
|
|
||||||
class Button : public Weakable<Button> {
|
class Button : public Weakable<Button> {
|
||||||
|
@ -28,7 +30,7 @@ public:
|
||||||
Gfx::IntRect rect() const { return { {}, m_relative_rect.size() }; }
|
Gfx::IntRect rect() const { return { {}, m_relative_rect.size() }; }
|
||||||
Gfx::IntRect screen_rect() const;
|
Gfx::IntRect screen_rect() const;
|
||||||
|
|
||||||
void paint(Gfx::Painter&);
|
void paint(Screen&, Gfx::Painter&);
|
||||||
|
|
||||||
void on_mouse_event(const MouseEvent&);
|
void on_mouse_event(const MouseEvent&);
|
||||||
|
|
||||||
|
@ -38,12 +40,12 @@ public:
|
||||||
|
|
||||||
bool is_visible() const { return m_visible; }
|
bool is_visible() const { return m_visible; }
|
||||||
|
|
||||||
void set_icon(const Gfx::Bitmap& icon) { m_icon = icon; }
|
void set_icon(const RefPtr<MultiScaleBitmaps>& icon) { m_icon = icon; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowFrame& m_frame;
|
WindowFrame& m_frame;
|
||||||
Gfx::IntRect m_relative_rect;
|
Gfx::IntRect m_relative_rect;
|
||||||
RefPtr<Gfx::Bitmap> m_icon;
|
RefPtr<MultiScaleBitmaps> m_icon;
|
||||||
bool m_pressed { false };
|
bool m_pressed { false };
|
||||||
bool m_visible { true };
|
bool m_visible { true };
|
||||||
bool m_hovered { false };
|
bool m_hovered { false };
|
||||||
|
|
|
@ -21,6 +21,7 @@ set(SOURCES
|
||||||
Menu.cpp
|
Menu.cpp
|
||||||
MenuItem.cpp
|
MenuItem.cpp
|
||||||
MenuManager.cpp
|
MenuManager.cpp
|
||||||
|
MultiScaleBitmaps.cpp
|
||||||
Screen.cpp
|
Screen.cpp
|
||||||
ScreenLayout.cpp
|
ScreenLayout.cpp
|
||||||
Window.cpp
|
Window.cpp
|
||||||
|
|
|
@ -682,7 +682,7 @@ void ClientConnection::set_window_custom_cursor(i32 window_id, Gfx::ShareableBit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.set_cursor(Cursor::create(*cursor.bitmap()));
|
window.set_cursor(Cursor::create(*cursor.bitmap(), 1));
|
||||||
Compositor::the().invalidate_cursor();
|
Compositor::the().invalidate_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -919,7 +919,7 @@ void Compositor::ScreenData::draw_cursor(Screen& screen, const Gfx::IntRect& cur
|
||||||
auto& current_cursor = compositor.m_current_cursor ? *compositor.m_current_cursor : wm.active_cursor();
|
auto& current_cursor = compositor.m_current_cursor ? *compositor.m_current_cursor : wm.active_cursor();
|
||||||
auto screen_rect = screen.rect();
|
auto screen_rect = screen.rect();
|
||||||
m_cursor_back_painter->blit({ 0, 0 }, *m_back_bitmap, current_cursor.rect().translated(cursor_rect.location()).intersected(screen_rect).translated(-screen_rect.location()));
|
m_cursor_back_painter->blit({ 0, 0 }, *m_back_bitmap, current_cursor.rect().translated(cursor_rect.location()).intersected(screen_rect).translated(-screen_rect.location()));
|
||||||
m_back_painter->blit(cursor_rect.location(), current_cursor.bitmap(), current_cursor.source_rect(compositor.m_current_cursor_frame));
|
m_back_painter->blit(cursor_rect.location(), current_cursor.bitmap(screen.scale_factor()), current_cursor.source_rect(compositor.m_current_cursor_frame));
|
||||||
m_last_cursor_rect = cursor_rect;
|
m_last_cursor_rect = cursor_rect;
|
||||||
VERIFY(compositor.m_current_cursor_screen == &screen);
|
VERIFY(compositor.m_current_cursor_screen == &screen);
|
||||||
m_cursor_back_is_valid = true;
|
m_cursor_back_is_valid = true;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <AK/LexicalPath.h>
|
#include <AK/LexicalPath.h>
|
||||||
#include <WindowServer/Cursor.h>
|
#include <WindowServer/Cursor.h>
|
||||||
|
#include <WindowServer/Screen.h>
|
||||||
#include <WindowServer/WindowManager.h>
|
#include <WindowServer/WindowManager.h>
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
@ -77,6 +78,7 @@ CursorParams CursorParams::parse_from_filename(const StringView& cursor_path, co
|
||||||
return { default_hotspot };
|
return { default_hotspot };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,37 +95,66 @@ CursorParams CursorParams::constrained(const Gfx::Bitmap& bitmap) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params.m_have_hotspot)
|
if (params.m_have_hotspot)
|
||||||
params.m_hotspot = params.m_hotspot.constrained(rect);
|
params.m_hotspot.constrain(rect);
|
||||||
else
|
else
|
||||||
params.m_hotspot = rect.center();
|
params.m_hotspot = rect.center();
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, const CursorParams& cursor_params)
|
Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor, const CursorParams& cursor_params)
|
||||||
: m_bitmap(move(bitmap))
|
: m_params(cursor_params.constrained(*bitmap))
|
||||||
, m_params(cursor_params.constrained(*m_bitmap))
|
, m_rect(bitmap->rect())
|
||||||
, m_rect(m_bitmap->rect())
|
|
||||||
{
|
{
|
||||||
|
m_bitmaps.set(scale_factor, move(bitmap));
|
||||||
if (m_params.frames() > 1) {
|
if (m_params.frames() > 1) {
|
||||||
VERIFY(m_rect.width() % m_params.frames() == 0);
|
VERIFY(m_rect.width() % m_params.frames() == 0);
|
||||||
m_rect.set_width(m_rect.width() / m_params.frames());
|
m_rect.set_width(m_rect.width() / m_params.frames());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor::~Cursor()
|
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap)
|
|
||||||
{
|
{
|
||||||
auto hotspot = bitmap->rect().center();
|
auto hotspot = bitmap->rect().center();
|
||||||
return adopt_ref(*new Cursor(move(bitmap), CursorParams(hotspot)));
|
return adopt_ref(*new Cursor(move(bitmap), scale_factor, CursorParams(hotspot)));
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, const StringView& filename)
|
RefPtr<Cursor> Cursor::create(const StringView& filename, const StringView& default_filename)
|
||||||
{
|
{
|
||||||
auto default_hotspot = bitmap->rect().center();
|
auto cursor = adopt_ref(*new Cursor());
|
||||||
return adopt_ref(*new Cursor(move(bitmap), CursorParams::parse_from_filename(filename, default_hotspot)));
|
if (cursor->load(filename, default_filename))
|
||||||
|
return cursor;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cursor::load(const StringView& filename, const StringView& default_filename)
|
||||||
|
{
|
||||||
|
bool did_load_any = false;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
auto load_bitmap = [&](const StringView& path, int scale_factor) {
|
||||||
|
auto bitmap = Gfx::Bitmap::load_from_file(path, scale_factor);
|
||||||
|
if (bitmap) {
|
||||||
|
did_load_any = true;
|
||||||
|
if (first) {
|
||||||
|
m_params = CursorParams::parse_from_filename(filename, bitmap->rect().center());
|
||||||
|
m_rect = bitmap->rect();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
m_bitmaps.set(scale_factor, bitmap.release_nonnull());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Screen::for_each_scale_factor_in_use([&](int scale_factor) {
|
||||||
|
load_bitmap(filename, scale_factor);
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
if (!did_load_any) {
|
||||||
|
Screen::for_each_scale_factor_in_use([&](int scale_factor) {
|
||||||
|
load_bitmap(default_filename, scale_factor);
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return did_load_any;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Cursor> Cursor::create(Gfx::StandardCursor standard_cursor)
|
RefPtr<Cursor> Cursor::create(Gfx::StandardCursor standard_cursor)
|
||||||
|
|
|
@ -6,12 +6,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashMap.h>
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/StandardCursor.h>
|
#include <LibGfx/StandardCursor.h>
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
class CursorParams {
|
class CursorParams {
|
||||||
|
friend class Cursor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CursorParams parse_from_filename(const StringView&, const Gfx::IntPoint&);
|
static CursorParams parse_from_filename(const StringView&, const Gfx::IntPoint&);
|
||||||
CursorParams(const Gfx::IntPoint& hotspot)
|
CursorParams(const Gfx::IntPoint& hotspot)
|
||||||
|
@ -34,13 +37,27 @@ private:
|
||||||
|
|
||||||
class Cursor : public RefCounted<Cursor> {
|
class Cursor : public RefCounted<Cursor> {
|
||||||
public:
|
public:
|
||||||
static NonnullRefPtr<Cursor> create(NonnullRefPtr<Gfx::Bitmap>&&, const StringView&);
|
static RefPtr<Cursor> create(const StringView&, const StringView&);
|
||||||
static NonnullRefPtr<Cursor> create(NonnullRefPtr<Gfx::Bitmap>&&);
|
static NonnullRefPtr<Cursor> create(NonnullRefPtr<Gfx::Bitmap>&&, int);
|
||||||
static RefPtr<Cursor> create(Gfx::StandardCursor);
|
static RefPtr<Cursor> create(Gfx::StandardCursor);
|
||||||
~Cursor();
|
~Cursor() = default;
|
||||||
|
|
||||||
const CursorParams& params() const { return m_params; }
|
const CursorParams& params() const { return m_params; }
|
||||||
const Gfx::Bitmap& bitmap() const { return *m_bitmap; }
|
const Gfx::Bitmap& bitmap(int scale_factor) const
|
||||||
|
{
|
||||||
|
auto it = m_bitmaps.find(scale_factor);
|
||||||
|
if (it == m_bitmaps.end()) {
|
||||||
|
it = m_bitmaps.find(1);
|
||||||
|
if (it == m_bitmaps.end())
|
||||||
|
it = m_bitmaps.begin();
|
||||||
|
}
|
||||||
|
// We better found something
|
||||||
|
if (it == m_bitmaps.end()) {
|
||||||
|
dbgln("Could not find any bitmap in this Cursor");
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
return it->value;
|
||||||
|
}
|
||||||
|
|
||||||
Gfx::IntRect source_rect(unsigned frame) const
|
Gfx::IntRect source_rect(unsigned frame) const
|
||||||
{
|
{
|
||||||
|
@ -51,9 +68,12 @@ public:
|
||||||
Gfx::IntSize size() const { return m_rect.size(); }
|
Gfx::IntSize size() const { return m_rect.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Cursor(NonnullRefPtr<Gfx::Bitmap>&&, const CursorParams&);
|
Cursor() { }
|
||||||
|
Cursor(NonnullRefPtr<Gfx::Bitmap>&&, int, const CursorParams&);
|
||||||
|
|
||||||
RefPtr<Gfx::Bitmap> m_bitmap;
|
bool load(const StringView&, const StringView&);
|
||||||
|
|
||||||
|
HashMap<int, NonnullRefPtr<Gfx::Bitmap>> m_bitmaps;
|
||||||
CursorParams m_params;
|
CursorParams m_params;
|
||||||
Gfx::IntRect m_rect;
|
Gfx::IntRect m_rect;
|
||||||
};
|
};
|
||||||
|
|
70
Userland/Services/WindowServer/MultiScaleBitmaps.cpp
Normal file
70
Userland/Services/WindowServer/MultiScaleBitmaps.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MultiScaleBitmaps.h"
|
||||||
|
#include "Screen.h"
|
||||||
|
|
||||||
|
namespace WindowServer {
|
||||||
|
|
||||||
|
const Gfx::Bitmap& MultiScaleBitmaps::bitmap(int scale_factor) const
|
||||||
|
{
|
||||||
|
auto it = m_bitmaps.find(scale_factor);
|
||||||
|
if (it == m_bitmaps.end()) {
|
||||||
|
it = m_bitmaps.find(1);
|
||||||
|
if (it == m_bitmaps.end())
|
||||||
|
it = m_bitmaps.begin();
|
||||||
|
}
|
||||||
|
// We better found *something*
|
||||||
|
if (it == m_bitmaps.end()) {
|
||||||
|
dbgln("Could not find any bitmap in this MultiScaleBitmaps");
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
return it->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MultiScaleBitmaps> MultiScaleBitmaps::create(StringView const& filename, StringView const& default_filename)
|
||||||
|
{
|
||||||
|
auto per_scale_bitmap = adopt_ref(*new MultiScaleBitmaps());
|
||||||
|
if (per_scale_bitmap->load(filename, default_filename))
|
||||||
|
return per_scale_bitmap;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MultiScaleBitmaps::load(StringView const& filename, StringView const& default_filename)
|
||||||
|
{
|
||||||
|
Optional<Gfx::BitmapFormat> bitmap_format;
|
||||||
|
bool did_load_any = false;
|
||||||
|
|
||||||
|
auto add_bitmap = [&](StringView const& path, int scale_factor) {
|
||||||
|
auto bitmap = Gfx::Bitmap::load_from_file(path, scale_factor);
|
||||||
|
if (bitmap) {
|
||||||
|
auto bitmap_format = bitmap->format();
|
||||||
|
if (m_format == Gfx::BitmapFormat::Invalid || m_format == bitmap_format) {
|
||||||
|
if (m_format == Gfx::BitmapFormat::Invalid)
|
||||||
|
m_format = bitmap_format;
|
||||||
|
|
||||||
|
did_load_any = true;
|
||||||
|
m_bitmaps.set(scale_factor, bitmap.release_nonnull());
|
||||||
|
} else {
|
||||||
|
dbgln("Bitmap {} (scale {}) has format inconsistent with the other per-scale bitmaps", path, bitmap->scale());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Screen::for_each_scale_factor_in_use([&](int scale_factor) {
|
||||||
|
add_bitmap(filename, scale_factor);
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
if (!did_load_any && !default_filename.is_null() && !default_filename.is_empty()) {
|
||||||
|
Screen::for_each_scale_factor_in_use([&](int scale_factor) {
|
||||||
|
add_bitmap(default_filename, scale_factor);
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return did_load_any;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
Userland/Services/WindowServer/MultiScaleBitmaps.h
Normal file
32
Userland/Services/WindowServer/MultiScaleBitmaps.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/RefCounted.h>
|
||||||
|
#include <AK/RefPtr.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
|
|
||||||
|
namespace WindowServer {
|
||||||
|
|
||||||
|
class MultiScaleBitmaps : public RefCounted<MultiScaleBitmaps> {
|
||||||
|
public:
|
||||||
|
static RefPtr<MultiScaleBitmaps> create(StringView const& filename, StringView const& default_filename = {});
|
||||||
|
|
||||||
|
Gfx::Bitmap const& default_bitmap() const { return bitmap(1); }
|
||||||
|
Gfx::Bitmap const& bitmap(int scale_factor) const;
|
||||||
|
Gfx::BitmapFormat format() const { return m_format; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
MultiScaleBitmaps() = default;
|
||||||
|
bool load(StringView const& filename, StringView const& default_filename);
|
||||||
|
|
||||||
|
HashMap<int, NonnullRefPtr<Gfx::Bitmap>> m_bitmaps;
|
||||||
|
Gfx::BitmapFormat m_format { Gfx::BitmapFormat::Invalid };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ NonnullOwnPtrVector<Screen, default_screen_count> Screen::s_screens;
|
||||||
Screen* Screen::s_main_screen { nullptr };
|
Screen* Screen::s_main_screen { nullptr };
|
||||||
Gfx::IntRect Screen::s_bounding_screens_rect {};
|
Gfx::IntRect Screen::s_bounding_screens_rect {};
|
||||||
ScreenLayout Screen::s_layout;
|
ScreenLayout Screen::s_layout;
|
||||||
|
Vector<int, default_scale_factors_in_use_count> Screen::s_scale_factors_in_use;
|
||||||
|
|
||||||
ScreenInput& ScreenInput::the()
|
ScreenInput& ScreenInput::the()
|
||||||
{
|
{
|
||||||
|
@ -83,9 +84,25 @@ bool Screen::apply_layout(ScreenLayout&& screen_layout, String& error_msg)
|
||||||
|
|
||||||
rollback.disarm();
|
rollback.disarm();
|
||||||
update_bounding_rect();
|
update_bounding_rect();
|
||||||
|
update_scale_factors_in_use();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::update_scale_factors_in_use()
|
||||||
|
{
|
||||||
|
s_scale_factors_in_use.clear();
|
||||||
|
for_each([&](auto& screen) {
|
||||||
|
auto scale_factor = screen.scale_factor();
|
||||||
|
// The This doesn't have to be extremely efficient as this
|
||||||
|
// code is only run when we start up or the screen configuration
|
||||||
|
// changes. But using a vector allows for efficient iteration,
|
||||||
|
// which is the most common use case.
|
||||||
|
if (!s_scale_factors_in_use.contains_slow(scale_factor))
|
||||||
|
s_scale_factors_in_use.append(scale_factor);
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Screen::Screen(ScreenLayout::Screen& screen_info)
|
Screen::Screen(ScreenLayout::Screen& screen_info)
|
||||||
: m_virtual_rect(screen_info.location, { screen_info.resolution.width() / screen_info.scale_factor, screen_info.resolution.height() / screen_info.scale_factor })
|
: m_virtual_rect(screen_info.location, { screen_info.resolution.width() / screen_info.scale_factor, screen_info.resolution.height() / screen_info.scale_factor })
|
||||||
, m_info(screen_info)
|
, m_info(screen_info)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "ScreenLayout.h"
|
#include "ScreenLayout.h"
|
||||||
#include <AK/NonnullOwnPtrVector.h>
|
#include <AK/NonnullOwnPtrVector.h>
|
||||||
#include <Kernel/API/KeyCode.h>
|
#include <Kernel/API/KeyCode.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/Color.h>
|
#include <LibGfx/Color.h>
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
#include <LibGfx/Size.h>
|
#include <LibGfx/Size.h>
|
||||||
|
@ -23,6 +24,8 @@ constexpr unsigned scroll_step_size_min = 1;
|
||||||
|
|
||||||
// Most people will probably have 4 screens or less
|
// Most people will probably have 4 screens or less
|
||||||
constexpr size_t default_screen_count = 4;
|
constexpr size_t default_screen_count = 4;
|
||||||
|
// We currently only support 2 scale factors: 1x and 2x
|
||||||
|
constexpr size_t default_scale_factors_in_use_count = 2;
|
||||||
|
|
||||||
class Screen;
|
class Screen;
|
||||||
|
|
||||||
|
@ -125,6 +128,17 @@ public:
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
static IterationDecision for_each_scale_factor_in_use(F f)
|
||||||
|
{
|
||||||
|
for (auto& scale_factor : s_scale_factors_in_use) {
|
||||||
|
IterationDecision decision = f(scale_factor);
|
||||||
|
if (decision != IterationDecision::Continue)
|
||||||
|
return decision;
|
||||||
|
}
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
}
|
||||||
|
|
||||||
void make_main_screen() { s_main_screen = this; }
|
void make_main_screen() { s_main_screen = this; }
|
||||||
bool is_main_screen() const { return s_main_screen == this; }
|
bool is_main_screen() const { return s_main_screen == this; }
|
||||||
|
|
||||||
|
@ -158,6 +172,7 @@ private:
|
||||||
s_screens[i].m_index = i;
|
s_screens[i].m_index = i;
|
||||||
}
|
}
|
||||||
static void update_bounding_rect();
|
static void update_bounding_rect();
|
||||||
|
static void update_scale_factors_in_use();
|
||||||
|
|
||||||
bool is_opened() const { return m_framebuffer_fd >= 0; }
|
bool is_opened() const { return m_framebuffer_fd >= 0; }
|
||||||
|
|
||||||
|
@ -165,6 +180,7 @@ private:
|
||||||
static Screen* s_main_screen;
|
static Screen* s_main_screen;
|
||||||
static Gfx::IntRect s_bounding_screens_rect;
|
static Gfx::IntRect s_bounding_screens_rect;
|
||||||
static ScreenLayout s_layout;
|
static ScreenLayout s_layout;
|
||||||
|
static Vector<int, default_scale_factors_in_use_count> s_scale_factors_in_use;
|
||||||
size_t m_index { 0 };
|
size_t m_index { 0 };
|
||||||
|
|
||||||
size_t m_size_in_bytes;
|
size_t m_size_in_bytes;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <WindowServer/Button.h>
|
#include <WindowServer/Button.h>
|
||||||
#include <WindowServer/Compositor.h>
|
#include <WindowServer/Compositor.h>
|
||||||
#include <WindowServer/Event.h>
|
#include <WindowServer/Event.h>
|
||||||
|
#include <WindowServer/MultiScaleBitmaps.h>
|
||||||
#include <WindowServer/Screen.h>
|
#include <WindowServer/Screen.h>
|
||||||
#include <WindowServer/Window.h>
|
#include <WindowServer/Window.h>
|
||||||
#include <WindowServer/WindowFrame.h>
|
#include <WindowServer/WindowFrame.h>
|
||||||
|
@ -34,20 +35,19 @@ static Gfx::WindowTheme::WindowType to_theme_window_type(WindowType type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static RefPtr<Gfx::Bitmap> s_minimize_icon;
|
static RefPtr<MultiScaleBitmaps> s_minimize_icon;
|
||||||
static RefPtr<Gfx::Bitmap> s_maximize_icon;
|
static RefPtr<MultiScaleBitmaps> s_maximize_icon;
|
||||||
static RefPtr<Gfx::Bitmap> s_restore_icon;
|
static RefPtr<MultiScaleBitmaps> s_restore_icon;
|
||||||
static RefPtr<Gfx::Bitmap> s_close_icon;
|
static RefPtr<MultiScaleBitmaps> s_close_icon;
|
||||||
static RefPtr<Gfx::Bitmap> s_close_modified_icon;
|
static RefPtr<MultiScaleBitmaps> s_close_modified_icon;
|
||||||
|
|
||||||
static String s_last_title_button_icons_path;
|
static String s_last_title_button_icons_path;
|
||||||
static int s_last_title_button_icons_scale;
|
|
||||||
|
|
||||||
static RefPtr<Gfx::Bitmap> s_active_window_shadow;
|
static RefPtr<MultiScaleBitmaps> s_active_window_shadow;
|
||||||
static RefPtr<Gfx::Bitmap> s_inactive_window_shadow;
|
static RefPtr<MultiScaleBitmaps> s_inactive_window_shadow;
|
||||||
static RefPtr<Gfx::Bitmap> s_menu_shadow;
|
static RefPtr<MultiScaleBitmaps> s_menu_shadow;
|
||||||
static RefPtr<Gfx::Bitmap> s_taskbar_shadow;
|
static RefPtr<MultiScaleBitmaps> s_taskbar_shadow;
|
||||||
static RefPtr<Gfx::Bitmap> s_tooltip_shadow;
|
static RefPtr<MultiScaleBitmaps> s_tooltip_shadow;
|
||||||
static String s_last_active_window_shadow_path;
|
static String s_last_active_window_shadow_path;
|
||||||
static String s_last_inactive_window_shadow_path;
|
static String s_last_inactive_window_shadow_path;
|
||||||
static String s_last_menu_shadow_path;
|
static String s_last_menu_shadow_path;
|
||||||
|
@ -117,7 +117,7 @@ void WindowFrame::set_button_icons()
|
||||||
|
|
||||||
m_close_button->set_icon(m_window.is_modified() ? *s_close_modified_icon : *s_close_icon);
|
m_close_button->set_icon(m_window.is_modified() ? *s_close_modified_icon : *s_close_icon);
|
||||||
if (m_window.is_minimizable())
|
if (m_window.is_minimizable())
|
||||||
m_minimize_button->set_icon(*s_minimize_icon);
|
m_minimize_button->set_icon(s_minimize_icon);
|
||||||
if (m_window.is_resizable())
|
if (m_window.is_resizable())
|
||||||
m_maximize_button->set_icon(m_window.is_maximized() ? *s_restore_icon : *s_maximize_icon);
|
m_maximize_button->set_icon(m_window.is_maximized() ? *s_restore_icon : *s_maximize_icon);
|
||||||
}
|
}
|
||||||
|
@ -125,54 +125,47 @@ void WindowFrame::set_button_icons()
|
||||||
void WindowFrame::reload_config()
|
void WindowFrame::reload_config()
|
||||||
{
|
{
|
||||||
String icons_path = WindowManager::the().palette().title_button_icons_path();
|
String icons_path = WindowManager::the().palette().title_button_icons_path();
|
||||||
int icons_scale = WindowManager::the().compositor_icon_scale(); // TODO: We'll need to load icons for all scales in use!
|
|
||||||
|
|
||||||
StringBuilder full_path;
|
StringBuilder full_path;
|
||||||
if (!s_minimize_icon || s_last_title_button_icons_path != icons_path || s_last_title_button_icons_scale != icons_scale) {
|
if (!s_minimize_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
full_path.append(icons_path);
|
full_path.append(icons_path);
|
||||||
full_path.append("window-minimize.png");
|
full_path.append("window-minimize.png");
|
||||||
if (!(s_minimize_icon = Gfx::Bitmap::load_from_file(full_path.to_string(), icons_scale)))
|
s_minimize_icon = MultiScaleBitmaps::create(full_path.to_string(), "/res/icons/16x16/downward-triangle.png");
|
||||||
s_minimize_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/downward-triangle.png", icons_scale);
|
|
||||||
full_path.clear();
|
full_path.clear();
|
||||||
}
|
}
|
||||||
if (!s_maximize_icon || s_last_title_button_icons_path != icons_path || s_last_title_button_icons_scale != icons_scale) {
|
if (!s_maximize_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
full_path.append(icons_path);
|
full_path.append(icons_path);
|
||||||
full_path.append("window-maximize.png");
|
full_path.append("window-maximize.png");
|
||||||
if (!(s_maximize_icon = Gfx::Bitmap::load_from_file(full_path.to_string(), icons_scale)))
|
s_maximize_icon = MultiScaleBitmaps::create(full_path.to_string(), "/res/icons/16x16/upward-triangle.png");
|
||||||
s_maximize_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/upward-triangle.png", icons_scale);
|
|
||||||
full_path.clear();
|
full_path.clear();
|
||||||
}
|
}
|
||||||
if (!s_restore_icon || s_last_title_button_icons_path != icons_path || s_last_title_button_icons_scale != icons_scale) {
|
if (!s_restore_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
full_path.append(icons_path);
|
full_path.append(icons_path);
|
||||||
full_path.append("window-restore.png");
|
full_path.append("window-restore.png");
|
||||||
if (!(s_restore_icon = Gfx::Bitmap::load_from_file(full_path.to_string(), icons_scale)))
|
s_restore_icon = MultiScaleBitmaps::create(full_path.to_string(), "/res/icons/16x16/window-restore.png");
|
||||||
s_restore_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-restore.png", icons_scale);
|
|
||||||
full_path.clear();
|
full_path.clear();
|
||||||
}
|
}
|
||||||
if (!s_close_icon || s_last_title_button_icons_path != icons_path || s_last_title_button_icons_scale != icons_scale) {
|
if (!s_close_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
full_path.append(icons_path);
|
full_path.append(icons_path);
|
||||||
full_path.append("window-close.png");
|
full_path.append("window-close.png");
|
||||||
if (!(s_close_icon = Gfx::Bitmap::load_from_file(full_path.to_string(), icons_scale)))
|
s_close_icon = MultiScaleBitmaps::create(full_path.to_string(), "/res/icons/16x16/window-close.png");
|
||||||
s_close_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-close.png", icons_scale);
|
|
||||||
full_path.clear();
|
full_path.clear();
|
||||||
}
|
}
|
||||||
if (!s_close_modified_icon || s_last_title_button_icons_path != icons_path || s_last_title_button_icons_scale != icons_scale) {
|
if (!s_close_modified_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
full_path.append(icons_path);
|
full_path.append(icons_path);
|
||||||
full_path.append("window-close-modified.png");
|
full_path.append("window-close-modified.png");
|
||||||
if (!(s_close_modified_icon = Gfx::Bitmap::load_from_file(full_path.to_string(), icons_scale)))
|
s_close_modified_icon = MultiScaleBitmaps::create(full_path.to_string(), "/res/icons/16x16/window-close-modified.png");
|
||||||
s_close_modified_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-close-modified.png", icons_scale);
|
|
||||||
full_path.clear();
|
full_path.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
s_last_title_button_icons_path = icons_path;
|
s_last_title_button_icons_path = icons_path;
|
||||||
s_last_title_button_icons_scale = icons_scale;
|
|
||||||
|
|
||||||
auto load_shadow = [](const String& path, String& last_path, RefPtr<Gfx::Bitmap>& shadow_bitmap) {
|
auto load_shadow = [](const String& path, String& last_path, RefPtr<MultiScaleBitmaps>& shadow_bitmap) {
|
||||||
if (path.is_empty()) {
|
if (path.is_empty()) {
|
||||||
last_path = String::empty();
|
last_path = String::empty();
|
||||||
shadow_bitmap = nullptr;
|
shadow_bitmap = nullptr;
|
||||||
} else if (!shadow_bitmap || shadow_bitmap->scale() != s_last_title_button_icons_scale || last_path != path) {
|
} else if (!shadow_bitmap || last_path != path) {
|
||||||
shadow_bitmap = Gfx::Bitmap::load_from_file(path, s_last_title_button_icons_scale);
|
shadow_bitmap = MultiScaleBitmaps::create(path);
|
||||||
if (shadow_bitmap)
|
if (shadow_bitmap)
|
||||||
last_path = path;
|
last_path = path;
|
||||||
else
|
else
|
||||||
|
@ -186,7 +179,7 @@ void WindowFrame::reload_config()
|
||||||
load_shadow(WindowManager::the().palette().tooltip_shadow_path(), s_last_tooltip_shadow_path, s_tooltip_shadow);
|
load_shadow(WindowManager::the().palette().tooltip_shadow_path(), s_last_tooltip_shadow_path, s_tooltip_shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::Bitmap* WindowFrame::shadow_bitmap() const
|
MultiScaleBitmaps* WindowFrame::shadow_bitmap() const
|
||||||
{
|
{
|
||||||
if (m_window.is_frameless())
|
if (m_window.is_frameless())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -317,7 +310,7 @@ void WindowFrame::paint(Screen& screen, Gfx::Painter& painter, const Gfx::IntRec
|
||||||
cached->paint(*this, painter, rect);
|
cached->paint(*this, painter, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowFrame::RenderedCache::paint(WindowFrame& frame, Gfx::Painter& painter, const Gfx::IntRect& rect)
|
void WindowFrame::PerScaleRenderedCache::paint(WindowFrame& frame, Gfx::Painter& painter, const Gfx::IntRect& rect)
|
||||||
{
|
{
|
||||||
auto frame_rect = frame.unconstrained_render_rect();
|
auto frame_rect = frame.unconstrained_render_rect();
|
||||||
auto window_rect = frame.window().rect();
|
auto window_rect = frame.window().rect();
|
||||||
|
@ -357,7 +350,7 @@ void WindowFrame::RenderedCache::paint(WindowFrame& frame, Gfx::Painter& painter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowFrame::render(Screen&, Gfx::Painter& painter)
|
void WindowFrame::render(Screen& screen, Gfx::Painter& painter)
|
||||||
{
|
{
|
||||||
if (m_window.is_frameless())
|
if (m_window.is_frameless())
|
||||||
return;
|
return;
|
||||||
|
@ -371,9 +364,8 @@ void WindowFrame::render(Screen&, Gfx::Painter& painter)
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto& button : m_buttons) {
|
for (auto& button : m_buttons)
|
||||||
button.paint(painter);
|
button.paint(screen, painter);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowFrame::theme_changed()
|
void WindowFrame::theme_changed()
|
||||||
|
@ -386,13 +378,13 @@ void WindowFrame::theme_changed()
|
||||||
m_has_alpha_channel = Gfx::WindowTheme::current().frame_uses_alpha(window_state_for_theme(), WindowManager::the().palette());
|
m_has_alpha_channel = Gfx::WindowTheme::current().frame_uses_alpha(window_state_for_theme(), WindowManager::the().palette());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto WindowFrame::render_to_cache(Screen& screen) -> RenderedCache*
|
auto WindowFrame::render_to_cache(Screen& screen) -> PerScaleRenderedCache*
|
||||||
{
|
{
|
||||||
auto scale = screen.scale_factor();
|
auto scale = screen.scale_factor();
|
||||||
RenderedCache* rendered_cache;
|
PerScaleRenderedCache* rendered_cache;
|
||||||
auto cached_it = m_rendered_cache.find(scale);
|
auto cached_it = m_rendered_cache.find(scale);
|
||||||
if (cached_it == m_rendered_cache.end()) {
|
if (cached_it == m_rendered_cache.end()) {
|
||||||
auto new_rendered_cache = make<RenderedCache>();
|
auto new_rendered_cache = make<PerScaleRenderedCache>();
|
||||||
rendered_cache = new_rendered_cache.ptr();
|
rendered_cache = new_rendered_cache.ptr();
|
||||||
m_rendered_cache.set(scale, move(new_rendered_cache));
|
m_rendered_cache.set(scale, move(new_rendered_cache));
|
||||||
} else {
|
} else {
|
||||||
|
@ -402,7 +394,7 @@ auto WindowFrame::render_to_cache(Screen& screen) -> RenderedCache*
|
||||||
return rendered_cache;
|
return rendered_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowFrame::RenderedCache::render(WindowFrame& frame, Screen& screen)
|
void WindowFrame::PerScaleRenderedCache::render(WindowFrame& frame, Screen& screen)
|
||||||
{
|
{
|
||||||
if (!m_dirty)
|
if (!m_dirty)
|
||||||
return;
|
return;
|
||||||
|
@ -417,7 +409,7 @@ void WindowFrame::RenderedCache::render(WindowFrame& frame, Screen& screen)
|
||||||
Gfx::IntPoint shadow_offset;
|
Gfx::IntPoint shadow_offset;
|
||||||
|
|
||||||
if (shadow_bitmap) {
|
if (shadow_bitmap) {
|
||||||
auto total_shadow_size = shadow_bitmap->height();
|
auto total_shadow_size = shadow_bitmap->bitmap(screen.scale_factor()).height();
|
||||||
frame_rect_including_shadow.inflate(total_shadow_size, total_shadow_size);
|
frame_rect_including_shadow.inflate(total_shadow_size, total_shadow_size);
|
||||||
auto offset = total_shadow_size / 2;
|
auto offset = total_shadow_size / 2;
|
||||||
shadow_offset = { offset, offset };
|
shadow_offset = { offset, offset };
|
||||||
|
@ -481,7 +473,7 @@ void WindowFrame::RenderedCache::render(WindowFrame& frame, Screen& screen)
|
||||||
painter.clear_rect({ rect.location() - frame_rect_to_update.location(), rect.size() }, { 255, 255, 255, 0 });
|
painter.clear_rect({ rect.location() - frame_rect_to_update.location(), rect.size() }, { 255, 255, 255, 0 });
|
||||||
|
|
||||||
if (m_shadow_dirty && shadow_bitmap)
|
if (m_shadow_dirty && shadow_bitmap)
|
||||||
frame.paint_simple_rect_shadow(painter, { { 0, 0 }, frame_rect_including_shadow.size() }, *shadow_bitmap);
|
frame.paint_simple_rect_shadow(painter, { { 0, 0 }, frame_rect_including_shadow.size() }, shadow_bitmap->bitmap(screen.scale_factor()));
|
||||||
|
|
||||||
{
|
{
|
||||||
Gfx::PainterStateSaver save(painter);
|
Gfx::PainterStateSaver save(painter);
|
||||||
|
@ -535,7 +527,7 @@ void WindowFrame::set_opacity(float opacity)
|
||||||
Gfx::IntRect WindowFrame::inflated_for_shadow(const Gfx::IntRect& frame_rect) const
|
Gfx::IntRect WindowFrame::inflated_for_shadow(const Gfx::IntRect& frame_rect) const
|
||||||
{
|
{
|
||||||
if (auto* shadow = shadow_bitmap()) {
|
if (auto* shadow = shadow_bitmap()) {
|
||||||
auto total_shadow_size = shadow->height();
|
auto total_shadow_size = shadow->default_bitmap().height();
|
||||||
return frame_rect.inflated(total_shadow_size, total_shadow_size);
|
return frame_rect.inflated(total_shadow_size, total_shadow_size);
|
||||||
}
|
}
|
||||||
return frame_rect;
|
return frame_rect;
|
||||||
|
@ -678,7 +670,7 @@ Optional<HitTestResult> WindowFrame::hit_test(Gfx::IntPoint const& position)
|
||||||
return cached->hit_test(*this, position, window_relative_position);
|
return cached->hit_test(*this, position, window_relative_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<HitTestResult> WindowFrame::RenderedCache::hit_test(WindowFrame& frame, Gfx::IntPoint const& position, Gfx::IntPoint const& window_relative_position)
|
Optional<HitTestResult> WindowFrame::PerScaleRenderedCache::hit_test(WindowFrame& frame, Gfx::IntPoint const& position, Gfx::IntPoint const& window_relative_position)
|
||||||
{
|
{
|
||||||
HitTestResult result {
|
HitTestResult result {
|
||||||
.window = frame.window(),
|
.window = frame.window(),
|
||||||
|
|
|
@ -19,12 +19,13 @@ namespace WindowServer {
|
||||||
class Button;
|
class Button;
|
||||||
class Menu;
|
class Menu;
|
||||||
class MouseEvent;
|
class MouseEvent;
|
||||||
class Window;
|
class MultiScaleBitmaps;
|
||||||
class Screen;
|
class Screen;
|
||||||
|
class Window;
|
||||||
|
|
||||||
class WindowFrame {
|
class WindowFrame {
|
||||||
public:
|
public:
|
||||||
class RenderedCache {
|
class PerScaleRenderedCache {
|
||||||
friend class WindowFrame;
|
friend class WindowFrame;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -60,7 +61,7 @@ public:
|
||||||
|
|
||||||
void paint(Screen&, Gfx::Painter&, const Gfx::IntRect&);
|
void paint(Screen&, Gfx::Painter&, const Gfx::IntRect&);
|
||||||
void render(Screen&, Gfx::Painter&);
|
void render(Screen&, Gfx::Painter&);
|
||||||
RenderedCache* render_to_cache(Screen&);
|
PerScaleRenderedCache* render_to_cache(Screen&);
|
||||||
|
|
||||||
void handle_mouse_event(MouseEvent const&);
|
void handle_mouse_event(MouseEvent const&);
|
||||||
void handle_titlebar_mouse_event(MouseEvent const&);
|
void handle_titlebar_mouse_event(MouseEvent const&);
|
||||||
|
@ -123,7 +124,7 @@ private:
|
||||||
void paint_normal_frame(Gfx::Painter&);
|
void paint_normal_frame(Gfx::Painter&);
|
||||||
void paint_tool_window_frame(Gfx::Painter&);
|
void paint_tool_window_frame(Gfx::Painter&);
|
||||||
void paint_menubar(Gfx::Painter&);
|
void paint_menubar(Gfx::Painter&);
|
||||||
Gfx::Bitmap* shadow_bitmap() const;
|
MultiScaleBitmaps* shadow_bitmap() const;
|
||||||
Gfx::IntRect inflated_for_shadow(const Gfx::IntRect&) const;
|
Gfx::IntRect inflated_for_shadow(const Gfx::IntRect&) const;
|
||||||
|
|
||||||
void handle_menubar_mouse_event(const MouseEvent&);
|
void handle_menubar_mouse_event(const MouseEvent&);
|
||||||
|
@ -140,7 +141,7 @@ private:
|
||||||
Button* m_maximize_button { nullptr };
|
Button* m_maximize_button { nullptr };
|
||||||
Button* m_minimize_button { nullptr };
|
Button* m_minimize_button { nullptr };
|
||||||
|
|
||||||
HashMap<int, NonnullOwnPtr<RenderedCache>> m_rendered_cache;
|
HashMap<int, NonnullOwnPtr<PerScaleRenderedCache>> m_rendered_cache;
|
||||||
|
|
||||||
RefPtr<Core::Timer> m_flash_timer;
|
RefPtr<Core::Timer> m_flash_timer;
|
||||||
size_t m_flash_counter { 0 };
|
size_t m_flash_counter { 0 };
|
||||||
|
|
|
@ -48,14 +48,10 @@ WindowManager::~WindowManager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Cursor> WindowManager::get_cursor(String const& name)
|
RefPtr<Cursor> WindowManager::get_cursor(String const& name)
|
||||||
{
|
{
|
||||||
static auto const s_default_cursor_path = "/res/cursors/arrow.x2y2.png";
|
static auto const s_default_cursor_path = "/res/cursors/arrow.x2y2.png";
|
||||||
auto path = m_config->read_entry("Cursor", name, s_default_cursor_path);
|
return Cursor::create(m_config->read_entry("Cursor", name, s_default_cursor_path), s_default_cursor_path);
|
||||||
auto gb = Gfx::Bitmap::load_from_file(path, compositor_icon_scale());
|
|
||||||
if (gb)
|
|
||||||
return Cursor::create(*gb, path);
|
|
||||||
return Cursor::create(*Gfx::Bitmap::load_from_file(s_default_cursor_path), s_default_cursor_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::reload_config()
|
void WindowManager::reload_config()
|
||||||
|
@ -1179,7 +1175,7 @@ void WindowManager::process_key_event(KeyEvent& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type() == Event::KeyDown && (event.modifiers() == (Mod_Ctrl | Mod_Super | Mod_Shift) && event.key() == Key_I)) {
|
if (event.type() == Event::KeyDown && (event.modifiers() == (Mod_Ctrl | Mod_Super | Mod_Shift) && event.key() == Key_I)) {
|
||||||
reload_icon_bitmaps_after_scale_change(!m_allow_hidpi_icons);
|
reload_icon_bitmaps_after_scale_change();
|
||||||
Compositor::the().invalidate_screen();
|
Compositor::the().invalidate_screen();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1595,16 +1591,8 @@ Gfx::IntPoint WindowManager::get_recommended_window_position(Gfx::IntPoint const
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WindowManager::compositor_icon_scale() const
|
void WindowManager::reload_icon_bitmaps_after_scale_change()
|
||||||
{
|
{
|
||||||
if (!m_allow_hidpi_icons)
|
|
||||||
return 1;
|
|
||||||
return Screen::main().scale_factor(); // TODO: There is no *one* scale factor...
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::reload_icon_bitmaps_after_scale_change(bool allow_hidpi_icons)
|
|
||||||
{
|
|
||||||
m_allow_hidpi_icons = allow_hidpi_icons;
|
|
||||||
reload_config();
|
reload_config();
|
||||||
m_window_stack.for_each_window([&](Window& window) {
|
m_window_stack.for_each_window([&](Window& window) {
|
||||||
auto& window_frame = window.frame();
|
auto& window_frame = window.frame();
|
||||||
|
|
|
@ -224,8 +224,7 @@ public:
|
||||||
|
|
||||||
Gfx::IntPoint get_recommended_window_position(Gfx::IntPoint const& desired);
|
Gfx::IntPoint get_recommended_window_position(Gfx::IntPoint const& desired);
|
||||||
|
|
||||||
int compositor_icon_scale() const;
|
void reload_icon_bitmaps_after_scale_change();
|
||||||
void reload_icon_bitmaps_after_scale_change(bool allow_hidpi_icons = true);
|
|
||||||
|
|
||||||
void reevaluate_hovered_window(Window* = nullptr);
|
void reevaluate_hovered_window(Window* = nullptr);
|
||||||
Window* hovered_window() const { return m_hovered_window.ptr(); }
|
Window* hovered_window() const { return m_hovered_window.ptr(); }
|
||||||
|
@ -233,7 +232,7 @@ public:
|
||||||
WindowStack& window_stack() { return m_window_stack; }
|
WindowStack& window_stack() { return m_window_stack; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NonnullRefPtr<Cursor> get_cursor(String const& name);
|
RefPtr<Cursor> get_cursor(String const& name);
|
||||||
|
|
||||||
void process_mouse_event(MouseEvent&);
|
void process_mouse_event(MouseEvent&);
|
||||||
void process_event_for_doubleclick(Window& window, MouseEvent& event);
|
void process_event_for_doubleclick(Window& window, MouseEvent& event);
|
||||||
|
@ -257,7 +256,6 @@ private:
|
||||||
|
|
||||||
void do_move_to_front(Window&, bool, bool);
|
void do_move_to_front(Window&, bool, bool);
|
||||||
|
|
||||||
bool m_allow_hidpi_icons { true };
|
|
||||||
RefPtr<Cursor> m_hidden_cursor;
|
RefPtr<Cursor> m_hidden_cursor;
|
||||||
RefPtr<Cursor> m_arrow_cursor;
|
RefPtr<Cursor> m_arrow_cursor;
|
||||||
RefPtr<Cursor> m_hand_cursor;
|
RefPtr<Cursor> m_hand_cursor;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue