From 0531409611867ae8dad711e52d6534fa634d40cc Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Sun, 10 Sep 2017 17:52:32 +0200
Subject: Initial steps towards pugl domination!

---
 .gitmodules                     |   3 +
 configure.ac                    |  40 +++--
 plugin/Makefile.mingw32.in      |   7 +-
 plugingui/Makefile.am           |  38 +++-
 plugingui/nativewindow.h        |   4 +-
 plugingui/nativewindow_pugl.cc  | 372 +++++++++++++++++++++++++++-------------
 plugingui/nativewindow_pugl.h   |  45 +++--
 plugingui/nativewindow_win32.cc |   4 +-
 plugingui/nativewindow_win32.h  |   4 +-
 plugingui/nativewindow_x11.cc   |  29 +---
 plugingui/nativewindow_x11.h    |   4 +-
 pugl                            |   1 +
 12 files changed, 360 insertions(+), 191 deletions(-)
 create mode 160000 pugl

diff --git a/.gitmodules b/.gitmodules
index 90bfcd8..91b8fee 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -11,3 +11,6 @@
 [submodule "getoptpp"]
 	path = getoptpp
 	url = https://github.com/cgloeckner/getoptpp
+[submodule "pugl"]
+	path = pugl
+	url = http://git.drobilla.net/pugl.git/
diff --git a/configure.ac b/configure.ac
index 1a3e285..f86ee54 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,7 +136,7 @@ dnl Check for GUI backend
 dnl ===========================
 AC_CANONICAL_HOST
 AC_ARG_ENABLE([gui],
-	AS_HELP_STRING([--enable-gui[=backend]], [Use specified gui backend. Can be win32, x11, pugl or auto [default=auto]]),,
+	AS_HELP_STRING([--enable-gui[=backend]], [Use specified gui backend. Can be x11, win32, cocoa, pugl-x11, pugl-win32, pugl-cocoa or auto [default=auto]]),,
         [enable_gui="auto"])
 
 AS_IF([test "x$enable_gui" = "xyes"], [enable_gui="auto"])
@@ -144,9 +144,9 @@ AS_IF([test "x$enable_gui" = "xyes"], [enable_gui="auto"])
 AS_IF([test "x$enable_gui" = "xauto"],
       [AC_MSG_RESULT([Auto setting gui based on host: $host_os])
 	     AS_CASE([$host_os],
-		      [darwin*], [enable_gui="cocoa"],
-		      [linux*|*bsd*], [enable_gui="x11"],
-		      [msys|mingw*|windows*|winnt|cygwin], [enable_gui="win32"],
+		      [darwin*], [enable_gui="pugl-cocoa"],
+		      [linux*|*bsd*], [enable_gui="pugl-x11"],
+		      [msys|mingw*|windows*|winnt|cygwin], [enable_gui="pugl-win32"],
 
 		      AC_MSG_ERROR([Your platform is not currently supported])
 	     )]
@@ -155,12 +155,8 @@ AS_IF([test "x$enable_gui" = "xauto"],
 AS_IF(
   [test "x$enable_gui" = "xx11"],
   [AC_MSG_RESULT([Setting gui backend to X11])
-  dnl ======================
-  dnl Check for Xlib
-  dnl ======================
   PKG_CHECK_MODULES(X11, x11 >= 1.0)
   PKG_CHECK_MODULES(XEXT, xext >= 1.0)
-
   GUI_CPPFLAGS="-DUI_X11 $X11_CFLAGS $XEXT_CFLAGS"
   GUI_LIBS="$X11_LIBS $XEXT_LIBS"],
 
@@ -169,26 +165,40 @@ AS_IF(
   GUI_CPPFLAGS="-DUI_WIN32"
   GUI_LIBS="-lgdi32 -lsetupapi -lws2_32 -lcomctl32"],
 
-  [test "x$enable_gui" = "xpugl"],
-  [AC_MSG_RESULT([Setting gui backend to Pugl])
-  GUI_CPPFLAGS="-DUI_PUGL -I../../pugl"
-  GUI_LIBS="-lGLU -lGL -lglut"],
-
   [test "x$enable_gui" = "xcocoa"],
   [AC_MSG_RESULT([Setting gui backend to Cocoa])
   GUI_CPPFLAGS="-DUI_COCOA -framework Cocoa"
   GUI_LIBS="-framework Cocoa"],
 
+  [test "x$enable_gui" = "xpugl-x11"],
+  [AC_MSG_RESULT([Setting gui backend to Pugl-X11])
+  PKG_CHECK_MODULES(X11, x11 >= 1.0)
+  PKG_CHECK_MODULES(XEXT, xext >= 1.0)
+  GUI_CPPFLAGS="-DUI_PUGL -DPUGL_HAVE_GL $X11_CFLAGS $XEXT_CFLAGS"
+  GUI_LIBS="-lGL $X11_LIBS $XEXT_LIBS"],
+
+  [test "x$enable_gui" = "xpugl-win32"],
+  [AC_MSG_RESULT([Setting gui backend to Pugl-Win32])
+  GUI_CPPFLAGS="-DUI_PUGL -DPUGL_HAVE_GL"
+  GUI_LIBS="-lopengl32 -lgdi32 -luser32 -lsetupapi -lws2_32 -lcomctl32"],
+
+  [test "x$enable_gui" = "xpugl-cocoa"],
+  [AC_MSG_RESULT([Setting gui backend to Pugl-Cocoa])
+  GUI_CPPFLAGS="-DUI_PUGL -DPUGL_HAVE_GL -framework Cocoa"
+  GUI_LIBS="-lCocoa -lOpenGL -framework Cocoa"],
+
   AC_MSG_ERROR([*** No GUI backend has been selected ***])
 )
 
 AC_SUBST(GUI_CPPFLAGS)
 AC_SUBST(GUI_LIBS)
 
-AM_CONDITIONAL([ENABLE_PUGL], [test "x$enable_gui" = "xpugl"])
-AM_CONDITIONAL([ENABLE_WIN32], [test "x$enable_gui" = "xwin32"])
 AM_CONDITIONAL([ENABLE_X11], [test "x$enable_gui" = "xx11"])
+AM_CONDITIONAL([ENABLE_WIN32], [test "x$enable_gui" = "xwin32"])
 AM_CONDITIONAL([ENABLE_COCOA], [test "x$enable_gui" = "xcocoa"])
+AM_CONDITIONAL([ENABLE_PUGL_X11], [test "x$enable_gui" = "xpugl-x11"])
+AM_CONDITIONAL([ENABLE_PUGL_WIN32], [test "x$enable_gui" = "xpugl-win32"])
+AM_CONDITIONAL([ENABLE_PUGL_COCOA], [test "x$enable_gui" = "xpugl-cocoa"])
 
 dnl ======================
 dnl Compile unit tests
diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in
index 3fe5933..f7623df 100644
--- a/plugin/Makefile.mingw32.in
+++ b/plugin/Makefile.mingw32.in
@@ -74,7 +74,7 @@ GUI_SRC = \
 	@top_srcdir@/plugingui/listboxthin.cc \
 	@top_srcdir@/plugingui/maintab.cc \
 	@top_srcdir@/plugingui/mainwindow.cc \
-	@top_srcdir@/plugingui/nativewindow_win32.cc \
+	@top_srcdir@/plugingui/nativewindow_pugl.cc \
 	@top_srcdir@/plugingui/painter.cc \
 	@top_srcdir@/plugingui/pixelbuffer.cc \
 	@top_srcdir@/plugingui/pluginconfig.cc \
@@ -97,9 +97,10 @@ GUI_SRC = \
 	@top_srcdir@/plugingui/verticalline.cc \
 	@top_srcdir@/plugingui/widget.cc \
 	@top_srcdir@/plugingui/window.cc \
-	@top_srcdir@/plugingui/lodepng/lodepng.cpp
+	@top_srcdir@/plugingui/lodepng/lodepng.cpp \
+	@top_srcdir@/pugl/pugl/pugl_win.cpp
 
-GUI_CPPFLAGS=-I@top_srcdir@/plugingui/ -DUSE_THREAD @GUI_CPPFLAGS@
+GUI_CPPFLAGS=-I@top_srcdir@/plugingui/ -I@top_srcdir@/pugl -DUSE_THREAD @GUI_CPPFLAGS@
 GUI_LIBS=@GUI_LIBS@
 
 DBG_SRC = \
diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am
index 714b21c..f9d9c09 100644
--- a/plugingui/Makefile.am
+++ b/plugingui/Makefile.am
@@ -42,6 +42,8 @@ libdggui_la_CPPFLAGS = \
 	-DLODEPNG_NO_COMPILE_ERROR_TEXT \
 	-DLODEPNG_NO_COMPILE_CPP
 
+libdggui_la_CFLAGS =
+
 libdggui_la_LIBADD = \
 	$(GUI_LIBS) $(PTHREAD_LIBS)
 
@@ -110,18 +112,42 @@ nodist_libdggui_la_SOURCES += \
 	nativewindow_win32.cc
 endif
 
-if ENABLE_PUGL
-nodist_libdggui_la_SOURCES += \
-	nativewindow_pugl.cc \
-	$(top_srcdir)/pugl/pugl/pugl_x11.c
-endif
-
 #if ENABLE_COCOA
 #nodist_libdggui_la_SOURCES += \
 #	nativewindow_cocoa.m \
 #	nativewindow_cocoa.cc
 #endif
 
+if ENABLE_PUGL_X11
+nodist_libdggui_la_SOURCES += \
+	nativewindow_pugl.cc \
+	$(top_srcdir)/pugl/pugl/pugl_x11.c
+
+libdggui_la_CPPFLAGS += \
+	-I$(top_srcdir)/pugl
+
+libdggui_la_CFLAGS += \
+	-std=c99
+endif
+
+if ENABLE_PUGL_WIN32
+nodist_libdggui_la_SOURCES += \
+	nativewindow_pugl.cc \
+	$(top_srcdir)/pugl/pugl/pugl_win.cpp
+
+libdggui_la_CPPFLAGS += \
+	-I$(top_srcdir)/pugl
+endif
+
+if ENABLE_PUGL_COCOA
+nodist_libdggui_la_SOURCES += \
+	nativewindow_pugl.cc \
+	$(top_srcdir)/pugl/pugl/pugl_osx.m
+
+libdggui_la_CPPFLAGS += \
+	-I$(top_srcdir)/pugl
+endif
+
 plugingui_LDADD = libdggui.la $(top_srcdir)/src/libdg.la
 
 plugingui_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) \
diff --git a/plugingui/nativewindow.h b/plugingui/nativewindow.h
index 6dcb308..3995d43 100644
--- a/plugingui/nativewindow.h
+++ b/plugingui/nativewindow.h
@@ -52,7 +52,7 @@ public:
 	virtual void resize(std::size_t width, std::size_t height) = 0;
 
 	//! Query size of the native window.
-	virtual std::pair<std::size_t, std::size_t> getSize() = 0;
+	virtual std::pair<std::size_t, std::size_t> getSize() const = 0;
 
 	//! Move the window to a new position.
 	//! Note: negative value are allowed.
@@ -60,7 +60,7 @@ public:
 
 	//! Query the screen position of the native window.
 	//! Note: returned values can be negative.
-	virtual std::pair<int, int> getPosition() = 0;
+	virtual std::pair<int, int> getPosition() const = 0;
 
 	//! Show the window if it is hidden.
 	virtual void show() = 0;
diff --git a/plugingui/nativewindow_pugl.cc b/plugingui/nativewindow_pugl.cc
index d7cca54..59f03b1 100644
--- a/plugingui/nativewindow_pugl.cc
+++ b/plugingui/nativewindow_pugl.cc
@@ -42,46 +42,284 @@
 
 #include <hugin.hpp>
 
-namespace GUI {
+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<std::size_t, std::size_t> 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<ResizeEvent>();
+			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>();
+			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>();
+			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>();
+			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();
+
+	printf("!!! %p %d %d\n", native, (int)window.wpixbuf.width, (int)window.wpixbuf.height);
+	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);
+	//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_LINEAR); //GL_NEAREST = no smoothing
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	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,
+	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.0, 0.0); glVertex2f(0.0, 0.0);
-	glTexCoord2d(0.0, 1.0); glVertex2f(0.0, window.wpixbuf.height);
-	glTexCoord2d(1.0, 1.0); glVertex2f(window.wpixbuf.width, window.wpixbuf.height);
-	glTexCoord2d(1.0, 0.0); glVertex2f(window.wpixbuf.width, 0.0);
+	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();
 
-	puglPostRedisplay(view);
+	puglLeaveContext(view, true);
 }
 
 void NativeWindowPugl::onMouse(PuglView* view, int button, bool press, int x, int y)
@@ -145,114 +383,4 @@ void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key)
 	native->eventq.push_back(e);
 }
 
-NativeWindowPugl::NativeWindowPugl(void* native_window, Window& window)
-	: window(window)
-	, native_window(native_window)
-{
-	INFO(nativewindow, "Running with PuGL native window\n");
-	init();
-}
-
-NativeWindowPugl::~NativeWindowPugl()
-{
-	puglDestroy(view);
-}
-
-void NativeWindowPugl::init()
-{
-	PuglView* oldView = view;
-	if(view)
-	{
-		oldView = view;
-	}
-
-//	view = puglCreate(0, "DrumgGizmo", window.x(), window.y(), false, true);
-	view = puglCreate((PuglNativeWindow)native_window, "DrumgGizmo", 370, 330, false, true);
-	puglSetHandle(view, (PuglHandle)this);
-	puglSetDisplayFunc(view, onDisplay);
-	puglSetMouseFunc(view, onMouse);
-	puglSetKeyboardFunc(view, onKeyboard);
-
-	if(oldView)
-	{
-		free(oldView);
-	}
-}
-
-void NativeWindowPugl::setFixedSize(int width, int height)
-{
-//	redraw();
-}
-
-void NativeWindowPugl::resize(int width, int height)
-{
-//	DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height);
-//	init();
-//	redraw();
-}
-
-void NativeWindowPugl::move(int x, int y)
-{
-//	redraw();
-}
-
-void NativeWindowPugl::show()
-{
-//	redraw();
-}
-
-void NativeWindowPugl::hide()
-{
-//	redraw();
-}
-
-void NativeWindowPugl::handleBuffer()
-{
-	onDisplay(view);
-}
-
-void NativeWindowPugl::redraw()
-{
-//	handleBuffer();
-}
-
-void NativeWindowPugl::setCaption(const std::string &caption)
-{
-//	redraw();
-}
-
-void NativeWindowPugl::grabMouse(bool grab)
-{
-//	redraw();
-}
-
-bool NativeWindowPugl::hasEvent()
-{
-	// dirty hack - assume that this function is called enough times to get fluent gui
-	// ^^ Bad assumption
-	puglProcessEvents(view);
-	return !eventq.empty();
-}
-
-Event *NativeWindowPugl::getNextEvent()
-{
-	Event *event = nullptr;
-
-	if(!eventq.empty()) {
-		event = eventq.front();
-		eventq.pop_front();
-	}
-	return event;
-}
-
-Event *NativeWindowPugl::peekNextEvent()
-{
-	Event *event = nullptr;
-
-	if(!eventq.empty()) {
-		event = eventq.front();
-	}
-	return event;
-}
-
 } // GUI::
diff --git a/plugingui/nativewindow_pugl.h b/plugingui/nativewindow_pugl.h
index 000a48b..6a667f4 100644
--- a/plugingui/nativewindow_pugl.h
+++ b/plugingui/nativewindow_pugl.h
@@ -27,11 +27,15 @@
 #pragma once
 
 #include "nativewindow.h"
-#include "pugl.h"
+extern "C"
+{
+#include <pugl/pugl.h>
+}
 
 #include <list>
 
-namespace GUI {
+namespace GUI
+{
 
 class Event;
 class Window;
@@ -41,32 +45,39 @@ public:
 	NativeWindowPugl(void* native_window, Window& window);
 	~NativeWindowPugl();
 
-	void init();
-	void setFixedSize(int width, int height);
-	void resize(int width, int height);
-	void move(int x, int y);
-	void show();
-	void setCaption(const std::string &caption);
-	void hide();
-	void handleBuffer();
-	void redraw();
-	void grabMouse(bool grab);
-
-	bool hasEvent();
-	Event *getNextEvent();
-	Event *peekNextEvent();
+	void setFixedSize(std::size_t width, std::size_t height) override;
+	void resize(std::size_t width, std::size_t height) override;
+	std::pair<std::size_t, std::size_t> getSize() const override;
+
+	void move(int x, int y) override;
+	std::pair<int, int> getPosition() const override{ return {}; }
+
+	void show() override;
+	void setCaption(const std::string &caption) override;
+	void hide() override;
+	bool visible() const override;
+	void redraw(const Rect& dirty_rect) override;
+	void grabMouse(bool grab) override;
+
+	EventQueue getEvents() override;
+
+	void* getNativeWindowHandle() const override;
 
 private:
 	Window& window;
-	void* native_window{nullptr};
 	PuglView* view{nullptr};
 
 	std::list<Event*> eventq;
 
 	// Internal pugl c-callbacks
+	static void onEvent(PuglView* view, const PuglEvent* event);
+	static void onReshape(PuglView* view, int width, int height);
 	static void onDisplay(PuglView* view);
 	static void onMouse(PuglView* view, int button, bool press, int x, int y);
 	static void onKeyboard(PuglView* view, bool press, uint32_t key);
+
+	EventQueue event_queue;
+	std::uint32_t last_click{0};
 };
 
 } // GUI::
diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc
index 1de78fb..5cfb179 100644
--- a/plugingui/nativewindow_win32.cc
+++ b/plugingui/nativewindow_win32.cc
@@ -432,7 +432,7 @@ void NativeWindowWin32::resize(std::size_t width, std::size_t height)
 	SetWindowPos(hwnd, nullptr, -1, -1, width + w, height + h, SWP_NOMOVE);
 }
 
-std::pair<std::size_t, std::size_t> NativeWindowWin32::getSize()
+std::pair<std::size_t, std::size_t> NativeWindowWin32::getSize() const
 {
 	RECT rect;
 	GetClientRect(m_hwnd, &rect);
@@ -444,7 +444,7 @@ void NativeWindowWin32::move(int x, int y)
 	SetWindowPos(m_hwnd, nullptr, (int)x, (int)y, -1, -1, SWP_NOSIZE);
 }
 
-std::pair<int, int> NativeWindowWin32::getPosition()
+std::pair<int, int> NativeWindowWin32::getPosition() const
 {
 	RECT rect;
 	GetClientRect(m_hwnd, &rect);
diff --git a/plugingui/nativewindow_win32.h b/plugingui/nativewindow_win32.h
index bb407d8..2945be6 100644
--- a/plugingui/nativewindow_win32.h
+++ b/plugingui/nativewindow_win32.h
@@ -46,9 +46,9 @@ public:
 
 	void setFixedSize(std::size_t width, std::size_t height) override;
 	void resize(std::size_t width, std::size_t height) override;
-	std::pair<std::size_t, std::size_t> getSize() override;
+	std::pair<std::size_t, std::size_t> getSize() const override;
 	void move(int x, int y) override;
-	std::pair<int, int> getPosition() override;
+	std::pair<int, int> getPosition() const override;
 	void show() override;
 	bool visible() const override;
 	void hide() override;
diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc
index 5faecc1..056c69f 100644
--- a/plugingui/nativewindow_x11.cc
+++ b/plugingui/nativewindow_x11.cc
@@ -130,25 +130,14 @@ void NativeWindowX11::setFixedSize(std::size_t width, std::size_t height)
 
 	resize(width, height);
 
-	XSizeHints* size_hints;
-	size_hints = XAllocSizeHints();
+	XSizeHints size_hints;
+	memset(&size_hints, 0, sizeof(size_hints));
 
-	if(size_hints == nullptr)
-	{
-		ERR(X11,"XMallocSizeHints() failed");
-		return;
-	}
-
-	size_hints->flags = USPosition | PMinSize | PMaxSize;
-	size_hints->min_width = size_hints->max_width = width;
-	size_hints->min_height = size_hints->max_height = height;
-
-	//size_hints->min_aspect.x = (float)window.width()/(float)window.height();
-	//size_hints->max_aspect.x = (float)window.width()/(float)window.height();
-	//size_hints->min_aspect.y = (float)window.width()/(float)window.height();
-	//size_hints->max_aspect.y = size_hints->min_aspect.y;
+	size_hints.flags = PMinSize|PMaxSize;
+	size_hints.min_width = size_hints.max_width = (int)width;
+	size_hints.min_height = size_hints.max_height = (int)height;
 
-	XSetWMNormalHints(display, xwindow, size_hints);
+	XSetNormalHints(display, xwindow, &size_hints);
 }
 
 void NativeWindowX11::resize(std::size_t width, std::size_t height)
@@ -161,7 +150,7 @@ void NativeWindowX11::resize(std::size_t width, std::size_t height)
 	XResizeWindow(display, xwindow, width, height);
 }
 
-std::pair<std::size_t, std::size_t> NativeWindowX11::getSize()
+std::pair<std::size_t, std::size_t> NativeWindowX11::getSize() const
 {
 //	XWindowAttributes attributes;
 //	XGetWindowAttributes(display, xwindow, &attributes);
@@ -175,7 +164,7 @@ std::pair<std::size_t, std::size_t> NativeWindowX11::getSize()
 	             &x, &y,
 	             &width, &height, &border, &depth);
 
-	return std::make_pair(width, height);
+	return {width, height};
 }
 
 void NativeWindowX11::move(int x, int y)
@@ -188,7 +177,7 @@ void NativeWindowX11::move(int x, int y)
 	XMoveWindow(display, xwindow, x, y);
 }
 
-std::pair<int, int> NativeWindowX11::getPosition()
+std::pair<int, int> NativeWindowX11::getPosition() const
 {
 	::Window root_window;
 	::Window child_window;
diff --git a/plugingui/nativewindow_x11.h b/plugingui/nativewindow_x11.h
index c6c038e..eb88b6c 100644
--- a/plugingui/nativewindow_x11.h
+++ b/plugingui/nativewindow_x11.h
@@ -48,9 +48,9 @@ public:
 	// From NativeWindow:
 	void setFixedSize(std::size_t width, std::size_t height) override;
 	void resize(std::size_t width, std::size_t height) override;
-	std::pair<std::size_t, std::size_t> getSize() override;
+	std::pair<std::size_t, std::size_t> getSize() const override;
 	void move(int x, int y) override;
-	std::pair<int, int> getPosition() override;
+	std::pair<int, int> getPosition() const override;
 	void show() override;
 	void hide() override;
 	bool visible() const override;
diff --git a/pugl b/pugl
new file mode 160000
index 0000000..8b8f97d
--- /dev/null
+++ b/pugl
@@ -0,0 +1 @@
+Subproject commit 8b8f97dac9dea213875db4cfc3a0bd2033b2f6a1
-- 
cgit v1.2.3