@@ -212,6 +212,7 @@ static void showhide(Client *c);
212212static void sigchld (int unused );
213213static void spawn (const Arg * arg );
214214static void gather (const Arg * arg );
215+ static void choose (const Arg * arg );
215216
216217static void ignore (const Arg * arg ) {}
217218
@@ -1780,6 +1781,19 @@ spawn(const Arg *arg)
17801781 }
17811782}
17821783
1784+ void
1785+ newterm (const Arg * arg ) {
1786+ for (Client * c = selmon -> clients ; c ; c = c -> next ) {
1787+ if (strstr (c -> name ,arg -> s ))
1788+ c -> tags |= 1 << TMPTAG ;
1789+ else
1790+ c -> tags &= ~(1 <<TMPTAG );
1791+ }
1792+
1793+ view (& (const Arg ){.ui = 1 << TMPTAG });
1794+ setlayout (& (const Arg ){.v = & layouts [0 ]});
1795+ }
1796+
17831797void
17841798gather (const Arg * arg ) {
17851799 for (Client * c = selmon -> clients ; c ; c = c -> next ) {
@@ -1791,6 +1805,95 @@ gather(const Arg* arg) {
17911805
17921806 view (& (const Arg ){.ui = 1 << TMPTAG });
17931807 setlayout (& (const Arg ){.v = & layouts [0 ]});
1808+
1809+ choose (NULL );
1810+ }
1811+
1812+ typedef struct {
1813+ FILE * in , * out , * err ;
1814+ pid_t pid ;
1815+ } StreamSet ;
1816+
1817+ static StreamSet meanwhile (void (* f )(void * ), void * ctx ) {
1818+ int input_pipe [2 ];
1819+ if (pipe (input_pipe ) != 0 )
1820+ return (StreamSet ){0 };
1821+
1822+ int output_pipe [2 ];
1823+ if (pipe (output_pipe ) != 0 )
1824+ return (StreamSet ){0 };
1825+
1826+ int error_pipe [2 ];
1827+ if (pipe (error_pipe ) != 0 )
1828+ return (StreamSet ){0 };
1829+
1830+ pid_t prog_pid = fork ();
1831+ if (prog_pid < 0 )
1832+ return (StreamSet ){0 };
1833+
1834+ else if (prog_pid == 0 ) {
1835+ close (input_pipe [1 ]);
1836+ close (output_pipe [0 ]);
1837+ close (error_pipe [0 ]);
1838+ dup2 (input_pipe [0 ], STDIN_FILENO );
1839+ dup2 (output_pipe [1 ], STDOUT_FILENO );
1840+ dup2 (error_pipe [1 ], STDERR_FILENO );
1841+
1842+ f (ctx );
1843+ exit (0 );
1844+ }
1845+
1846+ close (input_pipe [0 ]);
1847+ close (output_pipe [1 ]);
1848+ close (error_pipe [1 ]);
1849+
1850+ return (StreamSet ){
1851+ .in = fdopen (input_pipe [1 ], "w" ),
1852+ .out = fdopen (output_pipe [0 ], "r" ),
1853+ .err = fdopen (error_pipe [0 ], "r" ),
1854+ .pid = prog_pid
1855+ };
1856+ }
1857+
1858+ static void execute (void * _args ) {
1859+ char * * args = (char * * ) _args ;
1860+
1861+ execvp (args [0 ], args );
1862+ fprintf (stderr , "box: cannot run %s\n" , args [0 ]);
1863+ exit (1 );
1864+ }
1865+
1866+ static void
1867+ choose (const Arg * arg ) {
1868+ (void ) arg ;
1869+ //don't do it if there are no windows to choose
1870+ if (!selmon -> sel ) return ;
1871+
1872+ StreamSet streams = meanwhile (& execute , (char * []){"dmenu" , NULL });
1873+ if (streams .in == NULL )
1874+ fprintf (stderr , "error running dmenu" );
1875+
1876+ int tags = selmon -> seltags ;
1877+ for (Client * c = selmon -> clients ; c ; c = c -> next ) {
1878+ if ((c -> tags & tags ) == tags ) {
1879+ fprintf (streams .in , "%p %s\n" , (void * )c , c -> name );
1880+ }
1881+ }
1882+
1883+ fclose (streams .in );
1884+
1885+ Client * c ;
1886+ if (fscanf (streams .out , "%p" , (void * * )& c ) == 1 ) {
1887+ if (c ) {
1888+ focus (c );
1889+ arrange (selmon );
1890+ }
1891+ } else {
1892+ fprintf (stderr , "couldn't read from dmenu" );
1893+ }
1894+
1895+ fclose (streams .out );
1896+ fclose (streams .err );
17941897}
17951898
17961899void
0 commit comments