/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * nativewindow_pugl.cc * * Fri Dec 28 18:45:57 CET 2012 * Copyright 2012 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of DrumGizmo. * * DrumGizmo is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * DrumGizmo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "nativewindow_pugl.h" #include #include #ifdef __APPLE__ #include #else #include #include #include #endif #include "window.h" #include "guievent.h" #include namespace GUI { NativeWindowPugl::NativeWindowPugl(void* native_window, Window& window) : window(window) { INFO(nativewindow, "Running with PuGL native window\n"); view = puglInit(nullptr, nullptr); puglInitContextType(view, PUGL_GL); if(native_window) { puglInitWindowParent(view, (PuglNativeWindow)native_window); } puglInitWindowClass(view, "DrumgGizmo"); puglInitWindowSize(view, 750, 466); puglInitResizable(view, true); puglCreateWindow(view, "DrumGizmo"); puglSetHandle(view, (PuglHandle)this); puglSetEventFunc(view, onEvent); } NativeWindowPugl::~NativeWindowPugl() { puglDestroy(view); } void NativeWindowPugl::setFixedSize(std::size_t width, std::size_t height) { // redraw(); } void NativeWindowPugl::resize(std::size_t width, std::size_t height) { // DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height); // init(); // redraw(); } std::pair NativeWindowPugl::getSize() const { int width, height; puglGetSize(view, &width, &height); return {width, height}; } void NativeWindowPugl::move(int x, int y) { // redraw(); } void NativeWindowPugl::show() { puglShowWindow(view); } void NativeWindowPugl::hide() { puglHideWindow(view); } bool NativeWindowPugl::visible() const { return puglGetVisible(view); } void NativeWindowPugl::redraw(const Rect& dirty_rect) { //puglPostRedisplay(view);// handleBuffer(); onDisplay(view); } void NativeWindowPugl::setCaption(const std::string &caption) { // redraw(); } void NativeWindowPugl::grabMouse(bool grab) { puglGrabFocus(view); } EventQueue NativeWindowPugl::getEvents() { puglProcessEvents(view); EventQueue events; std::swap(events, event_queue); return events; } void* NativeWindowPugl::getNativeWindowHandle() const { return (void*)puglGetNativeWindow(view); } void NativeWindowPugl::onEvent(PuglView* view, const PuglEvent* event) { NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); switch(event->type) { case PUGL_NOTHING: break; case PUGL_CONFIGURE: onReshape(view, event->configure.width, event->configure.height); { auto resize_event = std::make_shared(); resize_event->width = event->configure.width; resize_event->height = event->configure.height; native->event_queue.push_back(resize_event); } break; case PUGL_EXPOSE: onDisplay(view); break; case PUGL_CLOSE: //quit = 1; break; case PUGL_KEY_PRESS: fprintf(stderr, "Key %u (char %u) press (%s)%s\n", event->key.keycode, event->key.character, event->key.utf8, event->key.filter ? " (filtered)" : ""); if (event->key.character == 'q' || event->key.character == 'Q' || event->key.character == PUGL_CHAR_ESCAPE) { //quit = 1; } break; case PUGL_KEY_RELEASE: fprintf(stderr, "Key %u (char %u) release (%s)%s\n", event->key.keycode, event->key.character, event->key.utf8, event->key.filter ? " (filtered)" : ""); break; case PUGL_MOTION_NOTIFY: { auto mouseMoveEvent = std::make_shared(); mouseMoveEvent->x = event->motion.x; mouseMoveEvent->y = event->motion.y; native->event_queue.push_back(mouseMoveEvent); } break; case PUGL_BUTTON_PRESS: case PUGL_BUTTON_RELEASE: { auto buttonEvent = std::make_shared(); buttonEvent->x = event->button.x; buttonEvent->y = event->button.y; switch(event->button.button) { case 1: buttonEvent->button = MouseButton::left; break; case 2: buttonEvent->button = MouseButton::middle; break; case 3: buttonEvent->button = MouseButton::right; break; default: WARN(X11, "Unknown button %d, setting to MouseButton::left\n", event->button.button); buttonEvent->button = MouseButton::left; break; } buttonEvent->direction = (event->type == PUGL_BUTTON_PRESS) ? Direction::down : Direction::up; buttonEvent->doubleClick = (event->type == PUGL_BUTTON_PRESS) && ((event->button.time - native->last_click) < 200); if(event->type == PUGL_BUTTON_PRESS) { native->last_click = event->button.time; } native->event_queue.push_back(buttonEvent); } fprintf(stderr, "Mouse %d %s at %f,%f ", event->button.button, (event->type == PUGL_BUTTON_PRESS) ? "down" : "up", event->button.x, event->button.y); ///printModifiers(view, event->scroll.state); break; case PUGL_SCROLL: { auto scrollEvent = std::make_shared(); scrollEvent->x = event->scroll.x; scrollEvent->y = event->scroll.y; scrollEvent->delta = event->scroll.dy * -1;//scroll * ((xevent.xbutton.button == 4) ? -1 : 1); native->event_queue.push_back(scrollEvent); } fprintf(stderr, "Scroll %f %f %f %f ", event->scroll.x, event->scroll.y, event->scroll.dx, event->scroll.dy); //printModifiers(view, event->scroll.state); //dist += event->scroll.dy; //if (dist < 10.0f) { // dist = 10.0f; //} puglPostRedisplay(view); break; case PUGL_ENTER_NOTIFY: fprintf(stderr, "Entered\n"); break; case PUGL_LEAVE_NOTIFY: fprintf(stderr, "Exited\n"); break; case PUGL_FOCUS_IN: fprintf(stderr, "Focus in\n"); break; case PUGL_FOCUS_OUT: fprintf(stderr, "Focus out\n"); break; } } void NativeWindowPugl::onReshape(PuglView* view, int width, int height) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, width, height); } void NativeWindowPugl::onDisplay(PuglView* view) { NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); Window& window = native->window; //window.redraw(); if((window.wpixbuf.width < 16) || (window.wpixbuf.height < 16)) { return; } puglEnterContext(view); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0f, 0.0f, 0.0f); GLuint image; glGenTextures(1, &image); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window.wpixbuf.width, window.wpixbuf.height, 0, GL_RGB, GL_UNSIGNED_BYTE, window.wpixbuf.buf); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2d(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2d(0.0f, -1.0f); glVertex2f(-1.0f, 1.0f); glTexCoord2d(1.0f, -1.0f); glVertex2f( 1.0f, 1.0f); glTexCoord2d(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); glEnd(); glDeleteTextures(1, &image); glDisable(GL_TEXTURE_2D); glFlush(); puglLeaveContext(view, true); } void NativeWindowPugl::onMouse(PuglView* view, int button, bool press, int x, int y) { NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button, press? "down":"up", x, y); ButtonEvent* e = new ButtonEvent(); e->x = x; e->y = y; switch(button) { case 1: e->button = MouseButton::left; break; case 2: e->button = MouseButton::middle; break; case 3: default: e->button = MouseButton::right; break; } e->direction = press ? Direction::down : Direction::up; e->doubleClick = false; native->eventq.push_back(e); } void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key) { NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); KeyEvent* e = new KeyEvent(); e->direction = press ? Direction::down : Direction::up; switch(key) { case PUGL_KEY_LEFT: e->keycode = Key::left; break; case PUGL_KEY_RIGHT: e->keycode = Key::right; break; case PUGL_KEY_UP: e->keycode = Key::up; break; case PUGL_KEY_DOWN: e->keycode = Key::down; break; case PUGL_KEY_PAGE_UP: e->keycode = Key::pageDown; break; case PUGL_KEY_PAGE_DOWN: e->keycode = Key::pageUp; break; default: e->keycode = Key::unknown; break; } // TODO: perform character type check if(e->keycode == Key::unknown) { e->keycode = Key::character; e->text.assign(1, (char)key); } native->eventq.push_back(e); } } // GUI::