1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /***************************************************************************
3 * nativewindow_pugl.cc
4 *
5 * Fri Dec 28 18:45:57 CET 2012
6 * Copyright 2012 Bent Bisballe Nyeng
7 * deva@aasimon.org
8 ****************************************************************************/
9
10 /*
11 * This file is part of DrumGizmo.
12 *
13 * DrumGizmo is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * DrumGizmo is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with DrumGizmo; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 */
27 #include "nativewindow_pugl.h"
28
29 #include <stdlib.h>
30 #include <list>
31
32 #ifdef __APPLE__
33 #include <OpenGL/glu.h>
34 #else
35 #include <GL/glu.h>
36 #include <GL/glext.h>
37 #include <GL/gl.h>
38 #endif
39
40 #include "window.h"
41 #include "guievent.h"
42
43 #include <hugin.hpp>
44
45 namespace GUI
46 {
47
NativeWindowPugl(void * native_window,Window & window)48 NativeWindowPugl::NativeWindowPugl(void* native_window, Window& window)
49 : window(window)
50 {
51 INFO(nativewindow, "Running with PuGL native window\n");
52 view = puglInit(nullptr, nullptr);
53 puglInitContextType(view, PUGL_GL);
54 if(native_window)
55 {
56 puglInitWindowParent(view, (PuglNativeWindow)native_window);
57 }
58 puglInitWindowClass(view, "DrumgGizmo");
59 puglInitWindowSize(view, 750, 466);
60 puglInitResizable(view, true);
61 puglCreateWindow(view, "DrumGizmo");
62
63 puglSetHandle(view, (PuglHandle)this);
64 puglSetEventFunc(view, onEvent);
65 }
66
~NativeWindowPugl()67 NativeWindowPugl::~NativeWindowPugl()
68 {
69 puglDestroy(view);
70 }
71
setFixedSize(std::size_t width,std::size_t height)72 void NativeWindowPugl::setFixedSize(std::size_t width, std::size_t height)
73 {
74 // redraw();
75 }
76
resize(std::size_t width,std::size_t height)77 void NativeWindowPugl::resize(std::size_t width, std::size_t height)
78 {
79 // DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height);
80 // init();
81 // redraw();
82 }
83
getSize() const84 std::pair<std::size_t, std::size_t> NativeWindowPugl::getSize() const
85 {
86 int width, height;
87 puglGetSize(view, &width, &height);
88 return {width, height};
89 }
90
move(int x,int y)91 void NativeWindowPugl::move(int x, int y)
92 {
93 // redraw();
94 }
95
show()96 void NativeWindowPugl::show()
97 {
98 puglShowWindow(view);
99 }
100
hide()101 void NativeWindowPugl::hide()
102 {
103 puglHideWindow(view);
104 }
105
visible() const106 bool NativeWindowPugl::visible() const
107 {
108 return puglGetVisible(view);
109 }
110
redraw(const Rect & dirty_rect)111 void NativeWindowPugl::redraw(const Rect& dirty_rect)
112 {
113 //puglPostRedisplay(view);// handleBuffer();
114 onDisplay(view);
115 }
116
setCaption(const std::string & caption)117 void NativeWindowPugl::setCaption(const std::string &caption)
118 {
119 // redraw();
120 }
121
grabMouse(bool grab)122 void NativeWindowPugl::grabMouse(bool grab)
123 {
124 puglGrabFocus(view);
125 }
126
getEvents()127 EventQueue NativeWindowPugl::getEvents()
128 {
129 puglProcessEvents(view);
130 EventQueue events;
131 std::swap(events, event_queue);
132 return events;
133 }
134
getNativeWindowHandle() const135 void* NativeWindowPugl::getNativeWindowHandle() const
136 {
137 return (void*)puglGetNativeWindow(view);
138 }
139
onEvent(PuglView * view,const PuglEvent * event)140 void NativeWindowPugl::onEvent(PuglView* view, const PuglEvent* event)
141 {
142 NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view);
143
144 switch(event->type)
145 {
146 case PUGL_NOTHING:
147 break;
148 case PUGL_CONFIGURE:
149 onReshape(view, event->configure.width, event->configure.height);
150 {
151 auto resize_event = std::make_shared<ResizeEvent>();
152 resize_event->width = event->configure.width;
153 resize_event->height = event->configure.height;
154 native->event_queue.push_back(resize_event);
155 }
156 break;
157 case PUGL_EXPOSE:
158 onDisplay(view);
159 break;
160 case PUGL_CLOSE:
161 //quit = 1;
162 break;
163 case PUGL_KEY_PRESS:
164 fprintf(stderr, "Key %u (char %u) press (%s)%s\n",
165 event->key.keycode, event->key.character, event->key.utf8,
166 event->key.filter ? " (filtered)" : "");
167 if (event->key.character == 'q' ||
168 event->key.character == 'Q' ||
169 event->key.character == PUGL_CHAR_ESCAPE) {
170 //quit = 1;
171 }
172 break;
173 case PUGL_KEY_RELEASE:
174 fprintf(stderr, "Key %u (char %u) release (%s)%s\n",
175 event->key.keycode, event->key.character, event->key.utf8,
176 event->key.filter ? " (filtered)" : "");
177 break;
178 case PUGL_MOTION_NOTIFY:
179 {
180 auto mouseMoveEvent = std::make_shared<MouseMoveEvent>();
181 mouseMoveEvent->x = event->motion.x;
182 mouseMoveEvent->y = event->motion.y;
183 native->event_queue.push_back(mouseMoveEvent);
184 }
185 break;
186 case PUGL_BUTTON_PRESS:
187 case PUGL_BUTTON_RELEASE:
188 {
189 auto buttonEvent = std::make_shared<ButtonEvent>();
190 buttonEvent->x = event->button.x;
191 buttonEvent->y = event->button.y;
192 switch(event->button.button) {
193 case 1:
194 buttonEvent->button = MouseButton::left;
195 break;
196 case 2:
197 buttonEvent->button = MouseButton::middle;
198 break;
199 case 3:
200 buttonEvent->button = MouseButton::right;
201 break;
202 default:
203 WARN(X11, "Unknown button %d, setting to MouseButton::left\n",
204 event->button.button);
205 buttonEvent->button = MouseButton::left;
206 break;
207 }
208
209 buttonEvent->direction =
210 (event->type == PUGL_BUTTON_PRESS) ?
211 Direction::down : Direction::up;
212
213 buttonEvent->doubleClick =
214 (event->type == PUGL_BUTTON_PRESS) &&
215 ((event->button.time - native->last_click) < 200);
216
217 if(event->type == PUGL_BUTTON_PRESS)
218 {
219 native->last_click = event->button.time;
220 }
221 native->event_queue.push_back(buttonEvent);
222 }
223 fprintf(stderr, "Mouse %d %s at %f,%f ",
224 event->button.button,
225 (event->type == PUGL_BUTTON_PRESS) ? "down" : "up",
226 event->button.x,
227 event->button.y);
228 ///printModifiers(view, event->scroll.state);
229 break;
230 case PUGL_SCROLL:
231 {
232 auto scrollEvent = std::make_shared<ScrollEvent>();
233 scrollEvent->x = event->scroll.x;
234 scrollEvent->y = event->scroll.y;
235 scrollEvent->delta = event->scroll.dy * -1;//scroll * ((xevent.xbutton.button == 4) ? -1 : 1);
236 native->event_queue.push_back(scrollEvent);
237 }
238 fprintf(stderr, "Scroll %f %f %f %f ",
239 event->scroll.x, event->scroll.y, event->scroll.dx, event->scroll.dy);
240 //printModifiers(view, event->scroll.state);
241 //dist += event->scroll.dy;
242 //if (dist < 10.0f) {
243 // dist = 10.0f;
244 //}
245 puglPostRedisplay(view);
246 break;
247 case PUGL_ENTER_NOTIFY:
248 fprintf(stderr, "Entered\n");
249 break;
250 case PUGL_LEAVE_NOTIFY:
251 fprintf(stderr, "Exited\n");
252 break;
253 case PUGL_FOCUS_IN:
254 fprintf(stderr, "Focus in\n");
255 break;
256 case PUGL_FOCUS_OUT:
257 fprintf(stderr, "Focus out\n");
258 break;
259 }
260 }
261
onReshape(PuglView * view,int width,int height)262 void NativeWindowPugl::onReshape(PuglView* view, int width, int height)
263 {
264 glMatrixMode(GL_PROJECTION);
265 glLoadIdentity();
266 glViewport(0, 0, width, height);
267 }
268
onDisplay(PuglView * view)269 void NativeWindowPugl::onDisplay(PuglView* view)
270 {
271 NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view);
272 Window& window = native->window;
273 //window.redraw();
274
275 if((window.wpixbuf.width < 16) || (window.wpixbuf.height < 16))
276 {
277 return;
278 }
279
280 puglEnterContext(view);
281
282 glDisable(GL_DEPTH_TEST);
283 glClear(GL_COLOR_BUFFER_BIT);
284
285 glMatrixMode(GL_MODELVIEW);
286 glLoadIdentity();
287 glTranslatef(0.0f, 0.0f, 0.0f);
288
289 GLuint image;
290
291 glGenTextures(1, &image);
292
293 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
294 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
295
296 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
297 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
298 glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
299
300 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
301 glTexImage2D(GL_TEXTURE_2D,
302 0, GL_RGBA,
303 window.wpixbuf.width,
304 window.wpixbuf.height,
305 0, GL_RGB, GL_UNSIGNED_BYTE,
306 window.wpixbuf.buf);
307
308 glEnable(GL_TEXTURE_2D);
309
310 glBegin(GL_QUADS);
311 glTexCoord2d(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
312 glTexCoord2d(0.0f, -1.0f); glVertex2f(-1.0f, 1.0f);
313 glTexCoord2d(1.0f, -1.0f); glVertex2f( 1.0f, 1.0f);
314 glTexCoord2d(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
315 glEnd();
316
317 glDeleteTextures(1, &image);
318 glDisable(GL_TEXTURE_2D);
319 glFlush();
320
321 puglLeaveContext(view, true);
322 }
323
onMouse(PuglView * view,int button,bool press,int x,int y)324 void NativeWindowPugl::onMouse(PuglView* view, int button, bool press, int x, int y)
325 {
326 NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view);
327
328 DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button,
329 press? "down":"up", x, y);
330
331 ButtonEvent* e = new ButtonEvent();
332 e->x = x;
333 e->y = y;
334
335 switch(button) {
336 case 1:
337 e->button = MouseButton::left;
338 break;
339 case 2:
340 e->button = MouseButton::middle;
341 break;
342 case 3:
343 default:
344 e->button = MouseButton::right;
345 break;
346 }
347
348 e->direction = press ? Direction::down : Direction::up;
349 e->doubleClick = false;
350
351 native->eventq.push_back(e);
352 }
353
onKeyboard(PuglView * view,bool press,uint32_t key)354 void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key)
355 {
356 NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view);
357
358 KeyEvent* e = new KeyEvent();
359 e->direction = press ? Direction::down : Direction::up;
360
361 switch(key)
362 {
363 case PUGL_KEY_LEFT: e->keycode = Key::left; break;
364 case PUGL_KEY_RIGHT: e->keycode = Key::right; break;
365 case PUGL_KEY_UP: e->keycode = Key::up; break;
366 case PUGL_KEY_DOWN: e->keycode = Key::down; break;
367 case PUGL_KEY_PAGE_UP: e->keycode = Key::pageDown; break;
368 case PUGL_KEY_PAGE_DOWN: e->keycode = Key::pageUp; break;
369 default: e->keycode = Key::unknown; break;
370 }
371
372 // TODO: perform character type check
373 if(e->keycode == Key::unknown)
374 {
375 e->keycode = Key::character;
376 e->text.assign(1, (char)key);
377 }
378
379 native->eventq.push_back(e);
380 }
381
382 } // GUI::
383