diff options
author | David Robillard <d@drobilla.net> | 2022-06-05 20:24:51 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-06-08 19:48:13 -0400 |
commit | 27ce10b5039e931eaad33e9499a630552d4e1f06 (patch) | |
tree | 9ad33d28562935d72f768e68e9d24531b6059d8a /src/common.c | |
parent | bb0fe3975df149eb45a21e39940f71e2273c8fd5 (diff) | |
download | pugl-27ce10b5039e931eaad33e9499a630552d4e1f06.tar.gz pugl-27ce10b5039e931eaad33e9499a630552d4e1f06.tar.bz2 pugl-27ce10b5039e931eaad33e9499a630552d4e1f06.zip |
Separate private and public function implementations
Diffstat (limited to 'src/common.c')
-rw-r--r-- | src/common.c | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..313f0d0 --- /dev/null +++ b/src/common.c @@ -0,0 +1,294 @@ +// Copyright 2012-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include "internal.h" + +#include "types.h" + +#include "pugl/pugl.h" + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +const char* +puglStrerror(const PuglStatus status) +{ + // clang-format off + switch (status) { + case PUGL_SUCCESS: return "Success"; + case PUGL_FAILURE: return "Non-fatal failure"; + case PUGL_UNKNOWN_ERROR: return "Unknown system error"; + case PUGL_BAD_BACKEND: return "Invalid or missing backend"; + case PUGL_BAD_CONFIGURATION: return "Invalid view configuration"; + case PUGL_BAD_PARAMETER: return "Invalid parameter"; + case PUGL_BACKEND_FAILED: return "Backend initialisation failed"; + case PUGL_REGISTRATION_FAILED: return "Class registration failed"; + case PUGL_REALIZE_FAILED: return "View creation failed"; + case PUGL_SET_FORMAT_FAILED: return "Failed to set pixel format"; + case PUGL_CREATE_CONTEXT_FAILED: return "Failed to create drawing context"; + case PUGL_UNSUPPORTED: return "Unsupported operation"; + case PUGL_NO_MEMORY: return "Failed to allocate memory"; + } + // clang-format on + + return "Unknown error"; +} + +PuglWorld* +puglNewWorld(PuglWorldType type, PuglWorldFlags flags) +{ + PuglWorld* world = (PuglWorld*)calloc(1, sizeof(PuglWorld)); + if (!world || !(world->impl = puglInitWorldInternals(type, flags))) { + free(world); + return NULL; + } + + world->startTime = puglGetTime(world); + + puglSetString(&world->className, "Pugl"); + + return world; +} + +void +puglFreeWorld(PuglWorld* const world) +{ + puglFreeWorldInternals(world); + free(world->className); + free(world->views); + free(world); +} + +void +puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle) +{ + world->handle = handle; +} + +PuglWorldHandle +puglGetWorldHandle(PuglWorld* world) +{ + return world->handle; +} + +PuglStatus +puglSetClassName(PuglWorld* const world, const char* const name) +{ + puglSetString(&world->className, name); + return PUGL_SUCCESS; +} + +const char* +puglGetClassName(const PuglWorld* world) +{ + return world->className; +} + +static void +puglSetDefaultHints(PuglHints hints) +{ + hints[PUGL_USE_COMPAT_PROFILE] = PUGL_TRUE; + hints[PUGL_CONTEXT_VERSION_MAJOR] = 2; + hints[PUGL_CONTEXT_VERSION_MINOR] = 0; + 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_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; +} + +PuglView* +puglNewView(PuglWorld* const world) +{ + PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); + if (!view || !(view->impl = puglInitViewInternals(world))) { + free(view); + return NULL; + } + + view->world = world; + view->sizeHints[PUGL_MIN_SIZE].width = 1; + view->sizeHints[PUGL_MIN_SIZE].height = 1; + + puglSetDefaultHints(view->hints); + + // Add to world view list + ++world->numViews; + world->views = + (PuglView**)realloc(world->views, world->numViews * sizeof(PuglView*)); + + world->views[world->numViews - 1] = view; + + return view; +} + +void +puglFreeView(PuglView* view) +{ + if (view->eventFunc && view->backend) { + puglDispatchSimpleEvent(view, PUGL_DESTROY); + } + + // Remove from world view list + PuglWorld* world = view->world; + for (size_t i = 0; i < world->numViews; ++i) { + if (world->views[i] == view) { + if (i == world->numViews - 1) { + world->views[i] = NULL; + } else { + memmove(world->views + i, + world->views + i + 1, + sizeof(PuglView*) * (world->numViews - i - 1)); + world->views[world->numViews - 1] = NULL; + } + --world->numViews; + } + } + + free(view->title); + puglFreeViewInternals(view); + free(view); +} + +PuglWorld* +puglGetWorld(PuglView* view) +{ + return view->world; +} + +void +puglSetHandle(PuglView* view, PuglHandle handle) +{ + view->handle = handle; +} + +PuglHandle +puglGetHandle(PuglView* view) +{ + return view->handle; +} + +PuglStatus +puglSetBackend(PuglView* view, const PuglBackend* backend) +{ + view->backend = backend; + return PUGL_SUCCESS; +} + +const PuglBackend* +puglGetBackend(const PuglView* view) +{ + return view->backend; +} + +PuglStatus +puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc) +{ + view->eventFunc = eventFunc; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetViewHint(PuglView* view, PuglViewHint hint, int value) +{ + if (value == PUGL_DONT_CARE) { + switch (hint) { + case PUGL_USE_COMPAT_PROFILE: + case PUGL_USE_DEBUG_CONTEXT: + case PUGL_CONTEXT_VERSION_MAJOR: + case PUGL_CONTEXT_VERSION_MINOR: + case PUGL_SWAP_INTERVAL: + return PUGL_BAD_PARAMETER; + default: + break; + } + } + + view->hints[hint] = value; + return PUGL_SUCCESS; +} + +int +puglGetViewHint(const PuglView* view, PuglViewHint hint) +{ + return view->hints[hint]; +} + +PuglRect +puglGetFrame(const PuglView* view) +{ + return view->frame; +} + +const char* +puglGetWindowTitle(const PuglView* const view) +{ + return view->title; +} + +PuglStatus +puglSetParentWindow(PuglView* view, PuglNativeView parent) +{ + view->parent = parent; + return PUGL_SUCCESS; +} + +PuglNativeView +puglGetParentWindow(const PuglView* const view) +{ + return view->parent; +} + +PuglNativeView +puglGetTransientParent(const PuglView* const view) +{ + return view->transientParent; +} + +bool +puglGetVisible(const PuglView* view) +{ + return view->visible; +} + +void* +puglGetContext(PuglView* view) +{ + return view->backend->getContext(view); +} + +#ifndef PUGL_DISABLE_DEPRECATED + +PuglStatus +puglPollEvents(PuglWorld* world, double timeout) +{ + return puglUpdate(world, timeout); +} + +PuglStatus +puglDispatchEvents(PuglWorld* world) +{ + return puglUpdate(world, 0.0); +} + +PuglStatus +puglShowWindow(PuglView* view) +{ + return puglShow(view); +} + +PuglStatus +puglHideWindow(PuglView* view) +{ + return puglHide(view); +} + +#endif |