aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/detail
diff options
context:
space:
mode:
Diffstat (limited to 'pugl/detail')
-rw-r--r--pugl/detail/mac.h2
-rw-r--r--pugl/detail/mac.m51
-rw-r--r--pugl/detail/win.c41
-rw-r--r--pugl/detail/win.h1
-rw-r--r--pugl/detail/x11.c74
-rw-r--r--pugl/detail/x11.h3
6 files changed, 170 insertions, 2 deletions
diff --git a/pugl/detail/mac.h b/pugl/detail/mac.h
index b38dcd3..296faeb 100644
--- a/pugl/detail/mac.h
+++ b/pugl/detail/mac.h
@@ -61,6 +61,8 @@ struct PuglInternalsImpl {
NSApplication* app;
PuglWrapperView* wrapperView;
NSView* drawView;
+ NSCursor* cursor;
PuglWindow* window;
uint32_t mods;
+ bool mouseTracked;
};
diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m
index da9de20..3bf7cdf 100644
--- a/pugl/detail/mac.m
+++ b/pugl/detail/mac.m
@@ -343,11 +343,15 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
- (void) mouseEntered:(NSEvent*)event
{
handleCrossing(self, event, PUGL_POINTER_IN);
+ [puglview->impl->cursor set];
+ puglview->impl->mouseTracked = true;
}
- (void) mouseExited:(NSEvent*)event
{
+ [[NSCursor arrowCursor] set];
handleCrossing(self, event, PUGL_POINTER_OUT);
+ puglview->impl->mouseTracked = false;
}
- (void) mouseMoved:(NSEvent*)event
@@ -807,7 +811,11 @@ puglGetNativeWorld(PuglWorld* PUGL_UNUSED(world))
PuglInternals*
puglInitViewInternals(void)
{
- return (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
+
+ impl->cursor = [NSCursor arrowCursor];
+
+ return impl;
}
static NSLayoutConstraint*
@@ -1309,6 +1317,47 @@ puglGetClipboard(PuglView* const view,
return puglGetInternalClipboard(view, type, len);
}
+static NSCursor*
+puglGetNsCursor(const PuglCursor cursor)
+{
+ switch (cursor) {
+ case PUGL_CURSOR_ARROW:
+ return [NSCursor arrowCursor];
+ case PUGL_CURSOR_CARET:
+ return [NSCursor IBeamCursor];
+ case PUGL_CURSOR_CROSSHAIR:
+ return [NSCursor crosshairCursor];
+ case PUGL_CURSOR_HAND:
+ return [NSCursor pointingHandCursor];
+ case PUGL_CURSOR_NO:
+ return [NSCursor operationNotAllowedCursor];
+ case PUGL_CURSOR_LEFT_RIGHT:
+ return [NSCursor resizeLeftRightCursor];
+ case PUGL_CURSOR_UP_DOWN:
+ return [NSCursor resizeUpDownCursor];
+ }
+
+ return NULL;
+}
+
+PuglStatus
+puglSetCursor(PuglView* view, PuglCursor cursor)
+{
+ PuglInternals* const impl = view->impl;
+ NSCursor* const cur = puglGetNsCursor(cursor);
+ if (!cur) {
+ return PUGL_FAILURE;
+ }
+
+ impl->cursor = cur;
+
+ if (impl->mouseTracked) {
+ [cur set];
+ }
+
+ return PUGL_SUCCESS;
+}
+
PuglStatus
puglSetClipboard(PuglView* const view,
const char* const type,
diff --git a/pugl/detail/win.c b/pugl/detail/win.c
index 4b73c99..3f9f8f9 100644
--- a/pugl/detail/win.c
+++ b/pugl/detail/win.c
@@ -190,6 +190,8 @@ puglRealize(PuglView* view)
puglSetWindowTitle(view, view->title);
}
+ view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
+
puglSetFrame(view, view->frame);
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
@@ -540,6 +542,11 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
}
switch (message) {
+ case WM_SETCURSOR:
+ if (LOWORD(lParam) == HTCLIENT) {
+ SetCursor(view->impl->cursor);
+ }
+ break;
case WM_SHOWWINDOW:
if (wParam) {
handleConfigure(view, &event);
@@ -1107,6 +1114,40 @@ puglWinStubLeave(PuglView* view, const PuglEventExpose* expose)
return PUGL_SUCCESS;
}
+static const char* const cursor_ids[] = {
+ IDC_ARROW, // ARROW
+ IDC_IBEAM, // CARET
+ IDC_CROSS, // CROSSHAIR
+ IDC_HAND, // HAND
+ IDC_NO, // NO
+ IDC_SIZEWE, // LEFT_RIGHT
+ IDC_SIZENS, // UP_DOWN
+};
+
+PuglStatus
+puglSetCursor(PuglView* view, PuglCursor cursor)
+{
+ PuglInternals* const impl = view->impl;
+ const unsigned index = (unsigned)cursor;
+ const unsigned count = sizeof(cursor_ids) / sizeof(cursor_ids[0]);
+
+ if (index >= count) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ const HCURSOR cur = LoadCursor(NULL, cursor_ids[index]);
+ if (!cur) {
+ return PUGL_FAILURE;
+ }
+
+ impl->cursor = cur;
+ if (impl->mouseTracked) {
+ SetCursor(cur);
+ }
+
+ return PUGL_SUCCESS;
+}
+
const PuglBackend*
puglStubBackend(void)
{
diff --git a/pugl/detail/win.h b/pugl/detail/win.h
index 087bbce..1b9b0c4 100644
--- a/pugl/detail/win.h
+++ b/pugl/detail/win.h
@@ -35,6 +35,7 @@ struct PuglInternalsImpl {
PuglWinPFD pfd;
int pfId;
HWND hwnd;
+ HCURSOR cursor;
HDC hdc;
PuglSurface* surface;
DWORD refreshRate;
diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c
index da7b23d..2d74b68 100644
--- a/pugl/detail/x11.c
+++ b/pugl/detail/x11.c
@@ -41,6 +41,11 @@
# include <X11/extensions/syncconst.h>
#endif
+#ifdef HAVE_XCURSOR
+# include <X11/Xcursor/Xcursor.h>
+# include <X11/cursorfont.h>
+#endif
+
#include <sys/select.h>
#include <sys/time.h>
@@ -152,7 +157,13 @@ puglGetNativeWorld(PuglWorld* world)
PuglInternals*
puglInitViewInternals(void)
{
- return (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
+
+#ifdef HAVE_XCURSOR
+ impl->cursorShape = XC_arrow;
+#endif
+
+ return impl;
}
static PuglStatus
@@ -240,6 +251,25 @@ updateSizeHints(const PuglView* view)
return PUGL_SUCCESS;
}
+#ifdef HAVE_XCURSOR
+static PuglStatus
+puglDefineCursorShape(PuglView* view, unsigned shape)
+{
+ PuglInternals* const impl = view->impl;
+ PuglWorld* const world = view->world;
+ Display* const display = world->impl->display;
+ const Cursor cur = XcursorShapeLoadCursor(display, shape);
+
+ if (cur) {
+ XDefineCursor(display, impl->win, cur);
+ XFreeCursor(display, cur);
+ return PUGL_SUCCESS;
+ }
+
+ return PUGL_FAILURE;
+}
+#endif
+
PuglStatus
puglRealize(PuglView* view)
{
@@ -323,6 +353,10 @@ puglRealize(PuglView* view)
"XCreateID failed\n");
}
+#ifdef HAVE_XCURSOR
+ puglDefineCursorShape(view, impl->cursorShape);
+#endif
+
puglDispatchSimpleEvent(view, PUGL_CREATE);
return PUGL_SUCCESS;
@@ -1234,6 +1268,44 @@ puglSetClipboard(PuglView* const view,
return PUGL_SUCCESS;
}
+#ifdef HAVE_XCURSOR
+static const unsigned cursor_nums[] = {
+ XC_arrow, // ARROW
+ XC_xterm, // CARET
+ XC_crosshair, // CROSSHAIR
+ XC_hand2, // HAND
+ XC_pirate, // NO
+ XC_sb_h_double_arrow, // LEFT_RIGHT
+ XC_sb_v_double_arrow, // UP_DOWN
+};
+#endif
+
+PuglStatus
+puglSetCursor(PuglView* view, PuglCursor cursor)
+{
+#ifdef HAVE_XCURSOR
+ PuglInternals* const impl = view->impl;
+ const unsigned index = (unsigned)cursor;
+ const unsigned count = sizeof(cursor_nums) / sizeof(cursor_nums[0]);
+ if (index >= count) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ const unsigned shape = cursor_nums[index];
+ if (!impl->win || impl->cursorShape == shape) {
+ return PUGL_SUCCESS;
+ }
+
+ impl->cursorShape = cursor_nums[index];
+
+ return puglDefineCursorShape(view, impl->cursorShape);
+#else
+ (void)view;
+ (void)cursor;
+ return PUGL_FAILURE;
+#endif
+}
+
const PuglBackend*
puglStubBackend(void)
{
diff --git a/pugl/detail/x11.h b/pugl/detail/x11.h
index aac8177..164a57e 100644
--- a/pugl/detail/x11.h
+++ b/pugl/detail/x11.h
@@ -64,6 +64,9 @@ struct PuglInternalsImpl {
int screen;
XVisualInfo* vi;
Window win;
+#ifdef HAVE_XCURSOR
+ unsigned cursorShape;
+#endif
XIC xic;
PuglSurface* surface;
PuglEvent pendingConfigure;