Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite the xcursor caching code #3745

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 21 additions & 105 deletions common/xcursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,129 +22,45 @@
#include "common/xcursor.h"
#include "common/util.h"

#include <X11/cursorfont.h>

static char const * const xcursor_font[] =
{
[XC_X_cursor] = "X_cursor",
[XC_arrow] = "arrow",
[XC_based_arrow_down] = "based_arrow_down",
[XC_based_arrow_up] = "based_arrow_up",
[XC_boat] = "boat",
[XC_bogosity] = "bogosity",
[XC_bottom_left_corner] = "bottom_left_corner",
[XC_bottom_right_corner] = "bottom_right_corner",
[XC_bottom_side] = "bottom_side",
[XC_bottom_tee] = "bottom_tee",
[XC_box_spiral] = "box_spiral",
[XC_center_ptr] = "center_ptr",
[XC_circle] = "circle",
[XC_clock] = "clock",
[XC_coffee_mug] = "coffee_mug",
[XC_cross] = "cross",
[XC_cross_reverse] = "cross_reverse",
[XC_crosshair] = "crosshair",
[XC_diamond_cross] = "diamond_cross",
[XC_dot] = "dot",
[XC_dotbox] = "dotbox",
[XC_double_arrow] = "double_arrow",
[XC_draft_large] = "draft_large",
[XC_draft_small] = "draft_small",
[XC_draped_box] = "draped_box",
[XC_exchange] = "exchange",
[XC_fleur] = "fleur",
[XC_gobbler] = "gobbler",
[XC_gumby] = "gumby",
[XC_hand1] = "hand1",
[XC_hand2] = "hand2",
[XC_heart] = "heart",
[XC_icon] = "icon",
[XC_iron_cross] = "iron_cross",
[XC_left_ptr] = "left_ptr",
[XC_left_side] = "left_side",
[XC_left_tee] = "left_tee",
[XC_leftbutton] = "leftbutton",
[XC_ll_angle] = "ll_angle",
[XC_lr_angle] = "lr_angle",
[XC_man] = "man",
[XC_middlebutton] = "middlebutton",
[XC_mouse] = "mouse",
[XC_pencil] = "pencil",
[XC_pirate] = "pirate",
[XC_plus] = "plus",
[XC_question_arrow] = "question_arrow",
[XC_right_ptr] = "right_ptr",
[XC_right_side] = "right_side",
[XC_right_tee] = "right_tee",
[XC_rightbutton] = "rightbutton",
[XC_rtl_logo] = "rtl_logo",
[XC_sailboat] = "sailboat",
[XC_sb_down_arrow] = "sb_down_arrow",
[XC_sb_h_double_arrow] = "sb_h_double_arrow",
[XC_sb_left_arrow] = "sb_left_arrow",
[XC_sb_right_arrow] = "sb_right_arrow",
[XC_sb_up_arrow] = "sb_up_arrow",
[XC_sb_v_double_arrow] = "sb_v_double_arrow",
[XC_shuttle] = "shuttle",
[XC_sizing] = "sizing",
[XC_spider] = "spider",
[XC_spraycan] = "spraycan",
[XC_star] = "star",
[XC_target] = "target",
[XC_tcross] = "tcross",
[XC_top_left_arrow] = "top_left_arrow",
[XC_top_left_corner] = "top_left_corner",
[XC_top_right_corner] = "top_right_corner",
[XC_top_side] = "top_side",
[XC_top_tee] = "top_tee",
[XC_trek] = "trek",
[XC_ul_angle] = "ul_angle",
[XC_umbrella] = "umbrella",
[XC_ur_angle] = "ur_angle",
[XC_watch] = "watch",
[XC_xterm] = "xterm",
struct cursor_cache_entry_t {
char const * name;
xcb_cursor_t cursor;
};

/** Get a cursor from a string.
* \param s The string.
*/
uint16_t
xcursor_font_fromstr(const char *s)
{
if(s)
for(int i = 0; i < countof(xcursor_font); i++)
if(xcursor_font[i] && A_STREQ(s, xcursor_font[i]))
return i;
return 0;
static int
cursor_cache_entry_cmp(const void *a, const void *b) {
return a_strcmp(((cursor_cache_entry_t *) a)->name, ((cursor_cache_entry_t *) b)->name);
}

/** Get a cursor name.
* \param c The cursor.
*/
const char *
xcursor_font_tostr(uint16_t c)
static void
cursor_cache_entry_wipe(cursor_cache_entry_t *entry)
{
if(c < countof(xcursor_font))
return xcursor_font[c];
return NULL;
p_delete(&entry->name);
}

BARRAY_FUNCS(cursor_cache_entry_t, cursors, cursor_cache_entry_wipe, cursor_cache_entry_cmp)

/** Equivalent to 'XCreateFontCursor()', error are handled by the
* default current error handler.
* \param ctx The xcb-cursor context.
* \param cursor_font Type of cursor to use.
* \return Allocated cursor font.
*/
xcb_cursor_t
xcursor_new(xcb_cursor_context_t *ctx, uint16_t cursor_font)
xcursor_new(cursors_array_t *array, xcb_cursor_context_t *ctx, const char *cursor_name)
{
static xcb_cursor_t xcursor[countof(xcursor_font)];
cursor_cache_entry_t entry;
entry.name = cursor_name;

if (!xcursor[cursor_font]) {
xcursor[cursor_font] = xcb_cursor_load_cursor(ctx, xcursor_font_tostr(cursor_font));
cursor_cache_entry_t *found = cursors_array_lookup(array, &entry);
if (NULL == found) {
entry.name = a_strdup(cursor_name);
entry.cursor = xcb_cursor_load_cursor(ctx, cursor_name);
cursors_array_insert(array, entry);
found = &entry;
}

return xcursor[cursor_font];
return found->cursor;
}


Expand Down
8 changes: 5 additions & 3 deletions common/xcursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@

#include <xcb/xcb.h>
#include <xcb/xcb_cursor.h>
#include "common/array.h"

uint16_t xcursor_font_fromstr(const char *);
const char * xcursor_font_tostr(uint16_t);
xcb_cursor_t xcursor_new(xcb_cursor_context_t *, uint16_t);
typedef struct cursor_cache_entry_t cursor_cache_entry_t;
ARRAY_TYPE(cursor_cache_entry_t, cursors)

xcb_cursor_t xcursor_new(cursors_array_t *, xcb_cursor_context_t *, const char *);

#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
3 changes: 3 additions & 0 deletions globalconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "objects/key.h"
#include "common/xembed.h"
#include "common/xcursor.h"
#include "common/buffer.h"

#define ROOT_WINDOW_EVENT_MASK \
Expand Down Expand Up @@ -88,6 +89,8 @@ typedef struct
int default_screen;
/** xcb-cursor context */
xcb_cursor_context_t *cursor_ctx;
/** cache of already loaded cursors */
cursors_array_t cursor_cache;
#ifdef WITH_XCB_ERRORS
/** xcb-errors context */
xcb_errors_context_t *errors_ctx;
Expand Down
6 changes: 2 additions & 4 deletions mousegrabber.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,12 @@ luaA_mousegrabber_run(lua_State *L)

if(!lua_isnil(L, 2))
{
uint16_t cfont = xcursor_font_fromstr(luaL_checkstring(L, 2));
if(!cfont)
cursor = xcursor_new(&globalconf.cursor_cache, globalconf.cursor_ctx, luaL_checkstring(L, 2));
if (!cursor)
{
luaA_warn(L, "invalid cursor");
return 0;
}

cursor = xcursor_new(globalconf.cursor_ctx, cfont);
}

luaA_registerfct(L, 1, &globalconf.mousegrabber);
Expand Down
7 changes: 3 additions & 4 deletions objects/drawin.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@
| XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_PROPERTY_CHANGE,
globalconf.default_cmap,
xcursor_new(globalconf.cursor_ctx, xcursor_font_fromstr(w->cursor))
xcursor_new(&globalconf.cursor_cache, globalconf.cursor_ctx, w->cursor)
});
xwindow_set_class_instance(w->window);
xwindow_set_name_static(w->window, "Awesome drawin");
Expand Down Expand Up @@ -608,10 +608,9 @@
const char *buf = luaL_checkstring(L, -1);
if(buf)
{
uint16_t cursor_font = xcursor_font_fromstr(buf);
if(cursor_font)
xcb_cursor_t cursor = xcursor_new(&globalconf.cursor_cache, globalconf.cursor_ctx, buf);
if(cursor)

Check warning on line 612 in objects/drawin.c

View check run for this annotation

Codecov / codecov/patch

objects/drawin.c#L611-L612

Added lines #L611 - L612 were not covered by tests
{
xcb_cursor_t cursor = xcursor_new(globalconf.cursor_ctx, cursor_font);
p_delete(&drawin->cursor);
drawin->cursor = a_strdup(buf);
xwindow_set_cursor(drawin->window, cursor);
Expand Down
6 changes: 3 additions & 3 deletions root.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,11 @@ static int
luaA_root_cursor(lua_State *L)
{
const char *cursor_name = luaL_checkstring(L, 1);
uint16_t cursor_font = xcursor_font_fromstr(cursor_name);
xcb_cursor_t cursor = xcursor_new(&globalconf.cursor_cache, globalconf.cursor_ctx, cursor_name);

if(cursor_font)
if(cursor)
{
uint32_t change_win_vals[] = { xcursor_new(globalconf.cursor_ctx, cursor_font) };
uint32_t change_win_vals[] = { cursor };

xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
Expand Down