Userland: Implement a magnifier app

This utility is useful for making sure those UI elements are pixel
perfect. A simple 2x/4x magnification around the mouse cursor, shown in
a window.
This commit is contained in:
Valtteri Koskivuori 2021-05-10 00:15:35 +03:00 committed by Linus Groh
parent 4864ef9440
commit 4d01183f5c
Notes: sideshowbarker 2024-07-18 18:20:58 +09:00
6 changed files with 183 additions and 0 deletions

View File

@ -2,6 +2,7 @@
alias fm=FileManager
alias irc=IRCClient
alias mag=Magnifier
alias ms=Minesweeper
alias sh=Shell
alias sn=Snake

View File

@ -13,6 +13,7 @@ add_subdirectory(HexEditor)
add_subdirectory(IRCClient)
add_subdirectory(KeyboardMapper)
add_subdirectory(KeyboardSettings)
add_subdirectory(Magnifier)
add_subdirectory(MouseSettings)
add_subdirectory(Piano)
add_subdirectory(PixelPaint)

View File

@ -0,0 +1,8 @@
set(SOURCES
MagnifierWidget.cpp
MagnifierWidget.h
main.cpp
)
serenity_app(Magnifier ICON find)
target_link_libraries(Magnifier LibGUI)

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, Valtteri Koskivuori <vkoskiv@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "MagnifierWidget.h"
#include <LibGUI/Painter.h>
#include <LibGUI/Window.h>
#include <LibGUI/WindowServerConnection.h>
#include <LibGfx/AffineTransform.h>
#include <math.h>
MagnifierWidget::MagnifierWidget()
{
}
MagnifierWidget::~MagnifierWidget()
{
}
void MagnifierWidget::track_cursor_globally()
{
VERIFY(window());
auto window_id = window()->window_id();
VERIFY(window_id >= 0);
set_global_cursor_tracking(true);
GUI::WindowServerConnection::the().set_global_cursor_tracking(window_id, true);
}
void MagnifierWidget::set_scale_factor(int scale_factor)
{
VERIFY(scale_factor == 2 || scale_factor == 4);
m_scale_factor = scale_factor;
update();
}
void MagnifierWidget::timer_event(Core::TimerEvent&)
{
m_mouse_position = GUI::WindowServerConnection::the().get_global_cursor_position();
update();
}
void MagnifierWidget::paint_event(GUI::PaintEvent&)
{
GUI::Painter painter(*this);
int grab_frame_size = 200;
grab_frame_size /= m_scale_factor;
// Paint our screenshot
Gfx::Rect region { m_mouse_position.x() - (grab_frame_size / 2), m_mouse_position.y() - (grab_frame_size / 2), grab_frame_size, grab_frame_size };
auto map = GUI::WindowServerConnection::the().get_screen_bitmap(region);
painter.draw_scaled_bitmap(rect(), *map.bitmap(), map.bitmap()->rect());
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2021, Valtteri Koskivuori <vkoskiv@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGUI/Widget.h>
#include <LibGfx/Point.h>
class MagnifierWidget final : public GUI::Widget {
C_OBJECT(MagnifierWidget)
public:
MagnifierWidget();
virtual ~MagnifierWidget();
void set_scale_factor(int scale_factor);
void track_cursor_globally();
private:
virtual void timer_event(Core::TimerEvent&) override;
virtual void paint_event(GUI::PaintEvent&) override;
Gfx::IntPoint m_mouse_position;
int m_scale_factor { 2 };
};

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2021, Valtteri Koskivuori <vkoskiv@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "MagnifierWidget.h"
#include <LibGUI/ActionGroup.h>
#include <LibGUI/Application.h>
#include <LibGUI/Icon.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Menubar.h>
#include <LibGUI/Window.h>
#include <unistd.h>
int main(int argc, char** argv)
{
if (pledge("stdio cpath rpath recvfd sendfd unix fattr", nullptr) < 0) {
perror("pledge");
return 1;
}
auto app = GUI::Application::construct(argc, argv);
if (pledge("stdio cpath rpath recvfd sendfd", nullptr) < 0) {
perror("pledge");
return 1;
}
if (unveil("/res", "r") < 0) {
perror("unveil");
return 1;
}
if (unveil(nullptr, nullptr) < 0) {
perror("unveil");
return 1;
}
// Sneaky!
// FIXME: Doesn't have a 32x32 icon yet, need to make one!
auto app_icon = GUI::Icon::default_icon("find");
// 4px on each side for padding
constexpr int window_dimensions = 200 + 4 + 4;
auto window = GUI::Window::construct();
window->set_title("Magnifier");
window->resize(window_dimensions, window_dimensions);
window->set_resizable(false);
window->set_minimizable(false);
window->set_icon(app_icon.bitmap_for_size(16));
auto& magnifier = window->set_main_widget<MagnifierWidget>();
auto menubar = GUI::Menubar::construct();
auto& file_menu = menubar->add_menu("&File");
file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) {
app->quit();
}));
auto size_action_group = make<GUI::ActionGroup>();
auto two_x_action = GUI::Action::create_checkable(
"&2x", [&](auto&) {
magnifier.set_scale_factor(2);
});
auto four_x_action = GUI::Action::create_checkable(
"&4x", [&](auto&) {
magnifier.set_scale_factor(4);
});
size_action_group->add_action(two_x_action);
size_action_group->add_action(four_x_action);
size_action_group->set_exclusive(true);
auto& view_menu = menubar->add_menu("&View");
view_menu.add_action(two_x_action);
view_menu.add_action(four_x_action);
two_x_action->set_checked(true);
auto& help_menu = menubar->add_menu("&Help");
help_menu.add_action(GUI::CommonActions::make_about_action("Magnifier", app_icon, window));
window->set_menubar(move(menubar));
window->show();
magnifier.track_cursor_globally();
magnifier.start_timer(16);
return app->exec();
}