libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
cursor-lin.c
1/*
2 * CDDL HEADER START
3 *
4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
7 * 1.0 of the CDDL.
8 *
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
12 *
13 * CDDL HEADER END
14*/
15/*
16 * Copyright 2020 Saso Kiselkov. All rights reserved.
17 */
18
19#include <X11/Xcursor/Xcursor.h>
20
21#include "acfutils/cursor.h"
22#include "acfutils/dr.h"
23#include "acfutils/helpers.h"
24#include "acfutils/png.h"
25#include "acfutils/safe_alloc.h"
26
27struct cursor_s {
28 Cursor crs;
29};
30
31/*
32 * Because cursors are only ever created & used from the main rendering
33 * thread, it is safe to use a simple unprotected global var with a refcount.
34 */
35static int dpy_refcount = 0;
36static Display *dpy = NULL;
37
38cursor_t *
39cursor_read_from_file(const char *filename_png)
40{
41 cursor_t *cursor;
42 uint8_t *buf;
43 int w, h;
44 XcursorImage img = { .pixels = NULL };
45
46 ASSERT(filename_png != NULL);
47
48 buf = png_load_from_file_rgba(filename_png, &w, &h);
49 if (buf == NULL)
50 return (NULL);
51
52 if (dpy_refcount == 0)
53 dpy = XOpenDisplay(NULL);
54 if (dpy == NULL) {
55 logMsg("Can't open display");
56 free(buf);
57 return (NULL);
58 }
59 dpy_refcount++;
60
61 img.size = w;
62 img.width = w;
63 img.height = h;
64 img.xhot = w / 2;
65 img.yhot = h / 2;
66 img.pixels = (XcursorPixel *)buf;
67 cursor = safe_calloc(1, sizeof (*cursor));
68 cursor->crs = XcursorImageLoadCursor(dpy, &img);
69
70 free(buf);
71
72 return (cursor);
73}
74
75void
76cursor_free(cursor_t *cursor)
77{
78 if (cursor == NULL)
79 return;
80
81 ASSERT(dpy != NULL);
82 XFreeCursor(dpy, cursor->crs);
83 free(cursor);
84
85 dpy_refcount--;
86 ASSERT3S(dpy_refcount, >=, 0);
87 if (dpy_refcount == 0) {
88 XCloseDisplay(dpy);
89 dpy = NULL;
90 }
91}
92
93void
94cursor_make_current(cursor_t *cursor)
95{
96 dr_t system_window_dr;
97 int win_ptr[2];
98 Window win;
99
100 ASSERT(cursor != NULL);
101 ASSERT(dpy != NULL);
102 fdr_find(&system_window_dr, "sim/operation/windows/system_window_64");
103 VERIFY3S(dr_getvi(&system_window_dr, win_ptr, 0, 2), ==, 2);
104 memcpy(&win, win_ptr, sizeof (void *));
105
106 XDefineCursor(dpy, win, cursor->crs);
107 XFlush(dpy);
108}
#define ASSERT3S(x, op, y)
Definition assert.h:209
#define ASSERT(x)
Definition assert.h:208
#define VERIFY3S(x, op, y)
Definition assert.h:125
void cursor_make_current(cursor_t *cursor)
Definition cursor-lin.c:94
cursor_t * cursor_read_from_file(const char *filename_png)
Definition cursor-lin.c:39
void cursor_free(cursor_t *cursor)
Definition cursor-lin.c:76
#define fdr_find(dr,...)
Definition dr.h:318
#define dr_getvi(__dr, __i, __off, __num)
Definition dr.h:426
#define logMsg(...)
Definition log.h:112
static void * safe_calloc(size_t nmemb, size_t size)
Definition safe_alloc.h:71