diff --git a/README.html b/README.html
index bb2debf..27b4abb 100644
--- a/README.html
+++ b/README.html
@@ -314,8 +314,6 @@ it’s not like you will be unable to use spmenu in its current
state.
-
Bugs
-None discovered yet! :)
Scripts
There’s a page dedicated to user scripts over on the
diff --git a/README.md b/README.md
index 6acbc89..b09b8ff 100644
--- a/README.md
+++ b/README.md
@@ -138,10 +138,6 @@ code which as of now seems unlikely, or if someone makes a patch.
- You can just use XWayland anyway if you happen to use Wayland, so it's not
like you will be unable to use spmenu in its current state.
-### Bugs
-
-None discovered yet! :)
-
## Scripts
There's a page dedicated to user scripts
diff --git a/libs/client.c b/libs/x11/client.c
similarity index 100%
rename from libs/client.c
rename to libs/x11/client.c
diff --git a/libs/client.h b/libs/x11/client.h
similarity index 100%
rename from libs/client.h
rename to libs/x11/client.h
diff --git a/libs/x11/init.c b/libs/x11/init.c
new file mode 100644
index 0000000..8771b71
--- /dev/null
+++ b/libs/x11/init.c
@@ -0,0 +1,164 @@
+void setupdisplay(void) {
+ int x, y, i;
+#if USEXINERAMA
+ int j, di;
+#endif
+ unsigned int du;
+ unsigned int tmp, minstrlen = 0, curstrlen = 0;
+ int numwidthchecks = 100;
+ struct item *item;
+ XIM xim;
+ Window w, dw, *dws;
+ XWindowAttributes wa;
+#if USEXINERAMA
+ XineramaScreenInfo *info;
+ Window pw;
+ int a, n, area = 0;
+#endif
+
+ // set properties indicating what spmenu handles
+ clip = XInternAtom(dpy, "CLIPBOARD", False);
+ utf8 = XInternAtom(dpy, "UTF8_STRING", False);
+ types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+ dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
+
+ // resize client
+ bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
+ lines = MAX(lines, 0);
+ reallines = lines;
+
+ // resize client to image height if deemed necessary
+#if USEIMAGE
+ if (image) resizetoimageheight(imageheight);
+#endif
+
+ mh = (lines + 1) * bh + 2 * menumarginv; // lines + 1 * bh is the menu height
+
+ // set prompt width based on prompt size
+ promptw = (prompt && *prompt)
+ ? pango_prompt ? TEXTWM(prompt) : TEXTW(prompt) - lrpad / 4 : 0; // prompt width
+
+ // get accurate width
+ if (accuratewidth) {
+ for (item = items; !lines && item && item->text; ++item) {
+ curstrlen = strlen(item->text);
+ if (numwidthchecks || minstrlen < curstrlen) {
+ numwidthchecks = MAX(numwidthchecks - 1, 0);
+ minstrlen = MAX(minstrlen, curstrlen);
+ if ((tmp = MIN(TEXTW(item->text), mw/3) > inputw)) {
+ inputw = tmp;
+ if (tmp == mw/3)
+ break;
+ }
+ }
+ }
+ }
+
+ // init xinerama screens
+#if USEXINERAMA
+ i = 0;
+ if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
+ XGetInputFocus(dpy, &w, &di);
+ if (mon >= 0 && mon < n)
+ i = mon;
+ else if (w != root && w != PointerRoot && w != None) {
+ // find top-level window containing current input focus
+ do {
+ if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
+ XFree(dws);
+ } while (w != root && w != pw);
+ // find xinerama screen with which the window intersects most
+ if (XGetWindowAttributes(dpy, pw, &wa))
+ for (j = 0; j < n; j++)
+ if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
+ area = a;
+ i = j;
+ }
+ }
+ // no focused window is on screen, so use pointer location instead
+ if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
+ for (i = 0; i < n; i++)
+ if (INTERSECT(x, y, 1, 1, info[i]))
+ break;
+
+ // calculate x/y position
+ if (menuposition == 2) { // centered
+ mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
+ x = info[i].x_org + ((info[i].width - mw) / 2);
+ y = info[i].y_org + ((info[i].height - mh) / 2);
+ } else { // top or bottom
+ x = info[i].x_org + xpos;
+ y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
+ mw = (menuwidth>0 ? menuwidth : info[i].width);
+ }
+
+ XFree(info);
+ } else
+#endif
+ {
+ if (!XGetWindowAttributes(dpy, parentwin, &wa))
+ die("spmenu: could not get embedding window attributes: 0x%lx",
+ parentwin); // die because unable to get attributes for the parent window
+
+ if (menuposition == 2) { // centered
+ mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
+ x = (wa.width - mw) / 2;
+ y = (wa.height - mh) / 2;
+ } else { // top or bottom
+ x = 0;
+ y = menuposition ? 0 : wa.width - mh - ypos;
+ mw = wa.width;
+ }
+ }
+
+ // might be faster in some instances, most of the time unnecessary
+ if (!accuratewidth) inputw = MIN(inputw, mw/3);
+
+ match(); // match entries
+
+ // create menu window and set properties for it
+ create_window(x + sp, y + vp - (menuposition == 1 ? 0 : menuposition == 2 ? borderwidth : borderwidth * 2), mw - 2 * sp - borderwidth * 2, mh);
+ set_window();
+ set_prop();
+
+#if USEIMAGE
+ setimageopts();
+#endif
+
+ // input methods
+ if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
+ XSetLocaleModifiers("@im=local");
+ if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
+ XSetLocaleModifiers("@im=");
+ if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
+ die("XOpenIM failed: could not open input device");
+ }
+ }
+
+ xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow, win, XNFocusWindow, win, NULL);
+
+ XMapRaised(dpy, win);
+
+ XSync(dpy, False);
+ XGetWindowAttributes(dpy, win, &wa);
+
+ if (wa.map_state == IsViewable) // must be viewable, otherwise we get a BadMatch error
+ XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
+
+ // embed spmenu inside parent window
+ if (embed) {
+ XReparentWindow(dpy, win, parentwin, x, y);
+ XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
+ if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
+ for (i = 0; i < du && dws[i] != win; ++i)
+ XSelectInput(dpy, dws[i], FocusChangeMask);
+ XFree(dws);
+ }
+ grabfocus();
+ }
+
+ // resize and draw
+ drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
+ drawmenu();
+}
diff --git a/libs/x11/init.h b/libs/x11/init.h
new file mode 100644
index 0000000..b9f2d77
--- /dev/null
+++ b/libs/x11/init.h
@@ -0,0 +1 @@
+static void setupdisplay(void);
diff --git a/libs/key.c b/libs/x11/key.c
similarity index 100%
rename from libs/key.c
rename to libs/x11/key.c
diff --git a/libs/key.h b/libs/x11/key.h
similarity index 100%
rename from libs/key.h
rename to libs/x11/key.h
diff --git a/libs/mouse.c b/libs/x11/mouse.c
similarity index 100%
rename from libs/mouse.c
rename to libs/x11/mouse.c
diff --git a/libs/mouse.h b/libs/x11/mouse.h
similarity index 100%
rename from libs/mouse.h
rename to libs/x11/mouse.h
diff --git a/libs/xrdb.c b/libs/x11/xrdb.c
similarity index 100%
rename from libs/xrdb.c
rename to libs/x11/xrdb.c
diff --git a/libs/xrdb.h b/libs/x11/xrdb.h
similarity index 100%
rename from libs/xrdb.h
rename to libs/x11/xrdb.h
diff --git a/libs/xresources.h b/libs/x11/xresources.h
similarity index 100%
rename from libs/xresources.h
rename to libs/x11/xresources.h
diff --git a/spmenu.c b/spmenu.c
index d71f49a..09b242a 100644
--- a/spmenu.c
+++ b/spmenu.c
@@ -1,9 +1,9 @@
/* spmenu - fancy dynamic menu
*
* If you're looking for functions used to draw text, see 'libs/draw.c'
- * If you're looking for wrapper functions used inside the draw functions, see 'libs/sl/draw.c'
+ * If you're looking for wrapper functions used inside the draw functions, see 'libs/libdrw/drw.c'
* If you're looking for functions used to draw images, see 'libs/img.c'
- * If you're looking for the .Xresources array, see 'libs/xresources.h'
+ * If you're looking for the .Xresources array, see 'libs/x11/xresources.h'
*
* You don't need to edit spmenu.c if you aren't making big changes to the software.
*
@@ -118,13 +118,14 @@ static int allowkeys = 1; // whether or not to interpret a keypress as an insert
// various headers
#include "libs/libdrw/drw.h"
#include "libs/sl/main.h"
+#include "libs/x11/init.h"
#include "libs/draw.h"
#include "libs/stream.h"
#include "libs/schemes.h"
#include "libs/arg.h"
-#include "libs/xrdb.h"
-#include "libs/key.h"
-#include "libs/mouse.h"
+#include "libs/x11/xrdb.h"
+#include "libs/x11/key.h"
+#include "libs/x11/mouse.h"
#include "libs/sort.h"
#include "libs/history.h"
@@ -237,7 +238,6 @@ static void grabfocus(void);
static void pastesel(void);
static void appenditem(struct item *item, struct item **list, struct item **last);
static void xinitvisual(void);
-static void setupdisplay(void);
static int max_textw(void);
static size_t nextrune(int inc);
@@ -252,7 +252,7 @@ static int listchanged = 0;
#include "mouse.h"
// xresources/color arrays
-#include "libs/xresources.h"
+#include "libs/x11/xresources.h"
#include "libs/colors.h"
static char *fonts[] = { font };
@@ -273,16 +273,16 @@ static char *(*fstrstr)(const char *, const char *) = cistrstr;
#include "libs/img.c"
#include "libs/rtl.h"
#include "libs/rtl.c"
-#include "libs/key.c"
-#include "libs/mouse.c"
+#include "libs/x11/key.c"
+#include "libs/x11/mouse.c"
#include "libs/sort.c"
#include "libs/draw.c"
#include "libs/schemes.c"
#include "libs/argv.h"
#include "libs/argv.c"
-#include "libs/xrdb.c"
-#include "libs/client.h"
-#include "libs/client.c"
+#include "libs/x11/xrdb.c"
+#include "libs/x11/client.h"
+#include "libs/x11/client.c"
#include "libs/match.h"
#include "libs/match.c"
#include "libs/history.c"
@@ -290,6 +290,7 @@ static char *(*fstrstr)(const char *, const char *) = cistrstr;
#include "libs/stream.c"
#include "libs/event.h"
#include "libs/event.c"
+#include "libs/x11/init.c"
int is_selected(size_t index) {
for (int i = 0; i < sel_size; i++) {
@@ -554,173 +555,6 @@ void xinitvisual(void) {
}
}
-void setupdisplay(void) {
- int x, y, i;
-#if USEXINERAMA
- int j, di;
-#endif
- unsigned int du;
- unsigned int tmp, minstrlen = 0, curstrlen = 0;
- int numwidthchecks = 100;
- struct item *item;
- XIM xim;
- Window w, dw, *dws;
- XWindowAttributes wa;
-#if USEXINERAMA
- XineramaScreenInfo *info;
- Window pw;
- int a, n, area = 0;
-#endif
-
- init_appearance(); // init colorschemes by reading arrays
-
- // set properties indicating what spmenu handles
- clip = XInternAtom(dpy, "CLIPBOARD", False);
- utf8 = XInternAtom(dpy, "UTF8_STRING", False);
- types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
-
- // resize client
- bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
- lines = MAX(lines, 0);
- reallines = lines;
-
- // resize client to image height if deemed necessary
-#if USEIMAGE
- if (image) resizetoimageheight(imageheight);
-#endif
-
- mh = (lines + 1) * bh + 2 * menumarginv; // lines + 1 * bh is the menu height
-
- // set prompt width based on prompt size
- promptw = (prompt && *prompt)
- ? pango_prompt ? TEXTWM(prompt) : TEXTW(prompt) - lrpad / 4 : 0; // prompt width
-
- // get accurate width
- if (accuratewidth) {
- for (item = items; !lines && item && item->text; ++item) {
- curstrlen = strlen(item->text);
- if (numwidthchecks || minstrlen < curstrlen) {
- numwidthchecks = MAX(numwidthchecks - 1, 0);
- minstrlen = MAX(minstrlen, curstrlen);
- if ((tmp = MIN(TEXTW(item->text), mw/3) > inputw)) {
- inputw = tmp;
- if (tmp == mw/3)
- break;
- }
- }
- }
- }
-
- // init xinerama screens
-#if USEXINERAMA
- i = 0;
- if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
- XGetInputFocus(dpy, &w, &di);
- if (mon >= 0 && mon < n)
- i = mon;
- else if (w != root && w != PointerRoot && w != None) {
- // find top-level window containing current input focus
- do {
- if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
- XFree(dws);
- } while (w != root && w != pw);
- // find xinerama screen with which the window intersects most
- if (XGetWindowAttributes(dpy, pw, &wa))
- for (j = 0; j < n; j++)
- if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
- area = a;
- i = j;
- }
- }
- // no focused window is on screen, so use pointer location instead
- if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
- for (i = 0; i < n; i++)
- if (INTERSECT(x, y, 1, 1, info[i]))
- break;
-
- // calculate x/y position
- if (menuposition == 2) { // centered
- mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
- x = info[i].x_org + ((info[i].width - mw) / 2);
- y = info[i].y_org + ((info[i].height - mh) / 2);
- } else { // top or bottom
- x = info[i].x_org + xpos;
- y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
- mw = (menuwidth>0 ? menuwidth : info[i].width);
- }
-
- XFree(info);
- } else
-#endif
- {
- if (!XGetWindowAttributes(dpy, parentwin, &wa))
- die("spmenu: could not get embedding window attributes: 0x%lx",
- parentwin); // die because unable to get attributes for the parent window
-
- if (menuposition == 2) { // centered
- mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
- x = (wa.width - mw) / 2;
- y = (wa.height - mh) / 2;
- } else { // top or bottom
- x = 0;
- y = menuposition ? 0 : wa.width - mh - ypos;
- mw = wa.width;
- }
- }
-
- // might be faster in some instances, most of the time unnecessary
- if (!accuratewidth) inputw = MIN(inputw, mw/3);
-
- match(); // match entries
-
- // create menu window and set properties for it
- create_window(x + sp, y + vp - (menuposition == 1 ? 0 : menuposition == 2 ? borderwidth : borderwidth * 2), mw - 2 * sp - borderwidth * 2, mh);
- set_window();
- set_prop();
-
-#if USEIMAGE
- setimageopts();
-#endif
-
- // input methods
- if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
- XSetLocaleModifiers("@im=local");
- if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
- XSetLocaleModifiers("@im=");
- if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
- die("XOpenIM failed: could not open input device");
- }
- }
-
- xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, win, XNFocusWindow, win, NULL);
-
- XMapRaised(dpy, win);
-
- XSync(dpy, False);
- XGetWindowAttributes(dpy, win, &wa);
-
- if (wa.map_state == IsViewable) // must be viewable, otherwise we get a BadMatch error
- XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
-
- // embed spmenu inside parent window
- if (embed) {
- XReparentWindow(dpy, win, parentwin, x, y);
- XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
- if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
- for (i = 0; i < du && dws[i] != win; ++i)
- XSelectInput(dpy, dws[i], FocusChangeMask);
- XFree(dws);
- }
- grabfocus();
- }
-
- // resize and draw
- drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
- drawmenu();
-}
-
int main(int argc, char *argv[]) {
XWindowAttributes wa;
@@ -804,6 +638,7 @@ int main(int argc, char *argv[]) {
}
#endif
+ init_appearance(); // init colorschemes by reading arrays
setupdisplay(); // set up display and create window
eventloop(); // function is a loop which checks X11 events and calls other functions accordingly