@@ -225,7 +225,10 @@ HAVE_OPENGL = true | |||||
else | else | ||||
HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true) | HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true) | ||||
ifneq ($(HAIKU),true) | ifneq ($(HAIKU),true) | ||||
HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true) | |||||
HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true) | |||||
HAVE_XCURSOR = $(shell $(PKG_CONFIG) --exists xcursor && echo true) | |||||
HAVE_XEXT = $(shell $(PKG_CONFIG) --exists xext && echo true) | |||||
HAVE_XRANDR = $(shell $(PKG_CONFIG) --exists xrandr && echo true) | |||||
endif | endif | ||||
endif | endif | ||||
@@ -254,6 +257,19 @@ ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) | |||||
ifeq ($(HAVE_X11),true) | ifeq ($(HAVE_X11),true) | ||||
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) | DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) | ||||
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11) | DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11) | ||||
ifeq ($(HAVE_XCURSOR),true) | |||||
# TODO -DHAVE_XCURSOR | |||||
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xcursor) | |||||
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xcursor) | |||||
endif | |||||
ifeq ($(HAVE_XEXT),true) | |||||
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xext) -DHAVE_XEXT -DHAVE_XSYNC | |||||
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xext) | |||||
endif | |||||
ifeq ($(HAVE_XRANDR),true) | |||||
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xrandr) -DHAVE_XRANDR | |||||
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xrandr) | |||||
endif | |||||
endif | endif | ||||
endif | endif | ||||
@@ -77,12 +77,12 @@ public: | |||||
Idle callbacks trigger right after OS event handling and Window idle events (within the same cycle). | Idle callbacks trigger right after OS event handling and Window idle events (within the same cycle). | ||||
There are no guarantees in terms of timing. | There are no guarantees in terms of timing. | ||||
*/ | */ | ||||
void addIdleCallback(IdleCallback* const callback); | |||||
void addIdleCallback(IdleCallback* callback); | |||||
/** | /** | ||||
Remove an idle callback previously added via addIdleCallback(). | Remove an idle callback previously added via addIdleCallback(). | ||||
*/ | */ | ||||
void removeIdleCallback(IdleCallback* const callback); | |||||
void removeIdleCallback(IdleCallback* callback); | |||||
private: | private: | ||||
struct PrivateData; | struct PrivateData; | ||||
@@ -67,6 +67,8 @@ public: | |||||
Window& getWindow() const noexcept; | Window& getWindow() const noexcept; | ||||
// TODO group stuff after here, convenience functions present in Window class | // TODO group stuff after here, convenience functions present in Window class | ||||
bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0); | |||||
bool removeIdleCallback(IdleCallback* callback); | |||||
double getScaleFactor() const noexcept; | double getScaleFactor() const noexcept; | ||||
void repaint() noexcept; | void repaint() noexcept; | ||||
void repaint(const Rectangle<uint>& rect) noexcept; | void repaint(const Rectangle<uint>& rect) noexcept; | ||||
@@ -190,6 +190,25 @@ public: | |||||
*/ | */ | ||||
void setIgnoringKeyRepeat(bool ignore) noexcept; | void setIgnoringKeyRepeat(bool ignore) noexcept; | ||||
/** | |||||
Add a callback function to be triggered on every idle cycle or on a specific timer frequency. | |||||
You can add more than one, and remove them at anytime with removeIdleCallback(). | |||||
This can be used to perform some action at a regular interval with relatively low frequency. | |||||
If providing a timer frequency, there are a few things to note: | |||||
1. There is a platform-specific limit to the number of supported timers, and overhead associated with each, | |||||
so you should create only a few timers and perform several tasks in one if necessary. | |||||
2. This timer frequency is not guaranteed to have a resolution better than 10ms | |||||
(the maximum timer resolution on Windows) and may be rounded up if it is too short. | |||||
On X11 and MacOS, a resolution of about 1ms can usually be relied on. | |||||
*/ | |||||
bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0); | |||||
/** | |||||
Remove an idle callback previously added via addIdleCallback(). | |||||
*/ | |||||
bool removeIdleCallback(IdleCallback* callback); | |||||
/** | /** | ||||
Get the application associated with this window. | Get the application associated with this window. | ||||
*/ | */ | ||||
@@ -40,6 +40,16 @@ Window& TopLevelWidget::getWindow() const noexcept | |||||
return pData->window; | return pData->window; | ||||
} | } | ||||
bool TopLevelWidget::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) | |||||
{ | |||||
return pData->window.addIdleCallback(callback, timerFrequencyInMs); | |||||
} | |||||
bool TopLevelWidget::removeIdleCallback(IdleCallback* const callback) | |||||
{ | |||||
return pData->window.removeIdleCallback(callback); | |||||
} | |||||
double TopLevelWidget::getScaleFactor() const noexcept | double TopLevelWidget::getScaleFactor() const noexcept | ||||
{ | { | ||||
return pData->window.getScaleFactor(); | return pData->window.getScaleFactor(); | ||||
@@ -153,6 +153,20 @@ void Window::setIgnoringKeyRepeat(const bool ignore) noexcept | |||||
puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); | puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); | ||||
} | } | ||||
bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false) | |||||
return pData->addIdleCallback(callback, timerFrequencyInMs); | |||||
} | |||||
bool Window::removeIdleCallback(IdleCallback* const callback) | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false) | |||||
return pData->removeIdleCallback(callback); | |||||
} | |||||
Application& Window::getApp() const noexcept | Application& Window::getApp() const noexcept | ||||
{ | { | ||||
return pData->app; | return pData->app; | ||||
@@ -347,6 +347,31 @@ void Window::PrivateData::idleCallback() | |||||
// modal.parent->idleCallback(); | // modal.parent->idleCallback(); | ||||
} | } | ||||
// ----------------------------------------------------------------------- | |||||
bool Window::PrivateData::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) | |||||
{ | |||||
if (timerFrequencyInMs == 0) | |||||
{ | |||||
appData->idleCallbacks.push_back(callback); | |||||
return true; | |||||
} | |||||
return puglStartTimer(view, (uintptr_t)callback, static_cast<double>(timerFrequencyInMs) / 1000.0) == PUGL_SUCCESS; | |||||
} | |||||
bool Window::PrivateData::removeIdleCallback(IdleCallback* const callback) | |||||
{ | |||||
if (std::find(appData->idleCallbacks.begin(), | |||||
appData->idleCallbacks.end(), callback) != appData->idleCallbacks.end()) | |||||
{ | |||||
appData->idleCallbacks.remove(callback); | |||||
return true; | |||||
} | |||||
return puglStopTimer(view, (uintptr_t)callback) == PUGL_SUCCESS; | |||||
} | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// modal handling | // modal handling | ||||
@@ -740,6 +765,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||||
///< Timer triggered, a #PuglEventTimer | ///< Timer triggered, a #PuglEventTimer | ||||
case PUGL_TIMER: | case PUGL_TIMER: | ||||
if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id)) | |||||
idleCallback->idleCallback(); | |||||
break; | break; | ||||
///< Recursive loop entered, a #PuglEventLoopEnter | ///< Recursive loop entered, a #PuglEventLoopEnter | ||||
@@ -136,6 +136,9 @@ struct Window::PrivateData : IdleCallback { | |||||
void idleCallback() override; | void idleCallback() override; | ||||
bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs); | |||||
bool removeIdleCallback(IdleCallback* callback); | |||||
// modal handling | // modal handling | ||||
void startModal(); | void startModal(); | ||||
void stopModal(); | void stopModal(); | ||||
@@ -152,6 +155,7 @@ struct Window::PrivateData : IdleCallback { | |||||
void onPuglMouse(const Events::MouseEvent& ev); | void onPuglMouse(const Events::MouseEvent& ev); | ||||
void onPuglMotion(const Events::MotionEvent& ev); | void onPuglMotion(const Events::MotionEvent& ev); | ||||
void onPuglScroll(const Events::ScrollEvent& ev); | void onPuglScroll(const Events::ScrollEvent& ev); | ||||
void onPuglTimer(IdleCallback* idleCallback); | |||||
// Pugl event handling entry point | // Pugl event handling entry point | ||||
static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); | static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); | ||||