mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-25 13:55:34 -05:00
Very dirty first attempt at glib mainloop in switcher (not yet dmenu.)
This commit is contained in:
parent
4b7a29a26f
commit
984257fffc
6 changed files with 137 additions and 56 deletions
|
@ -93,5 +93,6 @@ const char * menu_state_get_user_input ( const MenuState *state );
|
|||
void menu_state_free ( MenuState *state );
|
||||
void menu_state_restart ( MenuState *state );
|
||||
void menu_state_set_selected_line ( MenuState *state, unsigned int selected_line );
|
||||
void menu_state_queue_redraw ( void );
|
||||
/*@}*/
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,8 @@ typedef struct
|
|||
cairo_t *main_draw;
|
||||
|
||||
int update;
|
||||
int blink;
|
||||
guint blink_timeout;
|
||||
} textbox;
|
||||
|
||||
typedef enum
|
||||
|
|
158
source/rofi.c
158
source/rofi.c
|
@ -64,7 +64,7 @@
|
|||
#include "xrmoptions.h"
|
||||
#include "dialogs/dialogs.h"
|
||||
|
||||
ModeMode switcher_run ( char **input, Mode *sw );
|
||||
//ModeMode switcher_run ( char **input, Mode *sw );
|
||||
|
||||
typedef enum _MainLoopEvent
|
||||
{
|
||||
|
@ -77,6 +77,7 @@ typedef struct _ModeHolder
|
|||
textbox *tb;
|
||||
} ModeHolder;
|
||||
|
||||
gboolean daemon_mode = FALSE;
|
||||
// Pidfile.
|
||||
extern Atom netatoms[NUM_NETATOMS];
|
||||
char *pidfile = NULL;
|
||||
|
@ -105,6 +106,8 @@ XIC xic;
|
|||
GThreadPool *tpool = NULL;
|
||||
GMainLoop *main_loop;
|
||||
|
||||
MenuState *current_active_menu = NULL;
|
||||
|
||||
static char * get_matching_state ( void )
|
||||
{
|
||||
if ( config.case_sensitive ) {
|
||||
|
@ -209,6 +212,14 @@ typedef struct MenuState
|
|||
void ( *x11_event_loop )( struct MenuState *state, XEvent *ev );
|
||||
}MenuState;
|
||||
|
||||
void menu_state_queue_redraw ( void )
|
||||
{
|
||||
if ( current_active_menu ) {
|
||||
current_active_menu->update = TRUE;
|
||||
XClearArea ( display, main_window, 0, 0, 1, 1, True );
|
||||
XFlush ( display );
|
||||
}
|
||||
}
|
||||
static MenuState *menu_state_create ( void )
|
||||
{
|
||||
return g_malloc0 ( sizeof ( MenuState ) );
|
||||
|
@ -1643,6 +1654,7 @@ MenuState *menu ( Mode *sw,
|
|||
XMoveResizeWindow ( display, main_window, state->x, state->y, state->w, state->h );
|
||||
cairo_xlib_surface_set_size ( surface, state->w, state->h );
|
||||
XMapRaised ( display, main_window );
|
||||
XFlush ( display );
|
||||
|
||||
// if grabbing keyboard failed, fall through
|
||||
state->selected = 0;
|
||||
|
@ -1806,14 +1818,14 @@ static int run_dmenu ()
|
|||
return ret_state;
|
||||
}
|
||||
|
||||
static int pfd = -1;
|
||||
static void run_switcher ( ModeMode mode )
|
||||
{
|
||||
int pfd = setup ();
|
||||
pfd = setup ();
|
||||
if ( pfd < 0 ) {
|
||||
return;
|
||||
}
|
||||
// Otherwise check if requested mode is enabled.
|
||||
char *input = g_strdup ( config.filter );
|
||||
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
||||
if ( !mode_init ( modi[i].sw ) ) {
|
||||
error_dialog ( ERROR_MSG ( "Failed to initialize all the modi." ), ERROR_MSG_MARKUP );
|
||||
|
@ -1821,39 +1833,64 @@ static void run_switcher ( ModeMode mode )
|
|||
return;
|
||||
}
|
||||
}
|
||||
do {
|
||||
ModeMode retv;
|
||||
char *input = g_strdup ( config.filter );
|
||||
char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode].sw ) );
|
||||
MenuState * state = menu ( modi[mode].sw, input, prompt, NULL, MENU_NORMAL );
|
||||
current_active_menu = state;
|
||||
g_free ( prompt );
|
||||
}
|
||||
static void process_result ()
|
||||
{
|
||||
MenuState * state = current_active_menu;
|
||||
unsigned int selected_line = menu_state_get_selected_line ( state );;
|
||||
MenuReturn mretv = menu_state_get_return_value ( state );
|
||||
char *input = g_strdup ( menu_state_get_user_input ( state ) );
|
||||
menu_state_free ( state );
|
||||
current_active_menu = NULL;
|
||||
ModeMode retv = mode_result ( modi[curr_switcher].sw, mretv, &input, selected_line );
|
||||
|
||||
curr_switcher = mode;
|
||||
retv = switcher_run ( &input, modi[mode].sw );
|
||||
// Find next enabled
|
||||
if ( retv == NEXT_DIALOG ) {
|
||||
mode = ( mode + 1 ) % num_modi;
|
||||
}
|
||||
else if ( retv == PREVIOUS_DIALOG ) {
|
||||
if ( mode == 0 ) {
|
||||
mode = num_modi - 1;
|
||||
}
|
||||
else {
|
||||
mode = ( mode - 1 ) % num_modi;
|
||||
}
|
||||
}
|
||||
else if ( retv == RELOAD_DIALOG ) {
|
||||
// do nothing.
|
||||
}
|
||||
else if ( retv < MODE_EXIT ) {
|
||||
mode = ( retv ) % num_modi;
|
||||
ModeMode mode = curr_switcher;
|
||||
// Find next enabled
|
||||
if ( retv == NEXT_DIALOG ) {
|
||||
mode = ( mode + 1 ) % num_modi;
|
||||
}
|
||||
else if ( retv == PREVIOUS_DIALOG ) {
|
||||
if ( mode == 0 ) {
|
||||
mode = num_modi - 1;
|
||||
}
|
||||
else {
|
||||
mode = retv;
|
||||
mode = ( mode - 1 ) % num_modi;
|
||||
}
|
||||
} while ( mode != MODE_EXIT );
|
||||
}
|
||||
else if ( retv == RELOAD_DIALOG ) {
|
||||
// do nothing.
|
||||
}
|
||||
else if ( retv < MODE_EXIT ) {
|
||||
mode = ( retv ) % num_modi;
|
||||
}
|
||||
else {
|
||||
mode = retv;
|
||||
}
|
||||
if ( mode != MODE_EXIT ) {
|
||||
char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode].sw ) );
|
||||
MenuState * state = menu ( modi[mode].sw, input, prompt, NULL, MENU_NORMAL );
|
||||
g_free ( prompt );
|
||||
// TODO FIX
|
||||
//g_return_val_if_fail ( state != NULL, MODE_EXIT );
|
||||
current_active_menu = state;
|
||||
g_free ( input );
|
||||
return;
|
||||
}
|
||||
// Cleanup
|
||||
g_free ( input );
|
||||
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
||||
mode_destroy ( modi[i].sw );
|
||||
}
|
||||
// cleanup
|
||||
teardown ( pfd );
|
||||
if ( !daemon_mode ) {
|
||||
g_main_loop_quit ( main_loop );
|
||||
}
|
||||
}
|
||||
|
||||
int show_error_message ( const char *msg, int markup )
|
||||
|
@ -2123,6 +2160,19 @@ static void reload_configuration ()
|
|||
*/
|
||||
static gboolean main_loop_x11_event_handler ( G_GNUC_UNUSED gpointer data )
|
||||
{
|
||||
if ( current_active_menu != NULL ) {
|
||||
while ( XPending ( display ) ) {
|
||||
XEvent ev;
|
||||
// Read event, we know this won't block as we checked with XPending.
|
||||
XNextEvent ( display, &ev );
|
||||
menu_state_itterrate ( current_active_menu, &ev );
|
||||
}
|
||||
if ( menu_state_get_completed ( current_active_menu ) ) {
|
||||
// This menu is done.
|
||||
process_result ();
|
||||
}
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
// X11 produced an event. Consume them.
|
||||
while ( XPending ( display ) ) {
|
||||
XEvent ev;
|
||||
|
@ -2175,32 +2225,6 @@ static gboolean main_loop_signal_handler_usr1 ( G_GNUC_UNUSED gpointer data )
|
|||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
ModeMode switcher_run ( char **input, Mode *sw )
|
||||
{
|
||||
char *prompt = g_strdup_printf ( "%s:", mode_get_name ( sw ) );
|
||||
MenuState * state = menu ( sw, *input, prompt, NULL, MENU_NORMAL );
|
||||
g_free ( prompt );
|
||||
g_return_val_if_fail ( state != NULL, MODE_EXIT );
|
||||
|
||||
// Enter main loop.
|
||||
while ( !menu_state_get_completed ( state ) ) {
|
||||
// Wait for event.
|
||||
XEvent ev;
|
||||
// Get next event. (might block)
|
||||
XNextEvent ( display, &ev );
|
||||
TICK_N ( "X Event" );
|
||||
menu_state_itterrate ( state, &ev );
|
||||
}
|
||||
// Update input string.
|
||||
g_free ( *input );
|
||||
*input = g_strdup ( menu_state_get_user_input ( state ) );
|
||||
|
||||
unsigned int selected_line = menu_state_get_selected_line ( state );;
|
||||
MenuReturn mretv = menu_state_get_return_value ( state );
|
||||
menu_state_free ( state );
|
||||
return mode_result ( sw, mretv, input, selected_line );
|
||||
}
|
||||
|
||||
static int error_trap_depth = 0;
|
||||
static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED Display *xdisplay )
|
||||
{
|
||||
|
@ -2217,7 +2241,14 @@ static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, Display *xdispl
|
|||
XSync ( xdisplay, False ); /* get all errors out of the queue */
|
||||
--error_trap_depth;
|
||||
}
|
||||
|
||||
static gboolean delayed_start ( gpointer data )
|
||||
{
|
||||
if ( XPending ( display ) ) {
|
||||
main_loop_x11_event_handler ( NULL );
|
||||
}
|
||||
// menu_state_queue_redraw();
|
||||
return FALSE;
|
||||
}
|
||||
int main ( int argc, char *argv[] )
|
||||
{
|
||||
TIMINGS_START ();
|
||||
|
@ -2400,7 +2431,27 @@ int main ( int argc, char *argv[] )
|
|||
if ( find_arg_str ( "-show", &sname ) == TRUE ) {
|
||||
int index = switcher_get ( sname );
|
||||
if ( index >= 0 ) {
|
||||
main_loop = g_main_loop_new ( NULL, FALSE );
|
||||
GSource *source = x11_event_source_new ( display );
|
||||
x11_event_source_set_callback ( source, main_loop_x11_event_handler );
|
||||
|
||||
// Setup signal handling sources.
|
||||
// SIGHup signal.
|
||||
g_unix_signal_add ( SIGHUP, main_loop_signal_handler_hup, NULL );
|
||||
// SIGTERM
|
||||
g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL );
|
||||
// SIGUSR1
|
||||
g_unix_signal_add ( SIGUSR1, main_loop_signal_handler_usr1, NULL );
|
||||
|
||||
// TODO delay this till mainloop is running or we might miss X events.
|
||||
run_switcher ( index );
|
||||
g_idle_add ( delayed_start, GINT_TO_POINTER ( index ) );
|
||||
// Start mainloop.
|
||||
g_main_loop_run ( main_loop );
|
||||
|
||||
// Cleanup
|
||||
g_source_unref ( (GSource *) source );
|
||||
g_main_loop_unref ( main_loop );
|
||||
}
|
||||
else {
|
||||
fprintf ( stderr, "The %s switcher has not been enabled\n", sname );
|
||||
|
@ -2428,6 +2479,7 @@ int main ( int argc, char *argv[] )
|
|||
if ( sncontext != NULL ) {
|
||||
sn_launchee_context_complete ( sncontext );
|
||||
}
|
||||
daemon_mode = TRUE;
|
||||
// Application Main loop.
|
||||
// This listens in the background for any events on the Xserver
|
||||
// catching global key presses.
|
||||
|
|
|
@ -59,6 +59,17 @@ typedef struct _RowColor
|
|||
RowColor colors[num_states];
|
||||
|
||||
PangoContext *p_context = NULL;
|
||||
static gboolean textbox_blink ( textbox *tb )
|
||||
{
|
||||
if ( tb->blink < 2) {
|
||||
tb->blink = !tb->blink;
|
||||
tb->update = TRUE;
|
||||
menu_state_queue_redraw ( );
|
||||
} else {
|
||||
tb->blink--;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
textbox* textbox_create ( TextboxFlags flags, short x, short y, short w, short h,
|
||||
TextBoxFontType tbft, const char *text )
|
||||
|
@ -88,6 +99,12 @@ textbox* textbox_create ( TextboxFlags flags, short x, short y, short w, short h
|
|||
// auto height/width modes get handled here
|
||||
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
|
||||
|
||||
tb->blink_timeout = 0;
|
||||
tb->blink = 1;
|
||||
if ( ( flags & TB_EDITABLE ) == TB_EDITABLE ) {
|
||||
tb->blink_timeout = g_timeout_add ( 1200, textbox_blink, tb );
|
||||
}
|
||||
|
||||
return tb;
|
||||
}
|
||||
|
||||
|
@ -218,6 +235,10 @@ void textbox_free ( textbox *tb )
|
|||
if ( tb == NULL ) {
|
||||
return;
|
||||
}
|
||||
if ( tb->blink_timeout > 0 ) {
|
||||
g_source_remove ( tb->blink_timeout );
|
||||
tb->blink_timeout = 0;
|
||||
}
|
||||
|
||||
g_free ( tb->text );
|
||||
|
||||
|
@ -304,7 +325,7 @@ static void texbox_update ( textbox *tb )
|
|||
col = tb->color_fg;
|
||||
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha * scale );
|
||||
// draw the cursor
|
||||
if ( tb->flags & TB_EDITABLE ) {
|
||||
if ( tb->flags & TB_EDITABLE && tb->blink ) {
|
||||
cairo_rectangle ( tb->main_draw, x + cursor_x, y, cursor_width, font_height );
|
||||
cairo_fill ( tb->main_draw );
|
||||
}
|
||||
|
@ -512,6 +533,8 @@ int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, int pad_len, KeySym k
|
|||
if ( !( tb->flags & TB_EDITABLE ) ) {
|
||||
return 0;
|
||||
}
|
||||
int old_blink = tb->blink;
|
||||
tb->blink = 2;
|
||||
if ( stat == XLookupKeySym || stat == XLookupBoth ) {
|
||||
// Left or Ctrl-b
|
||||
if ( abe_test_action ( MOVE_CHAR_BACK, ev->xkey.state, key ) ) {
|
||||
|
@ -586,7 +609,7 @@ int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, int pad_len, KeySym k
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
tb->blink = old_blink;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ static gboolean x11_event_source_prepare ( GSource * base, gint * timeout )
|
|||
{
|
||||
X11EventSource *xs = (X11EventSource *) base;
|
||||
*timeout = -1;
|
||||
return XPending ( xs->display );
|
||||
return XPending ( xs->display ) || g_source_query_unix_fd ( base, xs->fd_x11 );
|
||||
}
|
||||
|
||||
static gboolean x11_event_source_check ( GSource * base )
|
||||
|
|
|
@ -25,6 +25,9 @@ unsigned int normal_window_mode = 0;
|
|||
Display *display = NULL;
|
||||
Colormap map = None;
|
||||
XVisualInfo vinfo;
|
||||
void menu_state_queue_redraw ()
|
||||
{
|
||||
}
|
||||
|
||||
void error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue