aboutsummaryrefslogtreecommitdiff
path: root/pugl/pugl
diff options
context:
space:
mode:
authorGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2018-05-07 19:02:49 +0200
committerGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2018-05-07 19:02:49 +0200
commit1457b922e1d7c277c558bd3fb247caba6b8df07a (patch)
tree80d2b97cda3be4288c3e4c4096f16c8cf3f5c7fe /pugl/pugl
parent81b2369388cd8a63611b8fe32f1701f73a80b100 (diff)
downloadcanvas_display.lv2-1457b922e1d7c277c558bd3fb247caba6b8df07a.zip
canvas_display.lv2-1457b922e1d7c277c558bd3fb247caba6b8df07a.tar.gz
canvas_display.lv2-1457b922e1d7c277c558bd3fb247caba6b8df07a.tar.bz2
canvas_display.lv2-1457b922e1d7c277c558bd3fb247caba6b8df07a.tar.xz
strip canvas headers, migrate to meson.
Diffstat (limited to 'pugl/pugl')
-rw-r--r--pugl/pugl/cairo_gl.h105
-rw-r--r--pugl/pugl/gl.h32
-rw-r--r--pugl/pugl/glew.h32
-rw-r--r--pugl/pugl/glu.h32
-rw-r--r--pugl/pugl/pugl.h622
-rw-r--r--pugl/pugl/pugl.hpp106
-rw-r--r--pugl/pugl/pugl_internal.h241
-rw-r--r--pugl/pugl/pugl_osx.m648
-rw-r--r--pugl/pugl/pugl_win.cpp644
-rw-r--r--pugl/pugl/pugl_x11.c721
10 files changed, 0 insertions, 3183 deletions
diff --git a/pugl/pugl/cairo_gl.h b/pugl/pugl/cairo_gl.h
deleted file mode 100644
index 5c0f1f9..0000000
--- a/pugl/pugl/cairo_gl.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- Copyright 2016 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.
-*/
-
-#if defined(PUGL_HAVE_GL) && defined(PUGL_HAVE_CAIRO)
-
-#include <cairo/cairo.h>
-#include <stdint.h>
-
-#include "pugl/gl.h"
-
-typedef struct {
- unsigned texture_id;
- uint8_t* buffer;
-} PuglCairoGL;
-
-static cairo_surface_t*
-pugl_cairo_gl_create(PuglCairoGL* ctx, int width, int height, int bpp)
-{
- free(ctx->buffer);
- ctx->buffer = (uint8_t*)calloc(bpp * width * height, sizeof(uint8_t));
- if (!ctx->buffer) {
- fprintf(stderr, "failed to allocate surface buffer\n");
- return NULL;
- }
-
- return cairo_image_surface_create_for_data(
- ctx->buffer, CAIRO_FORMAT_ARGB32, width, height, bpp * width);
-}
-
-static void
-pugl_cairo_gl_free(PuglCairoGL* ctx)
-{
- free(ctx->buffer);
- ctx->buffer = NULL;
-}
-
-static void
-pugl_cairo_gl_configure(PuglCairoGL* ctx, int width, int height)
-{
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- glDeleteTextures(1, &ctx->texture_id);
- glGenTextures(1, &ctx->texture_id);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ctx->texture_id);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-}
-
-static void
-pugl_cairo_gl_draw(PuglCairoGL* ctx, int width, int height)
-{
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glViewport(0, 0, width, height);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glPushMatrix();
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glEnable(GL_TEXTURE_2D);
-
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
- width, height, 0,
- GL_BGRA, GL_UNSIGNED_BYTE, ctx->buffer);
-
- glBegin(GL_QUADS);
- glTexCoord2f(0.0f, (GLfloat)height);
- glVertex2f(-1.0f, -1.0f);
-
- glTexCoord2f((GLfloat)width, (GLfloat)height);
- glVertex2f(1.0f, -1.0f);
-
- glTexCoord2f((GLfloat)width, 0.0f);
- glVertex2f(1.0f, 1.0f);
-
- glTexCoord2f(0.0f, 0.0f);
- glVertex2f(-1.0f, 1.0f);
- glEnd();
-
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
- glPopMatrix();
-}
-
-#endif
diff --git a/pugl/pugl/gl.h b/pugl/pugl/gl.h
deleted file mode 100644
index 9a6aeef..0000000
--- a/pugl/pugl/gl.h
+++ /dev/null
@@ -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/pugl/pugl/glew.h b/pugl/pugl/glew.h
deleted file mode 100644
index 5374406..0000000
--- a/pugl/pugl/glew.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- Copyright 2016 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 glew.h.
-
- Unfortunately, GL includes vary across platforms so this header allows for
- pure portable programs.
-*/
-
-#ifdef __APPLE__
-# include "OpenGL/glew.h"
-#else
-# ifdef _WIN32
-# include <windows.h> /* Broken Windows GL headers require this */
-# endif
-# include "GL/glew.h"
-#endif
-
diff --git a/pugl/pugl/glu.h b/pugl/pugl/glu.h
deleted file mode 100644
index 0d3e8e1..0000000
--- a/pugl/pugl/glu.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- Copyright 2012-2015 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/pugl/pugl/pugl.h b/pugl/pugl/pugl.h
deleted file mode 100644
index 1b22260..0000000
--- a/pugl/pugl/pugl.h
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- Copyright 2012-2016 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 pugl.h API for Pugl, a minimal portable API for OpenGL.
-*/
-
-#ifndef PUGL_H_INCLUDED
-#define PUGL_H_INCLUDED
-
-#include <stdint.h>
-
-#ifdef PUGL_SHARED
-# ifdef _WIN32
-# define PUGL_LIB_IMPORT __declspec(dllimport)
-# define PUGL_LIB_EXPORT __declspec(dllexport)
-# else
-# define PUGL_LIB_IMPORT __attribute__((visibility("default")))
-# define PUGL_LIB_EXPORT __attribute__((visibility("default")))
-# endif
-# ifdef PUGL_INTERNAL
-# define PUGL_API PUGL_LIB_EXPORT
-# else
-# define PUGL_API PUGL_LIB_IMPORT
-# endif
-#else
-# define PUGL_API
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#else
-# include <stdbool.h>
-#endif
-
-/**
- @defgroup pugl Pugl
- A minimal portable API for OpenGL.
- @{
-*/
-
-/**
- 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 = 0x1,
- PUGL_CAIRO = 0x2,
- PUGL_CAIRO_GL = 0x3
-} 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.
-
- The numerical values of these symbols occupy a reserved range of Unicode
- points, so it is possible to express either a PuglKey value or a Unicode
- character in the same variable. This is sometimes useful for interfacing
- with APIs that do not make this distinction.
-*/
-typedef enum {
- PUGL_KEY_F1 = 0xE000,
- 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;
-
-/**
- The type of a PuglEvent.
-*/
-typedef enum {
- PUGL_NOTHING, /**< No event */
- PUGL_BUTTON_PRESS, /**< Mouse button press */
- PUGL_BUTTON_RELEASE, /**< Mouse button release */
- PUGL_CONFIGURE, /**< View moved and/or resized */
- PUGL_EXPOSE, /**< View exposed, redraw required */
- PUGL_CLOSE, /**< Close view */
- PUGL_KEY_PRESS, /**< Key press */
- PUGL_KEY_RELEASE, /**< Key release */
- PUGL_ENTER_NOTIFY, /**< Pointer entered view */
- PUGL_LEAVE_NOTIFY, /**< Pointer left view */
- PUGL_MOTION_NOTIFY, /**< Pointer motion */
- PUGL_SCROLL, /**< Scroll */
- PUGL_FOCUS_IN, /**< Keyboard focus entered view */
- PUGL_FOCUS_OUT /**< Keyboard focus left view */
-} PuglEventType;
-
-typedef enum {
- PUGL_IS_SEND_EVENT = 1
-} PuglEventFlag;
-
-/**
- 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
-} 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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;
-
-/**
- Window close event.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_CLOSE. */
- PuglView* view; /**< View that received this event. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
-} PuglEventClose;
-
-/**
- Key press/release event.
-
- Keys that correspond to a Unicode character have `character` and `utf8` set.
- Other keys will have `character` 0, but `special` may be set if this is a
- known special key.
-
- A key press may be part of a multi-key sequence to generate a wide
- character. If `filter` is set, this event is part of a multi-key sequence
- and should be ignored if the application is reading textual input.
- Following the series of filtered press events, a press event with
- `character` and `utf8` (but `keycode` 0) will be sent. This event will have
- no corresponding release event.
-
- Generally, an application should either work with raw keyboard press/release
- events based on `keycode` (ignoring events with `keycode` 0), or
- read textual input based on `character` or `utf8` (ignoring releases and
- events with `filter` 1). Note that blindly appending `utf8` will yield
- incorrect text, since press events are sent for both individually composed
- keys and the resulting synthetic multi-byte press.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_KEY_PRESS or PUGL_KEY_RELEASE. */
- PuglView* view; /**< View that received this event. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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 keycode; /**< Raw key code. */
- uint32_t character; /**< Unicode character code, or 0. */
- PuglKey special; /**< Special key, or 0. */
- uint8_t utf8[8]; /**< UTF-8 string. */
- bool filter; /**< True if part of a multi-key sequence. */
-} 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- 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;
-
-/**
- Keyboard focus event.
-*/
-typedef struct {
- PuglEventType type; /**< PUGL_FOCUS_IN or PUGL_FOCUS_OUT. */
- PuglView* view; /**< View that received this event. */
- uint32_t flags; /**< Bitwise OR of PuglEventFlag values. */
- bool grab; /**< True iff this is a grab/ungrab event. */
-} PuglEventFocus;
-
-/**
- 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. */
- PuglEventExpose expose; /**< PUGL_EXPOSE. */
- PuglEventClose close; /**< PUGL_CLOSE. */
- PuglEventKey key; /**< PUGL_KEY_PRESS, PUGL_KEY_RELEASE. */
- PuglEventCrossing crossing; /**< PUGL_ENTER_NOTIFY, PUGL_LEAVE_NOTIFY. */
- PuglEventMotion motion; /**< PUGL_MOTION_NOTIFY. */
- PuglEventScroll scroll; /**< PUGL_SCROLL. */
- PuglEventFocus focus; /**< PUGL_FOCUS_IN, PUGL_FOCUS_OUT. */
-} PuglEvent;
-
-/**
- @name Initialization
- Configuration functions which must be called before creating a window.
- @{
-*/
-
-/**
- Create a Pugl view.
-
- To create a window, call the various puglInit* functions as necessary, then
- call puglCreateWindow().
-
- @param pargc Pointer to argument count (currently unused).
- @param argv Arguments (currently unused).
- @return A newly created view.
-*/
-PUGL_API PuglView*
-puglInit(int* pargc, char** argv);
-
-/**
- Set the window class name before creating a window.
-*/
-PUGL_API void
-puglInitWindowClass(PuglView* view, const char* name);
-
-/**
- Set the parent window before creating a window (for embedding).
-*/
-PUGL_API void
-puglInitWindowParent(PuglView* view, PuglNativeWindow parent);
-
-/**
- Set the window size before creating a window.
-*/
-PUGL_API void
-puglInitWindowSize(PuglView* view, int width, int height);
-
-/**
- Set the minimum window size before creating a window.
-*/
-PUGL_API void
-puglInitWindowMinSize(PuglView* view, int width, int height);
-
-/**
- Set the window aspect ratio range before creating a window.
-
- The x and y values here represent a ratio of width to height. To set a
- fixed aspect ratio, set the minimum and maximum values to the same ratio.
-*/
-PUGL_API void
-puglInitWindowAspectRatio(PuglView* view,
- int min_x,
- int min_y,
- int max_x,
- int max_y);
-
-/**
- Enable or disable resizing before creating a window.
-*/
-PUGL_API void
-puglInitResizable(PuglView* view, bool resizable);
-
-/**
- Set transient parent before creating a window.
-
- On X11, parent must be a Window.
- On OSX, parent must be an NSView*.
-*/
-PUGL_API void
-puglInitTransientFor(PuglView* view, uintptr_t parent);
-
-/**
- Set the context type before creating a window.
-*/
-PUGL_API void
-puglInitContextType(PuglView* view, PuglContextType type);
-
-/**
- @}
-*/
-
-/**
- @name Windows
- Functions for creating and managing a visible window for a view.
- @{
-*/
-
-/**
- Create a window with the settings given by the various puglInit functions.
-
- @return 1 (pugl does not currently support multiple windows).
-*/
-PUGL_API int
-puglCreateWindow(PuglView* view, const char* title);
-
-/**
- Show the current window.
-*/
-PUGL_API void
-puglShowWindow(PuglView* view);
-
-/**
- Hide the current window.
-*/
-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.
- Everything needed in callbacks should be here, not in static variables.
-*/
-PUGL_API void
-puglSetHandle(PuglView* view, PuglHandle handle);
-
-/**
- Get the handle to be passed to all callbacks.
-*/
-PUGL_API PuglHandle
-puglGetHandle(PuglView* view);
-
-/**
- Return true iff the view is currently visible.
-*/
-PUGL_API bool
-puglGetVisible(PuglView* view);
-
-/**
- Get the current size of the view.
-*/
-PUGL_API void
-puglGetSize(PuglView* view, int* width, int* height);
-
-/**
- @name Context
- Functions for accessing the drawing context.
- @{
-*/
-
-/**
- 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);
-
-
-/**
- Enter the drawing context.
-
- This must be called before any code that accesses the drawing context,
- including any GL functions. This is only necessary for code that does so
- outside the usual draw callback or handling of an expose event.
-*/
-PUGL_API void
-puglEnterContext(PuglView* view);
-
-/**
- Leave the drawing context.
-
- This must be called after puglEnterContext and applies the results of the
- drawing code (for example, by swapping buffers).
-*/
-PUGL_API void
-puglLeaveContext(PuglView* view, bool flush);
-
-/**
- @}
-*/
-
-/**
- @name Event Handling
- @{
-*/
-
-/**
- A function called when an event occurs.
-*/
-typedef void (*PuglEventFunc)(PuglView* view, const PuglEvent* event);
-
-/**
- Set the function to call when an event occurs.
-*/
-PUGL_API void
-puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
-
-/**
- Ignore synthetic repeated key events.
-*/
-PUGL_API void
-puglIgnoreKeyRepeat(PuglView* view, bool ignore);
-
-/**
- Grab the input focus.
-*/
-PUGL_API void
-puglGrabFocus(PuglView* view);
-
-/**
- Block and wait for an event to be ready.
-
- This can be used in a loop to only process events via puglProcessEvents when
- necessary. This function will block indefinitely if no events are
- available, so is not appropriate for use in programs that need to perform
- regular updates (e.g. animation).
-*/
-PUGL_API PuglStatus
-puglWaitForEvent(PuglView* view);
-
-/**
- Process all pending window events.
-
- This handles input events as well as rendering, so it should be called
- regularly and rapidly enough to keep the UI responsive. This function does
- not block if no events are pending.
-*/
-PUGL_API PuglStatus
-puglProcessEvents(PuglView* view);
-
-/**
- @}
-*/
-
-/**
- Request a redisplay on the next call to puglProcessEvents().
-*/
-PUGL_API void
-puglPostRedisplay(PuglView* view);
-
-/**
- Destroy a GL window.
-*/
-PUGL_API void
-puglDestroy(PuglView* view);
-
-/**
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* PUGL_H_INCLUDED */
diff --git a/pugl/pugl/pugl.hpp b/pugl/pugl/pugl.hpp
deleted file mode 100644
index 8232887..0000000
--- a/pugl/pugl/pugl.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- Copyright 2012-2015 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 pugl.hpp C++ API for Pugl, a minimal portable API for OpenGL.
-*/
-
-#ifndef PUGL_HPP_INCLUDED
-#define PUGL_HPP_INCLUDED
-
-#include "pugl/pugl.h"
-
-/**
- @defgroup puglmm Puglmm
- C++ API wrapper for Pugl.
- @{
-*/
-
-namespace pugl {
-
-class View {
-public:
- View(int* pargc, char** argv)
- : _view(puglInit(pargc, argv))
- {
- puglSetHandle(_view, this);
- puglSetEventFunc(_view, _onEvent);
- }
-
- virtual ~View() { puglDestroy(_view); }
-
- virtual void initWindowParent(PuglNativeWindow parent) {
- puglInitWindowParent(_view, parent);
- }
-
- virtual void initWindowSize(int width, int height) {
- puglInitWindowSize(_view, width, height);
- }
-
- virtual void initWindowMinSize(int width, int height) {
- puglInitWindowMinSize(_view, width, height);
- }
-
- virtual void initWindowAspectRatio(int min_x, int min_y, int max_x, int max_y) {
- puglInitWindowAspectRatio(_view, min_x, min_y, max_x, max_y);
- }
-
- virtual void initResizable(bool resizable) {
- puglInitResizable(_view, resizable);
- }
-
- virtual void initTransientFor(uintptr_t parent) {
- puglInitTransientFor(_view, parent);
- }
-
- virtual void initContextType(PuglContextType type) {
- puglInitContextType(_view, type);
- }
-
- virtual void createWindow(const char* title) {
- puglCreateWindow(_view, title);
- }
-
- virtual void showWindow() { puglShowWindow(_view); }
- virtual void hideWindow() { puglHideWindow(_view); }
- virtual PuglNativeWindow getNativeWindow() { return puglGetNativeWindow(_view); }
-
- virtual void onEvent(const PuglEvent* event) = 0;
-
- virtual void* getContext() { return puglGetContext(_view); }
- virtual void ignoreKeyRepeat(bool ignore) { puglIgnoreKeyRepeat(_view, ignore); }
- virtual void grabFocus() { puglGrabFocus(_view); }
- virtual PuglStatus waitForEvent() { return puglWaitForEvent(_view); }
- virtual PuglStatus processEvents() { return puglProcessEvents(_view); }
- virtual void postRedisplay() { puglPostRedisplay(_view); }
-
- PuglView* cobj() { return _view; }
-
-private:
- static void _onEvent(PuglView* view, const PuglEvent* event) {
- ((View*)puglGetHandle(view))->onEvent(event);
- }
-
- PuglView* _view;
-};
-
-} // namespace pugl
-
-/**
- @}
-*/
-
-#endif /* PUGL_HPP_INCLUDED */
diff --git a/pugl/pugl/pugl_internal.h b/pugl/pugl/pugl_internal.h
deleted file mode 100644
index 4a3fc0c..0000000
--- a/pugl/pugl/pugl_internal.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- Copyright 2012-2016 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 pugl_internal.h Private platform-independent definitions.
-
- Note this file contains function definitions, so it must be compiled into
- the final binary exactly once. Each platform specific implementation file
- including it once should achieve this.
-
- 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.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "pugl/pugl.h"
-
-typedef struct PuglInternalsImpl PuglInternals;
-
-struct PuglViewImpl {
- PuglHandle handle;
- PuglEventFunc eventFunc;
-
- PuglInternals* impl;
-
- char* windowClass;
- PuglNativeWindow parent;
- PuglContextType ctx_type;
- uintptr_t transient_parent;
-
- int width;
- int height;
- int min_width;
- int min_height;
- int min_aspect_x;
- int min_aspect_y;
- int max_aspect_x;
- int max_aspect_y;
- bool ignoreKeyRepeat;
- bool redisplay;
- bool resizable;
- bool visible;
-};
-
-PuglInternals* puglInitInternals(void);
-
-PuglView*
-puglInit(int* pargc, char** argv)
-{
- PuglView* view = (PuglView*)calloc(1, sizeof(PuglView));
- if (!view) {
- return NULL;
- }
-
- PuglInternals* impl = puglInitInternals();
- if (!impl) {
- return NULL;
- }
-
- view->ctx_type = PUGL_GL;
- view->impl = impl;
- view->width = 640;
- view->height = 480;
-
- return view;
-}
-
-void
-puglInitWindowSize(PuglView* view, int width, int height)
-{
- view->width = width;
- view->height = height;
-}
-
-void
-puglInitWindowMinSize(PuglView* view, int width, int height)
-{
- view->min_width = width;
- view->min_height = height;
-}
-
-void
-puglInitWindowAspectRatio(PuglView* view,
- int min_x,
- int min_y,
- int max_x,
- int max_y)
-{
- view->min_aspect_x = min_x;
- view->min_aspect_y = min_y;
- view->max_aspect_x = max_x;
- view->max_aspect_y = max_y;
-}
-
-void
-puglInitWindowClass(PuglView* view, const char* name)
-{
- const size_t len = strlen(name);
-
- free(view->windowClass);
- view->windowClass = (char*)calloc(1, len + 1);
- memcpy(view->windowClass, name, len);
-}
-
-void
-puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
-{
- view->parent = parent;
-}
-
-void
-puglInitResizable(PuglView* view, bool resizable)
-{
- view->resizable = resizable;
-}
-
-void
-puglInitTransientFor(PuglView* view, uintptr_t parent)
-{
- view->transient_parent = parent;
-}
-
-void
-puglInitContextType(PuglView* view, PuglContextType type)
-{
- view->ctx_type = type;
-}
-
-void
-puglSetHandle(PuglView* view, PuglHandle handle)
-{
- view->handle = handle;
-}
-
-PuglHandle
-puglGetHandle(PuglView* view)
-{
- return view->handle;
-}
-
-bool
-puglGetVisible(PuglView* view)
-{
- return view->visible;
-}
-
-void
-puglGetSize(PuglView* view, int* width, int* height)
-{
- *width = view->width;
- *height = view->height;
-}
-
-void
-puglIgnoreKeyRepeat(PuglView* view, bool ignore)
-{
- view->ignoreKeyRepeat = ignore;
-}
-
-void
-puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc)
-{
- view->eventFunc = eventFunc;
-}
-
-/** Return the code point for buf, or the replacement character on error. */
-static uint32_t
-puglDecodeUTF8(const uint8_t* buf)
-{
-#define FAIL_IF(cond) { if (cond) return 0xFFFD; }
-
- // http://en.wikipedia.org/wiki/UTF-8
-
- if (buf[0] < 0x80) {
- return buf[0];
- } else if (buf[0] < 0xC2) {
- return 0xFFFD;
- } else if (buf[0] < 0xE0) {
- FAIL_IF((buf[1] & 0xC0) != 0x80);
- return (buf[0] << 6) + buf[1] - 0x3080;
- } else if (buf[0] < 0xF0) {
- FAIL_IF((buf[1] & 0xC0) != 0x80);
- FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0);
- FAIL_IF((buf[2] & 0xC0) != 0x80);
- return (buf[0] << 12) + (buf[1] << 6) + buf[2] - 0xE2080;
- } else if (buf[0] < 0xF5) {
- FAIL_IF((buf[1] & 0xC0) != 0x80);
- FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90);
- FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90);
- FAIL_IF((buf[2] & 0xC0) != 0x80);
- FAIL_IF((buf[3] & 0xC0) != 0x80);
- return ((buf[0] << 18) +
- (buf[1] << 12) +
- (buf[2] << 6) +
- buf[3] - 0x3C82080);
- }
- return 0xFFFD;
-}
-
-static void
-puglDispatchEvent(PuglView* view, const PuglEvent* event)
-{
- switch (event->type) {
- case PUGL_NOTHING:
- break;
- case PUGL_CONFIGURE:
- view->width = event->configure.width;
- view->height = event->configure.height;
- puglEnterContext(view);
- view->eventFunc(view, event);
- puglLeaveContext(view, false);
- break;
- case PUGL_EXPOSE:
- if (event->expose.count == 0) {
- puglEnterContext(view);
- view->eventFunc(view, event);
- puglLeaveContext(view, true);
- }
- break;
- default:
- view->eventFunc(view, event);
- }
-}
diff --git a/pugl/pugl/pugl_osx.m b/pugl/pugl/pugl_osx.m
deleted file mode 100644
index d2681cb..0000000
--- a/pugl/pugl/pugl_osx.m
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- Copyright 2012-2016 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 pugl_osx.m OSX/Cocoa Pugl Implementation.
-*/
-
-#include <stdlib.h>
-
-#import <Cocoa/Cocoa.h>
-
-#include "pugl/cairo_gl.h"
-#include "pugl/gl.h"
-#include "pugl/pugl_internal.h"
-
-@class PuglOpenGLView;
-
-struct PuglInternalsImpl {
- NSApplication* app;
- PuglOpenGLView* glview;
- id window;
- NSEvent* nextEvent;
-#ifdef PUGL_HAVE_CAIRO
- cairo_surface_t* surface;
- cairo_t* cr;
- PuglCairoGL cairo_gl;
-#endif
-};
-
-@interface PuglWindow : NSWindow
-{
-@public
- PuglView* puglview;
-}
-
-- (id) initWithContentRect:(NSRect)contentRect
- styleMask:(unsigned int)aStyle
- backing:(NSBackingStoreType)bufferingType
- defer:(BOOL)flag;
-- (void) setPuglview:(PuglView*)view;
-- (BOOL) windowShouldClose:(id)sender;
-- (BOOL) canBecomeKeyWindow:(id)sender;
-@end
-
-@implementation PuglWindow
-
-- (id)initWithContentRect:(NSRect)contentRect
- styleMask:(unsigned int)aStyle
- backing:(NSBackingStoreType)bufferingType
- defer:(BOOL)flag
-{
- if (![super initWithContentRect:contentRect
- styleMask:(NSClosableWindowMask |
- NSTitledWindowMask |
- NSResizableWindowMask)
- backing:NSBackingStoreBuffered defer:NO]) {
- return nil;
- }
-
- [self setAcceptsMouseMovedEvents:YES];
- return (PuglWindow*)self;
-}
-
-- (void)setPuglview:(PuglView*)view
-{
- puglview = view;
- [self setContentSize:NSMakeSize(view->width, view->height)];
-}
-
-- (BOOL)windowShouldClose:(id)sender
-{
- const PuglEventClose ev = {
- PUGL_CLOSE,
- puglview,
- 0
- };
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
-
- return YES;
-}
-
-- (BOOL) canBecomeKeyWindow
-{
- return YES;
-}
-
-- (BOOL) canBecomeMainWindow
-{
- return YES;
-}
-
-- (BOOL) canBecomeKeyWindow:(id)sender
-{
- return NO;
-}
-
-@end
-
-@interface PuglOpenGLView : NSOpenGLView
-{
-@public
- PuglView* puglview;
-
- NSTrackingArea* trackingArea;
-}
-
-- (id) initWithFrame:(NSRect)frame;
-- (void) reshape;
-- (void) drawRect:(NSRect)rect;
-- (NSPoint) eventLocation:(NSEvent*)event;
-- (void) mouseEntered:(NSEvent*)event;
-- (void) mouseExited:(NSEvent*)event;
-- (void) mouseMoved:(NSEvent*)event;
-- (void) mouseDragged:(NSEvent*)event;
-- (void) rightMouseDragged:(NSEvent*)event;
-- (void) mouseDown:(NSEvent*)event;
-- (void) mouseUp:(NSEvent*)event;
-- (void) rightMouseDragged:(NSEvent*)event;
-- (void) rightMouseDown:(NSEvent*)event;
-- (void) rightMouseUp:(NSEvent*)event;
-- (void) otherMouseDragged:(NSEvent*)event;
-- (void) otherMouseDown:(NSEvent*)event;
-- (void) otherMouseUp:(NSEvent*)event;
-- (void) scrollWheel:(NSEvent*)event;
-- (void) keyDown:(NSEvent*)event;
-- (void) keyUp:(NSEvent*)event;
-- (void) flagsChanged:(NSEvent*)event;
-
-@end
-
-@implementation PuglOpenGLView
-
-- (id) initWithFrame:(NSRect)frame
-{
- NSOpenGLPixelFormatAttribute pixelAttribs[16] = {
- NSOpenGLPFADoubleBuffer,
- NSOpenGLPFAAccelerated,
- NSOpenGLPFAColorSize, 32,
- NSOpenGLPFADepthSize, 32,
- 0
- };
-
- NSOpenGLPixelFormat* pixelFormat = [
- [NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs];
-
- if (pixelFormat) {
- self = [super initWithFrame:frame pixelFormat:pixelFormat];
- [pixelFormat release];
- } else {
- self = [super initWithFrame:frame];
- }
-
- if (self) {
- [[self openGLContext] makeCurrentContext];
- [self reshape];
- }
- return self;
-}
-
-- (void) reshape
-{
- [[self openGLContext] update];
-
- if (!puglview) {
- return;
- }
-
- const NSRect bounds = [self bounds];
- const PuglEventConfigure ev = {
- PUGL_CONFIGURE,
- puglview,
- 0,
- bounds.origin.x,
- bounds.origin.y,
- bounds.size.width,
- bounds.size.height,
- };
-
-#ifdef PUGL_HAVE_CAIRO
- PuglInternals* impl = puglview->impl;
- if (puglview->ctx_type & PUGL_CAIRO) {
- cairo_surface_destroy(impl->surface);
- cairo_destroy(impl->cr);
- impl->surface = pugl_cairo_gl_create(
- &impl->cairo_gl, ev.width, ev.height, 4);
- impl->cr = cairo_create(impl->surface);
- pugl_cairo_gl_configure(&impl->cairo_gl, ev.width, ev.height);
- }
-#endif
-
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
-}
-
-- (void) drawRect:(NSRect)rect
-{
- const PuglEventExpose ev = {
- PUGL_EXPOSE,
- puglview,
- 0,
- rect.origin.x,
- rect.origin.y,
- rect.size.width,
- rect.size.height,
- 0
- };
-
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
-
-#ifdef PUGL_HAVE_CAIRO
- if (puglview->ctx_type & PUGL_CAIRO) {
- pugl_cairo_gl_draw(
- &puglview->impl->cairo_gl, puglview->width, puglview->height);
- }
-#endif
-}
-
-- (BOOL) acceptsFirstResponder
-{
- return YES;
-}
-
-static unsigned
-getModifiers(PuglView* view, NSEvent* ev)
-{
- const unsigned modifierFlags = [ev modifierFlags];
-
- unsigned mods = 0;
- mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
- mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
- mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0;
- mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0;
- return mods;
-}
-
--(void)updateTrackingAreas
-{
- if (trackingArea != nil) {
- [self removeTrackingArea:trackingArea];
- [trackingArea release];
- }
-
- const int opts = (NSTrackingMouseEnteredAndExited |
- NSTrackingMouseMoved |
- NSTrackingActiveAlways);
- trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
- options:opts
- owner:self
- userInfo:nil];
- [self addTrackingArea:trackingArea];
-}
-
-- (NSPoint) eventLocation:(NSEvent*)event
-{
- return [self convertPoint:[event locationInWindow] fromView:nil];
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent
-{
- [self updateTrackingAreas];
-}
-
-- (void)mouseExited:(NSEvent*)theEvent
-{
-}
-
-- (void) mouseMoved:(NSEvent*)event
-{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventMotion ev = {
- PUGL_MOTION_NOTIFY,
- puglview,
- 0,
- [event timestamp],
- wloc.x,
- puglview->height - wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(puglview, event),
- 0,
- 1
- };
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
-}
-
-- (void) mouseDragged:(NSEvent*)event
-{
- [self mouseMoved: event];
-}
-
-- (void) rightMouseDragged:(NSEvent*)event
-{
- [self mouseMoved: event];
-}
-
-- (void) otherMouseDragged:(NSEvent*)event
-{
- [self mouseMoved: event];
-}
-
-- (void) mouseDown:(NSEvent*)event
-{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventButton ev = {
- PUGL_BUTTON_PRESS,
- puglview,
- 0,
- [event timestamp],
- wloc.x,
- puglview->height - wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(puglview, event),
- [event buttonNumber] + 1
- };
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
-}
-
-- (void) mouseUp:(NSEvent*)event
-{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventButton ev = {
- PUGL_BUTTON_RELEASE,
- puglview,
- 0,
- [event timestamp],
- wloc.x,
- puglview->height - wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(puglview, event),
- [event buttonNumber] + 1
- };
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
- [self updateTrackingAreas];
-}
-
-- (void) rightMouseDown:(NSEvent*)event
-{
- [self mouseDown: event];
-}
-
-- (void) rightMouseUp:(NSEvent*)event
-{
- [self mouseUp: event];
-}
-
-- (void) otherMouseDown:(NSEvent*)event
-{
- [self mouseDown: event];
-}
-
-- (void) otherMouseUp:(NSEvent*)event
-{
- [self mouseUp: event];
-}
-
-- (void) scrollWheel:(NSEvent*)event
-{
- [self updateTrackingAreas];
-
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventScroll ev = {
- PUGL_SCROLL,
- puglview,
- 0,
- [event timestamp],
- wloc.x,
- puglview->height - wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(puglview, event),
- [event deltaX],
- [event deltaY]
- };
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
- [self updateTrackingAreas];
-}
-
-- (void) keyDown:(NSEvent*)event
-{
- if (puglview->ignoreKeyRepeat && [event isARepeat]) {
- return;
- }
-
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const NSString* chars = [event characters];
- const char* str = [chars UTF8String];
- PuglEventKey ev = {
- PUGL_KEY_PRESS,
- puglview,
- 0,
- [event timestamp],
- wloc.x,
- puglview->height - wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(puglview, event),
- [event keyCode],
- puglDecodeUTF8((const uint8_t*)str),
- 0, // TODO: Special keys?
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- false
- };
- strncpy((char*)ev.utf8, str, 8);
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
-}
-
-- (void) keyUp:(NSEvent*)event
-{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const NSString* chars = [event characters];
- const char* str = [chars UTF8String];
- const PuglEventKey ev = {
- PUGL_KEY_RELEASE,
- puglview,
- 0,
- [event timestamp],
- wloc.x,
- puglview->height - wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(puglview, event),
- [event keyCode],
- puglDecodeUTF8((const uint8_t*)str),
- 0, // TODO: Special keys?
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- false,
- };
- strncpy((char*)ev.utf8, str, 8);
- puglDispatchEvent(puglview, (PuglEvent*)&ev);
-}
-
-- (void) flagsChanged:(NSEvent*)event
-{
- // TODO: Is this a sensible way to handle special keys?
- /*
- const unsigned mods = getModifiers(puglview, event);
- if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) {
- puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT);
- } else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) {
- puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL);
- } else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) {
- puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT);
- } else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) {
- puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER);
- }
- puglview->mods = mods;
- }
- */
-}
-
-@end
-
-PuglInternals*
-puglInitInternals(void)
-{
- return (PuglInternals*)calloc(1, sizeof(PuglInternals));
-}
-
-void
-puglEnterContext(PuglView* view)
-{
- [[view->impl->glview openGLContext] makeCurrentContext];
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- cairo_set_source_rgb(view->impl->cr, 0, 0, 0);
- cairo_paint(view->impl->cr);
- }
-#endif
-}
-
-void
-puglLeaveContext(PuglView* view, bool flush)
-{
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- pugl_cairo_gl_draw(&view->impl->cairo_gl, view->width, view->height);
- }
-#endif
-
- if (flush) {
- [[view->impl->glview openGLContext] flushBuffer];
- }
-}
-
-int
-puglCreateWindow(PuglView* view, const char* title)
-{
- PuglInternals* impl = view->impl;
-
- [NSAutoreleasePool new];
- impl->app = [NSApplication sharedApplication];
-
- impl->glview = [PuglOpenGLView new];
- impl->glview->puglview = view;
-
- if (view->transient_parent) {
- NSView* pview = (NSView*)view->transient_parent;
- [pview addSubview:impl->glview];
- [impl->glview setHidden:NO];
- } else {
- NSString* titleString = [[NSString alloc]
- initWithBytes:title
- length:strlen(title)
- encoding:NSUTF8StringEncoding];
-
- id window = [[PuglWindow new] retain];
- [window setPuglview:view];
- [window setTitle:titleString];
- if (view->min_width || view->min_height) {
- [window setContentMinSize:NSMakeSize(view->min_width,
- view->min_height)];
- }
- impl->window = window;
-
- [window setContentView:impl->glview];
- [impl->app activateIgnoringOtherApps:YES];
- [window makeFirstResponder:impl->glview];
- [window makeKeyAndOrderFront:window];
-#if 0
- if (resizable) {
- [impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
- }
-#endif
- }
-
- return 0;
-}
-
-void
-puglShowWindow(PuglView* view)
-{
- [view->impl->window setIsVisible:YES];
- view->visible = true;
-}
-
-void
-puglHideWindow(PuglView* view)
-{
- [view->impl->window setIsVisible:NO];
- view->visible = false;
-}
-
-void
-puglDestroy(PuglView* view)
-{
-#ifdef PUGL_HAVE_CAIRO
- pugl_cairo_gl_free(&view->impl->cairo_gl);
-#endif
- view->impl->glview->puglview = NULL;
- [view->impl->glview removeFromSuperview];
- if (view->impl->window) {
- [view->impl->window close];
- }
- [view->impl->glview release];
- if (view->impl->window) {
- [view->impl->window release];
- }
- free(view->windowClass);
- free(view->impl);
- free(view);
-}
-
-void
-puglGrabFocus(PuglView* view)
-{
- // TODO
-}
-
-PuglStatus
-puglWaitForEvent(PuglView* view)
-{
- /* OSX supposedly has queue: and untilDate: selectors that can be used for
- a blocking non-queueing event check, but if used here cause an
- unsupported selector error at runtime. I have no idea why, so just get
- the event and keep it around until the call to puglProcessEvents. */
- if (!view->impl->nextEvent) {
- view->impl->nextEvent = [view->impl->window
- nextEventMatchingMask: NSAnyEventMask];
- }
-
- return PUGL_SUCCESS;
-}
-
-PuglStatus
-puglProcessEvents(PuglView* view)
-{
- while (true) {
- // Get the next event, or use the cached one from puglWaitForEvent
- if (!view->impl->nextEvent) {
- view->impl->nextEvent = [view->impl->window
- nextEventMatchingMask: NSAnyEventMask];
- }
-
- if (!view->impl->nextEvent) {
- break; // No events to process, done
- }
-
- // Dispatch event
- [view->impl->app sendEvent: view->impl->nextEvent];
- view->impl->nextEvent = NULL;
- }
-
- return PUGL_SUCCESS;
-}
-
-void
-puglPostRedisplay(PuglView* view)
-{
- //view->redisplay = true; // unused
- [view->impl->glview setNeedsDisplay: YES];
-}
-
-PuglNativeWindow
-puglGetNativeWindow(PuglView* view)
-{
- return (PuglNativeWindow)view->impl->glview;
-}
-
-void*
-puglGetContext(PuglView* view)
-{
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- return view->impl->cr;
- }
-#endif
- return NULL;
-}
diff --git a/pugl/pugl/pugl_win.cpp b/pugl/pugl/pugl_win.cpp
deleted file mode 100644
index 83d4474..0000000
--- a/pugl/pugl/pugl_win.cpp
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- Copyright 2012-2015 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 pugl_win.cpp Windows/WGL Pugl Implementation.
-*/
-
-#include <windows.h>
-#include <windowsx.h>
-#include <GL/gl.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wctype.h>
-
-#include "pugl/pugl_internal.h"
-
-#ifndef WM_MOUSEWHEEL
-# define WM_MOUSEWHEEL 0x020A
-#endif
-#ifndef WM_MOUSEHWHEEL
-# define WM_MOUSEHWHEEL 0x020E
-#endif
-#ifndef WHEEL_DELTA
-# define WHEEL_DELTA 120
-#endif
-#ifdef _WIN64
-# ifndef GWLP_USERDATA
-# define GWLP_USERDATA (-21)
-# endif
-#else
-# ifndef GWL_USERDATA
-# define GWL_USERDATA (-21)
-# endif
-#endif
-
-#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)
-
-struct PuglInternalsImpl {
- HWND hwnd;
- HDC hdc;
- HGLRC hglrc;
- WNDCLASS wc;
-};
-
-LRESULT CALLBACK
-wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-
-PuglView*
-puglInit()
-{
- PuglView* view = (PuglView*)calloc(1, sizeof(PuglView));
- PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
- if (!view || !impl) {
- return NULL;
- }
-
- view->impl = impl;
- view->width = 640;
- view->height = 480;
-
- return view;
-}
-
-PuglInternals*
-puglInitInternals(void)
-{
- return (PuglInternals*)calloc(1, sizeof(PuglInternals));
-}
-
-void
-puglEnterContext(PuglView* view)
-{
- PAINTSTRUCT ps;
- BeginPaint(view->impl->hwnd, &ps);
-
-#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
-
- PAINTSTRUCT ps;
- EndPaint(view->impl->hwnd, &ps);
-}
-
-int
-puglCreateWindow(PuglView* view, const char* title)
-{
- static const TCHAR* DEFAULT_CLASSNAME = "Pugl";
-
- PuglInternals* impl = view->impl;
-
- if (!title) {
- title = "Window";
- }
-
- WNDCLASSEX wc;
- memset(&wc, 0, sizeof(wc));
- wc.cbSize = sizeof(wc);
- wc.style = CS_OWNDC;
- wc.lpfnWndProc = wndProc;
- wc.hInstance = GetModuleHandle(NULL);
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // TODO: user-specified icon
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.lpszClassName = view->windowClass ? view->windowClass : DEFAULT_CLASSNAME;
- if (!RegisterClassEx(&wc)) {
- free((void*)impl->wc.lpszClassName);
- free(impl);
- free(view);
- return NULL;
- }
-
- int winFlags = WS_POPUPWINDOW | WS_CAPTION;
- if (view->resizable) {
- winFlags |= WS_SIZEBOX;
- if (view->min_width || view->min_height) {
- // Adjust the minimum window size to accomodate requested view size
- RECT mr = { 0, 0, view->min_width, view->min_height };
- AdjustWindowRectEx(&mr, winFlags, FALSE, WS_EX_TOPMOST);
- view->min_width = mr.right - mr.left;
- view->min_height = mr.bottom - mr.top;
- }
- }
-
- // Adjust the window size to accomodate requested view size
- RECT wr = { 0, 0, view->width, view->height };
- AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST);
-
- impl->hwnd = CreateWindowEx(
- WS_EX_TOPMOST,
- wc.lpszClassName, title,
- (view->parent ? WS_CHILD : winFlags),
- CW_USEDEFAULT, CW_USEDEFAULT, wr.right-wr.left, wr.bottom-wr.top,
- (HWND)view->parent, NULL, NULL, NULL);
-
- if (!impl->hwnd) {
- 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);
-
- PIXELFORMATDESCRIPTOR pfd;
- ZeroMemory(&pfd, sizeof(pfd));
- pfd.nSize = sizeof(pfd);
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = 24;
- pfd.cDepthBits = 16;
- pfd.iLayerType = PFD_MAIN_PLANE;
-
- int format = ChoosePixelFormat(impl->hdc, &pfd);
- 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 NULL;
- }
- wglMakeCurrent(impl->hdc, impl->hglrc);
-
- return 0;
-}
-
-void
-puglShowWindow(PuglView* view)
-{
- PuglInternals* impl = view->impl;
-
- ShowWindow(impl->hwnd, SW_SHOWNORMAL);
- view->visible = true;
-}
-
-void
-puglHideWindow(PuglView* view)
-{
- PuglInternals* impl = view->impl;
-
- ShowWindow(impl->hwnd, SW_HIDE);
- view->visible = false;
-}
-
-void
-puglDestroy(PuglView* view)
-{
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(view->impl->hglrc);
- ReleaseDC(view->impl->hwnd, view->impl->hdc);
- DestroyWindow(view->impl->hwnd);
- UnregisterClass(view->impl->wc.lpszClassName, NULL);
- free(view->windowClass);
- free(view->impl);
- free(view);
-}
-
-static PuglKey
-keySymToSpecial(int sym)
-{
- switch (sym) {
- case VK_F1: return PUGL_KEY_F1;
- case VK_F2: return PUGL_KEY_F2;
- case VK_F3: return PUGL_KEY_F3;
- case VK_F4: return PUGL_KEY_F4;
- case VK_F5: return PUGL_KEY_F5;
- case VK_F6: return PUGL_KEY_F6;
- case VK_F7: return PUGL_KEY_F7;
- case VK_F8: return PUGL_KEY_F8;
- case VK_F9: return PUGL_KEY_F9;
- case VK_F10: return PUGL_KEY_F10;
- case VK_F11: return PUGL_KEY_F11;
- case VK_F12: return PUGL_KEY_F12;
- case VK_LEFT: return PUGL_KEY_LEFT;
- case VK_UP: return PUGL_KEY_UP;
- case VK_RIGHT: return PUGL_KEY_RIGHT;
- case VK_DOWN: return PUGL_KEY_DOWN;
- case VK_PRIOR: return PUGL_KEY_PAGE_UP;
- case VK_NEXT: return PUGL_KEY_PAGE_DOWN;
- case VK_HOME: return PUGL_KEY_HOME;
- case VK_END: return PUGL_KEY_END;
- case VK_INSERT: return PUGL_KEY_INSERT;
- case VK_SHIFT: return PUGL_KEY_SHIFT;
- case VK_CONTROL: return PUGL_KEY_CTRL;
- case VK_MENU: return PUGL_KEY_ALT;
- case VK_LWIN: return PUGL_KEY_SUPER;
- case VK_RWIN: return PUGL_KEY_SUPER;
- }
- return (PuglKey)0;
-}
-
-static unsigned int
-getModifiers()
-{
- unsigned int mods = 0;
- mods |= (GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0;
- mods |= (GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0;
- mods |= (GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0;
- mods |= (GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0;
- mods |= (GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0;
- return mods;
-}
-
-static void
-initMouseEvent(PuglEvent* event,
- PuglView* view,
- int button,
- bool press,
- LPARAM lParam)
-{
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- ClientToScreen(view->impl->hwnd, &pt);
-
- if (press) {
- SetCapture(view->impl->hwnd);
- } else {
- ReleaseCapture();
- }
-
- event->button.time = GetMessageTime();
- event->button.type = press ? PUGL_BUTTON_PRESS : PUGL_BUTTON_RELEASE;
- event->button.x = GET_X_LPARAM(lParam);
- event->button.y = GET_Y_LPARAM(lParam);
- event->button.x_root = pt.x;
- event->button.y_root = pt.y;
- event->button.state = getModifiers();
- event->button.button = button;
-}
-
-static void
-initScrollEvent(PuglEvent* event, PuglView* view, LPARAM lParam, WPARAM wParam)
-{
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- ScreenToClient(view->impl->hwnd, &pt);
-
- event->scroll.time = GetMessageTime();
- event->scroll.type = PUGL_SCROLL;
- event->scroll.x = pt.x;
- event->scroll.y = pt.y;
- event->scroll.x_root = GET_X_LPARAM(lParam);
- event->scroll.y_root = GET_Y_LPARAM(lParam);
- event->scroll.state = getModifiers();
- event->scroll.dx = 0;
- event->scroll.dy = 0;
-}
-
-static unsigned int
-utf16_to_code_point(const wchar_t* input, size_t input_size)
-{
- unsigned int code_unit = *input;
- // Equiv. range check between 0xD800 to 0xDBFF inclusive
- if ((code_unit & 0xFC00) == 0xD800) {
- if (input_size < 2) {
- // "Error: is surrogate but input_size too small"
- return 0xFFFD; // replacement character
- }
-
- unsigned int code_unit_2 = *++input;
- // Equiv. range check between 0xDC00 to 0xDFFF inclusive
- if ((code_unit_2 & 0xFC00) == 0xDC00) {
- return (code_unit << 10) + code_unit_2 - 0x35FDC00;
- }
-
- // TODO: push_back(code_unit_2);
- // "Error: Unpaired surrogates."
- return 0xFFFD; // replacement character
- }
- return code_unit;
-}
-
-static void
-initKeyEvent(PuglEvent* event, PuglView* view, bool press, LPARAM lParam)
-{
- POINT rpos = { 0, 0 };
- GetCursorPos(&rpos);
-
- POINT cpos = { rpos.x, rpos.y };
- ScreenToClient(view->impl->hwnd, &rpos);
-
- event->key.type = press ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
- event->key.time = GetMessageTime();
- event->key.state = getModifiers();
- event->key.x_root = rpos.x;
- event->key.y_root = rpos.y;
- event->key.x = cpos.x;
- event->key.y = cpos.y;
- event->key.keycode = (lParam & 0xFF0000) >> 16;
- event->key.character = 0;
- event->key.special = static_cast<PuglKey>(0);
- event->key.filter = 0;
-}
-
-static void
-wcharBufToEvent(wchar_t* buf, int n, PuglEvent* event)
-{
- if (n > 0) {
- char* charp = reinterpret_cast<char*>(event->key.utf8);
- if (!WideCharToMultiByte(CP_UTF8, 0, buf, n,
- charp, 8, NULL, NULL)) {
- /* error: could not convert to utf-8,
- GetLastError has details */
- memset(event->key.utf8, 0, 8);
- // replacement character
- event->key.utf8[0] = 0xEF;
- event->key.utf8[1] = 0xBF;
- event->key.utf8[2] = 0xBD;
- }
-
- event->key.character = utf16_to_code_point(buf, n);
- } else {
- // replacement character
- event->key.utf8[0] = 0xEF;
- event->key.utf8[1] = 0xBF;
- event->key.utf8[2] = 0xBD;
- event->key.character = 0xFFFD;
- }
-}
-
-static void
-translateMessageParamsToEvent(LPARAM lParam, WPARAM wParam, PuglEvent* event)
-{
- /* TODO: This is a kludge. Would be nice to use ToUnicode here, but this
- breaks composed keys because it messes with the keyboard state. Not
- sure how to correctly handle this on Windows. */
-
- // This is how I really want to do this, but it breaks composed keys (é,
- // è, ü, ö, and so on) because ToUnicode messes with the keyboard state.
-
- //wchar_t buf[5];
- //BYTE keyboard_state[256];
- //int wcharCount = 0;
- //GetKeyboardState(keyboard_state);
- //wcharCount = ToUnicode(wParam, MapVirtualKey(wParam, MAPVK_VK_TO_VSC),
- // keyboard_state, buf, 4, 0);
- //wcharBufToEvent(buf, wcharCount, event);
-
- // So, since Google refuses to give me a better solution, and if no one
- // else has a better solution, I will make a hack...
- wchar_t buf[5] = { 0, 0, 0, 0, 0 };
- UINT c = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
- buf[0] = c & 0xffff;
- // TODO: This does not take caps lock into account
- // TODO: Dead keys should affect key releases as well
- if (!(event->key.state && PUGL_MOD_SHIFT))
- buf[0] = towlower(buf[0]);
- wcharBufToEvent(buf, 1, event);
- event->key.filter = ((c >> 31) & 0x1);
-}
-
-static void
-translateCharEventToEvent(WPARAM wParam, PuglEvent* event)
-{
- wchar_t buf[2];
- int wcharCount;
- if (wParam & 0xFFFF0000) {
- wcharCount = 2;
- buf[0] = (wParam & 0xFFFF);
- buf[1] = ((wParam >> 16) & 0xFFFF);
- } else {
- wcharCount = 1;
- buf[0] = (wParam & 0xFFFF);
- }
- wcharBufToEvent(buf, wcharCount, event);
-}
-
-static bool
-ignoreKeyEvent(PuglView* view, LPARAM lParam)
-{
- return view->ignoreKeyRepeat && (lParam & (1 << 30));
-}
-
-static LRESULT
-handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
-{
- PuglEvent event;
- void* dummy_ptr = NULL;
- RECT rect;
- MINMAXINFO* mmi;
- POINT pt;
- bool dispatchThisEvent = true;
-
- memset(&event, 0, sizeof(event));
-
- event.any.type = PUGL_NOTHING;
- event.any.view = view;
- if (InSendMessageEx(dummy_ptr)) {
- event.any.flags |= PUGL_IS_SEND_EVENT;
- }
-
- switch (message) {
- case WM_CREATE:
- case WM_SHOWWINDOW:
- case WM_SIZE:
- GetWindowRect(view->impl->hwnd, &rect);
- event.configure.type = PUGL_CONFIGURE;
- event.configure.x = rect.left;
- event.configure.y = rect.top;
- view->width = rect.right - rect.left;
- view->height = rect.bottom - rect.top;
- event.configure.width = view->width;
- event.configure.height = view->height;
- break;
- case WM_GETMINMAXINFO:
- mmi = (MINMAXINFO*)lParam;
- mmi->ptMinTrackSize.x = view->min_width;
- mmi->ptMinTrackSize.y = view->min_height;
- break;
- case WM_PAINT:
- GetUpdateRect(view->impl->hwnd, &rect, false);
- event.expose.type = PUGL_EXPOSE;
- event.expose.x = rect.left;
- event.expose.y = rect.top;
- event.expose.width = rect.right - rect.left;
- event.expose.height = rect.bottom - rect.top;
- event.expose.count = 0;
- break;
- case WM_MOUSEMOVE:
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- ClientToScreen(view->impl->hwnd, &pt);
-
- event.motion.type = PUGL_MOTION_NOTIFY;
- event.motion.time = GetMessageTime();
- event.motion.x = GET_X_LPARAM(lParam);
- event.motion.y = GET_Y_LPARAM(lParam);
- event.motion.x_root = pt.x;
- event.motion.y_root = pt.y;
- event.motion.state = getModifiers();
- event.motion.is_hint = false;
- break;
- case WM_LBUTTONDOWN:
- initMouseEvent(&event, view, 1, true, lParam);
- break;
- case WM_MBUTTONDOWN:
- initMouseEvent(&event, view, 2, true, lParam);
- break;
- case WM_RBUTTONDOWN:
- initMouseEvent(&event, view, 3, true, lParam);
- break;
- case WM_LBUTTONUP:
- initMouseEvent(&event, view, 1, false, lParam);
- break;
- case WM_MBUTTONUP:
- initMouseEvent(&event, view, 2, false, lParam);
- break;
- case WM_RBUTTONUP:
- initMouseEvent(&event, view, 3, false, lParam);
- break;
- case WM_MOUSEWHEEL:
- initScrollEvent(&event, view, lParam, wParam);
- event.scroll.dy = GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
- break;
- case WM_MOUSEHWHEEL:
- initScrollEvent(&event, view, lParam, wParam);
- event.scroll.dx = GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
- break;
- case WM_KEYDOWN:
- if (!ignoreKeyEvent(view, lParam)) {
- initKeyEvent(&event, view, true, lParam);
- if (!(event.key.special = keySymToSpecial(wParam))) {
- event.key.type = PUGL_NOTHING;
- }
- }
- break;
- case WM_CHAR:
- if (!ignoreKeyEvent(view, lParam)) {
- initKeyEvent(&event, view, true, lParam);
- translateCharEventToEvent(wParam, &event);
- }
- break;
- case WM_DEADCHAR:
- if (!ignoreKeyEvent(view, lParam)) {
- initKeyEvent(&event, view, true, lParam);
- translateCharEventToEvent(wParam, &event);
- event.key.filter = 1;
- }
- break;
- case WM_KEYUP:
- initKeyEvent(&event, view, false, lParam);
- if (!(event.key.special = keySymToSpecial(wParam))) {
- translateMessageParamsToEvent(lParam, wParam, &event);
- }
- break;
- case WM_QUIT:
- case PUGL_LOCAL_CLOSE_MSG:
- event.close.type = PUGL_CLOSE;
- break;
- default:
- return DefWindowProc(
- view->impl->hwnd, message, wParam, lParam);
- }
-
- puglDispatchEvent(view, &event);
-
- return 0;
-}
-
-void
-puglGrabFocus(PuglView* view)
-{
- // TODO
-}
-
-PuglStatus
-puglWaitForEvent(PuglView* view)
-{
- WaitMessage();
- return PUGL_SUCCESS;
-}
-
-PuglStatus
-puglProcessEvents(PuglView* view)
-{
- MSG msg;
- while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- handleMessage(view, msg.message, msg.wParam, msg.lParam);
- }
-
- if (view->redisplay) {
- InvalidateRect(view->impl->hwnd, NULL, FALSE);
- view->redisplay = false;
- }
-
- return PUGL_SUCCESS;
-}
-
-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);
- return 0;
- case WM_DESTROY:
- return 0;
- default:
- if (view && hwnd == view->impl->hwnd) {
- return handleMessage(view, message, wParam, lParam);
- } else {
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
- }
-}
-
-void
-puglPostRedisplay(PuglView* view)
-{
- view->redisplay = true;
-}
-
-PuglNativeWindow
-puglGetNativeWindow(PuglView* view)
-{
- return (PuglNativeWindow)view->impl->hwnd;
-}
diff --git a/pugl/pugl/pugl_x11.c b/pugl/pugl/pugl_x11.c
deleted file mode 100644
index 6a9135b..0000000
--- a/pugl/pugl/pugl_x11.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- Copyright 2012-2016 David Robillard <http://drobilla.net>
- Copyright 2013 Robin Gareus <robin@gareus.org>
- Copyright 2011-2012 Ben Loftis, Harrison Consoles
-
- 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 pugl_x11.c X11 Pugl Implementation.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.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/cairo_gl.h"
-#include "pugl/pugl_internal.h"
-
-#ifndef MIN
-# define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
-#ifndef MAX
-# define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#endif
-
-#ifdef PUGL_HAVE_GL
-
-/** Attributes for double-buffered RGBA. */
-static int attrListDbl[] = {
- GLX_RGBA,
- GLX_DOUBLEBUFFER , True,
- GLX_RED_SIZE , 4,
- GLX_GREEN_SIZE , 4,
- GLX_BLUE_SIZE , 4,
- GLX_DEPTH_SIZE , 16,
- /* GLX_SAMPLE_BUFFERS , 1, */
- /* GLX_SAMPLES , 4, */
- None
-};
-
-/** Attributes for single-buffered RGBA. */
-static int attrListSgl[] = {
- GLX_RGBA,
- GLX_DOUBLEBUFFER , False,
- GLX_RED_SIZE , 4,
- GLX_GREEN_SIZE , 4,
- GLX_BLUE_SIZE , 4,
- GLX_DEPTH_SIZE , 16,
- /* GLX_SAMPLE_BUFFERS , 1, */
- /* GLX_SAMPLES , 4, */
- None
-};
-
-/** Null-terminated list of attributes in order of preference. */
-static int* attrLists[] = { attrListDbl, attrListSgl, NULL };
-
-#endif // PUGL_HAVE_GL
-
-struct PuglInternalsImpl {
- Display* display;
- int screen;
- Window win;
- XIM xim;
- XIC xic;
-#ifdef PUGL_HAVE_CAIRO
- cairo_surface_t* surface;
- cairo_t* cr;
-#endif
-#ifdef PUGL_HAVE_GL
- GLXContext ctx;
- int doubleBuffered;
-#endif
-#if defined(PUGL_HAVE_CAIRO) && defined(PUGL_HAVE_GL)
- PuglCairoGL cairo_gl;
-#endif
-};
-
-PuglInternals*
-puglInitInternals(void)
-{
- 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) {
- for (int* attr = *attrLists; !vi && *attr; ++attr) {
- vi = glXChooseVisual(impl->display, impl->screen, attr);
- }
- }
-#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;
-}
-
-#ifdef PUGL_HAVE_CAIRO
-static int
-createCairoContext(PuglView* view)
-{
- PuglInternals* const impl = view->impl;
-
- if (impl->cr) {
- cairo_destroy(impl->cr);
- }
-
- impl->cr = cairo_create(impl->surface);
- return cairo_status(impl->cr);
-}
-#endif
-
-static bool
-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);
- glXGetConfig(impl->display, vi, GLX_DOUBLEBUFFER, &impl->doubleBuffered);
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- impl->surface = cairo_xlib_surface_create(
- impl->display, impl->win, vi->visual, view->width, view->height);
- }
-#endif
-#if defined(PUGL_HAVE_GL) && defined(PUGL_HAVE_CAIRO)
- if (view->ctx_type == PUGL_CAIRO_GL) {
- impl->surface = pugl_cairo_gl_create(
- &impl->cairo_gl, view->width, view->height, 4);
- }
-#endif
-
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- if (cairo_surface_status(impl->surface) != CAIRO_STATUS_SUCCESS) {
- fprintf(stderr, "error: failed to create cairo surface\n");
- return false;
- }
-
- if (createCairoContext(view) != CAIRO_STATUS_SUCCESS) {
- cairo_surface_destroy(impl->surface);
- fprintf(stderr, "error: failed to create cairo context\n");
- return false;
- }
- }
-#endif
-
- return true;
-}
-
-static void
-destroyContext(PuglView* view)
-{
-#if defined(PUGL_HAVE_CAIRO) && defined(PUGL_HAVE_GL)
- if (view->ctx_type == PUGL_CAIRO_GL) {
- pugl_cairo_gl_free(&view->impl->cairo_gl);
- }
-#endif
-#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) {
- cairo_destroy(view->impl->cr);
- cairo_surface_destroy(view->impl->surface);
- }
-#endif
-}
-
-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
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- cairo_set_source_rgb(view->impl->cr, 0, 0, 0);
- cairo_paint(view->impl->cr);
- }
-#endif
-}
-
-void
-puglLeaveContext(PuglView* view, bool flush)
-{
-#ifdef PUGL_HAVE_GL
- if (flush && view->ctx_type & PUGL_GL) {
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO_GL) {
- pugl_cairo_gl_draw(&view->impl->cairo_gl, view->width, view->height);
- }
-#endif
-
- glFlush();
- if (view->impl->doubleBuffered) {
- glXSwapBuffers(view->impl->display, view->impl->win);
- }
- }
-
- glXMakeCurrent(view->impl->display, None, NULL);
-#endif
-}
-
-int
-puglCreateWindow(PuglView* view, const char* title)
-{
- PuglInternals* const impl = view->impl;
-
- impl->display = XOpenDisplay(0);
- impl->screen = DefaultScreen(impl->display);
-
- XVisualInfo* const vi = getVisual(view);
- if (!vi) {
- return 1;
- }
-
- Window xParent = view->parent
- ? (Window)view->parent
- : RootWindow(impl->display, impl->screen);
-
- Colormap cmap = XCreateColormap(
- impl->display, xParent, vi->visual, AllocNone);
-
- XSetWindowAttributes attr;
- memset(&attr, 0, sizeof(XSetWindowAttributes));
- attr.colormap = cmap;
- attr.event_mask = (ExposureMask | StructureNotifyMask |
- EnterWindowMask | LeaveWindowMask |
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | FocusChangeMask);
-
- impl->win = XCreateWindow(
- impl->display, xParent,
- 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual,
- CWColormap | CWEventMask, &attr);
-
- if (!createContext(view, vi)) {
- return 2;
- }
-
- XSizeHints sizeHints;
- memset(&sizeHints, 0, sizeof(sizeHints));
- if (!view->resizable) {
- sizeHints.flags = PMinSize|PMaxSize;
- sizeHints.min_width = view->width;
- sizeHints.min_height = view->height;
- sizeHints.max_width = view->width;
- sizeHints.max_height = view->height;
- XSetNormalHints(impl->display, impl->win, &sizeHints);
- } else {
- if (view->min_width || view->min_height) {
- sizeHints.flags = PMinSize;
- sizeHints.min_width = view->min_width;
- sizeHints.min_height = view->min_height;
- }
- if (view->min_aspect_x) {
- sizeHints.flags |= PAspect;
- sizeHints.min_aspect.x = view->min_aspect_x;
- sizeHints.min_aspect.y = view->min_aspect_y;
- sizeHints.max_aspect.x = view->max_aspect_x;
- sizeHints.max_aspect.y = view->max_aspect_y;
- }
-
- XSetNormalHints(impl->display, impl->win, &sizeHints);
- }
-
- if (title) {
- XStoreName(impl->display, impl->win, title);
- }
-
- if (!view->parent) {
- Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True);
- XSetWMProtocols(impl->display, impl->win, &wmDelete, 1);
- }
-
- if (view->transient_parent) {
- XSetTransientForHint(impl->display, impl->win,
- (Window)(view->transient_parent));
- }
-
- XSetLocaleModifiers("");
- if (!(impl->xim = XOpenIM(impl->display, NULL, NULL, NULL))) {
- XSetLocaleModifiers("@im=");
- if (!(impl->xim = XOpenIM(impl->display, NULL, NULL, NULL))) {
- fprintf(stderr, "warning: XOpenIM failed\n");
- }
- }
-
- const XIMStyle im_style = XIMPreeditNothing | XIMStatusNothing;
- if (!(impl->xic = XCreateIC(impl->xim,
- XNInputStyle, im_style,
- XNClientWindow, impl->win,
- XNFocusWindow, impl->win,
- NULL))) {
- fprintf(stderr, "warning: XCreateIC failed\n");
- }
-
- XFree(vi);
-
- return 0;
-}
-
-void
-puglShowWindow(PuglView* view)
-{
- XMapRaised(view->impl->display, view->impl->win);
- view->visible = true;
-}
-
-void
-puglHideWindow(PuglView* view)
-{
- XUnmapWindow(view->impl->display, view->impl->win);
- view->visible = false;
-}
-
-void
-puglDestroy(PuglView* view)
-{
- if (view) {
- destroyContext(view);
- XDestroyWindow(view->impl->display, view->impl->win);
- XCloseDisplay(view->impl->display);
- free(view->windowClass);
- free(view->impl);
- free(view);
- }
-}
-
-static PuglKey
-keySymToSpecial(KeySym sym)
-{
- switch (sym) {
- case XK_F1: return PUGL_KEY_F1;
- case XK_F2: return PUGL_KEY_F2;
- case XK_F3: return PUGL_KEY_F3;
- case XK_F4: return PUGL_KEY_F4;
- case XK_F5: return PUGL_KEY_F5;
- case XK_F6: return PUGL_KEY_F6;
- case XK_F7: return PUGL_KEY_F7;
- case XK_F8: return PUGL_KEY_F8;
- case XK_F9: return PUGL_KEY_F9;
- case XK_F10: return PUGL_KEY_F10;
- case XK_F11: return PUGL_KEY_F11;
- case XK_F12: return PUGL_KEY_F12;
- case XK_Left: return PUGL_KEY_LEFT;
- case XK_Up: return PUGL_KEY_UP;
- case XK_Right: return PUGL_KEY_RIGHT;
- case XK_Down: return PUGL_KEY_DOWN;
- case XK_Page_Up: return PUGL_KEY_PAGE_UP;
- case XK_Page_Down: return PUGL_KEY_PAGE_DOWN;
- case XK_Home: return PUGL_KEY_HOME;
- case XK_End: return PUGL_KEY_END;
- case XK_Insert: return PUGL_KEY_INSERT;
- case XK_Shift_L: return PUGL_KEY_SHIFT;
- case XK_Shift_R: return PUGL_KEY_SHIFT;
- case XK_Control_L: return PUGL_KEY_CTRL;
- case XK_Control_R: return PUGL_KEY_CTRL;
- case XK_Alt_L: return PUGL_KEY_ALT;
- case XK_Alt_R: return PUGL_KEY_ALT;
- case XK_Super_L: return PUGL_KEY_SUPER;
- case XK_Super_R: return PUGL_KEY_SUPER;
- }
- return (PuglKey)0;
-}
-
-static void
-translateKey(PuglView* view, XEvent* xevent, PuglEvent* event)
-{
- KeySym sym = 0;
- char* str = (char*)event->key.utf8;
- memset(str, 0, 8);
- event->key.filter = XFilterEvent(xevent, None);
- if (xevent->type == KeyRelease || event->key.filter || !view->impl->xic) {
- if (XLookupString(&xevent->xkey, str, 7, &sym, NULL) == 1) {
- event->key.character = str[0];
- }
- } else {
- /* TODO: Not sure about this. On my system, some characters work with
- Xutf8LookupString but not with XmbLookupString, and some are the
- opposite. */
- Status status = 0;
-#ifdef X_HAVE_UTF8_STRING
- const int n = Xutf8LookupString(
- view->impl->xic, &xevent->xkey, str, 7, &sym, &status);
-#else
- const int n = XmbLookupString(
- view->impl->xic, &xevent->xkey, str, 7, &sym, &status);
-#endif
- if (n > 0) {
- event->key.character = puglDecodeUTF8((const uint8_t*)str);
- }
- }
- event->key.special = keySymToSpecial(sym);
- event->key.keycode = xevent->xkey.keycode;
-}
-
-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;
-}
-
-static PuglEvent
-translateEvent(PuglView* view, XEvent xevent)
-{
- PuglEvent event;
- memset(&event, 0, sizeof(event));
-
- event.any.view = view;
- if (xevent.xany.send_event) {
- event.any.flags |= PUGL_IS_SEND_EVENT;
- }
-
- switch (xevent.type) {
- case ClientMessage: {
- char* type = XGetAtomName(view->impl->display,
- xevent.xclient.message_type);
- if (!strcmp(type, "WM_PROTOCOLS")) {
- event.type = PUGL_CLOSE;
- }
- break;
- }
- 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.xkey.time;
- event.key.x = xevent.xkey.x;
- event.key.y = xevent.xkey.y;
- event.key.x_root = xevent.xkey.x_root;
- event.key.y_root = xevent.xkey.y_root;
- event.key.state = translateModifiers(xevent.xkey.state);
- translateKey(view, &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;
-
- case FocusIn:
- case FocusOut:
- event.type = ((xevent.type == FocusIn)
- ? PUGL_FOCUS_IN
- : PUGL_FOCUS_OUT);
- event.focus.grab = (xevent.xfocus.mode != NotifyNormal);
- break;
-
- default:
- break;
- }
-
- return event;
-}
-
-void
-puglGrabFocus(PuglView* view)
-{
- XSetInputFocus(
- view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime);
-}
-
-PuglStatus
-puglWaitForEvent(PuglView* view)
-{
- XEvent xevent;
- XPeekEvent(view->impl->display, &xevent);
- return PUGL_SUCCESS;
-}
-
-static void
-merge_draw_events(PuglEvent* dst, const PuglEvent* src)
-{
- if (!dst->type) {
- *dst = *src;
- } else {
- dst->expose.x = MIN(dst->expose.x, src->expose.x);
- dst->expose.y = MIN(dst->expose.y, src->expose.y);
- dst->expose.width = MAX(dst->expose.width, src->expose.width);
- dst->expose.height = MAX(dst->expose.height, src->expose.height);
- }
-}
-
-PuglStatus
-puglProcessEvents(PuglView* view)
-{
- /* Maintain a single expose/configure event to execute after all pending
- events. This avoids redundant drawing/configuration which prevents a
- series of window resizes in the same loop from being laggy. */
- PuglEvent expose_event = { 0 };
- PuglEvent config_event = { 0 };
- XEvent xevent;
- while (XPending(view->impl->display) > 0) {
- XNextEvent(view->impl->display, &xevent);
- if (xevent.type == KeyRelease) {
- // Ignore key repeat if necessary
- 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);
- continue;
- }
- }
- } else if (xevent.type == FocusIn) {
- XSetICFocus(view->impl->xic);
- } else if (xevent.type == FocusOut) {
- XUnsetICFocus(view->impl->xic);
- }
-
- // Translate X11 event to Pugl event
- const PuglEvent event = translateEvent(view, xevent);
-
- if (event.type == PUGL_EXPOSE) {
- // Expand expose event to be dispatched after loop
- merge_draw_events(&expose_event, &event);
- } else if (event.type == PUGL_CONFIGURE) {
- // Expand configure event to be dispatched after loop
- merge_draw_events(&config_event, &event);
- } else {
- // Dispatch event to application immediately
- puglDispatchEvent(view, &event);
- }
- }
-
- if (config_event.type) {
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- // Resize surfaces/contexts before dispatching
- view->redisplay = true;
- cairo_xlib_surface_set_size(view->impl->surface,
- config_event.configure.width,
- config_event.configure.height);
- }
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type == PUGL_CAIRO_GL) {
- view->redisplay = true;
- cairo_surface_destroy(view->impl->surface);
- view->impl->surface = pugl_cairo_gl_create(
- &view->impl->cairo_gl,
- config_event.configure.width,
- config_event.configure.height,
- 4);
- pugl_cairo_gl_configure(&view->impl->cairo_gl,
- config_event.configure.width,
- config_event.configure.height);
- createCairoContext(view);
- }
-#endif
-#endif
- puglDispatchEvent(view, (const PuglEvent*)&config_event);
- }
-
- if (view->redisplay) {
- expose_event.expose.type = PUGL_EXPOSE;
- expose_event.expose.view = view;
- expose_event.expose.x = 0;
- expose_event.expose.y = 0;
- expose_event.expose.width = view->width;
- expose_event.expose.height = view->height;
- view->redisplay = false;
- }
-
- if (expose_event.type) {
- puglDispatchEvent(view, (const PuglEvent*)&expose_event);
- }
-
- return PUGL_SUCCESS;
-}
-
-void
-puglPostRedisplay(PuglView* view)
-{
- view->redisplay = true;
-}
-
-PuglNativeWindow
-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;
-}