aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format17
-rw-r--r--.clang-tidy4
-rw-r--r--.clant.json4
-rw-r--r--README.md6
-rw-r--r--bindings/cpp/include/.clang-tidy2
-rw-r--r--bindings/cpp/include/pugl/cairo.hpp4
-rw-r--r--bindings/cpp/include/pugl/gl.hpp6
-rw-r--r--bindings/cpp/include/pugl/pugl.hpp80
-rw-r--r--bindings/cpp/include/pugl/stub.hpp4
-rw-r--r--bindings/cpp/include/pugl/vulkan.hpp6
-rw-r--r--bindings/cpp/meson.build14
-rw-r--r--bindings/cpp/test/headers/.clang-tidy26
-rw-r--r--bindings/cpp/test/headers/meson.build39
-rw-r--r--bindings/cpp/test/headers/test_headers.cpp20
-rw-r--r--doc/c/Doxyfile.in1
-rw-r--r--doc/c/api/meson.build6
-rw-r--r--doc/c/event-loop.rst5
-rw-r--r--doc/c/meson.build6
-rw-r--r--doc/c/view.rst4
-rw-r--r--doc/c/xml/meson.build4
-rw-r--r--doc/cpp/Doxyfile.in1
-rw-r--r--doc/cpp/api/meson.build2
-rw-r--r--doc/cpp/event-loop.rst5
-rw-r--r--doc/cpp/meson.build6
-rw-r--r--doc/cpp/view.rst4
-rw-r--r--doc/cpp/xml/meson.build4
-rw-r--r--doc/meson.build18
-rw-r--r--examples/.clang-tidy11
-rw-r--r--examples/cube_view.h6
-rw-r--r--examples/demo_utils.h11
-rw-r--r--examples/glad/.clang-format6
-rw-r--r--examples/meson.build40
-rw-r--r--examples/pugl_cairo_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_cairo_demo.c66
-rw-r--r--examples/pugl_clipboard_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_clipboard_demo.c15
-rw-r--r--examples/pugl_cpp_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_cpp_demo.cpp16
-rw-r--r--examples/pugl_cursor_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_cursor_demo.c18
-rw-r--r--examples/pugl_embed_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_embed_demo.c77
-rw-r--r--examples/pugl_management_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_management_demo.c55
-rw-r--r--examples/pugl_print_events.c6
-rw-r--r--examples/pugl_shader_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_shader_demo.c49
-rw-r--r--examples/pugl_vulkan_cpp_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_vulkan_cpp_demo.cpp32
-rw-r--r--examples/pugl_vulkan_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_vulkan_demo.c35
-rw-r--r--examples/pugl_window_demo.app/MacOS/meson.build4
-rw-r--r--examples/pugl_window_demo.c41
-rw-r--r--examples/sybok.hpp8
-rw-r--r--include/pugl/attributes.h19
-rw-r--r--include/pugl/cairo.h7
-rw-r--r--include/pugl/gl.h16
-rw-r--r--include/pugl/pugl.h1019
-rw-r--r--include/pugl/stub.h7
-rw-r--r--include/pugl/vulkan.h25
-rw-r--r--meson.build56
-rw-r--r--meson/suppressions/meson.build5
-rw-r--r--meson_options.txt16
-rw-r--r--src/.clang-tidy3
-rw-r--r--src/common.c114
-rw-r--r--src/internal.c84
-rw-r--r--src/internal.h37
-rw-r--r--src/mac.h2
-rw-r--r--src/mac.m331
-rw-r--r--src/mac_cairo.m2
-rw-r--r--src/mac_gl.m2
-rw-r--r--src/mac_stub.m2
-rw-r--r--src/mac_vulkan.m6
-rw-r--r--src/platform.h8
-rw-r--r--src/stub.h2
-rw-r--r--src/types.h33
-rw-r--r--src/win.c492
-rw-r--r--src/win.h21
-rw-r--r--src/win_cairo.c2
-rw-r--r--src/win_gl.c64
-rw-r--r--src/win_stub.c2
-rw-r--r--src/win_vulkan.c4
-rw-r--r--src/x11.c309
-rw-r--r--src/x11.h8
-rw-r--r--src/x11_cairo.c18
-rw-r--r--src/x11_gl.c10
-rw-r--r--src/x11_stub.c4
-rw-r--r--src/x11_vulkan.c4
-rw-r--r--subprojects/puglutil/include/puglutil/test_utils.h (renamed from test/test_utils.h)7
-rw-r--r--subprojects/puglutil/meson.build14
-rw-r--r--test/.clang-tidy7
-rw-r--r--test/cpp/.clang-tidy39
-rw-r--r--test/cpp/meson.build108
-rw-r--r--test/cpp/test_build.cpp16
-rw-r--r--test/cpp/test_inline_cpp.cpp (renamed from test/test_inline_cpp.cpp)26
-rw-r--r--test/cpp/test_inline_objcpp.mm (renamed from test/test_inline_objcpp.mm)16
-rw-r--r--test/headers/.clang-tidy16
-rw-r--r--test/headers/meson.build36
-rw-r--r--test/headers/test_headers.c22
-rw-r--r--test/meson.build138
-rw-r--r--test/test_build.c16
-rw-r--r--test/test_build.cpp20
-rw-r--r--test/test_cairo.c8
-rw-r--r--test/test_clipboard.c4
-rw-r--r--test/test_cursor.c12
-rw-r--r--test/test_gl.c8
-rw-r--r--test/test_gl_free_unrealized.c20
-rw-r--r--test/test_gl_hints.c15
-rw-r--r--test/test_local_copy_paste.c8
-rw-r--r--test/test_realize.c8
-rw-r--r--test/test_redisplay.c34
-rw-r--r--test/test_remote_copy_paste.c10
-rw-r--r--test/test_show_hide.c8
-rw-r--r--test/test_size.c41
-rw-r--r--test/test_strerror.c2
-rw-r--r--test/test_stub.c8
-rw-r--r--test/test_stub_hints.c15
-rw-r--r--test/test_timer.c10
-rw-r--r--test/test_update.c10
-rw-r--r--test/test_view.c8
-rw-r--r--test/test_vulkan.c8
-rw-r--r--test/test_world.c2
122 files changed, 2013 insertions, 2271 deletions
diff --git a/.clang-format b/.clang-format
index 26ada71..299c8a2 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,10 +1,17 @@
-# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
---
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
-AlignEscapedNewlinesLeft: true
+AlignEscapedNewlines: Left
+AttributeMacros:
+ - PUGL_API
+ - PUGL_CONST_API
+ - PUGL_CONST_FUNC
+ - PUGL_MALLOC_API
+ - PUGL_MALLOC_FUNC
+ - PUGL_WARN_UNUSED_RESULT
BasedOnStyle: Mozilla
BraceWrapping:
AfterNamespace: false
@@ -22,11 +29,5 @@ IndentPPDirectives: AfterHash
KeepEmptyLinesAtTheStartOfBlocks: false
SpacesInContainerLiterals: false
StatementMacros:
- - PUGL_API
- - PUGL_CONST_API
- - PUGL_CONST_FUNC
- - PUGL_DEPRECATED_BY
- PUGL_UNUSED
- - PUGL_WARN_UNUSED_RESULT
- - _Pragma
...
diff --git a/.clang-tidy b/.clang-tidy
index 7f81150..fb84f01 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,4 +1,4 @@
-# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
@@ -11,7 +11,9 @@ Checks: >
-clang-diagnostic-unused-macros,
-llvmlibc-*,
-misc-include-cleaner,
+ -readability-avoid-nested-conditional-operator,
-readability-identifier-length,
+ -readability-implicit-bool-conversion,
CheckOptions:
- key: hicpp-uppercase-literal-suffix.NewSuffixes
value: L;U;f
diff --git a/.clant.json b/.clant.json
index cb178c7..27ce960 100644
--- a/.clant.json
+++ b/.clant.json
@@ -1,9 +1,5 @@
{
"version": "1.0.0",
- "include_dirs": [
- "bindings/cpp/include",
- "include"
- ],
"exclude_patterns": [
"glad\\.c"
],
diff --git a/README.md b/README.md
index f8e9aba..839c52a 100644
--- a/README.md
+++ b/README.md
@@ -39,11 +39,7 @@ Stability
Pugl is currently being developed towards a long-term stable API. For the time
being, however, the API may break occasionally. Please report any relevant
feedback, or file feature requests, so that we can ensure that the released API
-is stable for as long as possible.
-
-When the API changes, backwards compatibility is maintained where possible.
-These compatibility shims will be removed before release, so users are
-encouraged to build with `PUGL_DISABLE_DEPRECATED` defined.
+will be stable for as long as possible.
Documentation
-------------
diff --git a/bindings/cpp/include/.clang-tidy b/bindings/cpp/include/.clang-tidy
index b7cee8e..f31247a 100644
--- a/bindings/cpp/include/.clang-tidy
+++ b/bindings/cpp/include/.clang-tidy
@@ -1,4 +1,4 @@
-# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
diff --git a/bindings/cpp/include/pugl/cairo.hpp b/bindings/cpp/include/pugl/cairo.hpp
index e619412..4a51f96 100644
--- a/bindings/cpp/include/pugl/cairo.hpp
+++ b/bindings/cpp/include/pugl/cairo.hpp
@@ -4,8 +4,8 @@
#ifndef PUGL_CAIRO_HPP
#define PUGL_CAIRO_HPP
-#include "pugl/cairo.h"
-#include "pugl/pugl.h"
+#include <pugl/cairo.h>
+#include <pugl/pugl.h>
namespace pugl {
diff --git a/bindings/cpp/include/pugl/gl.hpp b/bindings/cpp/include/pugl/gl.hpp
index 7c361e6..5aa5ca5 100644
--- a/bindings/cpp/include/pugl/gl.hpp
+++ b/bindings/cpp/include/pugl/gl.hpp
@@ -4,9 +4,9 @@
#ifndef PUGL_GL_HPP
#define PUGL_GL_HPP
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
-#include "pugl/pugl.hpp"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
+#include <pugl/pugl.hpp>
namespace pugl {
diff --git a/bindings/cpp/include/pugl/pugl.hpp b/bindings/cpp/include/pugl/pugl.hpp
index e374efc..eba2583 100644
--- a/bindings/cpp/include/pugl/pugl.hpp
+++ b/bindings/cpp/include/pugl/pugl.hpp
@@ -4,10 +4,10 @@
#ifndef PUGL_PUGL_HPP
#define PUGL_PUGL_HPP
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
-#include <cstddef> // IWYU pragma: keep
-#include <cstdint> // IWYU pragma: keep
+#include <cstddef>
+#include <cstdint>
#if defined(PUGL_HPP_THROW_FAILED_CONSTRUCTION)
# include <exception>
@@ -66,8 +66,17 @@ private:
} // namespace detail
-/// @copydoc PuglRect
-using Rect = PuglRect;
+/// @copydoc PuglCoord
+using Coord = PuglCoord;
+
+/// @copydoc PuglSpan
+using Span = PuglSpan;
+
+/// @copydoc PuglPoint
+using Point = PuglPoint;
+
+/// @copydoc PuglArea
+using Area = PuglArea;
/// @copydoc PuglStringHint
enum class StringHint {
@@ -227,6 +236,7 @@ enum class Status {
setFormatFailed, ///< @copydoc PUGL_SET_FORMAT_FAILED
createContextFailed, ///< @copydoc PUGL_CREATE_CONTEXT_FAILED
unsupported, ///< @copydoc PUGL_UNSUPPORTED
+ noMemory, ///< @copydoc PUGL_NO_MEMORY
};
static_assert(static_cast<Status>(PUGL_UNSUPPORTED) == Status::unsupported, "");
@@ -370,11 +380,19 @@ using Backend = PuglBackend;
/// @copydoc PuglNativeView
using NativeView = PuglNativeView;
+/// @copydoc PuglPositionHint
+enum class PositionHint {
+ defaultPosition, ///< @copydoc PUGL_DEFAULT_POSITION
+ currentPosition, ///< @copydoc PUGL_CURRENT_POSITION
+};
+
/// @copydoc PuglSizeHint
enum class SizeHint {
defaultSize, ///< @copydoc PUGL_DEFAULT_SIZE
+ currentSize, ///< @copydoc PUGL_CURRENT_SIZE
minSize, ///< @copydoc PUGL_MIN_SIZE
maxSize, ///< @copydoc PUGL_MAX_SIZE
+ fixedAspect, ///< @copydoc PUGL_FIXED_ASPECT
minAspect, ///< @copydoc PUGL_MIN_ASPECT
maxAspect, ///< @copydoc PUGL_MAX_ASPECT
};
@@ -535,17 +553,27 @@ public:
@{
*/
- /// @copydoc puglGetFrame
- Rect frame() const noexcept { return puglGetFrame(cobj()); }
+ /// @copydoc puglGetPositionHint
+ Point position(PositionHint hint) const noexcept
+ {
+ return puglGetPositionHint(cobj(), static_cast<PuglPositionHint>(hint));
+ }
+
+ /// @copydoc puglGetSizeHint
+ Area size(SizeHint hint) const noexcept
+ {
+ return puglGetSizeHint(cobj(), static_cast<PuglSizeHint>(hint));
+ }
- /// @copydoc puglSetFrame
- Status setFrame(const Rect& frame) noexcept
+ /// @copydoc puglSetSizeHint
+ Status setSize(unsigned width, unsigned height) noexcept
{
- return static_cast<Status>(puglSetFrame(cobj(), frame));
+ return static_cast<Status>(
+ puglSetSizeHint(cobj(), PUGL_CURRENT_SIZE, width, height));
}
/// @copydoc puglSetSizeHint
- Status setSizeHint(SizeHint hint, PuglSpan width, PuglSpan height) noexcept
+ Status setSizeHint(SizeHint hint, unsigned width, unsigned height) noexcept
{
return static_cast<Status>(
puglSetSizeHint(cobj(), static_cast<PuglSizeHint>(hint), width, height));
@@ -558,18 +586,27 @@ public:
@{
*/
- /// @copydoc puglSetParentWindow
- Status setParentWindow(NativeView parent) noexcept
+ /// @copydoc puglSetParent
+ Status setParent(NativeView parent) noexcept
{
- return static_cast<Status>(puglSetParentWindow(cobj(), parent));
+ return static_cast<Status>(puglSetParent(cobj(), parent));
}
+ /// @copydoc puglGetParent
+ NativeView parent() const noexcept { return puglGetParent(cobj()); }
+
/// @copydoc puglSetTransientParent
Status setTransientParent(NativeView parent) noexcept
{
return static_cast<Status>(puglSetTransientParent(cobj(), parent));
}
+ /// @copydoc puglGetTransientParent
+ NativeView transientParent() const noexcept
+ {
+ return puglGetTransientParent(cobj());
+ }
+
/// @copydoc puglRealize
Status realize() noexcept { return static_cast<Status>(puglRealize(cobj())); }
@@ -600,16 +637,19 @@ public:
/// @copydoc puglGetContext
void* context() noexcept { return puglGetContext(cobj()); }
- /// @copydoc puglPostRedisplay
- Status postRedisplay() noexcept
+ /// @copydoc puglObscure
+ Status obscure() noexcept
{
- return static_cast<Status>(puglPostRedisplay(cobj()));
+ return static_cast<Status>(puglObscureView(cobj()));
}
- /// @copydoc puglPostRedisplayRect
- Status postRedisplayRect(const Rect& rect) noexcept
+ /// "Obscure" a region so it will be exposed in the next render
+ Status obscure(const int x,
+ const int y,
+ const unsigned width,
+ const unsigned height)
{
- return static_cast<Status>(puglPostRedisplayRect(cobj(), rect));
+ return static_cast<Status>(puglObscureRegion(cobj(), x, y, width, height));
}
/**
diff --git a/bindings/cpp/include/pugl/stub.hpp b/bindings/cpp/include/pugl/stub.hpp
index 08281b0..13b050d 100644
--- a/bindings/cpp/include/pugl/stub.hpp
+++ b/bindings/cpp/include/pugl/stub.hpp
@@ -4,8 +4,8 @@
#ifndef PUGL_STUB_HPP
#define PUGL_STUB_HPP
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
namespace pugl {
diff --git a/bindings/cpp/include/pugl/vulkan.hpp b/bindings/cpp/include/pugl/vulkan.hpp
index 5bb790d..56c91b0 100644
--- a/bindings/cpp/include/pugl/vulkan.hpp
+++ b/bindings/cpp/include/pugl/vulkan.hpp
@@ -10,9 +10,9 @@
#ifndef PUGL_VULKAN_HPP
#define PUGL_VULKAN_HPP
-#include "pugl/pugl.h"
-#include "pugl/pugl.hpp"
-#include "pugl/vulkan.h"
+#include <pugl/pugl.h>
+#include <pugl/pugl.hpp>
+#include <pugl/vulkan.h>
#include <vulkan/vulkan_core.h>
diff --git a/bindings/cpp/meson.build b/bindings/cpp/meson.build
index 5d8f586..0e8ba6a 100644
--- a/bindings/cpp/meson.build
+++ b/bindings/cpp/meson.build
@@ -1,10 +1,14 @@
-# Copyright 2021 David Robillard <d@drobilla.net>
+# Copyright 2021-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
+######################################
+# C++ Bindings Package (Header-Only) #
+######################################
+
subdir('include')
puglpp_dep = declare_dependency(
- dependencies: core_deps + [pugl_dep],
+ dependencies: [pugl_dep],
include_directories: include_directories('include'),
link_with: libpugl,
)
@@ -20,3 +24,9 @@ pkg.generate(
)
meson.override_dependency(puglpp_versioned_name, puglpp_dep)
+
+############################
+# C++ Header Warning Tests #
+############################
+
+subdir('test/headers')
diff --git a/bindings/cpp/test/headers/.clang-tidy b/bindings/cpp/test/headers/.clang-tidy
new file mode 100644
index 0000000..0e20b52
--- /dev/null
+++ b/bindings/cpp/test/headers/.clang-tidy
@@ -0,0 +1,26 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ *,
+ -*-magic-numbers,
+ -*-use-using,
+ -altera-*,
+ -cppcoreguidelines-avoid-const-or-ref-data-members,
+ -cppcoreguidelines-pro-bounds-pointer-arithmetic,
+ -cppcoreguidelines-pro-type-reinterpret-cast,
+ -llvmlibc-*,
+ -modernize-redundant-void-arg,
+ -modernize-use-trailing-return-type,
+ -performance-enum-size,
+ -readability-implicit-bool-conversion,
+CheckOptions:
+ - key: readability-function-cognitive-complexity.Threshold
+ value: '2'
+ - key: readability-identifier-length.IgnoredParameterNames
+ value: '^(f)|(id)|(x)|(y)$'
+ - key: readability-identifier-length.IgnoredVariableNames
+ value: '^(r)$'
+FormatStyle: file
+HeaderFilterRegex: '.*'
+WarningsAsErrors: '*'
diff --git a/bindings/cpp/test/headers/meson.build b/bindings/cpp/test/headers/meson.build
new file mode 100644
index 0000000..064c2cf
--- /dev/null
+++ b/bindings/cpp/test/headers/meson.build
@@ -0,0 +1,39 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+header_cpp_suppressions = []
+
+if get_option('warning_level') == 'everything'
+ if cpp.get_id() == 'clang'
+ if not meson.is_cross_build()
+ header_cpp_suppressions += [
+ '-Wno-old-style-cast',
+ '-Wno-poison-system-directories',
+ ]
+ endif
+ endif
+endif
+
+header_cpp_suppressions = cpp.get_supported_arguments(header_cpp_suppressions)
+
+test_headers_cpp_args = header_cpp_suppressions
+test_headers_cpp_args += [
+ '-DPUGL_NO_INCLUDE_GL_H',
+ '-DPUGL_NO_INCLUDE_GLU_H',
+]
+
+if vulkan_dep.found()
+ test_headers_cpp_args += ['-DPUGL_TEST_VULKAN']
+endif
+
+test(
+ 'headers',
+ executable(
+ 'test_headers_cpp',
+ files('test_headers.cpp'),
+ cpp_args: test_headers_cpp_args,
+ dependencies: [puglpp_dep, vulkan_dep],
+ implicit_include_directories: false,
+ ),
+ suite: 'unit',
+)
diff --git a/bindings/cpp/test/headers/test_headers.cpp b/bindings/cpp/test/headers/test_headers.cpp
new file mode 100644
index 0000000..a28f537
--- /dev/null
+++ b/bindings/cpp/test/headers/test_headers.cpp
@@ -0,0 +1,20 @@
+// Copyright 2022-2025 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include <pugl/cairo.hpp> // IWYU pragma: keep
+#include <pugl/gl.hpp> // IWYU pragma: keep
+#include <pugl/pugl.hpp> // IWYU pragma: keep
+#include <pugl/stub.hpp> // IWYU pragma: keep
+
+#ifdef PUGL_TEST_VULKAN
+# include <pugl/vulkan.hpp> // IWYU pragma: keep
+#endif
+
+#ifdef __GNUC__
+__attribute__((const))
+#endif
+int
+main()
+{
+ return 0;
+}
diff --git a/doc/c/Doxyfile.in b/doc/c/Doxyfile.in
index 4bf1b42..f6990af 100644
--- a/doc/c/Doxyfile.in
+++ b/doc/c/Doxyfile.in
@@ -26,7 +26,6 @@ MACRO_EXPANSION = YES
PREDEFINED = PUGL_API \
PUGL_CONST_API= \
PUGL_CONST_FUNC= \
- PUGL_DISABLE_DEPRECATED \
PUGL_MALLOC_API= \
PUGL_MALLOC_FUNC=
diff --git a/doc/c/api/meson.build b/doc/c/api/meson.build
index 6b21aae..846dc94 100644
--- a/doc/c/api/meson.build
+++ b/doc/c/api/meson.build
@@ -1,9 +1,9 @@
-# Copyright 2021 David Robillard <d@drobilla.net>
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
c_pugl_rst = custom_target(
- 'C API ReST Documentation',
- command: [sphinxygen, '-f', '@INPUT0@', 'doc/c/api'],
+ 'c_pugl.rst',
+ command: [sphinxygen, '-f', '@INPUT0@', '@OUTDIR@'],
input: [c_index_xml] + c_rst_files,
output: 'pugl.rst',
)
diff --git a/doc/c/event-loop.rst b/doc/c/event-loop.rst
index be4e315..7bee397 100644
--- a/doc/c/event-loop.rst
+++ b/doc/c/event-loop.rst
@@ -23,12 +23,11 @@ while those that draw continuously may use a significant fraction of the frame p
Redrawing
*********
-Occasional redrawing can be requested by calling :func:`puglPostRedisplay` or :func:`puglPostRedisplayRect`.
+Occasional redrawing can be requested by calling :func:`puglObscureView` or :func:`puglObscureRegion`.
After these are called,
a :struct:`PuglExposeEvent` will be dispatched on the next call to :func:`puglUpdate`.
-For continuous redrawing,
-call :func:`puglPostRedisplay` while handling a :struct:`PuglUpdateEvent` event.
+For continuous redrawing, obscure the view while handling a :struct:`PuglUpdateEvent` event.
This event is sent just before views are redrawn,
so it can be used as a hook to expand the update region right before the view is exposed.
Anything else that needs to be done every frame can be handled similarly.
diff --git a/doc/c/meson.build b/doc/c/meson.build
index 1401aa3..ba14ca9 100644
--- a/doc/c/meson.build
+++ b/doc/c/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 David Robillard <d@drobilla.net>
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
config = configuration_data()
@@ -43,7 +43,7 @@ subdir('xml')
subdir('api')
docs = custom_target(
- 'singlehtml',
+ 'c_singlehtml',
build_by_default: true,
command: [
sphinx_build,
@@ -61,7 +61,7 @@ docs = custom_target(
)
docs = custom_target(
- 'html',
+ 'c_html',
build_by_default: true,
command: [
sphinx_build,
diff --git a/doc/c/view.rst b/doc/c/view.rst
index 31eab21..8c74ca1 100644
--- a/doc/c/view.rst
+++ b/doc/c/view.rst
@@ -50,14 +50,14 @@ Embedding
To embed the view in another window,
you will need to somehow get the :type:`native view handle <PuglNativeView>` for the parent,
-then set it with :func:`puglSetParentWindow`.
+then set it with :func:`puglSetParent`.
If the parent is a Pugl view,
the native handle can be accessed with :func:`puglGetNativeView`.
For example:
.. code-block:: c
- puglSetParentWindow(view, puglGetNativeView(parent));
+ puglSetParent(view, puglGetNativeView(parent));
************************
Setting an Event Handler
diff --git a/doc/c/xml/meson.build b/doc/c/xml/meson.build
index 8b5e0e2..3e371dc 100644
--- a/doc/c/xml/meson.build
+++ b/doc/c/xml/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021 David Robillard <d@drobilla.net>
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
config = configuration_data()
@@ -12,7 +12,7 @@ c_doxyfile = configure_file(
)
c_index_xml = custom_target(
- 'c-index.xml',
+ 'c_index.xml',
command: [doxygen, '@INPUT0@'],
input: [c_doxyfile] + c_headers,
output: 'index.xml',
diff --git a/doc/cpp/Doxyfile.in b/doc/cpp/Doxyfile.in
index 05deae7..3d0d45f 100644
--- a/doc/cpp/Doxyfile.in
+++ b/doc/cpp/Doxyfile.in
@@ -31,7 +31,6 @@ MACRO_EXPANSION = YES
PREDEFINED = PUGL_API \
PUGL_CONST_API= \
PUGL_CONST_FUNC= \
- PUGL_DISABLE_DEPRECATED \
PUGL_MALLOC_API= \
PUGL_MALLOC_FUNC=
diff --git a/doc/cpp/api/meson.build b/doc/cpp/api/meson.build
index 9b2f7e6..7f05f42 100644
--- a/doc/cpp/api/meson.build
+++ b/doc/cpp/api/meson.build
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: 0BSD OR ISC
cpp_pugl_rst = custom_target(
- 'C++ API ReST Documentation',
+ 'cpp_pugl.rst',
command: [sphinxygen, '-l', 'cpp', '-f', '@INPUT@', '@OUTDIR@'],
input: cpp_index_xml,
output: 'pugl.rst',
diff --git a/doc/cpp/event-loop.rst b/doc/cpp/event-loop.rst
index 1d2ac41..3223069 100644
--- a/doc/cpp/event-loop.rst
+++ b/doc/cpp/event-loop.rst
@@ -24,14 +24,13 @@ while those that draw continuously may use a significant fraction of the frame p
Redrawing
*********
-Occasional redrawing can be requested by calling :func:`View::postRedisplay` or :func:`View::postRedisplayRect`.
+Occasional redrawing can be requested by calling :func:`View::obscure`.
After these are called,
a :type:`ExposeEvent` will be dispatched on the next call to :func:`World::update`.
Note, however, that this will not wake up a blocked :func:`World::update` call on MacOS
(which does not handle drawing via events).
-For continuous redrawing,
-call :func:`View::postRedisplay` while handling a :type:`UpdateEvent`.
+For continuous redrawing, obscure the view while handling a :type:`UpdateEvent`.
This event is sent just before views are redrawn,
so it can be used as a hook to expand the update region right before the view is exposed.
Anything else that needs to be done every frame can be handled similarly.
diff --git a/doc/cpp/meson.build b/doc/cpp/meson.build
index ca6bc5b..723510b 100644
--- a/doc/cpp/meson.build
+++ b/doc/cpp/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021 David Robillard <d@drobilla.net>
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
config = configuration_data()
@@ -30,7 +30,7 @@ subdir('xml')
subdir('api')
docs = custom_target(
- 'singlehtml',
+ 'cpp_singlehtml',
build_by_default: true,
command: [
sphinx_build,
@@ -48,7 +48,7 @@ docs = custom_target(
)
docs = custom_target(
- 'html',
+ 'cpp_html',
command: [
sphinx_build,
'-M', 'html',
diff --git a/doc/cpp/view.rst b/doc/cpp/view.rst
index 49940c9..e2fc994 100644
--- a/doc/cpp/view.rst
+++ b/doc/cpp/view.rst
@@ -90,14 +90,14 @@ Embedding
To embed the view in another window,
you will need to somehow get the :type:`native view handle <pugl::NativeView>` for the parent,
-then set it with :func:`View::setParentWindow`.
+then set it with :func:`View::setParent`.
If the parent is a Pugl view,
the native handle can be accessed with :func:`View::nativeView`.
For example:
.. code-block:: cpp
- view.setParentWindow(view, parent.getNativeView());
+ view.setParent(view, parent.nativeView());
*****************
Setting a Backend
diff --git a/doc/cpp/xml/meson.build b/doc/cpp/xml/meson.build
index 72bb8ee..083a6cc 100644
--- a/doc/cpp/xml/meson.build
+++ b/doc/cpp/xml/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021 David Robillard <d@drobilla.net>
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
config = configuration_data()
@@ -12,7 +12,7 @@ cpp_doxyfile = configure_file(
)
cpp_index_xml = custom_target(
- 'cpp-index.xml',
+ 'cpp_index.xml',
command: [doxygen, '@INPUT0@'],
input: [cpp_doxyfile] + c_headers + cpp_headers,
output: 'index.xml',
diff --git a/doc/meson.build b/doc/meson.build
index e7a1763..6368f8a 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -1,19 +1,25 @@
-# Copyright 2021 David Robillard <d@drobilla.net>
+# Copyright 2021-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
docdir = get_option('datadir') / 'doc'
+# Find required external programs
doxygen = find_program('doxygen', required: get_option('docs'))
-sphinxygen = find_program('sphinxygen', required: false)
sphinx_build = find_program('sphinx-build', required: get_option('docs'))
-if not sphinxygen.found()
- subproject('sphinxygen')
- sphinxygen = find_program('sphinxygen', required: get_option('docs'))
+# Find sphinxygen or fall back to subproject
+if doxygen.found() and sphinx_build.found()
+ sphinxygen = find_program('sphinxygen', required: false)
+ if not sphinxygen.found()
+ subproject('sphinxygen')
+ sphinxygen = find_program('sphinxygen', required: get_option('docs'))
+ endif
+else
+ sphinxygen = disabler()
endif
+# Build documentation if all required tools are found
build_docs = doxygen.found() and sphinxygen.found() and sphinx_build.found()
-
if build_docs
subdir('_static')
subdir('c')
diff --git a/examples/.clang-tidy b/examples/.clang-tidy
index 7dde8bb..bc26cde 100644
--- a/examples/.clang-tidy
+++ b/examples/.clang-tidy
@@ -1,4 +1,4 @@
-# Copyright 2020-2023 David Robillard <d@drobilla.net>
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
@@ -6,11 +6,14 @@ Checks: >
-*-non-private-member-variables-in-classes,
-*avoid-c-arrays,
-android-cloexec-fopen,
+ -boost-*,
-bugprone-easily-swappable-parameters,
-bugprone-macro-parentheses,
+ -bugprone-multi-level-implicit-pointer-conversion,
-bugprone-reserved-identifier,
-bugprone-suspicious-string-compare,
-cert-dcl37-c,
+ -cert-dcl50-cpp,
-cert-dcl51-cpp,
-cert-err33-c,
-cert-err34-c,
@@ -26,6 +29,7 @@ Checks: >
-fuchsia-default-arguments,
-fuchsia-default-arguments-calls,
-fuchsia-overloaded-operator,
+ -google-readability-casting,
-google-runtime-references,
-hicpp-multiway-paths-covered,
-hicpp-no-array-decay,
@@ -33,10 +37,15 @@ Checks: >
-hicpp-vararg,
-llvm-header-guard,
-misc-misplaced-const,
+ -modernize-redundant-void-arg,
-modernize-use-trailing-return-type,
+ -modernize-use-using,
+ -performance-enum-size,
+ -performance-enum-size,
-performance-no-int-to-ptr,
-readability-function-cognitive-complexity,
-readability-implicit-bool-conversion,
+ -readability-redundant-member-init,
CheckOptions:
- key: cppcoreguidelines-avoid-do-while.IgnoreMacros
value: true
diff --git a/examples/cube_view.h b/examples/cube_view.h
index 399f625..a02154f 100644
--- a/examples/cube_view.h
+++ b/examples/cube_view.h
@@ -4,12 +4,12 @@
#ifndef EXAMPLES_CUBE_VIEW_H
#define EXAMPLES_CUBE_VIEW_H
-#define GL_SILENCE_DEPRECATION 1 // NOLINT(modernize-macro-to-enum)
+#define GL_SILENCE_DEPRECATION 1 // NOLINT(*-macro-to-enum)
#include "demo_utils.h"
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <stdbool.h>
diff --git a/examples/demo_utils.h b/examples/demo_utils.h
index b43cc2b..db66b21 100644
--- a/examples/demo_utils.h
+++ b/examples/demo_utils.h
@@ -4,7 +4,7 @@
#ifndef EXAMPLES_DEMO_UTILS_H
#define EXAMPLES_DEMO_UTILS_H
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <math.h>
#include <stdio.h>
@@ -95,13 +95,14 @@ puglPrintFps(const PuglWorld* world,
unsigned* const framesDrawn)
{
const double thisTime = puglGetTime(world);
- if (thisTime > printer->lastReportTime + 5) {
- const double fps = *framesDrawn / (thisTime - printer->lastReportTime);
+ if (thisTime > printer->lastReportTime + 5.0) {
+ const double elapsed = (thisTime - printer->lastReportTime);
+ const double fps = *framesDrawn / elapsed;
fprintf(stderr,
- "FPS: %.2f (%u frames in %.0f seconds)\n",
+ "FPS: %.2f (%u frames / %.2f seconds)\n",
fps,
*framesDrawn,
- thisTime - printer->lastReportTime);
+ elapsed);
printer->lastReportTime = thisTime;
*framesDrawn = 0;
diff --git a/examples/glad/.clang-format b/examples/glad/.clang-format
new file mode 100644
index 0000000..f219d75
--- /dev/null
+++ b/examples/glad/.clang-format
@@ -0,0 +1,6 @@
+# Copyright 2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+---
+DisableFormat: true
+...
diff --git a/examples/meson.build b/examples/meson.build
index aa04e80..65daa31 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# Copyright 2021-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
data_dir = get_option('prefix') / get_option('datadir') / 'pugl-0'
@@ -27,12 +27,6 @@ vulkan_examples = [
'pugl_vulkan_demo.c',
]
-includes = include_directories(
- '..',
- '../bindings/cpp/include',
- '../include',
-)
-
# Suppress some additional C warnings in examples
example_c_args = []
if get_option('warning_level') == 'everything'
@@ -61,6 +55,13 @@ if get_option('warning_level') == 'everything' and is_variable('cpp')
'-Wno-old-style-cast',
'-Wno-switch-enum',
]
+ if host_machine.system() == 'windows'
+ example_cpp_args += [
+ '-Wno-deprecated-declarations',
+ '-Wno-format-nonliteral',
+ '-Wno-nonportable-system-include-path',
+ ]
+ endif
elif cpp.get_id() == 'gcc'
example_cpp_args += [
'-Wno-effc++',
@@ -113,7 +114,7 @@ else
foreach example : stub_examples
source = [example]
target = example.split('.')[0]
- dependencies = [pugl_dep, pugl_stub_dep]
+ dependencies = [pugl_dep, pugl_stub_dep, puglutil_dep]
defines = []
executable(
@@ -122,7 +123,7 @@ else
c_args: example_defines + example_c_args + defines,
cpp_args: example_defines + example_cpp_args + defines,
dependencies: dependencies,
- include_directories: includes,
+ implicit_include_directories: false,
)
endforeach
@@ -131,7 +132,7 @@ else
foreach example : gl_examples
source = [example]
target = example.split('.')[0]
- dependencies = [pugl_dep, pugl_gl_dep]
+ dependencies = [pugl_dep, pugl_gl_dep, puglutil_dep]
defines = []
if target == 'pugl_shader_demo'
@@ -141,6 +142,10 @@ else
elif target == 'pugl_print_events'
dependencies += [pugl_stub_dep]
elif target == 'pugl_cpp_demo'
+ if not is_variable('puglpp_dep')
+ continue
+ endif
+
dependencies += [puglpp_dep]
endif
@@ -150,7 +155,7 @@ else
c_args: example_defines + example_c_args + defines,
cpp_args: example_defines + example_cpp_args + defines,
dependencies: dependencies,
- include_directories: includes,
+ implicit_include_directories: false,
)
endforeach
endif
@@ -163,8 +168,8 @@ else
target,
example,
c_args: example_defines + example_c_args + cairo_args,
- dependencies: [pugl_dep, pugl_cairo_dep],
- include_directories: includes,
+ dependencies: [pugl_dep, pugl_cairo_dep, puglutil_dep],
+ implicit_include_directories: false,
)
endforeach
endif
@@ -174,12 +179,17 @@ else
foreach example : vulkan_examples
source = [example]
target = example.split('.')[0]
- dependencies = [dl_dep, pugl_vulkan_dep]
+ dependencies = [dl_dep, pugl_vulkan_dep, puglutil_dep]
defines = []
if target == 'pugl_vulkan_cpp_demo'
+ if not is_variable('puglpp_dep')
+ continue
+ endif
+
source += ['file_utils.c']
defines += ['-D_POSIX_C_SOURCE=200809L']
+ dependencies += [puglpp_dep]
endif
executable(
@@ -188,7 +198,7 @@ else
c_args: example_defines + example_c_args + defines,
cpp_args: example_defines + example_cpp_args + defines,
dependencies: dependencies,
- include_directories: includes,
+ implicit_include_directories: false,
)
endforeach
endif
diff --git a/examples/pugl_cairo_demo.app/MacOS/meson.build b/examples/pugl_cairo_demo.app/MacOS/meson.build
index 18e1fcf..e8a5242 100644
--- a/examples/pugl_cairo_demo.app/MacOS/meson.build
+++ b/examples/pugl_cairo_demo.app/MacOS/meson.build
@@ -6,6 +6,6 @@ executable(
['../../pugl_cairo_demo.c'],
c_args: example_defines + example_c_args + cairo_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [pugl_dep, pugl_cairo_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_cairo_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_cairo_demo.c b/examples/pugl_cairo_demo.c
index 6608bab..109149d 100644
--- a/examples/pugl_cairo_demo.c
+++ b/examples/pugl_cairo_demo.c
@@ -2,10 +2,11 @@
// SPDX-License-Identifier: ISC
#include "demo_utils.h"
-#include "test/test_utils.h"
-#include "pugl/cairo.h"
-#include "pugl/pugl.h"
+#include <puglutil/test_utils.h>
+
+#include <pugl/cairo.h>
+#include <pugl/pugl.h>
#include <cairo.h>
@@ -49,9 +50,9 @@ static const Button buttons[] = {{128, 128, 64, 64, "1"},
static ViewScale
getScale(const PuglView* const view)
{
- const PuglRect frame = puglGetFrame(view);
- const ViewScale scale = {(frame.width - (512.0 / frame.width)) / 512.0,
- (frame.height - (512.0 / frame.height)) / 512.0};
+ const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
+ const ViewScale scale = {(size.width - (512.0 / size.width)) / 512.0,
+ (size.height - (512.0 / size.height)) / 512.0};
return scale;
}
@@ -100,8 +101,8 @@ buttonDraw(PuglTestApp* app, cairo_t* cr, const Button* but, const double time)
cairo_set_font_size(cr, 32.0);
cairo_text_extents(cr, but->label, &extents);
cairo_move_to(cr,
- (but->w / 2.0) - extents.width / 2,
- (but->h / 2.0) + extents.height / 2);
+ (but->w / 2.0) - (extents.width / 2),
+ (but->h / 2.0) + (extents.height / 2));
cairo_set_source_rgba(cr, 0, 0, 0, 1);
cairo_show_text(cr, but->label);
@@ -114,13 +115,12 @@ postButtonRedisplay(PuglView* view)
const ViewScale scale = getScale(view);
for (const Button* b = buttons; b->label; ++b) {
- const double span = sqrt(b->w * b->w + b->h * b->h);
- const PuglRect rect = {(PuglCoord)((b->x - span) * scale.x),
- (PuglCoord)((b->y - span) * scale.y),
- (PuglSpan)ceil(span * 2.0 * scale.x),
- (PuglSpan)ceil(span * 2.0 * scale.y)};
-
- puglPostRedisplayRect(view, rect);
+ const double span = sqrt((b->w * b->w) + (b->h * b->h));
+ puglObscureRegion(view,
+ (int)((b->x - span) * scale.x),
+ (int)((b->y - span) * scale.y),
+ (unsigned)ceil(span * 2.0 * scale.x),
+ (unsigned)ceil(span * 2.0 * scale.y));
}
}
@@ -172,18 +172,17 @@ onClose(PuglView* view)
app->quit = 1;
}
-static PuglRect
-mouseCursorViewBounds(const PuglView* const view,
- const double mouseX,
- const double mouseY)
+static PuglStatus
+obscureMouseCursor(PuglView* const view,
+ const ViewScale scale,
+ const double mouseX,
+ const double mouseY)
{
- const ViewScale scale = getScale(view);
- const PuglRect rect = {(PuglCoord)floor(mouseX - (10.0 * scale.x)),
- (PuglCoord)floor(mouseY - (10.0 * scale.y)),
- (PuglSpan)ceil(20.0 * scale.x),
- (PuglSpan)ceil(20.0 * scale.y)};
-
- return rect;
+ return puglObscureRegion(view,
+ (int)floor(mouseX - (10.0 * scale.x)),
+ (int)floor(mouseY - (10.0 * scale.y)),
+ (unsigned)ceil(20.0 * scale.x),
+ (unsigned)ceil(20.0 * scale.y));
}
static PuglStatus
@@ -193,6 +192,7 @@ onEvent(PuglView* view, const PuglEvent* event)
printEvent(event, "Event: ", app->opts.verbose);
+ const ViewScale scale = getScale(view);
switch (event->type) {
case PUGL_KEY_PRESS:
if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
@@ -209,31 +209,27 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_MOTION:
// Redisplay to clear the old cursor position
- puglPostRedisplayRect(
- view,
- mouseCursorViewBounds(view, app->lastDrawnMouseX, app->lastDrawnMouseY));
+ obscureMouseCursor(view, scale, app->lastDrawnMouseX, app->lastDrawnMouseY);
// Redisplay to show the new cursor position
app->currentMouseX = event->motion.x;
app->currentMouseY = event->motion.y;
- puglPostRedisplayRect(
- view,
- mouseCursorViewBounds(view, app->currentMouseX, app->currentMouseY));
+ obscureMouseCursor(view, scale, app->currentMouseX, app->currentMouseY);
app->lastDrawnMouseX = app->currentMouseX;
app->lastDrawnMouseY = app->currentMouseY;
break;
case PUGL_POINTER_IN:
app->entered = true;
- puglPostRedisplay(view);
+ puglObscureView(view);
break;
case PUGL_POINTER_OUT:
app->entered = false;
- puglPostRedisplay(view);
+ puglObscureView(view);
break;
case PUGL_UPDATE:
if (app->opts.continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
case PUGL_EXPOSE:
diff --git a/examples/pugl_clipboard_demo.app/MacOS/meson.build b/examples/pugl_clipboard_demo.app/MacOS/meson.build
index 31ad2f0..f56ae59 100644
--- a/examples/pugl_clipboard_demo.app/MacOS/meson.build
+++ b/examples/pugl_clipboard_demo.app/MacOS/meson.build
@@ -5,6 +5,6 @@ executable(
'pugl_clipboard_demo',
'../../pugl_clipboard_demo.c',
c_args: example_defines + example_c_args,
- dependencies: [pugl_dep, pugl_gl_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_gl_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_clipboard_demo.c b/examples/pugl_clipboard_demo.c
index efeb1eb..04929ab 100644
--- a/examples/pugl_clipboard_demo.c
+++ b/examples/pugl_clipboard_demo.c
@@ -4,10 +4,11 @@
// A demonstration of using clipboards for copy/paste and drag and drop
#include "cube_view.h"
-#include "test/test_utils.h"
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <puglutil/test_utils.h>
+
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <math.h>
#include <stdbool.h>
@@ -44,8 +45,8 @@ onDisplay(PuglView* view)
if (app->continuous) {
const double dTime = thisTime - cube->lastDrawTime;
- cube->xAngle = fmod(cube->xAngle + dTime * 100.0, 360.0);
- cube->yAngle = fmod(cube->yAngle + dTime * 100.0, 360.0);
+ cube->xAngle = fmod(cube->xAngle + (dTime * 100.0), 360.0);
+ cube->yAngle = fmod(cube->yAngle + (dTime * 100.0), 360.0);
}
displayCube(
@@ -116,7 +117,7 @@ static void
redisplayView(PuglTestApp* app, PuglView* view)
{
if (!app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
}
@@ -135,7 +136,7 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_UPDATE:
if (app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
case PUGL_EXPOSE:
diff --git a/examples/pugl_cpp_demo.app/MacOS/meson.build b/examples/pugl_cpp_demo.app/MacOS/meson.build
index f5ddd67..891dcd9 100644
--- a/examples/pugl_cpp_demo.app/MacOS/meson.build
+++ b/examples/pugl_cpp_demo.app/MacOS/meson.build
@@ -6,6 +6,6 @@ executable(
'../../pugl_cpp_demo.cpp',
c_args: example_defines + example_c_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [puglpp_dep, pugl_gl_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [puglpp_dep, pugl_gl_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_cpp_demo.cpp b/examples/pugl_cpp_demo.cpp
index 2b3c0a1..9ba5723 100644
--- a/examples/pugl_cpp_demo.cpp
+++ b/examples/pugl_cpp_demo.cpp
@@ -3,11 +3,12 @@
#include "cube_view.h"
#include "demo_utils.h"
-#include "test/test_utils.h"
-#include "pugl/gl.hpp"
-#include "pugl/pugl.h"
-#include "pugl/pugl.hpp"
+#include <puglutil/test_utils.h>
+
+#include <pugl/gl.hpp>
+#include <pugl/pugl.h>
+#include <pugl/pugl.hpp>
#include <cmath>
@@ -53,12 +54,13 @@ CubeView::onEvent(const pugl::ConfigureEvent& event) noexcept
pugl::Status
CubeView::onEvent(const pugl::UpdateEvent&) noexcept
{
- // Normally, we would post a redisplay:
- // return postRedisplay();
+ // Normally, we would obscure the view
+ // return obscure();
// But for testing, use sendEvent() instead:
+ const auto currentSize = this->size(pugl::SizeHint::currentSize);
return sendEvent(pugl::ExposeEvent{
- 0U, PuglCoord{0}, PuglCoord{0}, frame().width, frame().height});
+ 0U, PuglCoord{0}, PuglCoord{0}, currentSize.width, currentSize.height});
}
pugl::Status
diff --git a/examples/pugl_cursor_demo.app/MacOS/meson.build b/examples/pugl_cursor_demo.app/MacOS/meson.build
index 94359cd..0836875 100644
--- a/examples/pugl_cursor_demo.app/MacOS/meson.build
+++ b/examples/pugl_cursor_demo.app/MacOS/meson.build
@@ -6,6 +6,6 @@ executable(
'../../pugl_cursor_demo.c',
c_args: example_defines + example_c_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [pugl_dep, pugl_gl_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_gl_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_cursor_demo.c b/examples/pugl_cursor_demo.c
index ba9c54f..6ddd5ad 100644
--- a/examples/pugl_cursor_demo.c
+++ b/examples/pugl_cursor_demo.c
@@ -1,10 +1,10 @@
// Copyright 2012-2020 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-#include "test/test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <stdbool.h>
@@ -19,7 +19,7 @@ typedef struct {
} PuglTestApp;
static void
-onConfigure(const double width, const double height)
+onConfigure(const PuglSpan width, const PuglSpan height)
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
@@ -40,7 +40,7 @@ onExpose(void)
glColor3f(0.6f, 0.6f, 0.6f);
for (int row = 1; row < N_ROWS; ++row) {
- const float y = (float)row * (2.0f / (float)N_ROWS) - 1.0f;
+ const float y = ((float)row * (2.0f / (float)N_ROWS)) - 1.0f;
glBegin(GL_LINES);
glVertex2f(-1.0f, y);
glVertex2f(1.0f, y);
@@ -48,7 +48,7 @@ onExpose(void)
}
for (int col = 1; col < N_COLS; ++col) {
- const float x = (float)col * (2.0f / (float)N_COLS) - 1.0f;
+ const float x = ((float)col * (2.0f / (float)N_COLS)) - 1.0f;
glBegin(GL_LINES);
glVertex2f(x, -1.0f);
glVertex2f(x, 1.0f);
@@ -59,9 +59,9 @@ onExpose(void)
static void
onMotion(PuglView* view, double x, double y)
{
- const PuglRect frame = puglGetFrame(view);
- int row = (int)(y * N_ROWS / frame.height);
- int col = (int)(x * N_COLS / frame.width);
+ const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
+ int row = (int)(y * N_ROWS / size.height);
+ int col = (int)(x * N_COLS / size.width);
row = (row < 0) ? 0 : (row >= N_ROWS) ? (N_ROWS - 1) : row;
col = (col < 0) ? 0 : (col >= N_COLS) ? (N_COLS - 1) : col;
diff --git a/examples/pugl_embed_demo.app/MacOS/meson.build b/examples/pugl_embed_demo.app/MacOS/meson.build
index 9e6dd58..34d4ccb 100644
--- a/examples/pugl_embed_demo.app/MacOS/meson.build
+++ b/examples/pugl_embed_demo.app/MacOS/meson.build
@@ -6,6 +6,6 @@ executable(
'../../pugl_embed_demo.c',
c_args: example_defines + example_c_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [pugl_dep, pugl_gl_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_gl_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c
index a66e032..70e00c2 100644
--- a/examples/pugl_embed_demo.c
+++ b/examples/pugl_embed_demo.c
@@ -3,10 +3,11 @@
#include "cube_view.h"
#include "demo_utils.h"
-#include "test/test_utils.h"
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <puglutil/test_utils.h>
+
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <math.h>
#include <stdbool.h>
@@ -50,18 +51,6 @@ static const float backgroundColorVertices[] = {
// clang-format on
-static PuglRect
-getChildFrame(const PuglRect parentFrame)
-{
- const PuglRect childFrame = {
- borderWidth,
- borderWidth,
- (PuglSpan)(parentFrame.width - 2 * borderWidth),
- (PuglSpan)(parentFrame.height - 2 * borderWidth)};
-
- return childFrame;
-}
-
static void
onDisplay(PuglView* view)
{
@@ -72,8 +61,8 @@ onDisplay(PuglView* view)
const double dTime =
(thisTime - app->lastDrawTime) * (app->reversing ? -1.0 : 1.0);
- app->xAngle = fmod(app->xAngle + dTime * 100.0, 360.0);
- app->yAngle = fmod(app->yAngle + dTime * 100.0, 360.0);
+ app->xAngle = fmod(app->xAngle + (dTime * 100.0), 360.0);
+ app->yAngle = fmod(app->yAngle + (dTime * 100.0), 360.0);
}
displayCube(
@@ -92,40 +81,41 @@ swapFocus(PuglTestApp* app)
}
if (!app->continuous) {
- puglPostRedisplay(app->parent);
- puglPostRedisplay(app->child);
+ puglObscureView(app->parent);
+ puglObscureView(app->child);
}
}
static void
onKeyPress(PuglView* view, const PuglKeyEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- PuglRect frame = puglGetFrame(view);
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
if (event->key == '\t') {
swapFocus(app);
} else if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) {
app->quit = 1;
} else if (event->state & PUGL_MOD_SHIFT) {
+ const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
if (event->key == PUGL_KEY_UP) {
- puglSetSize(view, frame.width, frame.height - 10U);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width, size.height - 10U);
} else if (event->key == PUGL_KEY_DOWN) {
- puglSetSize(view, frame.width, frame.height + 10U);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width, size.height + 10U);
} else if (event->key == PUGL_KEY_LEFT) {
- puglSetSize(view, frame.width - 10U, frame.height);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width - 10U, size.height);
} else if (event->key == PUGL_KEY_RIGHT) {
- puglSetSize(view, frame.width + 10U, frame.height);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width + 10U, size.height);
}
} else {
+ const PuglPoint pos = puglGetPositionHint(view, PUGL_CURRENT_POSITION);
if (event->key == PUGL_KEY_UP) {
- puglSetPosition(view, frame.x, frame.y - 10);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x, pos.y - 10);
} else if (event->key == PUGL_KEY_DOWN) {
- puglSetPosition(view, frame.x, frame.y + 10);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x, pos.y + 10);
} else if (event->key == PUGL_KEY_LEFT) {
- puglSetPosition(view, frame.x - 10, frame.y);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x - 10, pos.y);
} else if (event->key == PUGL_KEY_RIGHT) {
- puglSetPosition(view, frame.x + 10, frame.y);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x + 10, pos.y);
}
}
}
@@ -133,20 +123,21 @@ onKeyPress(PuglView* view, const PuglKeyEvent* event)
static PuglStatus
onParentEvent(PuglView* view, const PuglEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- const PuglRect parentFrame = puglGetFrame(view);
+ PuglTestApp* const app = (PuglTestApp*)puglGetHandle(view);
printEvent(event, "Parent: ", app->verbose);
switch (event->type) {
case PUGL_CONFIGURE:
reshapeCube((float)event->configure.width, (float)event->configure.height);
-
- puglSetFrame(app->child, getChildFrame(parentFrame));
+ puglSetSizeHint(app->child,
+ PUGL_CURRENT_SIZE,
+ event->configure.width - (2U * borderWidth),
+ event->configure.height - (2U * borderWidth));
break;
case PUGL_UPDATE:
if (app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
case PUGL_EXPOSE:
@@ -195,7 +186,7 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_UPDATE:
if (app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
case PUGL_EXPOSE:
@@ -213,14 +204,14 @@ onEvent(PuglView* view, const PuglEvent* event)
app->lastMouseX = event->motion.x;
app->lastMouseY = event->motion.y;
if (!app->continuous) {
- puglPostRedisplay(view);
- puglPostRedisplay(app->parent);
+ puglObscureView(view);
+ puglObscureView(app->parent);
}
break;
case PUGL_SCROLL:
app->dist = fmaxf(10.0f, app->dist + (float)event->scroll.dy);
if (!app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
case PUGL_POINTER_IN:
@@ -261,7 +252,6 @@ main(int argc, char** argv)
puglSetWorldString(app.world, PUGL_CLASS_NAME, "PuglEmbedDemo");
- const PuglRect parentFrame = {0, 0, 512, 512};
puglSetSizeHint(app.parent, PUGL_DEFAULT_SIZE, 512, 512);
puglSetSizeHint(app.parent, PUGL_MIN_SIZE, 192, 192);
puglSetSizeHint(app.parent, PUGL_MAX_SIZE, 1024, 1024);
@@ -288,8 +278,13 @@ main(int argc, char** argv)
return logError("Failed to create parent window (%s)\n", puglStrerror(st));
}
- puglSetFrame(app.child, getChildFrame(parentFrame));
- puglSetParentWindow(app.child, puglGetNativeView(app.parent));
+ puglSetParent(app.child, puglGetNativeView(app.parent));
+ puglSetPositionHint(
+ app.child, PUGL_DEFAULT_POSITION, borderWidth, borderWidth);
+ puglSetSizeHint(app.child,
+ PUGL_DEFAULT_SIZE,
+ 512U - (2U * borderWidth),
+ 512U - (2U * borderWidth));
puglSetViewHint(app.child, PUGL_CONTEXT_DEBUG, opts.errorChecking);
puglSetViewHint(app.child, PUGL_SAMPLES, opts.samples);
diff --git a/examples/pugl_management_demo.app/MacOS/meson.build b/examples/pugl_management_demo.app/MacOS/meson.build
index 69dafc7..308a88c 100644
--- a/examples/pugl_management_demo.app/MacOS/meson.build
+++ b/examples/pugl_management_demo.app/MacOS/meson.build
@@ -6,6 +6,6 @@ executable(
['../../pugl_management_demo.c'],
c_args: example_defines + example_c_args + cairo_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [pugl_dep, pugl_cairo_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_cairo_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_management_demo.c b/examples/pugl_management_demo.c
index 50109a4..c9b3f4a 100644
--- a/examples/pugl_management_demo.c
+++ b/examples/pugl_management_demo.c
@@ -1,14 +1,12 @@
// Copyright 2012-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-/*
- A demonstration of window types, states, and management.
-*/
+// A demonstration of window types, states, and management
-#include "test/test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/cairo.h"
-#include "pugl/pugl.h"
+#include <pugl/cairo.h>
+#include <pugl/pugl.h>
#include <cairo.h>
@@ -37,12 +35,13 @@ onMainEvent(PuglView* view, const PuglEvent* event);
static PuglStatus
onExpose(PuglView* const view, const PuglExposeEvent* const event)
{
- PuglWorld* const world = puglGetWorld(view);
- DemoApp* const app = (DemoApp*)puglGetWorldHandle(world);
- const PuglRect frame = puglGetFrame(view);
+ PuglWorld* const world = puglGetWorld(view);
+ DemoApp* const app = (DemoApp*)puglGetWorldHandle(world);
+ const PuglPoint pos = puglGetPositionHint(view, PUGL_CURRENT_POSITION);
+ const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
const PuglViewStyleFlags style = puglGetViewStyle(view);
- const PuglCoord cx = (PuglCoord)(frame.width / 2U);
- const PuglCoord cy = (PuglCoord)(frame.height / 2U);
+ const PuglCoord cx = (PuglCoord)(size.width / 2U);
+ const PuglCoord cy = (PuglCoord)(size.height / 2U);
cairo_t* const cr = (cairo_t*)puglGetContext(view);
// Clip to expose region
@@ -58,12 +57,34 @@ onExpose(PuglView* const view, const PuglExposeEvent* const event)
char buf[128] = {0};
cairo_text_extents_t extents = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
cairo_set_font_size(cr, 30.0);
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+
+ // Draw position label
+ snprintf(buf, sizeof(buf), "Position: %5d, %5d", pos.x, pos.y);
+ cairo_text_extents(cr, buf, &extents);
+ cairo_move_to(
+ cr, cx - (extents.width / 2.0), cy + (extents.height / 2.0) - 192.0);
+ cairo_show_text(cr, buf);
+
+ // Draw size label
+ snprintf(buf, sizeof(buf), "Size: %5u, %5u", size.width, size.height);
+ cairo_text_extents(cr, buf, &extents);
+ cairo_move_to(
+ cr, cx - (extents.width / 2.0), cy + (extents.height / 2.0) - 144.0);
+ cairo_show_text(cr, buf);
+
+ // Draw scale label
+ snprintf(buf, sizeof(buf), "Scale: %g", puglGetScaleFactor(view));
+ cairo_text_extents(cr, buf, &extents);
+ cairo_move_to(
+ cr, cx - (extents.width / 2.0), cy + (extents.height / 2.0) - 96.0);
+ cairo_show_text(cr, buf);
// Draw time label
snprintf(buf, sizeof(buf), "Draw time: %g", puglGetTime(world));
cairo_text_extents(cr, buf, &extents);
- cairo_move_to(cr, cx - extents.width / 2.0, cy + extents.height / 2.0 - 48.0);
- cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
+ cairo_move_to(
+ cr, cx - (extents.width / 2.0), cy + (extents.height / 2.0) - 48.0);
cairo_show_text(cr, buf);
// Draw style label
@@ -80,8 +101,7 @@ onExpose(PuglView* const view, const PuglExposeEvent* const event)
style & PUGL_VIEW_STYLE_DEMANDING ? " demanding" : "",
style & PUGL_VIEW_STYLE_RESIZING ? " resizing" : "");
cairo_text_extents(cr, buf, &extents);
- cairo_move_to(cr, cx - extents.width / 2.0, cy + extents.height / 2.0);
- cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cairo_move_to(cr, cx - (extents.width / 2.0), cy + (extents.height / 2.0));
cairo_show_text(cr, buf);
if (view == app->mainView.view) {
@@ -89,8 +109,7 @@ onExpose(PuglView* const view, const PuglExposeEvent* const event)
snprintf(buf, sizeof(buf), "Keys: Space T W H M F A B D Q");
cairo_text_extents(cr, buf, &extents);
cairo_move_to(
- cr, cx - extents.width / 2.0, cy + extents.height / 2.0 + 48.0);
- cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ cr, cx - (extents.width / 2.0), cy + (extents.height / 2.0) + 48.0);
cairo_show_text(cr, buf);
}
@@ -185,7 +204,7 @@ onCommonEvent(PuglView* view, const PuglEvent* const event)
}
break;
case PUGL_CONFIGURE:
- return puglPostRedisplay(view);
+ return puglObscureView(view);
case PUGL_EXPOSE:
return onExpose(view, &event->expose);
case PUGL_KEY_PRESS:
diff --git a/examples/pugl_print_events.c b/examples/pugl_print_events.c
index 96a8889..9445e50 100644
--- a/examples/pugl_print_events.c
+++ b/examples/pugl_print_events.c
@@ -1,10 +1,10 @@
// Copyright 2012-2020 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-#include "test/test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <stdbool.h>
#include <stdio.h>
diff --git a/examples/pugl_shader_demo.app/MacOS/meson.build b/examples/pugl_shader_demo.app/MacOS/meson.build
index d3d0755..afcd532 100644
--- a/examples/pugl_shader_demo.app/MacOS/meson.build
+++ b/examples/pugl_shader_demo.app/MacOS/meson.build
@@ -10,6 +10,6 @@ executable(
],
c_args: example_defines + example_c_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [pugl_dep, pugl_gl_dep, dl_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_gl_dep, dl_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_shader_demo.c b/examples/pugl_shader_demo.c
index 9ba3da0..5bef21e 100644
--- a/examples/pugl_shader_demo.c
+++ b/examples/pugl_shader_demo.c
@@ -21,16 +21,19 @@
about 100000 rectangles.
*/
+#define PUGL_NO_INCLUDE_GL_H
+
#include "demo_utils.h"
#include "file_utils.h"
#include "rects.h"
#include "shader_utils.h"
-#include "test/test_utils.h"
#include "glad/glad.h"
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <puglutil/test_utils.h>
+
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <math.h>
#include <stddef.h>
@@ -75,7 +78,7 @@ static void
teardownGl(PuglTestApp* app);
static void
-onConfigure(PuglView* view, double width, double height)
+onConfigure(PuglView* view, PuglSpan width, PuglSpan height)
{
(void)view;
@@ -90,15 +93,15 @@ static void
onExpose(PuglView* view)
{
PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- const PuglRect frame = puglGetFrame(view);
- const float width = (float)frame.width;
- const float height = (float)frame.height;
+ const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
+ const float width = (float)size.width;
+ const float height = (float)size.height;
const double time = puglGetTime(puglGetWorld(view));
// Construct projection matrix for 2D window surface (in pixels)
mat4 proj;
mat4Ortho(
- proj, 0.0f, (float)frame.width, 0.0f, (float)frame.height, -1.0f, 1.0f);
+ proj, 0.0f, (float)size.width, 0.0f, (float)size.height, -1.0f, 1.0f);
// Clear and bind everything that is the same for every rect
glClear(GL_COLOR_BUFFER_BIT);
@@ -108,7 +111,7 @@ onExpose(PuglView* view)
// Update horizontal mouse cursor line (last rect)
Rect* const mouseH = &app->rects[app->numRects];
mouseH->pos[0] = (float)(app->mouseX - 8.0);
- mouseH->pos[1] = (float)(frame.height - app->mouseY - 1.0);
+ mouseH->pos[1] = (float)(size.height - app->mouseY - 1.0);
mouseH->size[0] = 16.0f;
mouseH->size[1] = 2.0f;
mouseH->fillColor[0] = 1.0f;
@@ -119,7 +122,7 @@ onExpose(PuglView* view)
// Update vertical mouse cursor line (second last rect)
Rect* const mouseV = &app->rects[app->numRects + 1];
mouseV->pos[0] = (float)(app->mouseX - 2.0);
- mouseV->pos[1] = (float)(frame.height - app->mouseY - 8.0);
+ mouseV->pos[1] = (float)(size.height - app->mouseY - 8.0);
mouseV->size[0] = 2.0f;
mouseV->size[1] = 16.0f;
mouseV->fillColor[0] = 1.0f;
@@ -168,7 +171,7 @@ onEvent(PuglView* view, const PuglEvent* event)
onConfigure(view, event->configure.width, event->configure.height);
break;
case PUGL_UPDATE:
- puglPostRedisplay(view);
+ puglObscureView(view);
break;
case PUGL_EXPOSE:
onExpose(view);
@@ -195,7 +198,7 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_TIMER:
if (event->timer.id == resizeTimerId) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
default:
@@ -230,10 +233,15 @@ loadShader(const char* const programPath, const char* const name)
free(path);
fseek(file, 0, SEEK_END);
- const size_t fileSize = (size_t)ftell(file);
+ const long filePos = ftell(file);
+ if (filePos <= 0) {
+ fclose(file);
+ return NULL;
+ }
fseek(file, 0, SEEK_SET);
- char* source = (char*)calloc(1, fileSize + 1U);
+ const size_t fileSize = (size_t)filePos;
+ char* source = (char*)calloc(1, fileSize + 1U);
if (fread(source, 1, fileSize, file) != fileSize) {
free(source);
@@ -351,17 +359,16 @@ setupGl(PuglTestApp* app)
char* const fragmentSource =
loadShader(app->programPath, SHADER_DIR "rect.frag");
- if (!vertexSource || !fragmentSource) {
- logError("Failed to load shader sources\n");
- return PUGL_FAILURE;
+ // Compile rectangle shaders and program
+ if (headerSource && vertexSource && fragmentSource) {
+ app->drawRect = compileProgram(headerSource, vertexSource, fragmentSource);
}
- // Compile rectangle shaders and program
- app->drawRect = compileProgram(headerSource, vertexSource, fragmentSource);
free(fragmentSource);
free(vertexSource);
free(headerSource);
if (!app->drawRect.program) {
+ logError("Failed to compile shader program\n");
return PUGL_FAILURE;
}
@@ -470,7 +477,7 @@ updateTimeout(const PuglTestApp* const app)
const double nextExposeTime = nextFrameEndTime - neededTime;
const double timeUntilNext = nextExposeTime - now;
- return timeUntilNext;
+ return fmax(0.0, (timeUntilNext * 0.9) - 0.001);
}
int
@@ -505,7 +512,7 @@ main(int argc, char** argv)
const double startTime = puglGetTime(app.world);
PuglFpsPrinter fpsPrinter = {startTime};
while (!app.quit) {
- puglUpdate(app.world, fmax(0.0, updateTimeout(&app)));
+ puglUpdate(app.world, updateTimeout(&app));
puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
}
diff --git a/examples/pugl_vulkan_cpp_demo.app/MacOS/meson.build b/examples/pugl_vulkan_cpp_demo.app/MacOS/meson.build
index d75c75d..7e7556b 100644
--- a/examples/pugl_vulkan_cpp_demo.app/MacOS/meson.build
+++ b/examples/pugl_vulkan_cpp_demo.app/MacOS/meson.build
@@ -9,6 +9,6 @@ executable(
],
c_args: example_defines + example_c_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [puglpp_dep, pugl_vulkan_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [puglpp_dep, pugl_vulkan_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_vulkan_cpp_demo.cpp b/examples/pugl_vulkan_cpp_demo.cpp
index 5e30b88..4a73157 100644
--- a/examples/pugl_vulkan_cpp_demo.cpp
+++ b/examples/pugl_vulkan_cpp_demo.cpp
@@ -17,13 +17,14 @@
#include "demo_utils.h"
#include "file_utils.h"
#include "rects.h"
-#include "test/test_utils.h"
#include "sybok.hpp"
-#include "pugl/pugl.h"
-#include "pugl/pugl.hpp"
-#include "pugl/vulkan.hpp"
+#include <puglutil/test_utils.h>
+
+#include <pugl/pugl.h>
+#include <pugl/pugl.hpp>
+#include <pugl/vulkan.hpp>
#include <vulkan/vk_platform.h>
@@ -559,7 +560,7 @@ Swapchain::init(const sk::VulkanApi& vk,
const auto minNumImages =
(!capabilities.maxImageCount || capabilities.maxImageCount >= 3U)
- ? 3U
+ ? std::max(capabilities.minImageCount, 3U)
: capabilities.maxImageCount;
const VkSwapchainCreateInfoKHR swapchainCreateInfo{
@@ -576,7 +577,7 @@ Swapchain::init(const sk::VulkanApi& vk,
VK_SHARING_MODE_EXCLUSIVE,
SK_COUNTED(0, nullptr),
capabilities.currentTransform,
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
mode == RenderMode::resizing ? gpu.resizePresentMode : gpu.presentMode,
VK_TRUE,
oldSwapchain};
@@ -715,7 +716,12 @@ readFile(const char* const programPath, const std::string& filename)
}
fseek(file.get(), 0, SEEK_END);
- const auto fileSize = static_cast<size_t>(ftell(file.get()));
+ const auto filePos = ftell(file.get());
+ if (filePos <= 0) {
+ return {};
+ }
+
+ const auto fileSize = static_cast<size_t>(filePos);
fseek(file.get(), 0, SEEK_SET);
const auto numWords = fileSize / sizeof(uint32_t);
@@ -1512,11 +1518,9 @@ pugl::Status
View::onEvent(const pugl::ConfigureEvent& event)
{
// We just record the size here and lazily resize the surface when exposed
- _app.extent = {static_cast<uint32_t>(event.width),
- static_cast<uint32_t>(event.height)};
-
- _app.mode = (event.style & PUGL_VIEW_STYLE_RESIZING) ? RenderMode::resizing
- : RenderMode::normal;
+ _app.extent = {event.width, event.height};
+ _app.mode = (event.style & PUGL_VIEW_STYLE_RESIZING) ? RenderMode::resizing
+ : RenderMode::normal;
return pugl::Status::success;
}
@@ -1524,7 +1528,7 @@ View::onEvent(const pugl::ConfigureEvent& event)
pugl::Status
View::onEvent(const pugl::UpdateEvent&)
{
- return postRedisplay();
+ return obscure();
}
VkResult
@@ -1710,7 +1714,7 @@ View::onEvent(const pugl::LoopEnterEvent&)
pugl::Status
View::onEvent(const pugl::TimerEvent&)
{
- return postRedisplay();
+ return obscure();
}
pugl::Status
diff --git a/examples/pugl_vulkan_demo.app/MacOS/meson.build b/examples/pugl_vulkan_demo.app/MacOS/meson.build
index 0d07171..0f7f4bf 100644
--- a/examples/pugl_vulkan_demo.app/MacOS/meson.build
+++ b/examples/pugl_vulkan_demo.app/MacOS/meson.build
@@ -8,6 +8,6 @@ executable(
'../../file_utils.c',
],
c_args: example_defines + example_c_args,
- dependencies: [pugl_dep, pugl_vulkan_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_vulkan_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_vulkan_demo.c b/examples/pugl_vulkan_demo.c
index 2f9eaff..75083c4 100644
--- a/examples/pugl_vulkan_demo.c
+++ b/examples/pugl_vulkan_demo.c
@@ -10,10 +10,11 @@
*/
#include "demo_utils.h"
-#include "test/test_utils.h"
-#include "pugl/pugl.h"
-#include "pugl/vulkan.h"
+#include <puglutil/test_utils.h>
+
+#include <pugl/pugl.h>
+#include <pugl/vulkan.h>
#include <vulkan/vk_platform.h>
#include <vulkan/vulkan_core.h>
@@ -83,8 +84,8 @@ typedef struct {
PuglView* view;
VulkanState vk;
uint32_t framesDrawn;
- uint32_t width;
- uint32_t height;
+ PuglSpan width;
+ PuglSpan height;
bool quit;
} VulkanApp;
@@ -569,8 +570,8 @@ configureSurface(VulkanState* const vk)
static VkResult
createRawSwapchain(VulkanState* const vk,
- const uint32_t width,
- const uint32_t height)
+ const PuglSpan width,
+ const PuglSpan height)
{
VkSurfaceCapabilitiesKHR surfaceCapabilities;
VkResult vr = VK_SUCCESS;
@@ -583,12 +584,12 @@ createRawSwapchain(VulkanState* const vk,
/* There is a known race condition with window/surface sizes, so we clamp
to what Vulkan reports and hope for the best. */
- vk->swapchain->extent.width = CLAMP(width,
+ vk->swapchain->extent.width = CLAMP((uint32_t)width,
surfaceCapabilities.minImageExtent.width,
surfaceCapabilities.maxImageExtent.width);
vk->swapchain->extent.height =
- CLAMP(height,
+ CLAMP((uint32_t)height,
surfaceCapabilities.minImageExtent.height,
surfaceCapabilities.maxImageExtent.height);
@@ -707,8 +708,8 @@ recordCommandBuffers(VulkanState* const vk)
static VkResult
createSwapchain(VulkanState* const vk,
- const uint32_t width,
- const uint32_t height)
+ const PuglSpan width,
+ const PuglSpan height)
{
VkResult vr = VK_SUCCESS;
@@ -895,21 +896,21 @@ destroyWorld(VulkanApp* const app)
}
static PuglStatus
-onConfigure(PuglView* const view, const double width, const double height)
+onConfigure(PuglView* const view, const PuglSpan width, const PuglSpan height)
{
VulkanApp* const app = (VulkanApp*)puglGetHandle(view);
// We just record the size here and lazily resize the surface when exposed
- app->width = (uint32_t)width;
- app->height = (uint32_t)height;
+ app->width = width;
+ app->height = height;
return PUGL_SUCCESS;
}
static PuglStatus
recreateSwapchain(VulkanState* const vk,
- const uint32_t width,
- const uint32_t height)
+ const PuglSpan width,
+ const PuglSpan height)
{
vkDeviceWaitIdle(vk->device);
destroySwapchain(vk, vk->swapchain);
@@ -1009,7 +1010,7 @@ onEvent(PuglView* const view, const PuglEvent* const e)
switch (e->type) {
case PUGL_UPDATE:
- return app->opts.continuous ? puglPostRedisplay(view) : PUGL_SUCCESS;
+ return app->opts.continuous ? puglObscureView(view) : PUGL_SUCCESS;
case PUGL_EXPOSE:
return onExpose(view);
case PUGL_CONFIGURE:
diff --git a/examples/pugl_window_demo.app/MacOS/meson.build b/examples/pugl_window_demo.app/MacOS/meson.build
index 7bfc219..f2623f2 100644
--- a/examples/pugl_window_demo.app/MacOS/meson.build
+++ b/examples/pugl_window_demo.app/MacOS/meson.build
@@ -6,6 +6,6 @@ executable(
'../../pugl_window_demo.c',
c_args: example_defines + example_c_args,
cpp_args: example_defines + example_cpp_args,
- dependencies: [pugl_dep, pugl_gl_dep],
- include_directories: include_directories('../../..'),
+ dependencies: [pugl_dep, pugl_gl_dep, puglutil_dep],
+ implicit_include_directories: false,
)
diff --git a/examples/pugl_window_demo.c b/examples/pugl_window_demo.c
index 67086bb..867f856 100644
--- a/examples/pugl_window_demo.c
+++ b/examples/pugl_window_demo.c
@@ -7,10 +7,11 @@
#include "cube_view.h"
#include "demo_utils.h"
-#include "test/test_utils.h"
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <puglutil/test_utils.h>
+
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <math.h>
#include <stdbool.h>
@@ -49,8 +50,8 @@ onDisplay(PuglView* view)
if (app->continuous) {
const double dTime = thisTime - cube->lastDrawTime;
- cube->xAngle = fmod(cube->xAngle + dTime * 100.0, 360.0);
- cube->yAngle = fmod(cube->yAngle + dTime * 100.0, 360.0);
+ cube->xAngle = fmod(cube->xAngle + (dTime * 100.0), 360.0);
+ cube->yAngle = fmod(cube->yAngle + (dTime * 100.0), 360.0);
}
displayCube(
@@ -64,29 +65,30 @@ onKeyPress(PuglView* view, const PuglKeyEvent* event)
{
PuglWorld* world = puglGetWorld(view);
PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
- PuglRect frame = puglGetFrame(view);
if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) {
app->quit = 1;
} else if (event->state & PUGL_MOD_SHIFT) {
+ const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
if (event->key == PUGL_KEY_UP) {
- puglSetSize(view, frame.width, frame.height - 10U);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width, size.height - 10U);
} else if (event->key == PUGL_KEY_DOWN) {
- puglSetSize(view, frame.width, frame.height + 10U);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width, size.height + 10U);
} else if (event->key == PUGL_KEY_LEFT) {
- puglSetSize(view, frame.width - 10U, frame.height);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width - 10U, size.height);
} else if (event->key == PUGL_KEY_RIGHT) {
- puglSetSize(view, frame.width + 10U, frame.height);
+ puglSetSizeHint(view, PUGL_CURRENT_SIZE, size.width + 10U, size.height);
}
} else {
+ const PuglPoint pos = puglGetPositionHint(view, PUGL_CURRENT_POSITION);
if (event->key == PUGL_KEY_UP) {
- puglSetPosition(view, frame.x, frame.y - 10);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x, pos.y - 10);
} else if (event->key == PUGL_KEY_DOWN) {
- puglSetPosition(view, frame.x, frame.y + 10);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x, pos.y + 10);
} else if (event->key == PUGL_KEY_LEFT) {
- puglSetPosition(view, frame.x - 10, frame.y);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x - 10, pos.y);
} else if (event->key == PUGL_KEY_RIGHT) {
- puglSetPosition(view, frame.x + 10, frame.y);
+ puglSetPositionHint(view, PUGL_CURRENT_POSITION, pos.x + 10, pos.y);
}
}
}
@@ -95,7 +97,7 @@ static void
redisplayView(PuglTestApp* app, PuglView* view)
{
if (!app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
}
@@ -115,7 +117,7 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_UPDATE:
if (app->continuous) {
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
case PUGL_EXPOSE:
@@ -186,9 +188,10 @@ main(int argc, char** argv)
cube->dist = 10;
puglSetViewString(view, PUGL_WINDOW_TITLE, "Pugl Window Demo");
- puglSetPosition(view,
- (PuglCoord)(pad + (128U + pad) * i),
- (PuglCoord)(pad + (128U + pad) * i));
+ puglSetPositionHint(view,
+ PUGL_DEFAULT_POSITION,
+ (PuglCoord)(pad + ((128U + pad) * i)),
+ (PuglCoord)(pad + ((128U + pad) * i)));
puglSetSizeHint(view, PUGL_DEFAULT_SIZE, 512, 512);
puglSetSizeHint(view, PUGL_MIN_SIZE, 128, 128);
diff --git a/examples/sybok.hpp b/examples/sybok.hpp
index 49abdf0..db0cdd5 100644
--- a/examples/sybok.hpp
+++ b/examples/sybok.hpp
@@ -1751,10 +1751,10 @@ public:
private:
template<class T>
- static inline VkResult wrapResult(const VkResult r,
- const typename T::Handle handle,
- typename T::Deleter&& deleter,
- T& result) noexcept
+ static VkResult wrapResult(const VkResult r,
+ const typename T::Handle handle,
+ typename T::Deleter&& deleter,
+ T& result) noexcept
{
if (r) {
return r;
diff --git a/include/pugl/attributes.h b/include/pugl/attributes.h
index 75322ee..1e2264c 100644
--- a/include/pugl/attributes.h
+++ b/include/pugl/attributes.h
@@ -26,17 +26,6 @@
# endif
#endif
-// Deprecated API
-#ifndef PUGL_DISABLE_DEPRECATED
-# if defined(__clang__)
-# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("", rep)))
-# elif defined(__GNUC__)
-# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("Use " rep)))
-# else
-# define PUGL_DEPRECATED_BY(rep)
-# endif
-#endif
-
// GCC function attributes
#if defined(__GNUC__)
# define PUGL_CONST_FUNC __attribute__((const))
@@ -47,13 +36,9 @@
#endif
/// A const function in the public API that only reads parameters
-#define PUGL_CONST_API \
- PUGL_API \
- PUGL_CONST_FUNC
+#define PUGL_CONST_API PUGL_API PUGL_CONST_FUNC
/// A malloc function in the public API that returns allocated memory
-#define PUGL_MALLOC_API \
- PUGL_API \
- PUGL_MALLOC_FUNC
+#define PUGL_MALLOC_API PUGL_API PUGL_MALLOC_FUNC
#endif // PUGL_ATTRIBUTES_H
diff --git a/include/pugl/cairo.h b/include/pugl/cairo.h
index fda1191..8a5ae4e 100644
--- a/include/pugl/cairo.h
+++ b/include/pugl/cairo.h
@@ -4,8 +4,8 @@
#ifndef PUGL_CAIRO_H
#define PUGL_CAIRO_H
-#include "pugl/attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/attributes.h>
+#include <pugl/pugl.h>
PUGL_BEGIN_DECLS
@@ -21,8 +21,7 @@ PUGL_BEGIN_DECLS
Pass the returned value to puglSetBackend() to draw to a view with Cairo.
*/
-PUGL_CONST_API
-const PuglBackend*
+PUGL_CONST_API const PuglBackend*
puglCairoBackend(void);
/**
diff --git a/include/pugl/gl.h b/include/pugl/gl.h
index ac7c557..f4d5f3d 100644
--- a/include/pugl/gl.h
+++ b/include/pugl/gl.h
@@ -4,8 +4,8 @@
#ifndef PUGL_GL_H
#define PUGL_GL_H
-#include "pugl/attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/attributes.h>
+#include <pugl/pugl.h>
// IWYU pragma: begin_exports
@@ -42,8 +42,7 @@ typedef void (*PuglGlFunc)(void);
/**
Return the address of an OpenGL extension function.
*/
-PUGL_API
-PuglGlFunc
+PUGL_API PuglGlFunc
puglGetProcAddress(const char* name);
/**
@@ -53,8 +52,7 @@ puglGetProcAddress(const char* name);
doing things like loading textures. Note that this must not be used for
drawing, which may only be done while processing an expose event.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglEnterContext(PuglView* view);
/**
@@ -62,8 +60,7 @@ puglEnterContext(PuglView* view);
This must only be called after puglEnterContext().
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglLeaveContext(PuglView* view);
/**
@@ -71,8 +68,7 @@ puglLeaveContext(PuglView* view);
Pass the returned value to puglSetBackend() to draw to a view with OpenGL.
*/
-PUGL_CONST_API
-const PuglBackend*
+PUGL_CONST_API const PuglBackend*
puglGlBackend(void);
PUGL_END_DECLS
diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h
index 2d7f4b4..5ba5a46 100644
--- a/include/pugl/pugl.h
+++ b/include/pugl/pugl.h
@@ -4,7 +4,7 @@
#ifndef PUGL_PUGL_H
#define PUGL_PUGL_H
-#include "pugl/attributes.h"
+#include <pugl/attributes.h>
#include <stddef.h>
#include <stdint.h>
@@ -46,22 +46,17 @@ typedef int16_t PuglCoord;
*/
typedef uint16_t PuglSpan;
-/**
- A rectangle in a view or on the screen.
-
- This type is used to describe two things: the position and size of a view
- (for configuring), or a rectangle within a view (for exposing).
-
- The coordinate (0, 0) represents the top-left pixel of the parent window (or
- display if there isn't one), or the top-left pixel of the view,
- respectively.
-*/
+/// A 2-dimensional position within/of a view
typedef struct {
PuglCoord x;
PuglCoord y;
- PuglSpan width;
- PuglSpan height;
-} PuglRect;
+} PuglPoint;
+
+/// A 2-dimensional size within/of a view
+typedef struct {
+ PuglSpan width;
+ PuglSpan height;
+} PuglArea;
/// A string property for configuration
typedef enum {
@@ -298,9 +293,9 @@ typedef PuglAnyEvent PuglCloseEvent;
This event is sent to every view near the end of a main loop iteration when
any pending exposures are about to be redrawn. It is typically used to mark
- regions to expose with puglPostRedisplay() or puglPostRedisplayRect(). For
- example, to continuously animate, a view calls puglPostRedisplay() when an
- update event is received, and it will then shortly receive an expose event.
+ regions to expose with puglObscureView() or puglObscureRegion(). For
+ example, to continuously animate, obscure the view when an update event is
+ received, and it will receive an expose event shortly afterwards.
*/
typedef PuglAnyEvent PuglUpdateEvent;
@@ -341,76 +336,77 @@ typedef struct {
mapping used here is arbitrary and specific to Pugl.
*/
typedef enum {
- PUGL_KEY_BACKSPACE = 0x00000008U, ///< Backspace
- PUGL_KEY_TAB = 0x00000009U, ///< Tab
- PUGL_KEY_ENTER = 0x0000000DU, ///< Enter
- PUGL_KEY_ESCAPE = 0x0000001BU, ///< Escape
- PUGL_KEY_DELETE = 0x0000007FU, ///< Delete
- PUGL_KEY_SPACE = 0x00000020U, ///< Space
- PUGL_KEY_F1 = 0x0000E000U, ///< F1
- PUGL_KEY_F2, ///< F2
- PUGL_KEY_F3, ///< F3
- PUGL_KEY_F4, ///< F4
- PUGL_KEY_F5, ///< F5
- PUGL_KEY_F6, ///< F6
- PUGL_KEY_F7, ///< F7
- PUGL_KEY_F8, ///< F8
- PUGL_KEY_F9, ///< F9
- PUGL_KEY_F10, ///< F10
- PUGL_KEY_F11, ///< F11
- PUGL_KEY_F12, ///< F12
- PUGL_KEY_PAGE_UP = 0xE031, ///< Page Up
- PUGL_KEY_PAGE_DOWN, ///< Page Down
- PUGL_KEY_END, ///< End
- PUGL_KEY_HOME, ///< Home
- PUGL_KEY_LEFT, ///< Left
- PUGL_KEY_UP, ///< Up
- PUGL_KEY_RIGHT, ///< Right
- PUGL_KEY_DOWN, ///< Down
- PUGL_KEY_PRINT_SCREEN = 0xE041U, ///< Print Screen
- PUGL_KEY_INSERT, ///< Insert
- PUGL_KEY_PAUSE, ///< Pause/Break
- PUGL_KEY_MENU, ///< Menu
- PUGL_KEY_NUM_LOCK, ///< Num Lock
- PUGL_KEY_SCROLL_LOCK, ///< Scroll Lock
- PUGL_KEY_CAPS_LOCK, ///< Caps Lock
- PUGL_KEY_SHIFT_L = 0xE051U, ///< Left Shift
- PUGL_KEY_SHIFT_R, ///< Right Shift
- PUGL_KEY_CTRL_L, ///< Left Control
- PUGL_KEY_CTRL_R, ///< Right Control
- PUGL_KEY_ALT_L, ///< Left Alt
- PUGL_KEY_ALT_R, ///< Right Alt / AltGr
- PUGL_KEY_SUPER_L, ///< Left Super
- PUGL_KEY_SUPER_R, ///< Right Super
- PUGL_KEY_PAD_0 = 0xE060U, ///< Keypad 0
- PUGL_KEY_PAD_1, ///< Keypad 1
- PUGL_KEY_PAD_2, ///< Keypad 2
- PUGL_KEY_PAD_3, ///< Keypad 3
- PUGL_KEY_PAD_4, ///< Keypad 4
- PUGL_KEY_PAD_5, ///< Keypad 5
- PUGL_KEY_PAD_6, ///< Keypad 6
- PUGL_KEY_PAD_7, ///< Keypad 7
- PUGL_KEY_PAD_8, ///< Keypad 8
- PUGL_KEY_PAD_9, ///< Keypad 9
- PUGL_KEY_PAD_ENTER, ///< Keypad Enter
- PUGL_KEY_PAD_PAGE_UP = 0xE071U, ///< Keypad Page Up
- PUGL_KEY_PAD_PAGE_DOWN, ///< Keypad Page Down
- PUGL_KEY_PAD_END, ///< Keypad End
- PUGL_KEY_PAD_HOME, ///< Keypad Home
- PUGL_KEY_PAD_LEFT, ///< Keypad Left
- PUGL_KEY_PAD_UP, ///< Keypad Up
- PUGL_KEY_PAD_RIGHT, ///< Keypad Right
- PUGL_KEY_PAD_DOWN, ///< Keypad Down
- PUGL_KEY_PAD_CLEAR = 0xE09DU, ///< Keypad Clear/Begin
- PUGL_KEY_PAD_INSERT, ///< Keypad Insert
- PUGL_KEY_PAD_DELETE, ///< Keypad Delete
- PUGL_KEY_PAD_EQUAL, ///< Keypad Equal
- PUGL_KEY_PAD_MULTIPLY = 0xE0AAU, ///< Keypad Multiply
- PUGL_KEY_PAD_ADD, ///< Keypad Add
- PUGL_KEY_PAD_SEPARATOR, ///< Keypad Separator
- PUGL_KEY_PAD_SUBTRACT, ///< Keypad Subtract
- PUGL_KEY_PAD_DECIMAL, ///< Keypad Decimal
- PUGL_KEY_PAD_DIVIDE, ///< Keypad Divide
+ PUGL_KEY_NONE = 0U, ///< Sentinel value for no key
+ PUGL_KEY_BACKSPACE = 0x0008U, ///< Backspace
+ PUGL_KEY_TAB = 0x0009U, ///< Tab
+ PUGL_KEY_ENTER = 0x000DU, ///< Enter
+ PUGL_KEY_ESCAPE = 0x001BU, ///< Escape
+ PUGL_KEY_DELETE = 0x007FU, ///< Delete
+ PUGL_KEY_SPACE = 0x0020U, ///< Space
+ PUGL_KEY_F1 = 0xE000U, ///< F1
+ PUGL_KEY_F2 = 0xE001U, ///< F2
+ PUGL_KEY_F3 = 0xE002U, ///< F3
+ PUGL_KEY_F4 = 0xE003U, ///< F4
+ PUGL_KEY_F5 = 0xE004U, ///< F5
+ PUGL_KEY_F6 = 0xE005U, ///< F6
+ PUGL_KEY_F7 = 0xE006U, ///< F7
+ PUGL_KEY_F8 = 0xE007U, ///< F8
+ PUGL_KEY_F9 = 0xE008U, ///< F9
+ PUGL_KEY_F10 = 0xE009U, ///< F10
+ PUGL_KEY_F11 = 0xE010U, ///< F11
+ PUGL_KEY_F12 = 0xE011U, ///< F12
+ PUGL_KEY_PAGE_UP = 0xE031U, ///< Page Up
+ PUGL_KEY_PAGE_DOWN = 0xE032U, ///< Page Down
+ PUGL_KEY_END = 0xE033U, ///< End
+ PUGL_KEY_HOME = 0xE034U, ///< Home
+ PUGL_KEY_LEFT = 0xE035U, ///< Left
+ PUGL_KEY_UP = 0xE036U, ///< Up
+ PUGL_KEY_RIGHT = 0xE037U, ///< Right
+ PUGL_KEY_DOWN = 0xE038U, ///< Down
+ PUGL_KEY_PRINT_SCREEN = 0xE041U, ///< Print Screen
+ PUGL_KEY_INSERT = 0xE042U, ///< Insert
+ PUGL_KEY_PAUSE = 0xE043U, ///< Pause/Break
+ PUGL_KEY_MENU = 0xE044U, ///< Menu
+ PUGL_KEY_NUM_LOCK = 0xE045U, ///< Num Lock
+ PUGL_KEY_SCROLL_LOCK = 0xE046U, ///< Scroll Lock
+ PUGL_KEY_CAPS_LOCK = 0xE047U, ///< Caps Lock
+ PUGL_KEY_SHIFT_L = 0xE051U, ///< Left Shift
+ PUGL_KEY_SHIFT_R = 0xE052U, ///< Right Shift
+ PUGL_KEY_CTRL_L = 0xE053U, ///< Left Control
+ PUGL_KEY_CTRL_R = 0xE054U, ///< Right Control
+ PUGL_KEY_ALT_L = 0xE055U, ///< Left Alt
+ PUGL_KEY_ALT_R = 0xE056U, ///< Right Alt / AltGr
+ PUGL_KEY_SUPER_L = 0xE057U, ///< Left Super
+ PUGL_KEY_SUPER_R = 0xE058U, ///< Right Super
+ PUGL_KEY_PAD_0 = 0xE060U, ///< Keypad 0
+ PUGL_KEY_PAD_1 = 0xE061U, ///< Keypad 1
+ PUGL_KEY_PAD_2 = 0xE062U, ///< Keypad 2
+ PUGL_KEY_PAD_3 = 0xE063U, ///< Keypad 3
+ PUGL_KEY_PAD_4 = 0xE064U, ///< Keypad 4
+ PUGL_KEY_PAD_5 = 0xE065U, ///< Keypad 5
+ PUGL_KEY_PAD_6 = 0xE066U, ///< Keypad 6
+ PUGL_KEY_PAD_7 = 0xE067U, ///< Keypad 7
+ PUGL_KEY_PAD_8 = 0xE068U, ///< Keypad 8
+ PUGL_KEY_PAD_9 = 0xE069U, ///< Keypad 9
+ PUGL_KEY_PAD_ENTER = 0xE070U, ///< Keypad Enter
+ PUGL_KEY_PAD_PAGE_UP = 0xE071U, ///< Keypad Page Up
+ PUGL_KEY_PAD_PAGE_DOWN = 0xE072U, ///< Keypad Page Down
+ PUGL_KEY_PAD_END = 0xE073U, ///< Keypad End
+ PUGL_KEY_PAD_HOME = 0xE074U, ///< Keypad Home
+ PUGL_KEY_PAD_LEFT = 0xE075U, ///< Keypad Left
+ PUGL_KEY_PAD_UP = 0xE076U, ///< Keypad Up
+ PUGL_KEY_PAD_RIGHT = 0xE077U, ///< Keypad Right
+ PUGL_KEY_PAD_DOWN = 0xE078U, ///< Keypad Down
+ PUGL_KEY_PAD_CLEAR = 0xE09DU, ///< Keypad Clear/Begin
+ PUGL_KEY_PAD_INSERT = 0xE09EU, ///< Keypad Insert
+ PUGL_KEY_PAD_DELETE = 0xE09FU, ///< Keypad Delete
+ PUGL_KEY_PAD_EQUAL = 0xE0A0U, ///< Keypad Equal
+ PUGL_KEY_PAD_MULTIPLY = 0xE0AAU, ///< Keypad Multiply
+ PUGL_KEY_PAD_ADD = 0xE0ABU, ///< Keypad Add
+ PUGL_KEY_PAD_SEPARATOR = 0xE0ACU, ///< Keypad Separator
+ PUGL_KEY_PAD_SUBTRACT = 0xE0ADU, ///< Keypad Subtract
+ PUGL_KEY_PAD_DECIMAL = 0xE0AEU, ///< Keypad Decimal
+ PUGL_KEY_PAD_DIVIDE = 0xE0AFU, ///< Keypad Divide
} PuglKey;
/// Keyboard modifier flags
@@ -443,8 +439,8 @@ typedef struct {
Key press or release event.
This event represents low-level key presses and releases. This can be used
- for "direct" keyboard handing like key bindings, but must not be interpreted
- as text input.
+ for "direct" keyboard handling like key bindings, but must not be
+ interpreted as text input.
Keys are represented portably as Unicode code points, using the "natural"
code point for the key where possible (see #PuglKey for details). The `key`
@@ -733,8 +729,7 @@ typedef enum {
} PuglStatus;
/// Return a string describing a status code
-PUGL_CONST_API
-const char*
+PUGL_CONST_API const char*
puglStrerror(PuglStatus status);
/**
@@ -790,13 +785,11 @@ typedef uint32_t PuglWorldFlags;
@param flags Flags to control world features.
@return A new world, which must be later freed with puglFreeWorld().
*/
-PUGL_MALLOC_API
-PuglWorld*
+PUGL_MALLOC_API PuglWorld*
puglNewWorld(PuglWorldType type, PuglWorldFlags flags);
/// Free a world allocated with puglNewWorld()
-PUGL_API
-void
+PUGL_API void
puglFreeWorld(PuglWorld* world);
/**
@@ -807,13 +800,11 @@ puglFreeWorld(PuglWorld* world);
The handle is opaque to Pugl and is not interpreted in any way.
*/
-PUGL_API
-void
+PUGL_API void
puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle);
/// Get the user data for the world
-PUGL_API
-PuglWorldHandle
+PUGL_API PuglWorldHandle
puglGetWorldHandle(PuglWorld* world);
/**
@@ -825,8 +816,7 @@ puglGetWorldHandle(PuglWorld* world);
Windows: Returns the `HMODULE` of the calling process.
*/
-PUGL_API
-void*
+PUGL_API void*
puglGetNativeWorld(PuglWorld* world);
/**
@@ -835,8 +825,7 @@ puglGetNativeWorld(PuglWorld* world);
The string value only needs to be valid for the duration of this call, it
will be copied if necessary.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetWorldString(PuglWorld* world, PuglStringHint key, const char* value);
/**
@@ -845,8 +834,7 @@ puglSetWorldString(PuglWorld* world, PuglStringHint key, const char* value);
The returned string should be accessed immediately, or copied. It may
become invalid upon any call to any function that manipulates the same view.
*/
-PUGL_API
-const char*
+PUGL_API const char*
puglGetWorldString(const PuglWorld* world, PuglStringHint key);
/**
@@ -856,8 +844,7 @@ puglGetWorldString(const PuglWorld* world, PuglStringHint key);
time is only useful to compare against other times returned by this
function, its absolute value has no meaning.
*/
-PUGL_API
-double
+PUGL_API double
puglGetTime(const PuglWorld* world);
/**
@@ -882,8 +869,7 @@ puglGetTime(const PuglWorld* world);
@return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if no events are
read, or an error.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglUpdate(PuglWorld* world, double timeout);
/**
@@ -959,9 +945,9 @@ typedef enum {
/// A special view hint value
typedef enum {
- PUGL_DONT_CARE = -1, ///< Generic trinary: Use best default
- PUGL_FALSE = 0, ///< Generic trinary: Explicitly false
- PUGL_TRUE = 1, ///< Generic trinary: Explicitly true
+ PUGL_DONT_CARE = -1, ///< Generic trinary: unset
+ PUGL_FALSE = 0, ///< Generic trinary: false
+ PUGL_TRUE = 1, ///< Generic trinary: true
PUGL_OPENGL_API = 2, ///< For #PUGL_CONTEXT_API
PUGL_OPENGL_ES_API = 3, ///< For #PUGL_CONTEXT_API
PUGL_OPENGL_CORE_PROFILE = 4, ///< For #PUGL_CONTEXT_PROFILE
@@ -976,6 +962,49 @@ typedef enum {
} PuglViewType;
/**
+ A hint for configuring/constraining the position of a view.
+
+ The system will attempt to make the view's window adhere to these, but they
+ are suggestions, not hard constraints. Applications should handle any view
+ position gracefully.
+
+ An unset position has `INT16_MIN` (-32768) for both `x` and `y`. In
+ practice, set positions should be between -16000 and 16000 for portability.
+ Usually, the origin is the top left of the display, although negative
+ coordinates are possible, particularly on multi-display system.
+*/
+typedef enum {
+ /**
+ Default position.
+
+ This is used as the position during window creation as a default, if no
+ other position is specified. It isn't necessary to set a default position
+ (unlike the default size, which is required). If not even a default
+ position is set, then the window will be created at an arbitrary position.
+ This position is a best-effort attempt to do the most reasonable thing for
+ the initial display of the window, for example, by centering. Note that
+ it is implementation-defined, subject to change, platform-specific, and
+ for embedded views, may no longer make sense if the parent's size is
+ adjusted. Code that wants to make assumptions about the initial position
+ must set the default to a specific valid one, such as `{0, 0}`.
+ */
+ PUGL_DEFAULT_POSITION,
+
+ /**
+ Current position.
+
+ This reflects the current position of the view, which may be different from
+ the default position if the view has been moved by the user, window
+ manager, or for any other reason. Typically, it overrides the
+ default position.
+ */
+ PUGL_CURRENT_POSITION,
+} PuglPositionHint;
+
+/// The number of #PuglPositionHint values
+#define PUGL_NUM_POSITION_HINTS ((unsigned)PUGL_CURRENT_POSITION + 1U)
+
+/**
A hint for configuring/constraining the size of a view.
The system will attempt to make the view's window adhere to these, but they
@@ -992,6 +1021,15 @@ typedef enum {
PUGL_DEFAULT_SIZE,
/**
+ Current size.
+
+ This reflects the current size of the view, which may be different from
+ the default size if the view is resizable. Typically, it overrides the
+ default size.
+ */
+ PUGL_CURRENT_SIZE,
+
+ /**
Minimum size.
If set, the view's size should be constrained to be at least this large.
@@ -1049,18 +1087,15 @@ typedef PuglStatus (*PuglEventFunc)(PuglView* view, const PuglEvent* event);
It must first be configured, then the system view can be created with
puglRealize().
*/
-PUGL_MALLOC_API
-PuglView*
+PUGL_MALLOC_API PuglView*
puglNewView(PuglWorld* world);
/// Free a view created with puglNewView()
-PUGL_API
-void
+PUGL_API void
puglFreeView(PuglView* view);
/// Return the world that `view` is a part of
-PUGL_API
-PuglWorld*
+PUGL_API PuglWorld*
puglGetWorld(PuglView* view);
/**
@@ -1072,13 +1107,11 @@ puglGetWorld(PuglView* view);
The handle is opaque to Pugl and is not interpreted in any way.
*/
-PUGL_API
-void
+PUGL_API void
puglSetHandle(PuglView* view, PuglHandle handle);
/// Get the user data for a view
-PUGL_API
-PuglHandle
+PUGL_API PuglHandle
puglGetHandle(PuglView* view);
/**
@@ -1098,18 +1131,15 @@ puglGetHandle(PuglView* view);
applications must link against the appropriate backend library, or be sure
to compile in the appropriate code if using a local copy of Pugl.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetBackend(PuglView* view, const PuglBackend* backend);
/// Return the graphics backend used by a view
-PUGL_API
-const PuglBackend*
+PUGL_API const PuglBackend*
puglGetBackend(const PuglView* view);
/// Set the function to call when an event occurs
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
/**
@@ -1117,8 +1147,7 @@ puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
This only has an effect when called before puglRealize().
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetViewHint(PuglView* view, PuglViewHint hint, int value);
/**
@@ -1128,8 +1157,7 @@ puglSetViewHint(PuglView* view, PuglViewHint hint, int value);
hint which was initially set to PUGL_DONT_CARE, or has been adjusted from
the suggested value.
*/
-PUGL_API
-int
+PUGL_API int
puglGetViewHint(const PuglView* view, PuglViewHint hint);
/**
@@ -1139,8 +1167,7 @@ puglGetViewHint(const PuglView* view, PuglViewHint hint);
string value only needs to be valid for the duration of this call, it will
be copied if necessary.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetViewString(PuglView* view, PuglStringHint key, const char* value);
/**
@@ -1149,8 +1176,7 @@ puglSetViewString(PuglView* view, PuglStringHint key, const char* value);
The returned string should be accessed immediately, or copied. It may
become invalid upon any call to any function that manipulates the same view.
*/
-PUGL_API
-const char*
+PUGL_API const char*
puglGetViewString(const PuglView* view, PuglStringHint key);
/**
@@ -1165,8 +1191,7 @@ puglGetViewString(const PuglView* view, PuglStringHint key);
that is reasonably sized on a 96 DPI display, and the scale 2.0 should have
text twice that large.
*/
-PUGL_API
-double
+PUGL_API double
puglGetScaleFactor(const PuglView* view);
/**
@@ -1177,64 +1202,56 @@ puglGetScaleFactor(const PuglView* view);
*/
/**
- Get the current position and size of the view.
+ Get a position hint for the view.
- The position is in screen coordinates with an upper left origin.
+ This can be used to get the default or current position of a view, in screen
+ coordinates with an upper left origin.
*/
-PUGL_API
-PuglRect
-puglGetFrame(const PuglView* view);
+PUGL_API PuglPoint
+puglGetPositionHint(const PuglView* view, PuglPositionHint hint);
/**
- Set the current position and size of the view.
-
- The position is in screen coordinates with an upper left origin.
+ Set a position hint for the view.
- @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is
- unchanged.
-*/
-PUGL_API
-PuglStatus
-puglSetFrame(PuglView* view, PuglRect frame);
+ This can be used to set the default or current position of a view.
-/**
- Set the current position of the view.
+ This should be called before puglRealize() so the initial window for the
+ view can be configured correctly. It may also be used dynamically after the
+ window is realized, for some hints.
- @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is
- unchanged.
+ @return An error code on failure, but always succeeds if the view is not yet
+ realized.
*/
-PUGL_API
-PuglStatus
-puglSetPosition(PuglView* view, int x, int y);
+PUGL_API PuglStatus
+puglSetPositionHint(PuglView* view, PuglPositionHint hint, int x, int y);
/**
- Set the current size of the view.
+ Get a size hint for the view.
- @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is
- unchanged.
+ This can be used to get the default, current, minimum, and maximum size of a
+ view, as well as the supported range of aspect ratios.
*/
-PUGL_API
-PuglStatus
-puglSetSize(PuglView* view, unsigned width, unsigned height);
+PUGL_API PuglArea
+puglGetSizeHint(const PuglView* view, PuglSizeHint hint);
/**
Set a size hint for the view.
- This can be used to set the default, minimum, and maximum size of a view,
- as well as the supported range of aspect ratios.
+ This can be used to set the default, current, minimum, and maximum size of a
+ view, as well as the supported range of aspect ratios.
This should be called before puglRealize() so the initial window for the
- view can be configured correctly.
+ view can be configured correctly. It may also be used dynamically after the
+ window is realized, for some hints.
- @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
- not yet realized.
+ @return An error code on failure, but always succeeds if the view is not yet
+ realized.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetSizeHint(PuglView* view,
PuglSizeHint hint,
- PuglSpan width,
- PuglSpan height);
+ unsigned width,
+ unsigned height);
/**
@}
@@ -1244,18 +1261,16 @@ puglSetSizeHint(PuglView* view,
*/
/**
- Set the parent window for embedding a view in an existing window.
+ Set the parent for embedding a view in an existing window.
This must be called before puglRealize(), reparenting is not supported.
*/
-PUGL_API
-PuglStatus
-puglSetParentWindow(PuglView* view, PuglNativeView parent);
+PUGL_API PuglStatus
+puglSetParent(PuglView* view, PuglNativeView parent);
/// Return the parent window this view is embedded in, or null
-PUGL_API
-PuglNativeView
-puglGetParentWindow(const PuglView* view);
+PUGL_API PuglNativeView
+puglGetParent(const PuglView* view);
/**
Set the transient parent of the window.
@@ -1267,8 +1282,7 @@ puglGetParentWindow(const PuglView* view);
A view can either have a parent (for embedding) or a transient parent (for
top-level windows like dialogs), but not both.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetTransientParent(PuglView* view, PuglNativeView parent);
/**
@@ -1277,8 +1291,7 @@ puglSetTransientParent(PuglView* view, PuglNativeView parent);
@return The native handle to the window this view is a transient child of,
or null.
*/
-PUGL_API
-PuglNativeView
+PUGL_API PuglNativeView
puglGetTransientParent(const PuglView* view);
/**
@@ -1290,8 +1303,7 @@ puglGetTransientParent(const PuglView* view);
The view should be fully configured using the above functions before this is
called. This function may only be called once per view.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglRealize(PuglView* view);
/**
@@ -1300,8 +1312,7 @@ puglRealize(PuglView* view);
This is the inverse of puglRealize(). After this call, the view no longer
corresponds to a real system view, and can be realized again later.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglUnrealize(PuglView* view);
/// A command to control the behaviour of puglShow()
@@ -1345,13 +1356,11 @@ typedef enum {
If the view is currently hidden, it will be shown and possibly raised to the
top depending on the platform.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglShow(PuglView* view, PuglShowCommand command);
/// Hide the current window
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglHide(PuglView* view);
/**
@@ -1364,8 +1373,7 @@ puglHide(PuglView* view);
used to determine if the state has actually been set. Any changes to the
actual state of the view will arrive in later configure events.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetViewStyle(PuglView* view, PuglViewStyleFlags flags);
/**
@@ -1374,18 +1382,15 @@ puglSetViewStyle(PuglView* view, PuglViewStyleFlags flags);
The result is determined based on the state announced in the last configure
event.
*/
-PUGL_API
-PuglViewStyleFlags
+PUGL_API PuglViewStyleFlags
puglGetViewStyle(const PuglView* view);
/// Return true iff the view is currently visible
-PUGL_API
-bool
+PUGL_API bool
puglGetVisible(const PuglView* view);
/// Return the native window handle
-PUGL_API
-PuglNativeView
+PUGL_API PuglNativeView
puglGetNativeView(PuglView* view);
/**
@@ -1406,8 +1411,7 @@ puglGetNativeView(PuglView* view);
All other backends: returns null.
*/
-PUGL_API
-void*
+PUGL_API void*
puglGetContext(PuglView* view);
/**
@@ -1419,19 +1423,32 @@ puglGetContext(PuglView* view);
platforms. If called elsewhere, an expose will be enqueued to be processed
in the next event loop iteration.
*/
-PUGL_API
-PuglStatus
-puglPostRedisplay(PuglView* view);
+PUGL_API PuglStatus
+puglObscureView(PuglView* view);
/**
- Request a redisplay of the given rectangle within the view.
+ "Obscure" a region so it will be exposed in the next render.
+
+ This will cause an expose event to be dispatched later. If called from
+ within the event handler, the expose should arrive at the end of the current
+ event loop iteration, though this is not strictly guaranteed on all
+ platforms. If called elsewhere, an expose will be enqueued to be processed
+ in the next event loop iteration.
+
+ The region is clamped to the size of the view if necessary.
- This has the same semantics as puglPostRedisplay(), but allows giving a
- precise region for redrawing only a portion of the view.
+ @param view The view to expose later.
+ @param x The top-left X coordinate of the rectangle to obscure.
+ @param y The top-left Y coordinate of the rectangle to obscure.
+ @param width The width of the rectangle to obscure.
+ @param height The height coordinate of the rectangle to obscure.
*/
-PUGL_API
-PuglStatus
-puglPostRedisplayRect(PuglView* view, PuglRect rect);
+PUGL_API PuglStatus
+puglObscureRegion(PuglView* view,
+ int x,
+ int y,
+ unsigned width,
+ unsigned height);
/**
@}
@@ -1470,13 +1487,11 @@ typedef enum {
@return #PUGL_SUCCESS if the focus was successfully grabbed, or an error.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglGrabFocus(PuglView* view);
/// Return whether `view` has the keyboard input focus
-PUGL_API
-bool
+PUGL_API bool
puglHasFocus(const PuglView* view);
/**
@@ -1484,8 +1499,7 @@ puglHasFocus(const PuglView* view);
A #PUGL_DATA_OFFER event will be sent if data is available.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglPaste(PuglView* view);
/**
@@ -1493,8 +1507,7 @@ puglPaste(PuglView* view);
Returns zero if the clipboard is empty.
*/
-PUGL_API
-uint32_t
+PUGL_API uint32_t
puglGetNumClipboardTypes(const PuglView* view);
/**
@@ -1506,8 +1519,7 @@ puglGetNumClipboardTypes(const PuglView* view);
Returns null if `typeIndex` is out of bounds according to
puglGetNumClipboardTypes().
*/
-PUGL_API
-const char*
+PUGL_API const char*
puglGetClipboardType(const PuglView* view, uint32_t typeIndex);
/**
@@ -1526,8 +1538,7 @@ puglGetClipboardType(const PuglView* view, uint32_t typeIndex);
the `typeIndex` argument to the call of puglGetClipboardType() that returned
the accepted type.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglAcceptOffer(PuglView* view,
const PuglDataOfferEvent* offer,
uint32_t typeIndex);
@@ -1543,8 +1554,7 @@ puglAcceptOffer(PuglView* view,
@param data The data to copy to the clipboard.
@param len The length of data in bytes (including terminator if necessary).
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetClipboard(PuglView* view,
const char* type,
const void* data,
@@ -1561,8 +1571,7 @@ puglSetClipboard(PuglView* view,
@param[out] len Set to the length of the data in bytes.
@return The clipboard contents, or null.
*/
-PUGL_API
-const void*
+PUGL_API const void*
puglGetClipboard(PuglView* view, uint32_t typeIndex, size_t* len);
/**
@@ -1573,10 +1582,10 @@ puglGetClipboard(PuglView* view, uint32_t typeIndex, size_t* len);
for example if compiled on X11 without Xcursor support.
@return #PUGL_BAD_PARAMETER if the given cursor is invalid,
- #PUGL_FAILURE if the cursor is known but loading it system fails.
+ #PUGL_UNSUPPORTED if setting the cursor is not supported on this system, or
+ another error if the cursor is known but loading it fails.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSetCursor(PuglView* view, PuglCursor cursor);
/**
@@ -1605,8 +1614,7 @@ puglSetCursor(PuglView* view, PuglCursor cursor);
@return #PUGL_FAILURE if timers are not supported by the system,
#PUGL_UNKNOWN_ERROR if setting the timer failed.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglStartTimer(PuglView* view, uintptr_t id, double timeout);
/**
@@ -1618,8 +1626,7 @@ puglStartTimer(PuglView* view, uintptr_t id, double timeout);
@return #PUGL_FAILURE if timers are not supported by this system,
#PUGL_UNKNOWN_ERROR if stopping the timer failed.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglStopTimer(PuglView* view, uintptr_t id);
/**
@@ -1632,553 +1639,17 @@ puglStopTimer(PuglView* view, uintptr_t id);
Currently, only #PUGL_CLIENT events are supported on all platforms.
X11: A #PUGL_EXPOSE event can be sent, which is similar to calling
- puglPostRedisplayRect(), but will always send a message to the X server,
- even when called in an event handler.
+ puglObscureRegion(), but will always send a message to the X server, even
+ when called in an event handler.
@return #PUGL_UNSUPPORTED if sending events of this type is not supported,
#PUGL_UNKNOWN_ERROR if sending the event failed.
*/
-PUGL_API
-PuglStatus
+PUGL_API PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event);
/**
@}
-*/
-
-#ifndef PUGL_DISABLE_DEPRECATED
-
-/**
- @}
- @defgroup pugl_deprecated Deprecated API
- @{
-*/
-
-PUGL_DEPRECATED_BY("PuglRealizeEvent")
-typedef PuglRealizeEvent PuglCreateEvent;
-
-PUGL_DEPRECATED_BY("PuglUnrealizeEvent")
-typedef PuglUnrealizeEvent PuglDestroyEvent;
-
-PUGL_DEPRECATED_BY("PuglRealizeEvent")
-typedef PuglRealizeEvent PuglEventCreate;
-
-PUGL_DEPRECATED_BY("PuglUnrealizeEvent")
-typedef PuglUnrealizeEvent PuglEventDestroy;
-
-PUGL_DEPRECATED_BY("PuglConfigureEvent")
-typedef PuglConfigureEvent PuglEventConfigure;
-
-PUGL_DEPRECATED_BY("PuglUpdateEvent")
-typedef PuglUpdateEvent PuglEventUpdate;
-
-PUGL_DEPRECATED_BY("PuglExposeEvent")
-typedef PuglExposeEvent PuglEventExpose;
-
-PUGL_DEPRECATED_BY("PuglCloseEvent")
-typedef PuglCloseEvent PuglEventClose;
-
-PUGL_DEPRECATED_BY("PuglFocusEvent")
-typedef PuglFocusEvent PuglEventFocus;
-
-PUGL_DEPRECATED_BY("PuglKeyEvent")
-typedef PuglKeyEvent PuglEventKey;
-
-PUGL_DEPRECATED_BY("PuglTextEvent")
-typedef PuglTextEvent PuglEventText;
-
-PUGL_DEPRECATED_BY("PuglCrossingEvent")
-typedef PuglCrossingEvent PuglEventCrossing;
-
-PUGL_DEPRECATED_BY("PuglButtonEvent")
-typedef PuglButtonEvent PuglEventButton;
-
-PUGL_DEPRECATED_BY("PuglMotionEvent")
-typedef PuglMotionEvent PuglEventMotion;
-
-PUGL_DEPRECATED_BY("PuglScrollEvent")
-typedef PuglScrollEvent PuglEventScroll;
-
-PUGL_DEPRECATED_BY("PuglClientEvent")
-typedef PuglClientEvent PuglEventClient;
-
-PUGL_DEPRECATED_BY("PuglTimerEvent")
-typedef PuglTimerEvent PuglEventTimer;
-
-PUGL_DEPRECATED_BY("PuglLoopEnterEvent")
-typedef PuglLoopEnterEvent PuglEventLoopEnter;
-
-PUGL_DEPRECATED_BY("PuglLoopLeaveEvent")
-typedef PuglLoopLeaveEvent PuglEventLoopLeave;
-
-/**
- A native window handle.
-
- X11: This is a `Window`.
-
- MacOS: This is a pointer to an `NSView*`.
-
- Windows: This is a `HWND`.
-*/
-PUGL_DEPRECATED_BY("PuglNativeView")
-typedef uintptr_t PuglNativeWindow;
-
-/**
- Create a Pugl application and view.
-
- To create a window, call the various puglInit* functions as necessary, then
- call puglRealize().
-
- @deprecated Use puglNewApp() and puglNewView().
-
- @param pargc Pointer to argument count (currently unused).
- @param argv Arguments (currently unused).
- @return A newly created view.
-*/
-static inline PUGL_DEPRECATED_BY("puglNewView")
-PuglView*
-puglInit(const int* pargc, char** argv)
-{
- (void)pargc;
- (void)argv;
-
- return puglNewView(puglNewWorld(PUGL_MODULE, 0));
-}
-
-/**
- Destroy an app and view created with `puglInit()`.
-
- @deprecated Use puglFreeApp() and puglFreeView().
-*/
-static inline PUGL_DEPRECATED_BY("puglFreeView")
-void
-puglDestroy(PuglView* view)
-{
- PuglWorld* const world = puglGetWorld(view);
-
- puglFreeView(view);
- puglFreeWorld(world);
-}
-
-/**
- Set the class name of the application.
-
- This is a stable identifier for the application, used as the window
- class/instance name on X11 and Windows. It is not displayed to the user,
- but can be used in scripts and by window managers, so it should be the same
- for every instance of the application, but different from other
- applications.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetWorldString")
-PuglStatus
-puglSetClassName(PuglWorld* world, const char* name)
-{
- return puglSetWorldString(world, PUGL_CLASS_NAME, name);
-}
-
-/// Get the class name of the application, or null
-static inline PUGL_DEPRECATED_BY("puglGetWorldString")
-const char*
-puglGetClassName(const PuglWorld* world)
-{
- return puglGetWorldString(world, PUGL_CLASS_NAME);
-}
-
-/**
- Set the window class name before creating a window.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetClassName")
-void
-puglInitWindowClass(PuglView* view, const char* name)
-{
- puglSetWorldString(puglGetWorld(view), PUGL_CLASS_NAME, name);
-}
-
-/**
- Set the window size before creating a window.
-
- @deprecated Use puglSetFrame().
-*/
-static inline PUGL_DEPRECATED_BY("puglSetFrame")
-void
-puglInitWindowSize(PuglView* view, int width, int height)
-{
- PuglRect frame = puglGetFrame(view);
-
- frame.width = (PuglSpan)width;
- frame.height = (PuglSpan)height;
-
- puglSetFrame(view, frame);
-}
-
-/**
- Set the minimum window size before creating a window.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetMinSize")
-void
-puglInitWindowMinSize(PuglView* view, int width, int height)
-{
- puglSetSizeHint(view, PUGL_MIN_SIZE, (PuglSpan)width, (PuglSpan)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.
-
- Note that setting different minimum and maximum constraints does not
- currently work on MacOS (the minimum is used), so only setting a fixed
- aspect ratio works properly across all platforms.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetAspectRatio")
-void
-puglInitWindowAspectRatio(PuglView* view,
- int minX,
- int minY,
- int maxX,
- int maxY)
-{
- puglSetSizeHint(view, PUGL_MIN_ASPECT, (PuglSpan)minX, (PuglSpan)minY);
- puglSetSizeHint(view, PUGL_MAX_ASPECT, (PuglSpan)maxX, (PuglSpan)maxY);
-}
-
-/**
- Set transient parent before creating a window.
-
- On X11, parent must be a Window.
- On OSX, parent must be an NSView*.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetTransientParent")
-void
-puglInitTransientFor(PuglView* view, uintptr_t parent)
-{
- puglSetTransientParent(view, (PuglNativeView)parent);
-}
-
-/**
- Set transient parent before creating a window.
-
- @deprecated Use puglSetTransientParent().
-*/
-static inline PUGL_DEPRECATED_BY("puglSetTransientParent")
-PuglStatus
-puglSetTransientFor(PuglView* view, uintptr_t parent)
-{
- return puglSetTransientParent(view, (PuglNativeView)parent);
-}
-
-/**
- Enable or disable resizing before creating a window.
-
- @deprecated Use puglSetViewHint() with #PUGL_RESIZABLE.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetViewHint")
-void
-puglInitResizable(PuglView* view, bool resizable)
-{
- puglSetViewHint(view, PUGL_RESIZABLE, resizable);
-}
-
-/**
- Get the current size of the view.
-
- @deprecated Use puglGetFrame().
-
-*/
-static inline PUGL_DEPRECATED_BY("puglGetFrame")
-void
-puglGetSize(PuglView* view, int* width, int* height)
-{
- const PuglRect frame = puglGetFrame(view);
-
- *width = (int)frame.width;
- *height = (int)frame.height;
-}
-
-/**
- Ignore synthetic repeated key events.
-
- @deprecated Use puglSetViewHint() with #PUGL_IGNORE_KEY_REPEAT.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetViewHint")
-void
-puglIgnoreKeyRepeat(PuglView* view, bool ignore)
-{
- puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, ignore);
-}
-
-/**
- Set a hint before creating a window.
-
- @deprecated Use puglSetWindowHint().
-*/
-static inline PUGL_DEPRECATED_BY("puglSetViewHint")
-void
-puglInitWindowHint(PuglView* view, PuglViewHint hint, int value)
-{
- puglSetViewHint(view, hint, value);
-}
-
-/**
- Set the parent window before creating a window (for embedding).
-
- @deprecated Use puglSetWindowParent().
-*/
-static inline PUGL_DEPRECATED_BY("puglSetParentWindow")
-void
-puglInitWindowParent(PuglView* view, PuglNativeView parent)
-{
- puglSetParentWindow(view, parent);
-}
-
-/**
- Set the graphics backend to use.
-
- @deprecated Use puglSetBackend().
-*/
-static inline PUGL_DEPRECATED_BY("puglSetBackend")
-int
-puglInitBackend(PuglView* view, const PuglBackend* backend)
-{
- return (int)puglSetBackend(view, backend);
-}
-
-/**
- Set the title of the window.
-
- This only makes sense for non-embedded views that will have a corresponding
- top-level window, and sets the title, typically displayed in the title bar
- or in window switchers.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetViewString")
-PuglStatus
-puglSetWindowTitle(PuglView* view, const char* title)
-{
- return puglSetViewString(view, PUGL_WINDOW_TITLE, title);
-}
-
-/// Return the title of the window, or null
-static inline PUGL_DEPRECATED_BY("puglGetViewString")
-const char*
-puglGetWindowTitle(const PuglView* view)
-{
- return puglGetViewString(view, PUGL_WINDOW_TITLE);
-}
-
-/**
- Realize a view by creating a corresponding system view or window.
-
- The view should be fully configured using the above functions before this is
- called. This function may only be called once per view.
-
- @deprecated Use puglRealize(), or just show the view.
-*/
-static inline PUGL_DEPRECATED_BY("puglRealize")
-PuglStatus
-puglCreateWindow(PuglView* view, const char* title)
-{
- puglSetViewString(view, PUGL_WINDOW_TITLE, title);
- return puglRealize(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).
-
- @deprecated Use puglPollEvents().
-*/
-PUGL_API
-PUGL_DEPRECATED_BY("puglPollEvents")
-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.
-
- @deprecated Use puglDispatchEvents().
-*/
-PUGL_API
-PUGL_DEPRECATED_BY("puglDispatchEvents")
-PuglStatus
-puglProcessEvents(PuglView* view);
-
-/**
- Poll for events that are ready to be processed.
-
- This polls for events that are ready for any view in the world, potentially
- blocking depending on `timeout`.
-
- @param world The world to poll for events.
-
- @param timeout Maximum time to wait, in seconds. If zero, the call returns
- immediately, if negative, the call blocks indefinitely.
-
- @return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if not, or an error.
-
- @deprecated Use puglUpdate().
-*/
-static inline PUGL_DEPRECATED_BY("puglUpdate")
-PuglStatus
-puglPollEvents(PuglWorld* world, double timeout)
-{
- return puglUpdate(world, timeout);
-}
-
-/**
- Dispatch any pending events to views.
-
- This processes all pending events, dispatching them to the appropriate
- views. View event handlers will be called in the scope of this call. This
- function does not block, if no events are pending then it will return
- immediately.
-
- @deprecated Use puglUpdate().
-*/
-static inline PUGL_DEPRECATED_BY("puglUpdate")
-PuglStatus
-puglDispatchEvents(PuglWorld* world)
-{
- return puglUpdate(world, 0.0);
-}
-
-static inline PUGL_DEPRECATED_BY("puglShow")
-PuglStatus
-puglShowWindow(PuglView* view)
-{
- return puglShow(view, PUGL_SHOW_RAISE);
-}
-
-static inline PUGL_DEPRECATED_BY("puglHide")
-PuglStatus
-puglHideWindow(PuglView* view)
-{
- return puglHide(view);
-}
-
-/**
- Set the default size of the view.
-
- This should be called before puglRealize() to set the default size of the
- view, which will be the initial size of the window if this is a top level
- view.
-
- @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
- not yet realized.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetSizeHint")
-PuglStatus
-puglSetDefaultSize(PuglView* view, int width, int height)
-{
- return puglSetSizeHint(
- view, PUGL_DEFAULT_SIZE, (PuglSpan)width, (PuglSpan)height);
-}
-
-/**
- Set the minimum size of the view.
-
- If an initial minimum size is known, this should be called before
- puglRealize() to avoid stutter, though it can be called afterwards as well.
-
- @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
- not yet realized.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetSizeHint")
-PuglStatus
-puglSetMinSize(PuglView* view, int width, int height)
-{
- return puglSetSizeHint(
- view, PUGL_MIN_SIZE, (PuglSpan)width, (PuglSpan)height);
-}
-
-/**
- Set the maximum size of the view.
-
- If an initial maximum size is known, this should be called before
- puglRealize() to avoid stutter, though it can be called afterwards as well.
-
- @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
- not yet realized.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetSizeHint")
-PuglStatus
-puglSetMaxSize(PuglView* view, int width, int height)
-{
- return puglSetSizeHint(
- view, PUGL_MAX_SIZE, (PuglSpan)width, (PuglSpan)height);
-}
-
-/**
- Set the view aspect ratio range.
-
- 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.
-
- Note that setting different minimum and maximum constraints does not
- currently work on MacOS (the minimum is used), so only setting a fixed
- aspect ratio works properly across all platforms.
-
- If an initial aspect ratio is known, this should be called before
- puglRealize() to avoid stutter, though it can be called afterwards as well.
-
- @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
- not yet realized.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetSizeHint")
-PuglStatus
-puglSetAspectRatio(PuglView* view, int minX, int minY, int maxX, int maxY)
-{
- const PuglStatus st0 =
- puglSetSizeHint(view, PUGL_MIN_ASPECT, (PuglSpan)minX, (PuglSpan)minY);
-
- const PuglStatus st1 =
- puglSetSizeHint(view, PUGL_MAX_ASPECT, (PuglSpan)maxX, (PuglSpan)maxY);
-
- return st0 ? st0 : st1;
-}
-
-/// Return the native window handle
-static inline PUGL_DEPRECATED_BY("puglGetNativeView")
-PuglNativeView
-puglGetNativeWindow(PuglView* view)
-{
- return puglGetNativeView(view);
-}
-
-/**
- Request user attention.
-
- This hints to the system that the window or application requires attention
- from the user. The exact effect depends on the platform, but is usually
- something like a flashing task bar entry or bouncing application icon.
-*/
-static inline PUGL_DEPRECATED_BY("puglSetViewStyle")
-PuglStatus
-puglRequestAttention(PuglView* view)
-{
- return puglSetViewStyle(view,
- puglGetViewStyle(view) | PUGL_VIEW_STYLE_DEMANDING);
-}
-
-# define PUGL_KEY_SHIFT PUGL_KEY_SHIFT_L
-
-# define PUGL_KEY_CTRL PUGL_KEY_CTRL_L
-
-# define PUGL_KEY_ALT PUGL_KEY_ALT_L
-
-# define PUGL_KEY_SUPER PUGL_KEY_SUPER_L
-
-#endif // PUGL_DISABLE_DEPRECATED
-
-/**
@}
@}
*/
diff --git a/include/pugl/stub.h b/include/pugl/stub.h
index 8bfe4d8..73f20aa 100644
--- a/include/pugl/stub.h
+++ b/include/pugl/stub.h
@@ -4,8 +4,8 @@
#ifndef PUGL_STUB_H
#define PUGL_STUB_H
-#include "pugl/attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/attributes.h>
+#include <pugl/pugl.h>
PUGL_BEGIN_DECLS
@@ -22,8 +22,7 @@ PUGL_BEGIN_DECLS
This backend just creates a simple native window without setting up any
portable graphics API.
*/
-PUGL_CONST_API
-const PuglBackend*
+PUGL_CONST_API const PuglBackend*
puglStubBackend(void);
/**
diff --git a/include/pugl/vulkan.h b/include/pugl/vulkan.h
index a26ca8a..325c39d 100644
--- a/include/pugl/vulkan.h
+++ b/include/pugl/vulkan.h
@@ -10,8 +10,8 @@
#ifndef PUGL_VULKAN_H
#define PUGL_VULKAN_H
-#include "pugl/attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/attributes.h>
+#include <pugl/pugl.h>
#include <vulkan/vulkan_core.h>
@@ -70,8 +70,7 @@ typedef struct PuglVulkanLoaderImpl PuglVulkanLoader;
@return A new Vulkan loader, or null on failure.
*/
-PUGL_API
-PuglVulkanLoader*
+PUGL_API PuglVulkanLoader*
puglNewVulkanLoader(PuglWorld* world, const char* libraryName);
/**
@@ -80,8 +79,7 @@ puglNewVulkanLoader(PuglWorld* world, const char* libraryName);
Note that this closes the Vulkan library, so no Vulkan objects or API may be
used after this is called.
*/
-PUGL_API
-void
+PUGL_API void
puglFreeVulkanLoader(PuglVulkanLoader* loader);
/**
@@ -90,8 +88,7 @@ puglFreeVulkanLoader(PuglVulkanLoader* loader);
@return Null if the Vulkan library does not contain this function (which is
unlikely and indicates a broken system).
*/
-PUGL_API
-PFN_vkGetInstanceProcAddr
+PUGL_API PFN_vkGetInstanceProcAddr
puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader);
/**
@@ -100,8 +97,7 @@ puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader);
@return Null if the Vulkan library does not contain this function (which is
unlikely and indicates a broken system).
*/
-PUGL_API
-PFN_vkGetDeviceProcAddr
+PUGL_API PFN_vkGetDeviceProcAddr
puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader);
/**
@@ -113,8 +109,7 @@ puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader);
@param[out] count The number of extensions in the returned array.
@return An array of extension name strings.
*/
-PUGL_API
-const char* const*
+PUGL_API const char* const*
puglGetInstanceExtensions(uint32_t* count);
/**
@@ -127,8 +122,7 @@ puglGetInstanceExtensions(uint32_t* count);
@param[out] surface Pointed to a newly created Vulkan surface.
@return `VK_SUCCESS` on success, or a Vulkan error code.
*/
-PUGL_API
-VkResult
+PUGL_API VkResult
puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
PuglView* view,
VkInstance instance,
@@ -140,8 +134,7 @@ puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
Pass the returned value to puglSetBackend() to draw to a view with Vulkan.
*/
-PUGL_CONST_API
-const PuglBackend*
+PUGL_CONST_API const PuglBackend*
puglVulkanBackend(void);
/**
diff --git a/meson.build b/meson.build
index e3b8450..6fc3973 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# Copyright 2021-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
project(
@@ -8,11 +8,12 @@ project(
'b_ndebug=if-release',
'buildtype=release',
'c_std=c99',
+ 'c_winlibs=',
'cpp_std=c++14',
],
license: 'ISC',
meson_version: '>= 0.54.0',
- version: '0.5.3',
+ version: '0.5.5',
)
pugl_src_root = meson.current_source_dir()
@@ -28,8 +29,11 @@ versioned_name = 'pugl' + version_suffix
pkg = import('pkgconfig')
cc = meson.get_compiler('c')
-# Enable C++ support if we're building the examples
-if not get_option('examples').disabled() or not get_option('tests').disabled()
+# Enable C++ support if we're building the examples or the bindings
+if (
+ not get_option('bindings_cpp').disabled()
+ or not get_option('examples').disabled()
+)
if add_languages(['cpp'], native: false, required: false)
cpp = meson.get_compiler('cpp')
endif
@@ -44,18 +48,13 @@ endif
# Set global warning suppressions
subdir('meson/suppressions')
-# Disable deprecated API which is not used by tests or examples
-add_project_arguments(
- ['-DPUGL_DISABLE_DEPRECATED'],
- language: ['c', 'cpp', 'objc', 'objcpp'],
-)
-
#############
# Platforms #
#############
core_args = []
dl_dep = cc.find_library('dl', required: false)
+with_timers = true
if host_machine.system() == 'darwin'
# MacOS
@@ -155,15 +154,20 @@ elif host_machine.system() == 'windows'
]
endif
+ if not get_option('win_wchar').disabled()
+ win_args += ['-DUNICODE', '-D_UNICODE']
+ endif
+
add_project_arguments(win_args, language: ['c', 'cpp'])
user32_dep = cc.find_library('user32')
shlwapi_dep = cc.find_library('shlwapi')
dwmapi_dep = cc.find_library('dwmapi')
+ gdi32_dep = cc.find_library('gdi32')
platform = 'win'
platform_sources = files('src/win.c')
- core_deps = [user32_dep, shlwapi_dep, dwmapi_dep]
+ core_deps = [user32_dep, shlwapi_dep, dwmapi_dep, gdi32_dep]
extension = '.c'
soversion = ''
@@ -173,15 +177,12 @@ else
core_args += '-D_POSIX_C_SOURCE=200809L'
xcursor_dep = cc.find_library('Xcursor', required: get_option('xcursor'))
- if xcursor_dep.found()
- core_args += ['-DUSE_XCURSOR=1']
- endif
+ core_args += ['-DUSE_XCURSOR=@0@'.format(xcursor_dep.found().to_int())]
xrandr_dep = cc.find_library('Xrandr', required: get_option('xrandr'))
- if xrandr_dep.found()
- core_args += ['-DUSE_XRANDR=1']
- endif
+ core_args += ['-DUSE_XRANDR=@0@'.format(xrandr_dep.found().to_int())]
+ with_timers = false
use_xsync = false
xext_dep = cc.find_library('Xext', required: get_option('xsync'))
if xext_dep.found()
@@ -189,12 +190,13 @@ else
#include <X11/extensions/sync.h>
int main(void) { XSyncQueryExtension(0, 0, 0); return 0; }'''
if cc.compiles(xsync_fragment, name: 'Xsync')
- core_args += ['-DUSE_XSYNC=1']
+ with_timers = true
use_xsync = true
elif get_option('xsync') == 'enabled'
error('C header <X11/extensions/sync.h> not found')
endif
endif
+ core_args += ['-DUSE_XSYNC=@0@'.format(use_xsync.to_int())]
x11_args = []
if cc.get_id() == 'clang'
@@ -241,6 +243,7 @@ libpugl = library(
c_args: library_args + core_args,
dependencies: core_deps,
gnu_symbol_visibility: 'hidden',
+ implicit_include_directories: false,
include_directories: includes,
install: true,
soversion: soversion,
@@ -250,7 +253,7 @@ libpugl = library(
pugl_dep = declare_dependency(
compile_args: extra_c_args,
dependencies: core_deps,
- include_directories: ['include'],
+ include_directories: includes,
link_with: libpugl,
)
@@ -280,6 +283,7 @@ if get_option('stub')
c_args: library_args,
dependencies: [pugl_dep],
gnu_symbol_visibility: 'hidden',
+ implicit_include_directories: false,
include_directories: includes,
install: true,
soversion: soversion,
@@ -322,6 +326,7 @@ if opengl_dep.found()
c_args: library_args,
dependencies: [pugl_dep, opengl_dep],
gnu_symbol_visibility: 'hidden',
+ implicit_include_directories: false,
include_directories: includes,
install: true,
soversion: soversion,
@@ -375,6 +380,7 @@ if cairo_dep.found()
c_args: library_args + cairo_args,
dependencies: [pugl_dep, cairo_dep],
gnu_symbol_visibility: 'hidden',
+ implicit_include_directories: false,
include_directories: includes,
install: true,
objc_args: library_args + cairo_args,
@@ -430,6 +436,7 @@ if vulkan_dep.found()
c_args: library_args,
dependencies: vulkan_deps,
gnu_symbol_visibility: 'hidden',
+ implicit_include_directories: false,
include_directories: includes,
install: true,
soversion: soversion,
@@ -461,12 +468,20 @@ endif
###############################
subdir('include')
-subdir('bindings/cpp')
+
+if not get_option('bindings_cpp').disabled()
+ subdir('bindings/cpp')
+endif
######################
# Tests and Examples #
######################
+if not get_option('tests').disabled() or not get_option('examples').disabled()
+ puglutil = subproject('puglutil')
+ puglutil_dep = puglutil.get_variable('puglutil_dep')
+endif
+
if not get_option('tests').disabled()
subdir('test')
endif
@@ -521,6 +536,7 @@ if meson.version().version_compare('>=0.53.0')
'Tests': not get_option('tests').disabled(),
'Examples': not get_option('examples').disabled(),
'Documentation': build_docs,
+ 'C++ bindings': not get_option('bindings_cpp').disabled(),
},
bool_yn: true,
section: 'Components',
diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build
index 270e64e..1f7171a 100644
--- a/meson/suppressions/meson.build
+++ b/meson/suppressions/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2020-2023 David Robillard <d@drobilla.net>
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
# Project-specific warning suppressions
@@ -30,6 +30,7 @@ if cc.get_id() == 'clang'
if host_machine.system() == 'windows'
c_suppressions += [
+ '-Wno-cast-function-type',
'-Wno-deprecated-declarations',
'-Wno-format-nonliteral',
'-Wno-nonportable-system-include-path',
@@ -121,6 +122,7 @@ if is_variable('cpp')
'-Wno-inline',
'-Wno-padded',
'-Wno-sign-conversion',
+ '-Wno-switch-default',
'-Wno-unsafe-buffer-usage',
]
@@ -136,6 +138,7 @@ if is_variable('cpp')
cpp_suppressions += [
'-Wno-inline',
'-Wno-padded',
+ '-Wno-suggest-attribute=pure',
]
if host_machine.system() == 'windows'
diff --git a/meson_options.txt b/meson_options.txt
index faab87a..571a640 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,18 +1,21 @@
-# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# Copyright 2021-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
+option('bindings_cpp', type: 'feature', yield: true,
+ description: 'Build C++ bindings')
+
option('cairo', type: 'feature',
description: 'Enable support for the Cairo graphics API')
-option('examples', type: 'feature', yield: true,
- description: 'Build example programs')
-
-option('docs', type: 'feature',
+option('docs', type: 'feature', yield: true,
description: 'Build documentation')
option('docs_cpp', type: 'boolean', value: false,
description: 'Attempt to build C++ documentation for development')
+option('examples', type: 'feature', yield: true,
+ description: 'Build example programs')
+
option('lint', type: 'boolean', value: false, yield: true,
description: 'Run code quality checks')
@@ -28,6 +31,9 @@ option('tests', type: 'feature', yield: true,
option('vulkan', type: 'feature',
description: 'Enable support for the Vulkan graphics API')
+option('win_wchar', type: 'feature', yield: true,
+ description: 'Use UTF-16 wchar_t and UNICODE with Windows API')
+
option('xcursor', type: 'feature',
description: 'Support changing the cursor on X11')
diff --git a/src/.clang-tidy b/src/.clang-tidy
index d57b1a8..cfc824d 100644
--- a/src/.clang-tidy
+++ b/src/.clang-tidy
@@ -1,8 +1,9 @@
-# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
-bugprone-easily-swappable-parameters,
+ -bugprone-multi-level-implicit-pointer-conversion,
-hicpp-multiway-paths-covered,
-hicpp-signed-bitwise,
-llvm-header-guard,
diff --git a/src/common.c b/src/common.c
index 46b2f3d..c8ac3d4 100644
--- a/src/common.c
+++ b/src/common.c
@@ -4,13 +4,11 @@
// Common implementations of public API functions in the core library
#include "internal.h"
-
#include "platform.h"
#include "types.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
-#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@@ -106,27 +104,37 @@ puglGetWorldString(const PuglWorld* const world, const PuglStringHint key)
}
static void
-puglSetDefaultHints(PuglHints hints)
+puglSetDefaultHints(PuglView* const view)
{
- hints[PUGL_CONTEXT_API] = PUGL_OPENGL_API;
- hints[PUGL_CONTEXT_VERSION_MAJOR] = 2;
- hints[PUGL_CONTEXT_VERSION_MINOR] = 0;
- hints[PUGL_CONTEXT_PROFILE] = PUGL_OPENGL_CORE_PROFILE;
- hints[PUGL_CONTEXT_DEBUG] = PUGL_FALSE;
- hints[PUGL_RED_BITS] = 8;
- hints[PUGL_GREEN_BITS] = 8;
- hints[PUGL_BLUE_BITS] = 8;
- hints[PUGL_ALPHA_BITS] = 8;
- hints[PUGL_DEPTH_BITS] = 0;
- hints[PUGL_STENCIL_BITS] = 0;
- hints[PUGL_SAMPLE_BUFFERS] = PUGL_DONT_CARE;
- hints[PUGL_SAMPLES] = 0;
- hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE;
- hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE;
- hints[PUGL_RESIZABLE] = PUGL_FALSE;
- hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE;
- hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE;
- hints[PUGL_VIEW_TYPE] = PUGL_DONT_CARE;
+ view->hints[PUGL_CONTEXT_API] = PUGL_OPENGL_API;
+ view->hints[PUGL_CONTEXT_VERSION_MAJOR] = 2;
+ view->hints[PUGL_CONTEXT_VERSION_MINOR] = 0;
+ view->hints[PUGL_CONTEXT_PROFILE] = PUGL_OPENGL_CORE_PROFILE;
+ view->hints[PUGL_CONTEXT_DEBUG] = PUGL_FALSE;
+ view->hints[PUGL_RED_BITS] = 8;
+ view->hints[PUGL_GREEN_BITS] = 8;
+ view->hints[PUGL_BLUE_BITS] = 8;
+ view->hints[PUGL_ALPHA_BITS] = 8;
+ view->hints[PUGL_DEPTH_BITS] = 0;
+ view->hints[PUGL_STENCIL_BITS] = 0;
+ view->hints[PUGL_SAMPLE_BUFFERS] = PUGL_DONT_CARE;
+ view->hints[PUGL_SAMPLES] = 0;
+ view->hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE;
+ view->hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE;
+ view->hints[PUGL_RESIZABLE] = PUGL_FALSE;
+ view->hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE;
+ view->hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE;
+ view->hints[PUGL_VIEW_TYPE] = PUGL_DONT_CARE;
+
+ for (unsigned i = 0U; i < PUGL_NUM_POSITION_HINTS; ++i) {
+ view->positionHints[i].x = INT16_MIN;
+ view->positionHints[i].y = INT16_MIN;
+ }
+
+ for (unsigned i = 0U; i < PUGL_NUM_SIZE_HINTS; ++i) {
+ view->sizeHints[i].width = 0U;
+ view->sizeHints[i].height = 0U;
+ }
}
PuglView*
@@ -138,13 +146,8 @@ puglNewView(PuglWorld* const world)
return NULL;
}
- view->world = world;
- view->sizeHints[PUGL_MIN_SIZE].width = 1;
- view->sizeHints[PUGL_MIN_SIZE].height = 1;
- view->defaultX = INT_MIN;
- view->defaultY = INT_MIN;
-
- puglSetDefaultHints(view->hints);
+ view->world = world;
+ puglSetDefaultHints(view);
// Enlarge world view list
const size_t newNumViews = world->numViews + 1U;
@@ -287,43 +290,48 @@ puglGetViewString(const PuglView* const view, const PuglStringHint key)
return view->strings[key];
}
-PuglRect
-puglGetFrame(const PuglView* view)
+PuglPoint
+puglGetPositionHint(const PuglView* const view, const PuglPositionHint hint)
{
- if (view->lastConfigure.type == PUGL_CONFIGURE) {
- // Return the last configured frame
- const PuglRect frame = {view->lastConfigure.x,
- view->lastConfigure.y,
- view->lastConfigure.width,
- view->lastConfigure.height};
- return frame;
+ if (hint == PUGL_CURRENT_POSITION) {
+ PuglPoint pos = {0, 0};
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ pos.x = view->lastConfigure.x;
+ pos.y = view->lastConfigure.y;
+ } else {
+ const PuglPoint defaultPos = view->positionHints[PUGL_DEFAULT_POSITION];
+ if (puglIsValidPosition(defaultPos.x, defaultPos.y)) {
+ pos.x = defaultPos.x;
+ pos.y = defaultPos.y;
+ }
+ }
+ return pos;
}
- // Get the default position if set, or fallback to (0, 0)
- int x = view->defaultX;
- int y = view->defaultY;
- if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) {
- x = 0;
- y = 0;
+ return view->positionHints[hint];
+}
+
+PuglArea
+puglGetSizeHint(const PuglView* const view, const PuglSizeHint hint)
+{
+ if (hint == PUGL_CURRENT_SIZE && view->lastConfigure.type == PUGL_CONFIGURE) {
+ const PuglArea area = {view->lastConfigure.width,
+ view->lastConfigure.height};
+ return area;
}
- // Return the default frame, sanitized if necessary
- const PuglRect frame = {(PuglCoord)x,
- (PuglCoord)y,
- view->sizeHints[PUGL_DEFAULT_SIZE].width,
- view->sizeHints[PUGL_DEFAULT_SIZE].height};
- return frame;
+ return view->sizeHints[hint];
}
PuglStatus
-puglSetParentWindow(PuglView* view, PuglNativeView parent)
+puglSetParent(PuglView* view, PuglNativeView parent)
{
view->parent = parent;
return PUGL_SUCCESS;
}
PuglNativeView
-puglGetParentWindow(const PuglView* const view)
+puglGetParent(const PuglView* const view)
{
return view->parent;
}
diff --git a/src/internal.c b/src/internal.c
index 3c4d304..ca84ed1 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -5,19 +5,80 @@
#include "types.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+static PuglPoint
+make_point(const PuglCoord x, const PuglCoord y)
+{
+ const PuglPoint point = {x, y};
+ return point;
+}
+
+bool
+puglIsValidPosition(const int x, const int y)
+{
+ // INT16_MIN is a sentinel, INT16_MAX is impossible with non-zero size
+ return x > INT16_MIN && x < INT16_MAX && y > INT16_MIN && y < INT16_MAX;
+}
+
+bool
+puglIsValidSize(const unsigned width, const unsigned height)
+{
+ return width && height && width <= INT16_MAX && height <= INT16_MAX;
+}
+
bool
-puglIsValidSize(const PuglViewSize size)
+puglIsValidArea(const PuglArea size)
{
return size.width && size.height;
}
+PuglArea
+puglGetInitialSize(const PuglView* const view)
+{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured size
+ const PuglConfigureEvent config = view->lastConfigure;
+ const PuglArea size = {config.width, config.height};
+ return size;
+ }
+
+ // Use the default size hint set by the application
+ return view->sizeHints[PUGL_DEFAULT_SIZE];
+}
+
+PuglPoint
+puglGetInitialPosition(const PuglView* const view, const PuglArea size)
+{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured frame
+ return make_point(view->lastConfigure.x, view->lastConfigure.y);
+ }
+
+ const PuglPoint defaultPos = view->positionHints[PUGL_DEFAULT_POSITION];
+ if (puglIsValidPosition(defaultPos.x, defaultPos.y)) {
+ // Use the default position hint set by the application
+ return make_point(defaultPos.x, defaultPos.y);
+ }
+
+ if (view->parent) {
+ // Default to the top/left origin of the parent
+ return make_point(0, 0);
+ }
+
+ // Center frame on a transient ancestor, or failing that, the screen
+ const PuglPoint center = puglGetAncestorCenter(view);
+ const PuglPoint pos = {(PuglCoord)(center.x - (size.width / 2)),
+ (PuglCoord)(center.y - (size.height / 2))};
+ return pos;
+}
+
void
puglEnsureHint(PuglView* const view, const PuglViewHint hint, const int value)
{
@@ -68,6 +129,21 @@ puglSetString(char** dest, const char* string)
}
}
+PuglStatus
+puglStoreSizeHint(PuglView* const view,
+ const PuglSizeHint hint,
+ const unsigned width,
+ const unsigned height)
+{
+ if (!puglIsValidSize(width, height)) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ view->sizeHints[hint].width = (PuglSpan)width;
+ view->sizeHints[hint].height = (PuglSpan)height;
+ return PUGL_SUCCESS;
+}
+
uint32_t
puglDecodeUTF8(const uint8_t* buf)
{
@@ -159,7 +235,7 @@ puglPreRealize(PuglView* const view)
}
// Ensure that the default size is set to a valid size
- if (!puglIsValidSize(view->sizeHints[PUGL_DEFAULT_SIZE])) {
+ if (!puglIsValidArea(view->sizeHints[PUGL_DEFAULT_SIZE])) {
return PUGL_BAD_CONFIGURATION;
}
@@ -173,7 +249,7 @@ puglDispatchSimpleEvent(PuglView* view, const PuglEventType type)
type == PUGL_UPDATE || type == PUGL_CLOSE || type == PUGL_LOOP_ENTER ||
type == PUGL_LOOP_LEAVE);
- const PuglEvent event = {{type, 0}};
+ const PuglEvent event = {{type, 0U}};
return puglDispatchEvent(view, &event);
}
diff --git a/src/internal.h b/src/internal.h
index 3721c10..8678982 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -9,8 +9,8 @@
#include "attributes.h"
#include "types.h"
-#include "pugl/attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/attributes.h>
+#include <pugl/pugl.h>
#include <stdbool.h>
#include <stddef.h>
@@ -18,9 +18,29 @@
PUGL_BEGIN_DECLS
+/// Return true if `x`,`y` is a valid position
+bool
+puglIsValidPosition(int x, int y);
+
+/// Return true if `width`,`height` is a valid position
+bool
+puglIsValidSize(unsigned x, unsigned y);
+
/// Return true if `size` is a valid view size
bool
-puglIsValidSize(PuglViewSize size);
+puglIsValidArea(PuglArea size);
+
+/// Return the center point of some "soft" ancestor (parent window or screen)
+PuglPoint
+puglGetAncestorCenter(const PuglView* view);
+
+/// Return the initial size of a view
+PuglArea
+puglGetInitialSize(const PuglView* view);
+
+/// Return the initial position of a view if known, or an invalid position
+PuglPoint
+puglGetInitialPosition(const PuglView* view, PuglArea size);
/// Set hint to a default value if it is unset (PUGL_DONT_CARE)
void
@@ -34,8 +54,14 @@ puglSetBlob(PuglBlob* dest, const void* data, size_t len);
void
puglSetString(char** dest, const char* string);
+/// Store `width` and `height` as the current value of a size `hint`
+PuglStatus
+puglStoreSizeHint(PuglView* view,
+ PuglSizeHint hint,
+ unsigned width,
+ unsigned height);
+
/// Handle a changed string property
-PUGL_API
PuglStatus
puglViewStringChanged(PuglView* view, PuglStringHint key, const char* value);
@@ -56,8 +82,7 @@ PuglStatus
puglDispatchSimpleEvent(PuglView* view, PuglEventType type);
/// Process configure event while already in the graphics context
-PUGL_WARN_UNUSED_RESULT
-PuglStatus
+PUGL_WARN_UNUSED_RESULT PuglStatus
puglConfigure(PuglView* view, const PuglEvent* event);
/// Dispatch `event` to `view`, entering graphics context if necessary
diff --git a/src/mac.h b/src/mac.h
index 119e7c8..305cf30 100644
--- a/src/mac.h
+++ b/src/mac.h
@@ -5,7 +5,7 @@
#ifndef PUGL_SRC_MAC_H
#define PUGL_SRC_MAC_H
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#import <Cocoa/Cocoa.h>
diff --git a/src/mac.m b/src/mac.m
index cf7e8d2..41d358a 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -7,9 +7,10 @@
#include "mac.h"
#include "internal.h"
+#include "macros.h"
#include "platform.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#import <Cocoa/Cocoa.h>
@@ -121,7 +122,7 @@ viewScreen(const PuglView* view)
}
static NSRect
-nsRectToPoints(PuglView* view, const NSRect rect)
+nsRectToPoints(const PuglView* view, const NSRect rect)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -132,7 +133,7 @@ nsRectToPoints(PuglView* view, const NSRect rect)
}
static NSRect
-nsRectFromPoints(PuglView* view, const NSRect rect)
+nsRectFromPoints(const PuglView* view, const NSRect rect)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -143,21 +144,15 @@ nsRectFromPoints(PuglView* view, const NSRect rect)
}
static NSPoint
-nsPointFromPoints(PuglView* view, const NSPoint point)
+nsPointFromPoints(const PuglView* view, const NSPoint point)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor);
}
-static NSRect
-rectToNsRect(const PuglRect rect)
-{
- return NSMakeRect(rect.x, rect.y, rect.width, rect.height);
-}
-
static NSSize
-sizePoints(PuglView* view, const double width, const double height)
+sizePoints(PuglView* view, const PuglSpan width, const PuglSpan height)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -199,7 +194,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view)
const PuglConfigureEvent ev = {
PUGL_CONFIGURE,
- 0,
+ 0U,
(PuglCoord)framePx.origin.x,
(PuglCoord)framePx.origin.y,
(PuglSpan)framePx.size.width,
@@ -249,7 +244,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view)
const PuglConfigureEvent ev = {
PUGL_CONFIGURE,
- 0,
+ 0U,
(PuglCoord)contentPx.origin.x,
(PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height),
(PuglSpan)contentPx.size.width,
@@ -326,11 +321,14 @@ dispatchCurrentChildViewConfiguration(PuglView* const view)
return;
}
+ const double viewY = (double)puglview->lastConfigure.height -
+ ((rect.origin.y + rect.size.height) * scaleFactor);
+
const PuglExposeEvent ev = {
PUGL_EXPOSE,
- 0,
+ 0U,
(PuglCoord)(rect.origin.x * scaleFactor),
- (PuglCoord)(rect.origin.y * scaleFactor),
+ (PuglCoord)viewY,
(PuglSpan)(rect.size.width * scaleFactor),
(PuglSpan)(rect.size.height * scaleFactor),
};
@@ -342,9 +340,9 @@ dispatchCurrentChildViewConfiguration(PuglView* const view)
- (NSSize)intrinsicContentSize
{
- const PuglViewSize defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE];
+ const PuglArea defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE];
- return puglIsValidSize(defaultSize)
+ return puglIsValidArea(defaultSize)
? sizePoints(puglview, defaultSize.width, defaultSize.height)
: NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric);
}
@@ -460,7 +458,7 @@ keySymToSpecial(const NSEvent* const ev)
return PUGL_KEY_PAD_9;
}
- return (PuglKey)0;
+ return PUGL_KEY_NONE;
}
- (void)updateTrackingAreas
@@ -493,7 +491,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const NSPoint rloc = [NSEvent mouseLocation];
const PuglCrossingEvent ev = {
type,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -534,7 +532,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const NSPoint rloc = [NSEvent mouseLocation];
const PuglMotionEvent ev = {
PUGL_MOTION,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -569,7 +567,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const NSPoint rloc = [NSEvent mouseLocation];
const PuglButtonEvent ev = {
PUGL_BUTTON_PRESS,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -590,7 +588,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const NSPoint rloc = [NSEvent mouseLocation];
const PuglButtonEvent ev = {
PUGL_BUTTON_RELEASE,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -627,10 +625,16 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
- (void)scrollWheel:(NSEvent*)event
{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const double dx = -[event scrollingDeltaX];
- const double dy = [event scrollingDeltaY];
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+
+ double dx = -[event scrollingDeltaX];
+ double dy = [event scrollingDeltaY];
+ if ([event hasPreciseScrollingDeltas]) {
+ dx /= 20.0;
+ dy /= 20.0;
+ }
+
const PuglScrollDirection dir =
((dx == 0.0 && dy > 0.0)
? PUGL_SCROLL_UP
@@ -643,14 +647,14 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const PuglScrollEvent ev = {
PUGL_SCROLL,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
rloc.x,
[[NSScreen mainScreen] frame].size.height - rloc.y,
getModifiers(event),
- [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir,
+ dir,
dx,
dy,
};
@@ -675,7 +679,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const PuglKeyEvent ev = {
PUGL_KEY_PRESS,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -706,7 +710,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
const PuglKeyEvent ev = {
PUGL_KEY_RELEASE,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -818,7 +822,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
PuglTextEvent ev = {
PUGL_TEXT,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -847,7 +851,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask)
- (void)flagsChanged:(NSEvent*)event
{
const uint32_t mods = getModifiers(event);
- PuglKey special = (PuglKey)0;
+ PuglKey special = PUGL_KEY_NONE;
const uint16_t keyCode = [event keyCode];
if (flagDiffers(mods, puglview->impl->mods, PUGL_MOD_SHIFT)) {
@@ -868,7 +872,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask)
const bool release = [event type] == NSEventTypeKeyUp;
const PuglKeyEvent ev = {release ? PUGL_KEY_RELEASE : PUGL_KEY_PRESS,
- 0,
+ 0U,
[event timestamp],
wloc.x,
wloc.y,
@@ -910,7 +914,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask)
- (void)timerTick:(NSTimer*)userTimer
{
const NSNumber* userInfo = userTimer.userInfo;
- const PuglTimerEvent ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue};
+ const PuglTimerEvent ev = {PUGL_TIMER, 0U, userInfo.unsignedLongValue};
PuglEvent timerEvent;
timerEvent.timer = ev;
@@ -975,7 +979,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask)
{
(void)notification;
- PuglEvent ev = {{PUGL_FOCUS_IN, 0}};
+ PuglEvent ev = {{PUGL_FOCUS_IN, 0U}};
ev.focus.mode = PUGL_CROSSING_NORMAL;
puglDispatchEvent(window->puglview, &ev);
}
@@ -984,7 +988,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask)
{
(void)notification;
- PuglEvent ev = {{PUGL_FOCUS_OUT, 0}};
+ PuglEvent ev = {{PUGL_FOCUS_OUT, 0U}};
ev.focus.mode = PUGL_CROSSING_NORMAL;
puglDispatchEvent(window->puglview, &ev);
}
@@ -1108,12 +1112,13 @@ updateSizeHint(PuglView* const view, const PuglSizeHint hint)
{
const PuglSpan width = view->sizeHints[hint].width;
const PuglSpan height = view->sizeHints[hint].height;
- if (!puglIsValidSize(view->sizeHints[hint])) {
+ if (!puglIsValidArea(view->sizeHints[hint])) {
return PUGL_FAILURE;
}
switch (hint) {
case PUGL_DEFAULT_SIZE:
+ case PUGL_CURRENT_SIZE:
break;
case PUGL_MIN_SIZE:
@@ -1144,30 +1149,9 @@ updateSizeHints(PuglView* const view)
}
}
-static PuglRect
-getInitialFrame(PuglView* const view)
+PuglPoint
+puglGetAncestorCenter(const PuglView* const view)
{
- if (view->lastConfigure.type == PUGL_CONFIGURE) {
- // Use the last configured frame
- const PuglRect frame = {view->lastConfigure.x,
- view->lastConfigure.y,
- view->lastConfigure.width,
- view->lastConfigure.height};
- return frame;
- }
-
- const int x = view->defaultX;
- const int y = view->defaultY;
- if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) {
- // Use the default position set with puglSetPosition while unrealized
- const PuglRect frame = {(PuglCoord)x,
- (PuglCoord)y,
- view->sizeHints[PUGL_DEFAULT_SIZE].width,
- view->sizeHints[PUGL_DEFAULT_SIZE].height};
- return frame;
- }
-
- // Get a bounding rect from the transient parent or the screen
const NSScreen* const screen = viewScreen(view);
const NSRect boundsPt =
rectFromScreen(screen,
@@ -1175,17 +1159,11 @@ getInitialFrame(PuglView* const view)
? [[(const NSView*)view->transientParent window] frame]
: [screen frame]);
- // Center the frame around the center of the bounding rectangle
- const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
- const NSRect boundsPx = nsRectFromPoints(view, boundsPt);
- const double centerX = boundsPx.origin.x + boundsPx.size.width / 2;
- const double centerY = boundsPx.origin.y + boundsPx.size.height / 2;
-
- const PuglRect frame = {(PuglCoord)(centerX - (defaultSize.width / 2U)),
- (PuglCoord)(centerY - (defaultSize.height / 2U)),
- view->sizeHints[PUGL_DEFAULT_SIZE].width,
- view->sizeHints[PUGL_DEFAULT_SIZE].height};
- return frame;
+ const NSRect boundsPx = nsRectFromPoints(view, boundsPt);
+ const PuglPoint center = {
+ (PuglCoord)(boundsPx.origin.x + (boundsPx.size.width / 2.0)),
+ (PuglCoord)(boundsPx.origin.y + (boundsPx.size.height / 2.0))};
+ return center;
}
PuglStatus
@@ -1233,11 +1211,12 @@ puglRealize(PuglView* view)
CVDisplayLinkRelease(link);
}
- // Get the initial frame to use from the defaults or last configuration
- const PuglRect initialFrame = getInitialFrame(view);
+ // Get the initial size and position from the defaults or last configuration
+ const PuglArea size = puglGetInitialSize(view);
+ const PuglPoint pos = puglGetInitialPosition(view, size);
// Convert frame to points
- const NSRect framePx = rectToNsRect(initialFrame);
+ const NSRect framePx = NSMakeRect(pos.x, pos.y, size.width, size.height);
const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor,
framePx.origin.y / scaleFactor,
framePx.size.width / scaleFactor,
@@ -1263,7 +1242,7 @@ puglRealize(PuglView* view)
NSLayoutRelationGreaterThanOrEqual,
view->sizeHints[PUGL_MIN_SIZE].height)];
- if (puglIsValidSize(view->sizeHints[PUGL_MAX_SIZE])) {
+ if (puglIsValidArea(view->sizeHints[PUGL_MAX_SIZE])) {
[impl->wrapperView
addConstraint:puglConstraint(impl->wrapperView,
NSLayoutAttributeWidth,
@@ -1323,8 +1302,17 @@ puglRealize(PuglView* view)
((NSWindow*)window).delegate =
[[PuglWindowDelegate alloc] initWithPuglWindow:window];
- // Set basic window hints and attributes
- puglSetFrame(view, initialFrame);
+ // Set window frame
+ const NSRect screenPt = rectToScreen(screen, framePt);
+ const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
+ [impl->window setFrame:winFrame display:NO];
+
+ // Resize views and move them to (0, 0)
+ const NSRect sizePx = {{0, 0}, {framePx.size.width, framePx.size.height}};
+ const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
+ [impl->wrapperView setFrame:sizePt];
+ [impl->drawView setFrame:sizePt];
+
puglSetTransientParent(view, view->transientParent);
updateSizeHints(view);
@@ -1596,14 +1584,6 @@ puglSendEvent(PuglView* view, const PuglEvent* event)
return PUGL_UNSUPPORTED;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglWaitForEvent(PuglView* view)
-{
- return puglPollEvents(view->world, -1.0);
-}
-#endif
-
PuglStatus
puglUpdate(PuglWorld* world, const double timeout)
{
@@ -1641,14 +1621,6 @@ puglUpdate(PuglWorld* world, const double timeout)
return PUGL_SUCCESS;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglProcessEvents(PuglView* view)
-{
- return puglDispatchEvents(view->world);
-}
-#endif
-
double
puglGetTime(const PuglWorld* world)
{
@@ -1660,22 +1632,37 @@ puglGetTime(const PuglWorld* world)
}
PuglStatus
-puglPostRedisplay(PuglView* view)
+puglObscureView(PuglView* view)
{
[view->impl->drawView setNeedsDisplay:YES];
return PUGL_SUCCESS;
}
PuglStatus
-puglPostRedisplayRect(PuglView* view, const PuglRect rect)
+puglObscureRegion(PuglView* view,
+ const int x,
+ const int y,
+ const unsigned width,
+ const unsigned height)
{
- const NSRect rectPx = {
- {(double)rect.x,
- (double)view->lastConfigure.height - (rect.y + rect.height)},
- {(double)rect.width, (double)rect.height},
- };
+ if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ const PuglSpan viewHeight = view->lastConfigure.height;
+
+ const int cx = MAX(0, x);
+ const int cy = MAX(0, viewHeight - y - (int)height);
+ const unsigned cw = MIN(view->lastConfigure.width, width);
+ const unsigned ch = MIN(view->lastConfigure.height, height);
+
+ if (cw == view->lastConfigure.width && ch == view->lastConfigure.height) {
+ [view->impl->drawView setNeedsDisplay:YES];
+ } else {
+ const NSRect rectPx = NSMakeRect(cx, cy, cw, ch);
- [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)];
+ [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)];
+ }
return PUGL_SUCCESS;
}
@@ -1720,108 +1707,36 @@ puglGetScaleFactor(const PuglView* const view)
return [viewScreen(view) backingScaleFactor];
}
-PuglStatus
-puglSetFrame(PuglView* view, const PuglRect frame)
-{
- PuglInternals* const impl = view->impl;
- const NSRect framePx = rectToNsRect(frame);
- const NSRect framePt = nsRectToPoints(view, framePx);
-
- if (!impl->wrapperView) {
- // Set defaults to be used when realized
- view->defaultX = frame.x;
- view->defaultY = frame.y;
- view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)frame.width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)frame.height;
- return PUGL_SUCCESS;
- }
-
- if (impl->window) {
- const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
-
- // Move and resize window to fit new content rect
- const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
- [impl->window setFrame:winFrame display:NO];
-
- // Resize views
- const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
- const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
- [impl->wrapperView setFrame:sizePt];
- [impl->drawView setFrame:sizePt];
- [impl->window dispatchCurrentConfiguration];
- return PUGL_SUCCESS;
- }
-
- // Resize view
- const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
- const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
-
- [impl->wrapperView setFrame:framePt];
- [impl->drawView setFrame:sizePt];
- return dispatchCurrentChildViewConfiguration(view);
-}
-
-PuglStatus
-puglSetPosition(PuglView* const view, const int x, const int y)
+static PuglStatus
+puglSetWindowPosition(PuglView* const view, const int x, const int y)
{
- if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) {
- return PUGL_BAD_PARAMETER;
- }
-
PuglInternals* const impl = view->impl;
- if (!impl->wrapperView) {
- // Set defaults to be used when realized
- view->defaultX = x;
- view->defaultY = y;
- return PUGL_SUCCESS;
- }
- const PuglRect frame = {(PuglCoord)x,
- (PuglCoord)y,
- view->lastConfigure.width,
- view->lastConfigure.height};
+ const NSRect framePx =
+ NSMakeRect(x, y, view->lastConfigure.width, view->lastConfigure.height);
+
+ const NSRect framePt = nsRectToPoints(view, framePx);
if (impl->window) {
// Adjust top-level window frame
- return puglSetFrame(view, frame);
+ const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
+ [impl->window setFrameOrigin:screenPt.origin];
+ return PUGL_SUCCESS;
}
// Set wrapper view origin
- const NSRect framePx = rectToNsRect(frame);
- const NSRect framePt = nsRectToPoints(view, framePx);
[impl->wrapperView setFrameOrigin:framePt.origin];
- // Set draw view origin
- const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height);
- const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx];
- [impl->drawView setFrameOrigin:drawPt.origin];
-
// Dispatch new configuration
return dispatchCurrentChildViewConfiguration(view);
}
-PuglStatus
-puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+static PuglStatus
+puglSetWindowSize(PuglView* const view,
+ const unsigned width,
+ const unsigned height)
{
- if (width > INT16_MAX || height > INT16_MAX) {
- return PUGL_BAD_PARAMETER;
- }
-
PuglInternals* const impl = view->impl;
- if (!impl->wrapperView) {
- // Set defaults to be used when realized
- view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
- return PUGL_SUCCESS;
- }
-
- if (impl->window) {
- // Adjust top-level window frame
- PuglRect frame = puglGetFrame(view);
- frame.width = (PuglSpan)width;
- frame.height = (PuglSpan)height;
- return puglSetFrame(view, frame);
- }
// Set wrapper view size
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -1833,24 +1748,50 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx];
[impl->drawView setFrameSize:drawPt.size];
+ if (impl->window) {
+ const NSRect framePx =
+ NSMakeRect(view->lastConfigure.x, view->lastConfigure.y, width, height);
+ const NSRect framePt = nsRectToPoints(view, framePx);
+ const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
+
+ // Resize window to fit new content rect
+ const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
+ [impl->window setFrame:winFrame display:NO];
+ [impl->window dispatchCurrentConfiguration];
+ }
+
// Dispatch new configuration
return dispatchCurrentChildViewConfiguration(view);
}
PuglStatus
-puglSetSizeHint(PuglView* const view,
- const PuglSizeHint hint,
- const PuglSpan width,
- const PuglSpan height)
+puglSetPositionHint(PuglView* const view,
+ const PuglPositionHint hint,
+ const int x,
+ const int y)
{
- if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) {
+ if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) {
return PUGL_BAD_PARAMETER;
}
- view->sizeHints[hint].width = width;
- view->sizeHints[hint].height = height;
+ view->positionHints[hint].x = (PuglCoord)x;
+ view->positionHints[hint].y = (PuglCoord)y;
+
+ return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y)
+ : PUGL_SUCCESS;
+}
+
+PuglStatus
+puglSetSizeHint(PuglView* const view,
+ const PuglSizeHint hint,
+ const unsigned width,
+ const unsigned height)
+{
+ const PuglStatus st = puglStoreSizeHint(view, hint, width, height);
- return view->impl->window ? updateSizeHint(view, hint) : PUGL_SUCCESS;
+ return st ? st
+ : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height)
+ : updateSizeHint(view, hint);
}
PuglStatus
@@ -1878,7 +1819,7 @@ puglPaste(PuglView* const view)
{
const PuglDataOfferEvent offer = {
PUGL_DATA_OFFER,
- 0,
+ 0U,
puglGetTime(view->world),
};
diff --git a/src/mac_cairo.m b/src/mac_cairo.m
index e4d2f5f..112b727 100644
--- a/src/mac_cairo.m
+++ b/src/mac_cairo.m
@@ -5,7 +5,7 @@
#include "mac.h"
#include "stub.h"
-#include "pugl/cairo.h"
+#include <pugl/cairo.h>
#include <cairo-quartz.h>
diff --git a/src/mac_gl.m b/src/mac_gl.m
index f177bf9..57dfc41 100644
--- a/src/mac_gl.m
+++ b/src/mac_gl.m
@@ -5,7 +5,7 @@
#include "mac.h"
#include "stub.h"
-#include "pugl/gl.h"
+#include <pugl/gl.h>
#ifndef __MAC_10_10
# define NSOpenGLProfileVersion4_1Core NSOpenGLProfileVersion3_2Core
diff --git a/src/mac_stub.m b/src/mac_stub.m
index 9ebedca..c7e4512 100644
--- a/src/mac_stub.m
+++ b/src/mac_stub.m
@@ -5,7 +5,7 @@
#include "mac.h"
#include "stub.h"
-#include "pugl/stub.h"
+#include <pugl/stub.h>
#import <Cocoa/Cocoa.h>
diff --git a/src/mac_vulkan.m b/src/mac_vulkan.m
index 4fdbaf6..f3563e2 100644
--- a/src/mac_vulkan.m
+++ b/src/mac_vulkan.m
@@ -8,9 +8,9 @@
#include "stub.h"
#include "types.h"
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
-#include "pugl/vulkan.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
+#include <pugl/vulkan.h>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan_macos.h>
diff --git a/src/platform.h b/src/platform.h
index cfdb1b7..e43a58e 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -8,13 +8,12 @@
#include "types.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
PUGL_BEGIN_DECLS
/// Allocate and initialise world internals (implemented once per platform)
-PUGL_MALLOC_FUNC
-PuglWorldInternals*
+PUGL_MALLOC_FUNC PuglWorldInternals*
puglInitWorldInternals(PuglWorldType type, PuglWorldFlags flags);
/// Destroy and free world internals (implemented once per platform)
@@ -22,8 +21,7 @@ void
puglFreeWorldInternals(PuglWorld* world);
/// Allocate and initialise view internals (implemented once per platform)
-PUGL_MALLOC_FUNC
-PuglInternals*
+PUGL_MALLOC_FUNC PuglInternals*
puglInitViewInternals(PuglWorld* world);
/// Destroy and free view internals (implemented once per platform)
diff --git a/src/stub.h b/src/stub.h
index 699bbb9..476aa1a 100644
--- a/src/stub.h
+++ b/src/stub.h
@@ -4,7 +4,7 @@
#ifndef PUGL_SRC_STUB_H
#define PUGL_SRC_STUB_H
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <stddef.h>
diff --git a/src/types.h b/src/types.h
index 9817474..b453f11 100644
--- a/src/types.h
+++ b/src/types.h
@@ -6,7 +6,7 @@
#include "attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <stdbool.h>
#include <stddef.h>
@@ -21,18 +21,6 @@ typedef struct PuglInternalsImpl PuglInternals;
/// View hints
typedef int PuglHints[PUGL_NUM_VIEW_HINTS];
-/// View position (both X and Y coordinates) or general point
-typedef struct {
- PuglCoord x;
- PuglCoord y;
-} PuglPoint;
-
-/// View size (both X and Y coordinates)
-typedef struct {
- PuglSpan width;
- PuglSpan height;
-} PuglViewSize;
-
/// Blob of arbitrary data
typedef struct {
void* data; ///< Dynamically allocated data
@@ -57,10 +45,9 @@ struct PuglViewImpl {
uintptr_t transientParent;
PuglConfigureEvent lastConfigure;
PuglHints hints;
- PuglViewSize sizeHints[PUGL_NUM_SIZE_HINTS];
+ PuglPoint positionHints[PUGL_NUM_POSITION_HINTS];
+ PuglArea sizeHints[PUGL_NUM_SIZE_HINTS];
char* strings[PUGL_NUM_STRING_HINTS];
- int defaultX;
- int defaultY;
PuglViewStage stage;
bool resizing;
};
@@ -82,23 +69,21 @@ typedef void PuglSurface;
/// Graphics backend interface
struct PuglBackendImpl {
/// Get visual information from display and setup view as necessary
- PUGL_WARN_UNUSED_RESULT
- PuglStatus (*configure)(PuglView*);
+ PUGL_WARN_UNUSED_RESULT PuglStatus (*configure)(PuglView*);
/// Create surface and drawing context
- PUGL_WARN_UNUSED_RESULT
- PuglStatus (*create)(PuglView*);
+ PUGL_WARN_UNUSED_RESULT PuglStatus (*create)(PuglView*);
/// Destroy surface and drawing context
void (*destroy)(PuglView*);
/// Enter drawing context, for drawing if expose is non-null
- PUGL_WARN_UNUSED_RESULT
- PuglStatus (*enter)(PuglView*, const PuglExposeEvent*);
+ PUGL_WARN_UNUSED_RESULT PuglStatus (*enter)(PuglView*,
+ const PuglExposeEvent*);
/// Leave drawing context, after drawing if expose is non-null
- PUGL_WARN_UNUSED_RESULT
- PuglStatus (*leave)(PuglView*, const PuglExposeEvent*);
+ PUGL_WARN_UNUSED_RESULT PuglStatus (*leave)(PuglView*,
+ const PuglExposeEvent*);
/// Return the puglGetContext() handle for the application, if any
void* (*getContext)(PuglView*);
diff --git a/src/win.c b/src/win.c
index 1cc02e5..a8cd841 100644
--- a/src/win.c
+++ b/src/win.c
@@ -4,9 +4,10 @@
#include "win.h"
#include "internal.h"
+#include "macros.h"
#include "platform.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <dwmapi.h>
#include <windows.h>
@@ -43,12 +44,10 @@
#ifdef __cplusplus
# define PUGL_INIT_STRUCT \
- {}
-#else
-# define PUGL_INIT_STRUCT \
{ \
- 0 \
}
+#else
+# define PUGL_INIT_STRUCT {0}
#endif
typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void);
@@ -58,8 +57,12 @@ typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*);
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-static wchar_t*
-puglUtf8ToWideChar(const char* const utf8)
+#ifdef UNICODE
+
+typedef wchar_t ArgStringChar;
+
+static ArgStringChar*
+puglArgStringNew(const char* const utf8)
{
const int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
if (len > 0) {
@@ -71,6 +74,30 @@ puglUtf8ToWideChar(const char* const utf8)
return NULL;
}
+static void
+puglArgStringFree(ArgStringChar* const utf8)
+{
+ free(utf8);
+}
+
+#else // !defined(UNICODE)
+
+typedef const char ArgStringChar;
+
+static ArgStringChar*
+puglArgStringNew(const char* const utf8)
+{
+ return utf8;
+}
+
+static void
+puglArgStringFree(ArgStringChar* const utf8)
+{
+ (void)utf8;
+}
+
+#endif
+
static char*
puglWideCharToUtf8(const wchar_t* const wstr, size_t* len)
{
@@ -94,6 +121,8 @@ puglWinStatus(const BOOL success)
static bool
puglRegisterWindowClass(const char* name)
{
+ ArgStringChar* const nameArg = puglArgStringNew(name);
+
HMODULE module = NULL;
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
@@ -103,7 +132,7 @@ puglRegisterWindowClass(const char* name)
}
WNDCLASSEX wc = PUGL_INIT_STRUCT;
- if (GetClassInfoEx(module, name, &wc)) {
+ if (GetClassInfoEx(module, nameArg, &wc)) {
return true; // Already registered
}
@@ -114,9 +143,11 @@ puglRegisterWindowClass(const char* name)
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.lpszClassName = name;
+ wc.lpszClassName = nameArg;
- return !!RegisterClassEx(&wc);
+ const bool success = !!RegisterClassEx(&wc);
+ puglArgStringFree(nameArg);
+ return success;
}
static unsigned
@@ -174,7 +205,7 @@ static double
puglWinGetViewScaleFactor(const PuglView* const view)
{
const HMODULE shcore =
- LoadLibraryEx("Shcore.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ LoadLibraryEx(TEXT("Shcore.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!shcore) {
return 1.0;
}
@@ -209,7 +240,7 @@ puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags))
if (type == PUGL_PROGRAM) {
HMODULE user32 =
- LoadLibraryEx("user32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ LoadLibraryEx(TEXT("user32.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (user32) {
PFN_SetProcessDPIAware SetProcessDPIAware =
(PFN_SetProcessDPIAware)GetProcAddress(user32, "SetProcessDPIAware");
@@ -240,20 +271,6 @@ puglInitViewInternals(PuglWorld* PUGL_UNUSED(world))
return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}
-static PuglStatus
-puglPollWinEvents(PuglWorld* world, const double timeout)
-{
- (void)world;
-
- if (timeout < 0) {
- WaitMessage();
- } else {
- MsgWaitForMultipleObjects(
- 0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS);
- }
- return PUGL_SUCCESS;
-}
-
PuglStatus
puglRealize(PuglView* view)
{
@@ -277,9 +294,9 @@ puglRealize(PuglView* view)
puglEnsureHint(view, PUGL_ALPHA_BITS, 8);
// Get refresh rate for resize draw timer
- DEVMODEA devMode;
+ DEVMODE devMode;
memset(&devMode, 0, sizeof(devMode));
- EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devMode);
+ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency;
// Register window class if necessary
@@ -298,16 +315,16 @@ puglRealize(PuglView* view)
puglSetViewString(view, PUGL_WINDOW_TITLE, view->strings[PUGL_WINDOW_TITLE]);
puglSetTransientParent(view, view->transientParent);
- view->impl->scaleFactor = puglWinGetViewScaleFactor(view);
- view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
+ impl->scaleFactor = puglWinGetViewScaleFactor(view);
+ impl->cursor = LoadCursor(NULL, IDC_ARROW);
if (view->hints[PUGL_DARK_FRAME]) {
const BOOL useDarkMode = TRUE;
- if ((DwmSetWindowAttribute(view->impl->hwnd,
+ if ((DwmSetWindowAttribute(impl->hwnd,
DWMWA_USE_IMMERSIVE_DARK_MODE,
&useDarkMode,
sizeof(useDarkMode)) != S_OK)) {
- DwmSetWindowAttribute(view->impl->hwnd,
+ DwmSetWindowAttribute(impl->hwnd,
PRE_20H1_DWMWA_USE_IMMERSIVE_DARK_MODE,
&useDarkMode,
sizeof(useDarkMode));
@@ -333,24 +350,22 @@ puglUnrealize(PuglView* const view)
view->backend->destroy(view);
}
- ReleaseDC(view->impl->hwnd, view->impl->hdc);
- view->impl->hdc = NULL;
-
- DestroyWindow(view->impl->hwnd);
- view->impl->hwnd = NULL;
-
memset(&view->lastConfigure, 0, sizeof(PuglConfigureEvent));
- return PUGL_SUCCESS;
+ ReleaseDC(impl->hwnd, impl->hdc);
+ impl->hdc = NULL;
+
+ const PuglStatus st = puglWinStatus(DestroyWindow(impl->hwnd));
+ impl->hwnd = NULL;
+ return st;
}
PuglStatus
puglShow(PuglView* view, const PuglShowCommand command)
{
PuglInternals* impl = view->impl;
-
+ PuglStatus st = PUGL_SUCCESS;
if (!impl->hwnd) {
- const PuglStatus st = puglRealize(view);
- if (st) {
+ if ((st = puglRealize(view))) {
return st;
}
}
@@ -369,15 +384,13 @@ puglShow(PuglView* view, const PuglShowCommand command)
break;
}
- return PUGL_SUCCESS;
+ return st;
}
PuglStatus
puglHide(PuglView* view)
{
- PuglInternals* impl = view->impl;
-
- ShowWindow(impl->hwnd, SW_HIDE);
+ ShowWindow(view->impl->hwnd, SW_HIDE);
return PUGL_SUCCESS;
}
@@ -398,7 +411,11 @@ puglFreeViewInternals(PuglView* view)
void
puglFreeWorldInternals(PuglWorld* world)
{
- UnregisterClass(world->strings[PUGL_CLASS_NAME], NULL);
+ const char* const className = world->strings[PUGL_CLASS_NAME];
+ ArgStringChar* const classNameArg = puglArgStringNew(className);
+
+ UnregisterClass(classNameArg, NULL);
+ puglArgStringFree(classNameArg);
free(world->impl);
}
@@ -409,14 +426,14 @@ keyInRange(const WPARAM winSym,
const PuglKey puglMin)
{
return (winSym >= winMin && winSym <= winMax)
- ? (PuglKey)(puglMin + (winSym - winMin))
- : (PuglKey)0;
+ ? (PuglKey)((WPARAM)puglMin + (winSym - winMin))
+ : PUGL_KEY_NONE;
}
static PuglKey
keySymToSpecial(const WPARAM sym, const bool ext)
{
- PuglKey key = (PuglKey)0;
+ PuglKey key = PUGL_KEY_NONE;
if ((key = keyInRange(sym, VK_F1, VK_F12, PUGL_KEY_F1)) ||
(key = keyInRange(sym,
VK_PRIOR,
@@ -465,23 +482,26 @@ keySymToSpecial(const WPARAM sym, const bool ext)
// clang-format on
}
- return (PuglKey)0;
+ return PUGL_KEY_NONE;
+}
+
+static bool
+is_toggled(int vkey)
+{
+ return (unsigned)GetKeyState(vkey) & 1U;
}
static uint32_t
getModifiers(void)
{
- // clang-format off
- return (
- ((GetKeyState(VK_SHIFT) < 0) ? (uint32_t)PUGL_MOD_SHIFT : 0U) |
- ((GetKeyState(VK_CONTROL) < 0) ? (uint32_t)PUGL_MOD_CTRL : 0U) |
- ((GetKeyState(VK_MENU) < 0) ? (uint32_t)PUGL_MOD_ALT : 0U) |
- ((GetKeyState(VK_LWIN) < 0) ? (uint32_t)PUGL_MOD_SUPER : 0U) |
- ((GetKeyState(VK_RWIN) < 0) ? (uint32_t)PUGL_MOD_SUPER : 0U) |
- ((GetKeyState(VK_NUMLOCK) & 1U) ? (uint32_t)PUGL_MOD_NUM_LOCK : 0U) |
- ((GetKeyState(VK_SCROLL) & 1U) ? (uint32_t)PUGL_MOD_SCROLL_LOCK : 0U) |
- ((GetKeyState(VK_CAPITAL) & 1U) ? (uint32_t)PUGL_MOD_CAPS_LOCK : 0U));
- // clang-format on
+ return ((uint32_t)(((GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0) |
+ ((GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0) |
+ ((GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0) |
+ ((GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0) |
+ ((GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0) |
+ (is_toggled(VK_NUMLOCK) ? PUGL_MOD_NUM_LOCK : 0) |
+ (is_toggled(VK_SCROLL) ? PUGL_MOD_SCROLL_LOCK : 0) |
+ (is_toggled(VK_CAPITAL) ? PUGL_MOD_CAPS_LOCK : 0)));
}
static void
@@ -656,7 +676,7 @@ handleCrossing(PuglView* view, const PuglEventType type, POINT pos)
const PuglCrossingEvent ev = {
type,
- 0,
+ 0U,
GetMessageTime() / 1e3,
(double)pos.x,
(double)pos.y,
@@ -666,7 +686,7 @@ handleCrossing(PuglView* view, const PuglEventType type, POINT pos)
PUGL_CROSSING_NORMAL,
};
- PuglEvent crossingEvent = {{type, 0}};
+ PuglEvent crossingEvent = {{type, 0U}};
crossingEvent.crossing = ev;
puglDispatchEvent(view, &crossingEvent);
}
@@ -676,8 +696,8 @@ constrainAspect(const PuglView* const view,
RECT* const size,
const WPARAM wParam)
{
- const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT];
- const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT];
+ const PuglArea minAspect = view->sizeHints[PUGL_MIN_ASPECT];
+ const PuglArea maxAspect = view->sizeHints[PUGL_MAX_ASPECT];
const float minA = (float)minAspect.width / (float)minAspect.height;
const float maxA = (float)maxAspect.width / (float)maxAspect.height;
@@ -716,7 +736,7 @@ constrainAspect(const PuglView* const view,
static LRESULT
handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
{
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
RECT rect = {0, 0, 0, 0};
POINT pt = {0, 0};
MINMAXINFO* mmi = NULL;
@@ -762,8 +782,8 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
handleConfigure(view, &event);
break;
case WM_SIZING:
- if (puglIsValidSize(view->sizeHints[PUGL_MIN_ASPECT]) &&
- puglIsValidSize(view->sizeHints[PUGL_MAX_ASPECT])) {
+ if (puglIsValidArea(view->sizeHints[PUGL_MIN_ASPECT]) &&
+ puglIsValidArea(view->sizeHints[PUGL_MAX_ASPECT])) {
constrainAspect(view, (RECT*)lParam, wParam);
return TRUE;
}
@@ -778,7 +798,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_TIMER:
if (wParam >= PUGL_USER_TIMER_MIN) {
- PuglEvent ev = {{PUGL_TIMER, 0}};
+ PuglEvent ev = {{PUGL_TIMER, 0U}};
ev.timer.id = wParam - PUGL_USER_TIMER_MIN;
puglDispatchEvent(view, &ev);
}
@@ -795,7 +815,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
mmi = (MINMAXINFO*)lParam;
mmi->ptMinTrackSize.x = view->sizeHints[PUGL_MIN_SIZE].width;
mmi->ptMinTrackSize.y = view->sizeHints[PUGL_MIN_SIZE].height;
- if (puglIsValidSize(view->sizeHints[PUGL_MAX_SIZE])) {
+ if (puglIsValidArea(view->sizeHints[PUGL_MAX_SIZE])) {
mmi->ptMaxTrackSize.x = view->sizeHints[PUGL_MAX_SIZE].width;
mmi->ptMaxTrackSize.y = view->sizeHints[PUGL_MAX_SIZE].height;
}
@@ -931,8 +951,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
PuglStatus
puglGrabFocus(PuglView* view)
{
- SetFocus(view->impl->hwnd);
- return PUGL_SUCCESS;
+ return puglWinStatus(!!SetFocus(view->impl->hwnd));
}
bool
@@ -1006,7 +1025,7 @@ puglSetViewStyle(PuglView* const view, const PuglViewStyleFlags flags)
const bool newMaximized = styleIsMaximized(flags);
if (oldMaximized != newMaximized) {
ShowWindow(impl->hwnd, newMaximized ? SW_SHOWMAXIMIZED : SW_RESTORE);
- puglPostRedisplay(view);
+ puglObscureView(view);
}
return PUGL_SUCCESS;
@@ -1017,9 +1036,8 @@ puglStartTimer(PuglView* view, uintptr_t id, double timeout)
{
const UINT msec = (UINT)floor(timeout * 1000.0);
- return (SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL)
- ? PUGL_SUCCESS
- : PUGL_UNKNOWN_ERROR);
+ SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL);
+ return PUGL_SUCCESS;
}
PuglStatus
@@ -1032,31 +1050,19 @@ PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event)
{
if (event->type == PUGL_CLOSE) {
- PostMessage(view->impl->hwnd, WM_CLOSE, 0, 0);
- return PUGL_SUCCESS;
+ return puglWinStatus(PostMessage(view->impl->hwnd, WM_CLOSE, 0, 0));
}
if (event->type == PUGL_CLIENT) {
- PostMessage(view->impl->hwnd,
- PUGL_LOCAL_CLIENT_MSG,
- (WPARAM)event->client.data1,
- (LPARAM)event->client.data2);
-
- return PUGL_SUCCESS;
+ return puglWinStatus(PostMessage(view->impl->hwnd,
+ PUGL_LOCAL_CLIENT_MSG,
+ (WPARAM)event->client.data1,
+ (LPARAM)event->client.data2));
}
return PUGL_UNSUPPORTED;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglWaitForEvent(PuglView* PUGL_UNUSED(view))
-{
- WaitMessage();
- return PUGL_SUCCESS;
-}
-#endif
-
static PuglStatus
puglDispatchViewEvents(PuglView* view)
{
@@ -1101,21 +1107,24 @@ puglDispatchWinEvents(PuglWorld* world)
PuglStatus
puglUpdate(PuglWorld* world, double timeout)
{
+ static const double minWaitSeconds = 0.002;
+
const double startTime = puglGetTime(world);
PuglStatus st = PUGL_SUCCESS;
if (timeout < 0.0) {
- st = puglPollWinEvents(world, timeout);
- st = st ? st : puglDispatchWinEvents(world);
- } else if (timeout <= 0.001) {
+ WaitMessage();
+ st = puglDispatchWinEvents(world);
+ } else if (timeout < minWaitSeconds) {
st = puglDispatchWinEvents(world);
} else {
- const double endTime = startTime + timeout - 0.001;
- for (double t = startTime; t < endTime; t = puglGetTime(world)) {
- if ((st = puglPollWinEvents(world, endTime - t)) ||
- (st = puglDispatchWinEvents(world))) {
- break;
- }
+ const double endTime = startTime + timeout - minWaitSeconds;
+ double t = startTime;
+ while (!st && t < endTime) {
+ const DWORD timeoutMs = (DWORD)((endTime - t) * 1e3);
+ MsgWaitForMultipleObjects(0, NULL, FALSE, timeoutMs, QS_ALLEVENTS);
+ st = puglDispatchWinEvents(world);
+ t = puglGetTime(world);
}
}
@@ -1130,14 +1139,6 @@ puglUpdate(PuglWorld* world, double timeout)
return st;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglProcessEvents(PuglView* view)
-{
- return puglUpdate(view->world, 0.0);
-}
-#endif
-
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
@@ -1171,23 +1172,29 @@ puglGetTime(const PuglWorld* world)
}
PuglStatus
-puglPostRedisplay(PuglView* view)
+puglObscureView(PuglView* view)
{
- InvalidateRect(view->impl->hwnd, NULL, false);
- return PUGL_SUCCESS;
+ return puglWinStatus(InvalidateRect(view->impl->hwnd, NULL, false));
}
PuglStatus
-puglPostRedisplayRect(PuglView* view, const PuglRect rect)
+puglObscureRegion(PuglView* const view,
+ const int x,
+ const int y,
+ const unsigned width,
+ const unsigned height)
{
- const RECT r = {(long)floor(rect.x),
- (long)floor(rect.y),
- (long)ceil(rect.x + rect.width),
- (long)ceil(rect.y + rect.height)};
+ if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) {
+ return PUGL_BAD_PARAMETER;
+ }
- InvalidateRect(view->impl->hwnd, &r, false);
+ const int cx = MAX(0, x);
+ const int cy = MAX(0, y);
+ const unsigned cw = MIN(view->lastConfigure.width, width);
+ const unsigned ch = MIN(view->lastConfigure.height, height);
- return PUGL_SUCCESS;
+ const RECT r = {cx, cy, cx + (long)cw, cy + (long)ch};
+ return puglWinStatus(InvalidateRect(view->impl->hwnd, &r, false));
}
PuglNativeView
@@ -1201,19 +1208,18 @@ puglViewStringChanged(PuglView* const view,
const PuglStringHint key,
const char* const value)
{
+ PuglStatus st = PUGL_SUCCESS;
if (!view->impl->hwnd) {
- return PUGL_SUCCESS;
+ return st;
}
if (key == PUGL_WINDOW_TITLE) {
- wchar_t* const wtitle = puglUtf8ToWideChar(value);
- if (wtitle) {
- SetWindowTextW(view->impl->hwnd, wtitle);
- free(wtitle);
- }
+ ArgStringChar* const titleArg = puglArgStringNew(value);
+ st = puglWinStatus(SetWindowText(view->impl->hwnd, titleArg));
+ puglArgStringFree(titleArg);
}
- return PUGL_SUCCESS;
+ return st;
}
static RECT
@@ -1238,45 +1244,9 @@ puglGetScaleFactor(const PuglView* const view)
: puglWinGetViewScaleFactor(view);
}
-PuglStatus
-puglSetFrame(PuglView* view, const PuglRect frame)
-{
- if (!view->impl->hwnd) {
- // Set defaults to be used when realized
- view->defaultX = frame.x;
- view->defaultY = frame.y;
- view->sizeHints[PUGL_DEFAULT_SIZE].width = frame.width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = frame.height;
- return PUGL_SUCCESS;
- }
-
- const RECT rect =
- adjustedWindowRect(view, frame.x, frame.y, frame.width, frame.height);
-
- return puglWinStatus(
- SetWindowPos(view->impl->hwnd,
- HWND_TOP,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER));
-}
-
-PuglStatus
-puglSetPosition(PuglView* const view, const int x, const int y)
+static PuglStatus
+puglSetWindowPosition(PuglView* const view, const int x, const int y)
{
- if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) {
- return PUGL_BAD_PARAMETER;
- }
-
- if (!view->impl->hwnd) {
- // Set defaults to be used when realized
- view->defaultX = x;
- view->defaultY = y;
- return PUGL_SUCCESS;
- }
-
const RECT rect = adjustedWindowRect(
view, x, y, view->lastConfigure.width, view->lastConfigure.height);
@@ -1287,20 +1257,11 @@ puglSetPosition(PuglView* const view, const int x, const int y)
SetWindowPos(view->impl->hwnd, HWND_TOP, rect.left, rect.top, 0, 0, flags));
}
-PuglStatus
-puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+static PuglStatus
+puglSetWindowSize(PuglView* const view,
+ const unsigned width,
+ const unsigned height)
{
- if (width > INT16_MAX || height > INT16_MAX) {
- return PUGL_BAD_PARAMETER;
- }
-
- if (!view->impl->hwnd) {
- // Set defaults to be used when realized
- view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
- return PUGL_SUCCESS;
- }
-
const RECT rect = adjustedWindowRect(view,
view->lastConfigure.x,
view->lastConfigure.y,
@@ -1320,18 +1281,33 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
}
PuglStatus
-puglSetSizeHint(PuglView* const view,
- const PuglSizeHint hint,
- const PuglSpan width,
- const PuglSpan height)
+puglSetPositionHint(PuglView* const view,
+ const PuglPositionHint hint,
+ const int x,
+ const int y)
{
- if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) {
+ if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) {
return PUGL_BAD_PARAMETER;
}
- view->sizeHints[hint].width = width;
- view->sizeHints[hint].height = height;
- return PUGL_SUCCESS;
+ view->positionHints[hint].x = (PuglCoord)x;
+ view->positionHints[hint].y = (PuglCoord)y;
+
+ return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y)
+ : PUGL_SUCCESS;
+}
+
+PuglStatus
+puglSetSizeHint(PuglView* const view,
+ const PuglSizeHint hint,
+ const unsigned width,
+ const unsigned height)
+{
+ const PuglStatus st = puglStoreSizeHint(view, hint, width, height);
+
+ return (!st && hint == PUGL_CURRENT_SIZE)
+ ? puglSetWindowSize(view, width, height)
+ : st;
}
PuglStatus
@@ -1377,15 +1353,14 @@ puglAcceptOffer(PuglView* const view,
const PuglDataEvent data = {
PUGL_DATA,
- 0,
+ 0U,
GetMessageTime() / 1e3,
0,
};
PuglEvent dataEvent;
dataEvent.data = data;
- puglDispatchEvent(view, &dataEvent);
- return PUGL_SUCCESS;
+ return puglDispatchEvent(view, &dataEvent);
}
const void*
@@ -1395,8 +1370,21 @@ puglGetClipboard(PuglView* const view,
{
PuglInternals* const impl = view->impl;
- if (typeIndex > 0U || !IsClipboardFormatAvailable(CF_UNICODETEXT) ||
- !OpenClipboard(impl->hwnd)) {
+ if (typeIndex > 0U || !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+ return NULL;
+ }
+
+ // Try to open the clipboard several times since others may have locked it
+ BOOL opened = FALSE;
+ static const unsigned max_tries = 16U;
+ for (unsigned i = 0U; !opened && i < max_tries; ++i) {
+ opened = OpenClipboard(impl->hwnd);
+ if (!opened) {
+ Sleep(0);
+ }
+ }
+
+ if (!opened) {
return NULL;
}
@@ -1407,15 +1395,14 @@ puglGetClipboard(PuglView* const view,
return NULL;
}
- free(view->impl->clipboard.data);
- view->impl->clipboard.data =
- puglWideCharToUtf8(wstr, &view->impl->clipboard.len);
+ free(impl->clipboard.data);
+ impl->clipboard.data = puglWideCharToUtf8(wstr, &impl->clipboard.len);
GlobalUnlock(mem);
CloseClipboard();
- *len = view->impl->clipboard.len;
- return view->impl->clipboard.data;
+ *len = impl->clipboard.len;
+ return impl->clipboard.data;
}
PuglStatus
@@ -1426,7 +1413,7 @@ puglSetClipboard(PuglView* const view,
{
PuglInternals* const impl = view->impl;
- PuglStatus st = puglSetBlob(&view->impl->clipboard, data, len);
+ PuglStatus st = puglSetBlob(&impl->clipboard, data, len);
if (st) {
return st;
}
@@ -1471,17 +1458,16 @@ puglPaste(PuglView* const view)
{
const PuglDataOfferEvent offer = {
PUGL_DATA_OFFER,
- 0,
+ 0U,
GetMessageTime() / 1e3,
};
PuglEvent offerEvent;
offerEvent.offer = offer;
- puglDispatchEvent(view, &offerEvent);
- return PUGL_SUCCESS;
+ return puglDispatchEvent(view, &offerEvent);
}
-static const char* const cursor_ids[] = {
+static const TCHAR* const cursor_ids[] = {
IDC_ARROW, // ARROW
IDC_IBEAM, // CARET
IDC_CROSS, // CROSSHAIR
@@ -1546,42 +1532,18 @@ puglWinGetPixelFormatDescriptor(const PuglHints hints)
return pfd;
}
-static PuglRect
-getInitialFrame(PuglView* const view)
+PuglPoint
+puglGetAncestorCenter(const PuglView* const view)
{
- if (view->lastConfigure.type == PUGL_CONFIGURE) {
- // Use the last configured frame
- const PuglRect frame = {view->lastConfigure.x,
- view->lastConfigure.y,
- view->lastConfigure.width,
- view->lastConfigure.height};
- return frame;
- }
-
- const PuglSpan defaultWidth = view->sizeHints[PUGL_DEFAULT_SIZE].width;
- const PuglSpan defaultHeight = view->sizeHints[PUGL_DEFAULT_SIZE].height;
- const int x = view->defaultX;
- const int y = view->defaultY;
- if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) {
- // Use the default position set with puglSetPosition while unrealized
- const PuglRect frame = {
- (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight};
- return frame;
- }
-
- // Get a bounding rect from the "nearest" parent or parent-like window
- const HWND hwnd = puglWinGetWindow(view);
- RECT rect = {0, 0, 0, 0};
- GetWindowRect(hwnd ? hwnd : GetDesktopWindow(), &rect);
+ RECT rect = {0, 0, 0, 0};
+ GetWindowRect(view->transientParent ? (HWND)view->transientParent
+ : GetDesktopWindow(),
+ &rect);
- // Center the frame around the center of the bounding rectangle
- const LONG centerX = rect.left + (rect.right - rect.left) / 2;
- const LONG centerY = rect.top + (rect.bottom - rect.top) / 2;
- const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2)),
- (PuglCoord)(centerY - (defaultHeight / 2)),
- defaultWidth,
- defaultHeight};
- return frame;
+ const PuglPoint center = {
+ (PuglCoord)(rect.left + ((rect.right - rect.left) / 2)),
+ (PuglCoord)(rect.top + ((rect.bottom - rect.top) / 2))};
+ return center;
}
PuglStatus
@@ -1596,28 +1558,35 @@ puglWinCreateWindow(PuglView* const view,
PuglNativeView parent = view->parent ? view->parent : view->transientParent;
// Calculate initial window rectangle
- const unsigned winFlags = puglWinGetWindowFlags(view);
- const unsigned winExFlags = puglWinGetWindowExFlags(view);
- const PuglRect frame = getInitialFrame(view);
- RECT wr = {(long)frame.x,
- (long)frame.y,
- (long)frame.x + frame.width,
- (long)frame.y + frame.height};
+ const unsigned winFlags = puglWinGetWindowFlags(view);
+ const unsigned winExFlags = puglWinGetWindowExFlags(view);
+ const PuglArea size = puglGetInitialSize(view);
+ const PuglPoint pos = puglGetInitialPosition(view, size);
+ RECT wr = {(long)pos.x,
+ (long)pos.y,
+ (long)pos.x + size.width,
+ (long)pos.y + size.height};
AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
+ ArgStringChar* const classNameArg = puglArgStringNew(className);
+ ArgStringChar* const titleArg = puglArgStringNew(title);
+
// Create window and get drawing context
- if (!(*hwnd = CreateWindowEx(winExFlags,
- className,
- title,
- winFlags,
- wr.left,
- wr.right,
- wr.right - wr.left,
- wr.bottom - wr.top,
- (HWND)parent,
- NULL,
- NULL,
- NULL))) {
+ *hwnd = CreateWindowEx(winExFlags,
+ classNameArg,
+ titleArg,
+ winFlags,
+ wr.left,
+ wr.right,
+ wr.right - wr.left,
+ wr.bottom - wr.top,
+ (HWND)parent,
+ NULL,
+ NULL,
+ NULL);
+ puglArgStringFree(titleArg);
+ puglArgStringFree(classNameArg);
+ if (!*hwnd) {
return PUGL_REALIZE_FAILED;
}
@@ -1643,7 +1612,6 @@ puglWinConfigure(PuglView* view)
{
PuglInternals* const impl = view->impl;
PuglStatus st = PUGL_SUCCESS;
-
if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) {
return st;
}
@@ -1656,20 +1624,18 @@ puglWinConfigure(PuglView* view)
DestroyWindow(impl->hwnd);
impl->hwnd = NULL;
impl->hdc = NULL;
- return PUGL_SET_FORMAT_FAILED;
+ st = PUGL_SET_FORMAT_FAILED;
}
- return PUGL_SUCCESS;
+ return st;
}
PuglStatus
puglWinEnter(PuglView* view, const PuglExposeEvent* expose)
{
- if (expose) {
- BeginPaint(view->impl->hwnd, &view->impl->paint);
- }
-
- return PUGL_SUCCESS;
+ return expose
+ ? puglWinStatus(!!BeginPaint(view->impl->hwnd, &view->impl->paint))
+ : PUGL_SUCCESS;
}
PuglStatus
diff --git a/src/win.h b/src/win.h
index 84f1d4e..b37db3f 100644
--- a/src/win.h
+++ b/src/win.h
@@ -6,7 +6,7 @@
#include "internal.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <windows.h>
@@ -37,28 +37,19 @@ struct PuglInternalsImpl {
bool fullscreen;
};
-PUGL_API
-PuglWinPFD
+PUGL_API PuglWinPFD
puglWinGetPixelFormatDescriptor(const PuglHints hints);
-PUGL_WARN_UNUSED_RESULT
-PUGL_API
-PuglStatus
+PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus
puglWinCreateWindow(PuglView* view, const char* title, HWND* hwnd, HDC* hdc);
-PUGL_WARN_UNUSED_RESULT
-PUGL_API
-PuglStatus
+PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus
puglWinConfigure(PuglView* view);
-PUGL_WARN_UNUSED_RESULT
-PUGL_API
-PuglStatus
+PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus
puglWinEnter(PuglView* view, const PuglExposeEvent* expose);
-PUGL_WARN_UNUSED_RESULT
-PUGL_API
-PuglStatus
+PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus
puglWinLeave(PuglView* view, const PuglExposeEvent* expose);
#endif // PUGL_SRC_WIN_H
diff --git a/src/win_cairo.c b/src/win_cairo.c
index 0aab254..873d395 100644
--- a/src/win_cairo.c
+++ b/src/win_cairo.c
@@ -5,7 +5,7 @@
#include "types.h"
#include "win.h"
-#include "pugl/cairo.h"
+#include <pugl/cairo.h>
#include <cairo-win32.h>
#include <cairo.h>
diff --git a/src/win_gl.c b/src/win_gl.c
index f707fc6..4f33e36 100644
--- a/src/win_gl.c
+++ b/src/win_gl.c
@@ -5,7 +5,7 @@
#include "types.h"
#include "win.h"
-#include "pugl/gl.h"
+#include <pugl/gl.h>
#include <windows.h>
@@ -14,30 +14,42 @@
#include <stdbool.h>
#include <stdlib.h>
-#define WGL_DRAW_TO_WINDOW_ARB 0x2001
-#define WGL_ACCELERATION_ARB 0x2003
-#define WGL_SUPPORT_OPENGL_ARB 0x2010
-#define WGL_DOUBLE_BUFFER_ARB 0x2011
-#define WGL_PIXEL_TYPE_ARB 0x2013
-#define WGL_RED_BITS_ARB 0x2015
-#define WGL_GREEN_BITS_ARB 0x2017
-#define WGL_BLUE_BITS_ARB 0x2019
-#define WGL_ALPHA_BITS_ARB 0x201b
-#define WGL_DEPTH_BITS_ARB 0x2022
-#define WGL_STENCIL_BITS_ARB 0x2023
-#define WGL_FULL_ACCELERATION_ARB 0x2027
-#define WGL_TYPE_RGBA_ARB 0x202b
-#define WGL_SAMPLE_BUFFERS_ARB 0x2041
-#define WGL_SAMPLES_ARB 0x2042
-
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+typedef enum {
+ WGL_DRAW_TO_WINDOW_ARB = 0x2001,
+ WGL_ACCELERATION_ARB = 0x2003,
+ WGL_SUPPORT_OPENGL_ARB = 0x2010,
+ WGL_DOUBLE_BUFFER_ARB = 0x2011,
+ WGL_PIXEL_TYPE_ARB = 0x2013,
+ WGL_RED_BITS_ARB = 0x2015,
+ WGL_GREEN_BITS_ARB = 0x2017,
+ WGL_BLUE_BITS_ARB = 0x2019,
+ WGL_ALPHA_BITS_ARB = 0x201B,
+ WGL_DEPTH_BITS_ARB = 0x2022,
+ WGL_STENCIL_BITS_ARB = 0x2023,
+ WGL_SAMPLE_BUFFERS_ARB = 0x2041,
+ WGL_SAMPLES_ARB = 0x2042,
+} PuglWinGlHintName;
+
+typedef enum {
+ WGL_FULL_ACCELERATION_ARB = 0x2027,
+ WGL_TYPE_RGBA_ARB = 0x202B,
+} PuglWinGlHintValue;
+
+typedef enum {
+ WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091,
+ WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092,
+ WGL_CONTEXT_FLAGS_ARB = 0x2094,
+ WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126,
+} PuglWinGlContextAttribName;
+
+typedef enum {
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001,
+ WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002,
+} PuglWinGlContextProfileBit;
+
+typedef enum {
+ WGL_CONTEXT_DEBUG_BIT_ARB = 0x00000001,
+} PuglWinGlContextDebugBit;
typedef HGLRC(WINAPI* WglCreateContextAttribs)(HDC, HGLRC, const int*);
@@ -288,7 +300,7 @@ puglGetProcAddress(const char* name)
return func
? func
- : (PuglGlFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), name);
+ : (PuglGlFunc)GetProcAddress(GetModuleHandleA("opengl32.dll"), name);
}
PuglStatus
diff --git a/src/win_stub.c b/src/win_stub.c
index e98357c..d2dc3f3 100644
--- a/src/win_stub.c
+++ b/src/win_stub.c
@@ -5,7 +5,7 @@
#include "types.h"
#include "win.h"
-#include "pugl/stub.h"
+#include <pugl/stub.h>
static PuglStatus
puglWinStubConfigure(PuglView* view)
diff --git a/src/win_vulkan.c b/src/win_vulkan.c
index 6d7c632..bd3bf45 100644
--- a/src/win_vulkan.c
+++ b/src/win_vulkan.c
@@ -7,7 +7,7 @@
#include "types.h"
#include "win.h"
-#include "pugl/vulkan.h"
+#include <pugl/vulkan.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_win32.h>
@@ -32,7 +32,7 @@ puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world),
const char* const filename = libraryName ? libraryName : "vulkan-1.dll";
if (!(loader->libvulkan =
- LoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS))) {
+ LoadLibraryExA(filename, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS))) {
free(loader);
return NULL;
}
diff --git a/src/x11.c b/src/x11.c
index 4db095e..3d2e080 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -11,7 +11,7 @@
#include "platform.h"
#include "types.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <X11/X.h>
#include <X11/Xatom.h>
@@ -70,12 +70,10 @@
#ifdef __cplusplus
# define PUGL_INIT_STRUCT \
- {}
-#else
-# define PUGL_INIT_STRUCT \
{ \
- 0 \
}
+#else
+# define PUGL_INIT_STRUCT {0}
#endif
enum WmClientStateMessageAction {
@@ -407,39 +405,44 @@ updateSizeHints(const PuglView* const view)
XSizeHints sizeHints = PUGL_INIT_STRUCT;
if (!view->hints[PUGL_RESIZABLE]) {
- const PuglRect frame = puglGetFrame(view);
+ PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
+ if (!puglIsValidSize(size.width, size.height)) {
+ size = puglGetSizeHint(view, PUGL_DEFAULT_SIZE);
+ }
+
sizeHints.flags = PBaseSize | PMinSize | PMaxSize;
- sizeHints.base_width = (int)frame.width;
- sizeHints.base_height = (int)frame.height;
- sizeHints.min_width = (int)frame.width;
- sizeHints.min_height = (int)frame.height;
- sizeHints.max_width = (int)frame.width;
- sizeHints.max_height = (int)frame.height;
+ sizeHints.base_width = (int)size.width;
+ sizeHints.base_height = (int)size.height;
+ sizeHints.min_width = (int)size.width;
+ sizeHints.min_height = (int)size.height;
+ sizeHints.max_width = (int)size.width;
+ sizeHints.max_height = (int)size.height;
} else {
- const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
- if (puglIsValidSize(defaultSize)) {
+ // Avoid setting PBaseSize for top level views to avoid window manager bugs
+ const PuglArea defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
+ if (puglIsValidArea(defaultSize) && view->parent) {
sizeHints.flags |= PBaseSize;
sizeHints.base_width = defaultSize.width;
sizeHints.base_height = defaultSize.height;
}
- const PuglViewSize minSize = view->sizeHints[PUGL_MIN_SIZE];
- if (puglIsValidSize(minSize)) {
+ const PuglArea minSize = view->sizeHints[PUGL_MIN_SIZE];
+ if (puglIsValidArea(minSize)) {
sizeHints.flags |= PMinSize;
sizeHints.min_width = minSize.width;
sizeHints.min_height = minSize.height;
}
- const PuglViewSize maxSize = view->sizeHints[PUGL_MAX_SIZE];
- if (puglIsValidSize(maxSize)) {
+ const PuglArea maxSize = view->sizeHints[PUGL_MAX_SIZE];
+ if (puglIsValidArea(maxSize)) {
sizeHints.flags |= PMaxSize;
sizeHints.max_width = maxSize.width;
sizeHints.max_height = maxSize.height;
}
- const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT];
- const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT];
- if (puglIsValidSize(minAspect) && puglIsValidSize(maxAspect)) {
+ const PuglArea minAspect = view->sizeHints[PUGL_MIN_ASPECT];
+ const PuglArea maxAspect = view->sizeHints[PUGL_MAX_ASPECT];
+ if (puglIsValidArea(minAspect) && puglIsValidArea(maxAspect)) {
sizeHints.flags |= PAspect;
sizeHints.min_aspect.x = minAspect.width;
sizeHints.min_aspect.y = minAspect.height;
@@ -447,8 +450,8 @@ updateSizeHints(const PuglView* const view)
sizeHints.max_aspect.y = maxAspect.height;
}
- const PuglViewSize fixedAspect = view->sizeHints[PUGL_FIXED_ASPECT];
- if (puglIsValidSize(fixedAspect)) {
+ const PuglArea fixedAspect = view->sizeHints[PUGL_FIXED_ASPECT];
+ if (puglIsValidArea(fixedAspect)) {
sizeHints.flags |= PAspect;
sizeHints.min_aspect.x = fixedAspect.width;
sizeHints.min_aspect.y = fixedAspect.height;
@@ -512,48 +515,21 @@ clearX11Clipboard(PuglX11Clipboard* const board)
board->data.len = 0;
}
-static PuglRect
-getInitialFrame(PuglView* const view)
+PuglPoint
+puglGetAncestorCenter(const PuglView* const view)
{
- if (view->lastConfigure.type == PUGL_CONFIGURE) {
- // Use the last configured frame
- const PuglRect frame = {view->lastConfigure.x,
- view->lastConfigure.y,
- view->lastConfigure.width,
- view->lastConfigure.height};
- return frame;
- }
-
- const PuglSpan defaultWidth = view->sizeHints[PUGL_DEFAULT_SIZE].width;
- const PuglSpan defaultHeight = view->sizeHints[PUGL_DEFAULT_SIZE].height;
- const int x = view->defaultX;
- const int y = view->defaultY;
- if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) {
- // Use the default position set with puglSetPosition while unrealized
- const PuglRect frame = {
- (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight};
- return frame;
- }
+ Display* const display = view->world->impl->display;
+ const int screen = view->impl->screen;
+ XWindowAttributes ancestorAttrs = PUGL_INIT_STRUCT;
+ XGetWindowAttributes(display,
+ view->transientParent ? (Window)view->transientParent
+ : RootWindow(display, screen),
+ &ancestorAttrs);
- // Get the best "parentish" window to position the window in
- Display* const display = view->world->impl->display;
- const Window parent =
- (view->parent ? (Window)view->parent
- : view->transientParent ? (Window)view->transientParent
- : RootWindow(display, view->impl->screen));
-
- // Get the position/size of the parent as bounds for the new window
- XWindowAttributes parentAttrs = PUGL_INIT_STRUCT;
- XGetWindowAttributes(display, parent, &parentAttrs);
-
- // Center the frame within the parent bounds
- const int centerX = parentAttrs.x + parentAttrs.width / 2;
- const int centerY = parentAttrs.y + parentAttrs.height / 2;
- const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2)),
- (PuglCoord)(centerY - (defaultHeight / 2)),
- defaultWidth,
- defaultHeight};
- return frame;
+ const PuglPoint center = {
+ (PuglCoord)(ancestorAttrs.x + (ancestorAttrs.width / 2)),
+ (PuglCoord)(ancestorAttrs.y + (ancestorAttrs.height / 2))};
+ return center;
}
PuglStatus
@@ -608,16 +584,17 @@ puglRealize(PuglView* const view)
attr.event_mask |= StructureNotifyMask;
attr.event_mask |= VisibilityChangeMask;
- // Calculate the initial window rectangle
- const PuglRect initialFrame = getInitialFrame(view);
+ // Calculate the initial window frame
+ const PuglArea initialSize = puglGetInitialSize(view);
+ const PuglPoint initialPos = puglGetInitialPosition(view, initialSize);
// Create the window
impl->win = XCreateWindow(display,
parent,
- initialFrame.x,
- initialFrame.y,
- initialFrame.width,
- initialFrame.height,
+ initialPos.x,
+ initialPos.y,
+ initialSize.width,
+ initialSize.height,
0,
impl->vi->depth,
InputOutput,
@@ -649,7 +626,7 @@ puglRealize(PuglView* const view)
if (XRRQueryExtension(display, &ignored, &ignored)) {
// Set refresh rate hint to the real refresh rate
XRRScreenConfiguration* conf = XRRGetScreenInfo(display, parent);
- short current_rate = XRRConfigCurrentRate(conf);
+ const short current_rate = XRRConfigCurrentRate(conf);
view->hints[PUGL_REFRESH_RATE] = current_rate;
XRRFreeScreenConfigInfo(conf);
@@ -772,7 +749,7 @@ puglShow(PuglView* const view, const PuglShowCommand command)
}
if (view->stage == PUGL_VIEW_STAGE_CONFIGURED) {
- st = puglPostRedisplay(view);
+ st = puglObscureView(view);
}
}
@@ -816,13 +793,13 @@ keyInRange(const KeySym xSym,
const PuglKey puglMin)
{
return (xSym >= xMin && xSym <= xMax) ? (PuglKey)(puglMin + (xSym - xMin))
- : (PuglKey)0;
+ : PUGL_KEY_NONE;
}
static PuglKey
keySymToSpecial(const KeySym sym)
{
- PuglKey key = (PuglKey)0;
+ PuglKey key = PUGL_KEY_NONE;
if ((key = keyInRange(sym, XK_F1, XK_F12, PUGL_KEY_F1)) ||
(key = keyInRange(sym, XK_Page_Up, XK_End, PUGL_KEY_PAGE_UP)) ||
(key = keyInRange(sym, XK_Home, XK_Down, PUGL_KEY_HOME)) ||
@@ -855,7 +832,7 @@ keySymToSpecial(const KeySym sym)
}
// clang-format on
- return (PuglKey)0;
+ return PUGL_KEY_NONE;
}
static int
@@ -896,7 +873,8 @@ translateKey(PuglView* const view, XEvent* const xevent, PuglEvent* const event)
event->key.key = (PuglKey)puglDecodeUTF8((const uint8_t*)ustr);
}
- if (xevent->type == KeyPress && !filter && !special && view->impl->xic) {
+ if (xevent->type == KeyPress && !filter && !(special && ufound <= 0) &&
+ view->impl->xic) {
// Lookup shifted key for possible text event
xevent->xkey.state = state;
@@ -1027,7 +1005,7 @@ translateClientMessage(PuglView* const view, XClientMessageEvent message)
{
Display* const display = view->world->impl->display;
const PuglX11Atoms* const atoms = &view->world->impl->atoms;
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
if (message.message_type == atoms->WM_PROTOCOLS) {
const Atom protocol = (Atom)message.data.l[0];
@@ -1100,17 +1078,19 @@ getCurrentConfiguration(PuglView* const view)
XWindowAttributes attrs;
XGetWindowAttributes(display, view->impl->win, &attrs);
- // Get window position relative to the root window
+ // Get window position (relative to the root window if not a child)
Window ignoredChild = 0;
- int rootX = 0;
- int rootY = 0;
- XTranslateCoordinates(
- display, view->impl->win, attrs.root, 0, 0, &rootX, &rootY, &ignoredChild);
+ int x = attrs.x;
+ int y = attrs.y;
+ if (!view->parent) {
+ XTranslateCoordinates(
+ display, view->impl->win, attrs.root, 0, 0, &x, &y, &ignoredChild);
+ }
// Build a configure event based on the current window configuration
- PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}};
- configureEvent.configure.x = (PuglCoord)rootX;
- configureEvent.configure.y = (PuglCoord)rootY;
+ PuglEvent configureEvent = {{PUGL_CONFIGURE, 0U}};
+ configureEvent.configure.x = (PuglCoord)x;
+ configureEvent.configure.y = (PuglCoord)y;
configureEvent.configure.width = (PuglSpan)attrs.width;
configureEvent.configure.height = (PuglSpan)attrs.height;
configureEvent.configure.style = getCurrentViewStyleFlags(view);
@@ -1139,7 +1119,7 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message)
{
const PuglInternals* const impl = view->impl;
const PuglX11Atoms* const atoms = &view->world->impl->atoms;
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
if (message.atom == atoms->NET_WM_STATE) {
// Get all the current states set in the window hints
@@ -1189,7 +1169,7 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message)
static PuglEvent
translateEvent(PuglView* const view, XEvent xevent)
{
- PuglEvent event = {{PUGL_NOTHING, 0}};
+ PuglEvent event = {{PUGL_NOTHING, 0U}};
event.any.flags = xevent.xany.send_event ? PUGL_IS_SEND_EVENT : 0;
switch (xevent.type) {
@@ -1210,6 +1190,9 @@ translateEvent(PuglView* const view, XEvent xevent)
view->impl->mapped = false;
event = makeConfigureEvent(view);
break;
+ case DestroyNotify:
+ view->impl->win = None;
+ break;
case ConfigureNotify:
event = makeConfigureEvent(view);
event.configure.width = (PuglSpan)xevent.xconfigure.width;
@@ -1533,21 +1516,11 @@ puglSendEvent(PuglView* const view, const PuglEvent* const event)
return PUGL_UNSUPPORTED;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglWaitForEvent(PuglView* const view)
-{
- XEvent xevent;
- XPeekEvent(view->world->impl->display, &xevent);
- return PUGL_SUCCESS;
-}
-#endif
-
static void
mergeExposeEvents(PuglExposeEvent* const dst, const PuglExposeEvent* const src)
{
if (!dst->type) {
- if (src->width > 0.0 && src->height > 0.0) {
+ if (src->width && src->height) {
*dst = *src;
}
} else {
@@ -1611,7 +1584,7 @@ handleSelectionNotify(const PuglWorld* const world,
Display* const display = view->world->impl->display;
const Atom selection = event->selection;
PuglX11Clipboard* const board = getX11SelectionClipboard(view, selection);
- PuglEvent puglEvent = {{PUGL_NOTHING, 0}};
+ PuglEvent puglEvent = {{PUGL_NOTHING, 0U}};
if (event->target == atoms->TARGETS) {
// Notification of available datatypes
@@ -1621,7 +1594,7 @@ handleSelectionNotify(const PuglWorld* const world,
view, event->requestor, event->property, &numFormats, &formats) &&
!setClipboardFormats(view, board, numFormats, formats)) {
const PuglDataOfferEvent offer = {
- PUGL_DATA_OFFER, 0, (double)event->time / 1e3};
+ PUGL_DATA_OFFER, 0U, (double)event->time / 1e3};
puglEvent.offer = offer;
board->acceptedFormatIndex = UINT32_MAX;
@@ -1698,8 +1671,7 @@ handleSelectionRequest(const PuglWorld* const world,
}
/// Flush pending configure and expose events for all views
-PUGL_WARN_UNUSED_RESULT
-static PuglStatus
+PUGL_WARN_UNUSED_RESULT static PuglStatus
flushExposures(PuglWorld* const world)
{
PuglStatus st0 = PUGL_SUCCESS;
@@ -1752,7 +1724,7 @@ handleTimerEvent(PuglWorld* const world, const XEvent xevent)
for (size_t i = 0; i < world->impl->numTimers; ++i) {
if (world->impl->timers[i].alarm == notify->alarm) {
- PuglEvent event = {{PUGL_TIMER, 0}};
+ PuglEvent event = {{PUGL_TIMER, 0U}};
event.timer.id = world->impl->timers[i].id;
puglDispatchEvent(world->impl->timers[i].view, &event);
}
@@ -1850,14 +1822,6 @@ dispatchX11Events(PuglWorld* const world)
return st;
}
-#ifndef PUGL_DISABLE_DEPRECATED
-PuglStatus
-puglProcessEvents(PuglView* const view)
-{
- return puglUpdate(view->world, 0.0);
-}
-#endif
-
PuglStatus
puglUpdate(PuglWorld* const world, const double timeout)
{
@@ -1868,8 +1832,9 @@ puglUpdate(PuglWorld* const world, const double timeout)
world->impl->dispatchingEvents = true;
if (timeout < 0.0) {
- st0 = pollX11Socket(world, timeout);
- st0 = st0 ? st0 : dispatchX11Events(world);
+ if (!(st0 = pollX11Socket(world, timeout))) {
+ st0 = dispatchX11Events(world);
+ }
} else if (timeout <= 0.001) {
st0 = dispatchX11Events(world);
} else {
@@ -1895,33 +1860,45 @@ double
puglGetTime(const PuglWorld* const world)
{
struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
+ return 0.0;
+ }
+
return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) -
world->startTime;
}
PuglStatus
-puglPostRedisplay(PuglView* const view)
+puglObscureView(PuglView* const view)
{
- PuglRect rect = puglGetFrame(view);
- rect.x = 0;
- rect.y = 0;
-
- return puglPostRedisplayRect(view, rect);
+ return puglObscureRegion(
+ view, 0, 0, view->lastConfigure.width, view->lastConfigure.height);
}
PuglStatus
-puglPostRedisplayRect(PuglView* const view, const PuglRect rect)
+puglObscureRegion(PuglView* const view,
+ const int x,
+ const int y,
+ const unsigned width,
+ const unsigned height)
{
- const PuglExposeEvent event = {
- PUGL_EXPOSE, 0, rect.x, rect.y, rect.width, rect.height};
+ if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ const PuglCoord cx = MAX((PuglCoord)0, (PuglCoord)x);
+ const PuglCoord cy = MAX((PuglCoord)0, (PuglCoord)y);
+ const PuglSpan cw = MIN(view->lastConfigure.width, (PuglSpan)width);
+ const PuglSpan ch = MIN(view->lastConfigure.height, (PuglSpan)height);
+
+ const PuglExposeEvent event = {PUGL_EXPOSE, 0U, cx, cy, cw, ch};
if (view->world->impl->dispatchingEvents) {
// Currently dispatching events, add/expand expose for the loop end
mergeExposeEvents(&view->impl->pendingExpose.expose, &event);
} else if (view->impl->win) {
// Not dispatching events, send an X expose so we wake up next time
- PuglEvent exposeEvent = {{PUGL_EXPOSE, 0}};
+ PuglEvent exposeEvent = {{PUGL_EXPOSE, 0U}};
exposeEvent.expose = event;
return puglSendEvent(view, &exposeEvent);
}
@@ -1975,80 +1952,54 @@ puglGetScaleFactor(const PuglView* const view)
return view->world->impl->scaleFactor;
}
-PuglStatus
-puglSetFrame(PuglView* const view, const PuglRect frame)
-{
- if (!view->impl->win) {
- // Set defaults to be used when realized
- view->defaultX = frame.x;
- view->defaultY = frame.y;
- view->sizeHints[PUGL_DEFAULT_SIZE].width = frame.width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = frame.height;
- return PUGL_SUCCESS;
- }
-
- return puglX11Status(XMoveResizeWindow(view->world->impl->display,
- view->impl->win,
- frame.x,
- frame.y,
- frame.width,
- frame.height));
-}
-
-PuglStatus
-puglSetPosition(PuglView* const view, const int x, const int y)
+static PuglStatus
+puglSetWindowPosition(PuglView* const view, const int x, const int y)
{
- Display* const display = view->world->impl->display;
-
- if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) {
- return PUGL_BAD_PARAMETER;
- }
-
- if (!view->impl->win) {
- // Set defaults to be used when realized
- view->defaultX = x;
- view->defaultY = y;
- return PUGL_SUCCESS;
- }
-
- return puglX11Status(XMoveWindow(display,
+ return puglX11Status(XMoveWindow(view->world->impl->display,
view->impl->win,
(int)(x - view->impl->frameExtentLeft),
(int)(y - view->impl->frameExtentTop)));
}
-PuglStatus
-puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+static PuglStatus
+puglSetWindowSize(PuglView* const view,
+ const unsigned width,
+ const unsigned height)
{
- Display* const display = view->world->impl->display;
+ return !view->impl->win
+ ? PUGL_SUCCESS
+ : puglX11Status(XResizeWindow(
+ view->world->impl->display, view->impl->win, width, height));
+}
- if (width > INT16_MAX || height > INT16_MAX) {
+PuglStatus
+puglSetPositionHint(PuglView* const view,
+ const PuglPositionHint hint,
+ const int x,
+ const int y)
+{
+ if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) {
return PUGL_BAD_PARAMETER;
}
- if (!view->impl->win) {
- // Set defaults to be used when realized
- view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
- view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
- return PUGL_SUCCESS;
- }
+ view->positionHints[hint].x = (PuglCoord)x;
+ view->positionHints[hint].y = (PuglCoord)y;
- return puglX11Status(XResizeWindow(display, view->impl->win, width, height));
+ return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y)
+ : PUGL_SUCCESS;
}
PuglStatus
puglSetSizeHint(PuglView* const view,
const PuglSizeHint hint,
- const PuglSpan width,
- const PuglSpan height)
+ const unsigned width,
+ const unsigned height)
{
- if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) {
- return PUGL_BAD_PARAMETER;
- }
+ const PuglStatus st = puglStoreSizeHint(view, hint, width, height);
- view->sizeHints[hint].width = width;
- view->sizeHints[hint].height = height;
- return updateSizeHints(view);
+ return st ? st
+ : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height)
+ : updateSizeHints(view);
}
PuglStatus
@@ -2194,7 +2145,7 @@ puglSetCursor(PuglView* const view, const PuglCursor cursor)
#else
(void)view;
(void)cursor;
- return PUGL_FAILURE;
+ return PUGL_UNSUPPORTED;
#endif
}
diff --git a/src/x11.h b/src/x11.h
index bc93630..da9b4f6 100644
--- a/src/x11.h
+++ b/src/x11.h
@@ -7,8 +7,8 @@
#include "attributes.h"
#include "types.h"
-#include "pugl/attributes.h"
-#include "pugl/pugl.h"
+#include <pugl/attributes.h>
+#include <pugl/pugl.h>
#include <X11/X.h>
#include <X11/Xlib.h>
@@ -93,9 +93,7 @@ struct PuglInternalsImpl {
bool mapped;
};
-PUGL_WARN_UNUSED_RESULT
-PUGL_API
-PuglStatus
+PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus
puglX11Configure(PuglView* view);
#endif // PUGL_SRC_X11_H
diff --git a/src/x11_cairo.c b/src/x11_cairo.c
index d6fbaec..bc7b133 100644
--- a/src/x11_cairo.c
+++ b/src/x11_cairo.c
@@ -5,8 +5,8 @@
#include "types.h"
#include "x11.h"
-#include "pugl/cairo.h"
-#include "pugl/pugl.h"
+#include <pugl/cairo.h>
+#include <pugl/pugl.h>
#include <cairo-xlib.h>
#include <cairo.h>
@@ -19,10 +19,10 @@ typedef struct {
cairo_t* cr;
} PuglX11CairoSurface;
-static PuglViewSize
+static PuglArea
puglX11CairoGetViewSize(const PuglView* const view)
{
- PuglViewSize size = {0U, 0U};
+ PuglArea size = {0U, 0U};
if (view->lastConfigure.type == PUGL_CONFIGURE) {
// Use the size of the last configured frame
@@ -97,11 +97,11 @@ puglX11CairoEnter(PuglView* view, const PuglExposeEvent* expose)
PuglStatus st = PUGL_SUCCESS;
if (expose) {
- const PuglViewSize viewSize = puglX11CairoGetViewSize(view);
- const PuglSpan right = (PuglSpan)(expose->x + expose->width);
- const PuglSpan bottom = (PuglSpan)(expose->y + expose->height);
- const PuglSpan surfaceWidth = MAX(right, viewSize.width);
- const PuglSpan surfaceHeight = MAX(bottom, viewSize.height);
+ const PuglArea viewSize = puglX11CairoGetViewSize(view);
+ const PuglSpan right = (PuglSpan)(expose->x + expose->width);
+ const PuglSpan bottom = (PuglSpan)(expose->y + expose->height);
+ const PuglSpan surfaceWidth = MAX(right, viewSize.width);
+ const PuglSpan surfaceHeight = MAX(bottom, viewSize.height);
if (!(st = puglX11CairoOpen(view, surfaceWidth, surfaceHeight))) {
surface->cr = cairo_create(surface->front);
if (cairo_status(surface->cr)) {
diff --git a/src/x11_gl.c b/src/x11_gl.c
index de22b34..527335b 100644
--- a/src/x11_gl.c
+++ b/src/x11_gl.c
@@ -6,8 +6,8 @@
#include "types.h"
#include "x11.h"
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <GL/glx.h>
#include <X11/X.h>
@@ -101,8 +101,7 @@ puglX11GlConfigure(PuglView* view)
return PUGL_SUCCESS;
}
-PUGL_WARN_UNUSED_RESULT
-static PuglStatus
+PUGL_WARN_UNUSED_RESULT static PuglStatus
puglX11GlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose))
{
PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface;
@@ -115,8 +114,7 @@ puglX11GlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose))
: PUGL_FAILURE;
}
-PUGL_WARN_UNUSED_RESULT
-static PuglStatus
+PUGL_WARN_UNUSED_RESULT static PuglStatus
puglX11GlLeave(PuglView* view, const PuglExposeEvent* expose)
{
Display* const display = view->world->impl->display;
diff --git a/src/x11_stub.c b/src/x11_stub.c
index 844b4db..11143fe 100644
--- a/src/x11_stub.c
+++ b/src/x11_stub.c
@@ -1,13 +1,13 @@
// Copyright 2012-2021 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-#include "pugl/stub.h"
+#include <pugl/stub.h>
#include "stub.h"
#include "types.h"
#include "x11.h"
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
const PuglBackend*
puglStubBackend(void)
diff --git a/src/x11_vulkan.c b/src/x11_vulkan.c
index 834ac37..078e524 100644
--- a/src/x11_vulkan.c
+++ b/src/x11_vulkan.c
@@ -8,8 +8,8 @@
#include "types.h"
#include "x11.h"
-#include "pugl/pugl.h"
-#include "pugl/vulkan.h"
+#include <pugl/pugl.h>
+#include <pugl/vulkan.h>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan_xlib.h>
diff --git a/test/test_utils.h b/subprojects/puglutil/include/puglutil/test_utils.h
index 214b360..6419e16 100644
--- a/test/test_utils.h
+++ b/subprojects/puglutil/include/puglutil/test_utils.h
@@ -4,7 +4,7 @@
#ifndef TEST_TEST_UTILS_H
#define TEST_TEST_UTILS_H
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <inttypes.h>
#include <stdarg.h>
@@ -471,11 +471,10 @@ static inline void
printViewHints(const PuglView* view)
{
for (unsigned i = 0; i < PUGL_NUM_VIEW_HINTS; ++i) {
- const PuglViewHint hint = (PuglViewHint)i;
fprintf(stderr,
"%s: %d\n",
- puglViewHintString(hint),
- puglGetViewHint(view, hint));
+ puglViewHintString((PuglViewHint)i),
+ puglGetViewHint(view, (PuglViewHint)i));
}
}
diff --git a/subprojects/puglutil/meson.build b/subprojects/puglutil/meson.build
new file mode 100644
index 0000000..e7ffece
--- /dev/null
+++ b/subprojects/puglutil/meson.build
@@ -0,0 +1,14 @@
+# Copyright 2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+project(
+ 'puglutil',
+ ['c'],
+ license: 'ISC',
+ meson_version: '>= 0.54.0',
+ version: '0.0.0',
+)
+
+puglutil_dep = declare_dependency(
+ include_directories: include_directories(['include']),
+)
diff --git a/test/.clang-tidy b/test/.clang-tidy
index 8ecb90f..4dbdc80 100644
--- a/test/.clang-tidy
+++ b/test/.clang-tidy
@@ -1,14 +1,13 @@
-# Copyright 2020-2023 David Robillard <d@drobilla.net>
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
- -bugprone-suspicious-include,
+ -bugprone-multi-level-implicit-pointer-conversion,
-cert-err33-c,
-cert-err34-c,
- -google-runtime-references,
+ -clang-analyzer-optin.core.EnumCastOutOfRange,
-hicpp-multiway-paths-covered,
-hicpp-signed-bitwise,
-llvm-header-guard,
- -modernize-use-trailing-return-type,
-readability-function-cognitive-complexity,
InheritParentConfig: true
diff --git a/test/cpp/.clang-tidy b/test/cpp/.clang-tidy
new file mode 100644
index 0000000..fe7d8ec
--- /dev/null
+++ b/test/cpp/.clang-tidy
@@ -0,0 +1,39 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ -*-use-auto,
+ -*-use-nullptr,
+ -bugprone-easily-swappable-parameters,
+ -bugprone-suspicious-include,
+ -cert-dcl50-cpp,
+ -cppcoreguidelines-avoid-c-arrays,
+ -cppcoreguidelines-avoid-do-while,
+ -cppcoreguidelines-macro-usage,
+ -cppcoreguidelines-no-malloc,
+ -cppcoreguidelines-owning-memory,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -cppcoreguidelines-pro-bounds-constant-array-index,
+ -cppcoreguidelines-pro-bounds-pointer-arithmetic,
+ -cppcoreguidelines-pro-type-cstyle-cast,
+ -cppcoreguidelines-pro-type-member-init,
+ -cppcoreguidelines-pro-type-union-access,
+ -cppcoreguidelines-pro-type-vararg,
+ -google-readability-casting,
+ -google-runtime-int,
+ -hicpp-avoid-c-arrays,
+ -hicpp-member-init,
+ -hicpp-named-parameter,
+ -hicpp-no-array-decay,
+ -hicpp-no-malloc,
+ -hicpp-vararg,
+ -misc-use-anonymous-namespace,
+ -modernize-avoid-c-arrays,
+ -modernize-loop-convert,
+ -modernize-loop-convert,
+ -modernize-redundant-void-arg,
+ -modernize-use-trailing-return-type,
+ -modernize-use-using,
+ -performance-enum-size,
+ -readability-named-parameter,
+InheritParentConfig: true
diff --git a/test/cpp/meson.build b/test/cpp/meson.build
new file mode 100644
index 0000000..94c64d1
--- /dev/null
+++ b/test/cpp/meson.build
@@ -0,0 +1,108 @@
+# Copyright 2021-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+test_cpp_args = []
+if get_option('warning_level') == 'everything' and is_variable('cpp')
+ if cpp.get_id() == 'clang'
+ test_cpp_args += [
+ '-Wno-documentation', # Cairo
+ '-Wno-documentation-unknown-command', # Cairo
+ '-Wno-old-style-cast',
+ ]
+ endif
+
+ test_cpp_args = cpp.get_supported_arguments(test_cpp_args)
+endif
+
+unified_args = core_args
+unified_deps = [core_deps]
+if cairo_dep.found()
+ unified_args += ['-DWITH_CAIRO']
+ unified_deps += [cairo_dep]
+endif
+
+if opengl_dep.found()
+ unified_args += ['-DWITH_OPENGL']
+ unified_deps += [opengl_dep]
+endif
+
+if vulkan_dep.found()
+ unified_args += ['-DWITH_VULKAN']
+ unified_deps += [vulkan_deps]
+endif
+
+if host_machine.system() == 'darwin'
+ add_languages(['objcpp'], native: false)
+
+ objcpp = meson.get_compiler('objcpp')
+
+ objcpp_unified_args = unified_args
+ if objcpp.get_id() == 'clang'
+ objcpp_unified_args += [
+ '-Wno-c++98-compat',
+ '-Wno-c++98-compat-pedantic',
+ '-Wno-deprecated-declarations',
+ '-Wno-direct-ivar-access',
+ ]
+ endif
+
+ objcpp_unified_args = objcpp.get_supported_arguments(objcpp_unified_args)
+
+ test(
+ 'inline_objcpp',
+ executable(
+ 'test_inline_objcpp',
+ 'test_inline_objcpp.mm',
+ dependencies: unified_deps,
+ implicit_include_directories: false,
+ include_directories: include_directories('../../include'),
+ objcpp_args: objcpp_unified_args,
+ ),
+ suite: 'unit',
+ )
+
+elif is_variable('cpp')
+ cpp_unified_args = unified_args
+ if cpp.get_id() == 'clang'
+ cpp_unified_args += [
+ '-Wno-old-style-cast',
+ '-Wno-switch-default',
+ '-Wno-switch-enum',
+ '-Wno-unused-macros', # Mac
+ ]
+ if host_machine.system() == 'windows'
+ cpp_unified_args += [
+ '-Wno-cast-function-type',
+ '-Wno-deprecated-declarations',
+ '-Wno-nonportable-system-include-path',
+ ]
+ endif
+ elif cpp.get_id() == 'gcc'
+ cpp_unified_args += [
+ '-Wno-conditionally-supported',
+ '-Wno-old-style-cast',
+ '-Wno-switch-default',
+ '-Wno-switch-enum',
+ '-Wno-useless-cast',
+ ]
+ elif cpp.get_id() == 'msvc'
+ cpp_unified_args += [
+ '/wd4464', # relative include path contains '..'
+ ]
+ endif
+
+ cpp_unified_args = cpp.get_supported_arguments(cpp_unified_args)
+
+ test(
+ 'inline_cpp',
+ executable(
+ 'test_inline_cpp',
+ 'test_inline_cpp.cpp',
+ cpp_args: cpp_unified_args,
+ dependencies: unified_deps,
+ implicit_include_directories: false,
+ include_directories: include_directories('../../include'),
+ ),
+ suite: 'unit',
+ )
+endif
diff --git a/test/cpp/test_build.cpp b/test/cpp/test_build.cpp
new file mode 100644
index 0000000..2419be9
--- /dev/null
+++ b/test/cpp/test_build.cpp
@@ -0,0 +1,16 @@
+// Copyright 2020 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+// Tests that C++ headers compile without any warnings
+
+#include <pugl/cairo.hpp> // IWYU pragma: keep
+#include <pugl/gl.hpp> // IWYU pragma: keep
+#include <pugl/pugl.h> // IWYU pragma: keep
+#include <pugl/pugl.hpp> // IWYU pragma: keep
+#include <pugl/stub.hpp> // IWYU pragma: keep
+
+int
+main()
+{
+ return 0;
+}
diff --git a/test/test_inline_cpp.cpp b/test/cpp/test_inline_cpp.cpp
index f5694eb..4c47ffb 100644
--- a/test/test_inline_cpp.cpp
+++ b/test/cpp/test_inline_cpp.cpp
@@ -23,34 +23,34 @@
# pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
-#include "../src/common.c" // IWYU pragma: keep
-#include "../src/internal.c" // IWYU pragma: keep
+#include "../../src/common.c" // IWYU pragma: keep
+#include "../../src/internal.c" // IWYU pragma: keep
#if defined(_WIN32)
-# include "../src/win.c" // IWYU pragma: keep
-# include "../src/win.h" // IWYU pragma: keep
-# include "../src/win_stub.c" // IWYU pragma: keep
+# include "../../src/win.c" // IWYU pragma: keep
+# include "../../src/win.h" // IWYU pragma: keep
+# include "../../src/win_stub.c" // IWYU pragma: keep
# if defined(WITH_CAIRO)
-# include "../src/win_cairo.c" // IWYU pragma: keep
+# include "../../src/win_cairo.c" // IWYU pragma: keep
# endif
# if defined(WITH_OPENGL)
-# include "../src/win_gl.c" // IWYU pragma: keep
+# include "../../src/win_gl.c" // IWYU pragma: keep
# endif
# if defined(WITH_VULKAN)
-# include "../src/win_vulkan.c" // IWYU pragma: keep
+# include "../../src/win_vulkan.c" // IWYU pragma: keep
# endif
#else
-# include "../src/x11.c" // IWYU pragma: keep
-# include "../src/x11_stub.c" // IWYU pragma: keep
+# include "../../src/x11.c" // IWYU pragma: keep
+# include "../../src/x11_stub.c" // IWYU pragma: keep
# if defined(WITH_CAIRO)
-# include "../src/x11_cairo.c" // IWYU pragma: keep
+# include "../../src/x11_cairo.c" // IWYU pragma: keep
# endif
# if defined(WITH_OPENGL)
-# include "../src/x11_gl.c" // IWYU pragma: keep
+# include "../../src/x11_gl.c" // IWYU pragma: keep
# endif
# if defined(WITH_VULKAN)
-# include "../src/x11_vulkan.c" // IWYU pragma: keep
+# include "../../src/x11_vulkan.c" // IWYU pragma: keep
# endif
#endif
diff --git a/test/test_inline_objcpp.mm b/test/cpp/test_inline_objcpp.mm
index 1c9079b..b4d65c6 100644
--- a/test/test_inline_objcpp.mm
+++ b/test/cpp/test_inline_objcpp.mm
@@ -9,22 +9,22 @@
# pragma clang diagnostic ignored "-Wold-style-cast"
#endif
-#include "../src/common.c" // IWYU pragma: keep
-#include "../src/internal.c" // IWYU pragma: keep
-#include "../src/mac.h" // IWYU pragma: keep
-#include "../src/mac.m" // IWYU pragma: keep
-#include "../src/mac_stub.m" // IWYU pragma: keep
+#include "../../src/common.c" // IWYU pragma: keep
+#include "../../src/internal.c" // IWYU pragma: keep
+#include "../../src/mac.h" // IWYU pragma: keep
+#include "../../src/mac.m" // IWYU pragma: keep
+#include "../../src/mac_stub.m" // IWYU pragma: keep
#if defined(WITH_CAIRO)
-# include "../src/mac_cairo.m" // IWYU pragma: keep
+# include "../../src/mac_cairo.m" // IWYU pragma: keep
#endif
#if defined(WITH_OPENGL)
-# include "../src/mac_gl.m" // IWYU pragma: keep
+# include "../../src/mac_gl.m" // IWYU pragma: keep
#endif
#if defined(WITH_VULKAN)
-# include "../src/mac_vulkan.m" // IWYU pragma: keep
+# include "../../src/mac_vulkan.m" // IWYU pragma: keep
#endif
#if defined(__clang__)
diff --git a/test/headers/.clang-tidy b/test/headers/.clang-tidy
new file mode 100644
index 0000000..7ec81cf
--- /dev/null
+++ b/test/headers/.clang-tidy
@@ -0,0 +1,16 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+Checks: >
+ *,
+ -*-magic-numbers,
+ -altera-*,
+ -llvmlibc-*,
+CheckOptions:
+ - key: readability-function-cognitive-complexity.Threshold
+ value: '0'
+ - key: readability-identifier-length.IgnoredParameterNames
+ value: '^(id)|(x)|(y)$'
+FormatStyle: file
+HeaderFilterRegex: '.*'
+WarningsAsErrors: '*'
diff --git a/test/headers/meson.build b/test/headers/meson.build
new file mode 100644
index 0000000..69fd51b
--- /dev/null
+++ b/test/headers/meson.build
@@ -0,0 +1,36 @@
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+header_c_suppressions = []
+
+if get_option('warning_level') == 'everything'
+ if cc.get_id() == 'clang'
+ if not meson.is_cross_build()
+ header_c_suppressions += ['-Wno-poison-system-directories']
+ endif
+ endif
+endif
+
+header_c_suppressions = cc.get_supported_arguments(header_c_suppressions)
+
+test_headers_c_args = header_c_suppressions
+test_headers_c_args += [
+ '-DPUGL_NO_INCLUDE_GL_H',
+ '-DPUGL_NO_INCLUDE_GLU_H',
+]
+
+if vulkan_dep.found()
+ test_headers_c_args += ['-DPUGL_TEST_VULKAN']
+endif
+
+test(
+ 'headers',
+ executable(
+ 'test_headers_c',
+ files('test_headers.c'),
+ c_args: test_headers_c_args,
+ dependencies: [pugl_dep, vulkan_dep],
+ implicit_include_directories: false,
+ ),
+ suite: 'unit',
+)
diff --git a/test/headers/test_headers.c b/test/headers/test_headers.c
new file mode 100644
index 0000000..2e109f2
--- /dev/null
+++ b/test/headers/test_headers.c
@@ -0,0 +1,22 @@
+// Copyright 2022-2025 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include <pugl/attributes.h> // IWYU pragma: keep
+#include <pugl/cairo.h> // IWYU pragma: keep
+#include <pugl/gl.h> // IWYU pragma: keep
+#include <pugl/glu.h> // IWYU pragma: keep
+#include <pugl/pugl.h> // IWYU pragma: keep
+#include <pugl/stub.h> // IWYU pragma: keep
+
+#ifdef PUGL_TEST_VULKAN
+# include <pugl/vulkan.h> // IWYU pragma: keep
+#endif
+
+#ifdef __GNUC__
+__attribute__((const))
+#endif
+int
+main(void)
+{
+ return 0;
+}
diff --git a/test/meson.build b/test/meson.build
index f8d2fd1..f047ff0 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2021-2023 David Robillard <d@drobilla.net>
+# Copyright 2021-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
# Suppress some additional C warnings in tests
@@ -17,20 +17,6 @@ if get_option('warning_level') == 'everything'
test_c_args = cc.get_supported_arguments(test_c_args)
endif
-# Suppress some additional C++ warnings in tests
-test_cpp_args = []
-if get_option('warning_level') == 'everything' and is_variable('cpp')
- if cpp.get_id() == 'clang'
- test_cpp_args += [
- '-Wno-documentation', # Cairo
- '-Wno-documentation-unknown-command', # Cairo
- '-Wno-old-style-cast',
- ]
- endif
-
- test_cpp_args = cpp.get_supported_arguments(test_cpp_args)
-endif
-
# Check licensing metadata
if not meson.is_subproject() and get_option('lint')
reuse = find_program('reuse', required: false)
@@ -39,10 +25,7 @@ if not meson.is_subproject() and get_option('lint')
endif
endif
-basic_exclusive_tests = [
- 'local_copy_paste',
- 'remote_copy_paste',
-]
+basic_exclusive_tests = []
basic_tests = [
'cursor',
@@ -53,7 +36,6 @@ basic_tests = [
'strerror',
'stub',
'stub_hints',
- 'timer',
'update',
'view',
'world',
@@ -69,10 +51,10 @@ gl_tests = [
vulkan_tests = ['vulkan']
-includes = [
- '.',
- '../include',
-]
+if with_timers
+ basic_exclusive_tests += ['local_copy_paste', 'remote_copy_paste']
+ basic_tests += ['timer']
+endif
foreach test : basic_tests
test(
@@ -81,8 +63,8 @@ foreach test : basic_tests
'test_' + test,
'test_@0@.c'.format(test),
c_args: test_c_args,
- dependencies: [pugl_dep, pugl_stub_dep],
- include_directories: include_directories(includes),
+ dependencies: [pugl_dep, pugl_stub_dep, puglutil_dep],
+ implicit_include_directories: false,
),
suite: 'unit',
)
@@ -95,8 +77,8 @@ foreach test : basic_exclusive_tests
'test_' + test,
'test_@0@.c'.format(test),
c_args: test_c_args,
- dependencies: [pugl_dep, pugl_stub_dep],
- include_directories: include_directories(includes),
+ dependencies: [pugl_dep, pugl_stub_dep, puglutil_dep],
+ implicit_include_directories: false,
),
is_parallel: false,
suite: 'unit',
@@ -111,8 +93,8 @@ if opengl_dep.found()
'test_' + test,
'test_@0@.c'.format(test),
c_args: test_c_args,
- dependencies: [pugl_dep, pugl_gl_dep],
- include_directories: include_directories(includes),
+ dependencies: [pugl_dep, pugl_gl_dep, puglutil_dep],
+ implicit_include_directories: false,
),
suite: 'unit',
)
@@ -127,8 +109,8 @@ if cairo_dep.found()
'test_' + test,
'test_@0@.c'.format(test),
c_args: test_c_args + cairo_args,
- dependencies: [pugl_dep, pugl_cairo_dep],
- include_directories: include_directories(includes),
+ dependencies: [pugl_dep, pugl_cairo_dep, puglutil_dep],
+ implicit_include_directories: false,
),
suite: 'unit',
)
@@ -143,94 +125,24 @@ if vulkan_dep.found()
'test_' + test,
'test_@0@.c'.format(test),
c_args: test_c_args,
- cpp_args: test_cpp_args,
- dependencies: [pugl_dep, pugl_vulkan_dep],
- include_directories: include_directories(includes),
+ dependencies: [pugl_dep, pugl_vulkan_dep, puglutil_dep],
+ implicit_include_directories: false,
),
suite: 'unit',
)
endforeach
endif
-unified_args = []
-unified_deps = [core_deps]
-if cairo_dep.found()
- unified_args += ['-DWITH_CAIRO']
- unified_deps += [cairo_dep]
-endif
+###################
+# Header Warnings #
+###################
-if opengl_dep.found()
- unified_args += ['-DWITH_OPENGL']
- unified_deps += [opengl_dep]
-endif
-
-if vulkan_dep.found()
- unified_args += ['-DWITH_VULKAN']
- unified_deps += [vulkan_deps]
-endif
+subdir('headers')
-if host_machine.system() == 'darwin'
- add_languages(['objcpp'], native: false)
-
- objcpp = meson.get_compiler('objcpp')
-
- objcpp_args = []
- if objcpp.get_id() == 'clang'
- objcpp_args += [
- '-Wno-c++98-compat',
- '-Wno-c++98-compat-pedantic',
- '-Wno-deprecated-declarations',
- '-Wno-direct-ivar-access',
- ]
- endif
+#######################
+# C++ / Objective C++ #
+#######################
- unified_args += objcpp.get_supported_arguments(test_cpp_args + objcpp_args)
-
- test(
- 'inline_objcpp',
- executable(
- 'test_inline_objcpp',
- 'test_inline_objcpp.mm',
- dependencies: unified_deps,
- include_directories: include_directories(includes),
- objcpp_args: unified_args,
- ),
- suite: 'unit',
- )
-
-elif is_variable('cpp')
- unified_args = []
-
- if cpp.get_id() == 'clang'
- unified_args += [
- '-Wno-old-style-cast',
- '-Wno-switch-default',
- '-Wno-switch-enum',
- '-Wno-unused-macros', # Mac
- ]
- elif cpp.get_id() == 'gcc'
- unified_args += [
- '-Wno-conditionally-supported',
- '-Wno-old-style-cast',
- '-Wno-switch-default',
- '-Wno-switch-enum',
- '-Wno-useless-cast',
- ]
- elif cpp.get_id() == 'msvc'
- unified_args += [
- '/wd4464', # relative include path contains '..'
- ]
- endif
-
- test(
- 'inline_cpp',
- executable(
- 'test_inline_cpp',
- 'test_inline_cpp.cpp',
- cpp_args: test_cpp_args + unified_args,
- dependencies: unified_deps,
- include_directories: include_directories(includes),
- ),
- suite: 'unit',
- )
+if is_variable('cpp')
+ subdir('cpp')
endif
diff --git a/test/test_build.c b/test/test_build.c
index e28df3c..4f66eca 100644
--- a/test/test_build.c
+++ b/test/test_build.c
@@ -1,17 +1,13 @@
// Copyright 2020 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-/*
- Tests that C headers compile without any warnings.
-*/
+// Tests that C headers compile without any warnings
-#define PUGL_DISABLE_DEPRECATED
-
-#include "pugl/cairo.h" // IWYU pragma: keep
-#include "pugl/gl.h" // IWYU pragma: keep
-#include "pugl/glu.h" // IWYU pragma: keep
-#include "pugl/pugl.h" // IWYU pragma: keep
-#include "pugl/stub.h" // IWYU pragma: keep
+#include <pugl/cairo.h> // IWYU pragma: keep
+#include <pugl/gl.h> // IWYU pragma: keep
+#include <pugl/glu.h> // IWYU pragma: keep
+#include <pugl/pugl.h> // IWYU pragma: keep
+#include <pugl/stub.h> // IWYU pragma: keep
int
main(void)
diff --git a/test/test_build.cpp b/test/test_build.cpp
deleted file mode 100644
index 4fd2dac..0000000
--- a/test/test_build.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2020 David Robillard <d@drobilla.net>
-// SPDX-License-Identifier: ISC
-
-/*
- Tests that C++ headers compile without any warnings.
-*/
-
-#define PUGL_DISABLE_DEPRECATED
-
-#include "pugl/cairo.hpp" // IWYU pragma: keep
-#include "pugl/gl.hpp" // IWYU pragma: keep
-#include "pugl/pugl.h" // IWYU pragma: keep
-#include "pugl/pugl.hpp" // IWYU pragma: keep
-#include "pugl/stub.hpp" // IWYU pragma: keep
-
-int
-main()
-{
- return 0;
-}
diff --git a/test/test_cairo.c b/test/test_cairo.c
index 11d6cce..9abc51e 100644
--- a/test/test_cairo.c
+++ b/test/test_cairo.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/cairo.h"
-#include "pugl/pugl.h"
+#include <pugl/cairo.h>
+#include <pugl/pugl.h>
#include <cairo.h>
@@ -66,7 +66,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglCairoBackend());
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 128, 896);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 128, 896);
puglShow(test.view, PUGL_SHOW_RAISE);
// Drive event loop until the view gets exposed
diff --git a/test/test_clipboard.c b/test/test_clipboard.c
index debe8e3..054f71d 100644
--- a/test/test_clipboard.c
+++ b/test/test_clipboard.c
@@ -9,8 +9,8 @@
#include "test_utils.h"
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
diff --git a/test/test_cursor.c b/test/test_cursor.c
index 11a52d7..399f797 100644
--- a/test/test_cursor.c
+++ b/test/test_cursor.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -52,7 +52,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglStubBackend());
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 896, 640);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 896, 640);
puglShow(test.view, PUGL_SHOW_RAISE);
// Drive event loop until the view gets exposed
@@ -63,7 +63,9 @@ main(int argc, char** argv)
// Change the cursor, updating each time
assert(puglSetCursor(test.view, (PuglCursor)-1));
for (unsigned i = 0; i < (unsigned)PUGL_CURSOR_ALL_SCROLL; ++i) {
- assert(!puglSetCursor(test.view, (PuglCursor)i));
+ const PuglStatus st = puglSetCursor(test.view, (PuglCursor)i);
+
+ assert(!st || st == PUGL_UNSUPPORTED);
assert(!puglUpdate(test.world, 0.1));
}
diff --git a/test/test_gl.c b/test/test_gl.c
index 8854cad..dac41b5 100644
--- a/test/test_gl.c
+++ b/test/test_gl.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <assert.h>
#include <stdbool.h>
@@ -85,7 +85,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglGlBackend());
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 384, 896);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 384, 896);
puglShow(test.view, PUGL_SHOW_RAISE);
// Enter OpenGL context as if setting things up
diff --git a/test/test_gl_free_unrealized.c b/test/test_gl_free_unrealized.c
index 82fc18b..7ff8913 100644
--- a/test/test_gl_free_unrealized.c
+++ b/test/test_gl_free_unrealized.c
@@ -1,4 +1,4 @@
-// Copyright 2022 David Robillard <d@drobilla.net>
+// Copyright 2022-2024 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
/*
@@ -9,25 +9,21 @@
#undef NDEBUG
-#include "test_utils.h"
-
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <assert.h>
#include <stddef.h>
typedef struct {
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
+ PuglWorld* world;
+ PuglView* view;
} PuglTest;
int
-main(int argc, char** argv)
+main(void)
{
- PuglTest test = {
- puglNewWorld(PUGL_PROGRAM, 0), NULL, puglParseTestOptions(&argc, &argv)};
+ PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0), NULL};
// Set up view
test.view = puglNewView(test.world);
@@ -36,7 +32,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglGlBackend());
puglSetHandle(test.view, &test);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 640, 896);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 640, 896);
assert(!puglGetVisible(test.view));
diff --git a/test/test_gl_hints.c b/test/test_gl_hints.c
index 16b51c5..824679a 100644
--- a/test/test_gl_hints.c
+++ b/test/test_gl_hints.c
@@ -1,16 +1,14 @@
// Copyright 2020 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-/*
- Tests that all hints are set to real values after a view is realized.
-*/
+// Tests that all hints are set to real values after a view is realized
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/gl.h"
-#include "pugl/pugl.h"
+#include <pugl/gl.h>
+#include <pugl/pugl.h>
#include <assert.h>
@@ -35,7 +33,7 @@ main(void)
puglSetBackend(view, puglGlBackend());
puglSetEventFunc(view, onEvent);
puglSetSizeHint(view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(view, 128, 128);
+ puglSetPositionHint(view, PUGL_DEFAULT_POSITION, 128, 128);
// Check invalid cases
assert(puglSetViewHint(view, PUGL_CONTEXT_API, PUGL_DONT_CARE) ==
@@ -85,7 +83,8 @@ main(void)
assert(puglGetViewHint(view, PUGL_SWAP_INTERVAL) != PUGL_DONT_CARE);
assert(puglGetViewHint(view, PUGL_RESIZABLE) != PUGL_DONT_CARE);
assert(puglGetViewHint(view, PUGL_IGNORE_KEY_REPEAT) != PUGL_DONT_CARE);
- assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_REFRESH_RATE) == PUGL_DONT_CARE ||
+ puglGetViewHint(view, PUGL_REFRESH_RATE) > 0);
// Tear down
puglFreeView(view);
diff --git a/test/test_local_copy_paste.c b/test/test_local_copy_paste.c
index 737f193..6d4899e 100644
--- a/test/test_local_copy_paste.c
+++ b/test/test_local_copy_paste.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -133,7 +133,7 @@ main(int argc, char** argv)
puglSetHandle(app.view, &app);
puglSetEventFunc(app.view, onEvent);
puglSetSizeHint(app.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(app.view, 384, 128);
+ puglSetPositionHint(app.view, PUGL_DEFAULT_POSITION, 384, 128);
// Create and show window
assert(!puglRealize(app.view));
diff --git a/test/test_realize.c b/test/test_realize.c
index 7e37319..3d706ce 100644
--- a/test/test_realize.c
+++ b/test/test_realize.c
@@ -11,10 +11,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -75,7 +75,7 @@ main(int argc, char** argv)
assert(puglRealize(test.view) == PUGL_BAD_CONFIGURATION);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 640, 128);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 640, 128);
// Create initially invisible window
assert(!puglRealize(test.view));
diff --git a/test/test_redisplay.c b/test/test_redisplay.c
index 1276136..01be5b6 100644
--- a/test/test_redisplay.c
+++ b/test/test_redisplay.c
@@ -8,10 +8,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -51,8 +51,11 @@ typedef struct {
State state;
} PuglTest;
-static const PuglRect redisplayRect = {2, 4, 8, 16};
-static const uintptr_t postRedisplayId = 42;
+static const PuglCoord obscureX = 2;
+static const PuglCoord obscureY = 4;
+static const PuglSpan obscureWidth = 8;
+static const PuglSpan obscureHeight = 16;
+static const uintptr_t obscureId = 42;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
@@ -67,7 +70,7 @@ onEvent(PuglView* view, const PuglEvent* event)
switch (event->type) {
case PUGL_UPDATE:
if (test->state == SHOULD_REDISPLAY) {
- puglPostRedisplayRect(view, redisplayRect);
+ puglObscureRegion(view, obscureX, obscureY, obscureWidth, obscureHeight);
test->state = POSTED_REDISPLAY;
}
break;
@@ -75,13 +78,12 @@ onEvent(PuglView* view, const PuglEvent* event)
case PUGL_EXPOSE:
if (test->state == START) {
test->state = EXPOSED;
- } else if (test->state == POSTED_REDISPLAY &&
- event->expose.x <= redisplayRect.x &&
- event->expose.y <= redisplayRect.y &&
+ } else if (test->state == POSTED_REDISPLAY && event->expose.x <= obscureX &&
+ event->expose.y <= obscureY &&
(event->expose.x + event->expose.width >=
- redisplayRect.x + redisplayRect.width) &&
+ obscureX + obscureWidth) &&
(event->expose.y + event->expose.height >=
- redisplayRect.y + redisplayRect.height)) {
+ obscureY + obscureHeight)) {
test->state = REDISPLAYED;
} else if (test->state == REDISPLAYED) {
test->state = REREDISPLAYED;
@@ -89,7 +91,7 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_CLIENT:
- if (event->client.data1 == postRedisplayId) {
+ if (event->client.data1 == obscureId) {
test->state = SHOULD_REDISPLAY;
}
break;
@@ -117,7 +119,7 @@ main(int argc, char** argv)
puglSetHandle(test.view, &test);
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 896, 128);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 896, 128);
// Create and show window
assert(!puglRealize(test.view));
@@ -127,8 +129,8 @@ main(int argc, char** argv)
}
// Send a custom event to trigger a redisplay in the event loop
- PuglEvent client_event = {{PUGL_CLIENT, 0}};
- client_event.client.data1 = postRedisplayId;
+ PuglEvent client_event = {{PUGL_CLIENT, 0U}};
+ client_event.client.data1 = obscureId;
client_event.client.data2 = 0;
assert(!puglSendEvent(test.view, &client_event));
@@ -140,7 +142,7 @@ main(int argc, char** argv)
}
// Redisplay from outside the event handler
- puglPostRedisplay(test.view);
+ puglObscureView(test.view);
while (test.state != REREDISPLAYED) {
assert(!puglUpdate(test.world, timeout));
}
diff --git a/test/test_remote_copy_paste.c b/test/test_remote_copy_paste.c
index a9f079e..3d1756b 100644
--- a/test/test_remote_copy_paste.c
+++ b/test/test_remote_copy_paste.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -148,7 +148,7 @@ main(int argc, char** argv)
puglSetHandle(app.copierView, &app);
puglSetEventFunc(app.copierView, onCopierEvent);
puglSetSizeHint(app.copierView, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(app.copierView, 640, 896);
+ puglSetPositionHint(app.copierView, PUGL_DEFAULT_POSITION, 640, 896);
// Set up paster view
app.pasterView = puglNewView(app.world);
@@ -158,7 +158,7 @@ main(int argc, char** argv)
puglSetHandle(app.pasterView, &app);
puglSetEventFunc(app.pasterView, onPasterEvent);
puglSetSizeHint(app.pasterView, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(app.pasterView, 896, 896);
+ puglSetPositionHint(app.pasterView, PUGL_DEFAULT_POSITION, 896, 896);
// Create and show both views
assert(!puglShow(app.copierView, PUGL_SHOW_RAISE));
diff --git a/test/test_show_hide.c b/test/test_show_hide.c
index 1517203..8b67325 100644
--- a/test/test_show_hide.c
+++ b/test/test_show_hide.c
@@ -8,10 +8,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -115,7 +115,7 @@ main(int argc, char** argv)
puglSetHandle(test.view, &test);
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 128, 384);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 128, 384);
// Create initially invisible window
assert(!puglRealize(test.view));
diff --git a/test/test_size.c b/test/test_size.c
index e3f738a..9c9f518 100644
--- a/test/test_size.c
+++ b/test/test_size.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -26,7 +26,8 @@ typedef struct {
PuglView* view;
PuglTestOptions opts;
State state;
- PuglRect configuredFrame;
+ PuglPoint configuredPos;
+ PuglArea configuredSize;
} PuglTest;
static PuglStatus
@@ -47,10 +48,10 @@ onEvent(PuglView* view, const PuglEvent* event)
if (test->state == REALIZED) {
test->state = CONFIGURED;
}
- test->configuredFrame.x = event->configure.x;
- test->configuredFrame.y = event->configure.y;
- test->configuredFrame.width = event->configure.width;
- test->configuredFrame.height = event->configure.height;
+ test->configuredPos.x = event->configure.x;
+ test->configuredPos.y = event->configure.y;
+ test->configuredSize.width = event->configure.width;
+ test->configuredSize.height = event->configure.height;
break;
case PUGL_UNREALIZE:
test->state = UNREALIZED;
@@ -73,7 +74,8 @@ main(int argc, char** argv)
NULL,
puglParseTestOptions(&argc, &argv),
START,
- {0, 0, 0U, 0U}};
+ {0, 0},
+ {0U, 0U}};
// Set up view with size bounds and an aspect ratio
test.view = puglNewView(test.world);
@@ -87,7 +89,7 @@ main(int argc, char** argv)
puglSetSizeHint(test.view, PUGL_MIN_SIZE, minSize, minSize);
puglSetSizeHint(test.view, PUGL_MAX_SIZE, maxSize, maxSize);
puglSetSizeHint(test.view, PUGL_FIXED_ASPECT, 1, 1);
- puglSetPosition(test.view, 384, 384);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 384, 384);
// Create and show window
assert(!puglRealize(test.view));
@@ -97,21 +99,22 @@ main(int argc, char** argv)
}
// Check that the frame matches the last configure event
- const PuglRect frame = puglGetFrame(test.view);
- assert(frame.x == test.configuredFrame.x);
- assert(frame.y == test.configuredFrame.y);
- assert(frame.width == test.configuredFrame.width);
- assert(frame.height == test.configuredFrame.height);
+ const PuglPoint pos = puglGetPositionHint(test.view, PUGL_CURRENT_POSITION);
+ const PuglArea size = puglGetSizeHint(test.view, PUGL_CURRENT_SIZE);
+ assert(pos.x == test.configuredPos.x);
+ assert(pos.y == test.configuredPos.y);
+ assert(size.width == test.configuredSize.width);
+ assert(size.height == test.configuredSize.height);
#if defined(_WIN32) || defined(__APPLE__)
/* Some window managers on Linux (particularly tiling ones) just disregard
these hints entirely, so we only check that the size is in bounds on MacOS
and Windows where this is more or less universally supported. */
- assert(frame.width >= minSize);
- assert(frame.height >= minSize);
- assert(frame.width <= maxSize);
- assert(frame.height <= maxSize);
+ assert(size.width >= minSize);
+ assert(size.height >= minSize);
+ assert(size.width <= maxSize);
+ assert(size.height <= maxSize);
#endif
// Tear down
diff --git a/test/test_strerror.c b/test/test_strerror.c
index c120a93..4bce4eb 100644
--- a/test/test_strerror.c
+++ b/test/test_strerror.c
@@ -5,7 +5,7 @@
#undef NDEBUG
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <assert.h>
#include <ctype.h>
diff --git a/test/test_stub.c b/test/test_stub.c
index bd8a0eb..7913fd4 100644
--- a/test/test_stub.c
+++ b/test/test_stub.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -52,7 +52,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglStubBackend());
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 384, 896);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 384, 896);
puglShow(test.view, PUGL_SHOW_RAISE);
// Drive event loop until the view gets exposed
diff --git a/test/test_stub_hints.c b/test/test_stub_hints.c
index 4c9d0c4..5694261 100644
--- a/test/test_stub_hints.c
+++ b/test/test_stub_hints.c
@@ -1,16 +1,14 @@
// Copyright 2020 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-/*
- Tests that all hints are set to real values after a view is realized.
-*/
+// Tests that all hints are set to real values after a view is realized
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
@@ -35,7 +33,7 @@ main(void)
puglSetBackend(view, puglStubBackend());
puglSetEventFunc(view, onEvent);
puglSetSizeHint(view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(view, 640, 384);
+ puglSetPositionHint(view, PUGL_DEFAULT_POSITION, 640, 384);
// Check invalid cases
assert(puglSetViewHint(view, (PuglViewHint)-1, 0) == PUGL_BAD_PARAMETER);
@@ -77,7 +75,8 @@ main(void)
assert(puglGetViewHint(view, PUGL_ALPHA_BITS) != PUGL_DONT_CARE);
assert(puglGetViewHint(view, PUGL_RESIZABLE) != PUGL_DONT_CARE);
assert(puglGetViewHint(view, PUGL_IGNORE_KEY_REPEAT) != PUGL_DONT_CARE);
- assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_REFRESH_RATE) == PUGL_DONT_CARE ||
+ puglGetViewHint(view, PUGL_REFRESH_RATE) > 0);
// Tear down
puglFreeView(view);
diff --git a/test/test_timer.c b/test/test_timer.c
index 1c9f281..8015b9a 100644
--- a/test/test_timer.c
+++ b/test/test_timer.c
@@ -8,10 +8,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <math.h>
@@ -19,7 +19,7 @@
#include <stdint.h>
#include <stdio.h>
-#define NUM_TIMERS 4U // NOLINT(modernize-macro-to-enum)
+#define NUM_TIMERS 4U // NOLINT(*-macro-to-enum)
#ifdef __APPLE__
static const double timeout = 1 / 60.0;
@@ -157,7 +157,7 @@ main(int argc, char** argv)
puglSetHandle(test.view, &test);
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 896, 384);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 896, 384);
// Create and show window
assert(!puglRealize(test.view));
diff --git a/test/test_update.c b/test/test_update.c
index 4710ca2..c078e6b 100644
--- a/test/test_update.c
+++ b/test/test_update.c
@@ -8,10 +8,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -63,7 +63,7 @@ onEvent(PuglView* view, const PuglEvent* event)
case PUGL_UPDATE:
if (test->state == EXPOSED1) {
test->state = UPDATED;
- puglPostRedisplay(view);
+ puglObscureView(view);
}
break;
@@ -90,7 +90,7 @@ main(int argc, char** argv)
puglSetHandle(test.view, &test);
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 128, 640);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 128, 640);
// Create and show window
assert(!puglRealize(test.view));
diff --git a/test/test_view.c b/test/test_view.c
index a6af9f2..08e5255 100644
--- a/test/test_view.c
+++ b/test/test_view.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/stub.h"
+#include <pugl/pugl.h>
+#include <pugl/stub.h>
#include <assert.h>
#include <stdbool.h>
@@ -73,7 +73,7 @@ main(int argc, char** argv)
puglSetHandle(test.view, &test);
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 384, 640);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 384, 640);
// Check basic accessors
assert(puglGetBackend(test.view) == puglStubBackend());
diff --git a/test/test_vulkan.c b/test/test_vulkan.c
index 3a7c612..258f978 100644
--- a/test/test_vulkan.c
+++ b/test/test_vulkan.c
@@ -5,10 +5,10 @@
#undef NDEBUG
-#include "test_utils.h"
+#include <puglutil/test_utils.h>
-#include "pugl/pugl.h"
-#include "pugl/vulkan.h"
+#include <pugl/pugl.h>
+#include <pugl/vulkan.h>
#include <vulkan/vulkan_core.h>
@@ -172,7 +172,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglVulkanBackend());
puglSetEventFunc(test.view, onEvent);
puglSetSizeHint(test.view, PUGL_DEFAULT_SIZE, 256, 256);
- puglSetPosition(test.view, 640, 640);
+ puglSetPositionHint(test.view, PUGL_DEFAULT_POSITION, 640, 640);
assert(!puglRealize(test.view));
// Create Vulkan surface for window
diff --git a/test/test_world.c b/test/test_world.c
index 18c8ef2..9d0d145 100644
--- a/test/test_world.c
+++ b/test/test_world.c
@@ -5,7 +5,7 @@
#undef NDEBUG
-#include "pugl/pugl.h"
+#include <pugl/pugl.h>
#include <assert.h>
#include <stdint.h>