mirror of
https://github.com/hyprwm/hyprcursor.git
synced 2024-11-17 02:35:57 +01:00
API: improve in prep for animated
This commit is contained in:
parent
953f2fb118
commit
6760e68a1b
9 changed files with 138 additions and 26 deletions
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cairo/cairo.h>
|
#include "shared.h"
|
||||||
|
|
||||||
struct hyprcursor_manager_t;
|
struct hyprcursor_manager_t;
|
||||||
|
|
||||||
|
@ -62,12 +62,21 @@ CAPI int hyprcursor_manager_valid(struct hyprcursor_manager_t* manager);
|
||||||
CAPI int hyprcursor_load_theme_style(struct hyprcursor_manager_t* manager, struct hyprcursor_cursor_style_info info);
|
CAPI int hyprcursor_load_theme_style(struct hyprcursor_manager_t* manager, struct hyprcursor_cursor_style_info info);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns a cairo_surface_t for a given cursor
|
Returns a hyprcursor_cursor_image_data*[] for a given cursor
|
||||||
shape and size.
|
shape and size.
|
||||||
|
|
||||||
|
The entire array needs to be freed instantly after using, see hyprcursor_cursor_image_data_free()
|
||||||
|
|
||||||
|
Surfaces stay valid.
|
||||||
|
|
||||||
Once done with a size, call hyprcursor_style_done()
|
Once done with a size, call hyprcursor_style_done()
|
||||||
*/
|
*/
|
||||||
CAPI cairo_surface_t* hyprcursor_get_surface_for(struct hyprcursor_manager_t* manager, const char* shape, struct hyprcursor_cursor_style_info info);
|
CAPI hyprcursor_cursor_image_data** hyprcursor_get_cursor_image_data(struct hyprcursor_manager_t* manager, const char* shape, struct hyprcursor_cursor_style_info info, int* out_size);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Free a returned hyprcursor_cursor_image_data.
|
||||||
|
*/
|
||||||
|
CAPI void hyprcursor_cursor_image_data_free(hyprcursor_cursor_image_data** data, int size);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Marks a certain style as done, allowing it to be potentially freed
|
Marks a certain style as done, allowing it to be potentially freed
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cairo/cairo.h>
|
#include <vector>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
class CHyprcursorImplementation;
|
class CHyprcursorImplementation;
|
||||||
|
|
||||||
|
@ -18,6 +21,14 @@ namespace Hyprcursor {
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
struct for cursor shape data
|
||||||
|
*/
|
||||||
|
struct SCursorShapeData {
|
||||||
|
std::vector<SCursorImageData> images;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Basic Hyprcursor manager.
|
Basic Hyprcursor manager.
|
||||||
|
|
||||||
|
@ -49,12 +60,38 @@ namespace Hyprcursor {
|
||||||
bool loadThemeStyle(const SCursorStyleInfo& info);
|
bool loadThemeStyle(const SCursorStyleInfo& info);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns a cairo_surface_t for a given cursor
|
Returns the shape data struct for a given
|
||||||
shape and size.
|
style.
|
||||||
|
|
||||||
Once done with a size, call cursorSurfaceDone()
|
Once done with a style, call cursorSurfaceDone()
|
||||||
|
|
||||||
|
The surfaces references stay valid until cursorSurfaceStyleDone() is called on the owning style.
|
||||||
*/
|
*/
|
||||||
cairo_surface_t* getSurfaceFor(const char* shape, const SCursorStyleInfo& info);
|
SCursorShapeData getShape(const char* shape, const SCursorStyleInfo& info) {
|
||||||
|
int size = 0;
|
||||||
|
SCursorImageData** images = getShapesC(size, shape, info);
|
||||||
|
|
||||||
|
SCursorShapeData data;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
SCursorImageData image;
|
||||||
|
image.delay = images[i]->delay;
|
||||||
|
image.size = images[i]->size;
|
||||||
|
image.surface = images[i]->surface;
|
||||||
|
data.images.push_back(image);
|
||||||
|
|
||||||
|
free(images[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(images);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Prefer getShape, this is for C compat.
|
||||||
|
*/
|
||||||
|
SCursorImageData** getShapesC(int& outSize, const char* shape_, const SCursorStyleInfo& info);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Marks a certain style as done, allowing it to be potentially freed
|
Marks a certain style as done, allowing it to be potentially freed
|
||||||
|
|
17
include/shared.h
Normal file
17
include/shared.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <cairo/cairo.h>
|
||||||
|
|
||||||
|
#ifndef HYPRCURSOR_SHARED_H
|
||||||
|
#define HYPRCURSOR_SHARED_H
|
||||||
|
|
||||||
|
/*!
|
||||||
|
struct for a single cursor image
|
||||||
|
*/
|
||||||
|
struct SCursorImageData {
|
||||||
|
cairo_surface_t* surface;
|
||||||
|
int size;
|
||||||
|
int delay;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct SCursorImageData hyprcursor_cursor_image_data;
|
||||||
|
|
||||||
|
#endif
|
|
@ -162,22 +162,29 @@ bool CHyprcursorManager::valid() {
|
||||||
return finalizedAndValid;
|
return finalizedAndValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t* CHyprcursorManager::getSurfaceFor(const char* shape_, const SCursorStyleInfo& info) {
|
SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shape_, const SCursorStyleInfo& info) {
|
||||||
std::string REQUESTEDSHAPE = shape_;
|
std::string REQUESTEDSHAPE = shape_;
|
||||||
|
|
||||||
|
std::vector<SLoadedCursorImage*> resultingImages;
|
||||||
|
|
||||||
for (auto& shape : impl->theme.shapes) {
|
for (auto& shape : impl->theme.shapes) {
|
||||||
if (REQUESTEDSHAPE != shape.directory && std::find(shape.overrides.begin(), shape.overrides.end(), REQUESTEDSHAPE) == shape.overrides.end())
|
if (REQUESTEDSHAPE != shape.directory && std::find(shape.overrides.begin(), shape.overrides.end(), REQUESTEDSHAPE) == shape.overrides.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// matched :)
|
// matched :)
|
||||||
|
bool foundAny = false;
|
||||||
for (auto& image : impl->loadedShapes[&shape].images) {
|
for (auto& image : impl->loadedShapes[&shape].images) {
|
||||||
if (image->side != info.size)
|
if (image->side != info.size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// found size
|
// found size
|
||||||
return image->cairoSurface;
|
resultingImages.push_back(image.get());
|
||||||
|
foundAny = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (foundAny)
|
||||||
|
break;
|
||||||
|
|
||||||
// if we get here, means loadThemeStyle wasn't called most likely. If resize algo is specified, this is an error.
|
// if we get here, means loadThemeStyle wasn't called most likely. If resize algo is specified, this is an error.
|
||||||
if (shape.resizeAlgo != RESIZE_NONE) {
|
if (shape.resizeAlgo != RESIZE_NONE) {
|
||||||
Debug::log(ERR, "getSurfaceFor didn't match a size?");
|
Debug::log(ERR, "getSurfaceFor didn't match a size?");
|
||||||
|
@ -185,27 +192,50 @@ cairo_surface_t* CHyprcursorManager::getSurfaceFor(const char* shape_, const SCu
|
||||||
}
|
}
|
||||||
|
|
||||||
// find nearest
|
// find nearest
|
||||||
int leader = 1337;
|
int leader = 13371337;
|
||||||
SLoadedCursorImage* leaderImg = nullptr;
|
|
||||||
for (auto& image : impl->loadedShapes[&shape].images) {
|
for (auto& image : impl->loadedShapes[&shape].images) {
|
||||||
if (std::abs((int)(image->side - info.size)) > leader)
|
if (std::abs((int)(image->side - info.size)) > leader)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
leaderImg = image.get();
|
|
||||||
leader = image->side;
|
leader = image->side;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!leaderImg) { // ???
|
if (leader == 13371337) { // ???
|
||||||
Debug::log(ERR, "getSurfaceFor didn't match any nearest size?");
|
Debug::log(ERR, "getSurfaceFor didn't match any nearest size?");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return leaderImg->cairoSurface;
|
// we found nearest size
|
||||||
|
for (auto& image : impl->loadedShapes[&shape].images) {
|
||||||
|
if (image->side != leader)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// found size
|
||||||
|
resultingImages.push_back(image.get());
|
||||||
|
foundAny = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (foundAny)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Debug::log(ERR, "getSurfaceFor didn't match any nearest size (2)?");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// alloc and return what we need
|
||||||
|
SCursorImageData** data = (SCursorImageData**)malloc(sizeof(SCursorImageData*) * resultingImages.size());
|
||||||
|
for (size_t i = 0; i < resultingImages.size(); ++i) {
|
||||||
|
data[i] = (SCursorImageData*)malloc(sizeof(SCursorImageData));
|
||||||
|
data[i]->delay = resultingImages[i]->delay;
|
||||||
|
data[i]->size = resultingImages[i]->side;
|
||||||
|
data[i]->surface = resultingImages[i]->cairoSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
outSize = resultingImages.size();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
||||||
for (auto& shape : impl->theme.shapes) {
|
for (auto& shape : impl->theme.shapes) {
|
||||||
if (shape.resizeAlgo == RESIZE_NONE)
|
if (shape.resizeAlgo == RESIZE_NONE)
|
||||||
|
|
|
@ -23,11 +23,22 @@ int hyprcursor_load_theme_style(hyprcursor_manager_t* manager, hyprcursor_cursor
|
||||||
return MGR->loadThemeStyle(info);
|
return MGR->loadThemeStyle(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t* hyprcursor_get_surface_for(hyprcursor_manager_t* manager, const char* shape, hyprcursor_cursor_style_info info_) {
|
struct SCursorImageData** hyprcursor_get_cursor_image_data(struct hyprcursor_manager_t* manager, const char* shape, struct hyprcursor_cursor_style_info info_, int* out_size) {
|
||||||
const auto MGR = (CHyprcursorManager*)manager;
|
const auto MGR = (CHyprcursorManager*)manager;
|
||||||
SCursorStyleInfo info;
|
SCursorStyleInfo info;
|
||||||
info.size = info_.size;
|
info.size = info_.size;
|
||||||
return MGR->getSurfaceFor(shape, info);
|
int size = 0;
|
||||||
|
struct SCursorImageData** data = MGR->getShapesC(size, shape, info);
|
||||||
|
*out_size = size;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hyprcursor_cursor_image_data_free(hyprcursor_cursor_image_data** data, int size) {
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
free(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyprcursor_style_done(hyprcursor_manager_t* manager, hyprcursor_cursor_style_info info_) {
|
void hyprcursor_style_done(hyprcursor_manager_t* manager, hyprcursor_cursor_style_info info_) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct SLoadedCursorImage {
|
||||||
|
|
||||||
cairo_surface_t* cairoSurface = nullptr;
|
cairo_surface_t* cairoSurface = nullptr;
|
||||||
int side = 0;
|
int side = 0;
|
||||||
|
int delay = 0;
|
||||||
|
|
||||||
// means this was created by resampling
|
// means this was created by resampling
|
||||||
void* artificialData = nullptr;
|
void* artificialData = nullptr;
|
||||||
|
|
|
@ -19,6 +19,7 @@ inline eResizeAlgo stringToAlgo(const std::string& s) {
|
||||||
struct SCursorImage {
|
struct SCursorImage {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
int delay = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SCursorShape {
|
struct SCursorShape {
|
||||||
|
|
11
tests/test.c
11
tests/test.c
|
@ -16,13 +16,16 @@ int main(int argc, char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t* surf = hyprcursor_get_surface_for(mgr, "left_ptr", info);
|
int dataSize = 0;
|
||||||
if (surf == NULL) {
|
hyprcursor_cursor_image_data** data = hyprcursor_get_cursor_image_data(mgr, "left_ptr", info, &dataSize);
|
||||||
printf("surf failed\n");
|
if (data == NULL) {
|
||||||
|
printf("data failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = cairo_surface_write_to_png(surf, "/tmp/arrowC.png");
|
int ret = cairo_surface_write_to_png(data[0]->surface, "/tmp/arrowC.png");
|
||||||
|
|
||||||
|
hyprcursor_cursor_image_data_free(data, dataSize);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("cairo failed\n");
|
printf("cairo failed\n");
|
||||||
|
|
|
@ -11,10 +11,13 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get cursor for left_ptr
|
// get cursor for left_ptr
|
||||||
const auto ARROW = mgr.getSurfaceFor("left_ptr", Hyprcursor::SCursorStyleInfo{.size = 48});
|
const auto SHAPEDATA = mgr.getShape("left_ptr", Hyprcursor::SCursorStyleInfo{.size = 48});
|
||||||
|
|
||||||
|
if (SHAPEDATA.images.empty())
|
||||||
|
return 1;
|
||||||
|
|
||||||
// save to disk
|
// save to disk
|
||||||
const auto RET = cairo_surface_write_to_png(ARROW, "/tmp/arrow.png");
|
const auto RET = cairo_surface_write_to_png(SHAPEDATA.images[0].surface, "/tmp/arrow.png");
|
||||||
|
|
||||||
std::cout << "Cairo returned for write: " << RET << "\n";
|
std::cout << "Cairo returned for write: " << RET << "\n";
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue