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()11EventLoop::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()23EventLoop::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() const56EventLoop::level() const 57 { 58 return m_level; 59 } 60 61 bool window_alive(Window * window) const62EventLoop::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)78EventLoop::add_window (Window *window) 79 { 80 windows.push_back (window); 81 } 82 83 void remove_window(Window * window)84EventLoop::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)95EventLoop::add_delete_later (Widget *widget) 96 { 97 delete_later_widgets.push_back (widget); 98 } 99 100 void on_widget_deleted(Widget * widget)101EventLoop::on_widget_deleted (Widget *widget) 102 { 103 for (auto& w : delete_later_widgets) 104 { 105 if (w == widget) 106 w = nullptr; 107 } 108 } 109