commit 8bccf9fcd6aef06e61b0462d8df1e23c07e743cf
parent a9a1b47a14ae9d57b16df11f944f7a19874c5bb6
Author: falkTX <falktx@gmail.com>
Date: Fri, 13 Feb 2015 00:30:01 +0000
Go back to older pugl; Import fixes from Robin; Misc fixes
Diffstat:
10 files changed, 432 insertions(+), 995 deletions(-)
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -15,8 +15,7 @@
*/
// we need this for now
-#define PUGL_HAVE_GL 1
-#define PUGL_GRAB_FOCUS 1
+//#define PUGL_GRAB_FOCUS 1
#include "AppPrivateData.hpp"
#include "../Widget.hpp"
@@ -63,7 +62,7 @@ struct Window::PrivateData {
PrivateData(App& app, Window* const self)
: fApp(app),
fSelf(self),
- fView(puglInit(nullptr, nullptr)),
+ fView(puglInit()),
fFirstInit(true),
fVisible(false),
fResizable(true),
@@ -91,7 +90,7 @@ struct Window::PrivateData {
PrivateData(App& app, Window* const self, Window& parent)
: fApp(app),
fSelf(self),
- fView(puglInit(nullptr, nullptr)),
+ fView(puglInit()),
fFirstInit(true),
fVisible(false),
fResizable(true),
@@ -129,7 +128,7 @@ struct Window::PrivateData {
PrivateData(App& app, Window* const self, const intptr_t parentId)
: fApp(app),
fSelf(self),
- fView(puglInit(nullptr, nullptr)),
+ fView(puglInit()),
fFirstInit(true),
fVisible(parentId != 0),
fResizable(parentId == 0),
@@ -193,7 +192,6 @@ struct Window::PrivateData {
puglSetCloseFunc(fView, onCloseCallback);
puglCreateWindow(fView, nullptr);
- puglEnterContext(fView);
PuglInternals* impl = fView->impl;
#if defined(DISTRHO_OS_WINDOWS)
@@ -458,7 +456,11 @@ struct Window::PrivateData {
fResizable = yesNo;
-#ifdef CARLA_OS_MAC
+#if defined(DISTRHO_OS_WINDOWS)
+ const int winFlags = fResizable ? GetWindowLong(hwnd, GWL_STYLE) | WS_SIZEBOX
+ : GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX;
+ SetWindowLong(hwnd, GWL_STYLE, winFlags);
+#elif defined(DISTRHO_OS_MAC)
// FIXME?
const uint flags(yesNo ? (NSViewWidthSizable|NSViewHeightSizable) : 0x0);
[mView setAutoresizingMask:flags];
@@ -471,7 +473,7 @@ struct Window::PrivateData {
void setSize(uint width, uint height, const bool forced = false)
{
- if (width == 0 || height == 0)
+ if (width <= 1 || height <= 1)
{
DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height);
return;
@@ -486,18 +488,15 @@ struct Window::PrivateData {
fWidth = width;
fHeight = height;
- DBGp("Window setSize called %s, size %i %i\n", forced ? "(forced)" : "(not forced)", width, height);
+ DBGp("Window setSize called %s, size %i %i, resizable %s\n", forced ? "(forced)" : "(not forced)", width, height, fResizable?"true":"false");
#if defined(DISTRHO_OS_WINDOWS)
- int winFlags = WS_POPUPWINDOW | WS_CAPTION;
-
- if (fResizable)
- winFlags |= WS_SIZEBOX;
-
+ const int winFlags = WS_POPUPWINDOW | WS_CAPTION | (fResizable ? WS_SIZEBOX : 0x0);
RECT wr = { 0, 0, static_cast<long>(width), static_cast<long>(height) };
AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST);
- SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top,
+ SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
if (! forced)
UpdateWindow(hwnd);
diff --git a/dgl/src/pugl/common.h b/dgl/src/pugl/common.h
@@ -1,121 +0,0 @@
-/*
- Copyright 2014 David Robillard <http://drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef PUGL_COMMON_H_INCLUDED
-#define PUGL_COMMON_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- @addtogroup pugl
- @{
-*/
-
-/**
- A Pugl view.
-*/
-typedef struct PuglViewImpl PuglView;
-
-/**
- A native window handle.
-
- On X11, this is a Window.
- On OSX, this is an NSView*.
- On Windows, this is a HWND.
-*/
-typedef intptr_t PuglNativeWindow;
-
-/**
- Handle for opaque user data.
-*/
-typedef void* PuglHandle;
-
-/**
- Return status code.
-*/
-typedef enum {
- PUGL_SUCCESS = 0
-} PuglStatus;
-
-/**
- Drawing context type.
-*/
-typedef enum {
- PUGL_GL,
- PUGL_CAIRO
-} PuglContextType;
-
-/**
- Convenience symbols for ASCII control characters.
-*/
-typedef enum {
- PUGL_CHAR_BACKSPACE = 0x08,
- PUGL_CHAR_ESCAPE = 0x1B,
- PUGL_CHAR_DELETE = 0x7F
-} PuglChar;
-
-/**
- Keyboard modifier flags.
-*/
-typedef enum {
- PUGL_MOD_SHIFT = 1, /**< Shift key */
- PUGL_MOD_CTRL = 1 << 1, /**< Control key */
- PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */
- PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */
-} PuglMod;
-
-/**
- Special (non-Unicode) keyboard keys.
-*/
-typedef enum {
- PUGL_KEY_F1 = 1,
- PUGL_KEY_F2,
- PUGL_KEY_F3,
- PUGL_KEY_F4,
- PUGL_KEY_F5,
- PUGL_KEY_F6,
- PUGL_KEY_F7,
- PUGL_KEY_F8,
- PUGL_KEY_F9,
- PUGL_KEY_F10,
- PUGL_KEY_F11,
- PUGL_KEY_F12,
- PUGL_KEY_LEFT,
- PUGL_KEY_UP,
- PUGL_KEY_RIGHT,
- PUGL_KEY_DOWN,
- PUGL_KEY_PAGE_UP,
- PUGL_KEY_PAGE_DOWN,
- PUGL_KEY_HOME,
- PUGL_KEY_END,
- PUGL_KEY_INSERT,
- PUGL_KEY_SHIFT,
- PUGL_KEY_CTRL,
- PUGL_KEY_ALT,
- PUGL_KEY_SUPER
-} PuglKey;
-
-/**
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* PUGL_COMMON_H_INCLUDED */
diff --git a/dgl/src/pugl/event.h b/dgl/src/pugl/event.h
@@ -1,217 +0,0 @@
-/*
- Copyright 2014 David Robillard <http://drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef PUGL_EVENT_H_INCLUDED
-#define PUGL_EVENT_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#else
-# include <stdbool.h>
-#endif
-
-#include "pugl/common.h"
-
-/**
- @addtogroup pugl
- @{
-*/
-
-/**
- The type of a PuglEvent.
-*/
-typedef enum {
- PUGL_BUTTON_PRESS,
- PUGL_BUTTON_RELEASE,
- PUGL_CONFIGURE,
- PUGL_EXPOSE,
- PUGL_KEY_PRESS,
- PUGL_KEY_RELEASE,
- PUGL_ENTER_NOTIFY,
- PUGL_LEAVE_NOTIFY,
- PUGL_MOTION_NOTIFY,
- PUGL_NOTHING,
- PUGL_SCROLL
-} PuglEventType;
-
-/**
- Reason for a PuglEventCrossing.
-*/
-typedef enum {
- PUGL_CROSSING_NORMAL, /**< Crossing due to pointer motion. */
- PUGL_CROSSING_GRAB, /**< Crossing due to a grab. */
- PUGL_CROSSING_UNGRAB /**< Crossing due to a grab release. */
-} PuglCrossingMode;
-
-/**
- Common header for all event structs.
-*/
-typedef struct {
- PuglEventType type; /**< Event type. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
-} PuglEventAny;
-
-/**
- Button press or release event.
-
- For event types PUGL_BUTTON_PRESS and PUGL_BUTTON_RELEASE.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_BUTTON_PRESS or PUGL_BUTTON_RELEASE. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- uint32_t time; /**< Time in milliseconds. */
- double x; /**< View-relative X coordinate. */
- double y; /**< View-relative Y coordinate. */
- double x_root; /**< Root-relative X coordinate. */
- double y_root; /**< Root-relative Y coordinate. */
- unsigned state; /**< Bitwise OR of PuglMod flags. */
- unsigned button; /**< 1-relative button number. */
-} PuglEventButton;
-
-/**
- Configure event for when window size or position has changed.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_CONFIGURE. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- double x; /**< New parent-relative X coordinate. */
- double y; /**< New parent-relative Y coordinate. */
- double width; /**< New width. */
- double height; /**< New height. */
-} PuglEventConfigure;
-
-/**
- Expose event for when a region must be redrawn.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_EXPOSE. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- double x; /**< View-relative X coordinate. */
- double y; /**< View-relative Y coordinate. */
- double width; /**< Width of exposed region. */
- double height; /**< Height of exposed region. */
- int count; /**< Number of expose events to follow. */
-} PuglEventExpose;
-
-/**
- Key press event.
-
- Keys that correspond to a Unicode character are expressed as a character
- code. For other keys, `character` will be 0 and `special` indicates the key
- pressed.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_KEY_PRESS or PUGL_KEY_RELEASE. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- uint32_t time; /**< Time in milliseconds. */
- double x; /**< View-relative X coordinate. */
- double y; /**< View-relative Y coordinate. */
- double x_root; /**< Root-relative X coordinate. */
- double y_root; /**< Root-relative Y coordinate. */
- unsigned state; /**< Bitwise OR of PuglMod flags. */
- uint32_t character; /**< Unicode character code, or 0. */
- PuglKey special; /**< Special key, if character is 0. */
-} PuglEventKey;
-
-/**
- Pointer crossing event (enter and leave).
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_ENTER_NOTIFY or PUGL_LEAVE_NOTIFY. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- uint32_t time; /**< Time in milliseconds. */
- double x; /**< View-relative X coordinate. */
- double y; /**< View-relative Y coordinate. */
- double x_root; /**< Root-relative X coordinate. */
- double y_root; /**< Root-relative Y coordinate. */
- unsigned state; /**< Bitwise OR of PuglMod flags. */
- PuglCrossingMode mode; /**< Reason for crossing. */
-} PuglEventCrossing;
-
-/**
- Pointer motion event.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_MOTION_NOTIFY. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- uint32_t time; /**< Time in milliseconds. */
- double x; /**< View-relative X coordinate. */
- double y; /**< View-relative Y coordinate. */
- double x_root; /**< Root-relative X coordinate. */
- double y_root; /**< Root-relative Y coordinate. */
- unsigned state; /**< Bitwise OR of PuglMod flags. */
- bool is_hint; /**< True iff this event is a motion hint. */
- bool focus; /**< True iff this is the focused window. */
-} PuglEventMotion;
-
-/**
- Scroll event.
-
- The scroll distance is expressed in "lines", an arbitrary unit that
- corresponds to a single tick of a detented mouse wheel. For example, `dy` =
- 1.0 scrolls 1 line up. Some systems and devices support finer resolution
- and/or higher values for fast scrolls, so programs should handle any value
- gracefully.
- */
-typedef struct {
- PuglEventType type; /**< PUGL_SCROLL. */
- PuglView* view; /**< View that received this event. */
- bool send_event; /**< True iff event was sent explicitly. */
- uint32_t time; /**< Time in milliseconds. */
- double x; /**< View-relative X coordinate. */
- double y; /**< View-relative Y coordinate. */
- double x_root; /**< Root-relative X coordinate. */
- double y_root; /**< Root-relative Y coordinate. */
- unsigned state; /**< Bitwise OR of PuglMod flags. */
- double dx; /**< Scroll X distance in lines. */
- double dy; /**< Scroll Y distance in lines. */
-} PuglEventScroll;
-
-/**
- Interface event.
-
- This is a union of all event structs. The `type` must be checked to
- determine which fields are safe to access. A pointer to PuglEvent can
- either be cast to the appropriate type, or the union members used.
-*/
-typedef union {
- PuglEventType type; /**< Event type. */
- PuglEventAny any; /**< Valid for all event types. */
- PuglEventButton button; /**< PUGL_BUTTON_PRESS, PUGL_BUTTON_RELEASE. */
- PuglEventConfigure configure; /**< PUGL_CONFIGURE. */
- PuglEventCrossing crossing; /**< PUGL_ENTER_NOTIFY, PUGL_LEAVE_NOTIFY. */
- PuglEventExpose expose; /**< PUGL_EXPOSE. */
- PuglEventKey key; /**< PUGL_KEY_PRESS, PUGL_KEY_RELEASE. */
- PuglEventMotion motion; /**< PUGL_MOTION_NOTIFY. */
- PuglEventScroll scroll; /**< PUGL_SCROLL. */
-} PuglEvent;
-
-/**
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* PUGL_EVENT_H_INCLUDED */
diff --git a/dgl/src/pugl/gl.h b/dgl/src/pugl/gl.h
@@ -1,32 +0,0 @@
-/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file gl.h Portable header wrapper for gl.h.
-
- Unfortunately, GL includes vary across platforms so this header allows for
- pure portable programs.
-*/
-
-#ifdef __APPLE__
-# include "OpenGL/gl.h"
-#else
-# ifdef _WIN32
-# include <windows.h> /* Broken Windows GL headers require this */
-# endif
-# include "GL/gl.h"
-#endif
-
diff --git a/dgl/src/pugl/glu.h b/dgl/src/pugl/glu.h
@@ -1,32 +0,0 @@
-/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file gl.h Portable header wrapper for glu.h.
-
- Unfortunately, GL includes vary across platforms so this header allows for
- pure portable programs.
-*/
-
-#ifdef __APPLE__
-# include "OpenGL/glu.h"
-#else
-# ifdef _WIN32
-# include <windows.h> /* Broken Windows GL headers require this */
-# endif
-# include "GL/glu.h"
-#endif
-
diff --git a/dgl/src/pugl/pugl.h b/dgl/src/pugl/pugl.h
@@ -23,8 +23,19 @@
#include <stdint.h>
-#include "pugl/common.h"
-#include "pugl/event.h"
+/*
+ This API is pure portable C and contains no platform specific elements, or
+ even a GL dependency. However, unfortunately GL includes vary across
+ platforms so they are included here to allow for pure portable programs.
+*/
+#ifdef __APPLE__
+# include "OpenGL/gl.h"
+#else
+# ifdef _WIN32
+# include <windows.h> /* Broken Windows GL headers require this */
+# endif
+# include "GL/gl.h"
+#endif
#ifdef PUGL_SHARED
# ifdef _WIN32
@@ -40,7 +51,11 @@
# define PUGL_API PUGL_LIB_IMPORT
# endif
#else
-# define PUGL_API
+# ifdef _WIN32
+# define PUGL_API
+# else
+# define PUGL_API __attribute__((visibility("hidden")))
+# endif
#endif
#ifdef __cplusplus
@@ -56,9 +71,80 @@ extern "C" {
*/
/**
- A function called when an event occurs.
+ An OpenGL view.
+*/
+typedef struct PuglViewImpl PuglView;
+
+/**
+ A native window handle.
+
+ On X11, this is a Window.
+ On OSX, this is an NSView*.
+ On Windows, this is a HWND.
+*/
+typedef intptr_t PuglNativeWindow;
+
+/**
+ Return status code.
*/
-typedef void (*PuglEventFunc)(PuglView* view, const PuglEvent* event);
+typedef enum {
+ PUGL_SUCCESS = 0
+} PuglStatus;
+
+/**
+ Convenience symbols for ASCII control characters.
+*/
+typedef enum {
+ PUGL_CHAR_BACKSPACE = 0x08,
+ PUGL_CHAR_ESCAPE = 0x1B,
+ PUGL_CHAR_DELETE = 0x7F
+} PuglChar;
+
+/**
+ Special (non-Unicode) keyboard keys.
+*/
+typedef enum {
+ PUGL_KEY_F1 = 1,
+ PUGL_KEY_F2,
+ PUGL_KEY_F3,
+ PUGL_KEY_F4,
+ PUGL_KEY_F5,
+ PUGL_KEY_F6,
+ PUGL_KEY_F7,
+ PUGL_KEY_F8,
+ PUGL_KEY_F9,
+ PUGL_KEY_F10,
+ PUGL_KEY_F11,
+ PUGL_KEY_F12,
+ PUGL_KEY_LEFT,
+ PUGL_KEY_UP,
+ PUGL_KEY_RIGHT,
+ PUGL_KEY_DOWN,
+ PUGL_KEY_PAGE_UP,
+ PUGL_KEY_PAGE_DOWN,
+ PUGL_KEY_HOME,
+ PUGL_KEY_END,
+ PUGL_KEY_INSERT,
+ PUGL_KEY_SHIFT,
+ PUGL_KEY_CTRL,
+ PUGL_KEY_ALT,
+ PUGL_KEY_SUPER
+} PuglKey;
+
+/**
+ Keyboard modifier flags.
+*/
+typedef enum {
+ PUGL_MOD_SHIFT = 1, /**< Shift key */
+ PUGL_MOD_CTRL = 1 << 1, /**< Control key */
+ PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */
+ PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */
+} PuglMod;
+
+/**
+ Handle for opaque user data.
+*/
+typedef void* PuglHandle;
/**
A function called when the window is closed.
@@ -114,19 +200,18 @@ typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height);
so programs should handle any value gracefully.
@param view The view being scrolled.
+ @param x The window-relative x coordinate of the pointer.
+ @param y The window-relative y coordinate of the pointer.
@param dx The scroll x distance.
@param dx The scroll y distance.
*/
-typedef void (*PuglScrollFunc)(PuglView* view,
- int x,
- int y,
- float dx,
- float dy);
+typedef void (*PuglScrollFunc)(PuglView* view, int x, int y, float dx, float dy);
/**
A function called when a special key is pressed or released.
This callback allows the use of keys that do not have unicode points.
+ Note that some are non-printable keys.
@param view The view the event occured in.
@param press True if the key was pressed, false if released.
@@ -135,22 +220,13 @@ typedef void (*PuglScrollFunc)(PuglView* view,
typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key);
/**
- @name Initialization
- Configuration functions which must be called before creating a window.
- @{
-*/
-
-/**
Create a Pugl context.
To create a window, call the various puglInit* functions as necessary, then
call puglCreateWindow().
-
- @param pargc Pointer to argument count (unused, for GLUT compatibility).
- @param argv Arguments (unused, for GLUT compatibility).
*/
PUGL_API PuglView*
-puglInit(int* pargc, char** argv);
+puglInit(void);
/**
Set the parent window before creating a window (for embedding).
@@ -168,23 +244,7 @@ puglInitWindowSize(PuglView* view, int width, int height);
Enable or disable resizing before creating a window.
*/
PUGL_API void
-puglInitResizable(PuglView* view, bool resizable);
-
-/**
- Set the context type before creating a window.
-*/
-PUGL_API void
-puglInitContextType(PuglView* view, PuglContextType type);
-
-/**
- @}
-*/
-
-/**
- @name Windows
- Window management functions.
- @{
-*/
+puglInitUserResizable(PuglView* view, bool resizable);
/**
Create a window with the settings given by the various puglInit functions.
@@ -207,16 +267,6 @@ PUGL_API void
puglHideWindow(PuglView* view);
/**
- Return the native window handle.
-*/
-PUGL_API PuglNativeWindow
-puglGetNativeWindow(PuglView* view);
-
-/**
- @}
-*/
-
-/**
Set the handle to be passed to all callbacks.
This is generally a pointer to a struct which contains all necessary state.
@@ -235,15 +285,6 @@ PUGL_API PuglHandle
puglGetHandle(PuglView* view);
/**
- Get the drawing context.
-
- For PUGL_GL contexts, this is unused and returns NULL.
- For PUGL_CAIRO contexts, this returns a pointer to a cairo_t.
-*/
-PUGL_API void*
-puglGetContext(PuglView* view);
-
-/**
Return the timestamp (if any) of the currently-processing event.
*/
PUGL_API uint32_t
@@ -264,18 +305,6 @@ PUGL_API void
puglIgnoreKeyRepeat(PuglView* view, bool ignore);
/**
- @name Event Callbacks
- Functions to set event callbacks for handling user input.
- @{
-*/
-
-/**
- Set the function to call when an event occurs.
-*/
-PUGL_API void
-puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
-
-/**
Set the function to call when the window is closed.
*/
PUGL_API void
@@ -324,14 +353,10 @@ PUGL_API void
puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc);
/**
- @}
-*/
-
-/**
- Grab the input focus.
+ Return the native window handle.
*/
-PUGL_API void
-puglGrabFocus(PuglView* view);
+PUGL_API PuglNativeWindow
+puglGetNativeWindow(PuglView* view);
/**
Process all pending window events.
diff --git a/dgl/src/pugl/pugl_internal.h b/dgl/src/pugl/pugl_internal.h
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -24,14 +24,11 @@
If you are copying the pugl code into your source tree, the following
symbols can be defined to tweak pugl behaviour:
- PUGL_HAVE_CAIRO: Include Cairo support code.
- PUGL_HAVE_GL: Include OpenGL support code.
PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus.
PUGL_VERBOSE: Print GL information to console.
*/
-#include "pugl/pugl.h"
-#include "pugl/event.h"
+#include "pugl.h"
#ifdef PUGL_VERBOSE
# include <stdio.h>
@@ -46,7 +43,6 @@ typedef struct PuglInternalsImpl PuglInternals;
struct PuglViewImpl {
PuglHandle handle;
- PuglEventFunc eventFunc;
PuglCloseFunc closeFunc;
PuglDisplayFunc displayFunc;
PuglKeyboardFunc keyboardFunc;
@@ -57,9 +53,7 @@ struct PuglViewImpl {
PuglSpecialFunc specialFunc;
PuglInternals* impl;
-
PuglNativeWindow parent;
- PuglContextType ctx_type;
int width;
int height;
@@ -71,10 +65,10 @@ struct PuglViewImpl {
uint32_t event_timestamp_ms;
};
-PuglInternals* puglInitInternals();
+PuglInternals* puglInitInternals(void);
PuglView*
-puglInit(int* pargc, char** argv)
+puglInit(void)
{
PuglView* view = (PuglView*)calloc(1, sizeof(PuglView));
if (!view) {
@@ -92,9 +86,6 @@ puglInit(int* pargc, char** argv)
view->height = 480;
return view;
-
- // unused
- (void)pargc; (void)argv;
}
void
@@ -117,12 +108,6 @@ puglInitResizable(PuglView* view, bool resizable)
}
void
-puglInitContextType(PuglView* view, PuglContextType type)
-{
- view->ctx_type = type;
-}
-
-void
puglSetHandle(PuglView* view, PuglHandle handle)
{
view->handle = handle;
@@ -146,16 +131,26 @@ puglGetModifiers(PuglView* view)
return view->mods;
}
-void
-puglIgnoreKeyRepeat(PuglView* view, bool ignore)
+static void
+puglDefaultReshape(PuglView* view, int width, int height)
{
- view->ignoreKeyRepeat = ignore;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, width, height, 0, 0, 1);
+ glViewport(0, 0, width, height);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ return;
+
+ // unused
+ (void)view;
}
void
-puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc)
+puglIgnoreKeyRepeat(PuglView* view, bool ignore)
{
- view->eventFunc = eventFunc;
+ view->ignoreKeyRepeat = ignore;
}
void
@@ -205,81 +200,3 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc)
{
view->specialFunc = specialFunc;
}
-
-void
-puglEnterContext(PuglView* view);
-
-void
-puglLeaveContext(PuglView* view, bool flush);
-
-static void
-puglDispatchEvent(PuglView* view, const PuglEvent* event)
-{
- if (view->eventFunc) {
- view->eventFunc(view, event);
- }
-
- switch (event->type) {
- case PUGL_CONFIGURE:
- puglEnterContext(view);
- view->width = event->configure.width;
- view->height = event->configure.height;
- if (view->reshapeFunc) {
- view->reshapeFunc(view, view->width, view->height);
- }
- puglLeaveContext(view, false);
- break;
- case PUGL_EXPOSE:
- if (event->expose.count == 0) {
- puglEnterContext(view);
- if (view->displayFunc) {
- view->displayFunc(view);
- }
- view->redisplay = false;
- puglLeaveContext(view, true);
- }
- break;
- case PUGL_MOTION_NOTIFY:
- view->event_timestamp_ms = event->motion.time;
- view->mods = event->motion.state;
- if (view->motionFunc) {
- view->motionFunc(view, event->motion.x, event->motion.y);
- }
- break;
- case PUGL_SCROLL:
- if (view->scrollFunc) {
- view->scrollFunc(view,
- event->scroll.x, event->scroll.y,
- event->scroll.dx, event->scroll.dy);
- }
- break;
- case PUGL_BUTTON_PRESS:
- case PUGL_BUTTON_RELEASE:
- view->event_timestamp_ms = event->button.time;
- view->mods = event->button.state;
- if (view->mouseFunc) {
- view->mouseFunc(view,
- event->button.button,
- event->type == PUGL_BUTTON_PRESS,
- event->button.x,
- event->button.y);
- }
- break;
- case PUGL_KEY_PRESS:
- case PUGL_KEY_RELEASE:
- view->event_timestamp_ms = event->key.time;
- view->mods = event->key.state;
- if (event->key.special && view->specialFunc) {
- view->specialFunc(view,
- event->type == PUGL_KEY_PRESS,
- event->key.special);
- } else if (event->key.character && view->keyboardFunc) {
- view->keyboardFunc(view,
- event->type == PUGL_KEY_PRESS,
- event->key.character);
- }
- break;
- default:
- break;
- }
-}
diff --git a/dgl/src/pugl/pugl_osx.m b/dgl/src/pugl/pugl_osx.m
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -22,7 +22,7 @@
#import <Cocoa/Cocoa.h>
-#include "pugl/pugl_internal.h"
+#include "pugl_internal.h"
@interface PuglWindow : NSWindow
{
@@ -36,8 +36,6 @@
defer:(BOOL)flag;
- (void) setPuglview:(PuglView*)view;
- (BOOL) windowShouldClose:(id)sender;
-- (BOOL) canBecomeKeyWindow:(id)sender;
-- (BOOL) canBecomeMainWindow:(id)sender;
@end
@implementation PuglWindow
@@ -78,22 +76,6 @@
(void)sender;
}
-- (BOOL) canBecomeKeyWindow:(id)sender
-{
- return YES;
-
- // unused
- (void)sender;
-}
-
-- (BOOL) canBecomeMainWindow:(id)sender
-{
- return YES;
-
- // unused
- (void)sender;
-}
-
@end
static void
@@ -214,6 +196,8 @@ puglDisplay(PuglView* view)
if (puglview->reshapeFunc) {
puglview->reshapeFunc(puglview, width, height);
+ } else {
+ puglDefaultReshape(puglview, width, height);
}
puglview->width = width;
diff --git a/dgl/src/pugl/pugl_win.cpp b/dgl/src/pugl/pugl_win.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2014 David Robillard <http://drobilla.net>
+ Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -22,11 +22,11 @@
#include <windowsx.h>
#include <GL/gl.h>
+#include <ctime>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
-#include "pugl/pugl_internal.h"
+#include "pugl_internal.h"
#ifndef WM_MOUSEWHEEL
# define WM_MOUSEWHEEL 0x020A
@@ -38,7 +38,9 @@
# define WHEEL_DELTA 120
#endif
-#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)
+const int LOCAL_CLOSE_MSG = WM_USER + 50;
+
+HINSTANCE hInstance = NULL;
struct PuglInternalsImpl {
HWND hwnd;
@@ -47,11 +49,10 @@ struct PuglInternalsImpl {
WNDCLASS wc;
};
-static HINSTANCE hInstance = NULL;
-
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+#if 0
extern "C" {
BOOL WINAPI
DllMain(HINSTANCE hInst, DWORD, LPVOID)
@@ -60,6 +61,7 @@ DllMain(HINSTANCE hInst, DWORD, LPVOID)
return 1;
}
} // extern "C"
+#endif
PuglInternals*
puglInitInternals()
@@ -67,27 +69,6 @@ puglInitInternals()
return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}
-void
-puglEnterContext(PuglView* view)
-{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL) {
- wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
- }
-#endif
-}
-
-void
-puglLeaveContext(PuglView* view, bool flush)
-{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL && flush) {
- glFlush();
- SwapBuffers(view->impl->hdc);
- }
-#endif
-}
-
int
puglCreateWindow(PuglView* view, const char* title)
{
@@ -101,8 +82,9 @@ puglCreateWindow(PuglView* view, const char* title)
// Should class be a parameter? Does this make sense on other platforms?
static int wc_count = 0;
char classNameBuf[256];
- srand((time(NULL)));
- _snprintf(classNameBuf, sizeof(classNameBuf), "%d-%d_%s\n", ++wc_count, rand(), title);
+ std::srand((std::time(NULL)));
+ _snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d-%d", title, std::rand(), ++wc_count);
+ classNameBuf[sizeof(classNameBuf)-1] = '\0';
impl->wc.style = CS_OWNDC;
impl->wc.lpfnWndProc = wndProc;
@@ -114,37 +96,35 @@ puglCreateWindow(PuglView* view, const char* title)
impl->wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
impl->wc.lpszMenuName = NULL;
impl->wc.lpszClassName = strdup(classNameBuf);
- RegisterClass(&impl->wc);
- int winFlags = WS_POPUPWINDOW | WS_CAPTION;
- if (view->resizable) {
- winFlags |= WS_SIZEBOX;
+ if (!RegisterClass(&impl->wc)) {
+ free((void*)impl->wc.lpszClassName);
+ free(impl);
+ free(view);
+ return 1;
}
// Adjust the overall window size to accomodate our requested client size
+ const int winFlags = WS_POPUPWINDOW | WS_CAPTION | (view->resizable ? WS_SIZEBOX : 0x0);
RECT wr = { 0, 0, view->width, view->height };
AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST);
impl->hwnd = CreateWindowEx(
WS_EX_TOPMOST,
classNameBuf, title,
- view->parent ? WS_CHILD : winFlags,
+ view->parent ? (WS_CHILD | WS_VISIBLE) : winFlags,
CW_USEDEFAULT, CW_USEDEFAULT, wr.right-wr.left, wr.bottom-wr.top,
(HWND)view->parent, NULL, hInstance, NULL);
if (!impl->hwnd) {
- UnregisterClass(impl->wc.lpszClassName, hInstance);
+ UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
}
-#ifdef _WIN64
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
-#else
- SetWindowLongPtr(impl->hwnd, GWL_USERDATA, (LONG)view);
-#endif
impl->hdc = GetDC(impl->hwnd);
@@ -162,6 +142,16 @@ puglCreateWindow(PuglView* view, const char* title)
SetPixelFormat(impl->hdc, format, &pfd);
impl->hglrc = wglCreateContext(impl->hdc);
+ if (!impl->hglrc) {
+ ReleaseDC (impl->hwnd, impl->hdc);
+ DestroyWindow (impl->hwnd);
+ UnregisterClass (impl->wc.lpszClassName, NULL);
+ free((void*)impl->wc.lpszClassName);
+ free(impl);
+ free(view);
+ return 1;
+ }
+
wglMakeCurrent(impl->hdc, impl->hglrc);
return 0;
@@ -190,7 +180,7 @@ puglDestroy(PuglView* view)
wglDeleteContext(view->impl->hglrc);
ReleaseDC(view->impl->hwnd, view->impl->hdc);
DestroyWindow(view->impl->hwnd);
- UnregisterClass(view->impl->wc.lpszClassName, hInstance);
+ UnregisterClass(view->impl->wc.lpszClassName, NULL);
free((void*)view->impl->wc.lpszClassName);
free(view->impl);
free(view);
@@ -199,10 +189,12 @@ puglDestroy(PuglView* view)
static void
puglReshape(PuglView* view, int width, int height)
{
- puglEnterContext(view);
+ wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
if (view->reshapeFunc) {
view->reshapeFunc(view, width, height);
+ } else {
+ puglDefaultReshape(view, width, height);
}
view->width = width;
@@ -212,14 +204,15 @@ puglReshape(PuglView* view, int width, int height)
static void
puglDisplay(PuglView* view)
{
- puglEnterContext(view);
+ wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
+ view->redisplay = false;
if (view->displayFunc) {
view->displayFunc(view);
}
- puglLeaveContext(view, true);
- view->redisplay = false;
+ glFlush();
+ SwapBuffers(view->impl->hdc);
}
static PuglKey
@@ -308,7 +301,6 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_MOUSEMOVE:
if (view->motionFunc) {
- view->event_timestamp_ms = GetMessageTime();
view->motionFunc(view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
break;
@@ -333,17 +325,21 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
case WM_MOUSEWHEEL:
if (view->scrollFunc) {
view->event_timestamp_ms = GetMessageTime();
+ POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+ ScreenToClient(view->impl->hwnd, &pt);
view->scrollFunc(
- view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
- 0.0f, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA);
+ view, pt.x, pt.y,
+ GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0);
}
break;
case WM_MOUSEHWHEEL:
if (view->scrollFunc) {
view->event_timestamp_ms = GetMessageTime();
+ POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+ ScreenToClient(view->impl->hwnd, &pt);
view->scrollFunc(
- view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
- (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0.0f);
+ view, pt.x, pt.y,
+ GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0);
}
break;
case WM_KEYDOWN:
@@ -357,11 +353,18 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
view->specialFunc(view, message == WM_KEYDOWN, key);
}
} else if (view->keyboardFunc) {
- view->keyboardFunc(view, message == WM_KEYDOWN, wParam);
+ static BYTE kbs[256];
+ if (GetKeyboardState(kbs) != FALSE) {
+ char lb[2];
+ UINT scanCode = (lParam >> 8) & 0xFFFFFF00;
+ if ( 1 == ToAscii(wParam, scanCode, kbs, (LPWORD)lb, 0)) {
+ view->keyboardFunc(view, message == WM_KEYDOWN, (char)lb[0]);
+ }
+ }
}
break;
case WM_QUIT:
- case PUGL_LOCAL_CLOSE_MSG:
+ case LOCAL_CLOSE_MSG:
if (view->closeFunc) {
view->closeFunc(view);
}
@@ -374,12 +377,6 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
-void
-puglGrabFocus(PuglView* /*view*/)
-{
- // TODO
-}
-
PuglStatus
puglProcessEvents(PuglView* view)
{
@@ -388,7 +385,6 @@ puglProcessEvents(PuglView* view)
handleMessage(view, msg.message, msg.wParam, msg.lParam);
}
-
if (view->redisplay) {
InvalidateRect(view->impl->hwnd, NULL, FALSE);
}
@@ -399,23 +395,19 @@ puglProcessEvents(PuglView* view)
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
-#ifdef _WIN64
PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
-#else
- PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWL_USERDATA);
-#endif
switch (message) {
case WM_CREATE:
PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0);
return 0;
case WM_CLOSE:
- PostMessage(hwnd, PUGL_LOCAL_CLOSE_MSG, wParam, lParam);
+ PostMessage(hwnd, LOCAL_CLOSE_MSG, wParam, lParam);
return 0;
case WM_DESTROY:
return 0;
default:
- if (view) {
+ if (view && hwnd == view->impl->hwnd) {
return handleMessage(view, message, wParam, lParam);
} else {
return DefWindowProc(hwnd, message, wParam, lParam);
diff --git a/dgl/src/pugl/pugl_x11.c b/dgl/src/pugl/pugl_x11.c
@@ -1,7 +1,7 @@
/*
Copyright 2012-2014 David Robillard <http://drobilla.net>
- Copyright 2013 Robin Gareus <robin@gareus.org>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
+ Copyright 2013 Robin Gareus <robin@gareus.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -24,170 +24,101 @@
#include <stdlib.h>
#include <string.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include <X11/keysym.h>
-#ifdef PUGL_HAVE_GL
-#include <GL/gl.h>
-#include <GL/glx.h>
-#endif
-
-#ifdef PUGL_HAVE_CAIRO
-#include <cairo/cairo.h>
-#include <cairo/cairo-xlib.h>
-#endif
-
-#include "pugl/event.h"
-#include "pugl/pugl_internal.h"
+#include "pugl_internal.h"
struct PuglInternalsImpl {
Display* display;
int screen;
Window win;
-#ifdef PUGL_HAVE_CAIRO
- cairo_t* cr;
-#endif
-#ifdef PUGL_HAVE_GL
GLXContext ctx;
Bool doubleBuffered;
-#endif
};
-PuglInternals*
-puglInitInternals()
-{
- return (PuglInternals*)calloc(1, sizeof(PuglInternals));
-}
-
-static XVisualInfo*
-getVisual(PuglView* view)
-{
- PuglInternals* const impl = view->impl;
- XVisualInfo* vi = NULL;
-
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL) {
- // Try to create double-buffered visual
- int double_attrs[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 4,
- GLX_GREEN_SIZE, 4,
- GLX_BLUE_SIZE, 4,
- GLX_DEPTH_SIZE, 16,
- None };
- vi = glXChooseVisual(impl->display, impl->screen, double_attrs);
- if (!vi) {
- // Failed, create single-buffered visual
- int single_attrs[] = { GLX_RGBA,
- GLX_RED_SIZE, 4,
- GLX_GREEN_SIZE, 4,
- GLX_BLUE_SIZE, 4,
- GLX_DEPTH_SIZE, 16,
- None };
- vi = glXChooseVisual(impl->display, impl->screen, single_attrs);
- impl->doubleBuffered = False;
- } else {
- impl->doubleBuffered = True;
- }
-#ifdef PUGL_VERBOSE
- int glxMajor, glxMinor;
- glXQueryVersion(impl->display, &glxMajor, &glxMinor);
- PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor);
-#endif
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- XVisualInfo pat;
- int n;
- pat.screen = impl->screen;
- vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
- }
-#endif
-
- return vi;
-}
-
-static void
-createContext(PuglView* view, XVisualInfo* vi)
-{
- PuglInternals* const impl = view->impl;
-
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL) {
- impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);
-#ifdef PUGL_VERBOSE
- if (glXIsDirect(impl->display, impl->ctx)) {
- PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
- } else {
- PUGL_LOG("No DRI available\n");
- }
-#endif
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- cairo_surface_t* surface = cairo_xlib_surface_create(
- impl->display, impl->win, vi->visual, view->width, view->height);
- if (!(impl->cr = cairo_create(surface))) {
- fprintf(stderr, "failed to create cairo context\n");
- }
- }
-#endif
-}
+/**
+ Attributes for single-buffered RGBA with at least
+ 4 bits per color and a 16 bit depth buffer.
+*/
+static int attrListSgl[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ GLX_ARB_multisample, 1,
+ None
+};
-static void
-destroyContext(PuglView* view)
-{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL) {
- glXDestroyContext(view->impl->display, view->impl->ctx);
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- glXDestroyContext(view->impl->display, view->impl->ctx);
- }
-#endif
-}
+/**
+ Attributes for double-buffered RGBA with at least
+ 4 bits per color and a 16 bit depth buffer.
+*/
+static int attrListDbl[] = {
+ GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ GLX_ARB_multisample, 1,
+ None
+};
-void
-puglEnterContext(PuglView* view)
-{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL) {
- glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
- }
-#endif
-}
+/**
+ Attributes for double-buffered RGBA with multi-sampling
+ (antialiasing)
+*/
+static int attrListDblMS[] = {
+ GLX_RGBA,
+ GLX_DOUBLEBUFFER , True,
+ GLX_RED_SIZE , 4,
+ GLX_GREEN_SIZE , 4,
+ GLX_BLUE_SIZE , 4,
+ GLX_ALPHA_SIZE , 4,
+ GLX_DEPTH_SIZE , 16,
+ GLX_SAMPLE_BUFFERS , 1,
+ GLX_SAMPLES , 4,
+ None
+};
-void
-puglLeaveContext(PuglView* view, bool flush)
+PuglInternals*
+puglInitInternals(void)
{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_GL && flush) {
- glFlush();
- if (view->impl->doubleBuffered) {
- glXSwapBuffers(view->impl->display, view->impl->win);
- }
- }
-#endif
+ return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}
int
puglCreateWindow(PuglView* view, const char* title)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* impl = view->impl;
impl->display = XOpenDisplay(0);
impl->screen = DefaultScreen(impl->display);
+ impl->doubleBuffered = True;
+
+ XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);
+
+ if (!vi) {
+ vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
+ PUGL_LOG("multisampling (antialiasing) is not available\n");
+ }
- XVisualInfo* const vi = getVisual(view);
if (!vi) {
- return 1;
+ vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
+ impl->doubleBuffered = False;
+ PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n");
}
+ int glxMajor, glxMinor;
+ glXQueryVersion(impl->display, &glxMajor, &glxMinor);
+ PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor);
+
+ impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);
+
Window xParent = view->parent
? (Window)view->parent
: RootWindow(impl->display, impl->screen);
@@ -197,21 +128,20 @@ puglCreateWindow(PuglView* view, const char* title)
XSetWindowAttributes attr;
memset(&attr, 0, sizeof(XSetWindowAttributes));
- attr.background_pixel = BlackPixel(impl->display, impl->screen);
- attr.border_pixel = BlackPixel(impl->display, impl->screen);
- attr.colormap = cmap;
- attr.event_mask = (ExposureMask | StructureNotifyMask |
- EnterWindowMask | LeaveWindowMask |
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask
+ | ButtonPressMask | ButtonReleaseMask
+#ifdef PUGL_GRAB_FOCUS
+ | EnterWindowMask
+#endif
+ | PointerMotionMask | StructureNotifyMask;
impl->win = XCreateWindow(
impl->display, xParent,
0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual,
- CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr);
-
- createContext(view, vi);
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
XSizeHints sizeHints;
memset(&sizeHints, 0, sizeof(sizeHints));
@@ -233,21 +163,33 @@ puglCreateWindow(PuglView* view, const char* title)
XSetWMProtocols(impl->display, impl->win, &wmDelete, 1);
}
+ if (glXIsDirect(impl->display, impl->ctx)) {
+ PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
+ } else {
+ PUGL_LOG("No DRI available\n");
+ }
+
XFree(vi);
+ glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
+
return 0;
}
void
puglShowWindow(PuglView* view)
{
- XMapRaised(view->impl->display, view->impl->win);
+ PuglInternals* impl = view->impl;
+
+ XMapRaised(impl->display, impl->win);
}
void
puglHideWindow(PuglView* view)
{
- XUnmapWindow(view->impl->display, view->impl->win);
+ PuglInternals* impl = view->impl;
+
+ XUnmapWindow(impl->display, impl->win);
}
void
@@ -257,13 +199,46 @@ puglDestroy(PuglView* view)
return;
}
- destroyContext(view);
+ glXDestroyContext(view->impl->display, view->impl->ctx);
XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display);
free(view->impl);
free(view);
}
+static void
+puglReshape(PuglView* view, int width, int height)
+{
+ glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
+
+ if (view->reshapeFunc) {
+ view->reshapeFunc(view, width, height);
+ } else {
+ puglDefaultReshape(view, width, height);
+ }
+
+ view->width = width;
+ view->height = height;
+}
+
+static void
+puglDisplay(PuglView* view)
+{
+ glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
+
+ view->redisplay = false;
+
+ if (view->displayFunc) {
+ view->displayFunc(view);
+ }
+
+ glFlush();
+
+ if (view->impl->doubleBuffered) {
+ glXSwapBuffers(view->impl->display, view->impl->win);
+ }
+}
+
static PuglKey
keySymToSpecial(KeySym sym)
{
@@ -302,184 +277,145 @@ keySymToSpecial(KeySym sym)
}
static void
-translateKey(XEvent* xevent, PuglEvent* event)
+setModifiers(PuglView* view, unsigned xstate, unsigned xtime)
{
- KeySym sym;
- char str[5];
- const int n = XLookupString(&xevent->xkey, str, 4, &sym, NULL);
- if (n == 1) {
- event->key.character = str[0]; // TODO: multi-byte support
- }
- event->key.special = keySymToSpecial(sym);
-}
+ view->event_timestamp_ms = xtime;
-static unsigned
-translateModifiers(unsigned xstate)
-{
- unsigned state = 0;
- state |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0;
- state |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0;
- state |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0;
- state |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0;
- return state;
+ view->mods = 0;
+ view->mods |= (xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0;
+ view->mods |= (xstate & ControlMask) ? PUGL_MOD_CTRL : 0;
+ view->mods |= (xstate & Mod1Mask) ? PUGL_MOD_ALT : 0;
+ view->mods |= (xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0;
}
-static PuglEvent
-translateEvent(PuglView* view, XEvent xevent)
+static void
+dispatchKey(PuglView* view, XEvent* event, bool press)
{
- PuglEvent event;
- memset(&event, 0, sizeof(event));
-
- event.any.view = view;
- event.any.send_event = xevent.xany.send_event;
-
- switch (xevent.type) {
- case ConfigureNotify:
- event.type = PUGL_CONFIGURE;
- event.configure.x = xevent.xconfigure.x;
- event.configure.y = xevent.xconfigure.y;
- event.configure.width = xevent.xconfigure.width;
- event.configure.height = xevent.xconfigure.height;
- break;
- case Expose:
- event.type = PUGL_EXPOSE;
- event.expose.x = xevent.xexpose.x;
- event.expose.y = xevent.xexpose.y;
- event.expose.width = xevent.xexpose.width;
- event.expose.height = xevent.xexpose.height;
- event.expose.count = xevent.xexpose.count;
- break;
- case MotionNotify:
- event.type = PUGL_MOTION_NOTIFY;
- event.motion.time = xevent.xmotion.time;
- event.motion.x = xevent.xmotion.x;
- event.motion.y = xevent.xmotion.y;
- event.motion.x_root = xevent.xmotion.x_root;
- event.motion.y_root = xevent.xmotion.y_root;
- event.motion.state = translateModifiers(xevent.xmotion.state);
- event.motion.is_hint = (xevent.xmotion.is_hint == NotifyHint);
- break;
- case ButtonPress:
- if (xevent.xbutton.button >= 4 && xevent.xbutton.button <= 7) {
- event.type = PUGL_SCROLL;
- event.scroll.time = xevent.xbutton.time;
- event.scroll.x = xevent.xbutton.x;
- event.scroll.y = xevent.xbutton.y;
- event.scroll.x_root = xevent.xbutton.x_root;
- event.scroll.y_root = xevent.xbutton.y_root;
- event.scroll.state = translateModifiers(xevent.xbutton.state);
- event.scroll.dx = 0.0;
- event.scroll.dy = 0.0;
- switch (xevent.xbutton.button) {
- case 4: event.scroll.dy = 1.0f; break;
- case 5: event.scroll.dy = -1.0f; break;
- case 6: event.scroll.dx = -1.0f; break;
- case 7: event.scroll.dx = 1.0f; break;
- }
- }
- // nobreak
- case ButtonRelease:
- if (xevent.xbutton.button < 4 || xevent.xbutton.button > 7) {
- event.button.type = ((xevent.type == ButtonPress)
- ? PUGL_BUTTON_PRESS
- : PUGL_BUTTON_RELEASE);
- event.button.time = xevent.xbutton.time;
- event.button.x = xevent.xbutton.x;
- event.button.y = xevent.xbutton.y;
- event.button.x_root = xevent.xbutton.x_root;
- event.button.y_root = xevent.xbutton.y_root;
- event.button.state = translateModifiers(xevent.xbutton.state);
- event.button.button = xevent.xbutton.button;
- }
- break;
- case KeyPress:
- case KeyRelease:
- event.type = ((xevent.type == KeyPress)
- ? PUGL_KEY_PRESS
- : PUGL_KEY_RELEASE);
- event.key.time = xevent.xbutton.time;
- event.key.x = xevent.xbutton.x;
- event.key.y = xevent.xbutton.y;
- event.key.x_root = xevent.xbutton.x_root;
- event.key.y_root = xevent.xbutton.y_root;
- event.key.state = translateModifiers(xevent.xbutton.state);
- translateKey(&xevent, &event);
- break;
- case EnterNotify:
- case LeaveNotify:
- event.type = ((xevent.type == EnterNotify)
- ? PUGL_ENTER_NOTIFY
- : PUGL_LEAVE_NOTIFY);
- event.crossing.time = xevent.xcrossing.time;
- event.crossing.x = xevent.xcrossing.x;
- event.crossing.y = xevent.xcrossing.y;
- event.crossing.x_root = xevent.xcrossing.x_root;
- event.crossing.y_root = xevent.xcrossing.y_root;
- event.crossing.state = translateModifiers(xevent.xcrossing.state);
- event.crossing.mode = PUGL_CROSSING_NORMAL;
- if (xevent.xcrossing.mode == NotifyGrab) {
- event.crossing.mode = PUGL_CROSSING_GRAB;
- } else if (xevent.xcrossing.mode == NotifyUngrab) {
- event.crossing.mode = PUGL_CROSSING_UNGRAB;
- }
- break;
- default:
- break;
- }
+ KeySym sym;
+ char str[5];
+ const int n = XLookupString(&event->xkey, str, 4, &sym, NULL);
- return event;
-}
+ if (sym == XK_Escape && view->closeFunc && !press && !view->parent) {
+ view->closeFunc(view);
+ view->redisplay = false;
+ return;
+ }
+ if (n == 0) {
+ return;
+ }
+ if (n > 1) {
+ fprintf(stderr, "warning: Unsupported multi-byte key %X\n", (int)sym);
+ return;
+ }
-void
-puglGrabFocus(PuglView* view)
-{
- XSetInputFocus(
- view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime);
+ const PuglKey special = keySymToSpecial(sym);
+ if (special && view->specialFunc) {
+ view->specialFunc(view, press, special);
+ } else if (!special && view->keyboardFunc) {
+ view->keyboardFunc(view, press, str[0]);
+ }
}
PuglStatus
puglProcessEvents(PuglView* view)
{
- XEvent xevent;
+ XEvent event;
while (XPending(view->impl->display) > 0) {
- XNextEvent(view->impl->display, &xevent);
- bool ignore = false;
- if (xevent.type == ClientMessage) {
- // Handle close message
- char* type = XGetAtomName(view->impl->display,
- xevent.xclient.message_type);
- if (!strcmp(type, "WM_PROTOCOLS") && view->closeFunc) {
- view->closeFunc(view);
+ XNextEvent(view->impl->display, &event);
+ switch (event.type) {
+ case MapNotify:
+ puglReshape(view, view->width, view->height);
+ break;
+ case ConfigureNotify:
+ if ((event.xconfigure.width != view->width) ||
+ (event.xconfigure.height != view->height)) {
+ puglReshape(view,
+ event.xconfigure.width,
+ event.xconfigure.height);
}
- XFree(type);
- continue;
- } else if (xevent.type == KeyRelease) {
- // Ignore key repeat if necessary
+ break;
+ case Expose:
+ if (event.xexpose.count != 0) {
+ break;
+ }
+ puglDisplay(view);
+ break;
+ case MotionNotify:
+ setModifiers(view, event.xmotion.state, event.xmotion.time);
+ if (view->motionFunc) {
+ view->motionFunc(view, event.xmotion.x, event.xmotion.y);
+ }
+ break;
+ case ButtonPress:
+ setModifiers(view, event.xbutton.state, event.xbutton.time);
+ if (event.xbutton.button >= 4 && event.xbutton.button <= 7) {
+ if (view->scrollFunc) {
+ float dx = 0, dy = 0;
+ switch (event.xbutton.button) {
+ case 4: dy = 1.0f; break;
+ case 5: dy = -1.0f; break;
+ case 6: dx = -1.0f; break;
+ case 7: dx = 1.0f; break;
+ }
+ view->scrollFunc(view, event.xbutton.x, event.xbutton.y, dx, dy);
+ }
+ break;
+ }
+ // nobreak
+ case ButtonRelease:
+ setModifiers(view, event.xbutton.state, event.xbutton.time);
+ if (view->mouseFunc &&
+ (event.xbutton.button < 4 || event.xbutton.button > 7)) {
+ view->mouseFunc(view,
+ event.xbutton.button, event.type == ButtonPress,
+ event.xbutton.x, event.xbutton.y);
+ }
+ break;
+ case KeyPress:
+ setModifiers(view, event.xkey.state, event.xkey.time);
+ dispatchKey(view, &event, true);
+ break;
+ case KeyRelease: {
+ setModifiers(view, event.xkey.state, event.xkey.time);
+ bool repeated = false;
if (view->ignoreKeyRepeat &&
XEventsQueued(view->impl->display, QueuedAfterReading)) {
XEvent next;
XPeekEvent(view->impl->display, &next);
if (next.type == KeyPress &&
- next.xkey.time == xevent.xkey.time &&
- next.xkey.keycode == xevent.xkey.keycode) {
- XNextEvent(view->impl->display, &xevent);
- ignore = true;
+ next.xkey.time == event.xkey.time &&
+ next.xkey.keycode == event.xkey.keycode) {
+ XNextEvent(view->impl->display, &event);
+ repeated = true;
}
}
- }
-
- if (!ignore) {
- // Translate and dispatch event
- const PuglEvent event = translateEvent(view, xevent);
- puglDispatchEvent(view, &event);
+ if (!repeated) {
+ dispatchKey(view, &event, false);
+ }
+ } break;
+ case ClientMessage: {
+ char* type = XGetAtomName(view->impl->display,
+ event.xclient.message_type);
+ if (!strcmp(type, "WM_PROTOCOLS")) {
+ if (view->closeFunc) {
+ view->closeFunc(view);
+ view->redisplay = false;
+ }
+ }
+ XFree(type);
+ } break;
+#ifdef PUGL_GRAB_FOCUS
+ case EnterNotify:
+ XSetInputFocus(view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime);
+ break;
+#endif
+ default:
+ break;
}
}
if (view->redisplay) {
- const PuglEventExpose expose = {
- PUGL_EXPOSE, view, true, 0.0, 0.0, (double)view->width, (double)view->height, 0
- };
- puglDispatchEvent(view, (const PuglEvent*)&expose);
+ puglDisplay(view);
}
return PUGL_SUCCESS;
@@ -496,17 +432,3 @@ puglGetNativeWindow(PuglView* view)
{
return view->impl->win;
}
-
-void*
-puglGetContext(PuglView* view)
-{
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- return view->impl->cr;
- }
-#endif
- return NULL;
-
- // possibly unused
- (void)view;
-}