diff --git a/docs/docs.md b/docs/docs.md index a1fd8ef..d9bbddf 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -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 diff --git a/docs/spmenu.conf b/docs/spmenu.conf index 8450cdc..d9c3056 100644 --- a/docs/spmenu.conf +++ b/docs/spmenu.conf @@ -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) }; diff --git a/libs/arg.c b/libs/arg.c index 3d6529e..9df9da9 100644 --- a/libs/arg.c +++ b/libs/arg.c @@ -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); +} diff --git a/libs/arg.h b/libs/arg.h index 520706d..f2260af 100644 --- a/libs/arg.h +++ b/libs/arg.h @@ -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); diff --git a/libs/conf/config.c b/libs/conf/config.c index a5a12d1..95ed777 100644 --- a/libs/conf/config.c +++ b/libs/conf/config.c @@ -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); + } } } diff --git a/libs/conf/config.h b/libs/conf/config.h index 62bd6ca..ec4fada 100644 --- a/libs/conf/config.h +++ b/libs/conf/config.h @@ -384,6 +384,7 @@ static FuncList fl[] = { { "setimggaps", setimggaps }, { "setlines", setlines }, { "setlines", setlines }, + { "screenshot", screenshot }, { "setcolumns", setcolumns }, { "togglehighlight",togglehighlight }, { "setprofile", setprofile }, diff --git a/libs/draw/draw.c b/libs/draw/draw.c index 6a513be..4d2f139 100644 --- a/libs/draw/draw.c +++ b/libs/draw/draw.c @@ -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) diff --git a/libs/draw/draw.h b/libs/draw/draw.h index c1d953a..95b085f 100644 --- a/libs/draw/draw.h +++ b/libs/draw/draw.h @@ -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); diff --git a/libs/keybinds.h b/libs/keybinds.h index 667c576..6afb4fa 100644 --- a/libs/keybinds.h +++ b/libs/keybinds.h @@ -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} }, diff --git a/libs/options.h b/libs/options.h index 4a8967c..cb7f4b6 100644 --- a/libs/options.h +++ b/libs/options.h @@ -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 */ diff --git a/spmenu.1 b/spmenu.1 index 1f9c636..09a063f 100644 --- a/spmenu.1 +++ b/spmenu.1 @@ -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