jGL
Loading...
Searching...
No Matches
desktopDisplay.h
Go to the documentation of this file.
1#ifndef DesktopDisplay_H
2#define DesktopDisplay_H
3
4#ifndef ANDROID
5
6#include <cstdlib>
7#include <vector>
8#include <map>
9
10#include <vulkan/vulkan.h>
11#define GLFW_INCLUDE_NONE
12#include <GLFW/glfw3.h>
13
14#include <imgui/imgui.h>
15#include <imgui/imgui_impl_glfw.h>
16#include <imgui/imgui_impl_opengl3.h>
17
18#include <jGL/Display/event.h>
19#include <jGL/Display/display.h>
20
21#include <jGL/common.h>
22#include <stb_image.h>
23#include <algorithm>
24
25#ifdef WINDOWS
26#include <windows.h>
27#include <mmsystem.h>
28#include <imgui/imgui_impl_win32.h>
29#endif
30
31#ifdef MACOS
32#include <imgui/imgui_impl_osx.h>
33#endif
34
35namespace jGL
36{
37
39 (
40 GLFWwindow * window,
41 int key,
42 int scancode,
43 int action,
44 int mods
45 );
46
48 (
49 GLFWwindow * window,
50 int button,
51 int action,
52 int mods
53 );
54
56 (
57 GLFWwindow * window,
58 double x,
59 double y
60 );
61
62 void parseAction
63 (
64 GLFWwindow * window,
65 int code,
66 int action
67 );
68
69 class DesktopDisplay : public Display
70 {
71 public:
72
73 struct Config
74 {
76 : VULKAN(false),
77 COCOA_RETINA(false),
78 CLIP_TO_MONITOR(true),
80 {}
81
83 (
84 bool vulkan,
85 bool cocoa,
86 bool clipMonitor,
87 bool clipWorkArea
88 )
89 : VULKAN(vulkan),
90 COCOA_RETINA(cocoa),
91 CLIP_TO_MONITOR(clipMonitor),
92 CLIP_TO_WORK_AREA(clipWorkArea)
93 {}
94
101
102 bool VULKAN;
104 // if screen size bigger than monitor clip
106 // if screen size too big to fit with taskbars, cip
108 };
109
111 (
112 glm::ivec2 res,
113 const char * title,
114 GLFWkeyfun keyCallback,
115 GLFWmousebuttonfun mouseButtonCallback,
116 GLFWscrollfun mouseScrollCallback,
117 const Config conf
118 );
119
121 (
122 glm::ivec2 res,
123 const char * title,
124 const Config conf
125 );
126
128 {
129 for (auto icon : logo)
130 {
131 stbi_image_free(icon.pixels);
132 }
133 logo.clear();
134
135 glfwTerminate();
136 #ifdef WINDOWS
137 timeEndPeriod(1);
138 #endif
139 }
140
141 GLFWwindow * getWindow() const { return glfwWindow; }
142
143 bool isOpen(){ if (glfwWindow != NULL) { return !glfwWindow ? false : true; } return false; }
144 bool closing(){ return glfwWindowShouldClose(glfwWindow); }
145
146 void open(){
147 #ifdef WINDOWS
148 timeBeginPeriod(1);
149 #endif
150 if (glfwWindow == NULL)
151 {
152 // required for MacOS
153 // https://www.glfw.org/faq.html#41__how_do_i_create_an_opengl_30_context
154 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
155 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
156 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
157 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
158 glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, windowConfig.COCOA_RETINA);
159 glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
160
161 // get work area (i.e. without taskbars)
162 int wxpos, wypos, wwidth, wheight;
163 glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &wxpos, &wypos, &wwidth, &wheight);
164
165 // hack to obtain decoration size
166 GLFWwindow * temporaryWindow = glfwCreateWindow(1, 1, "", NULL, NULL);
167 int fleft, ftop, fright, fbottom;
168 glfwGetWindowFrameSize(temporaryWindow, &fleft, &ftop, &fright, &fbottom);
169 glfwWindowShouldClose(temporaryWindow);
170 glfwDestroyWindow(temporaryWindow);
171
172 #ifdef WINDOWS
173 // windows pos includes decoration...
174 glm::ivec2 pos(wxpos, wypos+ftop);
175 #else
176 glm::ivec2 pos(wxpos, wypos);
177 #endif
178
179 if (windowConfig.CLIP_TO_MONITOR)
180 {
181 const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
182 resolution.x = std::min(resolution.x, mode->width);
183 resolution.y = std::min(resolution.y, mode->height);
184 }
185
186 if (windowConfig.CLIP_TO_WORK_AREA)
187 {
188 if (resolution.y+ftop > wheight)
189 {
190 resolution.y = wheight-ftop;
191 }
192
193 if (resolution.x > wwidth)
194 {
195 resolution.x = wwidth;
196 }
197 }
198
199 main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor());
200 glfwWindow = glfwCreateWindow(getResX()*main_scale, getResY()*main_scale,title,NULL,NULL);
201 glfwSwapInterval(1);
203 }
204 }
205
206 void close(){ if (glfwWindow != NULL) { glfwDestroyWindow(glfwWindow); glfwWindow = NULL; } }
207
208 void setAsFocus(){ if (glfwWindow != NULL) { glfwMakeContextCurrent(glfwWindow); } }
209
211 (
212 GLFWwindow * window,
213 int key,
214 int scancode,
215 int action,
216 int mods
217 );
218
219 void mousePosition(double & x, double & y){ if (glfwWindow != NULL){ glfwGetCursorPos(glfwWindow,&x,&y); } }
220
221 void setMousePosition(double x, double y)
222 {
223 if (glfwWindow != NULL)
224 {
225 glfwSetCursorPos(glfwWindow, x, y);
226 }
227 }
228
229 int getKeyLastState(int key) { return glfwGetKey(glfwWindow, key); }
230
231 void loop()
232 {
233 data.clear();
234 handleEvents();
235 if (glfwWindowShouldClose(glfwWindow)){ close(); }
236 throttle();
237 swap();
238 }
239
240 std::vector<Event> getEvents(int code)
241 {
242 if (data.events.find(code) == data.events.cend())
243 {
244 return {Event()};
245 }
246 else
247 {
248 return data.events[code];
249 }
250 }
251
252 bool keyHasEvent(int key, EventType action)
253 {
254 if (data.events.find(key) == data.events.cend())
255 {
256 return false;
257 }
258 else
259 {
260 auto ts = getEventTypes(key);
261 return std::find(ts.cbegin(), ts.cend(), action) != ts.cend();
262 }
263 }
264
265 bool keyHasAnyEvents(int key, std::vector<EventType> actions)
266 {
267 if (data.events.find(key) == data.events.cend())
268 {
269 return false;
270 }
271 else
272 {
273 auto ts = getEventTypes(key);
274 for (const auto & action : actions)
275 {
276 if (std::find(ts.cbegin(), ts.cend(), action) != ts.cend())
277 {
278 return true;
279 }
280 }
281 }
282 return false;
283 }
284
285 std::vector<EventType> getEventTypes(int code)
286 {
287 std::vector<EventType> e;
288 if (data.events.find(code) == data.events.cend())
289 {
290 return {EventType::NONE};
291 }
292 else
293 {
294 for (auto evt : data.events[code])
295 {
296 e.push_back(evt.type);
297 }
298 return e;
299 }
300 }
301
302 Event getEvent(int code)
303 {
304 if (data.events.find(code) == data.events.cend())
305 {
306 return Event();
307 }
308 else
309 {
310 return data.events[code][0];
311 }
312 }
313
315 {
316 std::map<int, std::vector<Event>> events;
317 double scrollX = 0.0;
318 double scrollY = 0.0;
319 bool scrolled = false;
320
321 void clear()
322 {
323 scrollX = 0.0;
324 scrollY = 0.0;
325 scrolled = false;
326 events.clear();
327 }
328 };
329
330 void setIcon(const std::vector<std::vector<std::byte>> & icons)
331 {
332 glfwSetWindowIcon(glfwWindow, 0, NULL);
333 logo.clear();
334 for (auto icon : icons)
335 {
336 GLFWimage image;
337 unsigned char * chData = reinterpret_cast<unsigned char*>(icon.data());
338 image.pixels = stbi_load_from_memory
339 (
340 chData,
341 icon.size(),
342 &image.width,
343 &image.height,
344 0,
345 4
346 );
347 logo.push_back(image);
348 }
349
350 glfwSetWindowIcon(glfwWindow,logo.size(),logo.data());
351 }
352
353 glm::ivec2 frameBufferSize() const
354 {
355 glm::ivec2 s;
356 if (glfwWindow != NULL)
357 {
358 glfwGetFramebufferSize(glfwWindow, &s.x, &s.y);
359 }
360 return s;
361 }
362
363 glm::ivec2 windowSize() const
364 {
365 glm::ivec2 s;
366 if (glfwWindow != NULL)
367 {
368 glfwGetWindowSize(glfwWindow, &s.x, &s.y);
369 }
370 return s;
371 }
372
373 glm::vec2 contentScale() const
374 {
375 glm::vec2 s;
376 if (glfwWindow != NULL)
377 {
378 glfwGetWindowContentScale(glfwWindow, &s.x, &s.y);
379 }
380 return s;
381 }
382
383 glm::ivec4 windowFrameSize() const
384 {
385 glm::ivec4 s;
386 if (glfwWindow != NULL)
387 {
388 glfwGetWindowFrameSize(glfwWindow, &s.x, &s.y, &s.z, &s.w);
389 }
390 return s;
391 }
392
393 glm::ivec2 windowPosition() const
394 {
395 glm::ivec2 s;
396 if (glfwWindow != NULL)
397 {
398 glfwGetWindowPos(glfwWindow, &s.x, &s.y);
399 }
400 return s;
401 }
402
403 void setWindowPosition(glm::ivec2 s)
404 {
405 if (glfwWindow != NULL)
406 {
407 glfwSetWindowPos(glfwWindow, s.x, s.y);
408 }
409 }
410
411 void setResolution(glm::ivec2 wh)
412 {
413 resolution = wh;
414 if (glfwWindow != NULL)
415 {
416 glfwSetWindowSize(glfwWindow, resolution.x*main_scale, resolution.y*main_scale);
417 }
418 }
419
421 {
422 IMGUI_CHECKVERSION();
423 ImGui::CreateContext();
424 ImGuiIO& io = ImGui::GetIO(); (void)io;
425 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
426
427 ImGui::StyleColorsDark();
428
429 ImGuiStyle& style = ImGui::GetStyle();
430 style.ScaleAllSizes(main_scale);
431 style.FontScaleDpi = main_scale;
432
433 ImGui_ImplGlfw_InitForOpenGL(glfwWindow, true);
434 ImGui_ImplOpenGL3_Init("#version " GLSL_VERSION "");
435 }
436
437 private:
438
439 const char * title;
440
441 std::vector<GLFWimage> logo;
442
443 GLFWwindow * glfwWindow;
444
445 WindowData data;
446
447 Config windowConfig;
448
449 float main_scale;
450
451 void swap(){ if (glfwWindow != NULL) { glfwSwapBuffers(glfwWindow); } }
452
453 void handleEvents(){ if (glfwWindow != NULL){ glfwPollEvents(); } }
454
455 };
456}
457
458#endif /* ANDROID */
459#endif /* DesktopDisplay_H */
Definition desktopDisplay.h:70
void setMousePosition(double x, double y)
Definition desktopDisplay.h:221
glm::ivec4 windowFrameSize() const
Definition desktopDisplay.h:383
void setWindowPosition(glm::ivec2 s)
Definition desktopDisplay.h:403
void loop()
Definition desktopDisplay.h:231
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
void setAsFocus()
Definition desktopDisplay.h:208
std::vector< Event > getEvents(int code)
Definition desktopDisplay.h:240
bool isOpen()
Definition desktopDisplay.h:143
std::vector< EventType > getEventTypes(int code)
Definition desktopDisplay.h:285
void mousePosition(double &x, double &y)
Definition desktopDisplay.h:219
~DesktopDisplay()
Definition desktopDisplay.h:127
glm::ivec2 windowSize() const
Definition desktopDisplay.h:363
void setResolution(glm::ivec2 wh)
Definition desktopDisplay.h:411
void setIcon(const std::vector< std::vector< std::byte > > &icons)
Definition desktopDisplay.h:330
int getKeyLastState(int key)
Definition desktopDisplay.h:229
bool keyHasAnyEvents(int key, std::vector< EventType > actions)
Definition desktopDisplay.h:265
bool keyHasEvent(int key, EventType action)
Definition desktopDisplay.h:252
GLFWwindow * getWindow() const
Definition desktopDisplay.h:141
bool closing()
Definition desktopDisplay.h:144
Event getEvent(int code)
Definition desktopDisplay.h:302
glm::vec2 contentScale() const
Definition desktopDisplay.h:373
void open()
Definition desktopDisplay.h:146
void close()
Definition desktopDisplay.h:206
glm::ivec2 windowPosition() const
Definition desktopDisplay.h:393
glm::ivec2 frameBufferSize() const
Definition desktopDisplay.h:353
void initImgui()
Definition desktopDisplay.h:420
Definition display.h:12
unsigned getResY() const
Definition display.h:26
virtual void throttle()
Definition display.h:50
glm::ivec2 resolution
Definition display.h:44
unsigned getResX() const
Definition display.h:25
A drawable graphic.
Definition id.h:10
void defaultScrollCallback(GLFWwindow *window, double x, double y)
Definition desktopDisplay.cpp:61
EventType
Definition event.h:9
void parseAction(GLFWwindow *window, int code, int action)
Definition desktopDisplay.cpp:8
void defaultMouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
Definition desktopDisplay.cpp:50
void defaultKeyEventCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
Definition desktopDisplay.cpp:32
Definition desktopDisplay.h:74
bool CLIP_TO_WORK_AREA
Definition desktopDisplay.h:107
bool VULKAN
Definition desktopDisplay.h:102
bool CLIP_TO_MONITOR
Definition desktopDisplay.h:105
bool COCOA_RETINA
Definition desktopDisplay.h:103
Config(const Config &c)
Definition desktopDisplay.h:95
Config(bool vulkan, bool cocoa, bool clipMonitor, bool clipWorkArea)
Definition desktopDisplay.h:83
Config()
Definition desktopDisplay.h:75
Definition desktopDisplay.h:315
double scrollY
Definition desktopDisplay.h:318
void clear()
Definition desktopDisplay.h:321
std::map< int, std::vector< Event > > events
Definition desktopDisplay.h:316
double scrollX
Definition desktopDisplay.h:317
bool scrolled
Definition desktopDisplay.h:319
Definition event.h:14