commit 1f1e3ca9d983389022b0257e48a250793136764d
parent 20199dfd053e2a00777f6b3b10de82852a8cf8f5
Author: falkTX <falktx@falktx.com>
Date: Sun, 16 May 2021 17:52:21 +0100
Implement custom timers
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
8 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/Makefile.base.mk b/Makefile.base.mk
@@ -225,7 +225,10 @@ HAVE_OPENGL = true
else
HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo 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
@@ -254,6 +257,19 @@ ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
ifeq ($(HAVE_X11),true)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags 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
diff --git a/dgl/Application.hpp b/dgl/Application.hpp
@@ -77,12 +77,12 @@ public:
Idle callbacks trigger right after OS event handling and Window idle events (within the same cycle).
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().
*/
- void removeIdleCallback(IdleCallback* const callback);
+ void removeIdleCallback(IdleCallback* callback);
private:
struct PrivateData;
diff --git a/dgl/TopLevelWidget.hpp b/dgl/TopLevelWidget.hpp
@@ -67,6 +67,8 @@ public:
Window& getWindow() const noexcept;
// 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;
void repaint() noexcept;
void repaint(const Rectangle<uint>& rect) noexcept;
diff --git a/dgl/Window.hpp b/dgl/Window.hpp
@@ -191,6 +191,25 @@ public:
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.
*/
Application& getApp() const noexcept;
diff --git a/dgl/src/TopLevelWidget.cpp b/dgl/src/TopLevelWidget.cpp
@@ -40,6 +40,16 @@ Window& TopLevelWidget::getWindow() const noexcept
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
{
return pData->window.getScaleFactor();
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -153,6 +153,20 @@ void Window::setIgnoringKeyRepeat(const bool ignore) noexcept
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
{
return pData->app;
diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp
@@ -348,6 +348,31 @@ void Window::PrivateData::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
void Window::PrivateData::startModal()
@@ -740,6 +765,8 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Timer triggered, a #PuglEventTimer
case PUGL_TIMER:
+ if (IdleCallback* const idleCallback = reinterpret_cast<IdleCallback*>(event->timer.id))
+ idleCallback->idleCallback();
break;
///< Recursive loop entered, a #PuglEventLoopEnter
diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp
@@ -136,6 +136,9 @@ struct Window::PrivateData : IdleCallback {
void idleCallback() override;
+ bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs);
+ bool removeIdleCallback(IdleCallback* callback);
+
// modal handling
void startModal();
void stopModal();
@@ -152,6 +155,7 @@ struct Window::PrivateData : IdleCallback {
void onPuglMouse(const Events::MouseEvent& ev);
void onPuglMotion(const Events::MotionEvent& ev);
void onPuglScroll(const Events::ScrollEvent& ev);
+ void onPuglTimer(IdleCallback* idleCallback);
// Pugl event handling entry point
static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event);