Feature: Add the ability to take "screenshots" of spmenu.

It doesn't actually capture your screen, but rather saves the Cairo
surface to an image. The path to the image and some other options
can also be configured in the config file.

By default, Print Screen can be pressed in Normal mode with no modifier
to take a screenshot. The default location is the user's home directory,
and the file has a date attached to it. Of course, this can be changed
as well.
This commit is contained in:
Jacob 2023-06-30 02:44:29 +02:00
parent eefa047c6e
commit 3f456f3a37
11 changed files with 98 additions and 0 deletions

View file

@ -792,6 +792,7 @@ These are the default keybinds. You can generate these yourself from a
| 0 | 0 | Prior | moveprev | 0 |
| 0 | Ctrl | p | navhistory | -1 |
| 0 | Ctrl | n | navhistory | +1 |
| 0 | 0 | Print | screenshot | 0 |
| 1 | 0 | Escape | switchmode | 0 |
## .Xresources

View file

@ -213,6 +213,9 @@ spmenu = {
binds = 1; // Load binds (~/.config/spmenu/binds.conf) on runtime
themefile = "NULL"; // Path to theme file to load on runtime. NULL means default.
bindsfile = "NULL"; // Path to binds file to load on runtime. NULL means default.
screenshotfile = "NULL"; // Screenshot file path. NULL means default.
screenshotname = "NULL"; // Screenshot file name. NULL means default.
screenshotdir = "NULL"; // Screenshot file directory. NULL means default.
} );
/* Input options */
@ -333,6 +336,7 @@ spmenu = {
{ mode = 0; modifier = "None"; key = "Prior"; function = "moveprev"; argument = "0"; }, // Prior: Move to the previous entry (undo)
{ mode = 0; modifier = "Ctrl"; key = "p"; function = "navhistory"; argument = "-1"; }, // Alt+p: Navigate to the previous entry in the history buffer
{ mode = 0; modifier = "Ctrl"; key = "n"; function = "navhistory"; argument = "+1"; }, // Alt+n: Navigate to the next entry in the history buffer
{ mode = 0; modifier = "None"; key = "PrintScr"; function = "screenshot"; argument = "0"; }, // Print Screen: Screenshot spmenu
{ ignoreglobalkeys = 1; } ), // Ignore hardcoded keybinds (0/1)
};

View file

@ -507,3 +507,51 @@ void switchmode(Arg *arg) {
strncpy(tx.modetext, sp.mode ? instext : normtext, 15);
drawmenu();
}
void screenshot(Arg *arg) {
char *file = NULL;
char *home = NULL;
time_t time_ = time(NULL);
struct tm t = *localtime(&time_);
if (!screenshotfile) {
if (!(home = getenv("HOME"))) {
fprintf(stderr, "spmenu: failed to determine home directory\n");
return;
}
if (!screenshotdir && !screenshotname) { // default
if (!(file = malloc(snprintf(NULL, 0, "%s/%s-%02d-%02d-%02d%s", home, "spmenu-screenshot", t.tm_hour, t.tm_min, t.tm_sec, ".png") + 1))) {
die("spmenu: failed to malloc screenshot file");
}
sprintf(file, "%s/%s-%02d-%02d-%02d%s", home, "spmenu-screenshot", t.tm_hour, t.tm_min, t.tm_sec, ".png");
} else if (!screenshotdir && screenshotname) { // no dir but name
if (!(file = malloc(snprintf(NULL, 0, "%s/%s", home, screenshotname) + 1))) {
die("spmenu: failed to malloc screenshot file");
}
sprintf(file, "%s/%s", home, screenshotname);
} else if (screenshotdir && !screenshotname) { // dir but no name
if (!(file = malloc(snprintf(NULL, 0, "%s/%s-%02d-%02d-%02d%s", screenshotdir, "spmenu-screenshot", t.tm_hour, t.tm_min, t.tm_sec, ".png") + 1))) {
die("spmenu: failed to malloc screenshot file");
}
sprintf(file, "%s/%s-%02d-%02d-%02d%s", screenshotdir, "spmenu-screenshot", t.tm_hour, t.tm_min, t.tm_sec, ".png");
} else { // dir and name
if (!(file = malloc(snprintf(NULL, 0, "%s/%s", screenshotdir, screenshotname) + 1))) {
die("spmenu: failed to malloc screenshot file");
}
sprintf(file, "%s/%s", screenshotdir, screenshotname);
}
} else { // custom file
if (!(file = malloc(snprintf(NULL, 0, "%s", screenshotfile) + 1))) {
die("spmenu: failed to malloc screenshot file");
}
sprintf(file, "%s", screenshotfile);
}
draw_save_screen(draw, file);
}

View file

@ -43,3 +43,4 @@ static void spawn(Arg *arg);
static void togglehighlight(Arg *arg);
static void setprofile(Arg *arg);
static void switchmode(Arg *arg);
static void screenshot(Arg *arg);

View file

@ -441,6 +441,18 @@ void conf_init(void) {
if (config_setting_lookup_string(conf, "bindsfile", &dest)) {
bindsfile = strdup(dest);
}
if (config_setting_lookup_string(conf, "screenshotfile", &dest) && strcmp(dest, "NULL")) {
screenshotfile = strdup(dest);
}
if (config_setting_lookup_string(conf, "screenshotname", &dest) && strcmp(dest, "NULL")) {
screenshotname = strdup(dest);
}
if (config_setting_lookup_string(conf, "screenshotdir", &dest) && strcmp(dest, "NULL")) {
screenshotdir = strdup(dest);
}
}
}

View file

@ -384,6 +384,7 @@ static FuncList fl[] = {
{ "setimggaps", setimggaps },
{ "setlines", setlines },
{ "setlines", setlines },
{ "screenshot", screenshot },
{ "setcolumns", setcolumns },
{ "togglehighlight",togglehighlight },
{ "setprofile", setprofile },

View file

@ -417,6 +417,16 @@ void draw_img(Draw_t *draw, int x, int y) {
cairo_set_source_surface(draw->d, draw->surface, draw->w, draw->h);
}
void draw_save_screen(Draw_t *draw, const char *file) {
if (!draw || !draw->surface) {
return;
}
if (cairo_surface_write_to_png(draw->surface, file)) {
fprintf(stderr, "spmenu: failed to write file %s\n", file);
}
}
unsigned int draw_fontset_getwidth_clamp(Draw_t *draw, const char *text, unsigned int n, Bool markup) {
unsigned int tmp = 0;
if (draw && draw->font && text && n)

View file

@ -64,3 +64,6 @@ void draw_map(Draw_t *draw, Window win, int x, int y, unsigned int w, unsigned i
/* Powerline functions */
void draw_arrow(Draw_t *draw, int x, int y, unsigned int w, unsigned int h, int direction, int slash, char *prevcol, char *nextcol, int prevalpha, int nextalpha);
void draw_circle(Draw_t *draw, int x, int y, unsigned int w, unsigned int h, int direction, char *prevcol, char *nextcol, int prevalpha, int nextalpha);
/* Screenshot functions */
void draw_save_screen(Draw_t *draw, const char *file);

View file

@ -71,6 +71,7 @@ static Key keys[] = {
{ 0, 0, XK_Prior, moveprev, {0} },
{ 0, Ctrl, XK_p, navhistory, {.i = -1 } },
{ 0, Ctrl, XK_n, navhistory, {.i = +1 } },
{ 0, 0, XK_Print, screenshot, {0} },
/* insert mode */
{ 1, 0, XK_Escape, switchmode, {0} },
@ -146,6 +147,7 @@ static WlKey wl_keys[] = {
{ 0, WL_None, XKB_KEY_Prior, moveprev, {0} },
{ 0, WL_Ctrl, XKB_KEY_p, navhistory, {.i = -1 } },
{ 0, WL_Ctrl, XKB_KEY_n, navhistory, {.i = +1 } },
{ 0, WL_None, XKB_KEY_Print, screenshot, {0} },
/* insert mode */
{ 1, WL_None, XKB_KEY_Escape, switchmode, {0} },

View file

@ -56,6 +56,11 @@ static int generatecache = 1; /* Generate image cache by default *
static int maxcache = 512; /* Max image size to cache */
static char *cachedir = "default"; /* Cache directory. Default means spmenu will determine automatically */
/* Screenshot options */
static char *screenshotfile = NULL; /* Screenshot file path. If set to NULL, the default path will be used. */
static char *screenshotname = NULL; /* Screenshot file name. If set to NULL, the default name will be used. */
static char *screenshotdir = NULL; /* Screenshot file directory. If set to NULL, the default directory will be used. */
/* Mode options */
static int mode = 0; /* Mode to start speedwm in (0: Normal mode, 1: Insert mode) */
static char *normtext = "Normal"; /* Text to display for normal mode */

View file

@ -1458,6 +1458,17 @@ T}@T{
+1
T}
T{
0
T}@T{
0
T}@T{
Print
T}@T{
screenshot
T}@T{
0
T}
T{
1
T}@T{
0