mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
Add ui::Display to support multiple windows in the future
This ui::Display is related to one native os::Window, so the dirty region/invalid region is now part of a ui::Display instead of a ui::Manager. * Replaced ui::display_w/h() functions with ui::Display::size() and ui::get_desktop_size() * The ui::Manager contains the main ui::Display, and in the future an ui::Window will have its own ui::Display
This commit is contained in:
parent
715600679d
commit
c3d52f0bbe
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit 0ae7eb7c7fd40c5a3829cfddaede60f458877920
|
||||
Subproject commit 410da165bde1e7353eb46aa58481a956f2ad489b
|
@ -359,7 +359,7 @@ void App::run()
|
||||
if (isGui()) {
|
||||
#ifdef _WIN32
|
||||
// How to interpret one finger on Windows tablets.
|
||||
ui::Manager::getDefault()->nativeWindow()
|
||||
ui::Manager::getDefault()->display()->nativeWindow()
|
||||
->setInterpretOneFingerGestureAsMouseMovement(
|
||||
preferences().experimental.oneFingerAsMouseMovement());
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ void FullscreenModeCommand::onExecute(Context* ctx)
|
||||
if (!manager)
|
||||
return;
|
||||
|
||||
os::Window* window = manager->nativeWindow();
|
||||
os::Window* window = manager->display()->nativeWindow();
|
||||
ASSERT(window);
|
||||
if (!window)
|
||||
return;
|
||||
|
@ -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
|
||||
@ -51,8 +51,13 @@ public:
|
||||
, m_pal(m_sprite->palette(editor->frame()))
|
||||
, 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()->makeRgbaSurface(ui::display_w(), ui::display_h())) {
|
||||
, m_doublebuf(Image::create(
|
||||
IMAGE_RGB,
|
||||
editor->display()->size().w,
|
||||
editor->display()->size().h))
|
||||
, m_doublesur(os::instance()->makeRgbaSurface(
|
||||
editor->display()->size().w,
|
||||
editor->display()->size().h)) {
|
||||
// Do not use DocWriter (do not lock the document) because we
|
||||
// will call other sub-commands (e.g. previous frame, next frame,
|
||||
// etc.).
|
||||
@ -170,6 +175,7 @@ protected:
|
||||
}
|
||||
|
||||
virtual void onPaint(PaintEvent& ev) override {
|
||||
gfx::Size displaySize = display()->size();
|
||||
Graphics* g = ev.graphics();
|
||||
EditorRender& render = m_editor->renderEngine();
|
||||
render.setRefLayersVisiblity(false);
|
||||
@ -213,18 +219,18 @@ protected:
|
||||
255, BlendMode::NORMAL);
|
||||
break;
|
||||
case TiledMode::X_AXIS:
|
||||
for (u=x-w; u<ui::display_w()+w; u+=w)
|
||||
for (u=x-w; u<displaySize.w+w; u+=w)
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, u, y,
|
||||
255, BlendMode::NORMAL);
|
||||
break;
|
||||
case TiledMode::Y_AXIS:
|
||||
for (v=y-h; v<ui::display_h()+h; v+=h)
|
||||
for (v=y-h; v<displaySize.h+h; v+=h)
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, x, v,
|
||||
255, BlendMode::NORMAL);
|
||||
break;
|
||||
case TiledMode::BOTH:
|
||||
for (v=y-h; v<ui::display_h()+h; v+=h)
|
||||
for (u=x-w; u<ui::display_w()+w; u+=w)
|
||||
for (v=y-h; v<displaySize.h+h; v+=h)
|
||||
for (u=x-w; u<displaySize.w+w; u+=w)
|
||||
render.renderImage(m_doublebuf.get(), m_render.get(), m_pal, u, v,
|
||||
255, BlendMode::NORMAL);
|
||||
break;
|
||||
|
@ -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
|
||||
@ -88,8 +88,9 @@ public:
|
||||
m_keyLabel.setStyle(theme->styles.listHeaderLabel());
|
||||
m_contextLabel.setStyle(theme->styles.listHeaderLabel());
|
||||
|
||||
m_splitter1.setPosition(ui::display_w()*3/4 * 4/10);
|
||||
m_splitter2.setPosition(ui::display_w()*3/4 * 2/10);
|
||||
gfx::Size displaySize = display()->size();
|
||||
m_splitter1.setPosition(displaySize.w*3/4 * 4/10);
|
||||
m_splitter2.setPosition(displaySize.w*3/4 * 2/10);
|
||||
|
||||
addChild(&m_splitter1);
|
||||
m_splitter1.addChild(&m_actionLabel);
|
||||
@ -881,7 +882,8 @@ void KeyboardShortcutsCommand::onExecute(Context* context)
|
||||
std::string neededSearchCopy = m_search;
|
||||
KeyboardShortcutsWindow window(keys, menuKeys, neededSearchCopy);
|
||||
|
||||
window.setBounds(gfx::Rect(0, 0, ui::display_w()*3/4, ui::display_h()*3/4));
|
||||
gfx::Size displaySize = ui::get_desktop_size();
|
||||
window.setBounds(gfx::Rect(0, 0, displaySize.w*3/4, displaySize.h*3/4));
|
||||
window.loadLayout();
|
||||
|
||||
window.centerWindow();
|
||||
|
@ -725,7 +725,7 @@ public:
|
||||
m_pref.tablet.api(tabletStr);
|
||||
m_pref.experimental.loadWintabDriver(wintabState);
|
||||
|
||||
manager()->nativeWindow()
|
||||
manager()->display()->nativeWindow()
|
||||
->setInterpretOneFingerGestureAsMouseMovement(
|
||||
oneFingerAsMouseMovement()->isSelected());
|
||||
|
||||
@ -845,10 +845,8 @@ private:
|
||||
|
||||
void updateScreenScaling() {
|
||||
ui::Manager* manager = ui::Manager::getDefault();
|
||||
os::Window* window = manager->nativeWindow();
|
||||
os::instance()->setGpuAcceleration(m_pref.general.gpuAcceleration());
|
||||
window->setScale(m_pref.general.screenScale());
|
||||
manager->setNativeWindow(window);
|
||||
manager->updateAllDisplaysWithNewScale(m_pref.general.screenScale());
|
||||
}
|
||||
|
||||
void onApply() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -29,7 +29,7 @@
|
||||
#include "render/dithering.h"
|
||||
#include "render/ordered_dither.h"
|
||||
#include "render/quantization.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/manager.h"
|
||||
|
||||
#include "paste_text.xml.h"
|
||||
|
||||
@ -124,10 +124,11 @@ private:
|
||||
}
|
||||
|
||||
if (!m_fontPopup->isVisible()) {
|
||||
gfx::Size displaySize = manager()->display()->size();
|
||||
gfx::Rect bounds = fontFace()->bounds();
|
||||
m_fontPopup->showPopup(
|
||||
gfx::Rect(bounds.x, bounds.y+bounds.h,
|
||||
ui::display_w()/2, ui::display_h()/2));
|
||||
displaySize.w/2, displaySize.h/2));
|
||||
}
|
||||
else {
|
||||
m_fontPopup->closeWindow(NULL);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -94,7 +94,7 @@ void UndoCommand::onExecute(Context* context)
|
||||
current_editor->drawSpriteClipped(
|
||||
gfx::Region(gfx::Rect(0, 0, sprite->width(), sprite->height())));
|
||||
|
||||
current_editor->manager()->flipDisplay();
|
||||
current_editor->display()->flipDisplay();
|
||||
base::this_thread::sleep_for(0.01);
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ void ScreenshotCommand::onExecute(Context* ctx)
|
||||
app::ResourceFinder rf(false);
|
||||
rf.includeDesktopDir("");
|
||||
|
||||
os::Window* window = ui::Manager::getDefault()->nativeWindow();
|
||||
os::Window* window = ui::Manager::getDefault()->display()->nativeWindow();
|
||||
os::Surface* surface = window->surface();
|
||||
std::string fn;
|
||||
|
||||
|
@ -70,8 +70,13 @@ public:
|
||||
|
||||
void centerConsole() {
|
||||
initTheme();
|
||||
|
||||
remapWindow();
|
||||
setBounds(gfx::Rect(0, 0, ui::display_w()*9/10, ui::display_h()*6/10));
|
||||
|
||||
// TODO center to main window or screen workspace
|
||||
gfx::Size displaySize = manager()->display()->size();
|
||||
setBounds(gfx::Rect(0, 0, displaySize.w*9/10, displaySize.h*6/10));
|
||||
|
||||
centerWindow();
|
||||
invalidate();
|
||||
}
|
||||
@ -116,14 +121,16 @@ Console::Console(Context* ctx)
|
||||
if (!ui::is_ui_thread())
|
||||
return;
|
||||
|
||||
if (ctx)
|
||||
if (ctx) {
|
||||
m_withUI = (ctx->isUIAvailable());
|
||||
else
|
||||
}
|
||||
else {
|
||||
m_withUI =
|
||||
(App::instance() &&
|
||||
App::instance()->isGui() &&
|
||||
Manager::getDefault() &&
|
||||
Manager::getDefault()->nativeWindow());
|
||||
Manager::getDefault()->display()->nativeWindow());
|
||||
}
|
||||
|
||||
if (!m_withUI)
|
||||
return;
|
||||
|
@ -81,8 +81,13 @@ static struct {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CustomizedGuiManager : public Manager
|
||||
, public LayoutIO {
|
||||
class CustomizedGuiManager : public ui::Manager
|
||||
, public ui::LayoutIO {
|
||||
public:
|
||||
CustomizedGuiManager(const os::WindowRef& nativeWindow)
|
||||
: ui::Manager(nativeWindow) {
|
||||
}
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(Message* msg) override;
|
||||
#if ENABLE_DEVMODE
|
||||
@ -90,7 +95,7 @@ protected:
|
||||
#endif
|
||||
void onInitTheme(InitThemeEvent& ev) override;
|
||||
LayoutIO* onGetLayoutIO() override { return this; }
|
||||
void onNewDisplayConfiguration() override;
|
||||
void onNewDisplayConfiguration(Display* display) override;
|
||||
|
||||
// LayoutIO implementation
|
||||
std::string loadLayout(Widget* widget) override;
|
||||
@ -193,8 +198,7 @@ int init_module_gui()
|
||||
}
|
||||
|
||||
// Create the default-manager
|
||||
manager = new CustomizedGuiManager();
|
||||
manager->setNativeWindow(main_window.get());
|
||||
manager = new CustomizedGuiManager(main_window);
|
||||
|
||||
// Setup the GUI theme for all widgets
|
||||
gui_theme = new SkinTheme;
|
||||
@ -205,17 +209,20 @@ int init_module_gui()
|
||||
|
||||
// Handle live resize too redraw the entire manager, dispatch the UI
|
||||
// messages, and flip the window.
|
||||
main_window->handleResize =
|
||||
os::instance()->handleWindowResize =
|
||||
[](os::Window* window) {
|
||||
manager->invalidate();
|
||||
Display* display = manager->getDisplayFromNativeWindow(window);
|
||||
if (!display)
|
||||
display = manager->display();
|
||||
ASSERT(display);
|
||||
|
||||
Message* msg = new Message(kResizeDisplayMessage);
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(manager);
|
||||
msg->setPropagateToChildren(true);
|
||||
manager->enqueueMessage(msg);
|
||||
|
||||
manager->enqueueMessage(msg);
|
||||
manager->dispatchMessages();
|
||||
manager->flipDisplay();
|
||||
};
|
||||
|
||||
// Set graphics options for next time
|
||||
@ -292,7 +299,7 @@ static void load_gui_config(int& w, int& h, bool& maximized,
|
||||
|
||||
static void save_gui_config()
|
||||
{
|
||||
os::Window* window = manager->nativeWindow();
|
||||
os::Window* window = manager->display()->nativeWindow();
|
||||
if (window) {
|
||||
set_config_bool("GfxMode", "Maximized", window->isMaximized());
|
||||
set_config_int("GfxMode", "Width", window->originalWidth());
|
||||
@ -327,6 +334,8 @@ void update_screen_for_document(const Doc* document)
|
||||
void load_window_pos(Widget* window, const char* section,
|
||||
const bool limitMinSize)
|
||||
{
|
||||
Size desktopSize = ui::get_desktop_size();
|
||||
|
||||
// Default position
|
||||
Rect orig_pos = window->bounds();
|
||||
Rect pos = orig_pos;
|
||||
@ -335,16 +344,16 @@ void load_window_pos(Widget* window, const char* section,
|
||||
pos = get_config_rect(section, "WindowPos", pos);
|
||||
|
||||
if (limitMinSize) {
|
||||
pos.w = base::clamp(pos.w, orig_pos.w, ui::display_w());
|
||||
pos.h = base::clamp(pos.h, orig_pos.h, ui::display_h());
|
||||
pos.w = base::clamp(pos.w, orig_pos.w, desktopSize.w);
|
||||
pos.h = base::clamp(pos.h, orig_pos.h, desktopSize.h);
|
||||
}
|
||||
else {
|
||||
pos.w = std::min(pos.w, ui::display_w());
|
||||
pos.h = std::min(pos.h, ui::display_h());
|
||||
pos.w = std::min(pos.w, desktopSize.w);
|
||||
pos.h = std::min(pos.h, desktopSize.h);
|
||||
}
|
||||
|
||||
pos.setOrigin(Point(base::clamp(pos.x, 0, ui::display_w()-pos.w),
|
||||
base::clamp(pos.y, 0, ui::display_h()-pos.h)));
|
||||
pos.setOrigin(Point(base::clamp(pos.x, 0, desktopSize.w-pos.w),
|
||||
base::clamp(pos.y, 0, desktopSize.h-pos.h)));
|
||||
|
||||
window->setBounds(pos);
|
||||
}
|
||||
@ -653,9 +662,9 @@ void CustomizedGuiManager::onInitTheme(InitThemeEvent& ev)
|
||||
AppMenus::instance()->initTheme();
|
||||
}
|
||||
|
||||
void CustomizedGuiManager::onNewDisplayConfiguration()
|
||||
void CustomizedGuiManager::onNewDisplayConfiguration(Display* display)
|
||||
{
|
||||
Manager::onNewDisplayConfiguration();
|
||||
Manager::onNewDisplayConfiguration(display);
|
||||
save_gui_config();
|
||||
|
||||
// TODO Should we provide a more generic way for all ui::Window to
|
||||
|
@ -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
|
||||
@ -1884,12 +1884,13 @@ void ColorBar::showPalettePresets()
|
||||
}
|
||||
|
||||
if (!m_palettePopup->isVisible()) {
|
||||
gfx::Size displaySize = ui::get_desktop_size();
|
||||
gfx::Rect bounds = m_buttons.getItem(
|
||||
static_cast<int>(PalButton::PRESETS))->bounds();
|
||||
|
||||
m_palettePopup->showPopup(
|
||||
gfx::Rect(bounds.x, bounds.y+bounds.h,
|
||||
ui::display_w()/2, ui::display_h()*3/4));
|
||||
displaySize.w/2, displaySize.h*3/4));
|
||||
}
|
||||
else {
|
||||
m_palettePopup->closeWindow(NULL);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -302,12 +302,13 @@ void ColorButton::openPopup(const bool forcePinned)
|
||||
m_window->setColor(m_color, ColorPopup::ChangeType);
|
||||
m_window->openWindow();
|
||||
|
||||
gfx::Size displaySize = ui::get_desktop_size();
|
||||
gfx::Rect winBounds;
|
||||
if (!pinned || (forcePinned && m_hiddenPopupBounds.isEmpty())) {
|
||||
winBounds = gfx::Rect(m_window->bounds().origin(),
|
||||
m_window->sizeHint());
|
||||
winBounds.x = base::clamp(bounds().x, 0, ui::display_w()-winBounds.w);
|
||||
if (bounds().y2() <= ui::display_h()-winBounds.h)
|
||||
winBounds.x = base::clamp(bounds().x, 0, displaySize.w-winBounds.w);
|
||||
if (bounds().y2() <= displaySize.h-winBounds.h)
|
||||
winBounds.y = std::max(0, bounds().y2());
|
||||
else
|
||||
winBounds.y = std::max(0, bounds().y-winBounds.h);
|
||||
@ -318,8 +319,8 @@ void ColorButton::openPopup(const bool forcePinned)
|
||||
else {
|
||||
winBounds = m_windowDefaultBounds;
|
||||
}
|
||||
winBounds.x = base::clamp(winBounds.x, 0, ui::display_w()-winBounds.w);
|
||||
winBounds.y = base::clamp(winBounds.y, 0, ui::display_h()-winBounds.h);
|
||||
winBounds.x = base::clamp(winBounds.x, 0, displaySize.w-winBounds.w);
|
||||
winBounds.y = base::clamp(winBounds.y, 0, displaySize.h-winBounds.h);
|
||||
m_window->setBounds(winBounds);
|
||||
|
||||
m_window->manager()->dispatchMessages();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2020 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.
|
||||
@ -147,14 +147,16 @@ private:
|
||||
paint.style(os::Paint::Fill);
|
||||
surface->drawRect(gfx::Rect(0, 0, surface->width(), surface->height()), paint);
|
||||
}
|
||||
|
||||
ui::Display* display = this->Base::display();
|
||||
{
|
||||
ui::Graphics g(surface, 0, 0);
|
||||
ui::Graphics g(display, surface, 0, 0);
|
||||
g.setFont(AddRef(this->font()));
|
||||
drawFloatingOverlay(g);
|
||||
}
|
||||
|
||||
m_floatingOverlay = base::make_ref<ui::Overlay>(
|
||||
surface, gfx::Point(),
|
||||
display, surface, gfx::Point(),
|
||||
(ui::Overlay::ZOrder)(ui::Overlay::MouseZOrder-1));
|
||||
ui::OverlayManager::instance()->addOverlay(m_floatingOverlay);
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ void BrushPreview::show(const gfx::Point& screenPos)
|
||||
// Save area and draw the cursor
|
||||
if (!(m_type & NATIVE_CROSSHAIR) ||
|
||||
(m_type & BRUSH_BOUNDARIES)) {
|
||||
ui::ScreenGraphics g;
|
||||
ui::ScreenGraphics g(m_editor->display());
|
||||
ui::SetClip clip(&g);
|
||||
gfx::Color uiCursorColor = color_utils::color_for_ui(appCursorColor);
|
||||
forEachBrushPixel(&g, m_screenPosition, spritePos, uiCursorColor, &BrushPreview::savePixelDelegate);
|
||||
@ -387,7 +387,7 @@ void BrushPreview::hide()
|
||||
|
||||
if (m_withModifiedPixels) {
|
||||
// Restore pixels
|
||||
ui::ScreenGraphics g;
|
||||
ui::ScreenGraphics g(m_editor->display());
|
||||
ui::SetClip clip(&g);
|
||||
forEachBrushPixel(&g, m_screenPosition, m_editorPosition, gfx::ColorNone,
|
||||
&BrushPreview::clearPixelDelegate);
|
||||
|
@ -947,7 +947,7 @@ void Editor::drawSpriteClipped(const gfx::Region& updateRegion)
|
||||
Region screenRegion;
|
||||
getDrawableRegion(screenRegion, kCutTopWindows);
|
||||
|
||||
ScreenGraphics screenGraphics;
|
||||
ScreenGraphics screenGraphics(display());
|
||||
GraphicsPtr editorGraphics = getGraphics(clientBounds());
|
||||
|
||||
for (const Rect& updateRect : updateRegion) {
|
||||
@ -1163,7 +1163,6 @@ void Editor::drawTileNumbers(ui::Graphics* g, const Cel* cel)
|
||||
int ti_offset =
|
||||
static_cast<LayerTilemap*>(cel->layer())->tileset()->baseIndex() - 1;
|
||||
|
||||
const gfx::Rect rc = cel->bounds();
|
||||
const doc::Image* image = cel->image();
|
||||
std::string text;
|
||||
for (int y=0; y<image->height(); ++y) {
|
||||
|
@ -1029,7 +1029,7 @@ void StandbyState::Decorator::postRenderDecorator(EditorPostRender* render)
|
||||
if (StandbyState::Decorator::getSymmetryHandles(editor, handles)) {
|
||||
skin::SkinTheme* theme = static_cast<skin::SkinTheme*>(ui::get_theme());
|
||||
os::Surface* part = theme->parts.transformationHandle()->bitmap(0);
|
||||
ScreenGraphics g;
|
||||
ScreenGraphics g(editor->display());
|
||||
for (const auto& handle : handles)
|
||||
g.drawRgbaSurface(part, handle.bounds.x, handle.bounds.y);
|
||||
}
|
||||
|
@ -67,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()->nativeWindow()->scale();
|
||||
int threshold = 8 * guiscale() * editor->display()->nativeWindow()->scale();
|
||||
|
||||
if (m_moved || std::sqrt(pt.x*pt.x + pt.y*pt.y) > threshold) {
|
||||
m_moved = true;
|
||||
|
@ -421,7 +421,8 @@ bool FileSelector::show(
|
||||
|
||||
FILESEL_TRACE("FILESEL: Start folder '%s' (%p)\n", start_folder_path.c_str(), start_folder);
|
||||
|
||||
setMinSize(gfx::Size(ui::display_w()*9/10, ui::display_h()*9/10));
|
||||
gfx::Size displaySize = ui::get_desktop_size();
|
||||
setMinSize(gfx::Size(displaySize.w*9/10, displaySize.h*9/10));
|
||||
remapWindow();
|
||||
centerWindow();
|
||||
|
||||
|
@ -77,10 +77,8 @@ public:
|
||||
|
||||
ui::set_theme(ui::get_theme(), newUIScale);
|
||||
|
||||
Manager* manager = Manager::getDefault();
|
||||
os::Window* window = manager->nativeWindow();
|
||||
window->setScale(newScreenScale);
|
||||
manager->setNativeWindow(window);
|
||||
Manager::getDefault()
|
||||
->updateAllDisplaysWithNewScale(newScreenScale);
|
||||
}
|
||||
};
|
||||
|
||||
@ -370,12 +368,13 @@ void MainWindow::onResize(ui::ResizeEvent& ev)
|
||||
{
|
||||
app::gen::MainWindow::onResize(ev);
|
||||
|
||||
os::Window* window = manager()->nativeWindow();
|
||||
if ((window) &&
|
||||
(window->scale()*ui::guiscale() > 2) &&
|
||||
gfx::Size desktopSize = ui::get_desktop_size();
|
||||
ui::Display* display = this->display();
|
||||
if ((display) &&
|
||||
(display->nativeWindow()->scale()*ui::guiscale() > 2) &&
|
||||
(!m_scalePanic) &&
|
||||
(ui::display_w()/ui::guiscale() < 320 ||
|
||||
ui::display_h()/ui::guiscale() < 260)) {
|
||||
(desktopSize.w/ui::guiscale() < 320 ||
|
||||
desktopSize.h/ui::guiscale() < 260)) {
|
||||
showNotification(m_scalePanic = new ScreenScalePanic);
|
||||
}
|
||||
}
|
||||
|
@ -224,13 +224,14 @@ bool PreviewEditorWindow::onProcessMessage(ui::Message* msg)
|
||||
SkinTheme* theme = SkinTheme::instance();
|
||||
|
||||
// Default bounds
|
||||
int width = ui::display_w()/4;
|
||||
int height = ui::display_h()/4;
|
||||
gfx::Size desktopSize = ui::get_desktop_size();
|
||||
const int width = desktopSize.w/4;
|
||||
const int height = desktopSize.h/4;
|
||||
int extra = 2*theme->dimensions.miniScrollbarSize();
|
||||
setBounds(
|
||||
gfx::Rect(
|
||||
ui::display_w() - width - ToolBar::instance()->bounds().w - extra,
|
||||
ui::display_h() - height - StatusBar::instance()->bounds().h - extra,
|
||||
desktopSize.w - width - ToolBar::instance()->bounds().w - extra,
|
||||
desktopSize.h - height - StatusBar::instance()->bounds().h - extra,
|
||||
width, height));
|
||||
|
||||
load_window_pos(this, "MiniEditor", false);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -941,6 +941,7 @@ void Tabs::createFloatingOverlay(Tab* tab)
|
||||
{
|
||||
ASSERT(!m_floatingOverlay);
|
||||
|
||||
ui::Display* display = this->display();
|
||||
os::SurfaceRef surface = os::instance()->makeRgbaSurface(
|
||||
tab->width, m_tabsHeight);
|
||||
|
||||
@ -953,13 +954,13 @@ void Tabs::createFloatingOverlay(Tab* tab)
|
||||
surface->drawRect(gfx::Rect(0, 0, surface->width(), surface->height()), paint);
|
||||
}
|
||||
{
|
||||
Graphics g(surface, 0, 0);
|
||||
Graphics g(display, surface, 0, 0);
|
||||
g.setFont(AddRef(font()));
|
||||
drawTab(&g, g.getClipBounds(), tab, 0, true, true);
|
||||
}
|
||||
|
||||
m_floatingOverlay = base::make_ref<ui::Overlay>(
|
||||
surface, gfx::Point(),
|
||||
display, surface, gfx::Point(),
|
||||
(ui::Overlay::ZOrder)(Overlay::MouseZOrder-1));
|
||||
OverlayManager::instance()->addOverlay(m_floatingOverlay);
|
||||
}
|
||||
|
@ -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
|
||||
@ -1242,7 +1242,7 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
|
||||
if (!m_confPopup->isVisible()) {
|
||||
gfx::Rect bounds = m_confPopup->bounds();
|
||||
ui::fit_bounds(BOTTOM, gearBounds, bounds);
|
||||
ui::fit_bounds(display(), BOTTOM, gearBounds, bounds);
|
||||
|
||||
m_confPopup->moveWindow(bounds);
|
||||
m_confPopup->openWindow();
|
||||
|
@ -530,7 +530,8 @@ void ToolBar::openTipWindow(int group_index, Tool* tool)
|
||||
if (tool && m_popupWindow && m_popupWindow->isVisible())
|
||||
toolrc.x += arrow.x - m_popupWindow->bounds().w;
|
||||
|
||||
m_tipWindow->pointAt(TOP | RIGHT, toolrc);
|
||||
m_tipWindow->pointAt(TOP | RIGHT, toolrc,
|
||||
ui::Manager::getDefault()->display());
|
||||
|
||||
if (m_tipOpened)
|
||||
m_tipWindow->openWindow();
|
||||
|
@ -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<os::System> system(os::create_system());
|
||||
ui::UISystem uiSystem;
|
||||
ui::Manager uiManager;
|
||||
ui::Manager uiManager(nullptr);
|
||||
#endif
|
||||
|
||||
exitcode = RUN_ALL_TESTS();
|
||||
|
@ -1,4 +1,5 @@
|
||||
# Aseprite UI Library
|
||||
# Copyright (C) 2019 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2018 David Capello
|
||||
|
||||
if(WIN32)
|
||||
@ -13,6 +14,7 @@ add_library(ui-lib
|
||||
combobox.cpp
|
||||
component.cpp
|
||||
cursor.cpp
|
||||
display.cpp
|
||||
entry.cpp
|
||||
event.cpp
|
||||
fit_bounds.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.
|
||||
@ -614,8 +614,12 @@ void ComboBox::openListBox()
|
||||
m_window = new Window(Window::WithoutTitleBar);
|
||||
View* view = new View();
|
||||
m_listbox = new ComboBoxListBox(this);
|
||||
// TODO create a real native window for comboboxes
|
||||
m_window->setDisplay(display());
|
||||
m_window->setOnTop(true);
|
||||
m_window->setWantFocus(false);
|
||||
m_window->setSizeable(false);
|
||||
m_window->setMoveable(false);
|
||||
|
||||
Widget* viewport = view->viewport();
|
||||
{
|
||||
@ -627,8 +631,10 @@ void ComboBox::openListBox()
|
||||
if (!item->hasFlags(HIDDEN))
|
||||
size.h += item->sizeHint().h;
|
||||
|
||||
int max = std::max(entryBounds.y, ui::display_h() - entryBounds.y2()) - 8*guiscale();
|
||||
size.h = base::clamp(size.h, textHeight(), max);
|
||||
const int maxVal =
|
||||
std::max(entryBounds.y, display()->size().h - entryBounds.y2())
|
||||
- 8*guiscale();
|
||||
size.h = base::clamp(size.h, textHeight(), maxVal);
|
||||
viewport->setMinSize(size);
|
||||
}
|
||||
|
||||
@ -688,7 +694,7 @@ gfx::Rect ComboBox::getListBoxPos() const
|
||||
gfx::Point(m_button->bounds().x2(),
|
||||
entryBounds.y2() + m_window->bounds().h));
|
||||
|
||||
if (rc.y2() > ui::display_h())
|
||||
if (rc.y2() > display()->size().h)
|
||||
rc.offset(0, -(rc.h + entryBounds.h));
|
||||
|
||||
return rc;
|
||||
|
114
src/ui/display.cpp
Normal file
114
src/ui/display.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ui/display.h"
|
||||
|
||||
#include "base/debug.h"
|
||||
#include "ui/widget.h"
|
||||
#include "ui/window.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ui {
|
||||
|
||||
Display::Display(const os::WindowRef& nativeWindow,
|
||||
Widget* containedWidget)
|
||||
: m_nativeWindow(nativeWindow)
|
||||
, m_containedWidget(containedWidget)
|
||||
{
|
||||
ASSERT(m_nativeWindow);
|
||||
ASSERT(m_containedWidget);
|
||||
ASSERT(m_containedWidget->type() == kManagerWidget ||
|
||||
m_containedWidget->type() == kWindowWidget);
|
||||
m_dirtyRegion = bounds();
|
||||
}
|
||||
|
||||
os::Surface* Display::surface() const
|
||||
{
|
||||
return m_nativeWindow->surface();
|
||||
}
|
||||
|
||||
gfx::Size Display::size() const
|
||||
{
|
||||
ASSERT(m_nativeWindow);
|
||||
const int scale = m_nativeWindow->scale();
|
||||
ASSERT(scale > 0);
|
||||
return gfx::Size(m_nativeWindow->width() / scale,
|
||||
m_nativeWindow->height() / scale);
|
||||
}
|
||||
|
||||
void Display::dirtyRect(const gfx::Rect& bounds)
|
||||
{
|
||||
m_dirtyRegion.createUnion(m_dirtyRegion, gfx::Region(bounds));
|
||||
}
|
||||
|
||||
void Display::flipDisplay()
|
||||
{
|
||||
if (!m_dirtyRegion.isEmpty()) {
|
||||
// Limit the region to the bounds of the window
|
||||
m_dirtyRegion &= gfx::Region(bounds());
|
||||
|
||||
if (!m_dirtyRegion.isEmpty()) {
|
||||
// Invalidate the dirty region in the os::Window
|
||||
m_nativeWindow->invalidateRegion(m_dirtyRegion);
|
||||
m_dirtyRegion.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display::invalidateRect(const gfx::Rect& rect)
|
||||
{
|
||||
m_containedWidget->invalidateRect(rect);
|
||||
}
|
||||
|
||||
void Display::invalidateRegion(const gfx::Region& region)
|
||||
{
|
||||
m_containedWidget->invalidateRegion(region);
|
||||
}
|
||||
|
||||
void Display::addWindow(Window* window)
|
||||
{
|
||||
m_windows.insert(m_windows.begin(), window);
|
||||
}
|
||||
|
||||
void Display::removeWindow(Window* window)
|
||||
{
|
||||
auto it = std::find(m_windows.begin(), m_windows.end(), window);
|
||||
ASSERT(it != m_windows.end())
|
||||
if (it == m_windows.end())
|
||||
return;
|
||||
|
||||
m_windows.erase(it);
|
||||
}
|
||||
|
||||
// TODO code similar to Manager::handleWindowZOrder()
|
||||
void Display::handleWindowZOrder(Window* window)
|
||||
{
|
||||
removeWindow(window);
|
||||
|
||||
if (window->isOnTop())
|
||||
m_windows.insert(m_windows.begin(), window);
|
||||
else {
|
||||
int pos = (int)m_windows.size();
|
||||
|
||||
for (auto it=m_windows.rbegin(),
|
||||
end=m_windows.rend();
|
||||
it != end; ++it) {
|
||||
if (static_cast<Window*>(*it)->isOnTop())
|
||||
break;
|
||||
|
||||
--pos;
|
||||
}
|
||||
|
||||
m_windows.insert(m_windows.begin()+pos, window);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ui
|
83
src/ui/display.h
Normal file
83
src/ui/display.h
Normal file
@ -0,0 +1,83 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef UI_DISPLAY_H_INCLUDED
|
||||
#define UI_DISPLAY_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "gfx/region.h"
|
||||
#include "gfx/size.h"
|
||||
#include "os/window.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ui {
|
||||
class Widget;
|
||||
class Window;
|
||||
|
||||
// Wraps a native window (os::Window). On each "display" we can show
|
||||
// the main manager or a window (containedWidget), and a set of
|
||||
// children window that doesn't have a native window counterpart
|
||||
// (tooltips?)
|
||||
class Display {
|
||||
public:
|
||||
Display(const os::WindowRef& nativeWindow,
|
||||
Widget* containedWidget);
|
||||
|
||||
os::Window* nativeWindow() { return m_nativeWindow.get(); }
|
||||
os::Surface* surface() const;
|
||||
|
||||
gfx::Size size() const;
|
||||
gfx::Rect bounds() const { return gfx::Rect(size()); }
|
||||
|
||||
Widget* containedWidget() const { return m_containedWidget; }
|
||||
|
||||
// Mark the given rectangle as a area to be flipped to the real
|
||||
// screen.
|
||||
void dirtyRect(const gfx::Rect& bounds);
|
||||
|
||||
// Refreshes the real display with the UI content.
|
||||
void flipDisplay();
|
||||
|
||||
// Returns the invalid region in the screen to being updated with
|
||||
// PaintMessages. This region is cleared when each widget receives
|
||||
// a paint message.
|
||||
const gfx::Region& getInvalidRegion() const {
|
||||
return m_invalidRegion;
|
||||
}
|
||||
|
||||
void addInvalidRegion(const gfx::Region& b) {
|
||||
m_invalidRegion |= b;
|
||||
}
|
||||
|
||||
void subtractInvalidRegion(const gfx::Region& b) {
|
||||
m_invalidRegion -= b;
|
||||
}
|
||||
|
||||
void setInvalidRegion(const gfx::Region& b) {
|
||||
m_invalidRegion = b;
|
||||
}
|
||||
|
||||
void invalidateRect(const gfx::Rect& rect);
|
||||
void invalidateRegion(const gfx::Region& region);
|
||||
|
||||
void addWindow(Window* window);
|
||||
void removeWindow(Window* window);
|
||||
void handleWindowZOrder(Window* window);
|
||||
const std::vector<Window*>& getWindows() const { return m_windows; }
|
||||
|
||||
private:
|
||||
os::WindowRef m_nativeWindow;
|
||||
Widget* m_containedWidget; // A ui::Manager or a ui::Window
|
||||
std::vector<Window*> m_windows; // Sub-windows in this display
|
||||
gfx::Region m_invalidRegion; // Invalid region (we didn't receive paint messages yet for this).
|
||||
gfx::Region m_dirtyRegion; // Region to flip to the os::Display
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif
|
@ -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-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -16,7 +16,6 @@
|
||||
#include "os/draw_text.h"
|
||||
#include "os/font.h"
|
||||
#include "os/system.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/menu.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/scale.h"
|
||||
@ -452,7 +451,7 @@ gfx::Size Entry::sizeHintWithText(Entry* entry,
|
||||
+ 2*entry->theme()->getEntryCaretSize(entry).w
|
||||
+ entry->border().width();
|
||||
|
||||
w = std::min(w, ui::display_w()/2);
|
||||
w = std::min(w, ui::get_desktop_size().w/2);
|
||||
|
||||
int h =
|
||||
+ entry->font()->height()
|
||||
@ -471,7 +470,7 @@ void Entry::onSizeHint(SizeHintEvent& ev)
|
||||
+ trailing
|
||||
+ border().width();
|
||||
|
||||
w = std::min(w, ui::display_w()/2);
|
||||
w = std::min(w, ui::get_desktop_size().w/2);
|
||||
|
||||
int h =
|
||||
+ font()->height()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -9,14 +9,17 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ui/fit_bounds.h"
|
||||
|
||||
#include "base/clamp.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "ui/base.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
int fit_bounds(int arrowAlign, const gfx::Rect& target, gfx::Rect& bounds)
|
||||
int fit_bounds(Display* display, int arrowAlign, const gfx::Rect& target, gfx::Rect& bounds)
|
||||
{
|
||||
bounds.x = target.x;
|
||||
bounds.y = target.y;
|
||||
@ -58,8 +61,9 @@ int fit_bounds(int arrowAlign, const gfx::Rect& target, gfx::Rect& bounds)
|
||||
break;
|
||||
}
|
||||
|
||||
bounds.x = base::clamp(bounds.x, 0, ui::display_w()-bounds.w);
|
||||
bounds.y = base::clamp(bounds.y, 0, ui::display_h()-bounds.h);
|
||||
gfx::Size displaySize = display->size();
|
||||
bounds.x = base::clamp(bounds.x, 0, displaySize.w-bounds.w);
|
||||
bounds.y = base::clamp(bounds.y, 0, displaySize.h-bounds.h);
|
||||
|
||||
if (target.intersects(bounds)) {
|
||||
switch (trycount) {
|
||||
|
@ -1,18 +1,21 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef UI_POINT_AT_H_INCLUDED
|
||||
#define UI_POINT_AT_H_INCLUDED
|
||||
#ifndef UI_FIT_BOUNDS_H_INCLUDED
|
||||
#define UI_FIT_BOUNDS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/fwd.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
int fit_bounds(int arrowAlign, const gfx::Rect& target, gfx::Rect& bounds);
|
||||
class Display;
|
||||
|
||||
int fit_bounds(Display* display, int arrowAlign, const gfx::Rect& target, gfx::Rect& bounds);
|
||||
|
||||
} // namespace ui
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "os/surface.h"
|
||||
#include "os/system.h"
|
||||
#include "os/window.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/scale.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
@ -34,8 +34,9 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
Graphics::Graphics(const os::SurfaceRef& surface, int dx, int dy)
|
||||
: m_surface(surface)
|
||||
Graphics::Graphics(Display* display, const os::SurfaceRef& surface, int dx, int dy)
|
||||
: m_display(display)
|
||||
, m_surface(surface)
|
||||
, m_dx(dx)
|
||||
, m_dy(dy)
|
||||
{
|
||||
@ -45,8 +46,8 @@ 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()->defaultWindow()->surface())
|
||||
Manager::getDefault()->dirtyRect(m_dirtyBounds);
|
||||
if (m_display)
|
||||
m_display->dirtyRect(m_dirtyBounds);
|
||||
}
|
||||
|
||||
int Graphics::width() const
|
||||
@ -611,8 +612,8 @@ void Graphics::dirty(const gfx::Rect& bounds)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ScreenGraphics
|
||||
|
||||
ScreenGraphics::ScreenGraphics()
|
||||
: Graphics(AddRef(os::instance()->defaultWindow()->surface()), 0, 0)
|
||||
ScreenGraphics::ScreenGraphics(Display* display)
|
||||
: Graphics(display, AddRef(display->surface()), 0, 0)
|
||||
{
|
||||
setFont(AddRef(get_theme()->getDefaultFont()));
|
||||
}
|
||||
|
@ -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.
|
||||
@ -33,7 +33,9 @@ namespace os {
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
using os::Paint;
|
||||
using os::Paint; // Define ui::Paint = os::Paint
|
||||
|
||||
class Display;
|
||||
|
||||
// Class to render a widget in the screen.
|
||||
class Graphics {
|
||||
@ -44,7 +46,7 @@ namespace ui {
|
||||
Checked,
|
||||
};
|
||||
|
||||
Graphics(const os::SurfaceRef& surface, int dx, int dy);
|
||||
Graphics(Display* display, const os::SurfaceRef& surface, int dx, int dy);
|
||||
~Graphics();
|
||||
|
||||
int width() const;
|
||||
@ -127,6 +129,7 @@ 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);
|
||||
|
||||
Display* m_display;
|
||||
os::SurfaceRef m_surface;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
@ -138,7 +141,7 @@ namespace ui {
|
||||
// Class to draw directly in the screen.
|
||||
class ScreenGraphics : public Graphics {
|
||||
public:
|
||||
ScreenGraphics();
|
||||
ScreenGraphics(Display* display);
|
||||
virtual ~ScreenGraphics();
|
||||
};
|
||||
|
||||
|
@ -183,10 +183,11 @@ void IntEntry::openPopup()
|
||||
|
||||
Rect rc = bounds();
|
||||
gfx::Size sz = m_popupWindow->sizeHint();
|
||||
gfx::Size displaySize = display()->size();
|
||||
rc.w = 128*guiscale();
|
||||
if (rc.x+rc.w > ui::display_w())
|
||||
if (rc.x+rc.w > displaySize.w)
|
||||
rc.x = rc.x-rc.w+bounds().w;
|
||||
if (rc.y+rc.h+sz.h < ui::display_h())
|
||||
if (rc.y+rc.h+sz.h < displaySize.h)
|
||||
rc.y += rc.h;
|
||||
else
|
||||
rc.y -= sz.h;
|
||||
|
@ -76,7 +76,6 @@ typedef std::list<Message*> Messages;
|
||||
typedef std::list<Filter*> Filters;
|
||||
|
||||
Manager* Manager::m_defaultManager = nullptr;
|
||||
gfx::Region Manager::m_dirtyRegion;
|
||||
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
static base::thread::native_id_type manager_thread = 0;
|
||||
@ -160,13 +159,15 @@ bool Manager::widgetAssociatedToManager(Widget* widget)
|
||||
widget) != mouse_widgets_list.end());
|
||||
}
|
||||
|
||||
Manager::Manager()
|
||||
Manager::Manager(const os::WindowRef& nativeWindow)
|
||||
: Widget(kManagerWidget)
|
||||
, m_window(nullptr)
|
||||
, m_eventQueue(nullptr)
|
||||
, m_display(nativeWindow, this)
|
||||
, m_eventQueue(os::instance()->eventQueue())
|
||||
, m_lockedWindow(nullptr)
|
||||
, m_mouseButton(kButtonNone)
|
||||
{
|
||||
nativeWindow->setUserData(&m_display);
|
||||
|
||||
#ifdef DEBUG_UI_THREADS
|
||||
ASSERT(!manager_thread);
|
||||
manager_thread = base::this_thread::native_id();
|
||||
@ -183,14 +184,15 @@ Manager::Manager()
|
||||
capture_widget = nullptr;
|
||||
}
|
||||
|
||||
setBounds(gfx::Rect(0, 0, ui::display_w(), ui::display_h()));
|
||||
setBounds(m_display.bounds());
|
||||
setVisible(true);
|
||||
|
||||
m_dirtyRegion = bounds();
|
||||
|
||||
// Default manager is the first one (and is always visible).
|
||||
if (!m_defaultManager)
|
||||
m_defaultManager = this;
|
||||
|
||||
// TODO check if this is needed
|
||||
onNewDisplayConfiguration(&m_display);
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
@ -226,16 +228,12 @@ Manager::~Manager()
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::setNativeWindow(os::Window* window)
|
||||
Display* Manager::getDisplayFromNativeWindow(os::Window* window) const
|
||||
{
|
||||
base::ScopedValue<bool> lock(
|
||||
auto_window_adjustment, false,
|
||||
auto_window_adjustment);
|
||||
|
||||
m_window = window;
|
||||
m_eventQueue = os::instance()->eventQueue();
|
||||
|
||||
onNewDisplayConfiguration();
|
||||
if (window)
|
||||
return window->userData<Display>();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Manager::run()
|
||||
@ -253,11 +251,8 @@ void Manager::run()
|
||||
loop.pumpMessages();
|
||||
}
|
||||
|
||||
void Manager::flipDisplay()
|
||||
void Manager::flipAllDisplays()
|
||||
{
|
||||
if (!m_window)
|
||||
return;
|
||||
|
||||
OverlayManager* overlays = OverlayManager::instance();
|
||||
|
||||
update_cursor_overlay();
|
||||
@ -265,15 +260,15 @@ void Manager::flipDisplay()
|
||||
// Draw overlays.
|
||||
overlays->drawOverlays();
|
||||
|
||||
// Invalidate the dirty region in the laf::os::Display (the real OS window).
|
||||
m_dirtyRegion.createIntersection(
|
||||
m_dirtyRegion,
|
||||
gfx::Region(gfx::Rect(0, 0, ui::display_w(), ui::display_h())));
|
||||
m_display.flipDisplay();
|
||||
}
|
||||
|
||||
if (!m_dirtyRegion.isEmpty()) {
|
||||
m_window->invalidateRegion(m_dirtyRegion);
|
||||
m_dirtyRegion.clear();
|
||||
}
|
||||
void Manager::updateAllDisplaysWithNewScale(int scale)
|
||||
{
|
||||
os::Window* nativeWindow = m_display.nativeWindow();
|
||||
nativeWindow->setScale(scale);
|
||||
|
||||
onNewDisplayConfiguration(&m_display);
|
||||
}
|
||||
|
||||
bool Manager::generateMessages()
|
||||
@ -308,7 +303,8 @@ bool Manager::generateMessages()
|
||||
return false;
|
||||
}
|
||||
|
||||
void Manager::generateSetCursorMessage(const gfx::Point& mousePos,
|
||||
void Manager::generateSetCursorMessage(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType)
|
||||
{
|
||||
@ -319,7 +315,8 @@ void Manager::generateSetCursorMessage(const gfx::Point& mousePos,
|
||||
if (dst)
|
||||
enqueueMessage(
|
||||
newMouseMessage(
|
||||
kSetCursorMessage, dst,
|
||||
kSetCursorMessage,
|
||||
display, dst,
|
||||
mousePos,
|
||||
pointerType,
|
||||
m_mouseButton,
|
||||
@ -375,10 +372,15 @@ void Manager::generateMessagesFromOSEvents()
|
||||
if (osEvent.type() == os::Event::None)
|
||||
break;
|
||||
|
||||
Display* display = getDisplayFromNativeWindow(osEvent.window().get());
|
||||
if (!display)
|
||||
display = this->display();
|
||||
|
||||
switch (osEvent.type()) {
|
||||
|
||||
case os::Event::CloseApp: {
|
||||
Message* msg = new Message(kCloseDisplayMessage);
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(this);
|
||||
msg->setPropagateToChildren(true);
|
||||
enqueueMessage(msg);
|
||||
@ -387,6 +389,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
|
||||
case os::Event::CloseWindow: {
|
||||
Message* msg = new Message(kCloseDisplayMessage);
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(this);
|
||||
msg->setPropagateToChildren(true);
|
||||
enqueueMessage(msg);
|
||||
@ -395,6 +398,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
|
||||
case os::Event::ResizeWindow: {
|
||||
Message* msg = new Message(kResizeDisplayMessage);
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(this);
|
||||
msg->setPropagateToChildren(true);
|
||||
enqueueMessage(msg);
|
||||
@ -403,6 +407,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
|
||||
case os::Event::DropFiles: {
|
||||
Message* msg = new DropFilesMessage(osEvent.files());
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(this);
|
||||
enqueueMessage(msg);
|
||||
break;
|
||||
@ -419,6 +424,8 @@ void Manager::generateMessagesFromOSEvents()
|
||||
osEvent.unicodeChar(),
|
||||
osEvent.repeat());
|
||||
|
||||
msg->setDisplay(display);
|
||||
|
||||
if (osEvent.isDeadKey())
|
||||
static_cast<KeyMessage*>(msg)->setDeadKey(true);
|
||||
|
||||
@ -449,6 +456,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
case os::Event::MouseMove: {
|
||||
_internal_set_mouse_position(osEvent.position());
|
||||
handleMouseMove(
|
||||
display,
|
||||
osEvent.position(),
|
||||
osEvent.modifiers(),
|
||||
osEvent.pointerType(),
|
||||
@ -459,6 +467,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
|
||||
case os::Event::MouseDown: {
|
||||
handleMouseDown(
|
||||
display,
|
||||
osEvent.position(),
|
||||
m_mouseButton = mouse_button_from_os_to_ui(osEvent),
|
||||
osEvent.modifiers(),
|
||||
@ -468,6 +477,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
|
||||
case os::Event::MouseUp: {
|
||||
handleMouseUp(
|
||||
display,
|
||||
osEvent.position(),
|
||||
mouse_button_from_os_to_ui(osEvent),
|
||||
osEvent.modifiers(),
|
||||
@ -478,6 +488,7 @@ void Manager::generateMessagesFromOSEvents()
|
||||
|
||||
case os::Event::MouseDoubleClick: {
|
||||
handleMouseDoubleClick(
|
||||
display,
|
||||
osEvent.position(),
|
||||
m_mouseButton = mouse_button_from_os_to_ui(osEvent),
|
||||
osEvent.modifiers(),
|
||||
@ -486,7 +497,8 @@ void Manager::generateMessagesFromOSEvents()
|
||||
}
|
||||
|
||||
case os::Event::MouseWheel: {
|
||||
handleMouseWheel(osEvent.position(),
|
||||
handleMouseWheel(display,
|
||||
osEvent.position(),
|
||||
osEvent.modifiers(),
|
||||
osEvent.pointerType(),
|
||||
osEvent.wheelDelta(),
|
||||
@ -497,7 +509,8 @@ void Manager::generateMessagesFromOSEvents()
|
||||
case os::Event::TouchMagnify: {
|
||||
_internal_set_mouse_position(osEvent.position());
|
||||
|
||||
handleTouchMagnify(osEvent.position(),
|
||||
handleTouchMagnify(display,
|
||||
osEvent.position(),
|
||||
osEvent.modifiers(),
|
||||
osEvent.magnification());
|
||||
break;
|
||||
@ -515,13 +528,20 @@ void Manager::generateMessagesFromOSEvents()
|
||||
// Generate just one kSetCursorMessage for the last mouse position
|
||||
if (lastMouseMoveEvent.type() != os::Event::None) {
|
||||
osEvent = lastMouseMoveEvent;
|
||||
generateSetCursorMessage(osEvent.position(),
|
||||
|
||||
Display* display = getDisplayFromNativeWindow(osEvent.window().get());
|
||||
if (!display)
|
||||
display = this->display();
|
||||
|
||||
generateSetCursorMessage(display,
|
||||
osEvent.position(),
|
||||
osEvent.modifiers(),
|
||||
osEvent.pointerType());
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::handleMouseMove(const gfx::Point& mousePos,
|
||||
void Manager::handleMouseMove(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
const KeyModifiers modifiers,
|
||||
const PointerType pointerType,
|
||||
const float pressure)
|
||||
@ -532,7 +552,8 @@ void Manager::handleMouseMove(const gfx::Point& mousePos,
|
||||
Widget* dst = (capture_widget ? capture_widget: mouse_widget);
|
||||
enqueueMessage(
|
||||
newMouseMessage(
|
||||
kMouseMoveMessage, dst,
|
||||
kMouseMoveMessage,
|
||||
display, dst,
|
||||
mousePos,
|
||||
pointerType,
|
||||
m_mouseButton,
|
||||
@ -542,7 +563,8 @@ void Manager::handleMouseMove(const gfx::Point& mousePos,
|
||||
pressure));
|
||||
}
|
||||
|
||||
void Manager::handleMouseDown(const gfx::Point& mousePos,
|
||||
void Manager::handleMouseDown(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
MouseButton mouseButton,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType)
|
||||
@ -552,6 +574,7 @@ void Manager::handleMouseDown(const gfx::Point& mousePos,
|
||||
enqueueMessage(
|
||||
newMouseMessage(
|
||||
kMouseDownMessage,
|
||||
display,
|
||||
(capture_widget ? capture_widget: mouse_widget),
|
||||
mousePos,
|
||||
pointerType,
|
||||
@ -559,7 +582,8 @@ void Manager::handleMouseDown(const gfx::Point& mousePos,
|
||||
modifiers));
|
||||
}
|
||||
|
||||
void Manager::handleMouseUp(const gfx::Point& mousePos,
|
||||
void Manager::handleMouseUp(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
MouseButton mouseButton,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType)
|
||||
@ -567,6 +591,7 @@ void Manager::handleMouseUp(const gfx::Point& mousePos,
|
||||
enqueueMessage(
|
||||
newMouseMessage(
|
||||
kMouseUpMessage,
|
||||
display,
|
||||
(capture_widget ? capture_widget: mouse_widget),
|
||||
mousePos,
|
||||
pointerType,
|
||||
@ -574,7 +599,8 @@ void Manager::handleMouseUp(const gfx::Point& mousePos,
|
||||
modifiers));
|
||||
}
|
||||
|
||||
void Manager::handleMouseDoubleClick(const gfx::Point& mousePos,
|
||||
void Manager::handleMouseDoubleClick(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
MouseButton mouseButton,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType)
|
||||
@ -584,12 +610,13 @@ void Manager::handleMouseDoubleClick(const gfx::Point& mousePos,
|
||||
enqueueMessage(
|
||||
newMouseMessage(
|
||||
kDoubleClickMessage,
|
||||
dst, mousePos, pointerType,
|
||||
display, dst, mousePos, pointerType,
|
||||
mouseButton, modifiers));
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::handleMouseWheel(const gfx::Point& mousePos,
|
||||
void Manager::handleMouseWheel(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType,
|
||||
const gfx::Point& wheelDelta,
|
||||
@ -597,12 +624,14 @@ void Manager::handleMouseWheel(const gfx::Point& mousePos,
|
||||
{
|
||||
enqueueMessage(newMouseMessage(
|
||||
kMouseWheelMessage,
|
||||
display,
|
||||
(capture_widget ? capture_widget: mouse_widget),
|
||||
mousePos, pointerType, m_mouseButton, modifiers,
|
||||
wheelDelta, preciseWheel));
|
||||
}
|
||||
|
||||
void Manager::handleTouchMagnify(const gfx::Point& mousePos,
|
||||
void Manager::handleTouchMagnify(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
const KeyModifiers modifiers,
|
||||
const double magnification)
|
||||
{
|
||||
@ -614,6 +643,7 @@ void Manager::handleTouchMagnify(const gfx::Point& mousePos,
|
||||
mousePos,
|
||||
magnification);
|
||||
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(widget);
|
||||
|
||||
enqueueMessage(msg);
|
||||
@ -622,6 +652,8 @@ void Manager::handleTouchMagnify(const gfx::Point& mousePos,
|
||||
|
||||
// Handles Z order: Send the window to top (only when you click in a
|
||||
// window that aren't the desktop).
|
||||
//
|
||||
// TODO code similar to Display::handleWindowZOrder()
|
||||
void Manager::handleWindowZOrder()
|
||||
{
|
||||
if (capture_widget || !mouse_widget)
|
||||
@ -642,6 +674,8 @@ void Manager::handleWindowZOrder()
|
||||
(window != win_manager->getTopWindow())) {
|
||||
base::ScopedValue<Widget*> scoped(m_lockedWindow, window, nullptr);
|
||||
|
||||
window->display()->handleWindowZOrder(window);
|
||||
|
||||
// Put it in the top of the list
|
||||
win_manager->removeChild(window);
|
||||
|
||||
@ -718,8 +752,8 @@ void Manager::dispatchMessages()
|
||||
flushRedraw();
|
||||
pumpQueue();
|
||||
|
||||
// Flip the back-buffer to the real display.
|
||||
flipDisplay();
|
||||
// Flip back-buffers to real displays.
|
||||
flipAllDisplays();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -854,8 +888,11 @@ void Manager::setMouse(Widget* widget)
|
||||
// Put the mouse
|
||||
mouse_widget = widget;
|
||||
if (widget) {
|
||||
Display* display = mouse_widget->display();
|
||||
|
||||
auto msg = newMouseMessage(
|
||||
kMouseEnterMessage, nullptr,
|
||||
kMouseEnterMessage,
|
||||
display, nullptr,
|
||||
get_mouse_position(),
|
||||
PointerType::Unknown,
|
||||
m_mouseButton,
|
||||
@ -865,7 +902,8 @@ void Manager::setMouse(Widget* widget)
|
||||
msg->setPropagateToParent(true);
|
||||
msg->setCommonAncestor(commonAncestor);
|
||||
enqueueMessage(msg);
|
||||
generateSetCursorMessage(get_mouse_position(),
|
||||
generateSetCursorMessage(display,
|
||||
get_mouse_position(),
|
||||
kKeyUninitializedModifier,
|
||||
PointerType::Unknown);
|
||||
|
||||
@ -888,7 +926,10 @@ void Manager::setCapture(Widget* widget)
|
||||
widget->enableFlags(HAS_CAPTURE);
|
||||
capture_widget = widget;
|
||||
|
||||
m_window->captureMouse();
|
||||
Display* display = (widget ? widget->display(): &m_display);
|
||||
ASSERT(display && display->nativeWindow());
|
||||
if (display && display->nativeWindow())
|
||||
display->nativeWindow()->captureMouse();
|
||||
}
|
||||
|
||||
// Sets the focus to the "magnetic" widget inside the window
|
||||
@ -925,10 +966,14 @@ void Manager::freeMouse()
|
||||
void Manager::freeCapture()
|
||||
{
|
||||
if (capture_widget) {
|
||||
Display* display = capture_widget->display();
|
||||
|
||||
capture_widget->disableFlags(HAS_CAPTURE);
|
||||
capture_widget = nullptr;
|
||||
|
||||
m_window->releaseMouse();
|
||||
ASSERT(display && display->nativeWindow());
|
||||
if (display && display->nativeWindow())
|
||||
display->nativeWindow()->releaseMouse();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1073,11 +1118,6 @@ bool Manager::isFocusMovementMessage(Message* msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Manager::dirtyRect(const gfx::Rect& bounds)
|
||||
{
|
||||
m_dirtyRegion.createUnion(m_dirtyRegion, gfx::Region(bounds));
|
||||
}
|
||||
|
||||
// Configures the window for begin the loop
|
||||
void Manager::_openWindow(Window* window)
|
||||
{
|
||||
@ -1100,6 +1140,9 @@ void Manager::_openWindow(Window* window)
|
||||
// Relayout
|
||||
window->layout();
|
||||
|
||||
// Same display as the manager.
|
||||
window->setDisplay(this->display());
|
||||
|
||||
// Dirty the entire window and show it
|
||||
window->setVisible(true);
|
||||
window->invalidate();
|
||||
@ -1121,6 +1164,8 @@ void Manager::_openWindow(Window* window)
|
||||
|
||||
void Manager::_closeWindow(Window* window, bool redraw_background)
|
||||
{
|
||||
window->setDisplay(nullptr);
|
||||
|
||||
if (!hasChild(window))
|
||||
return;
|
||||
|
||||
@ -1189,7 +1234,7 @@ bool Manager::onProcessMessage(Message* msg)
|
||||
return true;
|
||||
|
||||
case kResizeDisplayMessage:
|
||||
onNewDisplayConfiguration();
|
||||
onNewDisplayConfiguration(msg->display());
|
||||
break;
|
||||
|
||||
case kKeyDownMessage:
|
||||
@ -1236,7 +1281,7 @@ void Manager::onResize(ResizeEvent& ev)
|
||||
setBoundsQuietly(new_pos);
|
||||
|
||||
// The whole manager area is invalid now.
|
||||
m_invalidRegion = gfx::Region(new_pos);
|
||||
m_display.setInvalidRegion(gfx::Region(new_pos));
|
||||
|
||||
const int dx = new_pos.x - old_pos.x;
|
||||
const int dy = new_pos.y - old_pos.y;
|
||||
@ -1306,11 +1351,12 @@ void Manager::onInitTheme(InitThemeEvent& ev)
|
||||
window->layout();
|
||||
}
|
||||
else {
|
||||
gfx::Size displaySize = m_display.size();
|
||||
gfx::Rect bounds = window->bounds();
|
||||
bounds *= newUIScale;
|
||||
bounds /= oldUIScale;
|
||||
bounds.x = base::clamp(bounds.x, 0, m_window->width() - bounds.w);
|
||||
bounds.y = base::clamp(bounds.y, 0, m_window->height() - bounds.h);
|
||||
bounds.x = base::clamp(bounds.x, 0, displaySize.w - bounds.w);
|
||||
bounds.y = base::clamp(bounds.y, 0, displaySize.h - bounds.h);
|
||||
window->setBounds(bounds);
|
||||
}
|
||||
}
|
||||
@ -1322,19 +1368,19 @@ LayoutIO* Manager::onGetLayoutIO()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Manager::onNewDisplayConfiguration()
|
||||
void Manager::onNewDisplayConfiguration(Display* display)
|
||||
{
|
||||
if (m_window) {
|
||||
int w = m_window->width() / m_window->scale();
|
||||
int h = m_window->height() / m_window->scale();
|
||||
if ((bounds().w != w ||
|
||||
bounds().h != h)) {
|
||||
setBounds(gfx::Rect(0, 0, w, h));
|
||||
}
|
||||
ASSERT(display);
|
||||
Widget* container = display->containedWidget();
|
||||
|
||||
gfx::Size displaySize = display->size();
|
||||
if ((bounds().w != displaySize.w ||
|
||||
bounds().h != displaySize.h)) {
|
||||
container->setBounds(gfx::Rect(displaySize));
|
||||
}
|
||||
|
||||
_internal_set_mouse_window(m_window);
|
||||
invalidate();
|
||||
_internal_set_mouse_display(display);
|
||||
container->invalidate();
|
||||
flushRedraw();
|
||||
}
|
||||
|
||||
@ -1497,10 +1543,11 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
|
||||
|
||||
PaintMessage* paintMsg = static_cast<PaintMessage*>(msg);
|
||||
|
||||
// TODO use paintMsg->display() here
|
||||
// Restore overlays in the region that we're going to paint.
|
||||
OverlayManager::instance()->restoreOverlappedAreas(paintMsg->rect());
|
||||
|
||||
os::Surface* surface = m_window->surface();
|
||||
os::Surface* surface = paintMsg->display()->surface();
|
||||
surface->saveClip();
|
||||
|
||||
if (surface->clipRect(paintMsg->rect())) {
|
||||
@ -1520,8 +1567,7 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
|
||||
}
|
||||
|
||||
if (m_window) {
|
||||
m_window->invalidateRegion(
|
||||
gfx::Region(gfx::Rect(0, 0, display_w(), display_h())));
|
||||
m_window->invalidateRegion(gfx::Region(m_window->bounds()));
|
||||
// TODO m_window->update() ??
|
||||
}
|
||||
|
||||
@ -1539,7 +1585,7 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
|
||||
|
||||
// As this kPaintMessage's rectangle was updated, we can
|
||||
// remove it from "m_invalidRegion".
|
||||
m_invalidRegion -= gfx::Region(paintMsg->rect());
|
||||
paintMsg->display()->subtractInvalidRegion(gfx::Region(paintMsg->rect()));
|
||||
}
|
||||
else {
|
||||
// Call the message handler
|
||||
@ -1690,6 +1736,7 @@ Widget* Manager::findMagneticWidget(Widget* widget)
|
||||
// static
|
||||
Message* Manager::newMouseMessage(
|
||||
MessageType type,
|
||||
Display* display,
|
||||
Widget* widget,
|
||||
const gfx::Point& mousePos,
|
||||
PointerType pointerType,
|
||||
@ -1716,6 +1763,9 @@ Message* Manager::newMouseMessage(
|
||||
type, pointerType, button, modifiers, mousePos,
|
||||
wheelDelta, preciseWheel, pressure);
|
||||
|
||||
if (display)
|
||||
msg->setDisplay(display);
|
||||
|
||||
if (widget)
|
||||
msg->setRecipient(widget);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "gfx/region.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/keys.h"
|
||||
#include "ui/message_type.h"
|
||||
#include "ui/mouse_button.h"
|
||||
@ -32,17 +33,19 @@ namespace ui {
|
||||
static Manager* getDefault() { return m_defaultManager; }
|
||||
static bool widgetAssociatedToManager(Widget* widget);
|
||||
|
||||
Manager();
|
||||
Manager(const os::WindowRef& nativeWindow);
|
||||
~Manager();
|
||||
|
||||
os::Window* nativeWindow() { return m_window; }
|
||||
void setNativeWindow(os::Window* window);
|
||||
Display* display() { return &m_display; }
|
||||
Display* getDisplayFromNativeWindow(os::Window* window) const;
|
||||
|
||||
// Executes the main message loop.
|
||||
void run();
|
||||
|
||||
// Refreshes the real display with the UI content.
|
||||
void flipDisplay();
|
||||
// Refreshes all real displays with the UI content.
|
||||
void flipAllDisplays();
|
||||
|
||||
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
|
||||
@ -86,21 +89,6 @@ namespace ui {
|
||||
bool isFocusMovementMessage(Message* msg);
|
||||
bool processFocusMovementMessage(Message* msg);
|
||||
|
||||
// Returns the invalid region in the screen to being updated with
|
||||
// PaintMessages. This region is cleared when each widget receives
|
||||
// a paint message.
|
||||
const gfx::Region& getInvalidRegion() const {
|
||||
return m_invalidRegion;
|
||||
}
|
||||
|
||||
void addInvalidRegion(const gfx::Region& b) {
|
||||
m_invalidRegion |= b;
|
||||
}
|
||||
|
||||
// Mark the given rectangle as a area to be flipped to the real
|
||||
// screen
|
||||
void dirtyRect(const gfx::Rect& bounds);
|
||||
|
||||
void _openWindow(Window* window);
|
||||
void _closeWindow(Window* window, bool redraw_background);
|
||||
|
||||
@ -112,35 +100,43 @@ namespace ui {
|
||||
void onBroadcastMouseMessage(WidgetsList& targets) override;
|
||||
void onInitTheme(InitThemeEvent& ev) override;
|
||||
virtual LayoutIO* onGetLayoutIO();
|
||||
virtual void onNewDisplayConfiguration();
|
||||
virtual void onNewDisplayConfiguration(Display* display);
|
||||
|
||||
private:
|
||||
void generateSetCursorMessage(const gfx::Point& mousePos,
|
||||
void generateSetCursorMessage(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType);
|
||||
void generateMessagesFromOSEvents();
|
||||
void handleMouseMove(const gfx::Point& mousePos,
|
||||
|
||||
void handleMouseMove(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
const KeyModifiers modifiers,
|
||||
const PointerType pointerType,
|
||||
const float pressure);
|
||||
void handleMouseDown(const gfx::Point& mousePos,
|
||||
void handleMouseDown(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
MouseButton mouseButton,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType);
|
||||
void handleMouseUp(const gfx::Point& mousePos,
|
||||
void handleMouseUp(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
MouseButton mouseButton,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType);
|
||||
void handleMouseDoubleClick(const gfx::Point& mousePos,
|
||||
void handleMouseDoubleClick(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
MouseButton mouseButton,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType);
|
||||
void handleMouseWheel(const gfx::Point& mousePos,
|
||||
void handleMouseWheel(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
KeyModifiers modifiers,
|
||||
PointerType pointerType,
|
||||
const gfx::Point& wheelDelta,
|
||||
bool preciseWheel);
|
||||
void handleTouchMagnify(const gfx::Point& mousePos,
|
||||
void handleTouchMagnify(Display* display,
|
||||
const gfx::Point& mousePos,
|
||||
const KeyModifiers modifiers,
|
||||
const double magnification);
|
||||
void handleWindowZOrder();
|
||||
@ -154,7 +150,9 @@ namespace ui {
|
||||
static Widget* findMagneticWidget(Widget* widget);
|
||||
static Message* newMouseMessage(
|
||||
MessageType type,
|
||||
Widget* widget, const gfx::Point& mousePos,
|
||||
Display* display,
|
||||
Widget* widget,
|
||||
const gfx::Point& mousePos,
|
||||
PointerType pointerType,
|
||||
MouseButton button,
|
||||
KeyModifiers modifiers,
|
||||
@ -164,12 +162,10 @@ namespace ui {
|
||||
void broadcastKeyMsg(Message* msg);
|
||||
|
||||
static Manager* m_defaultManager;
|
||||
static gfx::Region m_dirtyRegion;
|
||||
|
||||
WidgetsList m_garbage;
|
||||
os::Window* m_window;
|
||||
Display m_display;
|
||||
os::EventQueue* m_eventQueue;
|
||||
gfx::Region m_invalidRegion; // Invalid region (we didn't receive paint messages yet for this).
|
||||
|
||||
// This member is used to make freeWidget() a no-op when we
|
||||
// restack a window if the user clicks on it.
|
||||
|
@ -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-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -14,6 +14,7 @@
|
||||
#include "base/clamp.h"
|
||||
#include "gfx/size.h"
|
||||
#include "os/font.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
@ -102,14 +103,15 @@ static MenuItem* find_previtem(Menu* menu, MenuItem* menuitem);
|
||||
static void add_scrollbars_if_needed(Window* window)
|
||||
{
|
||||
const gfx::Rect rc0 = window->bounds();
|
||||
gfx::Size displaySize = window->display()->size();
|
||||
gfx::Rect rc = rc0;
|
||||
|
||||
if (rc.x < 0) {
|
||||
rc.w += rc.x;
|
||||
rc.x = 0;
|
||||
}
|
||||
if (rc.x2() > ui::display_w()) {
|
||||
rc.w = ui::display_w() - rc.x;
|
||||
if (rc.x2() > displaySize.w) {
|
||||
rc.w = displaySize.w - rc.x;
|
||||
}
|
||||
|
||||
bool vscrollbarsAdded = false;
|
||||
@ -118,8 +120,8 @@ static void add_scrollbars_if_needed(Window* window)
|
||||
rc.y = 0;
|
||||
vscrollbarsAdded = true;
|
||||
}
|
||||
if (rc.y2() > ui::display_h()) {
|
||||
rc.h = ui::display_h() - rc.y;
|
||||
if (rc.y2() > displaySize.h) {
|
||||
rc.h = displaySize.h - rc.y;
|
||||
vscrollbarsAdded = true;
|
||||
}
|
||||
|
||||
@ -133,11 +135,11 @@ static void add_scrollbars_if_needed(Window* window)
|
||||
|
||||
if (vscrollbarsAdded) {
|
||||
rc.w += 2*view->verticalBar()->getBarWidth();
|
||||
if (rc.x2() > ui::display_w()) {
|
||||
rc.x = ui::display_w() - rc.w;
|
||||
if (rc.x2() > displaySize.w) {
|
||||
rc.x = displaySize.w - rc.w;
|
||||
if (rc.x < 0) {
|
||||
rc.x = 0;
|
||||
rc.w = ui::display_w();
|
||||
rc.w = displaySize.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -311,6 +313,7 @@ void Menu::showPopup(const gfx::Point& pos)
|
||||
MenuBaseData* base = menubox->createBase();
|
||||
base->was_clicked = true;
|
||||
window->setMoveable(false); // Can't move the window
|
||||
window->setSizeable(false); // Can't resize the window
|
||||
|
||||
// Set children
|
||||
menubox->setMenu(this);
|
||||
@ -320,9 +323,10 @@ void Menu::showPopup(const gfx::Point& pos)
|
||||
window->remapWindow();
|
||||
|
||||
// Menubox position
|
||||
gfx::Size displaySize = display()->size();
|
||||
window->positionWindow(
|
||||
base::clamp(pos.x, 0, ui::display_w() - window->bounds().w),
|
||||
base::clamp(pos.y, 0, ui::display_h() - window->bounds().h));
|
||||
base::clamp(pos.x, 0, displaySize.w - window->bounds().w),
|
||||
base::clamp(pos.y, 0, displaySize.h - window->bounds().h));
|
||||
|
||||
add_scrollbars_if_needed(window.get());
|
||||
|
||||
@ -821,9 +825,10 @@ bool MenuItem::onProcessMessage(Message* msg)
|
||||
|
||||
// Menubox position
|
||||
Rect pos = window->bounds();
|
||||
Size displaySize = display()->size();
|
||||
|
||||
if (inBar()) {
|
||||
pos.x = base::clamp(bounds().x, 0, ui::display_w()-pos.w);
|
||||
pos.x = base::clamp(bounds().x, 0, displaySize.w-pos.w);
|
||||
pos.y = std::max(0, bounds().y2());
|
||||
}
|
||||
else {
|
||||
@ -832,9 +837,9 @@ bool MenuItem::onProcessMessage(Message* msg)
|
||||
int x, y = bounds().y-3*guiscale();
|
||||
Rect r1(0, 0, pos.w, pos.h), r2(0, 0, pos.w, pos.h);
|
||||
|
||||
r1.x = x_left = base::clamp(x_left, 0, ui::display_w()-pos.w);
|
||||
r2.x = x_right = base::clamp(x_right, 0, ui::display_w()-pos.w);
|
||||
r1.y = r2.y = y = base::clamp(y, 0, ui::display_h()-pos.h);
|
||||
r1.x = x_left = base::clamp(x_left, 0, displaySize.w-pos.w);
|
||||
r2.x = x_right = base::clamp(x_right, 0, displaySize.w-pos.w);
|
||||
r1.y = r2.y = y = base::clamp(y, 0, displaySize.h-pos.h);
|
||||
|
||||
// Calculate both intersections
|
||||
gfx::Rect s1 = r1.createIntersection(old_pos);
|
||||
@ -1408,6 +1413,7 @@ MenuBoxWindow::MenuBoxWindow(MenuBox* menubox)
|
||||
: Window(WithoutTitleBar, "")
|
||||
{
|
||||
setMoveable(false); // Can't move the window
|
||||
setSizeable(false); // Can't resize the window
|
||||
addChild(menubox);
|
||||
remapWindow();
|
||||
}
|
||||
|
@ -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.
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "os/system.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/widget.h"
|
||||
|
||||
#include <cstring>
|
||||
@ -23,6 +22,7 @@ namespace ui {
|
||||
Message::Message(MessageType type, KeyModifiers modifiers)
|
||||
: m_type(type)
|
||||
, m_flags(0)
|
||||
, m_display(nullptr)
|
||||
, m_recipient(nullptr)
|
||||
, m_commonAncestor(nullptr)
|
||||
{
|
||||
@ -36,6 +36,11 @@ Message::~Message()
|
||||
{
|
||||
}
|
||||
|
||||
void Message::setDisplay(Display* display)
|
||||
{
|
||||
m_display = display;
|
||||
}
|
||||
|
||||
void Message::setRecipient(Widget* widget)
|
||||
{
|
||||
ASSERT(m_recipient == nullptr);
|
||||
|
@ -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-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Display;
|
||||
class Timer;
|
||||
class Widget;
|
||||
|
||||
@ -35,6 +36,7 @@ namespace ui {
|
||||
virtual ~Message();
|
||||
|
||||
MessageType type() const { return m_type; }
|
||||
Display* display() const { return m_display; }
|
||||
Widget* recipient() const { return m_recipient; }
|
||||
bool fromFilter() const { return hasFlag(FromFilter); }
|
||||
void setFromFilter(const bool state) { setFlag(FromFilter, state); }
|
||||
@ -50,6 +52,7 @@ namespace ui {
|
||||
bool onlyCmdPressed() const { return m_modifiers == kKeyCmdModifier; }
|
||||
bool onlyWinPressed() const { return m_modifiers == kKeyWinModifier; }
|
||||
|
||||
void setDisplay(Display* display);
|
||||
void setRecipient(Widget* widget);
|
||||
void removeRecipient(Widget* widget);
|
||||
|
||||
@ -72,6 +75,7 @@ namespace ui {
|
||||
|
||||
MessageType m_type; // Type of message
|
||||
int m_flags; // Special flags for this message
|
||||
Display* m_display;
|
||||
Widget* m_recipient; // Recipient of this message
|
||||
Widget* m_commonAncestor; // Common ancestor between the Leave <-> Enter messages
|
||||
KeyModifiers m_modifiers; // Key modifiers pressed when message was created
|
||||
@ -101,7 +105,9 @@ namespace ui {
|
||||
class PaintMessage : public Message {
|
||||
public:
|
||||
PaintMessage(int count, const gfx::Rect& rect)
|
||||
: Message(kPaintMessage), m_count(count), m_rect(rect) {
|
||||
: Message(kPaintMessage)
|
||||
, m_count(count)
|
||||
, m_rect(rect) {
|
||||
}
|
||||
|
||||
int count() const { return m_count; }
|
||||
|
@ -22,9 +22,13 @@ namespace ui {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
void move_region(Manager* manager, const Region& region, int dx, int dy)
|
||||
void move_region(Display* display, const Region& region, int dx, int dy)
|
||||
{
|
||||
os::Window* window = manager->nativeWindow();
|
||||
ASSERT(display);
|
||||
if (!display)
|
||||
return;
|
||||
|
||||
os::Window* window = display->nativeWindow();
|
||||
ASSERT(window);
|
||||
if (!window)
|
||||
return;
|
||||
@ -43,7 +47,7 @@ void move_region(Manager* manager, const Region& region, int dx, int dy)
|
||||
surface->scrollTo(rc, dx, dy);
|
||||
|
||||
rc.offset(dx, dy);
|
||||
manager->dirtyRect(rc);
|
||||
display->dirtyRect(rc);
|
||||
}
|
||||
// As rectangles in the region internals are separated by bands
|
||||
// through the y-axis, we can sort the rectangles by y-axis and then
|
||||
@ -87,7 +91,7 @@ void move_region(Manager* manager, const Region& region, int dx, int dy)
|
||||
surface->scrollTo(rc, dx, dy);
|
||||
|
||||
rc.offset(dx, dy);
|
||||
manager->dirtyRect(rc);
|
||||
display->dirtyRect(rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -12,9 +13,9 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Manager;
|
||||
class Display;
|
||||
|
||||
void move_region(Manager* manager, const gfx::Region& region, int dx, int dy);
|
||||
void move_region(Display* display, const gfx::Region& region, int dx, int dy);
|
||||
|
||||
} // namespace ui
|
||||
|
||||
|
@ -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-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -13,14 +13,16 @@
|
||||
|
||||
#include "os/surface.h"
|
||||
#include "os/system.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/display.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
Overlay::Overlay(const os::SurfaceRef& overlaySurface,
|
||||
Overlay::Overlay(Display* display,
|
||||
const os::SurfaceRef& overlaySurface,
|
||||
const gfx::Point& pos,
|
||||
ZOrder zorder)
|
||||
: m_surface(overlaySurface)
|
||||
: m_display(display)
|
||||
, m_surface(overlaySurface)
|
||||
, m_overlap(nullptr)
|
||||
, m_captured(nullptr)
|
||||
, m_pos(pos)
|
||||
@ -33,11 +35,8 @@ Overlay::~Overlay()
|
||||
ASSERT(!m_captured);
|
||||
|
||||
if (m_surface) {
|
||||
Manager* manager = Manager::getDefault();
|
||||
if (manager)
|
||||
manager->invalidateRect(gfx::Rect(m_pos.x, m_pos.y,
|
||||
m_surface->width(),
|
||||
m_surface->height()));
|
||||
if (m_display)
|
||||
m_display->invalidateRect(bounds());
|
||||
m_surface.reset();
|
||||
}
|
||||
|
||||
@ -69,7 +68,7 @@ void Overlay::drawOverlay()
|
||||
os::SurfaceLock lock(m_surface.get());
|
||||
m_captured->drawRgbaSurface(m_surface.get(), m_pos.x, m_pos.y);
|
||||
|
||||
Manager::getDefault()->dirtyRect(
|
||||
m_display->dirtyRect(
|
||||
gfx::Rect(m_pos.x, m_pos.y,
|
||||
m_surface->width(),
|
||||
m_surface->height()));
|
||||
@ -83,24 +82,27 @@ void Overlay::moveOverlay(const gfx::Point& newPos)
|
||||
m_pos = newPos;
|
||||
}
|
||||
|
||||
void Overlay::captureOverlappedArea(os::Surface* screen)
|
||||
void Overlay::captureOverlappedArea()
|
||||
{
|
||||
if (!m_surface ||
|
||||
m_captured)
|
||||
return;
|
||||
|
||||
os::Surface* displaySurface = m_display->surface();
|
||||
os::SurfaceLock lockDisplaySurface(displaySurface);
|
||||
|
||||
if (!m_overlap) {
|
||||
// Use the same color space for the overlay as in the screen
|
||||
m_overlap = os::instance()->makeSurface(m_surface->width(),
|
||||
m_surface->height(),
|
||||
screen->colorSpace());
|
||||
displaySurface->colorSpace());
|
||||
}
|
||||
|
||||
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());
|
||||
displaySurface->blitTo(m_overlap.get(), m_pos.x, m_pos.y, 0, 0,
|
||||
m_overlap->width(), m_overlap->height());
|
||||
|
||||
m_captured = screen;
|
||||
m_captured = displaySurface;
|
||||
}
|
||||
|
||||
void Overlay::restoreOverlappedArea(const gfx::Rect& restoreBounds)
|
||||
@ -118,8 +120,7 @@ void Overlay::restoreOverlappedArea(const gfx::Rect& restoreBounds)
|
||||
m_overlap->blitTo(m_captured, 0, 0, m_pos.x, m_pos.y,
|
||||
m_overlap->width(), m_overlap->height());
|
||||
|
||||
Manager::getDefault()->dirtyRect(bounds());
|
||||
|
||||
m_display->dirtyRect(bounds());
|
||||
m_captured = nullptr;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
@ -20,6 +20,7 @@ namespace os {
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class Display;
|
||||
|
||||
class Overlay;
|
||||
using OverlayRef = base::Ref<Overlay>;
|
||||
@ -31,7 +32,8 @@ namespace ui {
|
||||
MouseZOrder = 5000
|
||||
};
|
||||
|
||||
Overlay(const os::SurfaceRef& overlaySurface,
|
||||
Overlay(Display* display,
|
||||
const os::SurfaceRef& overlaySurface,
|
||||
const gfx::Point& pos,
|
||||
ZOrder zorder = NormalZOrder);
|
||||
~Overlay();
|
||||
@ -41,7 +43,7 @@ namespace ui {
|
||||
const gfx::Point& position() const { return m_pos; }
|
||||
gfx::Rect bounds() const;
|
||||
|
||||
void captureOverlappedArea(os::Surface* screen);
|
||||
void captureOverlappedArea();
|
||||
void restoreOverlappedArea(const gfx::Rect& restoreBounds);
|
||||
|
||||
void drawOverlay();
|
||||
@ -52,6 +54,7 @@ namespace ui {
|
||||
}
|
||||
|
||||
private:
|
||||
Display* m_display;
|
||||
os::SurfaceRef m_surface;
|
||||
os::SurfaceRef m_overlap;
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
#include "ui/overlay_manager.h"
|
||||
|
||||
#include "os/surface.h"
|
||||
#include "os/window.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/overlay.h"
|
||||
|
||||
@ -68,11 +66,6 @@ void OverlayManager::restoreOverlappedAreas(const gfx::Rect& restoreBounds)
|
||||
if (m_overlays.empty())
|
||||
return;
|
||||
|
||||
// TODO can we remove this?
|
||||
Manager* manager = Manager::getDefault();
|
||||
if (!manager)
|
||||
return;
|
||||
|
||||
for (auto& overlay : *this)
|
||||
overlay->restoreOverlappedArea(restoreBounds);
|
||||
}
|
||||
@ -82,15 +75,8 @@ void OverlayManager::drawOverlays()
|
||||
if (m_overlays.empty())
|
||||
return;
|
||||
|
||||
Manager* manager = Manager::getDefault();
|
||||
if (!manager)
|
||||
return;
|
||||
|
||||
os::Surface* windowSurface = manager->nativeWindow()->surface();
|
||||
os::SurfaceLock lock(windowSurface);
|
||||
|
||||
for (auto& overlay : *this)
|
||||
overlay->captureOverlappedArea(windowSurface);
|
||||
overlay->captureOverlappedArea();
|
||||
|
||||
for (auto& overlay : *this)
|
||||
overlay->drawOverlay();
|
||||
|
@ -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-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include "base/clamp.h"
|
||||
#include "os/font.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/size_hint_event.h"
|
||||
#include "ui/system.h"
|
||||
|
@ -36,17 +36,15 @@ namespace ui {
|
||||
base::thread::native_id_type main_gui_thread;
|
||||
|
||||
// Current mouse cursor type.
|
||||
|
||||
static CursorType mouse_cursor_type = kOutsideDisplay;
|
||||
static const Cursor* mouse_cursor_custom = nullptr;
|
||||
static const Cursor* mouse_cursor = nullptr;
|
||||
static os::Window* mouse_window = nullptr;
|
||||
static Display* mouse_display = nullptr;
|
||||
static OverlayRef mouse_cursor_overlay = nullptr;
|
||||
static bool use_native_mouse_cursor = true;
|
||||
static bool support_native_custom_cursor = false;
|
||||
|
||||
// Mouse information (button and position).
|
||||
|
||||
static gfx::Point m_mouse_pos;
|
||||
static int mouse_cursor_scale = 1;
|
||||
|
||||
@ -58,7 +56,9 @@ static void update_mouse_overlay(const Cursor* cursor)
|
||||
|
||||
if (mouse_cursor && mouse_scares == 0) {
|
||||
if (!mouse_cursor_overlay) {
|
||||
ASSERT(mouse_display);
|
||||
mouse_cursor_overlay = base::make_ref<Overlay>(
|
||||
mouse_display,
|
||||
mouse_cursor->getSurface(),
|
||||
get_mouse_position(),
|
||||
Overlay::MouseZOrder);
|
||||
@ -83,20 +83,22 @@ static bool update_custom_native_cursor(const Cursor* cursor)
|
||||
|
||||
// Check if we can use a custom native mouse in this platform
|
||||
if (support_native_custom_cursor &&
|
||||
mouse_window) {
|
||||
mouse_display) {
|
||||
os::Window* nativeWindow = mouse_display->nativeWindow();
|
||||
|
||||
if (cursor) {
|
||||
result = mouse_window->setNativeMouseCursor(
|
||||
result = nativeWindow->setNativeMouseCursor(
|
||||
// The surface is already scaled by guiscale()
|
||||
cursor->getSurface().get(),
|
||||
cursor->getFocus(),
|
||||
// We scale the cursor by the os::Display scale
|
||||
mouse_window->scale() * mouse_cursor_scale);
|
||||
nativeWindow->scale() * mouse_cursor_scale);
|
||||
}
|
||||
else if (mouse_cursor_type == kOutsideDisplay) {
|
||||
result = mouse_window->setNativeMouseCursor(os::NativeCursor::Arrow);
|
||||
result = nativeWindow->setNativeMouseCursor(os::NativeCursor::Arrow);
|
||||
}
|
||||
else {
|
||||
result = mouse_window->setNativeMouseCursor(os::NativeCursor::Hidden);
|
||||
result = nativeWindow->setNativeMouseCursor(os::NativeCursor::Hidden);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,8 +148,8 @@ static void update_mouse_cursor()
|
||||
}
|
||||
|
||||
// Set native cursor
|
||||
if (mouse_window) {
|
||||
bool ok = mouse_window->setNativeMouseCursor(nativeCursor);
|
||||
if (mouse_display) {
|
||||
bool ok = mouse_display->nativeWindow()->setNativeMouseCursor(nativeCursor);
|
||||
|
||||
// It looks like the specific native cursor is not supported,
|
||||
// so we can should use the internal overlay (even when we
|
||||
@ -166,7 +168,8 @@ static void update_mouse_cursor()
|
||||
}
|
||||
|
||||
// Try to use a custom native cursor if it's possible
|
||||
if (nativeCursor == os::NativeCursor::Hidden &&
|
||||
if (mouse_display &&
|
||||
nativeCursor == os::NativeCursor::Hidden &&
|
||||
!update_custom_native_cursor(cursor)) {
|
||||
// Or an overlay as last resource
|
||||
update_mouse_overlay(cursor);
|
||||
@ -207,7 +210,7 @@ UISystem::~UISystem()
|
||||
|
||||
details::exitWidgets();
|
||||
|
||||
_internal_set_mouse_window(nullptr);
|
||||
_internal_set_mouse_display(nullptr);
|
||||
if (!update_custom_native_cursor(nullptr))
|
||||
update_mouse_overlay(nullptr);
|
||||
|
||||
@ -215,29 +218,24 @@ UISystem::~UISystem()
|
||||
g_instance = nullptr;
|
||||
}
|
||||
|
||||
void _internal_set_mouse_window(os::Window* window)
|
||||
void _internal_set_mouse_display(Display* display)
|
||||
{
|
||||
CursorType cursor = get_mouse_cursor();
|
||||
set_mouse_cursor(kNoCursor);
|
||||
mouse_window = window;
|
||||
if (window)
|
||||
mouse_display = display;
|
||||
if (display)
|
||||
set_mouse_cursor(cursor); // Restore mouse cursor
|
||||
}
|
||||
|
||||
int display_w()
|
||||
void _internal_free_mouse_display(Display* display)
|
||||
{
|
||||
if (mouse_window)
|
||||
return mouse_window->width() / mouse_window->scale();
|
||||
else
|
||||
return 1;
|
||||
if (mouse_display == display)
|
||||
_internal_set_mouse_display(nullptr);
|
||||
}
|
||||
|
||||
int display_h()
|
||||
gfx::Size get_desktop_size()
|
||||
{
|
||||
if (mouse_window)
|
||||
return mouse_window->height() / mouse_window->scale();
|
||||
else
|
||||
return 1;
|
||||
return Manager::getDefault()->display()->size();
|
||||
}
|
||||
|
||||
void set_clipboard_text(const std::string& text)
|
||||
@ -331,8 +329,8 @@ const gfx::Point& get_mouse_position()
|
||||
|
||||
void set_mouse_position(const gfx::Point& newPos)
|
||||
{
|
||||
if (mouse_window)
|
||||
mouse_window->setMousePosition(newPos);
|
||||
if (mouse_display)
|
||||
mouse_display->nativeWindow()->setMousePosition(newPos);
|
||||
|
||||
_internal_set_mouse_position(newPos);
|
||||
}
|
||||
|
@ -16,12 +16,11 @@
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace os { class Window; }
|
||||
|
||||
namespace ui {
|
||||
|
||||
class ClipboardDelegate;
|
||||
class Cursor;
|
||||
class Display;
|
||||
class Widget;
|
||||
|
||||
class UISystem {
|
||||
@ -41,8 +40,7 @@ namespace ui {
|
||||
ClipboardDelegate* m_clipboardDelegate;
|
||||
};
|
||||
|
||||
int display_w();
|
||||
int display_h();
|
||||
gfx::Size get_desktop_size();
|
||||
|
||||
void set_clipboard_text(const std::string& text);
|
||||
bool get_clipboard_text(std::string& text);
|
||||
@ -61,7 +59,8 @@ namespace ui {
|
||||
void hide_mouse_cursor();
|
||||
void show_mouse_cursor();
|
||||
|
||||
void _internal_set_mouse_window(os::Window* window);
|
||||
void _internal_set_mouse_display(Display* display);
|
||||
void _internal_free_mouse_display(Display* display);
|
||||
void _internal_no_mouse_position();
|
||||
void _internal_set_mouse_position(const gfx::Point& newPos);
|
||||
|
||||
|
@ -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-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -122,7 +122,11 @@ void TooltipManager::onTick()
|
||||
if (!arrowAlign)
|
||||
target.setOrigin(ui::get_mouse_position()+12*guiscale());
|
||||
|
||||
if (m_tipWindow->pointAt(arrowAlign, target)) {
|
||||
if (m_tipWindow->pointAt(arrowAlign,
|
||||
target,
|
||||
m_target.widget->display())) {
|
||||
// TODO create a native transparent window for the tooltip
|
||||
m_tipWindow->setDisplay(m_target.widget->display());
|
||||
m_tipWindow->openWindow();
|
||||
}
|
||||
else {
|
||||
@ -161,7 +165,9 @@ void TipWindow::setCloseOnKeyDown(bool state)
|
||||
m_closeOnKeyDown = state;
|
||||
}
|
||||
|
||||
bool TipWindow::pointAt(int arrowAlign, const gfx::Rect& target)
|
||||
bool TipWindow::pointAt(int arrowAlign,
|
||||
const gfx::Rect& target,
|
||||
const ui::Display* display)
|
||||
{
|
||||
// TODO merge this code with the new ui::fit_bounds() algorithm
|
||||
|
||||
@ -212,8 +218,9 @@ bool TipWindow::pointAt(int arrowAlign, const gfx::Rect& target)
|
||||
break;
|
||||
}
|
||||
|
||||
x = base::clamp(x, 0, ui::display_w()-w);
|
||||
y = base::clamp(y, 0, ui::display_h()-h);
|
||||
auto displayBounds = display->bounds();
|
||||
x = base::clamp(x, displayBounds.x, displayBounds.x2()-w);
|
||||
y = base::clamp(y, displayBounds.y, displayBounds.y2()-h);
|
||||
|
||||
if (m_target.intersects(gfx::Rect(x, y, w, h))) {
|
||||
switch (trycount) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -18,6 +19,7 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Display;
|
||||
class TextBox;
|
||||
class TipWindow;
|
||||
|
||||
@ -70,7 +72,9 @@ namespace ui {
|
||||
|
||||
// Returns false there is no enough screen space to show the
|
||||
// window.
|
||||
bool pointAt(int arrowAlign, const gfx::Rect& target);
|
||||
bool pointAt(int arrowAlign,
|
||||
const gfx::Rect& target,
|
||||
const ui::Display* display);
|
||||
|
||||
TextBox* textBox() const { return m_textBox; }
|
||||
|
||||
|
@ -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,6 +19,7 @@
|
||||
#include "ui/component.h"
|
||||
#include "ui/cursor.h"
|
||||
#include "ui/cursor_type.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/entry.h"
|
||||
#include "ui/event.h"
|
||||
#include "ui/fit_bounds.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.
|
||||
@ -13,8 +13,8 @@
|
||||
|
||||
#include "base/clamp.h"
|
||||
#include "gfx/size.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/move_region.h"
|
||||
#include "ui/resize_event.h"
|
||||
@ -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 <algorithm>
|
||||
@ -289,9 +289,9 @@ void View::onSetViewScroll(const gfx::Point& pt)
|
||||
|
||||
// Remove invalid region in the screen (areas that weren't
|
||||
// re-painted yet)
|
||||
Manager* manager = this->manager();
|
||||
if (manager)
|
||||
validRegion -= manager->getInvalidRegion();
|
||||
Display* display = this->display();
|
||||
if (display)
|
||||
validRegion -= display->getInvalidRegion();
|
||||
|
||||
// Add extra regions that cannot be scrolled (this can be customized
|
||||
// by subclassing ui::View). We use two ScrollRegionEvent, this
|
||||
@ -327,27 +327,25 @@ void View::onSetViewScroll(const gfx::Point& pt)
|
||||
invalidRegion -= movable; // Remove the moved region as invalid
|
||||
movable.offset(-delta);
|
||||
|
||||
ui::move_region(manager, movable, delta.x, delta.y);
|
||||
ui::move_region(display, movable, delta.x, delta.y);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SCROLL_EVENTS
|
||||
// Paint invalid region with red fill
|
||||
{
|
||||
auto display = manager->getDisplay();
|
||||
if (display)
|
||||
display->invalidateRegion(
|
||||
gfx::Region(gfx::Rect(0, 0, display_w(), display_h())));
|
||||
if (auto nativeWindow = display->nativeWindow()) {
|
||||
nativeWindow->invalidateRegion(gfx::Region(display->bounds()));
|
||||
base::this_thread::sleep_for(0.002);
|
||||
{
|
||||
os::Surface* surface = display->getSurface();
|
||||
os::Surface* surface = nativeWindow->surface();
|
||||
os::SurfaceLock lock(surface);
|
||||
os::Paint p;
|
||||
p.style(os::Paint::Fill);
|
||||
p.color(gfx::rgba(255, 0, 0));
|
||||
for (const auto& rc : invalidRegion)
|
||||
surface->fillRect(gfx::rgba(255, 0, 0), rc);
|
||||
surface->drawRect(rc, p);
|
||||
}
|
||||
if (display)
|
||||
display->invalidateRegion(
|
||||
gfx::Region(gfx::Rect(0, 0, display_w(), display_h())));
|
||||
base::this_thread::sleep_for(0.002);
|
||||
nativeWindow->invalidateRegion(gfx::Region(display->bounds()));
|
||||
base::this_thread::sleep_for(0.02);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -420,6 +420,14 @@ Manager* Widget::manager() const
|
||||
return Manager::getDefault();
|
||||
}
|
||||
|
||||
Display* Widget::display() const
|
||||
{
|
||||
if (Window* win = this->window())
|
||||
return win->display();
|
||||
else
|
||||
return manager()->display();
|
||||
}
|
||||
|
||||
int Widget::getChildIndex(Widget* child)
|
||||
{
|
||||
auto it = std::find(m_children.begin(), m_children.end(), child);
|
||||
@ -754,36 +762,31 @@ void Widget::getRegion(gfx::Region& region)
|
||||
|
||||
void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags)
|
||||
{
|
||||
Widget* window, *manager, *view;
|
||||
|
||||
getRegion(region);
|
||||
|
||||
// Cut the top windows areas
|
||||
if (flags & kCutTopWindows) {
|
||||
window = this->window();
|
||||
manager = (window ? window->manager(): nullptr);
|
||||
Window* window = this->window();
|
||||
Display* display = this->display();
|
||||
|
||||
while (manager) {
|
||||
const WidgetsList& windows_list = manager->children();
|
||||
WidgetsList::const_reverse_iterator it =
|
||||
std::find(windows_list.rbegin(), windows_list.rend(), window);
|
||||
const auto& uiWindows = display->getWindows();
|
||||
|
||||
if (!windows_list.empty() &&
|
||||
window != windows_list.front() &&
|
||||
it != windows_list.rend()) {
|
||||
// Subtract the rectangles
|
||||
for (++it; it != windows_list.rend(); ++it) {
|
||||
if (!(*it)->isVisible())
|
||||
continue;
|
||||
// Reverse iterator
|
||||
auto it = std::find(uiWindows.rbegin(),
|
||||
uiWindows.rend(), window);
|
||||
|
||||
Region reg1;
|
||||
(*it)->getRegion(reg1);
|
||||
region.createSubtraction(region, reg1);
|
||||
}
|
||||
if (!uiWindows.empty() &&
|
||||
window != uiWindows.front() &&
|
||||
it != uiWindows.rend()) {
|
||||
// Subtract the rectangles of each window
|
||||
for (++it; it != uiWindows.rend(); ++it) {
|
||||
if (!(*it)->isVisible())
|
||||
continue;
|
||||
|
||||
Region reg1;
|
||||
(*it)->getRegion(reg1);
|
||||
region -= reg1;
|
||||
}
|
||||
|
||||
window = manager->window();
|
||||
manager = (window ? window->manager(): nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -804,7 +807,7 @@ void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags)
|
||||
else {
|
||||
reg1.createIntersection(reg2, reg3);
|
||||
}
|
||||
region.createSubtraction(region, reg1);
|
||||
region -= reg1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -813,36 +816,35 @@ void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags)
|
||||
if (!hasFlags(DECORATIVE)) {
|
||||
Widget* p = this->parent();
|
||||
while (p) {
|
||||
region.createIntersection(
|
||||
region, Region(p->childrenBounds()));
|
||||
region &= Region(p->childrenBounds());
|
||||
p = p->parent();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Widget* p = parent();
|
||||
if (p) {
|
||||
region.createIntersection(
|
||||
region, Region(p->bounds()));
|
||||
region &= Region(p->bounds());
|
||||
}
|
||||
}
|
||||
|
||||
// Limit to the manager area
|
||||
window = this->window();
|
||||
manager = (window ? window->manager(): nullptr);
|
||||
{
|
||||
Window* window = this->window();
|
||||
Manager* manager = (window ? window->manager(): nullptr);
|
||||
while (manager) {
|
||||
View* view = View::getView(manager);
|
||||
|
||||
while (manager) {
|
||||
view = View::getView(manager);
|
||||
Rect cpos;
|
||||
if (view)
|
||||
cpos = static_cast<View*>(view)->viewportBounds();
|
||||
else
|
||||
cpos = manager->childrenBounds();
|
||||
|
||||
Rect cpos;
|
||||
if (view)
|
||||
cpos = static_cast<View*>(view)->viewportBounds();
|
||||
else
|
||||
cpos = manager->childrenBounds();
|
||||
region &= Region(cpos);
|
||||
|
||||
region.createIntersection(region, Region(cpos));
|
||||
|
||||
window = manager->window();
|
||||
manager = (window ? window->manager(): nullptr);
|
||||
window = manager->window();
|
||||
manager = (window ? window->manager(): nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -980,6 +982,7 @@ void Widget::flushRedraw()
|
||||
processing.push(this);
|
||||
}
|
||||
|
||||
Display* display = this->display();
|
||||
Manager* manager = this->manager();
|
||||
ASSERT(manager);
|
||||
if (!manager)
|
||||
@ -1018,13 +1021,14 @@ void Widget::flushRedraw()
|
||||
for (c=0; c<nrects; ++c, ++it, --count) {
|
||||
// Create the draw message
|
||||
msg = new PaintMessage(count, *it);
|
||||
msg->setDisplay(display);
|
||||
msg->setRecipient(widget);
|
||||
|
||||
// Enqueue the draw message
|
||||
manager->enqueueMessage(msg);
|
||||
}
|
||||
|
||||
manager->addInvalidRegion(widget->m_updateRegion);
|
||||
display->addInvalidRegion(widget->m_updateRegion);
|
||||
widget->m_updateRegion.clear();
|
||||
}
|
||||
}
|
||||
@ -1040,6 +1044,8 @@ void Widget::paint(Graphics* graphics,
|
||||
std::queue<Widget*> processing;
|
||||
processing.push(this);
|
||||
|
||||
Display* display = this->display();
|
||||
|
||||
while (!processing.empty()) {
|
||||
Widget* widget = processing.front();
|
||||
processing.pop();
|
||||
@ -1059,17 +1065,17 @@ void Widget::paint(Graphics* graphics,
|
||||
region.createIntersection(region, drawRegion);
|
||||
|
||||
Graphics graphics2(
|
||||
display,
|
||||
base::AddRef(graphics->getInternalSurface()),
|
||||
widget->bounds().x,
|
||||
widget->bounds().y);
|
||||
graphics2.setFont(AddRef(widget->font()));
|
||||
|
||||
for (Region::const_iterator
|
||||
it = region.begin(),
|
||||
end = region.end(); it != end; ++it) {
|
||||
IntersectClip clip(&graphics2, Rect(*it).offset(
|
||||
-widget->bounds().x,
|
||||
-widget->bounds().y));
|
||||
for (const gfx::Rect& rc : region) {
|
||||
IntersectClip clip(&graphics2,
|
||||
Rect(rc).offset(
|
||||
-widget->bounds().x,
|
||||
-widget->bounds().y));
|
||||
widget->paintEvent(&graphics2, isBg);
|
||||
}
|
||||
}
|
||||
@ -1089,14 +1095,22 @@ bool Widget::paintEvent(Graphics* graphics,
|
||||
enableFlags(HIDDEN);
|
||||
|
||||
if (parent()) {
|
||||
gfx::Region rgn(parent()->bounds());
|
||||
rgn.createIntersection(
|
||||
rgn,
|
||||
gfx::Region(
|
||||
if (parent()->display() == display()) {
|
||||
gfx::Region rgn(parent()->bounds());
|
||||
rgn &= gfx::Region(
|
||||
graphics->getClipBounds().offset(
|
||||
graphics->getInternalDeltaX(),
|
||||
graphics->getInternalDeltaY())));
|
||||
parent()->paint(graphics, rgn, true);
|
||||
graphics->getInternalDeltaY()));
|
||||
parent()->paint(graphics, rgn, true);
|
||||
}
|
||||
else {
|
||||
// TODO clear surface with transparent color, the following
|
||||
// line doesn't work because we have to specify the
|
||||
// SkBlendMode::kSrc mode instead of
|
||||
// SkBlendMode::kSrcOver
|
||||
|
||||
//graphics->fillRect(gfx::rgba(0, 0, 0, 0), clientBounds());
|
||||
}
|
||||
}
|
||||
|
||||
disableFlags(HIDDEN);
|
||||
@ -1152,17 +1166,19 @@ void Widget::invalidateRegion(const Region& region)
|
||||
class DeleteGraphicsAndSurface {
|
||||
public:
|
||||
DeleteGraphicsAndSurface(const gfx::Rect& clip,
|
||||
const os::SurfaceRef& surface)
|
||||
: m_pt(clip.origin()), m_surface(surface) {
|
||||
const os::SurfaceRef& surface,
|
||||
os::SurfaceRef& dst)
|
||||
: m_pt(clip.origin())
|
||||
, m_surface(surface)
|
||||
, m_dst(dst) {
|
||||
}
|
||||
|
||||
void operator()(Graphics* graphics) {
|
||||
{
|
||||
os::Surface* dst = os::instance()->defaultWindow()->surface();
|
||||
os::SurfaceLock lockSrc(m_surface.get());
|
||||
os::SurfaceLock lockDst(dst);
|
||||
os::SurfaceLock lockDst(m_dst.get());
|
||||
m_surface->blitTo(
|
||||
dst, 0, 0, m_pt.x, m_pt.y,
|
||||
m_dst.get(), 0, 0, m_pt.x, m_pt.y,
|
||||
m_surface->width(), m_surface->height());
|
||||
}
|
||||
m_surface.reset();
|
||||
@ -1172,25 +1188,27 @@ public:
|
||||
private:
|
||||
gfx::Point m_pt;
|
||||
os::SurfaceRef m_surface;
|
||||
os::SurfaceRef m_dst;
|
||||
};
|
||||
|
||||
GraphicsPtr Widget::getGraphics(const gfx::Rect& clip)
|
||||
{
|
||||
GraphicsPtr graphics;
|
||||
os::SurfaceRef surface;
|
||||
os::Surface* defaultSurface = os::instance()->defaultWindow()->surface();
|
||||
Display* display = this->display();
|
||||
os::SurfaceRef dstSurface = AddRef(display->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()->makeSurface(clip.w, clip.h);
|
||||
graphics.reset(new Graphics(surface, -clip.x, -clip.y),
|
||||
DeleteGraphicsAndSurface(clip, surface));
|
||||
if (isDoubleBuffered() && dstSurface->isDirectToScreen()) {
|
||||
os::SurfaceRef surface =
|
||||
os::instance()->makeSurface(clip.w, clip.h);
|
||||
graphics.reset(new Graphics(display, surface, -clip.x, -clip.y),
|
||||
DeleteGraphicsAndSurface(clip, surface,
|
||||
dstSurface));
|
||||
}
|
||||
// In other case, we can draw directly onto the screen.
|
||||
else {
|
||||
surface = AddRef(defaultSurface);
|
||||
graphics.reset(new Graphics(surface, bounds().x, bounds().y));
|
||||
graphics.reset(new Graphics(display, dstSurface, bounds().x, bounds().y));
|
||||
}
|
||||
|
||||
graphics->setFont(AddRef(font()));
|
||||
|
@ -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-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Display;
|
||||
class InitThemeEvent;
|
||||
class KeyMessage;
|
||||
class LoadLayoutEvent;
|
||||
@ -161,6 +162,7 @@ namespace ui {
|
||||
Window* window() const;
|
||||
Widget* parent() const { return m_parent; }
|
||||
Manager* manager() const;
|
||||
Display* display() const;
|
||||
|
||||
// Returns a list of children.
|
||||
const WidgetsList& children() const { return m_children; }
|
||||
|
@ -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.
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "gfx/size.h"
|
||||
#include "ui/button.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/graphics.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/label.h"
|
||||
@ -107,6 +108,7 @@ protected:
|
||||
|
||||
Window::Window(Type type, const std::string& text)
|
||||
: Widget(kWindowWidget)
|
||||
, m_display(nullptr)
|
||||
, m_closer(nullptr)
|
||||
, m_titleLabel(nullptr)
|
||||
, m_closeButton(nullptr)
|
||||
@ -133,6 +135,27 @@ Window::~Window()
|
||||
manager()->_closeWindow(this, isVisible());
|
||||
}
|
||||
|
||||
Display* Window::display() const
|
||||
{
|
||||
if (m_display)
|
||||
return m_display;
|
||||
else if (auto man = manager())
|
||||
return man->display();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Window::setDisplay(Display* display)
|
||||
{
|
||||
if (m_display)
|
||||
m_display->removeWindow(this);
|
||||
|
||||
m_display = display;
|
||||
|
||||
if (m_display)
|
||||
m_display->addWindow(this);
|
||||
}
|
||||
|
||||
void Window::setAutoRemap(bool state)
|
||||
{
|
||||
m_isAutoRemap = state;
|
||||
@ -658,12 +681,13 @@ void Window::moveWindow(const gfx::Rect& rect, bool use_blit)
|
||||
moveableRegion.createIntersection(oldDrawableRegion, reg1);
|
||||
|
||||
// Move the window's graphics
|
||||
ScreenGraphics g;
|
||||
Display* display = this->display();
|
||||
ScreenGraphics g(display);
|
||||
hide_mouse_cursor();
|
||||
{
|
||||
IntersectClip clip(&g, man_pos);
|
||||
if (clip) {
|
||||
ui::move_region(manager, moveableRegion, dx, dy);
|
||||
ui::move_region(display, moveableRegion, dx, dy);
|
||||
}
|
||||
}
|
||||
show_mouse_cursor();
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -27,6 +28,9 @@ namespace ui {
|
||||
explicit Window(Type type, const std::string& text = "");
|
||||
~Window();
|
||||
|
||||
Display* display() const;
|
||||
void setDisplay(Display* display);
|
||||
|
||||
Widget* closer() const { return m_closer; }
|
||||
|
||||
void setAutoRemap(bool state);
|
||||
@ -77,6 +81,7 @@ namespace ui {
|
||||
void limitSize(int* w, int* h);
|
||||
void moveWindow(const gfx::Rect& rect, bool use_blit);
|
||||
|
||||
Display* m_display;
|
||||
Widget* m_closer;
|
||||
Label* m_titleLabel;
|
||||
ButtonBase* m_closeButton;
|
||||
|
Loading…
x
Reference in New Issue
Block a user