xaizek / euclid-wm (License: BSD 3-Clause) (since 2018-12-07)
A minimalist, tiling window manager for X11 that seeks to allow easy management of numerous windows entirely from the keyboard.
Commit 781596c2576fefefaa6ea6fdd3a16874598230cd

Added euclid-menu and handlers; updated makefile to compile and install
Author: wmdiem
Author date (UTC): 2014-02-16 16:09
Committer name: wmdiem
Committer date (UTC): 2014-02-16 16:09
Parent(s): 7dad795c87753587e132e9b12debf7e0756e8ad7
Signing key:
Tree: 7b465f1e1fe007b7e6e82f8e8fc6a11d8e5811ed
File Lines added Lines deleted
Makefile 13 1
euclid-menu.c 784 0
handlers/.echo_file.sh 14 0
handlers/c.sh 9 0
handlers/default.sh 11 0
File Makefile changed (mode: 100644) (index fb41872..9c9c330)
... ... LDFLAGS = -lX11 -lXinerama
18 18
19 19 .PHONY: all install install_conf clean uninstall dist dist_clean .PHONY: all install install_conf clean uninstall dist dist_clean
20 20
21 all: euclid-wm
21 all: euclid-wm euclid-menu
22 22
23 23 euclid-wm: euclid-wm.c euclid-wm: euclid-wm.c
24 24 ${CC} $< ${LDFLAGS} ${CFLAGS} -o $@ ${CC} $< ${LDFLAGS} ${CFLAGS} -o $@
25 25
26 euclid-menu: euclid-menu.c
27 ${CC} $< ${LDFLAGS} ${CFLAGS} -o $@
28
26 29 noxinerama: euclid-wm.c noxinerama: euclid-wm.c
27 30 ${CC} $< -lX11 ${CFLAGS} -D NOXINERAMA -o $@ ${CC} $< -lX11 ${CFLAGS} -D NOXINERAMA -o $@
28 31 cp noxinerama euclid-wm cp noxinerama euclid-wm
 
... ... install: all
36 39 @install -m644 VERSION -D ${DESTDIR}/${SHAREDIR}/euclid-wm/VERSION 2>/dev/null || echo "From SVN: `svn info | grep Revision: | cut -d ' ' -f2`/`date +%F`" >${DESTDIR}/${SHAREDIR}/euclid-wm/VERSION @install -m644 VERSION -D ${DESTDIR}/${SHAREDIR}/euclid-wm/VERSION 2>/dev/null || echo "From SVN: `svn info | grep Revision: | cut -d ' ' -f2`/`date +%F`" >${DESTDIR}/${SHAREDIR}/euclid-wm/VERSION
37 40 @sed s_/usr/share_/${SHAREDIR}_ <start-euclid >start-euclid-local @sed s_/usr/share_/${SHAREDIR}_ <start-euclid >start-euclid-local
38 41 @install -m755 start-euclid-local -D ${DESTDIR}/${BINDIR}/start-euclid @install -m755 start-euclid-local -D ${DESTDIR}/${BINDIR}/start-euclid
42 @install -m755 euclid-menu -D ${DESTDIR}/${BINDIR}/euclid-menu
43 @install -m755 ./handlers/c.sh -D ${DESTDIR}/${SHAREDIR}/euclid-menu/handlers/c.sh
44 @install -m755 ./handlers/default.sh -D ${DESTDIR}/${SHAREDIR}/euclid-menu/handlers/default.sh
45 @install -m755 ./handlers/.echo_file.sh -D ${DESTDIR}/${SHAREDIR}/euclid-menu/handlers/.echo_file.sh
46
47
39 48
40 49 install_conf: install_conf:
41 50 @install -b -D -m600 euclid-wm.conf.sample ${CONFDIR}/euclid-wm.conf @install -b -D -m600 euclid-wm.conf.sample ${CONFDIR}/euclid-wm.conf
 
... ... uninstall:
45 54 rm -f ${DESTDIR}/${BINDIR}/euclid-wm rm -f ${DESTDIR}/${BINDIR}/euclid-wm
46 55 rm -f ${DESTDIR}/${SHAREDIR}/xsessions/euclid.desktop rm -f ${DESTDIR}/${SHAREDIR}/xsessions/euclid.desktop
47 56 rm -f ${DESTDIR}/${MANDIR}/man1/euclid-wm.1 rm -f ${DESTDIR}/${MANDIR}/man1/euclid-wm.1
57 rm -f ${DESTDIR}/${BINDIR}/euclid-menu
58 rm -rf ${DESTDIR}/${SHAREDIR}/euclid-menu/
48 59
49 60 clean: clean:
50 61 rm -f euclid-wm rm -f euclid-wm
51 62 rm -f start-euclid-local rm -f start-euclid-local
52 63 rm -f noxinerama rm -f noxinerama
64 rm -f euclid-menu
53 65
54 66 dist: dist:
55 67 mkdir ${DIST} mkdir ${DIST}
File euclid-menu.c added (mode: 100644) (index 0000000..0ed2310)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <stdbool.h>
5 #include <string.h>
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/Xatom.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <dirent.h>
13 #include <sys/stat.h>
14 #include <poll.h>
15
16 #include <X11/extensions/Xinerama.h>
17
18 #define MAX_RESULTS 2000
19 #define MAX_HANDLERS 20
20
21 Display *dpy;
22 Window root;
23 unsigned long focus_pix;
24 unsigned long unfocus_pix;
25 unsigned long background_pix;
26 //etc.
27 Window wid;
28 char buf[128];
29 short unsigned int pos = 0;
30 int sxo, syo, sh, sw, sn;
31 int fh;
32 GC focus_gc = NULL;
33 GC unfocus_gc = NULL;
34 XIC xic;
35 XFontSet xfs;
36 char *handler = NULL;
37 int nu_results;
38 char *results[MAX_RESULTS];
39 size_t result_size[MAX_RESULTS];
40 int results_cmdchar[MAX_RESULTS];
41 int h_opt = -1;
42 char **handler_dir;
43 char *handlers[MAX_HANDLERS];
44 char *handlers_trimmed[MAX_HANDLERS];
45 FILE *fin = NULL;
46 FILE *fout = NULL;
47
48 int xerror(Display *d, XErrorEvent *e) {
49 //get and print the error description for diagnostics:
50 char buff[256];
51 XGetErrorText(dpy, e->error_code, buff, 256);
52 fprintf(stderr,"slaunch ERROR: X error: %s\n",buff);
53 //if the error is badwindow die, otherwise we keep the keyboard
54 return(0);
55 }
56
57 void spawn(char *cmd) {
58 if (cmd == NULL || cmd[0] == '\0') {
59 return;
60 };
61 setsid(); //need this?
62 char cmd2[512];
63 strcpy (&cmd2[0],"exec ");
64 strcpy (&cmd2[5],cmd);
65 cmd2[strlen (cmd2)+1] = '\0';
66 execl("/bin/sh","/bin/sh","-c",cmd2,NULL);
67 fprintf(stderr,"error number %d spawning %s\n",errno,cmd);
68 exit(1);
69
70 }
71
72
73 void draw_win () {
74 int x = sxo;
75 int y = syo;
76 int ih = fh + 5;
77 int h = (((nu_results+1) * (ih)) > (sh / 2)) ? (sh / 2) : ((nu_results+1) * (ih)) ;
78 int w = sw;
79 int lo = 0; //line offset
80 XClearWindow(dpy,wid);
81
82 XMoveResizeWindow(dpy,wid,x,y,w-2,h);
83 XRaiseWindow(dpy,wid);
84 XSync(dpy,false);//important!
85 GC gc;
86 gc = focus_gc;
87 char *str = NULL;
88 if (h_opt == -1) {
89 str = buf;
90 } else {
91 str = results[h_opt]+results_cmdchar[h_opt];
92 };
93 lo += fh;
94 lo += 2;
95
96 int cx = 0;
97 XDrawString(dpy,wid,gc,3,lo,str, strlen(str));
98 if (h_opt != -1) {//but the cursor at the end of the displayed option, leaving pos unchanged
99 cx = XmbTextEscapement(xfs,str,strlen(str));
100
101 } else { //draw it at pos
102 cx = XmbTextEscapement(xfs,str,pos);
103 };
104 XDrawLine(dpy,wid,focus_gc,cx+2,2,cx+2,fh+3);
105 //write results here
106
107 //we need to know how many results we can display, so we can figure out where to stawt drawing
108 int items = h / ih; //ih is the height of each item
109 items--; //at this point items is really "max items" we can display
110 int ro = 0; //results offset
111 if (items > nu_results) {
112 ro = 0; //they all fiti: ro is beasicaly how far down the list of results we start displaying
113 } else if (h_opt < items / 2) { //h_opt is the highlighted option/result
114 ro = 0;
115 } else if (nu_results - h_opt > items / 2) {
116 ro = h_opt - items / 2;
117 } else {
118 ro = nu_results - items;
119 };
120
121 items = items < nu_results ? items : nu_results;
122
123
124 int i = 0;
125 //printf("%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",str,h_opt,nu_results,i,lo,h,ro,items);
126 while (i < items ) {
127 lo += fh;
128 lo += 5;
129 gc = h_opt != i+ro ? unfocus_gc : focus_gc;
130 XDrawString(dpy,wid,gc,3,lo,results[i+ro],strlen(results[i+ro]));
131 //printf("%s",results[i+ro]);
132 i++;
133 };
134 XSync(dpy,false);
135
136 };
137
138 inline char* trim_name(char* file) {
139 char * ret[32];
140 int i = 0;
141 while (file[i] != '\0' && file[i] != '.' && i < 32) {
142
143 ret[i] = file[i];
144 i++;
145 };
146 ret[i < 32 ? i : 32] = '\0';
147 // printf("%s\n",ret);
148 return(ret);
149
150 };
151 void load_handlers() {
152 //find xdg_config_home
153 /*char *xdgconf = getenv("XDG_CONFIG_HOME");
154
155 if (xdgconf) {
156 handler_dir = malloc(strlen(xdgconf) + strlen("/euclid-menu/handlers/") + 1);
157 handler_dir[0] = '\0';
158 strcpy(handler_dir,xdgconf);
159 strcat(handler_dir,"/euclid-menu/handlers/");
160 } else {
161 char *home = getenv("HOME");
162 handler_dir = (char *) malloc(strlen(home) + strlen("/.config/euclid-menu/handlers/") + 1);
163 handler_dir[0] = '\0';
164 strcpy(handler_dir,home);
165 strcat(handler_dir,"/.config/euclid-menu/handlers/");
166 };
167 */
168 handler_dir = (char *) malloc(strlen("/usr/share/euclid-menu/handlers/") + 1);
169 handler_dir[0] = '\0';
170 strcpy(handler_dir,"/usr/share/euclid-menu/handlers/");
171 if (handlers[0] == NULL) {
172 DIR *dir;
173 struct dirent *de;
174 struct stat stt;
175 dir = opendir(handler_dir);
176 if (!dir) {
177 //printf("shit\n");
178 };
179 chdir(handler_dir);
180 int i = 0;
181 do {
182 //do stuff
183 de = NULL;
184 de = readdir(dir);
185 if (de) {
186 stat(de->d_name,&stt);
187 //printf("Name %s permissions %lo\n", de->d_name,(unsigned long) stt.st_mode);
188 if (stt.st_mode & S_IXUSR && de->d_name[0] != '.') {
189 handlers[i] = strdup(de->d_name);
190 handlers_trimmed[i] = strdup(de->d_name);
191 int j = 0;
192 while (handlers_trimmed[i][j] != '\0' && handlers_trimmed[i][j] != '.') {
193 handlers_trimmed[i][j] = handlers[i][j];
194 j++;
195 };
196 handlers_trimmed[i][j] = '\0';
197 i++;
198 };
199 };
200 if (i < MAX_HANDLERS) {
201 handlers[i] = NULL;
202 handlers_trimmed[i] = NULL;
203 };
204 //save name in araray
205 } while (de && i < MAX_HANDLERS) ;
206 };
207
208 //read all files
209 //store the names of all that are executable in a linked list
210 chdir(getenv("HOME")); //so when we run a program it isn't in a config dir.
211 };
212
213 inline char* find_handler() {
214 //read buf use an aray to pick the appropriate file handler and return the command
215 //what is here now is a bit simple, we need to also check the end of the line to see whether the returned command is prompting for another handler (e.g., if the command takes a filename or a URL as an argument
216 if (buf[0] == '!') {
217 if (buf[1] != '\0') {
218 //find match:
219 int i = 0;
220 while (i < MAX_HANDLERS && handlers[i] != NULL) {
221
222 if (!strcmp(&buf[1],handlers_trimmed[i])){
223 return(handlers[i]);
224 };
225 i++;
226 };
227 } else {
228 //we set the options to a list of handlers, and return null
229
230 //char *ret = (char *) malloc(strlen("echo -e \"\!c\tcalculate\\n\!s\tshell command\"")+1);
231 //strcpy(ret,"echo \"\!c calculate\n\!s shell command\"");
232 //use realloc to make sure there is roome
233 //must update the bytesize for each changed option
234 //must also update nu_return
235 //results, nu_results, result_size
236 int i = 0;
237 while (i < MAX_HANDLERS && handlers[i] != NULL) {
238 //check the size of the allocated memory?
239 //printf("\t%s\n",trim_name(handlers[i]));
240 if (results[i] == NULL) {
241 results[i] = (char *) malloc(strlen(handlers_trimmed[i] + 5));
242 };
243 if (strlen(handlers_trimmed[i]) +1 <= strlen(results[i])) {
244 strcpy(results[i],"!");
245 strcat(results[i],handlers_trimmed[i]);
246
247 } else {
248 results[i] = realloc(results[i],strlen(handlers_trimmed[i]) + 1);
249
250 result_size[i] = strlen(handlers_trimmed[i]) + 1;
251 strcpy(results[i],"!");
252 strcat(results[i],handlers_trimmed[i]);
253 };
254 //printf("%s\n",results[i]);
255 i++;
256 };
257 nu_results = i;
258 //we need to close the pipes
259 if (fin) {
260 fclose(fin);
261 fin = NULL;
262 };
263 if (fout) {
264 fclose(fout);
265 fout = NULL;
266 };
267 //instead of returning a string, we want to return a pair of pipes, one the stdin for the hanlder, the other it's standard out
268 //is this what we want here?
269 return(NULL);
270
271 };
272 } else { //default handerl
273 //char *ret = (char *) malloc(strlen("ls /usr/bin")+1);
274 //strcpy(ret,"ls /usr/bin");
275 int i = 0;
276 while (i < MAX_HANDLERS && handlers[i] != NULL && strcmp(handlers_trimmed[i],"default")) {
277 i++;
278 };
279 if (!handlers[i]) {
280 nu_results = 0;
281 h_opt = -1;
282 };
283 return(handlers[i]); //could be null;
284 };
285 };
286
287
288 void setup_pipes(char *cmd) {
289 //sets up a pair of pipes for bidirectional communicaiton with handler, and forks, in the child it then uses sets its STDIN and STDOUT to the pipes and execs the handler
290 static int pid;
291 int pipes[2][2];
292
293 if (fin) {
294 fclose(fin);
295 kill(pid,15);
296 };
297 if (fout) {
298 fclose(fout);
299 kill(pid,15);
300 };
301
302 if (cmd) {
303 //cat the handler to handler_dir
304 //we really out to do this only once and store it
305 char *cmd2 = (char*) malloc(strlen(cmd) + strlen(handler_dir) + strlen(buf) + 5);
306 strcpy(cmd2,handler_dir);
307 strcat(cmd2,cmd);
308 /* strcat(cmd2," ");
309 // have to strip the handler name from the front of buf
310 if (buf[0] == '!') {
311 int i = 0;
312 while (buf[i] != '\0' && buf[i] != ' ') {
313 i++;
314 };
315 strcat(cmd2,&buf[i]);
316 } else {
317 strcat(cmd2,buf);
318 };
319 */
320 //printf("Getting options from %s\n",cmd2);
321
322 pipe(pipes[0]);
323 pipe(pipes[1]);
324
325 pid = fork();
326
327 if (pid==0) { //child
328 if(dpy) {
329 close(ConnectionNumber(dpy));
330 };
331 close(pipes[0][0]);
332 close(pipes[1][1]);
333 dup2(pipes[0][1],STDOUT_FILENO);
334 dup2(pipes[1][0],STDIN_FILENO);
335 setvbuf(stdout,NULL,_IONBF,0);
336
337 execl("/bin/sh","/bin/sh","-c",cmd2,NULL);
338
339 } else { //parent
340
341 close(pipes[0][1]);
342 close(pipes[1][0]);
343 fin = fdopen(pipes[0][0],"r");
344 fout = fdopen(pipes[1][1],"w");
345 setvbuf(fout,NULL,_IONBF,0);
346 free(cmd2);
347 };
348 };
349 }
350
351
352 void update_options() {
353 // char rbuf[256];
354 // memset(rbuf,'\0',sizeof(rbuf));
355 // nu_results = 0;
356 /* if (cmd) {
357 //cat the handler to handler_dir
358 //we really out to do this only once and store it
359 char *cmd2 = (char*) malloc(strlen(cmd) + strlen(handler_dir) + strlen(buf) + 5);
360 strcpy(cmd2,handler_dir);
361 strcat(cmd2,cmd);
362 strcat(cmd2," ");
363 // have to strip the handler name from the front of buf
364 if (buf[0] == '!') {
365 int i = 0;
366 while (buf[i] != '\0' && buf[i] != ' ') {
367 i++;
368 };
369 strcat(cmd2,&buf[i]);
370 } else {
371 strcat(cmd2,buf);
372 };
373 //printf("Getting options from %s\n",cmd2);
374
375
376 FILE *ret;
377 //must add the buffer to the end of cmd
378 ret = (FILE *) popen(cmd2,"r");
379 if (ret) { */
380 //char *l = NULL;
381 //size_t n = 0;
382
383 //print buf to fout
384 // fflush(fin); //make sure any cruft left over from last time is out
385 if (fout) {
386 //printf("out is open\n");
387 int i = 1;
388 if (buf[0] == '!') { //trim handler name
389 while (buf[i] != '\0' && buf[i-1] !=' ') {
390 i++;
391 };
392 } else {
393 i = 0;
394 };
395 //if (buf[i] == '\0') return;
396 fprintf(fout,"%s\n",&buf[i]);
397
398 if(fin) {
399 //printf("checking\n");
400 i = 0;
401 bool break_next = false;
402
403 while (i < MAX_RESULTS && getline(&results[i],&result_size[i],fin) != -1) {
404
405 //printf("-> %s",results[i]);
406 //sanitize results now
407 results_cmdchar[i] = 0;
408 int j = 0;
409 int k = 0;
410 while (results[i][j] != '\0') {
411 if(results[i][j] == '\t'){
412 //copy a '\0' to that position, record the address of the next byte in another array so we can get to the command
413 results[i][k] = '\0';
414 results_cmdchar[i] = k + 1;
415 k++;
416 } else if (!iscntrl(results[i][j])) {
417 results[i][k] = results[i][j];
418 k++;
419 };
420 j++;
421 };
422 results[i][k] = '\0';
423 //i++;
424 if (*results[i]) { //write over empty lines and break if we get two consecutive empty lines
425 i++;
426 break_next = false;
427 } else {
428 if (break_next) break;
429 break_next = true;
430 };
431 };
432 nu_results = i; //+1;
433 //printf("%d\n",i);
434 // fclose(ret);
435 // free(cmd2);
436 };
437 };
438 // };
439 }
440
441 char* loop () {
442 XEvent ev;
443 KeySym key;
444 Status stat;
445 char txt[128];
446 char *t_exec = NULL;
447 int len = 0;
448 while (!t_exec) {
449 bool draw = false;
450 bool check = false;
451 do {
452 XNextEvent(dpy, &ev);
453 //all we care about are keypresses
454 if (ev.type == KeyPress) {
455 key = NoSymbol;
456 len = XmbLookupString(xic,&ev.xkey,txt, sizeof(txt),&key,&stat);
457 //XLookupKeysym(); //big long mess
458 //if the keypress is escape we leave, i.e., return NULL
459 //if it is home, end, right, left we modify position (but if pos is already the end of buff, and it is right we set buff == cur_option->exec
460 //if it is del of backspace, we modify buf and pos
461 //if it is a printable character we insert it into buf at pos
462 //if it is enter we set t_exec to the currenetly selected option, if any, else buf
463 //if it is up or down we select option
464 //if buffer was changed, we call a function to determine the handler, spawn handler as a pipe and update options
465 //if there was any keypress we always end with a call of draw_win() unless, we already returned
466 //if buf[1or buf[0]] gets touched free the handler
467 if (key == XK_Escape) {
468 //printf("ending\n");
469 return NULL;
470 } else if (key == XK_Left) {
471 if (h_opt == -1 && pos > 0) {
472 pos --;
473 } else {
474 h_opt = -1;
475 };
476 draw = true;
477 } else if (key == XK_Right) {
478 if (h_opt == -1 && buf[pos] != '\0') {
479 pos ++;
480 } else {
481 h_opt = -1;
482 };
483 draw = true;
484 } else if (key == XK_BackSpace) {
485 if (h_opt != -1) {
486 h_opt=-1;
487 draw = true;
488 } else if (pos > 0) {
489 pos--;
490 int t = pos;
491 h_opt = -1;
492 //buf[pos]='\0'; //too easy, have to copy whaterver is past pos, set it to \0 then cat it back
493 while (t > 0 && buf[t] != '\0') {
494 buf[t] = buf[t+1];
495 t++;
496 };
497 buf[t] = '\0';
498 // if (pos < 2 && handler) {
499 // handler = NULL;
500 // };
501 draw = true;
502 check = true;
503 };
504 } else if (key == XK_Delete && buf[pos] != '\0') {
505 int t = pos;
506 h_opt = -1;
507 while (buf[t] != '\0') {
508 buf[t] = buf[t+1] ;
509 t++;
510 };
511 // if (pos < 2 && handler) {
512 // //free(handler);
513 // handler = NULL;
514 // };
515
516 draw = true;
517 check = true;
518 } else if (key == XK_Up) {
519 if (h_opt > -1) {
520 h_opt--;
521 } else {
522 h_opt = nu_results -1;
523 };
524 draw = true;
525 } else if (key == XK_Down) {
526 if ( h_opt < (nu_results - 1)) {
527 h_opt++;
528 }else {
529 h_opt = -1;
530 };
531 draw = true;
532
533 } else if (key == XK_Home) {
534 if (h_opt == -1) {
535 pos = 0;
536 } else {
537 h_opt = -1;
538 };
539 draw = true;
540 } else if (key == XK_End) {
541 if (h_opt == -1) {
542 pos = strlen(buf) + 1;
543 } else {
544 h_opt = nu_results -1;
545 };
546 draw = true;
547 } else if (key == XK_Tab) {
548 if (h_opt == -1) {
549 h_opt = 0;
550 };
551
552 strcpy(buf,results[h_opt]+results_cmdchar[h_opt]);
553 pos = strlen(buf);
554 h_opt = -1;
555
556 // };
557 check = true;
558 draw = true;
559
560 } else if (key == XK_Return) {
561 if (nu_results) {
562 if (h_opt == -1) {
563 t_exec = results[0]+results_cmdchar[0];
564 } else {
565 t_exec = results[h_opt]+results_cmdchar[h_opt];
566 };
567 } else {
568 t_exec = buf;
569 };
570 return(t_exec);
571
572 } else if (!iscntrl(*txt) ) {
573
574 // printf("%c\n",key);
575 //if (h_opt != -1) {
576 // strcpy(buf,results[h_opt]);
577 // pos = strlen(buf);
578 // };
579 int t = pos;
580 h_opt = -1;
581 char c = txt[0];
582 char tc = buf[t];
583 while (c != '\0') {
584 tc = buf[t];
585 buf[t] = c;
586 c = tc;
587 t++;
588 };
589 buf[t] = '\0';
590 // if (pos < 2 ) {
591 //free(handler);
592 // handler = NULL;
593 // };
594
595 pos++;
596 buf[t+1] = '\0';
597 draw = true;
598 check = true;
599 };
600
601 };
602 //printf("handler %s\n",handler);
603
604 if (check) {
605 if (handler != NULL) {
606 //determine whether the handler has been changed
607 if (buf[0] == '\0' && strcmp(handler,"default")) {
608 //handler should be default, but isn't
609 handler = NULL;
610 } else if (buf[0] == '!' && buf[1] == '\0' ) {
611 handler = NULL;
612 } else if (buf[0] == '!') {
613 int i = 0;
614 while (buf[i+1] != '\0' && handler[i] != '\0') {
615 if (buf[i+1] != handler[i] && buf[i+1] != ' ') {
616 handler = NULL;
617 break;
618 };
619 i++;
620 };
621 };
622 };
623
624 if (!handler) {
625 handler = find_handler();
626
627 if (handler) {
628 setup_pipes(handler);
629 };
630 };
631 update_options();
632 };
633 if (draw) {
634 draw_win();
635 };
636 } while (XPending(dpy));
637 };
638 return (t_exec);
639 };
640
641 void clean_up() {
642 XFreeFontSet(dpy,xfs);
643 //ungrab keyboard,
644 XUngrabKeyboard(dpy,CurrentTime);
645 // Give focus to root!!!
646 XSetInputFocus(dpy,root,None,CurrentTime);
647 XFreeGC(dpy,focus_gc); //etc
648
649 XDestroyIC(xic);
650
651 XDestroyWindow(dpy,wid);
652 XCloseDisplay(dpy);
653 }
654
655 int main (int argc, char *argv[] ) {
656 //this is to avoid leaving zombies
657 //sighandler_t is a gnu extention
658 signal (SIGCHLD, SIG_IGN);
659
660 dpy = XOpenDisplay(0);
661 XSetErrorHandler(xerror);
662 root = DefaultRootWindow(dpy);
663
664 XColor color;
665 color.red = 100;
666 color.green = 65500;
667 color.blue = 100;
668 color.flags = DoRed | DoGreen | DoBlue;
669 XAllocColor(dpy,DefaultColormap(dpy,DefaultScreen(dpy)),&color);
670 focus_pix = color.pixel;
671
672 color.red = 50000;
673 color.green = 50000;
674 color.blue = 65500;
675 color.flags = DoRed | DoGreen | DoBlue;
676 XAllocColor(dpy,DefaultColormap(dpy,DefaultScreen(dpy)),&color);
677 unfocus_pix = color.pixel;
678
679 color.red = 100;
680 color.green = 100;
681 color.blue = 200;
682 color.flags = DoRed | DoGreen | DoBlue;
683 XAllocColor(dpy,DefaultColormap(dpy,DefaultScreen(dpy)),&color);
684 background_pix = color.pixel;
685
686 XGCValues xgcv;
687 xgcv.foreground = focus_pix;
688 focus_gc = XCreateGC(dpy,root,GCForeground,&xgcv);
689
690 xgcv.foreground = unfocus_pix;
691 unfocus_gc = XCreateGC(dpy,root,GCForeground,&xgcv);
692
693 char **missing;
694 char *def;
695 int nmiss;
696 xfs = XCreateFontSet(dpy,"fixed",&missing,&nmiss,&def);
697 if (missing) {
698 XFreeStringList(missing);
699 };
700 XFontStruct **xfst;
701 char **names;
702 XFontsOfFontSet(xfs,&xfst,&names);
703 fh = xfst[0]->ascent;
704 //look at load_conf and set_atoms
705
706 sh = DisplayHeight(dpy,DefaultScreen(dpy));
707 sw = DisplayWidth(dpy,DefaultScreen(dpy));
708 sxo = 0;
709 syo = 0;
710 sn = 0;
711
712
713 wid = XCreateSimpleWindow(dpy,root,sxo,syo,sw-2,20,1,unfocus_pix,background_pix);
714 XSetWindowAttributes att;
715 att.override_redirect = true;
716 XChangeWindowAttributes(dpy,wid,CWOverrideRedirect,&att);
717 XMapWindow(dpy,wid);
718 XSetInputFocus(dpy,wid,None,CurrentTime);
719 XSync(dpy,False);
720
721 //grab keyboard
722 int i = 0;
723 while (i < 1000 && XGrabKeyboard(dpy,wid,GrabModeAsync,True,GrabModeAsync,CurrentTime) != GrabSuccess) {
724 i++;
725 usleep(1000);
726 };
727 XIM xim = XOpenIM(dpy,NULL,NULL,NULL);
728 //if (!xim) die("No X input method could be opened\n");
729 xic = XCreateIC(xim,XNInputStyle, XIMPreeditNothing | XIMStatusNothing,XNClientWindow, wid, XNFocusWindow, wid, NULL);
730
731 buf[0] = '\0';
732 nu_results = 0;
733
734 bool spawn_exec = true;
735 handlers[0] = NULL;
736 if (argc >= 2) {
737 //printf("checking args\n");
738 //printf("1%s\n2%s",argv[1],argv[2]);
739 int i = 1;
740 while (i < argc) {
741
742 if (!strcmp(argv[i],"-l")) {
743 //printf("locking specified\n");
744 handlers[0] = strdup(argv[i+1]);
745 handlers[1] = NULL;
746 handlers_trimmed[0] = strdup("default");
747 handlers_trimmed[1] = NULL;
748 handler = strdup("default");
749 i++;
750 //printf("handler set to %s",handlers[0]);
751 } else if (!strcmp(argv[i],"-r")) {
752 spawn_exec=false;
753 } else {
754
755 printf("euclid-menu: an extensible interactive menu\nUSAGE:\neuclid-menu -l [handler [handler arguments]] [-r] \n\t-l <handler> lock to the specified handler. Handler must be the name of a file in in the handler folder. \n\t-r Don\'t try to execute final option, just print it.\n");
756 return(0);
757 };
758 i++;
759 };
760 };
761 load_handlers();
762 handler = find_handler();
763 if (handler) {
764 setup_pipes(handler);
765 };
766 update_options();
767 draw_win();
768
769
770 char *exec = loop();
771
772 clean_up();
773
774 if (spawn_exec == true && exec) {
775 //spawn(exec);
776 //make sure we trim any handler from the front if not already done
777 fprintf(fout,"exec %s\n",exec);
778 } else if (exec) {
779 printf("%s",exec);
780 } else {
781 return 0;
782 };
783
784 };
File handlers/.echo_file.sh added (mode: 100644) (index 0000000..d5f8833)
1 #! /bin/sh
2
3 #this handler is meand to read a file containing options specified as $1 and print matches
4
5 if [ $2 ]
6 then
7
8 cat $1 | grep $2
9
10 else
11
12 cat $1
13
14 fi
File handlers/c.sh added (mode: 100644) (index 0000000..dab13e2)
1 #! /bin/sh
2
3 #this is a test scripts
4 A=`echo $@ | bc -l`
5 if [ $A ]
6 then
7 echo $A
8 fi
9
File handlers/default.sh added (mode: 100644) (index 0000000..c36a808)
1 if [ $1 ]
2
3 then
4
5 echo -n $PATH | xargs -d : -I {} find {} -maxdepth 1 -executable -printf '%P\n' | sort -u | grep -i $1
6
7 else
8
9 echo -n $PATH | xargs -d : -I {} find {} -maxdepth 1 -executable -printf '%P\n' | sort -u
10
11 fi
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/euclid-wm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/euclid-wm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master