mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 06:32:42 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
22a5c4c324
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit 11ffdbd9cc6232faaff5eecd8cc628bb5a2c706f
|
||||
Subproject commit 80ec051ecf4b702d769d4b2483e1a34b52368bde
|
@ -380,7 +380,7 @@ public:
|
||||
|
||||
// If the platform supports native cursors...
|
||||
if ((int(os::instance()->capabilities()) &
|
||||
int(os::Capabilities::CustomNativeMouseCursor)) != 0) {
|
||||
int(os::Capabilities::CustomMouseCursor)) != 0) {
|
||||
if (m_pref.cursor.useNativeCursor())
|
||||
nativeCursor()->setSelected(true);
|
||||
nativeCursor()->Click.connect([this]{ onNativeCursorChange(); });
|
||||
@ -949,9 +949,9 @@ private:
|
||||
|
||||
void onNativeCursorChange() {
|
||||
bool state =
|
||||
// If the platform supports native cursors...
|
||||
// If the platform supports custom cursors...
|
||||
(((int(os::instance()->capabilities()) &
|
||||
int(os::Capabilities::CustomNativeMouseCursor)) != 0) &&
|
||||
int(os::Capabilities::CustomMouseCursor)) != 0) &&
|
||||
// If the native cursor option is not selec
|
||||
!nativeCursor()->isSelected());
|
||||
|
||||
|
@ -46,10 +46,57 @@
|
||||
#include "ui/manager.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
static int g_crosshair_pattern[7*7] = {
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
};
|
||||
|
||||
// We're going to keep a cache of native mouse cursor for each
|
||||
// possibility of the following crosshair:
|
||||
//
|
||||
// 2
|
||||
// 2
|
||||
// 22 3 22
|
||||
// 2
|
||||
// 2
|
||||
//
|
||||
// Number of crosshair cursors 2^8 * 3 + 2 = 770
|
||||
// Here the center can be black, white or hidden. When the center is
|
||||
// black or white, the crosshair can be empty.
|
||||
//
|
||||
// The index/key of this array is calculated in
|
||||
// BrushPreview::createCrosshairCursor().
|
||||
//
|
||||
// Win32: This is needed to avoid converting from a os::Surface ->
|
||||
// HCURSOR calling CreateIconIndirect() as many times as possible for
|
||||
// each mouse movement (because it's a slow function).
|
||||
//
|
||||
static std::array<os::CursorRef, 770> g_bwCursors;
|
||||
static int g_cacheCursorScale = 0;
|
||||
|
||||
// 3 cached cursors when we use a solid cursor (1 dot, crosshair
|
||||
// without dot at the center, crosshair with dot in the center)
|
||||
static std::array<os::CursorRef, 3> g_solidCursors;
|
||||
static gfx::Color g_solidCursorColor = gfx::ColorNone;
|
||||
|
||||
// static
|
||||
void BrushPreview::destroyInternals()
|
||||
{
|
||||
g_bwCursors.fill(nullptr);
|
||||
g_solidCursors.fill(nullptr);
|
||||
}
|
||||
|
||||
BrushPreview::BrushPreview(Editor* editor)
|
||||
: m_editor(editor)
|
||||
{
|
||||
@ -57,7 +104,6 @@ BrushPreview::BrushPreview(Editor* editor)
|
||||
|
||||
BrushPreview::~BrushPreview()
|
||||
{
|
||||
m_cursor.reset();
|
||||
}
|
||||
|
||||
BrushRef BrushPreview::getCurrentBrush()
|
||||
@ -351,9 +397,9 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
ui::SetClip clip(&g);
|
||||
gfx::Color uiCursorColor = color_utils::color_for_ui(appCursorColor);
|
||||
|
||||
createNativeCursor();
|
||||
if (m_cursor)
|
||||
forEachLittleCrossPixel(&g, m_screenPosition, uiCursorColor, &BrushPreview::putPixelInCursorDelegate);
|
||||
if (!(m_type & NATIVE_CROSSHAIR)) {
|
||||
createCrosshairCursor(&g, uiCursorColor);
|
||||
}
|
||||
|
||||
forEachBrushPixel(&g, spritePos, uiCursorColor, &BrushPreview::savePixelDelegate);
|
||||
forEachBrushPixel(&g, spritePos, uiCursorColor, &BrushPreview::drawPixelDelegate);
|
||||
@ -385,7 +431,7 @@ void BrushPreview::hide()
|
||||
// cursor will be changed anyway after the hide() by the caller.
|
||||
//
|
||||
//if (m_cursor)
|
||||
// m_editor->m_editor->display()->nativeWindow()->setNativeMouseCursor(os::NativeCursor::Hidden);
|
||||
// m_editor->display()->nativeWindow()->setCursor(os::NativeCursor::Hidden);
|
||||
|
||||
// Get drawable region
|
||||
m_editor->getDrawableRegion(m_clippingRegion, ui::Widget::kCutTopWindows);
|
||||
@ -484,79 +530,165 @@ void BrushPreview::generateBoundaries()
|
||||
delete mask;
|
||||
}
|
||||
|
||||
void BrushPreview::createNativeCursor()
|
||||
void BrushPreview::createCrosshairCursor(ui::Graphics* g,
|
||||
const gfx::Color cursorColor)
|
||||
{
|
||||
ASSERT(!(m_type & NATIVE_CROSSHAIR));
|
||||
|
||||
gfx::Rect cursorBounds;
|
||||
|
||||
if (m_type & CROSSHAIR) {
|
||||
cursorBounds |= gfx::Rect(-3, -3, 7, 7);
|
||||
m_cursorCenter = -cursorBounds.origin();
|
||||
}
|
||||
// Special case of a cursor for one pixel
|
||||
else if (!(m_type & NATIVE_CROSSHAIR) &&
|
||||
m_editor->zoom().scale() >= 4.0) {
|
||||
cursorBounds = gfx::Rect(0, 0, 1, 1);
|
||||
m_cursorCenter = gfx::Point(0, 0);
|
||||
}
|
||||
|
||||
if (m_cursor) {
|
||||
if (m_cursor->width() != cursorBounds.w ||
|
||||
m_cursor->height() != cursorBounds.h) {
|
||||
m_cursor.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorBounds.isEmpty()) {
|
||||
ASSERT(!m_cursor);
|
||||
if (!(m_type & NATIVE_CROSSHAIR)) {
|
||||
// TODO should we use ui::set_mouse_cursor()?
|
||||
ui::set_mouse_cursor_reset_info();
|
||||
m_editor->display()->nativeWindow()->setNativeMouseCursor(os::NativeCursor::Hidden);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_cursor) {
|
||||
m_cursor = os::instance()->makeRgbaSurface(cursorBounds.w, cursorBounds.h);
|
||||
|
||||
// Cannot clear the cursor on each iteration because it can
|
||||
// generate a flicker effect when zooming in the same mouse
|
||||
// position. That's strange.
|
||||
m_cursor->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void BrushPreview::forEachLittleCrossPixel(
|
||||
ui::Graphics* g,
|
||||
const gfx::Point& screenPos,
|
||||
gfx::Color color,
|
||||
PixelDelegate pixelDelegate)
|
||||
{
|
||||
if (m_type & CROSSHAIR)
|
||||
traceCrossPixels(g, screenPos, color, pixelDelegate);
|
||||
gfx::Point cursorCenter;
|
||||
|
||||
// Depending on the editor zoom, maybe we need subpixel movement (a
|
||||
// little dot inside the active pixel)
|
||||
if (!(m_type & NATIVE_CROSSHAIR) &&
|
||||
m_editor->zoom().scale() >= 4.0) {
|
||||
(this->*pixelDelegate)(g, screenPos, color);
|
||||
const bool requireLittleCenterDot = (m_editor->zoom().scale() >= 4.0);
|
||||
|
||||
if (m_type & CROSSHAIR) {
|
||||
// Regular crosshair of 7x7
|
||||
cursorBounds |= gfx::Rect(-3, -3, 7, 7);
|
||||
cursorCenter = -cursorBounds.origin();
|
||||
}
|
||||
else if (requireLittleCenterDot) {
|
||||
// Special case of a cursor for one pixel
|
||||
cursorBounds = gfx::Rect(0, 0, 1, 1);
|
||||
cursorCenter = gfx::Point(0, 0);
|
||||
}
|
||||
else {
|
||||
// We'll remove the pixel (as we didn't called Surface::clear() to
|
||||
// avoid a flickering issue when zooming in the same mouse
|
||||
// position).
|
||||
base::ScopedValue<bool> restore(m_blackAndWhiteNegative, false,
|
||||
m_blackAndWhiteNegative);
|
||||
(this->*pixelDelegate)(g, screenPos, gfx::ColorNone);
|
||||
}
|
||||
|
||||
if (m_cursor) {
|
||||
// TODO should we use ui::set_mouse_cursor()?
|
||||
ui::set_mouse_cursor_reset_info();
|
||||
m_editor->display()->nativeWindow()->setNativeMouseCursor(
|
||||
m_cursor.get(),
|
||||
m_cursorCenter,
|
||||
m_editor->display()->nativeWindow()->scale());
|
||||
m_editor->display()->nativeWindow()->setCursor(os::NativeCursor::Hidden);
|
||||
return;
|
||||
}
|
||||
|
||||
os::Window* window = m_editor->display()->nativeWindow();
|
||||
const int scale = window->scale();
|
||||
os::CursorRef cursor = nullptr;
|
||||
|
||||
// Invalidate the entire cache if the scale has changed
|
||||
if (g_cacheCursorScale != scale) {
|
||||
g_cacheCursorScale = scale;
|
||||
g_bwCursors.fill(nullptr);
|
||||
g_solidCursors.fill(nullptr);
|
||||
}
|
||||
|
||||
// Cursor with black/white colors (we create a key/index for
|
||||
// g_cachedCursors depending on the colors on the screen)
|
||||
if (m_blackAndWhiteNegative) {
|
||||
int k = 0;
|
||||
if (m_type & CROSSHAIR) {
|
||||
int bit = 0;
|
||||
for (int v=0; v<7; v++) {
|
||||
for (int u=0; u<7; u++) {
|
||||
if (g_crosshair_pattern[v*7+u]) {
|
||||
color_t c = g->getPixel(m_screenPosition.x-3+u,
|
||||
m_screenPosition.y-3+v);
|
||||
c = color_utils::blackandwhite_neg(c);
|
||||
if (rgba_getr(c) == 255) { // White
|
||||
k |= (1 << bit);
|
||||
}
|
||||
++bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requireLittleCenterDot) {
|
||||
color_t c = g->getPixel(m_screenPosition.x,
|
||||
m_screenPosition.y);
|
||||
c = color_utils::blackandwhite_neg(c);
|
||||
if (rgba_getr(c) == 255) { // White
|
||||
k |= (m_type & CROSSHAIR ? 0x200: 0x301);
|
||||
}
|
||||
else { // Black
|
||||
k |= (m_type & CROSSHAIR ? 0x100: 0x300);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(k < int(g_bwCursors.size()));
|
||||
if (k >= int(g_bwCursors.size())) // Unexpected key value in release mode
|
||||
return;
|
||||
|
||||
// Use cached cursor
|
||||
if (g_bwCursors[k]) {
|
||||
cursor = g_bwCursors[k];
|
||||
}
|
||||
else {
|
||||
const gfx::Color black = gfx::rgba(0, 0, 0);
|
||||
const gfx::Color white = gfx::rgba(255, 255, 255);
|
||||
os::SurfaceRef cursorSurface =
|
||||
os::instance()->makeRgbaSurface(cursorBounds.w,
|
||||
cursorBounds.h);
|
||||
cursorSurface->clear();
|
||||
int bit = 0;
|
||||
if (m_type & CROSSHAIR) {
|
||||
for (int v=0; v<7; v++) {
|
||||
for (int u=0; u<7; u++) {
|
||||
if (g_crosshair_pattern[v*7+u]) {
|
||||
cursorSurface->putPixel(
|
||||
(k & (1 << bit) ? white: black), u, v);
|
||||
++bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requireLittleCenterDot) {
|
||||
cursorSurface->putPixel(
|
||||
(k == 0x100 || k == 0x300 ? black: white),
|
||||
cursorBounds.w/2, cursorBounds.h/2);
|
||||
}
|
||||
|
||||
cursor = g_bwCursors[k] =
|
||||
os::instance()->makeCursor(
|
||||
cursorSurface.get(),
|
||||
cursorCenter,
|
||||
scale);
|
||||
}
|
||||
}
|
||||
// Cursor with solid color (easiest case, we don't have to check the
|
||||
// colors in the screen to create the crosshair)
|
||||
else {
|
||||
// We have to recreate all cursors if the color has changed.
|
||||
if (g_solidCursorColor != cursorColor) {
|
||||
g_solidCursors.fill(nullptr);
|
||||
g_solidCursorColor = cursorColor;
|
||||
}
|
||||
|
||||
int k = 0;
|
||||
if (m_type & CROSSHAIR) {
|
||||
if (requireLittleCenterDot)
|
||||
k = 2;
|
||||
else
|
||||
k = 1;
|
||||
}
|
||||
|
||||
// Use cached cursor
|
||||
if (g_solidCursors[k]) {
|
||||
cursor = g_solidCursors[k];
|
||||
}
|
||||
else {
|
||||
os::SurfaceRef cursorSurface =
|
||||
os::instance()->makeRgbaSurface(cursorBounds.w,
|
||||
cursorBounds.h);
|
||||
cursorSurface->clear();
|
||||
if (m_type & CROSSHAIR) {
|
||||
for (int v=0; v<7; v++)
|
||||
for (int u=0; u<7; u++)
|
||||
if (g_crosshair_pattern[v*7+u])
|
||||
cursorSurface->putPixel(cursorColor, u, v);
|
||||
}
|
||||
if (requireLittleCenterDot)
|
||||
cursorSurface->putPixel(cursorColor, cursorBounds.w/2, cursorBounds.h/2);
|
||||
|
||||
cursor = g_solidCursors[k] =
|
||||
os::instance()->makeCursor(
|
||||
cursorSurface.get(),
|
||||
cursorCenter,
|
||||
scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor) {
|
||||
// TODO should we use ui::set_mouse_cursor()?
|
||||
ui::set_mouse_cursor_reset_info();
|
||||
window->setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,34 +709,6 @@ void BrushPreview::forEachBrushPixel(
|
||||
m_savedPixelsLimit = m_savedPixelsIterator;
|
||||
}
|
||||
|
||||
void BrushPreview::traceCrossPixels(
|
||||
ui::Graphics* g,
|
||||
const gfx::Point& pt, gfx::Color color,
|
||||
PixelDelegate pixelDelegate)
|
||||
{
|
||||
static int cross[7*7] = {
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 0, 0, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0, 0,
|
||||
};
|
||||
gfx::Point out;
|
||||
int u, v;
|
||||
|
||||
for (v=0; v<7; v++) {
|
||||
for (u=0; u<7; u++) {
|
||||
if (cross[v*7+u]) {
|
||||
out.x = pt.x-3+u;
|
||||
out.y = pt.y-3+v;
|
||||
(this->*pixelDelegate)(g, out, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Old thick cross (used for selection tools)
|
||||
void BrushPreview::traceSelectionCrossPixels(
|
||||
ui::Graphics* g,
|
||||
@ -673,30 +777,6 @@ void BrushPreview::traceBrushBoundaries(ui::Graphics* g,
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Pixel delegates
|
||||
|
||||
void BrushPreview::putPixelInCursorDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color)
|
||||
{
|
||||
ASSERT(m_cursor);
|
||||
|
||||
if (!m_clippingRegion.contains(pt))
|
||||
return;
|
||||
|
||||
if (m_blackAndWhiteNegative) {
|
||||
color_t c = g->getPixel(pt.x, pt.y);
|
||||
int r = gfx::getr(c);
|
||||
int g = gfx::getg(c);
|
||||
int b = gfx::getb(c);
|
||||
|
||||
m_cursor->putPixel(color_utils::blackandwhite_neg(gfx::rgba(r, g, b)),
|
||||
pt.x - m_screenPosition.x + m_cursorCenter.x,
|
||||
pt.y - m_screenPosition.y + m_cursorCenter.y);
|
||||
}
|
||||
else {
|
||||
m_cursor->putPixel(color,
|
||||
pt.x - m_screenPosition.x + m_cursorCenter.x,
|
||||
pt.y - m_screenPosition.y + m_cursorCenter.y);
|
||||
}
|
||||
}
|
||||
|
||||
void BrushPreview::savePixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color)
|
||||
{
|
||||
if (m_clippingRegion.contains(pt)) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "gfx/rect.h"
|
||||
#include "gfx/region.h"
|
||||
#include "os/surface.h"
|
||||
#include "ui/cursor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -68,6 +69,8 @@ namespace app {
|
||||
NATIVE_CROSSHAIR = 8,
|
||||
};
|
||||
|
||||
static void destroyInternals();
|
||||
|
||||
BrushPreview(Editor* editor);
|
||||
~BrushPreview();
|
||||
|
||||
@ -90,23 +93,17 @@ namespace app {
|
||||
void generateBoundaries();
|
||||
|
||||
// Creates a little native cursor to draw the CROSSHAIR
|
||||
void createNativeCursor();
|
||||
void forEachLittleCrossPixel(
|
||||
ui::Graphics* g,
|
||||
const gfx::Point& screenPos,
|
||||
gfx::Color color,
|
||||
PixelDelegate pixelDelegate);
|
||||
void createCrosshairCursor(ui::Graphics* g, const gfx::Color cursorColor);
|
||||
|
||||
void forEachBrushPixel(
|
||||
ui::Graphics* g,
|
||||
const gfx::Point& spritePos,
|
||||
gfx::Color color,
|
||||
PixelDelegate pixelDelegate);
|
||||
|
||||
void traceCrossPixels(ui::Graphics* g, const gfx::Point& pt, gfx::Color color, PixelDelegate pixel);
|
||||
void traceSelectionCrossPixels(ui::Graphics* g, const gfx::Point& pt, gfx::Color color, int thickness, PixelDelegate pixel);
|
||||
void traceBrushBoundaries(ui::Graphics* g, gfx::Point pos, gfx::Color color, PixelDelegate pixel);
|
||||
|
||||
void putPixelInCursorDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
|
||||
void savePixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
|
||||
void drawPixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
|
||||
void clearPixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
|
||||
@ -125,10 +122,6 @@ namespace app {
|
||||
gfx::Point m_screenPosition; // Position in the screen (view)
|
||||
gfx::Point m_editorPosition; // Position in the editor (model)
|
||||
|
||||
// Native mouse cursor to draw crosshair
|
||||
os::SurfaceRef m_cursor;
|
||||
gfx::Point m_cursorCenter;
|
||||
|
||||
// Information about current brush
|
||||
doc::MaskBoundaries m_brushBoundaries;
|
||||
int m_brushGen;
|
||||
|
@ -233,6 +233,7 @@ Editor::~Editor()
|
||||
|
||||
void Editor::destroyEditorSharedInternals()
|
||||
{
|
||||
BrushPreview::destroyInternals();
|
||||
if (m_renderEngine) {
|
||||
delete m_renderEngine;
|
||||
m_renderEngine = nullptr;
|
||||
|
@ -222,12 +222,12 @@ SkinTheme* SkinTheme::instance()
|
||||
|
||||
SkinTheme::SkinTheme()
|
||||
: m_sheet(nullptr)
|
||||
, m_standardCursors(ui::kCursorTypes, nullptr)
|
||||
, m_defaultFont(nullptr)
|
||||
, m_miniFont(nullptr)
|
||||
, m_preferredScreenScaling(-1)
|
||||
, m_preferredUIScaling(-1)
|
||||
{
|
||||
m_standardCursors.fill(nullptr);
|
||||
}
|
||||
|
||||
SkinTheme::~SkinTheme()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -12,15 +12,17 @@
|
||||
#include "app/ui/skin/skin_part.h"
|
||||
#include "gfx/color.h"
|
||||
#include "gfx/fwd.h"
|
||||
#include "ui/cursor.h"
|
||||
#include "ui/cursor_type.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/scale.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
#include "theme.xml.h"
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ui {
|
||||
class Entry;
|
||||
@ -155,7 +157,7 @@ namespace app {
|
||||
std::map<std::string, gfx::Color> m_colors_by_id;
|
||||
std::map<std::string, int> m_dimensions_by_id;
|
||||
std::map<std::string, ui::Cursor*> m_cursors;
|
||||
std::vector<ui::Cursor*> m_standardCursors;
|
||||
std::array<ui::Cursor*, ui::kCursorTypes> m_standardCursors;
|
||||
std::map<std::string, ui::Style*> m_styles;
|
||||
std::map<std::string, FontData*> m_fonts;
|
||||
std::map<std::string, os::FontRef> m_themeFonts;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -13,14 +13,36 @@
|
||||
|
||||
#include "base/debug.h"
|
||||
#include "os/surface.h"
|
||||
#include "os/system.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
Cursor::Cursor(const os::SurfaceRef& surface, const gfx::Point& focus)
|
||||
Cursor::Cursor(const os::SurfaceRef& surface,
|
||||
const gfx::Point& focus)
|
||||
: m_surface(surface)
|
||||
, m_focus(focus)
|
||||
, m_scale(0)
|
||||
{
|
||||
ASSERT(m_surface != nullptr);
|
||||
}
|
||||
|
||||
void Cursor::reset()
|
||||
{
|
||||
m_surface.reset();
|
||||
m_cursor.reset();
|
||||
m_focus = gfx::Point(0, 0);
|
||||
m_scale = 0;
|
||||
}
|
||||
|
||||
os::CursorRef Cursor::nativeCursor(const int scale) const
|
||||
{
|
||||
if (m_cursor && m_scale == scale)
|
||||
return m_cursor;
|
||||
|
||||
m_cursor = os::instance()->makeCursor(
|
||||
m_surface.get(),
|
||||
m_focus,
|
||||
m_scale = scale);
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -10,22 +10,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "gfx/point.h"
|
||||
#include "os/cursor.h"
|
||||
#include "os/surface.h"
|
||||
|
||||
namespace os { class Surface; }
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Cursor {
|
||||
public:
|
||||
Cursor(const os::SurfaceRef& surface, const gfx::Point& focus);
|
||||
Cursor(const os::SurfaceRef& surface = nullptr,
|
||||
const gfx::Point& focus = gfx::Point(0, 0));
|
||||
|
||||
const os::SurfaceRef& getSurface() const { return m_surface; }
|
||||
const gfx::Point& getFocus() const { return m_focus; }
|
||||
const os::SurfaceRef& surface() const { return m_surface; }
|
||||
const gfx::Point& focus() const { return m_focus; }
|
||||
os::CursorRef nativeCursor(const int scale) const;
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
os::SurfaceRef m_surface;
|
||||
gfx::Point m_focus;
|
||||
mutable os::CursorRef m_cursor;
|
||||
mutable int m_scale;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
@ -60,14 +60,14 @@ static void update_mouse_overlay(const Cursor* cursor)
|
||||
ASSERT(mouse_display);
|
||||
mouse_cursor_overlay = base::make_ref<Overlay>(
|
||||
mouse_display,
|
||||
mouse_cursor->getSurface(),
|
||||
mouse_cursor->surface(),
|
||||
mouse_display->nativeWindow()->pointFromScreen(get_mouse_position()),
|
||||
Overlay::MouseZOrder);
|
||||
|
||||
OverlayManager::instance()->addOverlay(mouse_cursor_overlay);
|
||||
}
|
||||
else {
|
||||
mouse_cursor_overlay->setSurface(mouse_cursor->getSurface());
|
||||
mouse_cursor_overlay->setSurface(mouse_cursor->surface());
|
||||
update_cursor_overlay();
|
||||
}
|
||||
}
|
||||
@ -84,19 +84,19 @@ static bool set_native_cursor_on_all_displays(Display* display,
|
||||
bool result = false;
|
||||
while (display) {
|
||||
os::Window* nativeWindow = display->nativeWindow();
|
||||
if (cursor) {
|
||||
result |= nativeWindow->setNativeMouseCursor(
|
||||
// The surface is already scaled by guiscale()
|
||||
cursor->getSurface().get(),
|
||||
cursor->getFocus(),
|
||||
// We scale the cursor by the os::Display scale
|
||||
nativeWindow->scale() * mouse_cursor_scale);
|
||||
|
||||
if (cursor && cursor->surface()) {
|
||||
// The cursor surface is already scaled by guiscale(), we scale
|
||||
// the cursor by the os::Window scale and mouse scale.
|
||||
const int scale = nativeWindow->scale() * mouse_cursor_scale;
|
||||
if (auto osCursor = cursor->nativeCursor(scale))
|
||||
result |= nativeWindow->setCursor(osCursor);
|
||||
}
|
||||
else if (mouse_cursor_type == kOutsideDisplay) {
|
||||
result |= nativeWindow->setNativeMouseCursor(os::NativeCursor::Arrow);
|
||||
result |= nativeWindow->setCursor(os::NativeCursor::Arrow);
|
||||
}
|
||||
else {
|
||||
result |= nativeWindow->setNativeMouseCursor(os::NativeCursor::Hidden);
|
||||
result |= nativeWindow->setCursor(os::NativeCursor::Hidden);
|
||||
}
|
||||
display = display->parentDisplay();
|
||||
}
|
||||
@ -110,10 +110,10 @@ static bool set_native_cursor_on_all_displays(Display* display,
|
||||
while (display) {
|
||||
os::Window* nativeWindow = display->nativeWindow();
|
||||
if (mouse_cursor_type == kOutsideDisplay) {
|
||||
result |= nativeWindow->setNativeMouseCursor(os::NativeCursor::Arrow);
|
||||
result |= nativeWindow->setCursor(os::NativeCursor::Arrow);
|
||||
}
|
||||
else {
|
||||
result |= nativeWindow->setNativeMouseCursor(cursor);
|
||||
result |= nativeWindow->setCursor(cursor);
|
||||
}
|
||||
display = display->parentDisplay();
|
||||
}
|
||||
@ -223,7 +223,7 @@ UISystem::UISystem()
|
||||
support_native_custom_cursor =
|
||||
((os::instance() &&
|
||||
(int(os::instance()->capabilities()) &
|
||||
int(os::Capabilities::CustomNativeMouseCursor))) ?
|
||||
int(os::Capabilities::CustomMouseCursor))) ?
|
||||
true: false);
|
||||
|
||||
details::initWidgets();
|
||||
@ -231,8 +231,6 @@ UISystem::UISystem()
|
||||
|
||||
UISystem::~UISystem()
|
||||
{
|
||||
OverlayManager::destroyInstance();
|
||||
|
||||
// finish theme
|
||||
set_theme(nullptr, guiscale());
|
||||
|
||||
@ -242,6 +240,8 @@ UISystem::~UISystem()
|
||||
if (!update_custom_native_cursor(nullptr))
|
||||
update_mouse_overlay(nullptr);
|
||||
|
||||
OverlayManager::destroyInstance();
|
||||
|
||||
ASSERT(g_instance == this);
|
||||
g_instance = nullptr;
|
||||
}
|
||||
@ -288,7 +288,7 @@ void update_cursor_overlay()
|
||||
if (mouse_cursor_overlay != nullptr && mouse_scares == 0) {
|
||||
gfx::Point newPos =
|
||||
mouse_display->nativeWindow()->pointFromScreen(get_mouse_position())
|
||||
- mouse_cursor->getFocus();
|
||||
- mouse_cursor->focus();
|
||||
|
||||
if (newPos != mouse_cursor_overlay->position()) {
|
||||
mouse_cursor_overlay->moveOverlay(newPos);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -59,7 +59,7 @@ namespace ui {
|
||||
virtual os::Font* getDefaultFont() const = 0;
|
||||
virtual os::Font* getWidgetFont(const Widget* widget) const = 0;
|
||||
|
||||
virtual Cursor* getStandardCursor(CursorType type) = 0;
|
||||
virtual ui::Cursor* getStandardCursor(CursorType type) = 0;
|
||||
virtual void initWidget(Widget* widget) = 0;
|
||||
virtual void getWindowMask(Widget* widget, gfx::Region& region) = 0;
|
||||
virtual void setDecorativeWidgetBounds(Widget* widget);
|
||||
|
Loading…
x
Reference in New Issue
Block a user