From c42c5e1453357ba7176cdba1322eda0efafdb4a5 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 7 Jul 2020 19:06:48 -0300 Subject: [PATCH] Backport new laf API to main branch of aseprite Some features from the beta branch of aseprite & laf were backported to the main branch of aseprite. Related commits: - New memory handling (db4504e816ffccf0ea63a78737ebb6e22cc0453b) - New get event with timeout (e6ec13cc31e6e689040bc651f98ee1752834d14c) - Convert os::NativeCursor to an enum (06a5b4f3aebfafb6363ea33d349975d6e419ca7b) - Adapt code to the new os::Display -> os::Window refactor (5d31314cdb23f314391e5eaebd7cea84f5179ac7) - Save/load main window layout correctly and limit to current workarea (d6acb9e20f11fda938959c99285fe4f7d7051794) - Redraw window immediately on "live resizing" (d0b39ebade7736d47e6b2450bf68b088c0da8e57) --- docs/CODING_STYLE.md | 4 +- laf | 2 +- src/app/app.cpp | 13 +- src/app/app_menus.cpp | 60 +++--- src/app/app_menus.h | 13 +- src/app/cmd/assign_color_profile.cpp | 4 +- src/app/cmd/assign_color_profile.h | 8 +- src/app/cmd/convert_color_profile.cpp | 24 +-- src/app/cmd/convert_color_profile.h | 10 +- src/app/color_spaces.cpp | 22 +-- src/app/color_spaces.h | 18 +- src/app/commands/cmd_fullscreen_preview.cpp | 9 +- src/app/commands/cmd_options.cpp | 19 +- src/app/commands/cmd_sprite_properties.cpp | 4 +- src/app/commands/screenshot.cpp | 8 +- src/app/console.cpp | 3 +- src/app/crash/read_document.cpp | 6 +- src/app/crash/write_document.cpp | 2 +- src/app/doc.cpp | 12 +- src/app/doc.h | 4 +- src/app/doc_exporter.cpp | 2 +- src/app/file/ase_format.cpp | 2 +- src/app/file/file.cpp | 2 +- src/app/file/file_op_config.h | 2 +- src/app/file/jpeg_format.cpp | 6 +- src/app/file/png_format.cpp | 4 +- src/app/file_selector.cpp | 10 +- src/app/file_system.cpp | 28 +-- src/app/file_system.h | 14 +- src/app/modules/gui.cpp | 199 ++++++++++++++------ src/app/modules/gui.h | 2 +- src/app/script/image_spec_class.cpp | 4 +- src/app/script/sprite_class.cpp | 4 +- src/app/thumbnail_generator.cpp | 6 +- src/app/thumbnails.cpp | 8 +- src/app/thumbnails.h | 7 +- src/app/ui/app_menuitem.cpp | 32 +--- src/app/ui/app_menuitem.h | 13 +- src/app/ui/brush_popup.cpp | 6 +- src/app/ui/brush_popup.h | 4 +- src/app/ui/button_set.cpp | 2 +- src/app/ui/color_selector.cpp | 22 +-- src/app/ui/dithering_selector.cpp | 18 +- src/app/ui/draggable_widget.h | 17 +- src/app/ui/editor/brush_preview.cpp | 19 +- src/app/ui/editor/brush_preview.h | 3 +- src/app/ui/editor/editor.cpp | 15 +- src/app/ui/editor/zooming_state.cpp | 5 +- src/app/ui/file_list.cpp | 16 +- src/app/ui/font_popup.cpp | 9 +- src/app/ui/main_window.cpp | 10 +- src/app/ui/palette_view.cpp | 2 +- src/app/ui/palettes_listbox.cpp | 2 +- src/app/ui/search_entry.cpp | 2 +- src/app/ui/skin/font_data.cpp | 30 +-- src/app/ui/skin/font_data.h | 6 +- src/app/ui/skin/skin_part.cpp | 10 +- src/app/ui/skin/skin_part.h | 15 +- src/app/ui/skin/skin_theme.cpp | 59 +++--- src/app/ui/skin/skin_theme.h | 19 +- src/app/ui/tabs.cpp | 14 +- src/app/ui/tabs.h | 3 +- src/app/ui/timeline/timeline.cpp | 10 +- src/app/util/clipboard_native.cpp | 5 +- src/app/widget_loader.cpp | 4 +- src/dio/aseprite_decoder.cpp | 2 +- src/doc/image.h | 4 +- src/doc/image_spec.h | 10 +- src/doc/sprite.cpp | 2 +- src/doc/sprite.h | 4 +- src/main/main.cpp | 3 +- src/tests/test.h | 2 +- src/ui/cursor.cpp | 8 +- src/ui/cursor.h | 10 +- src/ui/graphics.cpp | 63 ++++--- src/ui/graphics.h | 16 +- src/ui/image_view.cpp | 11 +- src/ui/image_view.h | 7 +- src/ui/manager.cpp | 56 +++--- src/ui/manager.h | 14 +- src/ui/message_loop.cpp | 17 +- src/ui/move_region.cpp | 12 +- src/ui/overlay.cpp | 28 +-- src/ui/overlay.h | 27 ++- src/ui/overlay_manager.cpp | 22 +-- src/ui/overlay_manager.h | 13 +- src/ui/style.cpp | 8 + src/ui/style.h | 21 ++- src/ui/system.cpp | 59 +++--- src/ui/system.h | 6 +- src/ui/theme.cpp | 7 +- src/ui/timer.cpp | 26 ++- src/ui/timer.h | 4 +- src/ui/view.cpp | 4 +- src/ui/widget.cpp | 37 ++-- src/ui/widget.h | 7 +- 96 files changed, 717 insertions(+), 710 deletions(-) diff --git a/docs/CODING_STYLE.md b/docs/CODING_STYLE.md index 5c1e66614..b0d5d8f78 100644 --- a/docs/CODING_STYLE.md +++ b/docs/CODING_STYLE.md @@ -136,10 +136,10 @@ We are using some modern C++ (C++11, C++14, etc.) features, mainly: * Use range-based for loops (`for (const auto& item : values) { ... }`) * Use template alias (`template alias = orig;`) * Use non-generic lambda functions -* Use `std::shared_ptr` and `std::unique_ptr` +* Use `std::shared_ptr`, `std::unique_ptr`, or `base::Ref` * Use `base::clamp` (no `std::clamp` yet) * Use `static constexpr T v = ...;` * You can use ``, ``, ``, and `` -* We can use `using T = ...;` instead of `typedef ... T` +* Prefer `using T = ...;` instead of `typedef ... T` * We use gcc 9.2 or clang 9.0 on Linux, so check the features available in https://en.cppreference.com/w/cpp/compiler_support diff --git a/laf b/laf index 55158abc7..11ffdbd9c 160000 --- a/laf +++ b/laf @@ -1 +1 @@ -Subproject commit 55158abc7fc962498873d5a5a97f879cf62ba4fa +Subproject commit 11ffdbd9cc6232faaff5eecd8cc628bb5a2c706f diff --git a/src/app/app.cpp b/src/app/app.cpp index 581dbd776..3d59a5f28 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -60,10 +60,10 @@ #include "base/split_string.h" #include "doc/sprite.h" #include "fmt/format.h" -#include "os/display.h" #include "os/error.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "render/render.h" #include "ui/intern.h" #include "ui/ui.h" @@ -358,7 +358,7 @@ void App::run() if (isGui()) { #if LAF_WINDOWS // How to interpret one finger on Windows tablets. - ui::Manager::getDefault()->getDisplay() + ui::Manager::getDefault()->display() ->setInterpretOneFingerGestureAsMouseMovement( preferences().experimental.oneFingerAsMouseMovement()); #endif @@ -366,23 +366,20 @@ void App::run() #if LAF_LINUX // Setup app icon for Linux window managers try { - os::Display* display = os::instance()->defaultDisplay(); + os::Window* display = os::instance()->defaultWindow(); os::SurfaceList icons; for (const int size : { 32, 64, 128 }) { ResourceFinder rf; rf.includeDataDir(fmt::format("icons/ase{0}.png", size).c_str()); if (rf.findFirst()) { - os::Surface* surf = os::instance()->loadRgbaSurface(rf.filename().c_str()); + os::SurfaceRef surf = os::instance()->loadRgbaSurface(rf.filename().c_str()); if (surf) icons.push_back(surf); } } display->setIcons(icons); - - for (auto surf : icons) - surf->dispose(); } catch (const std::exception&) { // Just ignore the exception, we couldn't change the app icon, no @@ -668,7 +665,7 @@ void App::updateDisplayTitleBar() } title += defaultTitle; - os::instance()->defaultDisplay()->setTitle(title); + os::instance()->defaultWindow()->setTitle(title); } InputChain& App::inputChain() diff --git a/src/app/app_menus.cpp b/src/app/app_menus.cpp index 051f78d37..c2418d849 100644 --- a/src/app/app_menus.cpp +++ b/src/app/app_menus.cpp @@ -317,12 +317,6 @@ AppMenus::AppMenus() [this]{ rebuildRecentList(); }); } -AppMenus::~AppMenus() -{ - if (m_osMenu) - m_osMenu->dispose(); -} - void AppMenus::reload() { MENUS_TRACE("MENUS: AppMenus::reload()"); @@ -554,10 +548,10 @@ bool AppMenus::rebuildRecentList() // Sync native menus if (owner->native() && owner->native()->menuItem) { - os::Menus* menus = os::instance()->menus(); - os::Menu* osMenu = (menus ? menus->createMenu(): nullptr); + auto menus = os::instance()->menus(); + os::MenuRef osMenu = (menus ? menus->makeMenu(): nullptr); if (osMenu) { - createNativeSubmenus(osMenu, menu); + createNativeSubmenus(osMenu.get(), menu); owner->native()->menuItem->setSubmenu(osMenu); } } @@ -817,8 +811,9 @@ void AppMenus::createNativeMenus() if (!menus) // This platform doesn't support native menu items return; - os::Menu* oldOSMenu = m_osMenu; - m_osMenu = menus->createMenu(); + // Save a reference to the old menu to avoid destroying it. + os::MenuRef oldOSMenu = m_osMenu; + m_osMenu = menus->makeMenu(); #ifdef __APPLE__ // Create default macOS app menus (App ... Window) { @@ -854,24 +849,24 @@ void AppMenus::createNativeMenus() os::MenuItemInfo quit(fmt::format("Quit {}", get_app_name()), os::MenuItemInfo::Quit); quit.shortcut = os::Shortcut('q', os::kKeyCmdModifier); - os::Menu* appMenu = menus->createMenu(); - appMenu->addItem(menus->createMenuItem(about)); - appMenu->addItem(menus->createMenuItem(os::MenuItemInfo(os::MenuItemInfo::Separator))); - appMenu->addItem(menus->createMenuItem(preferences)); - appMenu->addItem(menus->createMenuItem(os::MenuItemInfo(os::MenuItemInfo::Separator))); - appMenu->addItem(menus->createMenuItem(hide)); - appMenu->addItem(menus->createMenuItem(os::MenuItemInfo("Hide Others", os::MenuItemInfo::HideOthers))); - appMenu->addItem(menus->createMenuItem(os::MenuItemInfo("Show All", os::MenuItemInfo::ShowAll))); - appMenu->addItem(menus->createMenuItem(os::MenuItemInfo(os::MenuItemInfo::Separator))); - appMenu->addItem(menus->createMenuItem(quit)); + os::MenuRef appMenu = menus->makeMenu(); + appMenu->addItem(menus->makeMenuItem(about)); + appMenu->addItem(menus->makeMenuItem(os::MenuItemInfo(os::MenuItemInfo::Separator))); + appMenu->addItem(menus->makeMenuItem(preferences)); + appMenu->addItem(menus->makeMenuItem(os::MenuItemInfo(os::MenuItemInfo::Separator))); + appMenu->addItem(menus->makeMenuItem(hide)); + appMenu->addItem(menus->makeMenuItem(os::MenuItemInfo("Hide Others", os::MenuItemInfo::HideOthers))); + appMenu->addItem(menus->makeMenuItem(os::MenuItemInfo("Show All", os::MenuItemInfo::ShowAll))); + appMenu->addItem(menus->makeMenuItem(os::MenuItemInfo(os::MenuItemInfo::Separator))); + appMenu->addItem(menus->makeMenuItem(quit)); - os::MenuItem* appItem = menus->createMenuItem(os::MenuItemInfo("App")); + os::MenuItemRef appItem = menus->makeMenuItem(os::MenuItemInfo("App")); appItem->setSubmenu(appMenu); m_osMenu->addItem(appItem); } #endif - createNativeSubmenus(m_osMenu, m_rootMenu.get()); + createNativeSubmenus(m_osMenu.get(), m_rootMenu.get()); #ifdef __APPLE__ { @@ -889,11 +884,11 @@ void AppMenus::createNativeMenus() os::MenuItemInfo minimize("Minimize", os::MenuItemInfo::Minimize); minimize.shortcut = os::Shortcut('m', os::kKeyCmdModifier); - os::Menu* windowMenu = menus->createMenu(); - windowMenu->addItem(menus->createMenuItem(minimize)); - windowMenu->addItem(menus->createMenuItem(os::MenuItemInfo("Zoom", os::MenuItemInfo::Zoom))); + os::MenuRef windowMenu = menus->makeMenu(); + windowMenu->addItem(menus->makeMenuItem(minimize)); + windowMenu->addItem(menus->makeMenuItem(os::MenuItemInfo("Zoom", os::MenuItemInfo::Zoom))); - os::MenuItem* windowItem = menus->createMenuItem(os::MenuItemInfo("Window")); + os::MenuItemRef windowItem = menus->makeMenuItem(os::MenuItemInfo("Window")); windowItem->setSubmenu(windowMenu); // We use helpIndex+1 because the first index in m_osMenu is the @@ -904,10 +899,11 @@ void AppMenus::createNativeMenus() menus->setAppMenu(m_osMenu); if (oldOSMenu) - oldOSMenu->dispose(); + oldOSMenu.reset(); } -void AppMenus::createNativeSubmenus(os::Menu* osMenu, const ui::Menu* uiMenu) +void AppMenus::createNativeSubmenus(os::Menu* osMenu, + const ui::Menu* uiMenu) { os::Menus* menus = os::instance()->menus(); @@ -951,7 +947,7 @@ void AppMenus::createNativeSubmenus(os::Menu* osMenu, const ui::Menu* uiMenu) continue; } - os::MenuItem* osItem = menus->createMenuItem(info); + os::MenuItemRef osItem = menus->makeMenuItem(info); if (osItem) { osMenu->addItem(osItem); if (appMenuItem) { @@ -961,8 +957,8 @@ void AppMenus::createNativeSubmenus(os::Menu* osMenu, const ui::Menu* uiMenu) if (child->type() == ui::kMenuItemWidget && ((ui::MenuItem*)child)->hasSubmenu()) { - os::Menu* osSubmenu = menus->createMenu(); - createNativeSubmenus(osSubmenu, ((ui::MenuItem*)child)->getSubmenu()); + os::MenuRef osSubmenu = menus->makeMenu(); + createNativeSubmenus(osSubmenu.get(), ((ui::MenuItem*)child)->getSubmenu()); osItem->setSubmenu(osSubmenu); } } diff --git a/src/app/app_menus.h b/src/app/app_menus.h index 8991b8e5a..be2da37ee 100644 --- a/src/app/app_menus.h +++ b/src/app/app_menus.h @@ -14,6 +14,7 @@ #include "app/widget_type_mismatch.h" #include "base/disable_copying.h" #include "obs/connection.h" +#include "os/menus.h" #include "ui/base.h" #include "ui/menu.h" @@ -22,11 +23,6 @@ class TiXmlElement; class TiXmlHandle; -namespace os { - class Menu; - class Shortcut; -} - namespace app { class Command; class Params; @@ -41,8 +37,6 @@ namespace app { public: static AppMenus* instance(); - ~AppMenus(); - void reload(); void initTheme(); @@ -83,7 +77,8 @@ namespace app { void syncNativeMenuItemKeyShortcuts(Menu* menu); void updateMenusList(); void createNativeMenus(); - void createNativeSubmenus(os::Menu* osMenu, const ui::Menu* uiMenu); + void createNativeSubmenus(os::Menu* osMenu, + const ui::Menu* uiMenu); #ifdef ENABLE_SCRIPTING void loadScriptsSubmenu(ui::Menu* menu, @@ -118,7 +113,7 @@ namespace app { std::map m_groups; // Native main menu bar (== nullptr if the platform doesn't // support native menus) - os::Menu* m_osMenu; + os::MenuRef m_osMenu; XmlTranslator m_xmlTranslator; }; diff --git a/src/app/cmd/assign_color_profile.cpp b/src/app/cmd/assign_color_profile.cpp index ff6e96223..686ba1ac2 100644 --- a/src/app/cmd/assign_color_profile.cpp +++ b/src/app/cmd/assign_color_profile.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -17,7 +17,7 @@ namespace app { namespace cmd { -AssignColorProfile::AssignColorProfile(doc::Sprite* sprite, const gfx::ColorSpacePtr& cs) +AssignColorProfile::AssignColorProfile(doc::Sprite* sprite, const gfx::ColorSpaceRef& cs) : WithSprite(sprite) , m_oldCS(sprite->colorSpace()) , m_newCS(cs) diff --git a/src/app/cmd/assign_color_profile.h b/src/app/cmd/assign_color_profile.h index 5de5d48db..14af7b8d4 100644 --- a/src/app/cmd/assign_color_profile.h +++ b/src/app/cmd/assign_color_profile.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -18,7 +18,7 @@ namespace cmd { class AssignColorProfile : public Cmd, public WithSprite { public: - AssignColorProfile(doc::Sprite* sprite, const gfx::ColorSpacePtr& cs); + AssignColorProfile(doc::Sprite* sprite, const gfx::ColorSpaceRef& cs); protected: void onExecute() override; @@ -32,8 +32,8 @@ namespace cmd { } private: - gfx::ColorSpacePtr m_oldCS; - gfx::ColorSpacePtr m_newCS; + gfx::ColorSpaceRef m_oldCS; + gfx::ColorSpaceRef m_newCS; }; } // namespace cmd diff --git a/src/app/cmd/convert_color_profile.cpp b/src/app/cmd/convert_color_profile.cpp index 9878376f5..585ba32a3 100644 --- a/src/app/cmd/convert_color_profile.cpp +++ b/src/app/cmd/convert_color_profile.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -24,7 +24,7 @@ namespace app { namespace cmd { static doc::ImageRef convert_image_color_space(const doc::Image* srcImage, - const gfx::ColorSpacePtr& newCS, + const gfx::ColorSpaceRef& newCS, os::ColorSpaceConversion* conversion) { ImageSpec spec = srcImage->spec(); @@ -71,14 +71,14 @@ static doc::ImageRef convert_image_color_space(const doc::Image* srcImage, } void convert_color_profile(doc::Sprite* sprite, - const gfx::ColorSpacePtr& newCS) + const gfx::ColorSpaceRef& newCS) { ASSERT(sprite->colorSpace()); ASSERT(newCS); os::System* system = os::instance(); - auto srcOCS = system->createColorSpace(sprite->colorSpace()); - auto dstOCS = system->createColorSpace(newCS); + auto srcOCS = system->makeColorSpace(sprite->colorSpace()); + auto dstOCS = system->makeColorSpace(newCS); ASSERT(srcOCS); ASSERT(dstOCS); @@ -123,15 +123,15 @@ void convert_color_profile(doc::Sprite* sprite, void convert_color_profile(doc::Image* image, doc::Palette* palette, - const gfx::ColorSpacePtr& oldCS, - const gfx::ColorSpacePtr& newCS) + const gfx::ColorSpaceRef& oldCS, + const gfx::ColorSpaceRef& newCS) { ASSERT(oldCS); ASSERT(newCS); os::System* system = os::instance(); - auto srcOCS = system->createColorSpace(oldCS); - auto dstOCS = system->createColorSpace(newCS); + auto srcOCS = system->makeColorSpace(oldCS); + auto dstOCS = system->makeColorSpace(newCS); ASSERT(srcOCS); ASSERT(dstOCS); @@ -161,7 +161,7 @@ void convert_color_profile(doc::Image* image, } } -ConvertColorProfile::ConvertColorProfile(doc::Sprite* sprite, const gfx::ColorSpacePtr& newCS) +ConvertColorProfile::ConvertColorProfile(doc::Sprite* sprite, const gfx::ColorSpaceRef& newCS) : WithSprite(sprite) { os::System* system = os::instance(); @@ -169,8 +169,8 @@ ConvertColorProfile::ConvertColorProfile(doc::Sprite* sprite, const gfx::ColorSp ASSERT(sprite->colorSpace()); ASSERT(newCS); - auto srcOCS = system->createColorSpace(sprite->colorSpace()); - auto dstOCS = system->createColorSpace(newCS); + auto srcOCS = system->makeColorSpace(sprite->colorSpace()); + auto dstOCS = system->makeColorSpace(newCS); ASSERT(srcOCS); ASSERT(dstOCS); diff --git a/src/app/cmd/convert_color_profile.h b/src/app/cmd/convert_color_profile.h index 1ee6bf5e9..c6c3dce74 100644 --- a/src/app/cmd/convert_color_profile.h +++ b/src/app/cmd/convert_color_profile.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -28,7 +28,7 @@ namespace cmd { class ConvertColorProfile : public Cmd, public WithSprite { public: - ConvertColorProfile(doc::Sprite* sprite, const gfx::ColorSpacePtr& newCS); + ConvertColorProfile(doc::Sprite* sprite, const gfx::ColorSpaceRef& newCS); protected: void onExecute() override; @@ -45,12 +45,12 @@ namespace cmd { // Converts the sprite to the new color profile without undo information. // TODO how to merge this function with cmd::ConvertColorProfile void convert_color_profile(doc::Sprite* sprite, - const gfx::ColorSpacePtr& newCS); + const gfx::ColorSpaceRef& newCS); void convert_color_profile(doc::Image* image, doc::Palette* palette, - const gfx::ColorSpacePtr& oldCS, - const gfx::ColorSpacePtr& newCS); + const gfx::ColorSpaceRef& oldCS, + const gfx::ColorSpaceRef& newCS); } // namespace cmd } // namespace app diff --git a/src/app/color_spaces.cpp b/src/app/color_spaces.cpp index 68e658554..b34080e6b 100644 --- a/src/app/color_spaces.cpp +++ b/src/app/color_spaces.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -14,8 +14,8 @@ #include "app/modules/editors.h" #include "app/pref/preferences.h" #include "app/ui/editor/editor.h" -#include "os/display.h" #include "os/system.h" +#include "os/window.h" namespace app { @@ -33,12 +33,12 @@ void initialize_color_spaces(Preferences& pref) }); } -os::ColorSpacePtr get_screen_color_space() +os::ColorSpaceRef get_screen_color_space() { - return os::instance()->defaultDisplay()->colorSpace(); + return os::instance()->defaultWindow()->colorSpace(); } -os::ColorSpacePtr get_current_color_space() +os::ColorSpaceRef get_current_color_space() { #ifdef ENABLE_UI if (current_editor) @@ -48,14 +48,14 @@ os::ColorSpacePtr get_current_color_space() return get_screen_color_space(); } -gfx::ColorSpacePtr get_working_rgb_space_from_preferences() +gfx::ColorSpaceRef get_working_rgb_space_from_preferences() { if (Preferences::instance().color.manage()) { const std::string name = Preferences::instance().color.workingRgbSpace(); if (name == "sRGB") return gfx::ColorSpace::MakeSRGB(); - std::vector colorSpaces; + std::vector colorSpaces; os::instance()->listColorSpaces(colorSpaces); for (auto& cs : colorSpaces) { if (cs->gfxColorSpace()->name() == name) @@ -78,8 +78,8 @@ ConvertCS::ConvertCS() } } -ConvertCS::ConvertCS(const os::ColorSpacePtr& srcCS, - const os::ColorSpacePtr& dstCS) +ConvertCS::ConvertCS(const os::ColorSpaceRef& srcCS, + const os::ColorSpaceRef& dstCS) { if (g_manage) { m_conversion = os::instance()->convertBetweenColorSpace(srcCS, dstCS); @@ -108,10 +108,10 @@ ConvertCS convert_from_current_to_screen_color_space() return ConvertCS(); } -ConvertCS convert_from_custom_to_srgb(const os::ColorSpacePtr& from) +ConvertCS convert_from_custom_to_srgb(const os::ColorSpaceRef& from) { return ConvertCS(from, - os::instance()->createColorSpace(gfx::ColorSpace::MakeSRGB())); + os::instance()->makeColorSpace(gfx::ColorSpace::MakeSRGB())); } } // namespace app diff --git a/src/app/color_spaces.h b/src/app/color_spaces.h index d25cf8009..99337153c 100644 --- a/src/app/color_spaces.h +++ b/src/app/color_spaces.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (c) 2018-2020 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -12,8 +12,6 @@ #include "gfx/color_space.h" #include "os/color_space.h" -#include - namespace doc { class Sprite; } @@ -23,27 +21,27 @@ namespace app { void initialize_color_spaces(Preferences& pref); - os::ColorSpacePtr get_screen_color_space(); + os::ColorSpaceRef get_screen_color_space(); // Returns the color space of the current document. - os::ColorSpacePtr get_current_color_space(); + os::ColorSpaceRef get_current_color_space(); - gfx::ColorSpacePtr get_working_rgb_space_from_preferences(); + gfx::ColorSpaceRef get_working_rgb_space_from_preferences(); class ConvertCS { public: ConvertCS(); - ConvertCS(const os::ColorSpacePtr& srcCS, - const os::ColorSpacePtr& dstCS); + ConvertCS(const os::ColorSpaceRef& srcCS, + const os::ColorSpaceRef& dstCS); ConvertCS(ConvertCS&&); ConvertCS& operator=(const ConvertCS&) = delete; gfx::Color operator()(const gfx::Color c); private: - std::unique_ptr m_conversion; + os::Ref m_conversion; }; ConvertCS convert_from_current_to_screen_color_space(); - ConvertCS convert_from_custom_to_srgb(const os::ColorSpacePtr& from); + ConvertCS convert_from_custom_to_srgb(const os::ColorSpaceRef& from); } // namespace app diff --git a/src/app/commands/cmd_fullscreen_preview.cpp b/src/app/commands/cmd_fullscreen_preview.cpp index fbbbb6d77..2797f04a5 100644 --- a/src/app/commands/cmd_fullscreen_preview.cpp +++ b/src/app/commands/cmd_fullscreen_preview.cpp @@ -26,7 +26,6 @@ #include "doc/palette.h" #include "doc/primitives.h" #include "doc/sprite.h" -#include "os/scoped_handle.h" #include "os/surface.h" #include "os/system.h" @@ -53,7 +52,7 @@ public: , m_proj(editor->projection()) , m_index_bg_color(-1) , m_doublebuf(Image::create(IMAGE_RGB, ui::display_w(), ui::display_h())) - , m_doublesur(os::instance()->createRgbaSurface(ui::display_w(), ui::display_h())) { + , m_doublesur(os::instance()->makeRgbaSurface(ui::display_w(), ui::display_h())) { // Do not use DocWriter (do not lock the document) because we // will call other sub-commands (e.g. previous frame, next frame, // etc.). @@ -232,8 +231,8 @@ protected: } convert_image_to_surface(m_doublebuf.get(), m_pal, - m_doublesur, 0, 0, 0, 0, m_doublebuf->width(), m_doublebuf->height()); - g->blit(m_doublesur, 0, 0, 0, 0, m_doublesur->width(), m_doublesur->height()); + m_doublesur.get(), 0, 0, 0, 0, m_doublebuf->width(), m_doublebuf->height()); + g->blit(m_doublesur.get(), 0, 0, 0, 0, m_doublesur->width(), m_doublesur->height()); } private: @@ -249,7 +248,7 @@ private: int m_index_bg_color; std::unique_ptr m_render; std::unique_ptr m_doublebuf; - os::ScopedHandle m_doublesur; + os::SurfaceRef m_doublesur; filters::TiledMode m_tiled; }; diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp index a1d0cd664..995d6999f 100644 --- a/src/app/commands/cmd_options.cpp +++ b/src/app/commands/cmd_options.cpp @@ -37,8 +37,8 @@ #include "base/version.h" #include "doc/image.h" #include "fmt/format.h" -#include "os/display.h" #include "os/system.h" +#include "os/window.h" #include "render/render.h" #include "ui/ui.h" @@ -98,13 +98,13 @@ class OptionsWindow : public app::gen::Options { class ColorSpaceItem : public ListItem { public: - ColorSpaceItem(const os::ColorSpacePtr& cs) + ColorSpaceItem(const os::ColorSpaceRef& cs) : ListItem(cs->gfxColorSpace()->name()), m_cs(cs) { } - os::ColorSpacePtr cs() const { return m_cs; } + os::ColorSpaceRef cs() const { return m_cs; } private: - os::ColorSpacePtr m_cs; + os::ColorSpaceRef m_cs; }; class ThemeItem : public ListItem { @@ -641,7 +641,6 @@ public: if (j == winCs) { name = gfxCs->name(); - os::instance()->setDisplaysColorSpace(cs); break; } ++j; @@ -651,7 +650,7 @@ public: break; } } - update_displays_color_profile_from_preferences(); + update_windows_color_profile_from_preferences(); // Change sprite grid bounds if (m_context && m_context->activeDocument()) { @@ -723,7 +722,7 @@ public: m_pref.tablet.api(tabletStr); m_pref.experimental.loadWintabDriver(wintabState); - manager()->getDisplay() + manager()->display() ->setInterpretOneFingerGestureAsMouseMovement( oneFingerAsMouseMovement()->isSelected()); @@ -843,10 +842,8 @@ private: void updateScreenScaling() { ui::Manager* manager = ui::Manager::getDefault(); - os::Display* display = manager->getDisplay(); os::instance()->setGpuAcceleration(m_pref.general.gpuAcceleration()); - display->setScale(m_pref.general.screenScale()); - manager->setDisplay(display); + manager->updateAllDisplaysWithNewScale(m_pref.general.screenScale()); } void onApply() { @@ -1608,7 +1605,7 @@ private: std::string m_restoreThisTheme; int m_restoreScreenScaling; int m_restoreUIScaling; - std::vector m_colorSpaces; + std::vector m_colorSpaces; std::string m_templateTextForDisplayCS; }; diff --git a/src/app/commands/cmd_sprite_properties.cpp b/src/app/commands/cmd_sprite_properties.cpp index 21587c2d7..975d16f5d 100644 --- a/src/app/commands/cmd_sprite_properties.cpp +++ b/src/app/commands/cmd_sprite_properties.cpp @@ -63,7 +63,7 @@ void SpritePropertiesCommand::onExecute(Context* context) ColorButton* color_button = nullptr; // List of available color profiles - std::vector colorSpaces; + std::vector colorSpaces; os::instance()->listColorSpaces(colorSpaces); // Load the window widget @@ -152,7 +152,7 @@ void SpritePropertiesCommand::onExecute(Context* context) ++i; } if (selectedColorProfile < 0) { - colorSpaces.push_back(os::instance()->createColorSpace(sprite->colorSpace())); + colorSpaces.push_back(os::instance()->makeColorSpace(sprite->colorSpace())); selectedColorProfile = colorSpaces.size()-1; } diff --git a/src/app/commands/screenshot.cpp b/src/app/commands/screenshot.cpp index d8bbcbe11..7e39a27e1 100644 --- a/src/app/commands/screenshot.cpp +++ b/src/app/commands/screenshot.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2021 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -25,8 +25,8 @@ #include "doc/layer.h" #include "doc/sprite.h" #include "fmt/format.h" -#include "os/display.h" #include "os/surface.h" +#include "os/window.h" #include "ui/alert.h" #include "ui/manager.h" #include "ui/scale.h" @@ -69,8 +69,8 @@ void ScreenshotCommand::onExecute(Context* ctx) app::ResourceFinder rf(false); rf.includeDesktopDir(""); - os::Display* display = ui::Manager::getDefault()->getDisplay(); - os::Surface* surface = display->getSurface(); + os::Window* display = ui::Manager::getDefault()->display(); + os::Surface* surface = display->surface(); std::string fn; if (params().save()) { diff --git a/src/app/console.cpp b/src/app/console.cpp index 0b1d115e4..3408edd6d 100644 --- a/src/app/console.cpp +++ b/src/app/console.cpp @@ -15,7 +15,6 @@ #include "app/context.h" #include "app/modules/gui.h" #include "app/ui/status_bar.h" -#include "base/bind.h" #include "base/memory.h" #include "base/string.h" #include "ui/system.h" @@ -125,7 +124,7 @@ Console::Console(Context* ctx) (App::instance() && App::instance()->isGui() && Manager::getDefault() && - Manager::getDefault()->getDisplay()); + Manager::getDefault()->display()); if (!m_withUI) return; diff --git a/src/app/crash/read_document.cpp b/src/app/crash/read_document.cpp index eb7316f44..c312c06e4 100644 --- a/src/app/crash/read_document.cpp +++ b/src/app/crash/read_document.cpp @@ -344,7 +344,7 @@ private: // Read color space if (!s.eof()) { - gfx::ColorSpacePtr colorSpace = readColorSpace(s); + gfx::ColorSpaceRef colorSpace = readColorSpace(s); if (colorSpace) spr->setColorSpace(colorSpace); } @@ -359,7 +359,7 @@ private: return spr.release(); } - gfx::ColorSpacePtr readColorSpace(std::ifstream& s) { + gfx::ColorSpaceRef readColorSpace(std::ifstream& s) { const gfx::ColorSpace::Type type = (gfx::ColorSpace::Type)read16(s); const gfx::ColorSpace::Flag flags = (gfx::ColorSpace::Flag)read16(s); const double gamma = fixmath::fixtof(read32(s)); @@ -375,7 +375,7 @@ private: s.read((char*)&buf[0], n); std::string name = read_string(s); - auto colorSpace = std::make_shared( + auto colorSpace = base::make_ref( type, flags, gamma, std::move(buf)); colorSpace->setName(name); return colorSpace; diff --git a/src/app/crash/write_document.cpp b/src/app/crash/write_document.cpp index b58b1dd39..3778a9038 100644 --- a/src/app/crash/write_document.cpp +++ b/src/app/crash/write_document.cpp @@ -185,7 +185,7 @@ private: return true; } - bool writeColorSpace(std::ofstream& s, const gfx::ColorSpacePtr& colorSpace) { + bool writeColorSpace(std::ofstream& s, const gfx::ColorSpaceRef& colorSpace) { write16(s, colorSpace->type()); write16(s, colorSpace->flags()); write32(s, fixmath::ftofix(colorSpace->gamma())); diff --git a/src/app/doc.cpp b/src/app/doc.cpp index 95627d8b8..c6168aa35 100644 --- a/src/app/doc.cpp +++ b/src/app/doc.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -30,11 +30,11 @@ #include "doc/mask.h" #include "doc/mask_boundaries.h" #include "doc/palette.h" +#include "doc/slice.h" #include "doc/sprite.h" #include "doc/tag.h" -#include "doc/slice.h" -#include "os/display.h" #include "os/system.h" +#include "os/window.h" #include "ui/system.h" #include @@ -603,9 +603,9 @@ void Doc::updateOSColorSpace(bool appWideSignal) { auto system = os::instance(); if (system) { - m_osColorSpace = system->createColorSpace(sprite()->colorSpace()); - if (!m_osColorSpace && system->defaultDisplay()) - m_osColorSpace = system->defaultDisplay()->colorSpace(); + m_osColorSpace = system->makeColorSpace(sprite()->colorSpace()); + if (!m_osColorSpace && system->defaultWindow()) + m_osColorSpace = system->defaultWindow()->colorSpace(); } if (appWideSignal && diff --git a/src/app/doc.h b/src/app/doc.h index c5a3ea210..90afcd20c 100644 --- a/src/app/doc.h +++ b/src/app/doc.h @@ -99,7 +99,7 @@ namespace app { color_t bgColor() const; color_t bgColor(Layer* layer) const; - os::ColorSpacePtr osColorSpace() const { return m_osColorSpace; } + os::ColorSpaceRef osColorSpace() const { return m_osColorSpace; } ////////////////////////////////////////////////////////////////////// // Notifications @@ -259,7 +259,7 @@ namespace app { gfx::Point m_lastDrawingPoint; // Last used color space to render a sprite. - os::ColorSpacePtr m_osColorSpace; + os::ColorSpaceRef m_osColorSpace; DISABLE_COPYING(Doc); }; diff --git a/src/app/doc_exporter.cpp b/src/app/doc_exporter.cpp index f5df4a6cd..32a18ed78 100644 --- a/src/app/doc_exporter.cpp +++ b/src/app/doc_exporter.cpp @@ -1090,7 +1090,7 @@ Doc* DocExporter::createEmptyTexture(const Samples& samples, ColorMode colorMode = ColorMode::INDEXED; Palette* palette = nullptr; int maxColors = 256; - gfx::ColorSpacePtr colorSpace; + gfx::ColorSpaceRef colorSpace; color_t transparentColor = 0; for (const auto& sample : samples) { diff --git a/src/app/file/ase_format.cpp b/src/app/file/ase_format.cpp index 5ad37a036..22559f366 100644 --- a/src/app/file/ase_format.cpp +++ b/src/app/file/ase_format.cpp @@ -868,7 +868,7 @@ static void ase_file_write_color_profile(FILE* f, dio::AsepriteFrameHeader* frame_header, const doc::Sprite* sprite) { - const gfx::ColorSpacePtr& cs = sprite->colorSpace(); + const gfx::ColorSpaceRef& cs = sprite->colorSpace(); if (!cs) // No color return; diff --git a/src/app/file/file.cpp b/src/app/file/file.cpp index 8e1425edd..ca44d3c04 100644 --- a/src/app/file/file.cpp +++ b/src/app/file/file.cpp @@ -935,7 +935,7 @@ void FileOp::postLoad() } // What to do with the sprite color profile? - gfx::ColorSpacePtr spriteCS = sprite->colorSpace(); + gfx::ColorSpaceRef spriteCS = sprite->colorSpace(); app::gen::ColorProfileBehavior behavior = app::gen::ColorProfileBehavior::DISABLE; diff --git a/src/app/file/file_op_config.h b/src/app/file/file_op_config.h index 2f31a69df..54f317489 100644 --- a/src/app/file/file_op_config.h +++ b/src/app/file/file_op_config.h @@ -24,7 +24,7 @@ namespace app { // profile or without a color profile. app::gen::ColorProfileBehavior filesWithProfile = app::gen::ColorProfileBehavior::EMBEDDED; app::gen::ColorProfileBehavior missingProfile = app::gen::ColorProfileBehavior::ASSIGN; - gfx::ColorSpacePtr workingCS = gfx::ColorSpace::MakeSRGB(); + gfx::ColorSpaceRef workingCS = gfx::ColorSpace::MakeSRGB(); // True if we should render each frame to save it with the new // blend mode.h diff --git a/src/app/file/jpeg_format.cpp b/src/app/file/jpeg_format.cpp index cc0ae9a15..4abde1853 100644 --- a/src/app/file/jpeg_format.cpp +++ b/src/app/file/jpeg_format.cpp @@ -69,7 +69,7 @@ class JpegFormat : public FileFormat { } bool onLoad(FileOp* fop) override; - gfx::ColorSpacePtr loadColorSpace(FileOp* fop, jpeg_decompress_struct* dinfo); + gfx::ColorSpaceRef loadColorSpace(FileOp* fop, jpeg_decompress_struct* dinfo); #ifdef ENABLE_SAVE bool onSave(FileOp* fop) override; void saveColorSpace(FileOp* fop, jpeg_compress_struct* cinfo, @@ -256,7 +256,7 @@ bool JpegFormat::onLoad(FileOp* fop) } // Read color space - gfx::ColorSpacePtr colorSpace = loadColorSpace(fop, &dinfo); + gfx::ColorSpaceRef colorSpace = loadColorSpace(fop, &dinfo); if (colorSpace) fop->setEmbeddedColorProfile(); else { // sRGB is the default JPG color space. @@ -282,7 +282,7 @@ bool JpegFormat::onLoad(FileOp* fop) // in two steps: // (1) Discover all ICC profile markers and verify that they are numbered properly. // (2) Copy the data from each marker into a contiguous ICC profile. -gfx::ColorSpacePtr JpegFormat::loadColorSpace(FileOp* fop, jpeg_decompress_struct* dinfo) +gfx::ColorSpaceRef JpegFormat::loadColorSpace(FileOp* fop, jpeg_decompress_struct* dinfo) { // Note that 256 will be enough storage space since each markerIndex is stored in 8-bits. jpeg_marker_struct* markerSequence[256]; diff --git a/src/app/file/png_format.cpp b/src/app/file/png_format.cpp index b86b5dc15..0b0a9ecf8 100644 --- a/src/app/file/png_format.cpp +++ b/src/app/file/png_format.cpp @@ -59,7 +59,7 @@ class PngFormat : public FileFormat { } bool onLoad(FileOp* fop) override; - gfx::ColorSpacePtr loadColorSpace(png_structp png, png_infop info); + gfx::ColorSpaceRef loadColorSpace(png_structp png, png_infop info); #ifdef ENABLE_SAVE bool onSave(FileOp* fop) override; void saveColorSpace(png_structp png, png_infop info, const gfx::ColorSpace* colorSpace); @@ -457,7 +457,7 @@ bool PngFormat::onLoad(FileOp* fop) // // Code to read color spaces from png files from Skia (SkPngCodec.cpp) // by Google Inc. -gfx::ColorSpacePtr PngFormat::loadColorSpace(png_structp png_ptr, png_infop info_ptr) +gfx::ColorSpaceRef PngFormat::loadColorSpace(png_structp png_ptr, png_infop info_ptr) { // First check for an ICC profile png_bytep profile; diff --git a/src/app/file_selector.cpp b/src/app/file_selector.cpp index e32753d0d..b5975356a 100644 --- a/src/app/file_selector.cpp +++ b/src/app/file_selector.cpp @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -13,9 +14,9 @@ #include "app/app.h" #include "app/pref/preferences.h" #include "app/ui/file_selector.h" -#include "os/display.h" #include "os/native_dialogs.h" #include "os/system.h" +#include "os/window.h" namespace app { @@ -31,8 +32,8 @@ bool show_file_selector( if (Preferences::instance().experimental.useNativeFileDialog() && os::instance()->nativeDialogs()) { - os::FileDialog* dlg = - os::instance()->nativeDialogs()->createFileDialog(); + os::FileDialogRef dlg = + os::instance()->nativeDialogs()->makeFileDialog(); if (dlg) { dlg->setTitle(title); @@ -58,14 +59,13 @@ bool show_file_selector( if (!defExtension.empty()) dlg->setDefaultExtension(defExtension); - bool res = dlg->show(os::instance()->defaultDisplay()); + bool res = dlg->show(os::instance()->defaultWindow()); if (res) { if (type == FileSelectorType::OpenMultiple) dlg->getMultipleFileNames(output); else output.push_back(dlg->fileName()); } - dlg->dispose(); return res; } } diff --git a/src/app/file_system.cpp b/src/app/file_system.cpp index 26199c6db..f9bad76a4 100644 --- a/src/app/file_system.cpp +++ b/src/app/file_system.cpp @@ -19,9 +19,9 @@ #include "base/fs.h" #include "base/string.h" -#include "os/display.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include #include @@ -58,7 +58,7 @@ namespace app { namespace { class FileItem; -typedef std::map FileItemMap; +using FileItemMap = std::map; // the root of the file-system FileItem* rootitem = nullptr; @@ -123,8 +123,8 @@ public: m_thumbnailProgress = progress; } - os::Surface* getThumbnail() override; - void setThumbnail(os::Surface* thumbnail) override; + os::SurfaceRef getThumbnail() override; + void setThumbnail(const os::SurfaceRef& thumbnail) override; // Calls "delete this" void deleteItem() { @@ -457,7 +457,7 @@ const FileItemList& FileItem::children() // Get the interface to enumerate subitems hr = pFolder->EnumObjects( - reinterpret_cast(os::instance()->defaultDisplay()->nativeHandle()), + reinterpret_cast(os::instance()->defaultWindow()->nativeHandle()), SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum); if (hr == S_OK && pEnum) { @@ -583,16 +583,21 @@ bool FileItem::hasExtension(const base::paths& extensions) return base::has_file_extension(m_filename, extensions); } -os::Surface* FileItem::getThumbnail() +os::SurfaceRef FileItem::getThumbnail() { - return m_thumbnail; + os::SurfaceRef ref(m_thumbnail.load()); + if (ref) + ref->ref(); // base::Ref(T*) doesn't add an extra reference + return ref; } -void FileItem::setThumbnail(os::Surface* thumbnail) +void FileItem::setThumbnail(const os::SurfaceRef& newThumbnail) { - auto old = m_thumbnail.exchange(thumbnail); + if (newThumbnail) + newThumbnail->ref(); + auto old = m_thumbnail.exchange(newThumbnail.get()); if (old) - old->dispose(); + old->unref(); } FileItem::FileItem(FileItem* parent) @@ -618,8 +623,7 @@ FileItem::~FileItem() { FS_TRACE("FS: Destroying FileItem() with parent %p\n", m_parent); - if (auto ptr = m_thumbnail.load()) - ptr->dispose(); + m_thumbnail.exchange(nullptr); #ifdef _WIN32 if (m_fullpidl && m_fullpidl != m_pidl) { diff --git a/src/app/file_system.h b/src/app/file_system.h index 133b714c9..5650ac4f3 100644 --- a/src/app/file_system.h +++ b/src/app/file_system.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -12,19 +12,15 @@ #include "base/mutex.h" #include "base/paths.h" #include "obs/signal.h" +#include "os/surface.h" #include #include -namespace os { - class Surface; -} - namespace app { class IFileItem; - - typedef std::vector FileItemList; + using FileItemList = std::vector; class FileSystemModule { static FileSystemModule* m_instance; @@ -91,8 +87,8 @@ namespace app { virtual double getThumbnailProgress() = 0; virtual void setThumbnailProgress(double progress) = 0; - virtual os::Surface* getThumbnail() = 0; - virtual void setThumbnail(os::Surface* thumbnail) = 0; + virtual os::SurfaceRef getThumbnail() = 0; + virtual void setThumbnail(const os::SurfaceRef& thumbnail) = 0; }; } // namespace app diff --git a/src/app/modules/gui.cpp b/src/app/modules/gui.cpp index 5b1931944..40f07f776 100644 --- a/src/app/modules/gui.cpp +++ b/src/app/modules/gui.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -42,10 +42,10 @@ #include "base/memory.h" #include "base/string.h" #include "doc/sprite.h" -#include "os/display.h" #include "os/error.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/intern.h" #include "ui/ui.h" @@ -83,6 +83,11 @@ static struct { class CustomizedGuiManager : public Manager , public LayoutIO { +public: + CustomizedGuiManager(const os::WindowRef& nativeWindow) + : ui::Manager(nativeWindow) { + } + protected: bool onProcessMessage(Message* msg) override; #if ENABLE_DEVMODE @@ -97,25 +102,24 @@ protected: void saveLayout(Widget* widget, const std::string& str) override; }; -static os::Display* main_display = NULL; -static CustomizedGuiManager* manager = NULL; -static Theme* gui_theme = NULL; +static os::WindowRef main_window = nullptr; +static CustomizedGuiManager* manager = nullptr; +static Theme* gui_theme = nullptr; static ui::Timer* defered_invalid_timer = nullptr; static gfx::Region defered_invalid_region; // Load & save graphics configuration -static void load_gui_config(int& w, int& h, bool& maximized, - std::string& windowLayout); +static bool load_gui_config(os::WindowSpec& spec, bool& maximized); static void save_gui_config(); -static bool create_main_display(bool gpuAccel, - bool& maximized, - std::string& lastError) +static bool create_main_window(bool gpuAccel, + bool& maximized, + std::string& lastError) { - int w, h; - std::string windowLayout; - load_gui_config(w, h, maximized, windowLayout); + os::WindowSpec spec; + if (!load_gui_config(spec, maximized)) + return false; // Scale is equal to 0 when it's the first time the program is // executed. @@ -124,45 +128,45 @@ static bool create_main_display(bool gpuAccel, os::instance()->setGpuAcceleration(gpuAccel); try { - if (w > 0 && h > 0) { - main_display = os::instance()->createDisplay( - w, h, (scale == 0 ? 2: base::clamp(scale, 1, 4))); + if (!spec.frame().isEmpty() || + !spec.contentRect().isEmpty()) { + spec.scale(scale == 0 ? 2: base::clamp(scale, 1, 4)); + main_window = os::instance()->makeWindow(spec); } } - catch (const os::DisplayCreationException& e) { + catch (const os::WindowCreationException& e) { lastError = e.what(); } - if (!main_display) { + if (!main_window) { for (int c=0; try_resolutions[c].width; ++c) { try { - main_display = - os::instance()->createDisplay( - try_resolutions[c].width, - try_resolutions[c].height, - (scale == 0 ? try_resolutions[c].scale: scale)); + spec.frame(); + spec.position(os::WindowSpec::Position::Default); + spec.scale(scale == 0 ? try_resolutions[c].scale: scale); + spec.contentRect(gfx::Rect(0, 0, + try_resolutions[c].width * spec.scale(), + try_resolutions[c].height * spec.scale())); + main_window = os::instance()->makeWindow(spec); break; } - catch (const os::DisplayCreationException& e) { + catch (const os::WindowCreationException& e) { lastError = e.what(); } } } - if (main_display) { + if (main_window) { // Change the scale value only in the first run (this will be // saved when the program is closed). if (scale == 0) - Preferences::instance().general.screenScale(main_display->scale()); + Preferences::instance().general.screenScale(main_window->scale()); - if (!windowLayout.empty()) { - main_display->setLayout(windowLayout); - if (main_display->isMinimized()) - main_display->maximize(); - } + if (main_window->isMinimized()) + main_window->maximize(); } - return (main_display != nullptr); + return (main_window != nullptr); } // Initializes GUI. @@ -173,40 +177,51 @@ int init_module_gui() std::string lastError = "Unknown error"; bool gpuAccel = pref.general.gpuAcceleration(); - if (!create_main_display(gpuAccel, maximized, lastError)) { + if (!create_main_window(gpuAccel, maximized, lastError)) { // If we've created the display with hardware acceleration, // now we try to do it without hardware acceleration. if (gpuAccel && (int(os::instance()->capabilities()) & int(os::Capabilities::GpuAccelerationSwitch)) == int(os::Capabilities::GpuAccelerationSwitch)) { - if (create_main_display(false, maximized, lastError)) { + if (create_main_window(false, maximized, lastError)) { // Disable hardware acceleration pref.general.gpuAcceleration(false); } } } - if (!main_display) { + if (!main_window) { os::error_message( ("Unable to create a user-interface display.\nDetails: "+lastError+"\n").c_str()); return -1; } // Create the default-manager - manager = new CustomizedGuiManager(); - manager->setDisplay(main_display); + manager = new CustomizedGuiManager(main_window); // Setup the GUI theme for all widgets gui_theme = new SkinTheme; ui::set_theme(gui_theme, pref.general.uiScale()); if (maximized) - main_display->maximize(); + main_window->maximize(); + + // Handle live resize too redraw the entire manager, dispatch the UI + // messages, and flip the window. + os::instance()->handleWindowResize = + [](os::Window* window) { + Message* msg = new Message(kResizeDisplayMessage); + msg->setRecipient(manager); + msg->setPropagateToChildren(false); + + manager->enqueueMessage(msg); + manager->dispatchMessages(); + }; // Set graphics options for next time save_gui_config(); - update_displays_color_profile_from_preferences(); + update_windows_color_profile_from_preferences(); return 0; } @@ -222,10 +237,11 @@ void exit_module_gui() ui::set_theme(nullptr, ui::guiscale()); delete gui_theme; - main_display->dispose(); + // This should be the last unref() of the display to delete it. + main_window.reset(); } -void update_displays_color_profile_from_preferences() +void update_windows_color_profile_from_preferences() { auto system = os::instance(); @@ -235,56 +251,117 @@ void update_displays_color_profile_from_preferences() else windowProfile = gen::WindowColorProfile::SRGB; + os::ColorSpaceRef osCS = nullptr; + switch (windowProfile) { case gen::WindowColorProfile::MONITOR: - system->setDisplaysColorSpace(nullptr); + osCS = nullptr; break; case gen::WindowColorProfile::SRGB: - system->setDisplaysColorSpace( - system->createColorSpace(gfx::ColorSpace::MakeSRGB())); + osCS = system->makeColorSpace(gfx::ColorSpace::MakeSRGB()); break; case gen::WindowColorProfile::SPECIFIC: { std::string name = Preferences::instance().color.windowProfileName(); - std::vector colorSpaces; + std::vector colorSpaces; system->listColorSpaces(colorSpaces); for (auto& cs : colorSpaces) { auto gfxCs = cs->gfxColorSpace(); if (gfxCs->type() == gfx::ColorSpace::ICC && gfxCs->name() == name) { - system->setDisplaysColorSpace(cs); + osCS = cs; break; } } break; } } + + // Set the default color space for all windows (osCS can be nullptr + // which means that each window should use its monitor color space) + system->setWindowsColorSpace(osCS); + + // Set the color space of the main window + if (manager && manager->display()) + manager->display()->setColorSpace(osCS); } -static void load_gui_config(int& w, int& h, bool& maximized, - std::string& windowLayout) +static bool load_gui_config(os::WindowSpec& spec, bool& maximized) { - gfx::Size defSize = os::instance()->defaultNewDisplaySize(); + os::ScreenRef screen = os::instance()->mainScreen(); +#ifdef LAF_SKIA + ASSERT(screen); +#else + // Compiled without Skia (none backend), without screen. + if (!screen) { + std::printf( + "\n" + " Aseprite cannot initialize GUI because it was compiled with LAF_BACKEND=none\n" + "\n" + " Check the documentation in:\n" + " https://github.com/aseprite/laf/blob/main/README.md\n" + " https://github.com/aseprite/aseprite/blob/main/INSTALL.md\n" + "\n"); + return false; + } +#endif - w = get_config_int("GfxMode", "Width", defSize.w); - h = get_config_int("GfxMode", "Height", defSize.h); - maximized = get_config_bool("GfxMode", "Maximized", false); - windowLayout = get_config_string("GfxMode", "WindowLayout", ""); + spec.screen(screen); + + gfx::Rect frame; + frame = get_config_rect("GfxMode", "Frame", frame); + if (!frame.isEmpty()) { + spec.position(os::WindowSpec::Position::Frame); + + // Limit the content rect position into the available workarea, + // e.g. this is needed in case that the user closed Aseprite in a + // 2nd monitor that then unplugged and start Aseprite again. + bool ok = false; + os::ScreenList screens; + os::instance()->listScreens(screens); + for (const auto& screen : screens) { + gfx::Rect wa = screen->workarea(); + gfx::Rect intersection = (frame & wa); + if (intersection.w >= 32 && + intersection.h >= 32) { + ok = true; + break; + } + } + + // Reset content rect + if (!ok) { + spec.position(os::WindowSpec::Position::Default); + frame = gfx::Rect(); + } + } + + if (frame.isEmpty()) { + frame = screen->workarea().shrink(64); + + // Try to get Width/Height from previous Aseprite versions + frame.w = get_config_int("GfxMode", "Width", frame.w); + frame.h = get_config_int("GfxMode", "Height", frame.h); + } + spec.frame(frame); + + maximized = get_config_bool("GfxMode", "Maximized", true); + return true; } static void save_gui_config() { - os::Display* display = manager->getDisplay(); - if (display) { - set_config_bool("GfxMode", "Maximized", display->isMaximized()); - set_config_int("GfxMode", "Width", display->originalWidth()); - set_config_int("GfxMode", "Height", display->originalHeight()); + os::Window* window = manager->display(); + if (window) { + const bool maximized = (window->isMaximized() || + window->isFullscreen()); + const gfx::Rect frame = (maximized ? window->restoredFrame(): + window->frame()); - std::string windowLayout = display->getLayout(); - if (!windowLayout.empty()) - set_config_string("GfxMode", "WindowLayout", windowLayout.c_str()); + set_config_bool("GfxMode", "Maximized", maximized); + set_config_rect("GfxMode", "Frame", frame); } } diff --git a/src/app/modules/gui.h b/src/app/modules/gui.h index 4dabeacef..ebe14cd5c 100644 --- a/src/app/modules/gui.h +++ b/src/app/modules/gui.h @@ -35,7 +35,7 @@ namespace app { int init_module_gui(); void exit_module_gui(); - void update_displays_color_profile_from_preferences(); + void update_windows_color_profile_from_preferences(); void update_screen_for_document(const Doc* document); void load_window_pos(ui::Widget* window, const char* section, diff --git a/src/app/script/image_spec_class.cpp b/src/app/script/image_spec_class.cpp index 2d76249a2..4c607cd95 100644 --- a/src/app/script/image_spec_class.cpp +++ b/src/app/script/image_spec_class.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (c) 2018-2019 Igara Studio S.A. +// Copyright (c) 2018-2020 Igara Studio S.A. // Copyright (C) 2018 David Capello // // This program is distributed under the terms of @@ -115,7 +115,7 @@ int ImageSpec_set_colorSpace(lua_State* L) { auto spec = get_obj(L, 1); auto cs = get_obj(L, 2); - spec->setColorSpace(std::make_shared(*cs)); + spec->setColorSpace(base::make_ref(*cs)); return 0; } diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index ba0d415db..ee9c16390 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -300,7 +300,7 @@ int Sprite_assignColorSpace(lua_State* L) auto cs = get_obj(L, 2); Tx tx; tx(new cmd::AssignColorProfile( - sprite, std::make_shared(*cs))); + sprite, base::make_ref(*cs))); tx.commit(); return 1; } @@ -311,7 +311,7 @@ int Sprite_convertColorSpace(lua_State* L) auto cs = get_obj(L, 2); Tx tx; tx(new cmd::ConvertColorProfile( - sprite, std::make_shared(*cs))); + sprite, base::make_ref(*cs))); tx.commit(); return 1; } diff --git a/src/app/thumbnail_generator.cpp b/src/app/thumbnail_generator.cpp index 2f4e40066..d4677d59a 100644 --- a/src/app/thumbnail_generator.cpp +++ b/src/app/thumbnail_generator.cpp @@ -158,13 +158,13 @@ private: // Set the thumbnail of the file-item. if (thumbnailImage) { - os::Surface* thumbnail = - os::instance()->createRgbaSurface( + os::SurfaceRef thumbnail = + os::instance()->makeRgbaSurface( thumbnailImage->width(), thumbnailImage->height()); convert_image_to_surface( - thumbnailImage.get(), palette.get(), thumbnail, + thumbnailImage.get(), palette.get(), thumbnail.get(), 0, 0, 0, 0, thumbnailImage->width(), thumbnailImage->height()); { diff --git a/src/app/thumbnails.cpp b/src/app/thumbnails.cpp index 17f406cdf..0c469121e 100644 --- a/src/app/thumbnails.cpp +++ b/src/app/thumbnails.cpp @@ -22,8 +22,8 @@ namespace app { namespace thumb { -os::Surface* get_cel_thumbnail(const doc::Cel* cel, - const gfx::Size& fitInSize) +os::SurfaceRef get_cel_thumbnail(const doc::Cel* cel, + const gfx::Size& fitInSize) { gfx::Size newSize; @@ -57,11 +57,11 @@ os::Surface* get_cel_thumbnail(const doc::Cel* cel, gfx::Clip(gfx::Rect(gfx::Point(0, 0), newSize)), 255, doc::BlendMode::NORMAL); - if (os::Surface* thumbnail = os::instance()->createRgbaSurface( + if (os::SurfaceRef thumbnail = os::instance()->makeRgbaSurface( thumbnailImage->width(), thumbnailImage->height())) { convert_image_to_surface( - thumbnailImage.get(), palette, thumbnail, + thumbnailImage.get(), palette, thumbnail.get(), 0, 0, 0, 0, thumbnailImage->width(), thumbnailImage->height()); return thumbnail; } diff --git a/src/app/thumbnails.h b/src/app/thumbnails.h index a735aa014..17adc5b72 100644 --- a/src/app/thumbnails.h +++ b/src/app/thumbnails.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2016 Carlo Caputo // // This program is distributed under the terms of @@ -10,6 +10,7 @@ #pragma once #include "gfx/size.h" +#include "os/surface.h" namespace doc { class Cel; @@ -22,8 +23,8 @@ namespace os { namespace app { namespace thumb { - os::Surface* get_cel_thumbnail(const doc::Cel* cel, - const gfx::Size& fitInSize); + os::SurfaceRef get_cel_thumbnail(const doc::Cel* cel, + const gfx::Size& fitInSize); } // thumb } // app diff --git a/src/app/ui/app_menuitem.cpp b/src/app/ui/app_menuitem.cpp index abe1ef6e7..52f8964e6 100644 --- a/src/app/ui/app_menuitem.cpp +++ b/src/app/ui/app_menuitem.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -25,8 +25,7 @@ #include "ui/widget.h" #include -#include -#include +#include namespace app { @@ -47,18 +46,6 @@ AppMenuItem::AppMenuItem(const std::string& text, { } -AppMenuItem::~AppMenuItem() -{ - if (m_native) { - // Do not call disposeNative(), the native handle will be disposed - // when the main menu (app menu) is disposed. - - // TODO improve handling of these kind of pointer from laf-os library - - delete m_native; - } -} - void AppMenuItem::setKey(const KeyPtr& key) { m_key = key; @@ -68,23 +55,14 @@ void AppMenuItem::setKey(const KeyPtr& key) void AppMenuItem::setNative(const Native& native) { if (!m_native) - m_native = new Native(native); - else { - // Do not call disposeNative(), the native handle will be disposed - // when the main menu (app menu) is disposed. - + m_native.reset(new Native(native)); + else *m_native = native; - } } void AppMenuItem::disposeNative() { -#if 0 // TODO fix this and the whole handling of native menu items from laf-os - if (m_native->menuItem) { - m_native->menuItem->dispose(); - m_native->menuItem = nullptr; - } -#endif + m_native.reset(); } void AppMenuItem::syncNativeMenuItemKeyShortcut() diff --git a/src/app/ui/app_menuitem.h b/src/app/ui/app_menuitem.h index d62fa3a9c..f31cb67bb 100644 --- a/src/app/ui/app_menuitem.h +++ b/src/app/ui/app_menuitem.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -10,12 +11,11 @@ #include "app/commands/params.h" #include "app/ui/key.h" +#include "os/menus.h" #include "os/shortcut.h" #include "ui/menu.h" -namespace os { - class MenuItem; -} +#include namespace app { class Command; @@ -28,7 +28,7 @@ namespace app { class AppMenuItem : public ui::MenuItem { public: struct Native { - os::MenuItem* menuItem = nullptr; + os::MenuItemRef menuItem = nullptr; os::Shortcut shortcut; app::KeyContext keyContext = app::KeyContext::Any; }; @@ -36,7 +36,6 @@ namespace app { AppMenuItem(const std::string& text, Command* command = nullptr, const Params& params = Params()); - ~AppMenuItem(); KeyPtr key() { return m_key; } void setKey(const KeyPtr& key); @@ -47,7 +46,7 @@ namespace app { Command* getCommand() { return m_command; } const Params& getParams() const { return m_params; } - Native* native() { return m_native; } + Native* native() const { return m_native.get(); } void setNative(const Native& native); void disposeNative(); void syncNativeMenuItemKeyShortcut(); @@ -65,7 +64,7 @@ namespace app { Command* m_command; Params m_params; bool m_isRecentFileItem; - Native* m_native; + std::unique_ptr m_native; static Params s_contextParams; }; diff --git a/src/app/ui/brush_popup.cpp b/src/app/ui/brush_popup.cpp index 5761b888a..63d78df54 100644 --- a/src/app/ui/brush_popup.cpp +++ b/src/app/ui/brush_popup.cpp @@ -443,7 +443,7 @@ void BrushPopup::onBrushChanges() } // static -os::Surface* BrushPopup::createSurfaceForBrush(const BrushRef& origBrush) +os::SurfaceRef BrushPopup::createSurfaceForBrush(const BrushRef& origBrush) { Image* image = nullptr; BrushRef brush = origBrush; @@ -455,7 +455,7 @@ os::Surface* BrushPopup::createSurfaceForBrush(const BrushRef& origBrush) image = brush->image(); } - os::Surface* surface = os::instance()->createRgbaSurface( + os::SurfaceRef surface = os::instance()->makeRgbaSurface( std::min(10, image ? image->width(): 4), std::min(10, image ? image->height(): 4)); @@ -468,7 +468,7 @@ os::Surface* BrushPopup::createSurfaceForBrush(const BrushRef& origBrush) } convert_image_to_surface( - image, palette, surface, + image, palette, surface.get(), 0, 0, 0, 0, image->width(), image->height()); if (image->pixelFormat() == IMAGE_BITMAP) diff --git a/src/app/ui/brush_popup.h b/src/app/ui/brush_popup.h index 11f6e522a..a5dc1af77 100644 --- a/src/app/ui/brush_popup.h +++ b/src/app/ui/brush_popup.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2001-2015 David Capello // // This program is distributed under the terms of @@ -23,7 +23,7 @@ namespace app { void setBrush(doc::Brush* brush); void regenerate(const gfx::Rect& box); - static os::Surface* createSurfaceForBrush(const doc::BrushRef& brush); + static os::SurfaceRef createSurfaceForBrush(const doc::BrushRef& brush); private: void onStandardBrush(); diff --git a/src/app/ui/button_set.cpp b/src/app/ui/button_set.cpp index e05e43eb2..169c31140 100644 --- a/src/app/ui/button_set.cpp +++ b/src/app/ui/button_set.cpp @@ -159,7 +159,7 @@ void ButtonSet::Item::onPaint(ui::PaintEvent& ev) } if (hasText()) { - g->setFont(font()); + g->setFont(AddRef(font())); g->drawUIText(text(), fg, gfx::ColorNone, textRc.origin(), 0); } } diff --git a/src/app/ui/color_selector.cpp b/src/app/ui/color_selector.cpp index 90318d394..1197dab63 100644 --- a/src/app/ui/color_selector.cpp +++ b/src/app/ui/color_selector.cpp @@ -94,10 +94,8 @@ public: } m_paintingThread.join(); - if (m_canvas) { - m_canvas->dispose(); - m_canvas = nullptr; - } + if (m_canvas) + m_canvas.reset(); } } @@ -113,18 +111,16 @@ public: std::unique_lock lock(m_mutex); stopCurrentPainting(lock); - auto oldCanvas = m_canvas; - m_canvas = os::instance()->createSurface(w, h, activeCS); + os::SurfaceRef oldCanvas = m_canvas; + m_canvas = os::instance()->makeSurface(w, h, activeCS); os::Paint paint; paint.color(bgColor); paint.style(os::Paint::Fill); m_canvas->drawRect(gfx::Rect(0, 0, w, h), paint); - if (oldCanvas) { - m_canvas->drawSurface(oldCanvas, 0, 0); - oldCanvas->dispose(); - } + if (oldCanvas) + m_canvas->drawSurface(oldCanvas.get(), 0, 0); } - return m_canvas; + return m_canvas.get(); } void startBgPainting(ColorSelector* colorSelector, @@ -182,7 +178,7 @@ private: { lock.unlock(); colorSel->onPaintSurfaceInBgThread( - m_canvas, + m_canvas.get(), m_mainBounds, m_bottomBarBounds, m_alphaBarBounds, @@ -211,7 +207,7 @@ private: std::mutex m_mutex; std::condition_variable m_paintingCV; std::condition_variable m_waitStopCV; - os::Surface* m_canvas; + os::SurfaceRef m_canvas; ColorSelector* m_colorSelector; ui::Manager* m_manager; gfx::Rect m_mainBounds; diff --git a/src/app/ui/dithering_selector.cpp b/src/app/ui/dithering_selector.cpp index 3e1e72998..7d1f03425 100644 --- a/src/app/ui/dithering_selector.cpp +++ b/src/app/ui/dithering_selector.cpp @@ -63,11 +63,6 @@ public: { } - ~DitherItem() { - if (m_preview) - m_preview->dispose(); - } - render::DitheringAlgorithm algo() const { return m_dithering.algorithm(); } @@ -85,11 +80,10 @@ private: // Reuse the preview in case that the palette is exactly the same if (palette->id() == m_palId && palette->getModifications() == m_palMods) - return m_preview; + return m_preview.get(); // In other case regenerate the preview for the current palette - m_preview->dispose(); - m_preview = nullptr; + m_preview.reset(); } const int w = 128, h = 16; @@ -116,13 +110,13 @@ private: m_dithering, nullptr, palette, true, -1, nullptr); } - m_preview = os::instance()->createRgbaSurface(w, h); - convert_image_to_surface(image2.get(), palette, m_preview, + m_preview = os::instance()->makeRgbaSurface(w, h); + convert_image_to_surface(image2.get(), palette, m_preview.get(), 0, 0, 0, 0, w, h); m_palId = palette->id(); m_palMods = palette->getModifications(); - return m_preview; + return m_preview.get(); } void onSizeHint(SizeHintEvent& ev) override { @@ -167,7 +161,7 @@ private: bool m_matrixOnly; render::Dithering m_dithering; - os::Surface* m_preview; + os::SurfaceRef m_preview; doc::ObjectId m_palId; int m_palMods; }; diff --git a/src/app/ui/draggable_widget.h b/src/app/ui/draggable_widget.h index 0a8e2fca9..ebcdd6461 100644 --- a/src/app/ui/draggable_widget.h +++ b/src/app/ui/draggable_widget.h @@ -138,10 +138,10 @@ private: gfx::Size sz = getFloatingOverlaySize(); sz.w = std::max(1, sz.w); sz.h = std::max(1, sz.h); - os::Surface* surface = os::instance()->createRgbaSurface(sz.w, sz.h); + os::SurfaceRef surface = os::instance()->makeRgbaSurface(sz.w, sz.h); { - os::SurfaceLock lock(surface); + os::SurfaceLock lock(surface.get()); os::Paint paint; paint.color(gfx::rgba(0, 0, 0, 0)); paint.style(os::Paint::Fill); @@ -149,17 +149,18 @@ private: } { ui::Graphics g(surface, 0, 0); - g.setFont(this->font()); + g.setFont(AddRef(this->font())); drawFloatingOverlay(g); } - m_floatingOverlay.reset(new ui::Overlay(surface, gfx::Point(), - ui::Overlay::MouseZOrder-1)); - ui::OverlayManager::instance()->addOverlay(m_floatingOverlay.get()); + m_floatingOverlay = base::make_ref( + surface, gfx::Point(), + (ui::Overlay::ZOrder)(ui::Overlay::MouseZOrder-1)); + ui::OverlayManager::instance()->addOverlay(m_floatingOverlay); } void destroyFloatingOverlay() { - ui::OverlayManager::instance()->removeOverlay(m_floatingOverlay.get()); + ui::OverlayManager::instance()->removeOverlay(m_floatingOverlay); m_floatingOverlay.reset(); m_isDragging = false; } @@ -213,7 +214,7 @@ private: // Overlay used to show the floating widget (this overlay floats // next to the mouse cursor). - std::unique_ptr m_floatingOverlay; + ui::OverlayRef m_floatingOverlay; // Relative mouse position between the widget and the overlay. gfx::Point m_floatingOffset; diff --git a/src/app/ui/editor/brush_preview.cpp b/src/app/ui/editor/brush_preview.cpp index 010ed2af7..2b78d766b 100644 --- a/src/app/ui/editor/brush_preview.cpp +++ b/src/app/ui/editor/brush_preview.cpp @@ -35,9 +35,9 @@ #include "doc/image_impl.h" #include "doc/layer.h" #include "doc/primitives.h" -#include "os/display.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "render/render.h" #include "ui/manager.h" #include "ui/system.h" @@ -53,8 +53,7 @@ BrushPreview::BrushPreview(Editor* editor) BrushPreview::~BrushPreview() { - if (m_cursor) - m_cursor->dispose(); + m_cursor.reset(); } BrushRef BrushPreview::getCurrentBrush() @@ -462,8 +461,7 @@ void BrushPreview::createNativeCursor() if (m_cursor) { if (m_cursor->width() != cursorBounds.w || m_cursor->height() != cursorBounds.h) { - m_cursor->dispose(); - m_cursor = nullptr; + m_cursor.reset(); } } @@ -472,13 +470,13 @@ void BrushPreview::createNativeCursor() if (!(m_type & NATIVE_CROSSHAIR)) { // TODO should we use ui::set_mouse_cursor()? ui::set_mouse_cursor_reset_info(); - m_editor->manager()->getDisplay()->setNativeMouseCursor(os::NativeCursor::kNoCursor); + m_editor->manager()->display()->setNativeMouseCursor(os::NativeCursor::Hidden); } return; } if (!m_cursor) { - m_cursor = os::instance()->createRgbaSurface(cursorBounds.w, cursorBounds.h); + 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 @@ -516,9 +514,10 @@ void BrushPreview::forEachLittleCrossPixel( // TODO should we use ui::set_mouse_cursor()? ui::set_mouse_cursor_reset_info(); - m_editor->manager()->getDisplay()->setNativeMouseCursor( - m_cursor, m_cursorCenter, - m_editor->manager()->getDisplay()->scale()); + m_editor->manager()->display()->setNativeMouseCursor( + m_cursor.get(), + m_cursorCenter, + m_editor->manager()->display()->scale()); } } diff --git a/src/app/ui/editor/brush_preview.h b/src/app/ui/editor/brush_preview.h index 153530a2c..d3673dd36 100644 --- a/src/app/ui/editor/brush_preview.h +++ b/src/app/ui/editor/brush_preview.h @@ -18,6 +18,7 @@ #include "gfx/point.h" #include "gfx/rect.h" #include "gfx/region.h" +#include "os/surface.h" #include @@ -129,7 +130,7 @@ namespace app { gfx::Point m_editorPosition; // Position in the editor (model) // Native mouse cursor to draw crosshair - os::Surface* m_cursor = nullptr; + os::SurfaceRef m_cursor; gfx::Point m_cursorCenter; // Information about current brush diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index c618bde44..07f9454cf 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -60,9 +60,9 @@ #include "doc/mask_boundaries.h" #include "doc/slice.h" #include "os/color_space.h" -#include "os/display.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/ui.h" #include @@ -676,7 +676,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite if (rendered) { // Convert the render to a os::Surface - static os::Surface* tmp = nullptr; // TODO move this to other centralized place + static os::SurfaceRef tmp = nullptr; // TODO move this to other centralized place if (!tmp || tmp->width() < rc2.w || @@ -684,10 +684,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite tmp->colorSpace() != m_document->osColorSpace()) { const int maxw = std::max(rc2.w, tmp ? tmp->width(): 0); const int maxh = std::max(rc2.h, tmp ? tmp->height(): 0); - if (tmp) - tmp->dispose(); - - tmp = os::instance()->createSurface( + tmp = os::instance()->makeSurface( maxw, maxh, m_document->osColorSpace()); } @@ -709,13 +706,13 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite } convert_image_to_surface(rendered.get(), m_sprite->palette(m_frame), - tmp, 0, 0, 0, 0, rc2.w, rc2.h); + tmp.get(), 0, 0, 0, 0, rc2.w, rc2.h); if (newEngine) { - g->drawSurface(tmp, gfx::Rect(0, 0, rc2.w, rc2.h), dest); + g->drawSurface(tmp.get(), gfx::Rect(0, 0, rc2.w, rc2.h), dest); } else { - g->blit(tmp, 0, 0, dest.x, dest.y, dest.w, dest.h); + g->blit(tmp.get(), 0, 0, dest.x, dest.y, dest.w, dest.h); } } } diff --git a/src/app/ui/editor/zooming_state.cpp b/src/app/ui/editor/zooming_state.cpp index 1e30485e4..d65810735 100644 --- a/src/app/ui/editor/zooming_state.cpp +++ b/src/app/ui/editor/zooming_state.cpp @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -16,7 +17,7 @@ #include "app/ui/status_bar.h" #include "doc/sprite.h" #include "gfx/rect.h" -#include "os/display.h" +#include "os/window.h" #include "ui/manager.h" #include "ui/message.h" #include "ui/system.h" @@ -66,7 +67,7 @@ bool ZoomingState::onMouseUp(Editor* editor, MouseMessage* msg) bool ZoomingState::onMouseMove(Editor* editor, MouseMessage* msg) { gfx::Point pt = (msg->position() - m_startPos); - int threshold = 8 * guiscale() * editor->manager()->getDisplay()->scale(); + int threshold = 8 * guiscale() * editor->manager()->display()->scale(); if (m_moved || std::sqrt(pt.x*pt.x + pt.y*pt.y) > threshold) { m_moved = true; diff --git a/src/app/ui/file_list.cpp b/src/app/ui/file_list.cpp index 6c33a2488..9f0b562ed 100644 --- a/src/app/ui/file_list.cpp +++ b/src/app/ui/file_list.cpp @@ -455,8 +455,8 @@ void FileList::onPaint(ui::PaintEvent& ev) g->drawRect(gfx::rgba(0, 0, 0, 64), tbounds); tbounds.shrink(1); - os::Surface* thumbnail = m_selected->getThumbnail(); - g->drawRgbaSurface(thumbnail, + os::SurfaceRef thumbnail = m_selected->getThumbnail(); + g->drawRgbaSurface(thumbnail.get(), gfx::Rect(0, 0, thumbnail->width(), thumbnail->height()), tbounds); } @@ -498,10 +498,10 @@ void FileList::paintItem(ui::Graphics* g, IFileItem* fi, const int i) gfx::Rect textBounds = info.text; // Folder icon or thumbnail - os::Surface* thumbnail = nullptr; + os::SurfaceRef thumbnail = nullptr; if (fi->isFolder()) { if (isListView()) { - thumbnail = theme->parts.folderIconSmall()->bitmap(0); + thumbnail = theme->parts.folderIconSmall()->bitmapRef(0); tbounds = textBounds; tbounds.x += 2*guiscale(); tbounds.w = tbounds.h; @@ -510,8 +510,8 @@ void FileList::paintItem(ui::Graphics* g, IFileItem* fi, const int i) else { thumbnail = (m_zoom < 4.0 ? - theme->parts.folderIconMedium()->bitmap(0): - theme->parts.folderIconBig()->bitmap(0)); + theme->parts.folderIconMedium()->bitmapRef(0): + theme->parts.folderIconBig()->bitmapRef(0)); } } else { @@ -552,7 +552,7 @@ void FileList::paintItem(ui::Graphics* g, IFileItem* fi, const int i) tbounds.shrink(1); } - g->drawRgbaSurface(thumbnail, + g->drawRgbaSurface(thumbnail.get(), gfx::Rect(0, 0, thumbnail->width(), thumbnail->height()), tbounds); } @@ -574,7 +574,7 @@ gfx::Rect FileList::mainThumbnailBounds() if (!m_selected) return result; - os::Surface* thumbnail = m_selected->getThumbnail(); + os::SurfaceRef thumbnail = m_selected->getThumbnail(); if (!thumbnail) return result; diff --git a/src/app/ui/font_popup.cpp b/src/app/ui/font_popup.cpp index 96105bfcc..4bdf44457 100644 --- a/src/app/ui/font_popup.cpp +++ b/src/app/ui/font_popup.cpp @@ -71,15 +71,14 @@ private: if (m_image) { Graphics* g = ev.graphics(); - os::Surface* sur = os::instance()->createRgbaSurface(m_image->width(), - m_image->height()); + os::SurfaceRef sur = os::instance()->makeRgbaSurface(m_image->width(), + m_image->height()); convert_image_to_surface( - m_image.get(), nullptr, sur, + m_image.get(), nullptr, sur.get(), 0, 0, 0, 0, m_image->width(), m_image->height()); - g->drawRgbaSurface(sur, textWidth()+4, 0); - sur->dispose(); + g->drawRgbaSurface(sur.get(), textWidth()+4, 0); } } diff --git a/src/app/ui/main_window.cpp b/src/app/ui/main_window.cpp index bc4661958..61ba7ba3d 100644 --- a/src/app/ui/main_window.cpp +++ b/src/app/ui/main_window.cpp @@ -39,8 +39,8 @@ #include "app/ui/workspace_tabs.h" #include "app/ui_context.h" #include "base/fs.h" -#include "os/display.h" #include "os/system.h" +#include "os/window.h" #include "ui/message.h" #include "ui/splitter.h" #include "ui/system.h" @@ -77,10 +77,8 @@ public: ui::set_theme(ui::get_theme(), newUIScale); - Manager* manager = Manager::getDefault(); - os::Display* display = manager->getDisplay(); - display->setScale(newScreenScale); - manager->setDisplay(display); + Manager::getDefault() + ->updateAllDisplaysWithNewScale(newScreenScale); } }; @@ -371,7 +369,7 @@ void MainWindow::onResize(ui::ResizeEvent& ev) { app::gen::MainWindow::onResize(ev); - os::Display* display = manager()->getDisplay(); + os::Window* display = manager()->display(); if ((display) && (display->scale()*ui::guiscale() > 2) && (!m_scalePanic) && diff --git a/src/app/ui/palette_view.cpp b/src/app/ui/palette_view.cpp index 67ec5a205..1c3f6946f 100644 --- a/src/app/ui/palette_view.cpp +++ b/src/app/ui/palette_view.cpp @@ -591,7 +591,7 @@ void PaletteView::onPaint(ui::PaintEvent& ev) gfx::Color neg = color_utils::blackandwhite_neg(negColor); os::Font* minifont = theme->getMiniFont(); const std::string text = base::convert_to(k); - g->setFont(minifont); + g->setFont(AddRef(minifont)); g->drawText(text, neg, gfx::ColorNone, gfx::Point(box2.x + box2.w/2 - minifont->textLength(text)/2, box2.y + box2.h/2 - minifont->height()/2)); diff --git a/src/app/ui/palettes_listbox.cpp b/src/app/ui/palettes_listbox.cpp index 3f915bc89..049fd3911 100644 --- a/src/app/ui/palettes_listbox.cpp +++ b/src/app/ui/palettes_listbox.cpp @@ -152,7 +152,7 @@ void PalettesListBox::onResourceChange(Resource* resource) void PalettesListBox::onPaintResource(Graphics* g, gfx::Rect& bounds, Resource* resource) { doc::Palette* palette = static_cast(resource)->palette(); - auto tick = SkinTheme::instance()->parts.checkSelected()->bitmap(0); + os::Surface* tick = SkinTheme::instance()->parts.checkSelected()->bitmap(0); // Draw tick (to say "this palette matches the active sprite // palette"). diff --git a/src/app/ui/search_entry.cpp b/src/app/ui/search_entry.cpp index 6b93cfbac..1d6655376 100644 --- a/src/app/ui/search_entry.cpp +++ b/src/app/ui/search_entry.cpp @@ -55,7 +55,7 @@ void SearchEntry::onPaint(ui::PaintEvent& ev) SkinTheme* theme = static_cast(this->theme()); theme->paintEntry(ev); - auto icon = theme->parts.iconSearch()->bitmap(0); + os::Surface* icon = theme->parts.iconSearch()->bitmap(0); Rect bounds = clientBounds(); ev.graphics()->drawColoredRgbaSurface( icon, theme->colors.text(), diff --git a/src/app/ui/skin/font_data.cpp b/src/app/ui/skin/font_data.cpp index bf351502e..ac7ecd94b 100644 --- a/src/app/ui/skin/font_data.cpp +++ b/src/app/ui/skin/font_data.cpp @@ -28,29 +28,7 @@ FontData::FontData(os::FontType type) { } -FontData::~FontData() -{ -#if _DEBUG - static std::set deletedFonts; -#endif - - // Destroy all fonts - for (auto& it : m_fonts) { - os::Font* font = it.second; - if (font) { -#if _DEBUG // Check that there are not double-cached fonts - auto it2 = deletedFonts.find(font); - ASSERT(it2 == deletedFonts.end()); - deletedFonts.insert(font); -#endif - // Don't delete font->fallback() as it's already m_fonts - font->dispose(); - } - } - m_fonts.clear(); -} - -os::Font* FontData::getFont(int size) +os::FontRef FontData::getFont(int size) { if (m_type == os::FontType::SpriteSheet) size = 1; // Same size always @@ -61,7 +39,7 @@ os::Font* FontData::getFont(int size) if (it != m_fonts.end()) return it->second; - os::Font* font = nullptr; + os::FontRef font = nullptr; switch (m_type) { case os::FontType::SpriteSheet: @@ -76,9 +54,9 @@ os::Font* FontData::getFont(int size) } if (m_fallback) { - os::Font* fallback = m_fallback->getFont(m_fallbackSize); + os::FontRef fallback = m_fallback->getFont(m_fallbackSize); if (font) - font->setFallback(fallback); + font->setFallback(fallback.get()); else return fallback; // Don't double-cache the fallback font } diff --git a/src/app/ui/skin/font_data.h b/src/app/ui/skin/font_data.h index ba4e954e5..3980e7f8a 100644 --- a/src/app/ui/skin/font_data.h +++ b/src/app/ui/skin/font_data.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2017 David Capello // // This program is distributed under the terms of @@ -19,7 +20,6 @@ namespace skin { class FontData { public: FontData(os::FontType type); - ~FontData(); void setFilename(const std::string& filename) { m_filename = filename; } void setAntialias(bool antialias) { m_antialias = antialias; } @@ -28,13 +28,13 @@ namespace skin { m_fallbackSize = fallbackSize; } - os::Font* getFont(int size); + os::FontRef getFont(int size); private: os::FontType m_type; std::string m_filename; bool m_antialias; - std::map m_fonts; // key=font size, value=real font + std::map m_fonts; // key=font size, value=real font FontData* m_fallback; int m_fallbackSize; diff --git a/src/app/ui/skin/skin_part.cpp b/src/app/ui/skin/skin_part.cpp index 887531c6f..c1e567ab5 100644 --- a/src/app/ui/skin/skin_part.cpp +++ b/src/app/ui/skin/skin_part.cpp @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -26,15 +27,10 @@ SkinPart::~SkinPart() void SkinPart::clear() { - for (auto& bitmap : m_bitmaps) { - if (bitmap) { - bitmap->dispose(); - bitmap = nullptr; - } - } + m_bitmaps.clear(); } -void SkinPart::setBitmap(std::size_t index, os::Surface* bitmap) +void SkinPart::setBitmap(std::size_t index, const os::SurfaceRef& bitmap) { if (index >= m_bitmaps.size()) m_bitmaps.resize(index+1, nullptr); diff --git a/src/app/ui/skin/skin_part.h b/src/app/ui/skin/skin_part.h index 483369251..d9bd20b90 100644 --- a/src/app/ui/skin/skin_part.h +++ b/src/app/ui/skin/skin_part.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -11,6 +11,7 @@ #include "gfx/rect.h" #include "gfx/size.h" +#include "os/surface_list.h" #include #include @@ -24,7 +25,7 @@ namespace app { class SkinPart { public: - typedef std::vector Bitmaps; + using Bitmaps = os::SurfaceList; SkinPart(); ~SkinPart(); @@ -35,12 +36,18 @@ namespace app { void clear(); // It doesn't destroy the previous bitmap in the given "index". - void setBitmap(std::size_t index, os::Surface* bitmap); + void setBitmap(std::size_t index, const os::SurfaceRef& bitmap); void setSpriteBounds(const gfx::Rect& bounds); void setSlicesBounds(const gfx::Rect& bounds); os::Surface* bitmap(std::size_t index) const { - return (index < m_bitmaps.size() ? m_bitmaps[index]: nullptr); + return (index < m_bitmaps.size() ? const_cast(this)->m_bitmaps[index].get(): nullptr); + } + + os::SurfaceRef bitmapRef(std::size_t index) { + return (index < m_bitmaps.size() ? + const_cast(this)->m_bitmaps[index]: + nullptr); } os::Surface* bitmapNW() const { return bitmap(0); } diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp index 0036832b7..2e3bd1611 100644 --- a/src/app/ui/skin/skin_theme.cpp +++ b/src/app/ui/skin/skin_theme.cpp @@ -76,7 +76,7 @@ struct app::skin::SkinTheme::BackwardCompatibility { const int h = font->height(); style.setId(theme->styles.slider()->id()); - style.setFont(font); + style.setFont(AddRef(font)); auto part = theme->parts.sliderEmpty(); style.setBorder( @@ -236,9 +236,7 @@ SkinTheme::~SkinTheme() for (auto& it : m_cursors) delete it.second; // Delete cursor - if (m_sheet) - m_sheet->dispose(); - + m_sheet.reset(); m_parts_by_id.clear(); // Delete all styles. @@ -325,7 +323,7 @@ void SkinTheme::loadSheet() { // Load the skin sheet std::string sheet_filename(base::join_path(m_path, "sheet.png")); - os::Surface* newSheet = nullptr; + os::SurfaceRef newSheet; try { newSheet = os::instance()->loadRgbaSurface(sheet_filename.c_str()); } @@ -337,10 +335,8 @@ void SkinTheme::loadSheet() throw base::Exception("Error loading %s file", sheet_filename.c_str()); // Replace the sprite sheet - if (m_sheet) { - m_sheet->dispose(); - m_sheet = nullptr; - } + if (m_sheet) + m_sheet.reset(); m_sheet = newSheet; if (m_sheet) m_sheet->applyScale(guiscale()); @@ -400,7 +396,7 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) if (sizeStr) size = std::strtol(sizeStr, nullptr, 10); - os::Font* font = fontData->getFont(size); + os::FontRef font = fontData->getFont(size); m_themeFonts[idStr] = font; if (id == "default") @@ -479,7 +475,7 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) if (w > 0 && h > 0) { part->setSpriteBounds(gfx::Rect(x, y, w, h)); - part->setBitmap(0, sliceSheet(part->bitmap(0), gfx::Rect(x, y, w, h))); + part->setBitmap(0, sliceSheet(part->bitmapRef(0), gfx::Rect(x, y, w, h))); } else if (xmlPart->Attribute("w1")) { // 3x3-1 part (NW, N, NE, E, SE, S, SW, W) int w1 = scale*strtol(xmlPart->Attribute("w1"), nullptr, 10); @@ -492,14 +488,14 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) part->setSpriteBounds(gfx::Rect(x, y, w1+w2+w3, h1+h2+h3)); part->setSlicesBounds(gfx::Rect(w1, h1, w2, h2)); - part->setBitmap(0, sliceSheet(part->bitmap(0), gfx::Rect(x, y, w1, h1))); // NW - part->setBitmap(1, sliceSheet(part->bitmap(1), gfx::Rect(x+w1, y, w2, h1))); // N - part->setBitmap(2, sliceSheet(part->bitmap(2), gfx::Rect(x+w1+w2, y, w3, h1))); // NE - part->setBitmap(3, sliceSheet(part->bitmap(3), gfx::Rect(x+w1+w2, y+h1, w3, h2))); // E - part->setBitmap(4, sliceSheet(part->bitmap(4), gfx::Rect(x+w1+w2, y+h1+h2, w3, h3))); // SE - part->setBitmap(5, sliceSheet(part->bitmap(5), gfx::Rect(x+w1, y+h1+h2, w2, h3))); // S - part->setBitmap(6, sliceSheet(part->bitmap(6), gfx::Rect(x, y+h1+h2, w1, h3))); // SW - part->setBitmap(7, sliceSheet(part->bitmap(7), gfx::Rect(x, y+h1, w1, h2))); // W + part->setBitmap(0, sliceSheet(part->bitmapRef(0), gfx::Rect(x, y, w1, h1))); // NW + part->setBitmap(1, sliceSheet(part->bitmapRef(1), gfx::Rect(x+w1, y, w2, h1))); // N + part->setBitmap(2, sliceSheet(part->bitmapRef(2), gfx::Rect(x+w1+w2, y, w3, h1))); // NE + part->setBitmap(3, sliceSheet(part->bitmapRef(3), gfx::Rect(x+w1+w2, y+h1, w3, h2))); // E + part->setBitmap(4, sliceSheet(part->bitmapRef(4), gfx::Rect(x+w1+w2, y+h1+h2, w3, h3))); // SE + part->setBitmap(5, sliceSheet(part->bitmapRef(5), gfx::Rect(x+w1, y+h1+h2, w2, h3))); // S + part->setBitmap(6, sliceSheet(part->bitmapRef(6), gfx::Rect(x, y+h1+h2, w1, h3))); // SW + part->setBitmap(7, sliceSheet(part->bitmapRef(7), gfx::Rect(x, y+h1, w1, h2))); // W } // Is it a mouse cursor? @@ -516,10 +512,8 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) it->second = nullptr; } - // TODO share the Surface with the SkinPart - os::Surface* slice = sliceSheet(nullptr, gfx::Rect(x, y, w, h)); - Cursor* cursor = - new Cursor(slice, gfx::Point(focusx, focusy)); + os::SurfaceRef slice = sliceSheet(nullptr, gfx::Rect(x, y, w, h)); + Cursor* cursor = new Cursor(slice, gfx::Point(focusx, focusy)); m_cursors[cursorName] = cursor; for (int c=0; cAttribute("font"); if (fontId) { - os::Font* font = m_themeFonts[fontId]; + os::FontRef font = m_themeFonts[fontId]; style->setFont(font); } } @@ -711,7 +705,7 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) SkinPartPtr part = it->second; if (part) { if (layer.type() == ui::Style::Layer::Type::kIcon) - layer.setIcon(part->bitmap(0)); + layer.setIcon(AddRef(part->bitmap(0))); else { layer.setSpriteSheet(m_sheet); layer.setSpriteBounds(part->spriteBounds()); @@ -748,21 +742,20 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) ThemeFile::updateInternals(); } -os::Surface* SkinTheme::sliceSheet(os::Surface* sur, const gfx::Rect& bounds) +os::SurfaceRef SkinTheme::sliceSheet(os::SurfaceRef sur, const gfx::Rect& bounds) { if (sur && (sur->width() != bounds.w || sur->height() != bounds.h)) { - sur->dispose(); sur = nullptr; } if (!bounds.isEmpty()) { if (!sur) - sur = os::instance()->createRgbaSurface(bounds.w, bounds.h); + sur = os::instance()->makeRgbaSurface(bounds.w, bounds.h); - os::SurfaceLock lockSrc(m_sheet); - os::SurfaceLock lockDst(sur); - m_sheet->blitTo(sur, bounds.x, bounds.y, 0, 0, bounds.w, bounds.h); + os::SurfaceLock lockSrc(m_sheet.get()); + os::SurfaceLock lockDst(sur.get()); + m_sheet->blitTo(sur.get(), bounds.x, bounds.y, 0, 0, bounds.w, bounds.h); } else { ASSERT(!sur); @@ -1455,7 +1448,7 @@ void SkinTheme::drawText(Graphics* g, const char* t, if (t || widget->hasText()) { Rect textrc; - g->setFont(widget->font()); + g->setFont(AddRef(widget->font())); if (!t) t = widget->text().c_str(); @@ -1606,7 +1599,7 @@ void SkinTheme::drawRect(Graphics* g, const Rect& rc, void SkinTheme::drawRect(ui::Graphics* g, const gfx::Rect& rc, SkinPart* skinPart, const bool drawCenter) { - Theme::drawSlices(g, m_sheet, rc, + Theme::drawSlices(g, m_sheet.get(), rc, skinPart->spriteBounds(), skinPart->slicesBounds(), gfx::ColorNone, diff --git a/src/app/ui/skin/skin_theme.h b/src/app/ui/skin/skin_theme.h index 83ef78f5d..ea25e1645 100644 --- a/src/app/ui/skin/skin_theme.h +++ b/src/app/ui/skin/skin_theme.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -26,10 +27,6 @@ namespace ui { class Graphics; } -namespace os { - class Surface; -} - namespace app { namespace skin { @@ -51,9 +48,9 @@ namespace app { int preferredScreenScaling() { return m_preferredScreenScaling; } int preferredUIScaling() { return m_preferredUIScaling; } - os::Font* getDefaultFont() const override { return m_defaultFont; } + os::Font* getDefaultFont() const override { return m_defaultFont.get(); } os::Font* getWidgetFont(const ui::Widget* widget) const override; - os::Font* getMiniFont() const { return m_miniFont; } + os::Font* getMiniFont() const { return m_miniFont.get(); } ui::Cursor* getStandardCursor(ui::CursorType type) override; void initWidget(ui::Widget* widget) override; @@ -138,7 +135,7 @@ namespace app { void loadSheet(); void loadXml(BackwardCompatibility* backward); - os::Surface* sliceSheet(os::Surface* sur, const gfx::Rect& bounds); + os::SurfaceRef sliceSheet(os::SurfaceRef sur, const gfx::Rect& bounds); gfx::Color getWidgetBgColor(ui::Widget* widget); void drawText(ui::Graphics* g, const char* t, @@ -153,7 +150,7 @@ namespace app { std::string findThemePath(const std::string& themeId) const; std::string m_path; - os::Surface* m_sheet; + os::SurfaceRef m_sheet; std::map m_parts_by_id; std::map m_colors_by_id; std::map m_dimensions_by_id; @@ -161,9 +158,9 @@ namespace app { std::vector m_standardCursors; std::map m_styles; std::map m_fonts; - std::map m_themeFonts; - os::Font* m_defaultFont; - os::Font* m_miniFont; + std::map m_themeFonts; + os::FontRef m_defaultFont; + os::FontRef m_miniFont; int m_preferredScreenScaling; int m_preferredUIScaling; }; diff --git a/src/app/ui/tabs.cpp b/src/app/ui/tabs.cpp index 1e1a1cc39..26e793b9d 100644 --- a/src/app/ui/tabs.cpp +++ b/src/app/ui/tabs.cpp @@ -931,12 +931,12 @@ void Tabs::createFloatingOverlay(Tab* tab) { ASSERT(!m_floatingOverlay); - os::Surface* surface = os::instance()->createRgbaSurface( + os::SurfaceRef surface = os::instance()->makeRgbaSurface( tab->width, m_tabsHeight); // Fill the surface with pink color { - os::SurfaceLock lock(surface); + os::SurfaceLock lock(surface.get()); os::Paint paint; paint.color(gfx::rgba(0, 0, 0, 0)); paint.style(os::Paint::Fill); @@ -944,12 +944,14 @@ void Tabs::createFloatingOverlay(Tab* tab) } { Graphics g(surface, 0, 0); - g.setFont(font()); + g.setFont(AddRef(font())); drawTab(&g, g.getClipBounds(), tab, 0, true, true); } - m_floatingOverlay.reset(new Overlay(surface, gfx::Point(), Overlay::MouseZOrder-1)); - OverlayManager::instance()->addOverlay(m_floatingOverlay.get()); + m_floatingOverlay = base::make_ref( + surface, gfx::Point(), + (ui::Overlay::ZOrder)(Overlay::MouseZOrder-1)); + OverlayManager::instance()->addOverlay(m_floatingOverlay); } void Tabs::destroyFloatingTab() @@ -974,7 +976,7 @@ void Tabs::destroyFloatingTab() void Tabs::destroyFloatingOverlay() { if (m_floatingOverlay) { - OverlayManager::instance()->removeOverlay(m_floatingOverlay.get()); + OverlayManager::instance()->removeOverlay(m_floatingOverlay); m_floatingOverlay.reset(); } } diff --git a/src/app/ui/tabs.h b/src/app/ui/tabs.h index 871a55af4..4ca1bec5c 100644 --- a/src/app/ui/tabs.h +++ b/src/app/ui/tabs.h @@ -9,6 +9,7 @@ #define APP_UI_TABS_H_INCLUDED #pragma once +#include "base/ref.h" #include "ui/animated_widget.h" #include "ui/timer.h" #include "ui/widget.h" @@ -286,7 +287,7 @@ namespace app { // (this overlay floats next to the mouse cursor). It's destroyed // and recreated every time the tab is put inside or outside the // Tabs widget. - std::unique_ptr m_floatingOverlay; + base::Ref m_floatingOverlay; // Relative mouse position inside the m_dragTab (used to adjust // the m_floatingOverlay precisely). diff --git a/src/app/ui/timeline/timeline.cpp b/src/app/ui/timeline/timeline.cpp index ec807c5a7..2cda00df5 100644 --- a/src/app/ui/timeline/timeline.cpp +++ b/src/app/ui/timeline/timeline.cpp @@ -2253,14 +2253,13 @@ void Timeline::drawCel(ui::Graphics* g, layer_t layerIndex, frame_t frame, Cel* skinTheme()->calcBorder(this, style)); if (!thumb_bounds.isEmpty()) { - if (os::Surface* surface = thumb::get_cel_thumbnail(cel, thumb_bounds.size())) { + if (os::SurfaceRef surface = thumb::get_cel_thumbnail(cel, thumb_bounds.size())) { const int t = base::clamp(thumb_bounds.w/8, 4, 16); draw_checked_grid(g, thumb_bounds, gfx::Size(t, t), docPref()); - g->drawRgbaSurface(surface, + g->drawRgbaSurface(surface.get(), thumb_bounds.center().x-surface->width()/2, thumb_bounds.center().y-surface->height()/2); - surface->dispose(); } } } @@ -2343,14 +2342,13 @@ void Timeline::drawCelOverlay(ui::Graphics* g) gfx::Rect rc = m_sprite->bounds().fitIn( gfx::Rect(m_thumbnailsOverlayBounds).shrink(1)); - if (os::Surface* surface = thumb::get_cel_thumbnail(cel, rc.size())) { + if (os::SurfaceRef surface = thumb::get_cel_thumbnail(cel, rc.size())) { draw_checked_grid(g, rc, gfx::Size(8, 8)*ui::guiscale(), docPref()); - g->drawRgbaSurface(surface, + g->drawRgbaSurface(surface.get(), rc.center().x-surface->width()/2, rc.center().y-surface->height()/2); g->drawRect(gfx::rgba(0, 0, 0, 128), m_thumbnailsOverlayBounds); - surface->dispose(); } } diff --git a/src/app/util/clipboard_native.cpp b/src/app/util/clipboard_native.cpp index 212421eaa..241d23845 100644 --- a/src/app/util/clipboard_native.cpp +++ b/src/app/util/clipboard_native.cpp @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2016-2018 David Capello // // This program is distributed under the terms of @@ -20,7 +21,7 @@ #include "doc/mask_io.h" #include "doc/palette_io.h" #include "gfx/size.h" -#include "os/display.h" +#include "os/window.h" #include "os/system.h" #include "ui/alert.h" @@ -37,7 +38,7 @@ namespace { clip::format custom_image_format = 0; void* native_display_handle() { - return os::instance()->defaultDisplay()->nativeHandle(); + return os::instance()->defaultWindow()->nativeHandle(); } void custom_error_handler(clip::ErrorCode code) { diff --git a/src/app/widget_loader.cpp b/src/app/widget_loader.cpp index 9b6c15792..8e971786d 100644 --- a/src/app/widget_loader.cpp +++ b/src/app/widget_loader.cpp @@ -497,8 +497,8 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget throw base::Exception("File %s not found", file); try { - os::Surface* sur = os::instance()->loadRgbaSurface(rf.filename().c_str()); - widget = new ImageView(sur, 0, true); + os::SurfaceRef sur = os::instance()->loadRgbaSurface(rf.filename().c_str()); + widget = new ImageView(sur, 0); } catch (...) { throw base::Exception("Error loading %s file", file); diff --git a/src/dio/aseprite_decoder.cpp b/src/dio/aseprite_decoder.cpp index 2dd8e2470..be2ab6bfb 100644 --- a/src/dio/aseprite_decoder.cpp +++ b/src/dio/aseprite_decoder.cpp @@ -773,7 +773,7 @@ void AsepriteDecoder::readColorProfile(doc::Sprite* sprite) readPadding(8); // Without color space, like old Aseprite versions - gfx::ColorSpacePtr cs(nullptr); + gfx::ColorSpaceRef cs(nullptr); switch (type) { diff --git a/src/doc/image.h b/src/doc/image.h index c95587f99..ff1ed89b6 100644 --- a/src/doc/image.h +++ b/src/doc/image.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (c) 2018 Igara Studio S.A. +// Copyright (c) 2018-2020 Igara Studio S.A. // Copyright (c) 2001-2016 David Capello // // This file is released under the terms of the MIT license. @@ -52,7 +52,7 @@ namespace doc { gfx::Rect bounds() const { return m_spec.bounds(); } color_t maskColor() const { return m_spec.maskColor(); } void setMaskColor(color_t c) { m_spec.setMaskColor(c); } - void setColorSpace(const gfx::ColorSpacePtr& cs) { m_spec.setColorSpace(cs); } + void setColorSpace(const gfx::ColorSpaceRef& cs) { m_spec.setColorSpace(cs); } virtual int getMemSize() const override; int getRowStrideSize() const; diff --git a/src/doc/image_spec.h b/src/doc/image_spec.h index c25be4082..a6a14bcb9 100644 --- a/src/doc/image_spec.h +++ b/src/doc/image_spec.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (c) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (c) 2016 David Capello // // This file is released under the terms of the MIT license. @@ -24,7 +24,7 @@ namespace doc { const int width, const int height, const color_t maskColor = 0, - const gfx::ColorSpacePtr& colorSpace = gfx::ColorSpace::MakeNone()) + const gfx::ColorSpaceRef& colorSpace = gfx::ColorSpace::MakeNone()) : m_colorMode(colorMode), m_size(width, height), m_maskColor(maskColor), @@ -38,7 +38,7 @@ namespace doc { int height() const { return m_size.h; } const gfx::Size& size() const { return m_size; } gfx::Rect bounds() const { return gfx::Rect(m_size); } - const gfx::ColorSpacePtr& colorSpace() const { return m_colorSpace; } + const gfx::ColorSpaceRef& colorSpace() const { return m_colorSpace; } // The transparent color for colored images (0 by default) or just 0 for RGBA and Grayscale color_t maskColor() const { return m_maskColor; } @@ -47,7 +47,7 @@ namespace doc { void setWidth(const int width) { m_size.w = width; } void setHeight(const int height) { m_size.h = height; } void setMaskColor(const color_t color) { m_maskColor = color; } - void setColorSpace(const gfx::ColorSpacePtr& cs) { m_colorSpace = cs; } + void setColorSpace(const gfx::ColorSpaceRef& cs) { m_colorSpace = cs; } void setSize(const int width, const int height) { @@ -74,7 +74,7 @@ namespace doc { ColorMode m_colorMode; gfx::Size m_size; color_t m_maskColor; - gfx::ColorSpacePtr m_colorSpace; + gfx::ColorSpaceRef m_colorSpace; }; } // namespace doc diff --git a/src/doc/sprite.cpp b/src/doc/sprite.cpp index 05c5936e2..a43be3661 100644 --- a/src/doc/sprite.cpp +++ b/src/doc/sprite.cpp @@ -159,7 +159,7 @@ void Sprite::setSize(int width, int height) m_spec.setSize(width, height); } -void Sprite::setColorSpace(const gfx::ColorSpacePtr& colorSpace) +void Sprite::setColorSpace(const gfx::ColorSpaceRef& colorSpace) { m_spec.setColorSpace(colorSpace); for (auto cel : uniqueCels()) diff --git a/src/doc/sprite.h b/src/doc/sprite.h index 1e6915676..bafe137bd 100644 --- a/src/doc/sprite.h +++ b/src/doc/sprite.h @@ -81,12 +81,12 @@ namespace doc { gfx::Rect bounds() const { return m_spec.bounds(); } int width() const { return m_spec.width(); } int height() const { return m_spec.height(); } - const gfx::ColorSpacePtr& colorSpace() const { return m_spec.colorSpace(); } + const gfx::ColorSpaceRef& colorSpace() const { return m_spec.colorSpace(); } void setPixelFormat(PixelFormat format); void setPixelRatio(const PixelRatio& pixelRatio); void setSize(int width, int height); - void setColorSpace(const gfx::ColorSpacePtr& colorSpace); + void setColorSpace(const gfx::ColorSpaceRef& colorSpace); // Returns true if the sprite has a background layer and it's visible bool isOpaque() const; diff --git a/src/main/main.cpp b/src/main/main.cpp index 95096d9a0..1c18a3df7 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -19,7 +19,6 @@ #include "base/memory_dump.h" #include "base/system_console.h" #include "os/error.h" -#include "os/scoped_handle.h" #include "os/system.h" #include @@ -83,7 +82,7 @@ int app_main(int argc, char* argv[]) MemLeak memleak; base::SystemConsole systemConsole; app::AppOptions options(argc, const_cast(argv)); - os::ScopedHandle system(os::create_system()); + os::SystemRef system(os::make_system()); app::App app; // Change the memory dump filename to save on disk (.dmp diff --git a/src/tests/test.h b/src/tests/test.h index 1d2d746c8..00b396183 100644 --- a/src/tests/test.h +++ b/src/tests/test.h @@ -40,7 +40,7 @@ int main(int argc, char* argv[]) // Do not create a os::System, as we don't need it for testing purposes. //os::ScopedHandle system(os::create_system()); ui::UISystem uiSystem; - ui::Manager uiManager; + ui::Manager uiManager(nullptr); #endif exitcode = RUN_ALL_TESTS(); diff --git a/src/ui/cursor.cpp b/src/ui/cursor.cpp index 46c641380..908636434 100644 --- a/src/ui/cursor.cpp +++ b/src/ui/cursor.cpp @@ -1,4 +1,5 @@ // Aseprite UI Library +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2016 David Capello // // This file is released under the terms of the MIT license. @@ -15,16 +16,11 @@ namespace ui { -Cursor::Cursor(os::Surface* surface, const gfx::Point& focus) +Cursor::Cursor(const os::SurfaceRef& surface, const gfx::Point& focus) : m_surface(surface) , m_focus(focus) { ASSERT(m_surface != nullptr); } -Cursor::~Cursor() -{ - m_surface->dispose(); -} - } // namespace ui diff --git a/src/ui/cursor.h b/src/ui/cursor.h index 3d9b35f7a..e22434eb8 100644 --- a/src/ui/cursor.h +++ b/src/ui/cursor.h @@ -1,4 +1,5 @@ // Aseprite UI Library +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This file is released under the terms of the MIT license. @@ -9,6 +10,7 @@ #pragma once #include "gfx/point.h" +#include "os/surface.h" namespace os { class Surface; } @@ -16,15 +18,13 @@ namespace ui { class Cursor { public: - // The surface is disposed in ~Cursor. - Cursor(os::Surface* surface, const gfx::Point& focus); - ~Cursor(); + Cursor(const os::SurfaceRef& surface, const gfx::Point& focus); - os::Surface* getSurface() const { return m_surface; } + const os::SurfaceRef& getSurface() const { return m_surface; } const gfx::Point& getFocus() const { return m_focus; } private: - os::Surface* m_surface; + os::SurfaceRef m_surface; gfx::Point m_focus; }; diff --git a/src/ui/graphics.cpp b/src/ui/graphics.cpp index 920011c1f..44eb97de7 100644 --- a/src/ui/graphics.cpp +++ b/src/ui/graphics.cpp @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This file is released under the terms of the MIT license. @@ -19,21 +19,22 @@ #include "gfx/rect.h" #include "gfx/region.h" #include "gfx/size.h" -#include "os/display.h" #include "os/draw_text.h" #include "os/font.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/manager.h" #include "ui/scale.h" #include "ui/theme.h" #include #include +#include namespace ui { -Graphics::Graphics(os::Surface* surface, int dx, int dy) +Graphics::Graphics(const os::SurfaceRef& surface, int dx, int dy) : m_surface(surface) , m_dx(dx) , m_dy(dy) @@ -44,7 +45,7 @@ Graphics::~Graphics() { // If we were drawing in the screen surface, we mark these regions // as dirty for the final flip. - if (m_surface == os::instance()->defaultDisplay()->getSurface()) + if (m_surface == os::instance()->defaultWindow()->surface()) Manager::getDefault()->dirtyRect(m_dirtyBounds); } @@ -132,7 +133,7 @@ void Graphics::setDrawMode(DrawMode mode, int param, gfx::Color Graphics::getPixel(int x, int y) { - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); return m_surface->getPixel(m_dx+x, m_dy+y); } @@ -140,7 +141,7 @@ void Graphics::putPixel(gfx::Color color, int x, int y) { dirty(gfx::Rect(m_dx+x, m_dy+y, 1, 1)); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); m_surface->putPixel(color, m_dx+x, m_dy+y); } @@ -148,7 +149,7 @@ void Graphics::drawHLine(gfx::Color color, int x, int y, int w) { dirty(gfx::Rect(m_dx+x, m_dy+y, w, 1)); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); os::Paint paint; paint.color(color); m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, w, 1), paint); @@ -158,7 +159,7 @@ void Graphics::drawVLine(gfx::Color color, int x, int y, int h) { dirty(gfx::Rect(m_dx+x, m_dy+y, 1, h)); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); os::Paint paint; paint.color(color); m_surface->drawRect(gfx::Rect(m_dx+x, m_dy+y, 1, h), paint); @@ -170,7 +171,7 @@ void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point gfx::Point b(m_dx+_b.x, m_dy+_b.y); dirty(gfx::Rect(a, b)); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); os::Paint paint; paint.color(color); m_surface->drawLine(a, b, paint); @@ -178,7 +179,7 @@ void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point void Graphics::drawPath(gfx::Path& path, const Paint& paint) { - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); auto m = matrix(); save(); @@ -197,7 +198,7 @@ void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig) rc.offset(m_dx, m_dy); dirty(rc); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); os::Paint paint; paint.color(color); paint.style(os::Paint::Stroke); @@ -210,7 +211,7 @@ void Graphics::fillRect(gfx::Color color, const gfx::Rect& rcOrig) rc.offset(m_dx, m_dy); dirty(rc); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); os::Paint paint; paint.color(color); paint.style(os::Paint::Fill); @@ -240,7 +241,7 @@ void Graphics::drawSurface(os::Surface* surface, int x, int y) dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height())); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawSurface(surface, m_dx+x, m_dy+y); } @@ -252,7 +253,7 @@ void Graphics::drawSurface(os::Surface* surface, dstRect.w, dstRect.h)); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawSurface( surface, srcRect, @@ -264,7 +265,7 @@ void Graphics::drawRgbaSurface(os::Surface* surface, int x, int y) dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height())); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawRgbaSurface(surface, m_dx+x, m_dy+y); } @@ -273,7 +274,7 @@ void Graphics::drawRgbaSurface(os::Surface* surface, int srcx, int srcy, int dst dirty(gfx::Rect(m_dx+dstx, m_dy+dsty, w, h)); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawRgbaSurface(surface, srcx, srcy, m_dx+dstx, m_dy+dsty, w, h); } @@ -285,7 +286,7 @@ void Graphics::drawRgbaSurface(os::Surface* surface, dstRect.w, dstRect.h)); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawRgbaSurface( surface, srcRect, @@ -297,7 +298,7 @@ void Graphics::drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, in dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height())); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawColoredRgbaSurface(surface, color, gfx::ColorNone, gfx::Clip(m_dx+x, m_dy+y, 0, 0, surface->width(), surface->height())); } @@ -308,7 +309,7 @@ void Graphics::drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, dirty(gfx::Rect(m_dx+dstx, m_dy+dsty, w, h)); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawColoredRgbaSurface(surface, color, gfx::ColorNone, gfx::Clip(m_dx+dstx, m_dy+dsty, srcx, srcy, w, h)); } @@ -323,7 +324,7 @@ void Graphics::drawSurfaceNine(os::Surface* surface, dirty(displacedDst); os::SurfaceLock lockSrc(surface); - os::SurfaceLock lockDst(m_surface); + os::SurfaceLock lockDst(m_surface.get()); m_surface->drawSurfaceNine(surface, src, center, displacedDst, paint); } @@ -332,11 +333,11 @@ void Graphics::blit(os::Surface* srcSurface, int srcx, int srcy, int dstx, int d dirty(gfx::Rect(m_dx+dstx, m_dy+dsty, w, h)); os::SurfaceLock lockSrc(srcSurface); - os::SurfaceLock lockDst(m_surface); - srcSurface->blitTo(m_surface, srcx, srcy, m_dx+dstx, m_dy+dsty, w, h); + os::SurfaceLock lockDst(m_surface.get()); + srcSurface->blitTo(m_surface.get(), srcx, srcy, m_dx+dstx, m_dy+dsty, w, h); } -void Graphics::setFont(os::Font* font) +void Graphics::setFont(const os::FontRef& font) { m_font = font; } @@ -349,9 +350,9 @@ void Graphics::drawText(base::utf8_const_iterator it, { gfx::Point pt(m_dx+origPt.x, m_dy+origPt.y); - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); gfx::Rect textBounds = - os::draw_text(m_surface, m_font, it, end, fg, bg, pt.x, pt.y, delegate); + os::draw_text(m_surface.get(), m_font.get(), it, end, fg, bg, pt.x, pt.y, delegate); dirty(gfx::Rect(pt.x, pt.y, textBounds.w, textBounds.h)); } @@ -431,12 +432,12 @@ private: void Graphics::drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt, const int mnemonic) { - os::SurfaceLock lock(m_surface); + os::SurfaceLock lock(m_surface.get()); int x = m_dx+pt.x; int y = m_dy+pt.y; - DrawUITextDelegate delegate(m_surface, m_font, mnemonic); - os::draw_text(m_surface, m_font, + DrawUITextDelegate delegate(m_surface.get(), m_font.get(), mnemonic); + os::draw_text(m_surface.get(), m_font.get(), base::utf8_const_iterator(str.begin()), base::utf8_const_iterator(str.end()), fg, bg, x, y, &delegate); @@ -453,7 +454,7 @@ void Graphics::drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Col gfx::Size Graphics::measureUIText(const std::string& str) { return gfx::Size( - Graphics::measureUITextLength(str, m_font), + Graphics::measureUITextLength(str, m_font.get()), m_font->height()); } @@ -611,9 +612,9 @@ void Graphics::dirty(const gfx::Rect& bounds) // ScreenGraphics ScreenGraphics::ScreenGraphics() - : Graphics(os::instance()->defaultDisplay()->getSurface(), 0, 0) + : Graphics(AddRef(os::instance()->defaultWindow()->surface()), 0, 0) { - setFont(get_theme()->getDefaultFont()); + setFont(AddRef(get_theme()->getDefaultFont())); } ScreenGraphics::~ScreenGraphics() diff --git a/src/ui/graphics.h b/src/ui/graphics.h index 0aa03c603..d0db15fb9 100644 --- a/src/ui/graphics.h +++ b/src/ui/graphics.h @@ -15,7 +15,9 @@ #include "gfx/point.h" #include "gfx/rect.h" #include "gfx/size.h" +#include "os/font.h" #include "os/paint.h" +#include "os/surface.h" #include #include @@ -28,8 +30,6 @@ namespace gfx { namespace os { class DrawTextDelegate; - class Font; - class Surface; } namespace ui { @@ -44,13 +44,13 @@ namespace ui { Checked, }; - Graphics(os::Surface* surface, int dx, int dy); + Graphics(const os::SurfaceRef& surface, int dx, int dy); ~Graphics(); int width() const; int height() const; - os::Surface* getInternalSurface() { return m_surface; } + os::Surface* getInternalSurface() { return m_surface.get(); } int getInternalDeltaX() { return m_dx; } int getInternalDeltaY() { return m_dy; } @@ -108,8 +108,8 @@ namespace ui { // FONT & TEXT // ====================================================================== - os::Font* font() { return m_font; } - void setFont(os::Font* font); + os::Font* font() { return m_font.get(); } + void setFont(const os::FontRef& font); void drawText(base::utf8_const_iterator it, const base::utf8_const_iterator& end, @@ -127,11 +127,11 @@ namespace ui { gfx::Size doUIStringAlgorithm(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, int align, bool draw); void dirty(const gfx::Rect& bounds); - os::Surface* m_surface; + os::SurfaceRef m_surface; int m_dx; int m_dy; gfx::Rect m_clipBounds; - os::Font* m_font; + os::FontRef m_font; gfx::Rect m_dirtyBounds; }; diff --git a/src/ui/image_view.cpp b/src/ui/image_view.cpp index 11e5992fa..7618d9248 100644 --- a/src/ui/image_view.cpp +++ b/src/ui/image_view.cpp @@ -21,20 +21,13 @@ namespace ui { -ImageView::ImageView(os::Surface* sur, int align, bool dispose) +ImageView::ImageView(const os::SurfaceRef& sur, int align) : Widget(kImageViewWidget) , m_sur(sur) - , m_disposeSurface(dispose) { setAlign(align); } -ImageView::~ImageView() -{ - if (m_disposeSurface) - delete m_sur; -} - void ImageView::onSizeHint(SizeHintEvent& ev) { gfx::Rect box; @@ -57,7 +50,7 @@ void ImageView::onPaint(PaintEvent& ev) m_sur->width(), m_sur->height()); g->fillRect(bgColor(), bounds); - g->drawRgbaSurface(m_sur, icon.x, icon.y); + g->drawRgbaSurface(m_sur.get(), icon.x, icon.y); } } // namespace ui diff --git a/src/ui/image_view.h b/src/ui/image_view.h index 0f7a42a05..63d1cc7bd 100644 --- a/src/ui/image_view.h +++ b/src/ui/image_view.h @@ -8,6 +8,7 @@ #define UI_IMAGE_VIEW_H_INCLUDED #pragma once +#include "os/ref.h" #include "ui/widget.h" namespace os { @@ -18,16 +19,14 @@ namespace ui { class ImageView : public Widget { public: - ImageView(os::Surface* sur, int align, bool disposeSurface); - ~ImageView(); + ImageView(const os::Ref& sur, int align); protected: void onSizeHint(SizeHintEvent& ev) override; void onPaint(PaintEvent& ev) override; private: - os::Surface* m_sur; - bool m_disposeSurface; + os::Ref m_sur; }; } // namespace ui diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp index c6531dc70..879f207ed 100644 --- a/src/ui/manager.cpp +++ b/src/ui/manager.cpp @@ -22,11 +22,11 @@ #include "base/concurrent_queue.h" #include "base/scoped_value.h" #include "base/time.h" -#include "os/display.h" #include "os/event.h" #include "os/event_queue.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/intern.h" #include "ui/ui.h" @@ -168,10 +168,10 @@ bool Manager::widgetAssociatedToManager(Widget* widget) widget) != mouse_widgets_list.end()); } -Manager::Manager() +Manager::Manager(const os::WindowRef& nativeWindow) : Widget(kManagerWidget) - , m_display(nullptr) - , m_eventQueue(nullptr) + , m_display(nativeWindow) + , m_eventQueue(os::instance()->eventQueue()) , m_lockedWindow(nullptr) , m_mouseButton(kButtonNone) { @@ -234,18 +234,6 @@ Manager::~Manager() } } -void Manager::setDisplay(os::Display* display) -{ - base::ScopedValue lock( - auto_window_adjustment, false, - auto_window_adjustment); - - m_display = display; - m_eventQueue = os::instance()->eventQueue(); - - onNewDisplayConfiguration(); -} - void Manager::run() { MessageLoop loop(this); @@ -284,6 +272,13 @@ void Manager::flipDisplay() } } +void Manager::updateAllDisplaysWithNewScale(int scale) +{ + m_display->setScale(scale); + + onNewDisplayConfiguration(); +} + bool Manager::generateMessages() { #ifdef DEBUG_UI_THREADS @@ -359,33 +354,36 @@ void Manager::generateMessagesFromOSEvents() // Events from laf-os os::Event osEvent; for (;;) { - // TODO Add timers to laf::os library so we can wait for then in - // the OS message loop. - bool canWait = (msg_queue.empty() && - redrawState == RedrawState::Normal && - !Timer::haveRunningTimers()); + // Calculate how much time we can wait for the next message in the + // event queue. + double timeout = 0.0; + if (msg_queue.empty() && redrawState == RedrawState::Normal) { + if (!Timer::getNextTimeout(timeout)) + timeout = os::EventQueue::kWithoutTimeout; + } - if (canWait && used_msg_queue.empty()) + if (timeout == os::EventQueue::kWithoutTimeout && used_msg_queue.empty()) collectGarbage(); #if _DEBUG else if (!m_garbage.empty()) { GARBAGE_TRACE("collectGarbage() wasn't called #objects=%d" - " (msg_queue=%d used_msg_queue=%d redrawState=%d runningTimers=%d)\n", + " (msg_queue=%d used_msg_queue=%d redrawState=%d timeout=%.16g)\n", int(m_garbage.size()), msg_queue.size(), used_msg_queue.size(), int(redrawState), - Timer::haveRunningTimers()); + timeout); } #endif - m_eventQueue->getEvent(osEvent, canWait); + m_eventQueue->getEvent(osEvent, timeout); if (osEvent.type() == os::Event::None) break; switch (osEvent.type()) { - case os::Event::CloseDisplay: { + case os::Event::CloseApp: + case os::Event::CloseWindow: { Message* msg = new Message(kCloseDisplayMessage); msg->setRecipient(this); msg->setPropagateToChildren(true); @@ -393,7 +391,7 @@ void Manager::generateMessagesFromOSEvents() break; } - case os::Event::ResizeDisplay: { + case os::Event::ResizeWindow: { Message* msg = new Message(kResizeDisplayMessage); msg->setRecipient(this); msg->setPropagateToChildren(true); @@ -1346,7 +1344,7 @@ void Manager::onNewDisplayConfiguration() } } - _internal_set_mouse_display(m_display); + _internal_set_mouse_display(m_display.get()); invalidate(); flushRedraw(); } @@ -1517,7 +1515,7 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget) // Restore overlays in the region that we're going to paint. OverlayManager::instance()->restoreOverlappedAreas(paintMsg->rect()); - os::Surface* surface = m_display->getSurface(); + os::Surface* surface = m_display->surface(); surface->saveClip(); if (surface->clipRect(paintMsg->rect())) { diff --git a/src/ui/manager.h b/src/ui/manager.h index 4554548ad..aca862a2b 100644 --- a/src/ui/manager.h +++ b/src/ui/manager.h @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This file is released under the terms of the MIT license. @@ -10,6 +10,7 @@ #pragma once #include "gfx/region.h" +#include "os/window.h" #include "ui/keys.h" #include "ui/message_type.h" #include "ui/mouse_button.h" @@ -17,7 +18,6 @@ #include "ui/widget.h" namespace os { - class Display; class EventQueue; } @@ -32,12 +32,10 @@ namespace ui { static Manager* getDefault() { return m_defaultManager; } static bool widgetAssociatedToManager(Widget* widget); - Manager(); + Manager(const os::WindowRef& nativeWindow); ~Manager(); - os::Display* getDisplay() { return m_display; } - - void setDisplay(os::Display* display); + os::Window* display() const { return m_display.get(); } // Executes the main message loop. void run(); @@ -45,6 +43,8 @@ namespace ui { // Refreshes the real display with the UI content. void flipDisplay(); + void updateAllDisplaysWithNewScale(int scale); + // Adds the given "msg" message to the queue of messages to be // dispached. "msg" cannot be used after this function, it'll be // automatically deleted. @@ -168,7 +168,7 @@ namespace ui { static gfx::Region m_dirtyRegion; WidgetsList m_garbage; - os::Display* m_display; + os::WindowRef m_display; os::EventQueue* m_eventQueue; gfx::Region m_invalidRegion; // Invalid region (we didn't receive paint messages yet for this). diff --git a/src/ui/message_loop.cpp b/src/ui/message_loop.cpp index 6d6e33e7a..b521762a9 100644 --- a/src/ui/message_loop.cpp +++ b/src/ui/message_loop.cpp @@ -1,4 +1,5 @@ // Aseprite UI Library +// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2001-2013 David Capello // // This file is released under the terms of the MIT license. @@ -10,8 +11,6 @@ #include "ui/message_loop.h" -#include "base/chrono.h" -#include "base/thread.h" #include "ui/manager.h" namespace ui { @@ -23,22 +22,8 @@ MessageLoop::MessageLoop(Manager* manager) void MessageLoop::pumpMessages() { - base::Chrono chrono; - if (m_manager->generateMessages()) m_manager->dispatchMessages(); - - // If the dispatching of messages was faster than 10 milliseconds, - // it means that the process is not using a lot of CPU, so we can - // wait the difference to cover those 10 milliseconds - // sleeping. With this code we can avoid 100% CPU usage. - // - // TODO check if we require this code, after adding support of event - // queues that wait for events. - // - double elapsedMSecs = chrono.elapsed() * 1000.0; - if (elapsedMSecs > 0.0 && elapsedMSecs < 10.0) - base::this_thread::sleep_for((10.0 - elapsedMSecs) / 1000.0); } } // namespace ui diff --git a/src/ui/move_region.cpp b/src/ui/move_region.cpp index 9ce9292a7..0c1c741a1 100644 --- a/src/ui/move_region.cpp +++ b/src/ui/move_region.cpp @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This file is released under the terms of the MIT license. @@ -11,9 +11,9 @@ #include "ui/manager.h" -#include "os/display.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/overlay_manager.h" #include @@ -24,9 +24,9 @@ using namespace gfx; void move_region(Manager* manager, const Region& region, int dx, int dy) { - os::Display* display = manager->getDisplay(); - ASSERT(display); - if (!display) + os::Window* window = manager->display(); + ASSERT(window); + if (!window) return; auto overlays = ui::OverlayManager::instance(); @@ -34,7 +34,7 @@ void move_region(Manager* manager, const Region& region, int dx, int dy) bounds |= gfx::Rect(bounds).offset(dx, dy); overlays->restoreOverlappedAreas(bounds); - os::Surface* surface = display->getSurface(); + os::Surface* surface = window->surface(); os::SurfaceLock lock(surface); // Fast path, move one rectangle. diff --git a/src/ui/overlay.cpp b/src/ui/overlay.cpp index 7b91e3f00..18be98fb4 100644 --- a/src/ui/overlay.cpp +++ b/src/ui/overlay.cpp @@ -17,7 +17,9 @@ namespace ui { -Overlay::Overlay(os::Surface* overlaySurface, const gfx::Point& pos, ZOrder zorder) +Overlay::Overlay(const os::SurfaceRef& overlaySurface, + const gfx::Point& pos, + ZOrder zorder) : m_surface(overlaySurface) , m_overlap(nullptr) , m_captured(nullptr) @@ -36,16 +38,16 @@ Overlay::~Overlay() manager->invalidateRect(gfx::Rect(m_pos.x, m_pos.y, m_surface->width(), m_surface->height())); - m_surface->dispose(); + m_surface.reset(); } if (m_overlap) - m_overlap->dispose(); + m_overlap.reset(); } -os::Surface* Overlay::setSurface(os::Surface* newSurface) +os::SurfaceRef Overlay::setSurface(const os::SurfaceRef& newSurface) { - os::Surface* oldSurface = m_surface; + os::SurfaceRef oldSurface = m_surface; m_surface = newSurface; return oldSurface; } @@ -64,8 +66,8 @@ void Overlay::drawOverlay() !m_captured) return; - os::SurfaceLock lock(m_surface); - m_captured->drawRgbaSurface(m_surface, m_pos.x, m_pos.y); + os::SurfaceLock lock(m_surface.get()); + m_captured->drawRgbaSurface(m_surface.get(), m_pos.x, m_pos.y); Manager::getDefault()->dirtyRect( gfx::Rect(m_pos.x, m_pos.y, @@ -89,13 +91,13 @@ void Overlay::captureOverlappedArea(os::Surface* screen) if (!m_overlap) { // Use the same color space for the overlay as in the screen - m_overlap = os::instance()->createSurface(m_surface->width(), - m_surface->height(), - screen->colorSpace()); + m_overlap = os::instance()->makeSurface(m_surface->width(), + m_surface->height(), + screen->colorSpace()); } - os::SurfaceLock lock(m_overlap); - screen->blitTo(m_overlap, m_pos.x, m_pos.y, 0, 0, + os::SurfaceLock lock(m_overlap.get()); + screen->blitTo(m_overlap.get(), m_pos.x, m_pos.y, 0, 0, m_overlap->width(), m_overlap->height()); m_captured = screen; @@ -112,7 +114,7 @@ void Overlay::restoreOverlappedArea(const gfx::Rect& restoreBounds) !restoreBounds.intersects(bounds())) return; - os::SurfaceLock lock(m_overlap); + os::SurfaceLock lock(m_overlap.get()); m_overlap->blitTo(m_captured, 0, 0, m_pos.x, m_pos.y, m_overlap->width(), m_overlap->height()); diff --git a/src/ui/overlay.h b/src/ui/overlay.h index afd14710b..79ed040eb 100644 --- a/src/ui/overlay.h +++ b/src/ui/overlay.h @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2001-2016 David Capello // // This file is released under the terms of the MIT license. @@ -9,8 +9,10 @@ #define UI_OVERLAY_H_INCLUDED #pragma once +#include "base/ref.h" #include "gfx/fwd.h" #include "gfx/point.h" +#include "os/surface.h" #include "ui/base.h" namespace os { @@ -19,17 +21,22 @@ namespace os { namespace ui { - class Overlay { + class Overlay; + using OverlayRef = base::Ref; + + class Overlay : public base::RefCountT { public: - typedef int ZOrder; + enum ZOrder { + NormalZOrder = 0, + MouseZOrder = 5000 + }; - static const ZOrder NormalZOrder = 0; - static const ZOrder MouseZOrder = 5000; - - Overlay(os::Surface* overlaySurface, const gfx::Point& pos, ZOrder zorder = 0); + Overlay(const os::SurfaceRef& overlaySurface, + const gfx::Point& pos, + ZOrder zorder = NormalZOrder); ~Overlay(); - os::Surface* setSurface(os::Surface* newSurface); + os::SurfaceRef setSurface(const os::SurfaceRef& newSurface); const gfx::Point& position() const { return m_pos; } gfx::Rect bounds() const; @@ -45,8 +52,8 @@ namespace ui { } private: - os::Surface* m_surface; - os::Surface* m_overlap; + os::SurfaceRef m_surface; + os::SurfaceRef m_overlap; // Surface where we captured the overlapped (m_overlap) // region. It's nullptr if the overlay wasn't drawn yet. diff --git a/src/ui/overlay_manager.cpp b/src/ui/overlay_manager.cpp index 132741d3c..597902c68 100644 --- a/src/ui/overlay_manager.cpp +++ b/src/ui/overlay_manager.cpp @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2016 David Capello // // This file is released under the terms of the MIT license. @@ -11,8 +11,8 @@ #include "ui/overlay_manager.h" -#include "os/display.h" #include "os/surface.h" +#include "os/window.h" #include "ui/manager.h" #include "ui/overlay.h" @@ -20,8 +20,8 @@ namespace ui { -static bool less_than(Overlay* x, Overlay* y) { - return *x < *y; +static bool zorder_less_than(const OverlayRef& a, const OverlayRef& b) { + return *a < *b; } OverlayManager* OverlayManager::m_singleton = nullptr; @@ -46,13 +46,13 @@ OverlayManager::~OverlayManager() { } -void OverlayManager::addOverlay(Overlay* overlay) +void OverlayManager::addOverlay(const OverlayRef& overlay) { - iterator it = std::lower_bound(begin(), end(), overlay, less_than); + iterator it = std::lower_bound(begin(), end(), overlay, zorder_less_than); m_overlays.insert(it, overlay); } -void OverlayManager::removeOverlay(Overlay* overlay) +void OverlayManager::removeOverlay(const OverlayRef& overlay) { if (overlay) overlay->restoreOverlappedArea(gfx::Rect()); @@ -73,7 +73,7 @@ void OverlayManager::restoreOverlappedAreas(const gfx::Rect& restoreBounds) if (!manager) return; - for (Overlay* overlay : *this) + for (auto& overlay : *this) overlay->restoreOverlappedArea(restoreBounds); } @@ -86,13 +86,13 @@ void OverlayManager::drawOverlays() if (!manager) return; - os::Surface* displaySurface = manager->getDisplay()->getSurface(); + os::Surface* displaySurface = manager->display()->surface(); os::SurfaceLock lock(displaySurface); - for (Overlay* overlay : *this) + for (auto& overlay : *this) overlay->captureOverlappedArea(displaySurface); - for (Overlay* overlay : *this) + for (auto& overlay : *this) overlay->drawOverlay(); } diff --git a/src/ui/overlay_manager.h b/src/ui/overlay_manager.h index bfeb73781..463754572 100644 --- a/src/ui/overlay_manager.h +++ b/src/ui/overlay_manager.h @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2001-2015 David Capello // // This file is released under the terms of the MIT license. @@ -9,16 +9,17 @@ #define UI_OVERLAY_MANAGER_H_INCLUDED #pragma once +#include "base/ref.h" #include "gfx/rect.h" #include "ui/base.h" +#include "ui/overlay.h" + #include namespace os { class Surface; } namespace ui { - class Overlay; - class OverlayManager { friend class UISystem; // So it can call destroyInstance() from ~UISystem static OverlayManager* m_singleton; @@ -29,8 +30,8 @@ namespace ui { public: static OverlayManager* instance(); - void addOverlay(Overlay* overlay); - void removeOverlay(Overlay* overlay); + void addOverlay(const OverlayRef& overlay); + void removeOverlay(const OverlayRef& overlay); void drawOverlays(); void restoreOverlappedAreas(const gfx::Rect& bounds); @@ -38,7 +39,7 @@ namespace ui { private: static void destroyInstance(); - typedef std::vector OverlayList; + typedef std::vector OverlayList; typedef OverlayList::iterator iterator; iterator begin() { return m_overlays.begin(); } diff --git a/src/ui/style.cpp b/src/ui/style.cpp index 83abe1ce9..583922579 100644 --- a/src/ui/style.cpp +++ b/src/ui/style.cpp @@ -1,4 +1,5 @@ // Aseprite UI Library +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2017 David Capello // // This file is released under the terms of the MIT license. @@ -10,6 +11,8 @@ #include "ui/style.h" +#include "os/font.h" + namespace ui { // static @@ -29,6 +32,11 @@ Style::Style(const Style* base) m_layers = base->layers(); } +void Style::setFont(const os::Ref& font) +{ + m_font = font; +} + void Style::addLayer(const Layer& layer) { int i, j = int(m_layers.size()); diff --git a/src/ui/style.h b/src/ui/style.h index 980a0e71d..441488089 100644 --- a/src/ui/style.h +++ b/src/ui/style.h @@ -1,4 +1,5 @@ // Aseprite UI Library +// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2017 David Capello // // This file is released under the terms of the MIT license. @@ -13,6 +14,8 @@ #include "gfx/point.h" #include "gfx/rect.h" #include "gfx/size.h" +#include "os/font.h" +#include "os/surface.h" #include "ui/base.h" #include @@ -62,8 +65,8 @@ namespace ui { int align() const { return m_align; } gfx::Color color() const { return m_color; } - os::Surface* icon() const { return m_icon; } - os::Surface* spriteSheet() const { return m_spriteSheet; } + os::Surface* icon() const { return m_icon.get(); } + os::Surface* spriteSheet() const { return m_spriteSheet.get(); } const gfx::Rect& spriteBounds() const { return m_spriteBounds; } const gfx::Rect& slicesBounds() const { return m_slicesBounds; } const gfx::Point& offset() const { return m_offset; } @@ -72,8 +75,8 @@ namespace ui { void setFlags(const int flags) { m_flags = flags; } void setAlign(const int align) { m_align = align; } void setColor(gfx::Color color) { m_color = color; } - void setIcon(os::Surface* icon) { m_icon = icon; } - void setSpriteSheet(os::Surface* spriteSheet) { m_spriteSheet = spriteSheet; } + void setIcon(const os::SurfaceRef& icon) { m_icon = icon; } + void setSpriteSheet(const os::SurfaceRef& spriteSheet) { m_spriteSheet = spriteSheet; } void setSpriteBounds(const gfx::Rect& bounds) { m_spriteBounds = bounds; } void setSlicesBounds(const gfx::Rect& bounds) { m_slicesBounds = bounds; } void setOffset(const gfx::Point& offset) { m_offset = offset; } @@ -83,8 +86,8 @@ namespace ui { int m_flags; int m_align; gfx::Color m_color; - os::Surface* m_icon; - os::Surface* m_spriteSheet; + os::SurfaceRef m_icon; + os::SurfaceRef m_spriteSheet; gfx::Rect m_spriteBounds; gfx::Rect m_slicesBounds; gfx::Point m_offset; @@ -100,7 +103,7 @@ namespace ui { const gfx::Border& margin() const { return m_margin; } const gfx::Border& border() const { return m_border; } const gfx::Border& padding() const { return m_padding; } - os::Font* font() const { return m_font; } + os::Font* font() const { return m_font.get(); } const Layers& layers() const { return m_layers; } Layers& layers() { return m_layers; } @@ -108,7 +111,7 @@ namespace ui { void setMargin(const gfx::Border& value) { m_margin = value; } void setBorder(const gfx::Border& value) { m_border = value; } void setPadding(const gfx::Border& value) { m_padding = value; } - void setFont(os::Font* font) { m_font = font; } + void setFont(const os::FontRef& font); void addLayer(const Layer& layer); private: @@ -118,7 +121,7 @@ namespace ui { gfx::Border m_margin; gfx::Border m_border; gfx::Border m_padding; - os::Font* m_font; + os::FontRef m_font; }; } // namespace ui diff --git a/src/ui/system.cpp b/src/ui/system.cpp index 16fcab42a..bc4461215 100644 --- a/src/ui/system.cpp +++ b/src/ui/system.cpp @@ -13,11 +13,11 @@ #include "base/thread.h" #include "gfx/point.h" -#include "os/display.h" #include "os/event.h" #include "os/event_queue.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/clipboard_delegate.h" #include "ui/cursor.h" #include "ui/intern.h" @@ -40,8 +40,8 @@ base::thread::native_id_type main_gui_thread; static CursorType mouse_cursor_type = kOutsideDisplay; static const Cursor* mouse_cursor_custom = nullptr; static const Cursor* mouse_cursor = nullptr; -static os::Display* mouse_display = nullptr; -static Overlay* mouse_cursor_overlay = nullptr; +static os::Window* mouse_display = nullptr; +static OverlayRef mouse_cursor_overlay = nullptr; static bool use_native_mouse_cursor = true; static bool support_native_custom_cursor = false; @@ -58,7 +58,7 @@ static void update_mouse_overlay(const Cursor* cursor) if (mouse_cursor && mouse_scares == 0) { if (!mouse_cursor_overlay) { - mouse_cursor_overlay = new Overlay( + mouse_cursor_overlay = base::make_ref( mouse_cursor->getSurface(), get_mouse_position(), Overlay::MouseZOrder); @@ -73,8 +73,7 @@ static void update_mouse_overlay(const Cursor* cursor) else if (mouse_cursor_overlay) { OverlayManager::instance()->removeOverlay(mouse_cursor_overlay); mouse_cursor_overlay->setSurface(nullptr); - delete mouse_cursor_overlay; - mouse_cursor_overlay = nullptr; + mouse_cursor_overlay.reset(); } } @@ -88,16 +87,16 @@ static bool update_custom_native_cursor(const Cursor* cursor) if (cursor) { result = mouse_display->setNativeMouseCursor( // The surface is already scaled by guiscale() - cursor->getSurface(), + cursor->getSurface().get(), cursor->getFocus(), // We scale the cursor by the os::Display scale mouse_display->scale() * mouse_cursor_scale); } else if (mouse_cursor_type == kOutsideDisplay) { - result = mouse_display->setNativeMouseCursor(os::kArrowCursor); + result = mouse_display->setNativeMouseCursor(os::NativeCursor::Arrow); } else { - result = mouse_display->setNativeMouseCursor(os::kNoCursor); + result = mouse_display->setNativeMouseCursor(os::NativeCursor::Hidden); } } @@ -106,43 +105,43 @@ static bool update_custom_native_cursor(const Cursor* cursor) static void update_mouse_cursor() { - os::NativeCursor nativeCursor = os::kNoCursor; + os::NativeCursor nativeCursor = os::NativeCursor::Hidden; const Cursor* cursor = nullptr; if (use_native_mouse_cursor || mouse_cursor_type == kOutsideDisplay) { switch (mouse_cursor_type) { case ui::kOutsideDisplay: - nativeCursor = os::kArrowCursor; + nativeCursor = os::NativeCursor::Arrow; break; case ui::kNoCursor: break; case ui::kArrowCursor: case ui::kArrowPlusCursor: - nativeCursor = os::kArrowCursor; + nativeCursor = os::NativeCursor::Arrow; break; case ui::kCrosshairCursor: - nativeCursor = os::kCrosshairCursor; + nativeCursor = os::NativeCursor::Crosshair; break; case ui::kForbiddenCursor: - nativeCursor = os::kForbiddenCursor; + nativeCursor = os::NativeCursor::Forbidden; break; case ui::kHandCursor: - nativeCursor = os::kLinkCursor; + nativeCursor = os::NativeCursor::Link; break; case ui::kScrollCursor: case ui::kMoveCursor: - nativeCursor = os::kMoveCursor; + nativeCursor = os::NativeCursor::Move; break; - case ui::kSizeNSCursor: nativeCursor = os::kSizeNSCursor; break; - case ui::kSizeWECursor: nativeCursor = os::kSizeWECursor; break; - case ui::kSizeNCursor: nativeCursor = os::kSizeNCursor; break; - case ui::kSizeNECursor: nativeCursor = os::kSizeNECursor; break; - case ui::kSizeECursor: nativeCursor = os::kSizeECursor; break; - case ui::kSizeSECursor: nativeCursor = os::kSizeSECursor; break; - case ui::kSizeSCursor: nativeCursor = os::kSizeSCursor; break; - case ui::kSizeSWCursor: nativeCursor = os::kSizeSWCursor; break; - case ui::kSizeWCursor: nativeCursor = os::kSizeWCursor; break; - case ui::kSizeNWCursor: nativeCursor = os::kSizeNWCursor; break; + case ui::kSizeNSCursor: nativeCursor = os::NativeCursor::SizeNS; break; + case ui::kSizeWECursor: nativeCursor = os::NativeCursor::SizeWE; break; + case ui::kSizeNCursor: nativeCursor = os::NativeCursor::SizeN; break; + case ui::kSizeNECursor: nativeCursor = os::NativeCursor::SizeNE; break; + case ui::kSizeECursor: nativeCursor = os::NativeCursor::SizeE; break; + case ui::kSizeSECursor: nativeCursor = os::NativeCursor::SizeSE; break; + case ui::kSizeSCursor: nativeCursor = os::NativeCursor::SizeS; break; + case ui::kSizeSWCursor: nativeCursor = os::NativeCursor::SizeSW; break; + case ui::kSizeWCursor: nativeCursor = os::NativeCursor::SizeW; break; + case ui::kSizeNWCursor: nativeCursor = os::NativeCursor::SizeNW; break; } } @@ -154,11 +153,11 @@ static void update_mouse_cursor() // so we can should use the internal overlay (even when we // have use_native_mouse_cursor flag enabled). if (!ok) - nativeCursor = os::kNoCursor; + nativeCursor = os::NativeCursor::Hidden; } // Use a custom cursor - if (nativeCursor == os::kNoCursor && + if (nativeCursor == os::NativeCursor::Hidden && mouse_cursor_type != ui::kOutsideDisplay) { if (get_theme() && mouse_cursor_type != ui::kCustomCursor) cursor = get_theme()->getStandardCursor(mouse_cursor_type); @@ -167,7 +166,7 @@ static void update_mouse_cursor() } // Try to use a custom native cursor if it's possible - if (nativeCursor == os::kNoCursor && + if (nativeCursor == os::NativeCursor::Hidden && !update_custom_native_cursor(cursor)) { // Or an overlay as last resource update_mouse_overlay(cursor); @@ -216,7 +215,7 @@ UISystem::~UISystem() g_instance = nullptr; } -void _internal_set_mouse_display(os::Display* display) +void _internal_set_mouse_display(os::Window* display) { CursorType cursor = get_mouse_cursor(); set_mouse_cursor(kNoCursor); diff --git a/src/ui/system.h b/src/ui/system.h index c5d8c4fbb..4a6bca8d6 100644 --- a/src/ui/system.h +++ b/src/ui/system.h @@ -16,7 +16,9 @@ #include #include -namespace os { class Display; } +namespace os { + class Window; +} namespace ui { @@ -62,7 +64,7 @@ namespace ui { void hide_mouse_cursor(); void show_mouse_cursor(); - void _internal_set_mouse_display(os::Display* display); + void _internal_set_mouse_display(os::Window* display); void _internal_no_mouse_position(); void _internal_set_mouse_position(const gfx::Point& newPos); diff --git a/src/ui/theme.cpp b/src/ui/theme.cpp index cb59726f3..5e8104e9d 100644 --- a/src/ui/theme.cpp +++ b/src/ui/theme.cpp @@ -408,9 +408,9 @@ void Theme::paintLayer(Graphics* g, case Style::Layer::Type::kText: if (layer.color() != gfx::ColorNone) { - os::Font* oldFont = g->font(); + os::FontRef oldFont = AddRef(g->font()); if (style->font()) - g->setFont(style->font()); + g->setFont(AddRef(style->font())); if (layer.align() & WORDWRAP) { gfx::Rect textBounds = rc; @@ -546,7 +546,8 @@ void Theme::measureLayer(const Widget* widget, case Style::Layer::Type::kText: if (layer.color() != gfx::ColorNone) { - os::Font* font = (style->font() ? style->font(): widget->font()); + os::Font* font = (style->font() ? style->font(): + widget->font()); gfx::Size textSize(Graphics::measureUITextLength(widget->text(), font), font->height()); diff --git a/src/ui/timer.cpp b/src/ui/timer.cpp index 45740919a..d56559d30 100644 --- a/src/ui/timer.cpp +++ b/src/ui/timer.cpp @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This file is released under the terms of the MIT license. @@ -18,6 +18,7 @@ #include "ui/widget.h" #include +#include #include namespace ui { @@ -128,9 +129,28 @@ bool Timer::haveTimers() return !timers.empty(); } -bool Timer::haveRunningTimers() +bool Timer::getNextTimeout(double& timeout) { - return (running_timers != 0); + if (running_timers == 0) + return false; + + base::tick_t t = base::current_tick(); + bool result = false; + timeout = std::numeric_limits::max(); + for (auto timer : timers) { + if (timer && timer->isRunning()) { + int64_t diff = (timer->m_lastTick + timer->m_interval) - t; + if (diff < 0) { + timeout = 0.0; // Right-now + return true; + } + else { + timeout = std::min(timeout, diff / 1000.0); + result = true; + } + } + } + return result; } } // namespace ui diff --git a/src/ui/timer.h b/src/ui/timer.h index afc44e97c..a8af18e23 100644 --- a/src/ui/timer.h +++ b/src/ui/timer.h @@ -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. @@ -38,7 +38,7 @@ namespace ui { static void pollTimers(); static bool haveTimers(); - static bool haveRunningTimers(); + static bool getNextTimeout(double& timeout); protected: virtual void onTick(); diff --git a/src/ui/view.cpp b/src/ui/view.cpp index 1d53cffc3..8b5f8c290 100644 --- a/src/ui/view.cpp +++ b/src/ui/view.cpp @@ -1,5 +1,5 @@ // Aseprite UI Library -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This file is released under the terms of the MIT license. @@ -28,8 +28,8 @@ #ifdef DEBUG_SCROLL_EVENTS #include "base/thread.h" -#include "os/display.h" #include "os/surface.h" +#include "os/window.h" #endif #include diff --git a/src/ui/widget.cpp b/src/ui/widget.cpp index 0ac359ea2..61d88cee7 100644 --- a/src/ui/widget.cpp +++ b/src/ui/widget.cpp @@ -16,10 +16,10 @@ #include "base/clamp.h" #include "base/memory.h" #include "base/string.h" -#include "os/display.h" #include "os/font.h" #include "os/surface.h" #include "os/system.h" +#include "os/window.h" #include "ui/init_theme_event.h" #include "ui/intern.h" #include "ui/layout_io.h" @@ -28,9 +28,9 @@ #include "ui/message.h" #include "ui/move_region.h" #include "ui/paint_event.h" -#include "ui/size_hint_event.h" #include "ui/resize_event.h" #include "ui/save_layout_event.h" +#include "ui/size_hint_event.h" #include "ui/system.h" #include "ui/theme.h" #include "ui/view.h" @@ -164,8 +164,8 @@ void Widget::setTextQuiet(const std::string& text) os::Font* Widget::font() const { if (!m_font && m_theme) - m_font = m_theme->getWidgetFont(this); - return m_font; + m_font = AddRef(m_theme->getWidgetFont(this)); + return m_font.get(); } void Widget::setBgColor(gfx::Color color) @@ -202,7 +202,7 @@ void Widget::setStyle(Style* style) m_border = m_theme->calcBorder(this, style); m_bgColor = m_theme->calcBgColor(this, style); if (style->font()) - m_font = style->font(); + m_font = AddRef(style->font()); } // =============================================================== @@ -1059,10 +1059,10 @@ void Widget::paint(Graphics* graphics, region.createIntersection(region, drawRegion); Graphics graphics2( - graphics->getInternalSurface(), + base::AddRef(graphics->getInternalSurface()), widget->bounds().x, widget->bounds().y); - graphics2.setFont(widget->font()); + graphics2.setFont(AddRef(widget->font())); for (Region::const_iterator it = region.begin(), @@ -1151,48 +1151,49 @@ void Widget::invalidateRegion(const Region& region) class DeleteGraphicsAndSurface { public: - DeleteGraphicsAndSurface(const gfx::Rect& clip, os::Surface* surface) + DeleteGraphicsAndSurface(const gfx::Rect& clip, + const os::SurfaceRef& surface) : m_pt(clip.origin()), m_surface(surface) { } void operator()(Graphics* graphics) { { - os::Surface* dst = os::instance()->defaultDisplay()->getSurface(); - os::SurfaceLock lockSrc(m_surface); + os::Surface* dst = os::instance()->defaultWindow()->surface(); + os::SurfaceLock lockSrc(m_surface.get()); os::SurfaceLock lockDst(dst); m_surface->blitTo( dst, 0, 0, m_pt.x, m_pt.y, m_surface->width(), m_surface->height()); } - m_surface->dispose(); + m_surface.reset(); delete graphics; } private: gfx::Point m_pt; - os::Surface* m_surface; + os::SurfaceRef m_surface; }; GraphicsPtr Widget::getGraphics(const gfx::Rect& clip) { GraphicsPtr graphics; - os::Surface* surface; - os::Surface* defaultSurface = os::instance()->defaultDisplay()->getSurface(); + os::SurfaceRef surface; + os::Surface* defaultSurface = os::instance()->defaultWindow()->surface(); // In case of double-buffering, we need to create the temporary // buffer only if the default surface is the screen. if (isDoubleBuffered() && defaultSurface->isDirectToScreen()) { - surface = os::instance()->createSurface(clip.w, clip.h); + surface = os::instance()->makeSurface(clip.w, clip.h); graphics.reset(new Graphics(surface, -clip.x, -clip.y), - DeleteGraphicsAndSurface(clip, surface)); + DeleteGraphicsAndSurface(clip, surface)); } // In other case, we can draw directly onto the screen. else { - surface = defaultSurface; + surface = AddRef(defaultSurface); graphics.reset(new Graphics(surface, bounds().x, bounds().y)); } - graphics->setFont(font()); + graphics->setFont(AddRef(font())); return graphics; } diff --git a/src/ui/widget.h b/src/ui/widget.h index 3b04a3c69..eadd36d42 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -16,6 +16,7 @@ #include "gfx/region.h" #include "gfx/size.h" #include "obs/signal.h" +#include "os/font.h" #include "ui/base.h" #include "ui/component.h" #include "ui/graphics.h" @@ -26,10 +27,6 @@ #define ASSERT_VALID_WIDGET(widget) ASSERT((widget) != nullptr) -namespace os { - class Font; -} - namespace ui { class InitThemeEvent; @@ -407,7 +404,7 @@ namespace ui { Theme* m_theme; // Widget's theme Style* m_style; std::string m_text; // Widget text - mutable os::Font* m_font; // Cached font returned by the theme + mutable os::FontRef m_font; // Cached font returned by the theme gfx::Color m_bgColor; // Background color gfx::Rect m_bounds; gfx::Region m_updateRegion; // Region to be redrawed.