diff options
Diffstat (limited to 'src/drivers/Base')
| -rw-r--r-- | src/drivers/Base/Fl_Base_Pen_Events.H | 116 | ||||
| -rw-r--r-- | src/drivers/Base/Fl_Base_Pen_Events.cxx | 148 |
2 files changed, 264 insertions, 0 deletions
diff --git a/src/drivers/Base/Fl_Base_Pen_Events.H b/src/drivers/Base/Fl_Base_Pen_Events.H new file mode 100644 index 000000000..ba4882d0b --- /dev/null +++ b/src/drivers/Base/Fl_Base_Pen_Events.H @@ -0,0 +1,116 @@ +// +// Definition of default Pen/Tablet event driver. +// +// Copyright 2025 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + + +#ifndef FL_BASE_PEN_EVENTS_H +#define FL_BASE_PEN_EVENTS_H + +#include <config.h> +#include <FL/core/pen_events.H> +#include <FL/Fl.H> + +#include <map> +#include <memory> + + +class Fl_Widget; + +namespace Fl { + +namespace Pen { + +/* Pen event data storage. + A second storage may be useful if the driver needs to collect pen data + from multiple events, or if one system event can send multiple FLTK events. +*/ +typedef struct EventData { + double x { 0.0 }; + double y { 0.0 }; + double rx { 0.0 }; + double ry { 0.0 }; + double tilt_x { 0.0 }; + double tilt_y { 0.0 }; + double pressure { 1.0 }; + double proximity { 0.0 }; + double barrel_pressure { 0.0 }; + double twist { 0.0 }; + int pen_id { 0 }; + Fl::Pen::State state { (Fl::Pen::State)0 }; + Fl::Pen::State trigger { (Fl::Pen::State)0 }; +} EventData; + +extern EventData e; + + +/* + Widgets and windows must subscribe to pen events. This is to reduce the amount + of events sent into the widget hierarchy. + + Usually there is a pretty small number of subscribers, so looping through the + subscriber list should not be an issue. + + All subscribers track their widget. If a widget is deleted while subscribed, + including during event handling, the driver will remove the subscription. + There is no need to explicitly unsubscribe. + */ +class Subscriber : public Fl_Widget_Tracker { +public: + Subscriber(Fl_Widget *w) : Fl_Widget_Tracker(w) { } +}; + + +/* + Manage a list of subscribers. + */ +class SubscriberList : public std::map<Fl_Widget*, std::shared_ptr<Subscriber>> { +public: + SubscriberList() = default; + void cleanup(); + std::shared_ptr<Subscriber> add(Fl_Widget *w); + void remove(Fl_Widget *w); +}; + +extern SubscriberList subscriber_list_; +extern std::shared_ptr<Subscriber> pushed_; +extern std::shared_ptr<Subscriber> below_pen_; + +/* The base driver for calls by apps into the pen system. + + Most traffic is generated by system events. The data is then converted + for the FLTK API and stored in Fl::Pen::e. The Pen interface then sends + the appropriate FLTK events to the subscribers. + + This driver class manages calls from the app into FLTK, including subscriber + management and queries for driver an pen abilities. +*/ +class Driver { +public: + Driver() = default; + virtual void subscribe(Fl_Widget* widget); + virtual void unsubscribe(Fl_Widget* widget); + virtual void release(); + virtual Trait traits(); + virtual Trait pen_traits(int pen_id); +}; + +extern Driver& driver; + +} // namespace Pen + +} // namespace Fl + + +#endif // FL_BASE_PEN_EVENTS_H diff --git a/src/drivers/Base/Fl_Base_Pen_Events.cxx b/src/drivers/Base/Fl_Base_Pen_Events.cxx new file mode 100644 index 000000000..f4ebbd8ad --- /dev/null +++ b/src/drivers/Base/Fl_Base_Pen_Events.cxx @@ -0,0 +1,148 @@ +// +// Implementation of default Pen/Tablet event driver. +// +// Copyright 2025 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include "src/drivers/Base/Fl_Base_Pen_Events.H" + + +class Fl_Widget; + + +namespace Fl { + +namespace Pen { + +EventData e; +SubscriberList subscriber_list_; +std::shared_ptr<Subscriber> pushed_; +std::shared_ptr<Subscriber> below_pen_; + +} // namespace Pen + +} // namespace Fl + + +using namespace Fl::Pen; + + +// ---- SubscriberList implementation ------------------------------------------ + +/* Remove subscribers that have a nullptr as a widget */ +void Fl::Pen::SubscriberList::cleanup() { + for (auto it = begin(); it != end(); ) { + if (!it->second->widget()) { + it = erase(it); + } else { + ++it; + } + } +} + +/* Add a new subscriber, or return an existing one. */ +std::shared_ptr<Subscriber> Fl::Pen::SubscriberList::add(Fl_Widget *w) { + cleanup(); + auto it = find(w); + if (it == end()) { + auto sub = std::make_shared<Subscriber>(w); + insert(std::make_pair(w, sub)); + return sub; + } else { + return it->second; + } +} + +/* Remove a subscriber from the list. */ +void Fl::Pen::SubscriberList::remove(Fl_Widget *w) { + auto it = find(w); + if (it != end()) { + it->second->clear(); + erase(it); + } +} + +// ---- Driver implementation -------------------------------------------------- +// Override the methods below to handle subscriptions and queries by user apps. + +void Fl::Pen::Driver::subscribe(Fl_Widget* widget) { + if (widget == nullptr) return; + subscriber_list_.add(widget); +} + +void Fl::Pen::Driver::unsubscribe(Fl_Widget* widget) { + if (widget == nullptr) return; + subscriber_list_.remove(widget); +} + +void Fl::Pen::Driver::release() { + pushed_ = nullptr; + below_pen_ = nullptr; +} + +Trait Fl::Pen::Driver::traits() { + return Trait::NONE; +} + +Trait Fl::Pen::Driver::pen_traits(int pen_id) { + (void)pen_id; + return Trait::NONE; +} + +// ---- Fl::Pen API ------------------------------------------------------------ + +void Fl::Pen::subscribe(Fl_Widget* widget) { + driver.subscribe(widget); +} + +void Fl::Pen::unsubscribe(Fl_Widget* widget) { + driver.unsubscribe(widget); +} + +void Fl::Pen::release() { + driver.release(); +} + +Trait Fl::Pen::driver_traits() { + return driver.traits(); +} + +Trait Fl::Pen::pen_traits(int pen_id) { + return driver.pen_traits(pen_id); +} + +double Fl::Pen::event_x() { return e.x; } + +double Fl::Pen::event_y() { return e.y; } + +double Fl::Pen::event_x_root() { return e.rx; } + +double Fl::Pen::event_y_root() { return e.ry; } + +int Fl::Pen::event_pen_id() { return e.pen_id; } + +double Fl::Pen::event_pressure() { return e.pressure; } + +double Fl::Pen::event_barrel_pressure() { return e.barrel_pressure; } + +double Fl::Pen::event_tilt_x() { return e.tilt_x; } + +double Fl::Pen::event_tilt_y() { return e.tilt_y; } + +double Fl::Pen::event_twist() { return e.twist; } + +double Fl::Pen::event_proximity() { return e.proximity; } + +State Fl::Pen::event_state() { return e.state; } + +State Fl::Pen::event_trigger() { return e.trigger; } |
