From 05cfe1a0da54fb96ec1d97d70201126e5f3fd8ac Mon Sep 17 00:00:00 2001 From: phillbush Date: Thu, 23 Jul 2020 17:37:28 -0300 Subject: [PATCH] Adding the -p option. Changing config.cursx and config.cursy to config.posx and config.posy. Adding the parseposition() function. --- xmenu.1 | 10 ++++++++++ xmenu.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++---------- xmenu.h | 9 +++------ 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/xmenu.1 b/xmenu.1 index 73a95f6..f119efc 100644 --- a/xmenu.1 +++ b/xmenu.1 @@ -4,6 +4,8 @@ xmenu \- menu utility for X .SH SYNOPSIS .B xmenu .RB [ \-iw ] +.RB [ -p +.IR position ] .RI [ title ] .SH DESCRIPTION .B xmenu @@ -23,6 +25,14 @@ Setting the .B -i option removes this space, making the menu narrower. .TP +.BI -p " position" +Set the position to spawn xmenu. +Without this option, xmenu spawns next to the cursor. +.I position +is a string of the form +.BR INTxINT , +where the first INT is the x position and the second INT is the y position. +.TP .B -w Asks the window manager to draw a border around the menus. This option may be buggy in some window managers, diff --git a/xmenu.c b/xmenu.c index af0f801..aa3a52b 100644 --- a/xmenu.c +++ b/xmenu.c @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include #include #include #include @@ -17,6 +19,9 @@ * Function declarations */ +/* argument parser */ +static void parseposition(const char *optarg); + /* initializers, and their helper routines */ static void ealloccolor(const char *s, XftColor *color); static void initresources(void); @@ -78,8 +83,9 @@ static Atom wmdelete; static Atom netatom[NetLast]; /* flags */ -static int wflag = 0; /* whether to let the window manager control XMenu */ static int iflag = 0; /* whether to disable icons */ +static int pflag = 0; /* whether the user specified a position */ +static int wflag = 0; /* whether to let the window manager control XMenu */ /* include config variable */ #include "config.h" @@ -97,11 +103,16 @@ main(int argc, char *argv[]) XClassHint classh; int ch; - while ((ch = getopt(argc, argv, "iw")) != -1) { + while ((ch = getopt(argc, argv, "ip:w")) != -1) { switch (ch) { case 'i': iflag = 1; break; + case 'p': + pflag = 1; + parseposition(optarg); + printf("%dx%d\n", config.posx, config.posy); + break; case 'w': wflag = 1; break; @@ -168,6 +179,30 @@ main(int argc, char *argv[]) return 0; } +/* parse position string from -p, put results on config.x and config.y */ +static void +parseposition(const char *optarg) +{ + long n; + const char *s = optarg; + char *endp; + + n = strtol(s, &endp, 10); + if (errno == ERANGE || n > INT_MAX || n < 0 || endp == s || *endp != 'x') + goto error; + config.posx = n; + s = endp+1; + n = strtol(s, &endp, 10); + if (errno == ERANGE || n > INT_MAX || n < 0 || endp == s || *endp != '\0') + goto error; + config.posy = n; + + return; + +error: + errx(1, "improper position: %s", optarg); +} + /* get color from color string */ static void ealloccolor(const char *s, XftColor *color) @@ -253,7 +288,8 @@ initconfig(void) int di; /* dummy variable */ unsigned du; /* dummy variable */ - XQueryPointer(dpy, rootwin, &dw, &dw, &config.cursx, &config.cursy, &di, &di, &du); + if (!pflag) /* if the user haven't specified a position, use cursor position*/ + XQueryPointer(dpy, rootwin, &dw, &dw, &config.posx, &config.posy, &di, &di, &du); config.screenw = DisplayWidth(dpy, screen); config.screenh = DisplayHeight(dpy, screen); config.iconsize = config.height_pixels - config.iconpadding * 2; @@ -525,13 +561,13 @@ setupmenupos(struct Menu *menu) width = menu->w + config.border_pixels * 2; height = menu->h + config.border_pixels * 2; if (menu->parent == NULL) { /* if root menu, calculate in respect to cursor */ - if (config.screenw - config.cursx >= menu->w) - menu->x = config.cursx; - else if (config.cursx > width) - menu->x = config.cursx - width; + if (pflag || config.screenw - config.posx >= menu->w) + menu->x = config.posx; + else if (config.posx > width) + menu->x = config.posx - width; - if (config.screenh - config.cursy >= height) - menu->y = config.cursy; + if (pflag || config.screenh - config.posy >= height) + menu->y = config.posy; else if (config.screenh > height) menu->y = config.screenh - height; } else { /* else, calculate in respect to parent menu */ @@ -1020,6 +1056,6 @@ cleanup(void) static void usage(void) { - (void)fprintf(stderr, "usage: xmenu [-iw] [title]\n"); + (void)fprintf(stderr, "usage: xmenu [-iw] [-p position] [title]\n"); exit(1); } diff --git a/xmenu.h b/xmenu.h index b636114..2ad68d6 100644 --- a/xmenu.h +++ b/xmenu.h @@ -17,30 +17,27 @@ enum {NetWMName, NetWMWindowType, NetWMWindowTypePopupMenu, NetLast}; /* configuration structure */ struct Config { + /* the values below are set by config.h */ const char *font; - const char *background_color; const char *foreground_color; const char *selbackground_color; const char *selforeground_color; const char *separator_color; const char *border_color; - int width_pixels; int height_pixels; int border_pixels; int separator_pixels; int gap_pixels; - int triangle_width; int triangle_height; - int iconpadding; int horzpadding; + /* the values below are computed by xmenu */ int iconsize; - - int cursx, cursy; /* cursor position */ + int posx, posy; /* cursor position */ int screenw, screenh; /* screen width and height */ }; -- 2.20.1