1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #include "smeventloop.hh"
4 #include "smwindow.hh"
5 
6 #include <unistd.h>
7 
8 using namespace SpectMorph;
9 
10 void
wait_event_fps()11 EventLoop::wait_event_fps()
12 {
13   /* tradeoff between UI responsiveness and cpu usage caused by thread wakeups
14    *
15    * 60 fps should make the UI look smooth
16    */
17   const double frames_per_second = 60;
18 
19   usleep (1000 * 1000 / frames_per_second);
20 }
21 
22 void
process_events()23 EventLoop::process_events()
24 {
25   assert (m_level == 0);
26 
27   /*
28    * NOTE: on Windows OS, events can be generated and processed outside this
29    * event loop, via wndProc - so all code needs to be safe for this case (as
30    * well as X11/macOS which only have events in windows[i]->process_events())
31    */
32 
33   signal_before_process();
34 
35   m_level++;
36   for (size_t i = 0; i < windows.size(); i++) /* avoid auto here */
37     {
38       if (windows[i])
39         windows[i]->process_events();
40     }
41 
42   /* do not use auto here */
43   for (size_t i = 0; i < delete_later_widgets.size(); i++)
44     {
45       delete delete_later_widgets[i];
46       assert (!delete_later_widgets[i]);
47     }
48 
49   cleanup_null (windows);
50   cleanup_null (delete_later_widgets);
51 
52   m_level--;
53 }
54 
55 int
level() const56 EventLoop::level() const
57 {
58   return m_level;
59 }
60 
61 bool
window_alive(Window * window) const62 EventLoop::window_alive (Window *window) const
63 {
64   /* windows that are about to be deleted are no longer considered alive */
65   for (auto w : delete_later_widgets)
66     if (w == window)
67       return false;
68 
69   /* windows need to be on the windows list to be alive */
70   for (auto w : windows)
71     if (w == window)
72       return true;
73 
74   return false;
75 }
76 
77 void
add_window(Window * window)78 EventLoop::add_window (Window *window)
79 {
80   windows.push_back (window);
81 }
82 
83 void
remove_window(Window * window)84 EventLoop::remove_window (Window *window)
85 {
86   for (auto& w : windows)
87     {
88       if (w == window)
89         w = nullptr;
90     }
91   on_widget_deleted (window);
92 }
93 
94 void
add_delete_later(Widget * widget)95 EventLoop::add_delete_later (Widget *widget)
96 {
97   delete_later_widgets.push_back (widget);
98 }
99 
100 void
on_widget_deleted(Widget * widget)101 EventLoop::on_widget_deleted (Widget *widget)
102 {
103   for (auto& w : delete_later_widgets)
104     {
105       if (w == widget)
106         w = nullptr;
107     }
108 }
109