diff options
| -rw-r--r-- | client/common/common.c | 8 | ||||
| -rw-r--r-- | lib/renderers/curses/curses.c | 81 | 
2 files changed, 72 insertions, 17 deletions
diff --git a/client/common/common.c b/client/common/common.c index fab2a58..af9fa31 100644 --- a/client/common/common.c +++ b/client/common/common.c @@ -82,7 +82,7 @@ usage(FILE *out, const char *name)            "   (...) At end of help indicates the backend support for option.\n\n"            " -b, --bottom          appears at the bottom of the screen. (x)\n" -          " -f, --grab            grabs the keyboard before reading stdin. (x)\n" +          " -f, --grab            show the menu before reading stdin. (wx)\n"            " -m, --monitor         index of monitor where menu will appear. (x)\n"            " --fn                  defines the font to be used ('name [size]'). (wx)\n"            " --tb                  defines the title background color. (wx)\n" @@ -264,8 +264,12 @@ menu_with_options(struct client *client)      for (uint32_t i = 0; i < BM_COLOR_LAST; ++i)          bm_menu_set_color(menu, i, client->colors[i]); -    if (client->grab) +    if (client->grab) { +        bm_menu_set_filter(menu, "Loading...");          bm_menu_grab_keyboard(menu, true); +        bm_menu_render(menu); +        bm_menu_set_filter(menu, NULL); +    }      return menu;  } diff --git a/lib/renderers/curses/curses.c b/lib/renderers/curses/curses.c index 7d30391..3b9563d 100644 --- a/lib/renderers/curses/curses.c +++ b/lib/renderers/curses/curses.c @@ -32,9 +32,53 @@ static struct curses {      size_t blen;      int old_stdin;      int old_stdout; +    bool polled_once; +    bool should_terminate;  } curses;  static void +reopen_stdin(void) +{ +    freopen(TTY, "r", stdin); +} + +static void +reopen_stdin_stdout(void) +{ +    reopen_stdin(); +    freopen(TTY, "w", stdout); +} + +static void +store_stdin_stdout(void) +{ +    curses.old_stdin = dup(STDIN_FILENO); +    curses.old_stdout = dup(STDOUT_FILENO); +} + +static void +restore_stdin(void) +{ +    if (curses.old_stdin != -1) { +        dup2(curses.old_stdin, STDIN_FILENO); +        close(curses.old_stdin); +        curses.old_stdin = -1; +    } +} + +static void +restore_stdin_stdout(void) +{ +    restore_stdin(); + +    if (curses.old_stdout != -1) { +        dup2(curses.old_stdout, STDOUT_FILENO); +        close(curses.old_stdout); +        curses.old_stdout = -1; +    } +} + +static void  terminate(void)  {      if (curses.buffer) { @@ -46,16 +90,10 @@ terminate(void)      if (!curses.stdscr)          return; -    freopen(TTY, "w", stdout); - +    reopen_stdin_stdout();      refresh();      endwin(); - -    dup2(curses.old_stdin, STDIN_FILENO); -    dup2(curses.old_stdout, STDOUT_FILENO); -    close(curses.old_stdin); -    close(curses.old_stdout); - +    restore_stdin_stdout();      curses.stdscr = NULL;  } @@ -139,13 +177,14 @@ draw_line(int32_t pair, int32_t y, const char *fmt, ...)  static void  render(const struct bm_menu *menu)  { -    if (!curses.stdscr) { -        curses.old_stdin = dup(STDIN_FILENO); -        curses.old_stdout = dup(STDOUT_FILENO); - -        freopen(TTY, "w", stdout); -        freopen(TTY, "r", stdin); +    if (curses.should_terminate) { +        terminate(); +        curses.should_terminate = false; +    } +    if (!curses.stdscr) { +        store_stdin_stdout(); +        reopen_stdin_stdout();          setlocale(LC_CTYPE, "");          if ((curses.stdscr = initscr()) == NULL) @@ -225,6 +264,15 @@ render(const struct bm_menu *menu)      move(0, title_len + (menu->curses_cursor < ccols ? menu->curses_cursor : ccols));      refresh(); + +    // Make it possible to read stdin even after rendering +    // Only make it impossible to read original stdin after poll_key is called once +    // This is mainly to make -f work even on curses backend +    if (!curses.polled_once) { +        reopen_stdin(); +        restore_stdin(); +        curses.should_terminate = true; +    }  }  static uint32_t @@ -240,8 +288,9 @@ poll_key(const struct bm_menu *menu, uint32_t *unicode)      (void)menu;      assert(unicode);      *unicode = 0; +    curses.polled_once = true; -    if (!curses.stdscr) +    if (!curses.stdscr || curses.should_terminate)          return BM_KEY_NONE;      get_wch((wint_t*)unicode); @@ -360,6 +409,8 @@ constructor(struct bm_menu *menu)      assert(!curses.stdscr && "bemenu supports only one curses instance");      memset(&curses, 0, sizeof(curses)); +    curses.old_stdin = -1; +    curses.old_stdout = -1;      struct sigaction action;      memset(&action, 0, sizeof(struct sigaction));  | 
