aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-01-12 10:30:10 -0500
committerDavid Robillard <d@drobilla.net>2023-01-14 11:53:28 -0500
commitbd4f79646f623e929e6aa22bea028952b515aeef (patch)
treee2dcc2635bb2b12b9c552755b35a0343005ce88a /src
parent786a28e4a2bc9fce95a8d2e6cd1a4c76d2ae1a0f (diff)
downloadpugl-bd4f79646f623e929e6aa22bea028952b515aeef.tar.gz
pugl-bd4f79646f623e929e6aa22bea028952b515aeef.tar.bz2
pugl-bd4f79646f623e929e6aa22bea028952b515aeef.zip
Add general string hint interface
This replaces the window title and class name APIs with a more general one that can be easily extended to other things, like icon names, more detailed application hints, and so on.
Diffstat (limited to 'src')
-rw-r--r--src/common.c60
-rw-r--r--src/internal.c17
-rw-r--r--src/internal.h5
-rw-r--r--src/mac.m34
-rw-r--r--src/types.h4
-rw-r--r--src/win.c34
-rw-r--r--src/x11.c30
7 files changed, 133 insertions, 51 deletions
diff --git a/src/common.c b/src/common.c
index 7113461..eafb07a 100644
--- a/src/common.c
+++ b/src/common.c
@@ -52,7 +52,7 @@ puglNewWorld(PuglWorldType type, PuglWorldFlags flags)
world->startTime = puglGetTime(world);
world->type = type;
- puglSetString(&world->className, "Pugl");
+ puglSetString(&world->strings[PUGL_CLASS_NAME], "Pugl");
return world;
}
@@ -61,7 +61,11 @@ void
puglFreeWorld(PuglWorld* const world)
{
puglFreeWorldInternals(world);
- free(world->className);
+
+ for (size_t i = 0; i < PUGL_NUM_STRING_HINTS; ++i) {
+ free(world->strings[i]);
+ }
+
free(world->views);
free(world);
}
@@ -79,16 +83,26 @@ puglGetWorldHandle(PuglWorld* world)
}
PuglStatus
-puglSetClassName(PuglWorld* const world, const char* const name)
+puglSetWorldString(PuglWorld* const world,
+ const PuglStringHint key,
+ const char* const value)
{
- puglSetString(&world->className, name);
+ if ((unsigned)key < 0 || (unsigned)key >= PUGL_NUM_STRING_HINTS) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ puglSetString(&world->strings[key], value);
return PUGL_SUCCESS;
}
const char*
-puglGetClassName(const PuglWorld* world)
+puglGetWorldString(const PuglWorld* const world, const PuglStringHint key)
{
- return world->className;
+ if ((unsigned)key < 0 || (unsigned)key >= PUGL_NUM_STRING_HINTS) {
+ return NULL;
+ }
+
+ return world->strings[key];
}
static void
@@ -161,7 +175,10 @@ puglFreeView(PuglView* view)
}
}
- free(view->title);
+ for (size_t i = 0; i < PUGL_NUM_STRING_HINTS; ++i) {
+ free(view->strings[i]);
+ }
+
puglFreeViewInternals(view);
free(view);
}
@@ -239,6 +256,29 @@ puglGetViewHint(const PuglView* view, PuglViewHint hint)
return PUGL_DONT_CARE;
}
+PuglStatus
+puglSetViewString(PuglView* const view,
+ const PuglStringHint key,
+ const char* const value)
+{
+ if ((unsigned)key < 0 || (unsigned)key >= PUGL_NUM_STRING_HINTS) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ puglSetString(&view->strings[key], value);
+ return puglViewStringChanged(view, key, view->strings[key]);
+}
+
+const char*
+puglGetViewString(const PuglView* const view, const PuglStringHint key)
+{
+ if ((unsigned)key < 0 || (unsigned)key >= PUGL_NUM_STRING_HINTS) {
+ return NULL;
+ }
+
+ return view->strings[key];
+}
+
PuglRect
puglGetFrame(const PuglView* view)
{
@@ -267,12 +307,6 @@ puglGetFrame(const PuglView* view)
return frame;
}
-const char*
-puglGetWindowTitle(const PuglView* const view)
-{
- return view->title;
-}
-
PuglStatus
puglSetParentWindow(PuglView* view, PuglNativeView parent)
{
diff --git a/src/internal.c b/src/internal.c
index c607fa7..06bf416 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -47,6 +47,10 @@ puglSetBlob(PuglBlob* const dest, const void* const data, const size_t len)
void
puglSetString(char** dest, const char* string)
{
+ if (*dest == string) {
+ return;
+ }
+
const size_t len = string ? strlen(string) : 0U;
if (!len) {
@@ -58,6 +62,19 @@ puglSetString(char** dest, const char* string)
}
}
+PuglStatus
+puglStoreViewString(PuglView* const view,
+ const PuglStringHint key,
+ const char* const value)
+{
+ if ((unsigned)key >= 0 && (unsigned)key < PUGL_NUM_STRING_HINTS) {
+ puglSetString(&view->strings[key], value);
+ return PUGL_SUCCESS;
+ }
+
+ return PUGL_BAD_PARAMETER;
+}
+
uint32_t
puglDecodeUTF8(const uint8_t* buf)
{
diff --git a/src/internal.h b/src/internal.h
index 6400422..f30532b 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -29,6 +29,11 @@ puglSetBlob(PuglBlob* dest, const void* data, size_t len);
void
puglSetString(char** dest, const char* string);
+/// Handle a changed string property
+PUGL_API
+PuglStatus
+puglViewStringChanged(PuglView* view, PuglStringHint key, const char* value);
+
/// Return the Unicode code point for `buf` or the replacement character
uint32_t
puglDecodeUTF8(const uint8_t* buf);
diff --git a/src/mac.m b/src/mac.m
index 945063a..a0b2017 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -1286,10 +1286,11 @@ puglRealize(PuglView* view)
impl->window = window;
[window setContentSize:framePt.size];
- if (view->title) {
+ const char* const title = view->strings[PUGL_WINDOW_TITLE];
+ if (title) {
NSString* titleString =
- [[NSString alloc] initWithBytes:view->title
- length:strlen(view->title)
+ [[NSString alloc] initWithBytes:title
+ length:strlen(title)
encoding:NSUTF8StringEncoding];
[window setTitle:titleString];
@@ -1656,17 +1657,28 @@ puglGetNativeView(PuglView* view)
}
PuglStatus
-puglSetWindowTitle(PuglView* view, const char* title)
+puglViewStringChanged(PuglView* const view,
+ const PuglStringHint key,
+ const char* const value)
{
- puglSetString(&view->title, title);
+ if (!view->impl->window) {
+ return PUGL_SUCCESS;
+ }
- if (view->impl->window) {
- NSString* titleString =
- [[NSString alloc] initWithBytes:title
- length:strlen(title)
- encoding:NSUTF8StringEncoding];
+ switch (key) {
+ case PUGL_CLASS_NAME:
+ return PUGL_UNSUPPORTED;
- [view->impl->window setTitle:titleString];
+ case PUGL_WINDOW_TITLE:
+ if (view->impl->window) {
+ NSString* const titleString =
+ [[NSString alloc] initWithBytes:value
+ length:strlen(value)
+ encoding:NSUTF8StringEncoding];
+
+ [view->impl->window setTitle:titleString];
+ }
+ break;
}
return PUGL_SUCCESS;
diff --git a/src/types.h b/src/types.h
index 12e4acf..9817474 100644
--- a/src/types.h
+++ b/src/types.h
@@ -53,12 +53,12 @@ struct PuglViewImpl {
PuglInternals* impl;
PuglHandle handle;
PuglEventFunc eventFunc;
- char* title;
PuglNativeView parent;
uintptr_t transientParent;
PuglConfigureEvent lastConfigure;
PuglHints hints;
PuglViewSize sizeHints[PUGL_NUM_SIZE_HINTS];
+ char* strings[PUGL_NUM_STRING_HINTS];
int defaultX;
int defaultY;
PuglViewStage stage;
@@ -69,10 +69,10 @@ struct PuglViewImpl {
struct PuglWorldImpl {
PuglWorldInternals* impl;
PuglWorldHandle handle;
- char* className;
double startTime;
size_t numViews;
PuglView** views;
+ char* strings[PUGL_NUM_STRING_HINTS];
PuglWorldType type;
};
diff --git a/src/win.c b/src/win.c
index b3ecf7f..db3f98c 100644
--- a/src/win.c
+++ b/src/win.c
@@ -269,7 +269,7 @@ puglRealize(PuglView* view)
view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency;
// Register window class if necessary
- if (!puglRegisterWindowClass(view->world->className)) {
+ if (!puglRegisterWindowClass(view->world->strings[PUGL_CLASS_NAME])) {
return PUGL_REGISTRATION_FAILED;
}
@@ -280,7 +280,7 @@ puglRealize(PuglView* view)
}
// Set basic window hints and attributes
- puglSetWindowTitle(view, view->title ? view->title : "");
+ puglSetViewString(view, PUGL_WINDOW_TITLE, view->strings[PUGL_WINDOW_TITLE]);
puglSetTransientParent(view, view->transientParent);
view->impl->scaleFactor = puglWinGetViewScaleFactor(view);
@@ -370,7 +370,7 @@ puglFreeViewInternals(PuglView* view)
void
puglFreeWorldInternals(PuglWorld* world)
{
- UnregisterClass(world->className, NULL);
+ UnregisterClass(world->strings[PUGL_CLASS_NAME], NULL);
free(world->impl);
}
@@ -1153,12 +1153,16 @@ puglGetNativeView(PuglView* view)
}
PuglStatus
-puglSetWindowTitle(PuglView* view, const char* title)
+puglViewStringChanged(PuglView* const view,
+ const PuglStringHint key,
+ const char* const value)
{
- puglSetString(&view->title, title);
+ if (!view->impl->hwnd) {
+ return PUGL_SUCCESS;
+ }
- if (view->impl->hwnd) {
- wchar_t* wtitle = puglUtf8ToWideChar(title);
+ if (key == PUGL_WINDOW_TITLE) {
+ wchar_t* const wtitle = puglUtf8ToWideChar(value);
if (wtitle) {
SetWindowTextW(view->impl->hwnd, wtitle);
free(wtitle);
@@ -1548,19 +1552,19 @@ puglWinCreateWindow(PuglView* const view,
HWND* const hwnd,
HDC* const hdc)
{
- const char* className = (const char*)view->world->className;
- const unsigned winFlags = puglWinGetWindowFlags(view);
- const unsigned winExFlags = puglWinGetWindowExFlags(view);
- const PuglRect frame = getInitialFrame(view);
+ const char* className = (const char*)view->world->strings[PUGL_CLASS_NAME];
// The meaning of "parent" depends on the window type (WS_CHILD)
PuglNativeView parent = view->parent ? view->parent : view->transientParent;
// Calculate initial window rectangle
- 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 PuglRect frame = getInitialFrame(view);
+ RECT wr = {(long)frame.x,
+ (long)frame.y,
+ (long)frame.x + frame.width,
+ (long)frame.y + frame.height};
AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
// Create window and get drawing context
diff --git a/src/x11.c b/src/x11.c
index 2511632..b4f68a7 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -625,9 +625,10 @@ puglRealize(PuglView* const view)
#endif
// Set basic window hints and attributes
- XClassHint classHint = {world->className, world->className};
+ char* const className = world->strings[PUGL_CLASS_NAME];
+ XClassHint classHint = {className, className};
XSetClassHint(display, impl->win, &classHint);
- puglSetWindowTitle(view, view->title ? view->title : "");
+ puglSetViewString(view, PUGL_WINDOW_TITLE, view->strings[PUGL_WINDOW_TITLE]);
puglSetTransientParent(view, view->transientParent);
updateSizeHints(view);
@@ -1881,23 +1882,32 @@ puglGetNativeView(PuglView* const view)
}
PuglStatus
-puglSetWindowTitle(PuglView* const view, const char* const title)
+puglViewStringChanged(PuglView* const view,
+ const PuglStringHint key,
+ const char* const value)
{
- Display* display = view->world->impl->display;
- const PuglX11Atoms* const atoms = &view->world->impl->atoms;
+ Display* const display = view->world->impl->display;
+ const PuglX11Atoms* atoms = &view->world->impl->atoms;
+
+ if (!view->impl->win) {
+ return PUGL_SUCCESS;
+ }
- puglSetString(&view->title, title);
+ switch (key) {
+ case PUGL_CLASS_NAME:
+ break;
- if (view->impl->win) {
- XStoreName(display, view->impl->win, title);
+ case PUGL_WINDOW_TITLE:
+ XStoreName(display, view->impl->win, value);
XChangeProperty(display,
view->impl->win,
atoms->NET_WM_NAME,
atoms->UTF8_STRING,
8,
PropModeReplace,
- (const uint8_t*)title,
- (int)strlen(title));
+ (const uint8_t*)value,
+ (int)strlen(value));
+ break;
}
return PUGL_SUCCESS;