44 #define ERR_GEN LOG_STREAM(err, lg::general)
47 #define LOG_DP LOG_STREAM(info, log_display)
50 #define LOG_EV LOG_STREAM(info, log_event)
51 #define DBG_EV LOG_STREAM(debug, log_event)
55 struct invoked_function_data
57 explicit invoked_function_data(
const std::function<
void(
void)>& func)
64 const std::function<void(
void)>&
f;
67 std::promise<void> finished;
78 finished.set_exception(std::current_exception());
105 static int depth = 0;
169 while(current != last) {
170 if(current !=
handlers.end() && (*current)->requires_event_focus()) {
186 if(
i !=
handlers.end() && (*i)->requires_event_focus()) {
200 if(
h->has_joined()) {
201 h->has_joined_ =
false;
204 if(
h->has_joined_global()) {
205 h->has_joined_global_ =
false;
242 , has_joined_global_(false)
252 : has_joined_(that.has_joined_)
253 , has_joined_global_(that.has_joined_global_)
259 bool found_context =
false;
262 found_context =
true;
268 if (!found_context) {
269 throw std::logic_error(
"Copy-constructing a sdl_handler that has_joined_ but can't be found by searching contexts");
354 if(members.empty()) {
358 for(
auto member : members) {
387 member->join_global();
394 member->leave_global();
424 if(foc == handlers.end()) {
430 if(foc_hand == hand) {
435 for(
auto i = handlers.rbegin();
i != handlers.rend(); ++
i) {
443 handlers.splice(handlers.end(), handlers, foc);
445 return thief_hand == hand;
457 handler->handle_window_event(event);
462 global_handler->handle_window_event(event);
487 SDL_Event temp_event;
489 int begin_ignoring = 0;
491 std::vector<SDL_Event>
events;
492 while(SDL_PollEvent(&temp_event)) {
494 static_cast<invoked_function_data*
>(temp_event.user.data1)->call();
500 if(!begin_ignoring && (
501 temp_event.type == SDL_EVENT_WINDOW_MOUSE_ENTER ||
502 temp_event.type == SDL_EVENT_WINDOW_FOCUS_GAINED)
504 begin_ignoring = poll_count;
505 }
else if(begin_ignoring > 0 &&
is_input(temp_event)) {
510 events.push_back(temp_event);
513 auto ev_it =
events.begin();
514 for(
int i = 1;
i < begin_ignoring; ++
i) {
517 ev_it =
events.erase(ev_it);
523 for(SDL_Event& event :
events) {
525 c.add_staging_handlers();
530 #ifdef MOUSE_TOUCH_EMULATION
531 switch (event.type) {
533 case SDL_EVENT_MOUSE_MOTION:
538 if(event.motion.state & SDL_BUTTON(SDL_BUTTON_RIGHT))
544 SDL_Event touch_event;
545 touch_event.type = SDL_EVENT_FINGER_MOTION;
546 touch_event.tfinger.type = SDL_EVENT_FINGER_MOTION;
547 touch_event.tfinger.timestamp =
event.motion.timestamp;
548 touch_event.tfinger.touchId = 1;
549 touch_event.tfinger.fingerId = 1;
550 touch_event.tfinger.dx =
static_cast<float>(
event.motion.xrel) /
c.x;
551 touch_event.tfinger.dy =
static_cast<float>(event.motion.yrel) /
c.y;
552 touch_event.tfinger.x =
static_cast<float>(
event.motion.x) /
c.x;
553 touch_event.tfinger.y =
static_cast<float>(event.motion.y) /
c.y;
554 touch_event.tfinger.pressure = 1;
555 ::SDL_PushEvent(&touch_event);
557 event.motion.state = SDL_BUTTON(SDL_BUTTON_LEFT);
558 event.motion.which = SDL_TOUCH_MOUSEID;
561 case SDL_EVENT_MOUSE_BUTTON_DOWN:
562 case SDL_EVENT_MOUSE_BUTTON_UP:
563 if(event.button.button == SDL_BUTTON_RIGHT)
565 event.button.button = SDL_BUTTON_LEFT;
566 event.button.which = SDL_TOUCH_MOUSEID;
571 SDL_Event touch_event;
572 touch_event.type = (
event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) ? SDL_EVENT_FINGER_DOWN : SDL_EVENT_FINGER_UP;
573 touch_event.tfinger.type = touch_event.type;
574 touch_event.tfinger.timestamp =
event.button.timestamp;
575 touch_event.tfinger.touchId = 1;
576 touch_event.tfinger.fingerId = 1;
577 touch_event.tfinger.dx = 0;
578 touch_event.tfinger.dy = 0;
579 touch_event.tfinger.x =
static_cast<float>(
event.button.x) /
c.x;
580 touch_event.tfinger.y =
static_cast<float>(event.button.y) /
c.y;
581 touch_event.tfinger.pressure = 1;
582 ::SDL_PushEvent(&touch_event);
591 if(event.type >= SDL_EVENT_WINDOW_FIRST && event.type <= SDL_EVENT_WINDOW_LAST) {
593 case SDL_EVENT_WINDOW_MOUSE_ENTER:
594 case SDL_EVENT_WINDOW_FOCUS_GAINED:
598 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
599 case SDL_EVENT_WINDOW_FOCUS_LOST:
605 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
606 LOG_DP <<
"events/SIZE_CHANGED "
607 <<
event.window.data1 <<
'x' <<
event.window.data2;
614 case SDL_EVENT_WINDOW_RESIZED:
615 LOG_DP <<
"events/RESIZED "
616 <<
event.window.data1 <<
'x' <<
event.window.data2;
622 case SDL_EVENT_WINDOW_EXPOSED:
623 LOG_DP <<
"events/EXPOSED";
627 case SDL_EVENT_WINDOW_MAXIMIZED:
628 LOG_DP <<
"events/MAXIMIZED";
631 case SDL_EVENT_WINDOW_RESTORED:
632 LOG_DP <<
"events/RESTORED";
635 case SDL_EVENT_WINDOW_SHOWN:
636 case SDL_EVENT_WINDOW_MOVED:
648 case SDL_EVENT_MOUSE_MOTION: {
655 case SDL_EVENT_MOUSE_BUTTON_DOWN: {
662 case SDL_EVENT_KEY_DOWN: {
663 if(event.key.key == SDLK_F4 &&
664 (event.key.mod == SDL_KMOD_RALT || event.key.mod == SDL_KMOD_LALT)
673 case SDL_EVENT_QUIT: {
680 global_handler->handle_event(event);
689 std::size_t h_size =
h.size();
690 for(
auto it =
h.begin(); it !=
h.end(); ++it) {
692 (*it)->handle_event(event);
695 LOG_EV <<
"ec size changed! bugging out";
698 if(h_size !=
h.size()) {
699 LOG_EV <<
"h size changed! bugging out";
723 handler->process_event();
732 event.type = SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED;
733 event.window.windowID = 0;
734 event.window.data1 =
size.x;
735 event.window.data2 =
size.y;
744 handler->process_tooltip_string(mousex, mousey);
750 #define INPUT_MIN 0x300
751 #define INPUT_MAX 0x8FF
765 return event.which == SDL_TOUCH_MOUSEID;
770 return event.which == SDL_TOUCH_MOUSEID;
781 invoked_function_data fdata{
f};
787 sdl_event.user = sdl_userevent;
789 SDL_PushEvent(&sdl_event);
792 fdata.finished.get_future().wait();
796 bool handle_windows_message([[maybe_unused]]
void* userdata,
MSG*
msg)
void set_focus(const sdl_handler *ptr)
bool has_handler(const sdl_handler *ptr) const
Returns true if ptr is found in either the handlers or staging_handlers lists.
handler_list::iterator focused_handler
std::vector< sdl_handler * > staging_handlers
void add_handler(sdl_handler *ptr)
bool remove_handler(sdl_handler *ptr)
void add_staging_handlers()
virtual bool requires_event_focus(const SDL_Event *=nullptr) const
virtual std::vector< sdl_handler * > handler_members()
virtual void join_global()
virtual void join_same(sdl_handler *parent)
virtual void leave_global()
sdl_handler & operator=(sdl_handler &&)=delete
Moving would require two instances' context membership to be handled, it's simpler to delete these an...
sdl_handler(sdl_handler &&)=delete
void set_resolution(const point &res)
static void quit_to_desktop()
Type that can be thrown as an exception to quit to desktop.
static lg::log_domain log_display("display")
static lg::log_domain log_event("event")
#define INVOKE_FUNCTION_EVENT
std::vector< events::sdl_handler * > sdl_handler_vector
std::string id
Text to match against addon_info.tags()
Standard logging facilities (interface).
void set_focus(bool focus)
void invalidate_all()
Mark the entire screen as requiring redraw.
void sparkle()
Ensure that everything which needs to be drawn is drawn.
Handling of system events.
void raise_resize_event()
bool has_focus(const sdl_handler *hand, const SDL_Event *event)
void discard_input()
Discards all input events.
void draw()
Trigger a draw cycle.
static std::thread::id main_thread
static void raise_window_event(const SDL_Event &event)
bool is_input(const SDL_Event &event)
Is the event an input event?
std::deque< context > event_contexts
std::vector< pump_monitor * > pump_monitors
void call_in_main_thread(const std::function< void(void)> &f)
void raise_process_event()
void process_tooltip_strings(int mousex, int mousey)
Triggered by mouse-motion, sends the cursor position to all handlers to check whether a tooltip shoul...
std::list< sdl_handler * > handler_list
void pump()
Process all events currently in the queue.
bool is_touch(const SDL_MouseButtonEvent &event)
Check if this mouse button event is caused by a touch.
void focus_handler(const sdl_handler *ptr)
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
std::size_t erase(Container &container, const Value &value)
Convenience wrapper for using std::remove on a container.
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
point game_canvas_size()
The size of the game canvas, in drawing coordinates / game pixels.
point window_size()
Returns the size of the window in display units / screen coordinates.
SDL_Renderer * get_renderer()
void update_buffers(bool autoupdate)
Update buffers to match current resolution and pixel scale settings.
std::string::const_iterator iterator
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
bool message_hook(const MSG &msg)
Frees resources when a notification disappears, switches user to the wesnoth window if the notificati...