Thanks to visit codestin.com
Credit goes to glvis.github.io

GLVis  v4.2
Accurate and flexible finite element visualization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
sdl.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-443271.
4 //
5 // This file is part of the GLVis visualization tool and library. For more
6 // information and source code availability see https://glvis.org.
7 //
8 // GLVis is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef GLVIS_SDL_HPP
13 #define GLVIS_SDL_HPP
14 
15 #include <string>
16 #include <memory>
17 #include <functional>
18 #include <map>
19 #include <mutex>
20 #include <condition_variable>
21 #include <deque>
22 #include "gl/renderer.hpp"
23 #include "sdl_helper.hpp"
24 
25 struct EventInfo
26 {
27  GLint mouse_x;
28  GLint mouse_y;
29  SDL_Keymod keymod;
30 };
31 
32 typedef void (*TouchDelegate)(SDL_MultiGestureEvent&);
33 typedef void (*MouseDelegate)(EventInfo*);
34 typedef std::function<void(GLenum)> KeyDelegate;
35 typedef void (*WindowDelegate)(int, int);
36 typedef void (*Delegate)();
37 typedef bool (*IdleDelegate)();
38 
39 class SdlMainThread;
40 
41 class SdlWindow
42 {
43 private:
44  friend class SdlMainThread;
45  struct Handle
46  {
47  SDL_Window * hwnd{nullptr};
48  SDL_GLContext gl_ctx{};
49 
50  Handle() = default;
51 
52  Handle(const std::string& title, int x, int y, int w, int h,
53  Uint32 wndflags);
54 
55  ~Handle();
56 
57  Handle(Handle&& other)
58  : hwnd(other.hwnd), gl_ctx(other.gl_ctx)
59  {
60  other.hwnd = nullptr;
61  other.gl_ctx = 0;
62  }
63 
64  Handle& operator= (Handle&& other)
65  {
66  std::swap(hwnd, other.hwnd);
67  std::swap(gl_ctx, other.gl_ctx);
68  return *this;
69  }
70 
71  bool isInitialized() const
72  {
73  return (hwnd != nullptr && gl_ctx != 0);
74  }
75  };
76 
77  int window_id = -1;
78  Handle handle;
79  std::unique_ptr<gl3::MeshRenderer> renderer;
80  static const int high_dpi_threshold = 144;
81  // The display is high-dpi when:
82  // - SDL's "screen coordinates" sizes are different from the pixel sizes, or
83  // - either the horizontal or the vertical dpi, as returned by getDpi(),
84  // is >= high_dpi_threshold, defined above.
85  bool high_dpi = false;
86  // Ratio of SDL's "screen coordinates" to GLVis' "screen coordinates":
87  // - set to 1 on non-high-dpi displays,
88  // - set to 1 on high-dpi displays where SDL's "screen coordinates" sizes are
89  // different from the pixels sizes (e.g. Mac retina displays),
90  // - set to 2 on other high-dpi displays, so that GLVis can always work with
91  // scaled "screen coordinates" on all high-dpi displays.
92  float pixel_scale_x = 1.0f, pixel_scale_y = 1.0f;
93 
94  bool running;
95 
96  IdleDelegate onIdle{nullptr};
97  Delegate onExpose{nullptr};
98  WindowDelegate onReshape{nullptr};
99  std::map<int, KeyDelegate> onKeyDown;
100  std::map<int, MouseDelegate> onMouseDown;
101  std::map<int, MouseDelegate> onMouseUp;
102  std::map<int, MouseDelegate> onMouseMove;
103  TouchDelegate onTouchPinch{nullptr};
104  TouchDelegate onTouchRotate{nullptr};
105 
106  bool ctrlDown{false};
107 
108 #ifdef __EMSCRIPTEN__
109  std::string canvas_id_;
110 #endif
111 
112  enum class RenderState
113  {
114  // window displayed is fully current (no events or backbuffer updates pending)
115  Updated,
116  // events issued which may require a call to MyExpose
118  // back buffer updated by MyExpose, now awaiting swap to be displayed on window
120  };
121 
122  RenderState wnd_state{RenderState::Updated};
123 
124  bool update_before_expose{false};
125 
126  //bool requiresExpose;
127  bool takeScreenshot{false};
128  std::string screenshot_file;
129  bool screenshot_convert;
130 
131  // internal event handlers
132  void windowEvent(SDL_WindowEvent& ew);
133  void motionEvent(SDL_MouseMotionEvent& em);
134  void mouseEventDown(SDL_MouseButtonEvent& eb);
135  void mouseEventUp(SDL_MouseButtonEvent& eb);
136  void keyEvent(SDL_Keysym& ks);
137  void keyEvent(char c);
138  void multiGestureEvent(SDL_MultiGestureEvent & e);
139 
140  bool is_multithreaded{true};
141 
142  bool call_idle_func{false};
143 
144  // Hand off events to the SdlWindow. Intended to be called by the main SDL
145  // thread in MainThread::MainLoop().
146  void queueEvents(std::vector<SDL_Event> events)
147  {
148  {
149  std::lock_guard<std::mutex> evt_guard{event_mutex};
150  waiting_events.insert(waiting_events.end(), events.begin(), events.end());
151  }
152  if (is_multithreaded)
153  {
154  events_available.notify_all();
155  }
156  }
157 
158  std::string saved_keys;
159 
160  std::condition_variable events_available;
161  std::mutex event_mutex;
162  // The window-specific events collected by the main event thread.
163  std::deque<SDL_Event> waiting_events;
164 public:
165  SdlWindow();
166  ~SdlWindow();
167 
168  // Initializes SDL2 and starts the main loop. Should be called from the main
169  // thread only.
170  static void StartSDL(bool server_mode);
171 
174  bool createWindow(const char * title, int x, int y, int w, int h,
175  bool legacyGlOnly);
176 
178  void mainLoop();
179  void mainIter();
180 
181  // Called by worker threads in GLVisCommand::signal()
182  void signalLoop();
183 
184  void setOnIdle(IdleDelegate func) { onIdle = func; }
185  void setOnExpose(Delegate func) { onExpose = func; }
186  void setOnReshape(WindowDelegate func) { onReshape = func; }
187 
188  void setOnKeyDown(int key, Delegate func)
189  {
190  onKeyDown[key] = [func](GLenum) { func(); };
191  }
192  void setOnKeyDown(int key, KeyDelegate func) { onKeyDown[key] = func; }
193 
194  void setOnMouseDown(int btn, MouseDelegate func) { onMouseDown[btn] = func; }
195  void setOnMouseUp(int btn, MouseDelegate func) { onMouseUp[btn] = func; }
196  void setOnMouseMove(int btn, MouseDelegate func) { onMouseMove[btn] = func; }
197 
198  void setTouchPinchCallback(TouchDelegate cb) { onTouchPinch = cb; }
199  void setTouchRotateCallback(TouchDelegate cb) { onTouchRotate = cb; }
200 
201  void clearEvents()
202  {
203  onIdle = nullptr;
204  onExpose = nullptr;
205  onReshape = nullptr;
206  onKeyDown.clear();
207  onMouseUp.clear();
208  onMouseDown.clear();
209  onMouseMove.clear();
210  }
211 
212  void callKeyDown(SDL_Keycode k, Uint16 mod=0)
213  {
214  if (onKeyDown[k])
215  {
216  onKeyDown[k](mod);
217  }
218  }
219 
220  void getWindowSize(int& w, int& h);
221  void getGLDrawSize(int& w, int& h);
222  void getDpi(int& wdpi, int& hdpi);
224  bool isHighDpi() const { return high_dpi; }
225 
226  gl3::MeshRenderer& getRenderer() { return *renderer.get(); }
227  void setWindowTitle(std::string& title);
228  void setWindowTitle(const char* title);
229  void setWindowSize(int w, int h);
230  void setWindowPos(int x, int y);
231 
232  void signalKeyDown(SDL_Keycode k, SDL_Keymod m = KMOD_NONE);
233  void signalExpose() { wnd_state = RenderState::ExposePending; }
234  void signalSwap() { wnd_state = RenderState::SwapPending; }
235  void signalQuit() { running = false; }
236 
238  std::string getSavedKeys() const { return saved_keys; }
239 
241  void screenshot(std::string filename, bool convert = false)
242  {
243  takeScreenshot = true;
244  screenshot_file = filename;
245  screenshot_convert = convert;
246  // Queue up an expose, so Screenshot() can pull image from the back
247  // buffer
248  signalExpose();
249  }
250 
251  void swapBuffer();
252 
253  operator bool() { return handle.isInitialized(); }
254  bool isWindowInitialized() { return handle.isInitialized(); }
256  bool isGlInitialized();
257 
258  bool isSwapPending() { return wnd_state == RenderState::SwapPending; }
259  bool isExposePending() { return wnd_state == RenderState::ExposePending; }
260 
261 #ifdef __EMSCRIPTEN__
262  std::string getCanvasId() const { return canvas_id_; }
263  void setCanvasId(std::string canvas_id) { canvas_id_ = canvas_id; }
264 #endif
265 };
266 
267 #endif
void signalQuit()
Definition: sdl.hpp:235
void signalExpose()
Definition: sdl.hpp:233
void signalKeyDown(SDL_Keycode k, SDL_Keymod m=KMOD_NONE)
Definition: sdl.cpp:630
void signalSwap()
Definition: sdl.hpp:234
void(* WindowDelegate)(int, int)
Definition: sdl.hpp:35
void getGLDrawSize(int &w, int &h)
Definition: sdl.cpp:563
bool isGlInitialized()
Returns true if the OpenGL context was successfully initialized.
Definition: sdl.cpp:76
bool isExposePending()
Definition: sdl.hpp:259
void mainLoop()
Runs the window loop.
Definition: sdl.cpp:483
gl3::MeshRenderer & getRenderer()
Definition: sdl.hpp:226
~SdlWindow()
Definition: sdl.cpp:185
SDL_Keymod keymod
Definition: sdl.hpp:29
void setTouchRotateCallback(TouchDelegate cb)
Definition: sdl.hpp:199
void setWindowTitle(std::string &title)
Definition: sdl.cpp:601
void signalLoop()
Definition: sdl.cpp:524
void setOnKeyDown(int key, KeyDelegate func)
Definition: sdl.hpp:192
void setWindowPos(int x, int y)
Definition: sdl.cpp:618
void setOnReshape(WindowDelegate func)
Definition: sdl.hpp:186
void swapBuffer()
Definition: sdl.cpp:649
bool isWindowInitialized()
Definition: sdl.hpp:254
GLint mouse_y
Definition: sdl.hpp:28
void screenshot(std::string filename, bool convert=false)
Queues a screenshot to be taken.
Definition: sdl.hpp:241
void getWindowSize(int &w, int &h)
Definition: sdl.cpp:534
void setOnMouseDown(int btn, MouseDelegate func)
Definition: sdl.hpp:194
void setCanvasId(std::string canvas_id)
Definition: sdl.hpp:263
void(* MouseDelegate)(EventInfo *)
Definition: sdl.hpp:33
void callKeyDown(SDL_Keycode k, Uint16 mod=0)
Definition: sdl.hpp:212
static void StartSDL(bool server_mode)
Definition: sdl.cpp:83
void setOnMouseMove(int btn, MouseDelegate func)
Definition: sdl.hpp:196
std::string getSavedKeys() const
Returns the keyboard events that have been logged by the window.
Definition: sdl.hpp:238
void clearEvents()
Definition: sdl.hpp:201
void setTouchPinchCallback(TouchDelegate cb)
Definition: sdl.hpp:198
bool isHighDpi() const
This property is set by createWindow().
Definition: sdl.hpp:224
bool(* IdleDelegate)()
Definition: sdl.hpp:37
void setOnExpose(Delegate func)
Definition: sdl.hpp:185
GLint mouse_x
Definition: sdl.hpp:27
void(* Delegate)()
Definition: sdl.hpp:36
bool createWindow(const char *title, int x, int y, int w, int h, bool legacyGlOnly)
Definition: sdl.cpp:90
void(* TouchDelegate)(SDL_MultiGestureEvent &)
Definition: sdl.hpp:32
void setOnIdle(IdleDelegate func)
Definition: sdl.hpp:184
std::function< void(GLenum)> KeyDelegate
Definition: sdl.hpp:34
void setOnKeyDown(int key, Delegate func)
Definition: sdl.hpp:188
SdlWindow()
Definition: sdl.cpp:81
bool isSwapPending()
Definition: sdl.hpp:258
void getDpi(int &wdpi, int &hdpi)
Definition: sdl.cpp:568
std::string getCanvasId() const
Definition: sdl.hpp:262
void mainIter()
Definition: sdl.cpp:362
void setOnMouseUp(int btn, MouseDelegate func)
Definition: sdl.hpp:195
void setWindowSize(int w, int h)
Definition: sdl.cpp:611