Add possibility to pick colors from the desktop (fix #594)

Requested several times (e.g. https://community.aseprite.org/t/2431)

Added support only for Windows and macOS at the moment.
This commit is contained in:
David Capello 2021-02-23 18:25:28 -03:00
parent 44437e0d1f
commit ddcc53469d
4 changed files with 52 additions and 7 deletions

2
laf

@ -1 +1 @@
Subproject commit 410da165bde1e7353eb46aa58481a956f2ad489b
Subproject commit 0b2e8b7a401aa34c245afe5e0114a498d4e341cd

View File

@ -27,6 +27,8 @@
#include "doc/layer.h"
#include "doc/sprite.h"
#include "gfx/rect_io.h"
#include "os/system.h"
#include "os/window.h"
#include "ui/ui.h"
#include <algorithm>
@ -145,14 +147,50 @@ bool ColorButton::onProcessMessage(Message* msg)
case kMouseMoveMessage:
if (hasCapture()) {
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
Widget* picked = manager()->pick(mousePos);
app::Color color = m_color;
if (picked && picked != this) {
// Pick a color from a IColorSource
if (IColorSource* colorSource = dynamic_cast<IColorSource*>(picked)) {
color = colorSource->getColorByPosition(mousePos);
// Pick a color from a IColorSource
Widget* picked = window()->pick(mousePos);
IColorSource* colorSource = (picked != this ? dynamic_cast<IColorSource*>(picked): nullptr);
// If there is no color source, get the color from the display
// surface, and finally from the desktop. The desktop must be
// a last resource method, because in macOS it will ask for
// permissions to record the screen.
if (!colorSource) {
os::Window* nativeWindow = display()->nativeWindow();
gfx::Point screenPos = nativeWindow->pointToScreen(mousePos);
picked = manager()->pickFromScreenPos(screenPos);
colorSource = (picked != this ? dynamic_cast<IColorSource*>(picked): nullptr);
if (colorSource) {
nativeWindow = picked->display()->nativeWindow();
mousePos = nativeWindow->pointFromScreen(screenPos);
}
else {
gfx::Color gfxColor = gfx::ColorNone;
// Get color from native window surface
if (nativeWindow->contentRect().contains(screenPos)) {
mousePos = nativeWindow->pointFromScreen(screenPos);
if (nativeWindow->surface()->bounds().contains(mousePos))
gfxColor = nativeWindow->surface()->getPixel(mousePos.x, mousePos.y);
}
// Or get the color from the screen
if (gfxColor == gfx::ColorNone) {
gfxColor = os::instance()->getColorFromScreen(screenPos);
}
color = app::Color::fromRgb(gfx::getr(gfxColor),
gfx::getg(gfxColor),
gfx::getb(gfxColor),
gfx::geta(gfxColor));
}
}
if (colorSource) {
color = colorSource->getColorByPosition(mousePos);
}
// Did the color change?

View File

@ -1118,6 +1118,11 @@ bool Manager::isFocusMovementMessage(Message* msg)
return false;
}
Widget* Manager::pickFromScreenPos(const gfx::Point& screenPos) const
{
return pick(gfx::Point(screenPos) - display()->nativeWindow()->contentRect().origin());
}
// Configures the window for begin the loop
void Manager::_openWindow(Window* window)
{

View File

@ -36,7 +36,7 @@ namespace ui {
Manager(const os::WindowRef& nativeWindow);
~Manager();
Display* display() { return &m_display; }
Display* display() const { return &const_cast<Manager*>(this)->m_display; }
Display* getDisplayFromNativeWindow(os::Window* window) const;
// Executes the main message loop.
@ -89,6 +89,8 @@ namespace ui {
bool isFocusMovementMessage(Message* msg);
bool processFocusMovementMessage(Message* msg);
Widget* pickFromScreenPos(const gfx::Point& screenPos) const;
void _openWindow(Window* window);
void _closeWindow(Window* window, bool redraw_background);