Merge branch 'main' into beta

This commit is contained in:
David Capello 2022-05-30 20:41:35 -03:00
commit 77771b703b
25 changed files with 301 additions and 98 deletions

View File

@ -2,11 +2,12 @@
# Copyright (C) 2018-2022 Igara Studio S.A. # Copyright (C) 2018-2022 Igara Studio S.A.
# Copyright (C) 2001-2018 David Capello # Copyright (C) 2001-2018 David Capello
cmake_minimum_required(VERSION 3.4) cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # We use -std=c++17 instead of -std=gnu++17 in macOS set(CMAKE_CXX_EXTENSIONS OFF) # We use -std=c++17 instead of -std=gnu++17 in macOS
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
if(COMMAND cmake_policy) if(COMMAND cmake_policy)
# CMP0003: Libraries linked via full path no longer produce linker search paths. # CMP0003: Libraries linked via full path no longer produce linker search paths.

View File

@ -226,6 +226,7 @@
<option id="new_blend" type="bool" default="true" /> <option id="new_blend" type="bool" default="true" />
<option id="use_native_clipboard" type="bool" default="true" /> <option id="use_native_clipboard" type="bool" default="true" />
<option id="use_native_file_dialog" type="bool" default="false" /> <option id="use_native_file_dialog" type="bool" default="false" />
<option id="use_shaders_for_color_selectors" type="bool" default="true" />
<option id="one_finger_as_mouse_movement" type="bool" default="true" /> <option id="one_finger_as_mouse_movement" type="bool" default="true" />
<option id="load_wintab_driver" type="bool" default="false" /> <option id="load_wintab_driver" type="bool" default="false" />
<option id="flash_layer" type="bool" default="false" /> <option id="flash_layer" type="bool" default="false" />

View File

@ -1387,6 +1387,7 @@ new_blend = New layer blending method
new_render_engine = New render engine for sprite editor new_render_engine = New render engine for sprite editor
native_clipboard = Use native clipboard native_clipboard = Use native clipboard
native_file_dialog = Use native file dialog native_file_dialog = Use native file dialog
shaders_for_color_selectors = Use shaders for color selectors
one_finger_as_mouse_movement = Interpret one finger as mouse movement one_finger_as_mouse_movement = Interpret one finger as mouse movement
one_finger_as_mouse_movement_tooltip = <<<END one_finger_as_mouse_movement_tooltip = <<<END
Only for Windows 8/10 Pointer API: Interprets one finger as mouse movement Only for Windows 8/10 Pointer API: Interprets one finger as mouse movement

View File

@ -513,6 +513,12 @@
</hbox> </hbox>
<check id="native_clipboard" text="@.native_clipboard" /> <check id="native_clipboard" text="@.native_clipboard" />
<check id="native_file_dialog" text="@.native_file_dialog" /> <check id="native_file_dialog" text="@.native_file_dialog" />
<hbox>
<check id="shaders_for_color_selectors"
text="@.shaders_for_color_selectors"
pref="experimental.use_shaders_for_color_selectors" />
<link text="(#960)" url="https://github.com/aseprite/aseprite/issues/960" />
</hbox>
<hbox id="load_wintab_driver_box"> <hbox id="load_wintab_driver_box">
<check id="load_wintab_driver2" <check id="load_wintab_driver2"
text="@.load_wintab_driver" text="@.load_wintab_driver"

2
laf

@ -1 +1 @@
Subproject commit 8b0422877a39d655bf6a405eb2e2985763b150da Subproject commit 68a44741998e5a769a9b952ddb422e993dc5b6a9

View File

@ -961,7 +961,7 @@ static FileItem* get_fileitem_by_fullpidl(LPITEMIDLIST fullpidl, bool create_if_
return nullptr; return nullptr;
// new file-item // new file-item
FileItem* fileitem = new FileItem(nullptr); auto fileitem = std::make_unique<FileItem>(nullptr);
fileitem->m_fullpidl = clone_pidl(fullpidl); fileitem->m_fullpidl = clone_pidl(fullpidl);
{ {
@ -973,19 +973,26 @@ static FileItem* get_fileitem_by_fullpidl(LPITEMIDLIST fullpidl, bool create_if_
free_pidl(parent_fullpidl); free_pidl(parent_fullpidl);
// The parent folder is sometimes deleted for some reasons. In
// that case, m_parent becomes nullptr, so we cannot use it
// anymore. Here we just return nullptr to indicate that the item
// doesn't exist anymore.
if (fileitem->m_parent == nullptr)
return nullptr;
// Get specific pidl attributes // Get specific pidl attributes
if (fileitem->m_pidl && if (fileitem->m_pidl &&
fileitem->m_parent) { fileitem->m_parent) {
attrib = get_pidl_attrib(fileitem, attrib); attrib = get_pidl_attrib(fileitem.get(), attrib);
} }
} }
update_by_pidl(fileitem, attrib); update_by_pidl(fileitem.get(), attrib);
put_fileitem(fileitem); put_fileitem(fileitem.get());
//LOG("FS: fileitem %p created %s with parent %p\n", fileitem, fileitem->keyname.c_str(), fileitem->parent); //LOG("FS: fileitem %p created %s with parent %p\n", fileitem, fileitem->keyname.c_str(), fileitem->parent);
return fileitem; return fileitem.release();
} }
// Inserts the fileitem in the hash map of items. // Inserts the fileitem in the hash map of items.

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -46,7 +46,7 @@ void HttpLoader::abort()
void HttpLoader::threadHttpRequest() void HttpLoader::threadHttpRequest()
{ {
try { try {
base::ScopedValue<bool> scoped(m_done, false, true); base::ScopedValue<std::atomic<bool>, bool> scoped(m_done, false, true);
LOG("HTTP: Sending http request to %s\n", m_url.c_str()); LOG("HTTP: Sending http request to %s\n", m_url.c_str());

View File

@ -1,4 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2022 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -9,6 +10,8 @@
#pragma once #pragma once
#include "base/thread.h" #include "base/thread.h"
#include <atomic>
#include <string> #include <string>
namespace net { namespace net {
@ -30,7 +33,7 @@ namespace app {
void threadHttpRequest(); void threadHttpRequest();
std::string m_url; std::string m_url;
bool m_done; std::atomic<bool> m_done;
net::HttpRequest* m_request; net::HttpRequest* m_request;
base::thread m_thread; base::thread m_thread;
std::string m_filename; std::string m_filename;

View File

@ -12,6 +12,7 @@
#include "app/resource_finder.h" #include "app/resource_finder.h"
#include "base/fs.h" #include "base/fs.h"
#include "base/log.h"
#include "base/string.h" #include "base/string.h"
#include "ver/info.h" #include "ver/info.h"
@ -110,6 +111,33 @@ bool Sentry::areThereCrashesToReport()
return false; return false;
} }
// static
void Sentry::addBreadcrumb(const std::string& message)
{
LOG(VERBOSE, "BC: %s\n", message.c_str());
sentry_value_t c = sentry_value_new_breadcrumb(nullptr, message.c_str());
sentry_add_breadcrumb(c);
}
// static
void Sentry::addBreadcrumb(const std::string& message,
const std::map<std::string, std::string>& data)
{
LOG(VERBOSE, "BC: %s\n", message.c_str());
sentry_value_t c = sentry_value_new_breadcrumb(nullptr, message.c_str());
sentry_value_t d = sentry_value_new_object();
for (const auto& kv : data) {
LOG(VERBOSE, " - [%s]=%s\n", kv.first.c_str(), kv.second.c_str());
sentry_value_set_by_key(d,
kv.first.c_str(),
sentry_value_new_string(kv.second.c_str()));
}
sentry_value_set_by_key(c, "data", d);
sentry_add_breadcrumb(c);
}
void Sentry::setupDirs(sentry_options_t* options) void Sentry::setupDirs(sentry_options_t* options)
{ {
// The expected handler executable name is aseprite_crashpad_handler (.exe) // The expected handler executable name is aseprite_crashpad_handler (.exe)

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2021-2022 Igara Studio S.A.
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -13,6 +13,7 @@
#include "sentry.h" #include "sentry.h"
#include <map>
#include <string> #include <string>
namespace app { namespace app {
@ -33,6 +34,10 @@ public:
// the "give consent" check box for first time. // the "give consent" check box for first time.
static bool areThereCrashesToReport(); static bool areThereCrashesToReport();
static void addBreadcrumb(const std::string& message);
static void addBreadcrumb(const std::string& message,
const std::map<std::string, std::string>& data);
private: private:
void setupDirs(sentry_options_t* options); void setupDirs(sentry_options_t* options);

View File

@ -17,6 +17,7 @@
#include "app/color_spaces.h" #include "app/color_spaces.h"
#include "app/color_utils.h" #include "app/color_utils.h"
#include "app/modules/gfx.h" #include "app/modules/gfx.h"
#include "app/pref/preferences.h"
#include "app/ui/skin/skin_theme.h" #include "app/ui/skin/skin_theme.h"
#include "app/ui/status_bar.h" #include "app/ui/status_bar.h"
#include "app/util/shader_helpers.h" #include "app/util/shader_helpers.h"
@ -441,8 +442,7 @@ void ColorSelector::onPaint(ui::PaintEvent& ev)
os::Surface* painterSurface = nullptr; os::Surface* painterSurface = nullptr;
#if SK_ENABLE_SKSL // Paint with shaders #if SK_ENABLE_SKSL // Paint with shaders
buildEffects(); if (buildEffects()) {
if (m_mainEffect && m_bottomEffect && m_alphaEffect) {
SkCanvas* canvas; SkCanvas* canvas;
bool isSRGB; bool isSRGB;
// TODO compare both color spaces // TODO compare both color spaces
@ -471,6 +471,7 @@ void ColorSelector::onPaint(ui::PaintEvent& ev)
SkRuntimeShaderBuilder builder1(m_mainEffect); SkRuntimeShaderBuilder builder1(m_mainEffect);
builder1.uniform("iRes") = SkV3{float(rc2.w), float(rc2.h), 0.0f}; builder1.uniform("iRes") = SkV3{float(rc2.w), float(rc2.h), 0.0f};
builder1.uniform("iColor") = appColor_to_SkV4(m_color); builder1.uniform("iColor") = appColor_to_SkV4(m_color);
setShaderMainAreaParams(builder1);
p.setShader(builder1.makeShader()); p.setShader(builder1.makeShader());
if (isSRGB) if (isSRGB)
@ -647,8 +648,11 @@ half4 main(vec2 fragcoord) {
)"; )";
} }
void ColorSelector::buildEffects() bool ColorSelector::buildEffects()
{ {
if (!Preferences::instance().experimental.useShadersForColorSelectors())
return false;
if (!m_mainEffect) { if (!m_mainEffect) {
if (const char* code = getMainAreaShader()) if (const char* code = getMainAreaShader())
m_mainEffect = buildEffect(code); m_mainEffect = buildEffect(code);
@ -663,6 +667,8 @@ void ColorSelector::buildEffects()
if (const char* code = getAlphaBarShader()) if (const char* code = getAlphaBarShader())
m_alphaEffect = buildEffect(code); m_alphaEffect = buildEffect(code);
} }
return (m_mainEffect && m_bottomEffect && m_alphaEffect);
} }
sk_sp<SkRuntimeEffect> ColorSelector::buildEffect(const char* code) sk_sp<SkRuntimeEffect> ColorSelector::buildEffect(const char* code)
@ -677,6 +683,6 @@ sk_sp<SkRuntimeEffect> ColorSelector::buildEffect(const char* code)
return result.effect; return result.effect;
} }
} }
#endif #endif // SK_ENABLE_SKSL
} // namespace app } // namespace app

View File

@ -70,6 +70,9 @@ namespace app {
virtual const char* getMainAreaShader() { return nullptr; } virtual const char* getMainAreaShader() { return nullptr; }
virtual const char* getBottomBarShader() { return nullptr; } virtual const char* getBottomBarShader() { return nullptr; }
#if SK_ENABLE_SKSL
virtual void setShaderMainAreaParams(SkRuntimeShaderBuilder& builder) { }
#endif
virtual app::Color getMainAreaColor(const int u, const int umax, virtual app::Color getMainAreaColor(const int u, const int umax,
const int v, const int vmax) = 0; const int v, const int vmax) = 0;
virtual app::Color getBottomBarColor(const int u, const int umax) = 0; virtual app::Color getBottomBarColor(const int u, const int umax) = 0;
@ -112,7 +115,7 @@ namespace app {
#if SK_ENABLE_SKSL #if SK_ENABLE_SKSL
static const char* getAlphaBarShader(); static const char* getAlphaBarShader();
void buildEffects(); bool buildEffects();
sk_sp<SkRuntimeEffect> buildEffect(const char* code); sk_sp<SkRuntimeEffect> buildEffect(const char* code);
#endif #endif

View File

@ -15,9 +15,9 @@
#include "app/pref/preferences.h" #include "app/pref/preferences.h"
#include "app/ui/skin/skin_theme.h" #include "app/ui/skin/skin_theme.h"
#include "app/ui/status_bar.h" #include "app/ui/status_bar.h"
#include "app/util/shader_helpers.h"
#include "base/clamp.h" #include "base/clamp.h"
#include "base/pi.h" #include "base/pi.h"
#include "filters/color_curve.h"
#include "os/surface.h" #include "os/surface.h"
#include "ui/graphics.h" #include "ui/graphics.h"
#include "ui/menu.h" #include "ui/menu.h"
@ -67,6 +67,117 @@ ColorWheel::ColorWheel()
initTheme(); initTheme();
} }
const char* ColorWheel::getMainAreaShader()
{
#if SK_ENABLE_SKSL
// TODO create one shader for each wheel mode (RGB, RYB, normal)
if (m_mainShader.empty()) {
m_mainShader += "uniform half3 iRes;"
"uniform half4 iColor;"
"uniform half4 iBack;"
"uniform int iDiscrete;"
"uniform int iMode;";
m_mainShader += kRGB_to_HSV_sksl;
m_mainShader += kHSV_to_RGB_sksl;
m_mainShader += R"(
const half PI = 3.1415;
half rybhue_to_rgbhue(half h) {
if (h >= 0 && h < 120) return h / 2; // from red to yellow
else if (h < 180) return (h-60.0); // from yellow to green
else if (h < 240) return 120 + 2*(h-180); // from green to blue
else return h; // from blue to red (same hue)
}
half4 main(vec2 fragcoord) {
vec2 res = vec2(min(iRes.x, iRes.y), min(iRes.x, iRes.y));
vec2 d = (fragcoord.xy-iRes.xy/2) / res.xy;
half r = length(d);
if (r <= 0.5) {
half a = atan(-d.y, d.x);
half hue = (floor(180.0 * a / PI)
+ 180 // To avoid [-180,0) range
+ 180 + 30 // To locate green at 12 o'clock
);
hue = mod(hue, 360); // To leave hue in [0,360) range
if (iDiscrete != 0) {
hue += 15.0;
hue = floor(hue / 30.0);
hue *= 30.0;
}
if (iMode == 1) { // RYB color wheel
hue = rybhue_to_rgbhue(hue);
}
hue /= 360.0;
if (iMode == 2) { // Normal map mode
float di = 0.5 * r / 0.5;
half3 rgb = half3(0.5+di*cos(a), 0.5+di*sin(a), 1.0-di);
return half4(
clamp(rgb.x, 0, 1),
clamp(rgb.y, 0, 1),
clamp(rgb.z, 0.5, 1), 1);
}
half sat = r / 0.5;
if (iDiscrete != 0) {
sat *= 120.0;
sat = floor(sat / 20.0);
sat *= 20.0;
sat /= 100.0;
sat = clamp(sat, 0.0, 1.0);
}
vec3 hsv = rgb_to_hsv(iColor.rgb);
return hsv_to_rgb(vec3(hue, sat, iColor.w > 0 ? hsv.z: 1.0)).rgb1;
}
else {
if (iMode == 2) // Normal map mode
return half4(0.5, 0.5, 1, 1);
return iBack;
}
}
)";
}
return m_mainShader.c_str();
#else
return nullptr;
#endif
}
const char* ColorWheel::getBottomBarShader()
{
#if SK_ENABLE_SKSL
if (m_bottomShader.empty()) {
m_bottomShader += "uniform half3 iRes;"
"uniform half4 iColor;";
m_bottomShader += kRGB_to_HSV_sksl;
m_bottomShader += kHSV_to_RGB_sksl;
// TODO should we display the hue bar with the current sat/value?
m_bottomShader += R"(
half4 main(vec2 fragcoord) {
half v = (fragcoord.x / iRes.x);
half3 hsv = rgb_to_hsv(iColor.rgb);
return hsv_to_rgb(half3(hsv.x, hsv.y, v)).rgb1;
}
)";
}
return m_bottomShader.c_str();
#else
return nullptr;
#endif
}
#if SK_ENABLE_SKSL
void ColorWheel::setShaderMainAreaParams(SkRuntimeShaderBuilder& builder)
{
builder.uniform("iBack") = gfxColor_to_SkV4(m_bgColor);
builder.uniform("iDiscrete") = (m_discrete ? 1: 0);
builder.uniform("iMode") = int(m_colorModel);
}
#endif
app::Color ColorWheel::getMainAreaColor(const int _u, const int umax, app::Color ColorWheel::getMainAreaColor(const int _u, const int umax,
const int _v, const int vmax) const int _v, const int vmax)
{ {
@ -89,7 +200,7 @@ app::Color ColorWheel::getMainAreaColor(const int _u, const int umax,
boxsize, boxsize).contains(pos)) { boxsize, boxsize).contains(pos)) {
m_harmonyPicked = true; m_harmonyPicked = true;
color = app::Color::fromHsv(convertHueAngle(int(color.getHsvHue()), 1), color = app::Color::fromHsv(convertHueAngle(color.getHsvHue(), 1),
color.getHsvSaturation(), color.getHsvSaturation(),
color.getHsvValue(), color.getHsvValue(),
m_color.getAlpha()); m_color.getAlpha());
@ -212,7 +323,7 @@ void ColorWheel::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
double angle = color.getHsvHue()-30.0; double angle = color.getHsvHue()-30.0;
double dist = color.getHsvSaturation(); double dist = color.getHsvSaturation();
color = app::Color::fromHsv(convertHueAngle(int(color.getHsvHue()), 1), color = app::Color::fromHsv(convertHueAngle(color.getHsvHue(), 1),
color.getHsvSaturation(), color.getHsvSaturation(),
color.getHsvValue()); color.getHsvValue());
@ -347,7 +458,7 @@ app::Color ColorWheel::getColorInHarmony(int j) const
{ {
int i = base::clamp((int)m_harmony, 0, (int)Harmony::LAST); int i = base::clamp((int)m_harmony, 0, (int)Harmony::LAST);
j = base::clamp(j, 0, harmonies[i].n-1); j = base::clamp(j, 0, harmonies[i].n-1);
double hue = convertHueAngle(int(m_color.getHsvHue()), -1) + harmonies[i].hues[j]; double hue = convertHueAngle(m_color.getHsvHue(), -1) + harmonies[i].hues[j];
double sat = m_color.getHsvSaturation() * harmonies[i].sats[j] / 100.0; double sat = m_color.getHsvSaturation() * harmonies[i].sats[j] / 100.0;
return app::Color::fromHsv(std::fmod(hue, 360), return app::Color::fromHsv(std::fmod(hue, 360),
base::clamp(sat, 0.0, 1.0), base::clamp(sat, 0.0, 1.0),
@ -421,51 +532,33 @@ void ColorWheel::onOptions()
menu.showPopup(gfx::Point(rc.x2(), rc.y), display()); menu.showPopup(gfx::Point(rc.x2(), rc.y), display());
} }
int ColorWheel::convertHueAngle(int hue, int dir) const float ColorWheel::convertHueAngle(float h, int dir) const
{ {
switch (m_colorModel) { if (m_colorModel == ColorModel::RYB) {
if (dir == 1) {
case ColorModel::RGB: // rybhue_to_rgbhue() maps:
return hue; // [0,120) -> [0,60)
// [120,180) -> [60,120)
case ColorModel::RYB: { // [180,240) -> [120,240)
static std::vector<int> map1; // [240,360] -> [240,360]
static std::vector<int> map2; if (h >= 0 && h < 120) return h / 2; // from red to yellow
else if (h < 180) return (h-60); // from yellow to green
if (map2.empty()) { else if (h < 240) return 120 + 2*(h-180); // from green to blue
filters::ColorCurve curve1(filters::ColorCurve::Linear); else return h; // from blue to red (same hue)
curve1.addPoint(gfx::Point(0, 0)); }
curve1.addPoint(gfx::Point(60, 35)); else {
curve1.addPoint(gfx::Point(122, 60)); // rgbhue_to_rybhue()
curve1.addPoint(gfx::Point(165, 120)); // [0,60) -> [0,120)
curve1.addPoint(gfx::Point(218, 180)); // [60,120) -> [120,180)
curve1.addPoint(gfx::Point(275, 240)); // [120,240) -> [180,240)
curve1.addPoint(gfx::Point(330, 300)); // [240,360] -> [240,360]
curve1.addPoint(gfx::Point(360, 360)); if (h >= 0 && h < 60) return 2 * h; // from red to yellow
else if (h < 120) return 60 + h; // from yellow to green
filters::ColorCurve curve2(filters::ColorCurve::Linear); else if (h < 240) return 180 + (h-120)/2; // from green to blue
for (const auto& pt : curve1) else return h; // from blue to red (same hue)
curve2.addPoint(gfx::Point(pt.y, pt.x));
map1.resize(360);
map2.resize(360);
curve1.getValues(0, 359, map1);
curve2.getValues(0, 359, map2);
}
if (hue < 0)
hue += 360;
hue %= 360;
ASSERT(hue >= 0 && hue < 360);
if (dir > 0)
return map1[hue];
else if (dir < 0)
return map2[hue];
} }
} }
return hue; return h;
} }
} // namespace app } // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2021-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -43,9 +43,14 @@ namespace app {
void setHarmony(Harmony harmony); void setHarmony(Harmony harmony);
protected: protected:
const char* getMainAreaShader() override;
const char* getBottomBarShader() override;
app::Color getMainAreaColor(const int u, const int umax, app::Color getMainAreaColor(const int u, const int umax,
const int v, const int vmax) override; const int v, const int vmax) override;
app::Color getBottomBarColor(const int u, const int umax) override; app::Color getBottomBarColor(const int u, const int umax) override;
#if SK_ENABLE_SKSL
void setShaderMainAreaParams(SkRuntimeShaderBuilder& builder) override;
#endif
void onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) override; void onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) override;
void onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc) override; void onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc) override;
void onPaintSurfaceInBgThread(os::Surface* s, void onPaintSurfaceInBgThread(os::Surface* s,
@ -65,8 +70,10 @@ namespace app {
// Converts an hue angle from HSV <-> current color model hue. // Converts an hue angle from HSV <-> current color model hue.
// With dir == +1, the angle is from the color model and it's converted to HSV hue. // With dir == +1, the angle is from the color model and it's converted to HSV hue.
// With dir == -1, the angle came from HSV and is converted to the current color model. // With dir == -1, the angle came from HSV and is converted to the current color model.
int convertHueAngle(int angle, int dir) const; float convertHueAngle(float angle, int dir) const;
std::string m_mainShader;
std::string m_bottomShader;
gfx::Rect m_wheelBounds; gfx::Rect m_wheelBounds;
gfx::Color m_bgColor; gfx::Color m_bgColor;
double m_wheelRadius; double m_wheelRadius;

View File

@ -352,8 +352,8 @@ bool DrawingState::onScrollChange(Editor* editor)
m_lastPointer = tools::Pointer(editor->screenToEditor(mousePos), m_lastPointer = tools::Pointer(editor->screenToEditor(mousePos),
m_velocity.velocity(), m_velocity.velocity(),
m_lastPointer.button(), m_lastPointer.button(),
tools::Pointer::Type::Unknown, m_lastPointer.type(),
0.0f); m_lastPointer.pressure());
handleMouseMovement(); handleMouseMovement();
} }
return true; return true;

View File

@ -227,9 +227,7 @@ bool ToolBar::onProcessMessage(Message* msg)
MouseMessage* mouseMsg2 = new MouseMessage( MouseMessage* mouseMsg2 = new MouseMessage(
kMouseDownMessage, kMouseDownMessage,
mouseMsg->pointerType(), *mouseMsg,
mouseMsg->button(),
mouseMsg->modifiers(),
mouseMsg->positionForDisplay(strip->display())); mouseMsg->positionForDisplay(strip->display()));
mouseMsg2->setRecipient(strip); mouseMsg2->setRecipient(strip);
mouseMsg2->setDisplay(strip->display()); mouseMsg2->setDisplay(strip->display());
@ -659,9 +657,7 @@ bool ToolBar::ToolStrip::onProcessMessage(Message* msg)
MouseMessage* mouseMsg2 = new MouseMessage( MouseMessage* mouseMsg2 = new MouseMessage(
kMouseDownMessage, kMouseDownMessage,
mouseMsg->pointerType(), *mouseMsg,
mouseMsg->button(),
mouseMsg->modifiers(),
mouseMsg->positionForDisplay(pick->display())); mouseMsg->positionForDisplay(pick->display()));
mouseMsg2->setRecipient(bar); mouseMsg2->setRecipient(bar);
mouseMsg2->setDisplay(pick->display()); mouseMsg2->setDisplay(pick->display());

View File

@ -24,6 +24,10 @@
#if ENABLE_SENTRY #if ENABLE_SENTRY
#include "app/sentry_wrapper.h" #include "app/sentry_wrapper.h"
#if LAF_WINDOWS
#define USE_SENTRY_BREADCRUMB_FOR_WINTAB 1
#include "os/win/wintab.h"
#endif
#else #else
#include "base/memory_dump.h" #include "base/memory_dump.h"
#endif #endif
@ -64,7 +68,31 @@ namespace {
CoUninitialize(); CoUninitialize();
} }
}; };
#endif #endif // LAF_WINDOWS
#if USE_SENTRY_BREADCRUMB_FOR_WINTAB
// Delegate to write Wintab information as a Sentry breadcrumb (to
// know if there is a specific Wintab driver giving problems)
class WintabApiDelegate : public os::WintabAPI::Delegate {
bool m_done = false;
public:
WintabApiDelegate() {
os::instance()->setWintabDelegate(this);
}
~WintabApiDelegate() {
os::instance()->setWintabDelegate(nullptr);
}
void onWintabID(const std::string& id) override {
if (!m_done) {
m_done = true;
app::Sentry::addBreadcrumb("Wintab ID=" + id);
}
}
void onWintabFields(const std::map<std::string, std::string>& fields) override {
app::Sentry::addBreadcrumb("Wintab DLL", fields);
}
};
#endif // USE_SENTRY_BREADCRUMB_FOR_WINTAB
} }
@ -99,6 +127,9 @@ int app_main(int argc, char* argv[])
#if ENABLE_SENTRY #if ENABLE_SENTRY
sentry.init(); sentry.init();
#if USE_SENTRY_BREADCRUMB_FOR_WINTAB
WintabApiDelegate wintabDelegate;
#endif
#else #else
// Change the memory dump filename to save on disk (.dmp // Change the memory dump filename to save on disk (.dmp
// file). Note: Only useful on Windows. // file). Note: Only useful on Windows.

View File

@ -536,9 +536,7 @@ bool ComboBoxEntry::onProcessMessage(Message* msg)
MouseMessage mouseMsg2( MouseMessage mouseMsg2(
kMouseDownMessage, kMouseDownMessage,
mouseMsg->pointerType(), *mouseMsg,
mouseMsg->button(),
mouseMsg->modifiers(),
mouseMsg->positionForDisplay(pick->display())); mouseMsg->positionForDisplay(pick->display()));
mouseMsg2.setDisplay(pick->display()); mouseMsg2.setDisplay(pick->display());
pick->sendMessage(&mouseMsg2); pick->sendMessage(&mouseMsg2);

View File

@ -1,5 +1,5 @@
// Aseprite UI Library // Aseprite UI Library
// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
@ -97,9 +97,7 @@ bool IntEntry::onProcessMessage(Message* msg)
releaseMouse(); releaseMouse();
MouseMessage mouseMsg2(kMouseDownMessage, MouseMessage mouseMsg2(kMouseDownMessage,
mouseMsg->pointerType(), *mouseMsg,
mouseMsg->button(),
mouseMsg->modifiers(),
mouseMsg->positionForDisplay(pick->display())); mouseMsg->positionForDisplay(pick->display()));
mouseMsg2.setDisplay(pick->display()); mouseMsg2.setDisplay(pick->display());
pick->sendMessage(&mouseMsg2); pick->sendMessage(&mouseMsg2);

View File

@ -540,7 +540,8 @@ void Manager::generateMessagesFromOSEvents()
osEvent.position(), osEvent.position(),
m_mouseButton = mouse_button_from_os_to_ui(osEvent), m_mouseButton = mouse_button_from_os_to_ui(osEvent),
osEvent.modifiers(), osEvent.modifiers(),
osEvent.pointerType()); osEvent.pointerType(),
osEvent.pressure());
break; break;
} }
@ -561,7 +562,8 @@ void Manager::generateMessagesFromOSEvents()
osEvent.position(), osEvent.position(),
m_mouseButton = mouse_button_from_os_to_ui(osEvent), m_mouseButton = mouse_button_from_os_to_ui(osEvent),
osEvent.modifiers(), osEvent.modifiers(),
osEvent.pointerType()); osEvent.pointerType(),
osEvent.pressure());
break; break;
} }
@ -634,7 +636,8 @@ void Manager::handleMouseDown(Display* display,
const gfx::Point& mousePos, const gfx::Point& mousePos,
MouseButton mouseButton, MouseButton mouseButton,
KeyModifiers modifiers, KeyModifiers modifiers,
PointerType pointerType) PointerType pointerType,
const float pressure)
{ {
handleWindowZOrder(); handleWindowZOrder();
@ -646,7 +649,10 @@ void Manager::handleMouseDown(Display* display,
mousePos, mousePos,
pointerType, pointerType,
mouseButton, mouseButton,
modifiers)); modifiers,
gfx::Point(0, 0),
false,
pressure));
} }
void Manager::handleMouseUp(Display* display, void Manager::handleMouseUp(Display* display,
@ -670,7 +676,8 @@ void Manager::handleMouseDoubleClick(Display* display,
const gfx::Point& mousePos, const gfx::Point& mousePos,
MouseButton mouseButton, MouseButton mouseButton,
KeyModifiers modifiers, KeyModifiers modifiers,
PointerType pointerType) PointerType pointerType,
const float pressure)
{ {
Widget* dst = (capture_widget ? capture_widget: mouse_widget); Widget* dst = (capture_widget ? capture_widget: mouse_widget);
if (dst) { if (dst) {
@ -678,7 +685,9 @@ void Manager::handleMouseDoubleClick(Display* display,
newMouseMessage( newMouseMessage(
kDoubleClickMessage, kDoubleClickMessage,
display, dst, mousePos, pointerType, display, dst, mousePos, pointerType,
mouseButton, modifiers)); mouseButton, modifiers,
gfx::Point(0, 0), false,
pressure));
} }
} }

View File

@ -129,7 +129,8 @@ namespace ui {
const gfx::Point& mousePos, const gfx::Point& mousePos,
MouseButton mouseButton, MouseButton mouseButton,
KeyModifiers modifiers, KeyModifiers modifiers,
PointerType pointerType); PointerType pointerType,
const float pressure);
void handleMouseUp(Display* display, void handleMouseUp(Display* display,
const gfx::Point& mousePos, const gfx::Point& mousePos,
MouseButton mouseButton, MouseButton mouseButton,
@ -139,7 +140,8 @@ namespace ui {
const gfx::Point& mousePos, const gfx::Point& mousePos,
MouseButton mouseButton, MouseButton mouseButton,
KeyModifiers modifiers, KeyModifiers modifiers,
PointerType pointerType); PointerType pointerType,
const float pressure);
void handleMouseWheel(Display* display, void handleMouseWheel(Display* display,
const gfx::Point& mousePos, const gfx::Point& mousePos,
KeyModifiers modifiers, KeyModifiers modifiers,

View File

@ -137,6 +137,19 @@ namespace ui {
m_pressure(pressure) { m_pressure(pressure) {
} }
// Copy other MouseMessage converting its type
MouseMessage(MessageType type,
const MouseMessage& other,
const gfx::Point& newPosition)
: Message(type, other.modifiers()),
m_pointerType(other.pointerType()),
m_button(other.button()),
m_pos(newPosition),
m_wheelDelta(other.wheelDelta()),
m_preciseWheel(other.preciseWheel()),
m_pressure(other.pressure()) {
}
PointerType pointerType() const { return m_pointerType; } PointerType pointerType() const { return m_pointerType; }
MouseButton button() const { return m_button; } MouseButton button() const { return m_button; }
bool left() const { return (m_button == kButtonLeft); } bool left() const { return (m_button == kButtonLeft); }

View File

@ -1462,9 +1462,7 @@ bool Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
MouseMessage* mouseMsg2 = new MouseMessage( MouseMessage* mouseMsg2 = new MouseMessage(
kMouseDownMessage, kMouseDownMessage,
mouseMsg->pointerType(), *mouseMsg,
mouseMsg->button(),
mouseMsg->modifiers(),
mouseMsg->positionForDisplay(pick->display())); mouseMsg->positionForDisplay(pick->display()));
mouseMsg2->setDisplay(pick->display()); mouseMsg2->setDisplay(pick->display());
mouseMsg2->setRecipient(pick); mouseMsg2->setRecipient(pick);
@ -1554,11 +1552,8 @@ bool Widget::onProcessMessage(Message* msg)
// Convert double clicks into mouse down // Convert double clicks into mouse down
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
MouseMessage mouseMsg2(kMouseDownMessage, MouseMessage mouseMsg2(kMouseDownMessage,
mouseMsg->pointerType(), *mouseMsg,
mouseMsg->button(), mouseMsg->position());
mouseMsg->modifiers(),
mouseMsg->position(),
mouseMsg->wheelDelta());
mouseMsg2.setDisplay(mouseMsg->display()); mouseMsg2.setDisplay(mouseMsg->display());
sendMessage(&mouseMsg2); sendMessage(&mouseMsg2);
break; break;

@ -1 +1 @@
Subproject commit a52c6df38a38c4e36ff991dfb4b7d92e48a44553 Subproject commit 3412c32b35db911832c0b396894203899f8f5157

2
third_party/pixman vendored

@ -1 +1 @@
Subproject commit eb0dfaa0c6eb54ca9f8a6d8bf63d346c0fc4f2b9 Subproject commit 285b9a907caffeb979322e629d4e57aa42061b5a