mirror of https://github.com/davatorium/rofi.git
Very dirty first attempt at glib mainloop in switcher (not yet dmenu.)
This commit is contained in:
parent
4b7a29a26f
commit
984257fffc
|
@ -93,5 +93,6 @@ const char * menu_state_get_user_input ( const MenuState *state );
|
||||||
void menu_state_free ( MenuState *state );
|
void menu_state_free ( MenuState *state );
|
||||||
void menu_state_restart ( MenuState *state );
|
void menu_state_restart ( MenuState *state );
|
||||||
void menu_state_set_selected_line ( MenuState *state, unsigned int selected_line );
|
void menu_state_set_selected_line ( MenuState *state, unsigned int selected_line );
|
||||||
|
void menu_state_queue_redraw ( void );
|
||||||
/*@}*/
|
/*@}*/
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,6 +36,8 @@ typedef struct
|
||||||
cairo_t *main_draw;
|
cairo_t *main_draw;
|
||||||
|
|
||||||
int update;
|
int update;
|
||||||
|
int blink;
|
||||||
|
guint blink_timeout;
|
||||||
} textbox;
|
} textbox;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
158
source/rofi.c
158
source/rofi.c
|
@ -64,7 +64,7 @@
|
||||||
#include "xrmoptions.h"
|
#include "xrmoptions.h"
|
||||||
#include "dialogs/dialogs.h"
|
#include "dialogs/dialogs.h"
|
||||||
|
|
||||||
ModeMode switcher_run ( char **input, Mode *sw );
|
//ModeMode switcher_run ( char **input, Mode *sw );
|
||||||
|
|
||||||
typedef enum _MainLoopEvent
|
typedef enum _MainLoopEvent
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@ typedef struct _ModeHolder
|
||||||
textbox *tb;
|
textbox *tb;
|
||||||
} ModeHolder;
|
} ModeHolder;
|
||||||
|
|
||||||
|
gboolean daemon_mode = FALSE;
|
||||||
// Pidfile.
|
// Pidfile.
|
||||||
extern Atom netatoms[NUM_NETATOMS];
|
extern Atom netatoms[NUM_NETATOMS];
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
|
@ -105,6 +106,8 @@ XIC xic;
|
||||||
GThreadPool *tpool = NULL;
|
GThreadPool *tpool = NULL;
|
||||||
GMainLoop *main_loop;
|
GMainLoop *main_loop;
|
||||||
|
|
||||||
|
MenuState *current_active_menu = NULL;
|
||||||
|
|
||||||
static char * get_matching_state ( void )
|
static char * get_matching_state ( void )
|
||||||
{
|
{
|
||||||
if ( config.case_sensitive ) {
|
if ( config.case_sensitive ) {
|
||||||
|
@ -209,6 +212,14 @@ typedef struct MenuState
|
||||||
void ( *x11_event_loop )( struct MenuState *state, XEvent *ev );
|
void ( *x11_event_loop )( struct MenuState *state, XEvent *ev );
|
||||||
}MenuState;
|
}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 )
|
static MenuState *menu_state_create ( void )
|
||||||
{
|
{
|
||||||
return g_malloc0 ( sizeof ( MenuState ) );
|
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 );
|
XMoveResizeWindow ( display, main_window, state->x, state->y, state->w, state->h );
|
||||||
cairo_xlib_surface_set_size ( surface, state->w, state->h );
|
cairo_xlib_surface_set_size ( surface, state->w, state->h );
|
||||||
XMapRaised ( display, main_window );
|
XMapRaised ( display, main_window );
|
||||||
|
XFlush ( display );
|
||||||
|
|
||||||
// if grabbing keyboard failed, fall through
|
// if grabbing keyboard failed, fall through
|
||||||
state->selected = 0;
|
state->selected = 0;
|
||||||
|
@ -1806,14 +1818,14 @@ static int run_dmenu ()
|
||||||
return ret_state;
|
return ret_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pfd = -1;
|
||||||
static void run_switcher ( ModeMode mode )
|
static void run_switcher ( ModeMode mode )
|
||||||
{
|
{
|
||||||
int pfd = setup ();
|
pfd = setup ();
|
||||||
if ( pfd < 0 ) {
|
if ( pfd < 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Otherwise check if requested mode is enabled.
|
// Otherwise check if requested mode is enabled.
|
||||||
char *input = g_strdup ( config.filter );
|
|
||||||
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
||||||
if ( !mode_init ( modi[i].sw ) ) {
|
if ( !mode_init ( modi[i].sw ) ) {
|
||||||
error_dialog ( ERROR_MSG ( "Failed to initialize all the modi." ), ERROR_MSG_MARKUP );
|
error_dialog ( ERROR_MSG ( "Failed to initialize all the modi." ), ERROR_MSG_MARKUP );
|
||||||
|
@ -1821,39 +1833,64 @@ static void run_switcher ( ModeMode mode )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
do {
|
char *input = g_strdup ( config.filter );
|
||||||
ModeMode retv;
|
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;
|
ModeMode mode = curr_switcher;
|
||||||
retv = switcher_run ( &input, modi[mode].sw );
|
// Find next enabled
|
||||||
// Find next enabled
|
if ( retv == NEXT_DIALOG ) {
|
||||||
if ( retv == NEXT_DIALOG ) {
|
mode = ( mode + 1 ) % num_modi;
|
||||||
mode = ( mode + 1 ) % num_modi;
|
}
|
||||||
}
|
else if ( retv == PREVIOUS_DIALOG ) {
|
||||||
else if ( retv == PREVIOUS_DIALOG ) {
|
if ( mode == 0 ) {
|
||||||
if ( mode == 0 ) {
|
mode = num_modi - 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
else {
|
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 );
|
g_free ( input );
|
||||||
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
for ( unsigned int i = 0; i < num_modi; i++ ) {
|
||||||
mode_destroy ( modi[i].sw );
|
mode_destroy ( modi[i].sw );
|
||||||
}
|
}
|
||||||
// cleanup
|
// cleanup
|
||||||
teardown ( pfd );
|
teardown ( pfd );
|
||||||
|
if ( !daemon_mode ) {
|
||||||
|
g_main_loop_quit ( main_loop );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int show_error_message ( const char *msg, int markup )
|
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 )
|
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.
|
// X11 produced an event. Consume them.
|
||||||
while ( XPending ( display ) ) {
|
while ( XPending ( display ) ) {
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
|
@ -2175,32 +2225,6 @@ static gboolean main_loop_signal_handler_usr1 ( G_GNUC_UNUSED gpointer data )
|
||||||
return G_SOURCE_CONTINUE;
|
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 int error_trap_depth = 0;
|
||||||
static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED Display *xdisplay )
|
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 */
|
XSync ( xdisplay, False ); /* get all errors out of the queue */
|
||||||
--error_trap_depth;
|
--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[] )
|
int main ( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
TIMINGS_START ();
|
TIMINGS_START ();
|
||||||
|
@ -2400,7 +2431,27 @@ int main ( int argc, char *argv[] )
|
||||||
if ( find_arg_str ( "-show", &sname ) == TRUE ) {
|
if ( find_arg_str ( "-show", &sname ) == TRUE ) {
|
||||||
int index = switcher_get ( sname );
|
int index = switcher_get ( sname );
|
||||||
if ( index >= 0 ) {
|
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 );
|
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 {
|
else {
|
||||||
fprintf ( stderr, "The %s switcher has not been enabled\n", sname );
|
fprintf ( stderr, "The %s switcher has not been enabled\n", sname );
|
||||||
|
@ -2428,6 +2479,7 @@ int main ( int argc, char *argv[] )
|
||||||
if ( sncontext != NULL ) {
|
if ( sncontext != NULL ) {
|
||||||
sn_launchee_context_complete ( sncontext );
|
sn_launchee_context_complete ( sncontext );
|
||||||
}
|
}
|
||||||
|
daemon_mode = TRUE;
|
||||||
// Application Main loop.
|
// Application Main loop.
|
||||||
// This listens in the background for any events on the Xserver
|
// This listens in the background for any events on the Xserver
|
||||||
// catching global key presses.
|
// catching global key presses.
|
||||||
|
|
|
@ -59,6 +59,17 @@ typedef struct _RowColor
|
||||||
RowColor colors[num_states];
|
RowColor colors[num_states];
|
||||||
|
|
||||||
PangoContext *p_context = NULL;
|
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,
|
textbox* textbox_create ( TextboxFlags flags, short x, short y, short w, short h,
|
||||||
TextBoxFontType tbft, const char *text )
|
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
|
// auto height/width modes get handled here
|
||||||
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
|
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;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +235,10 @@ void textbox_free ( textbox *tb )
|
||||||
if ( tb == NULL ) {
|
if ( tb == NULL ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ( tb->blink_timeout > 0 ) {
|
||||||
|
g_source_remove ( tb->blink_timeout );
|
||||||
|
tb->blink_timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
g_free ( tb->text );
|
g_free ( tb->text );
|
||||||
|
|
||||||
|
@ -304,7 +325,7 @@ static void texbox_update ( textbox *tb )
|
||||||
col = tb->color_fg;
|
col = tb->color_fg;
|
||||||
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha * scale );
|
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha * scale );
|
||||||
// draw the cursor
|
// 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_rectangle ( tb->main_draw, x + cursor_x, y, cursor_width, font_height );
|
||||||
cairo_fill ( tb->main_draw );
|
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 ) ) {
|
if ( !( tb->flags & TB_EDITABLE ) ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int old_blink = tb->blink;
|
||||||
|
tb->blink = 2;
|
||||||
if ( stat == XLookupKeySym || stat == XLookupBoth ) {
|
if ( stat == XLookupKeySym || stat == XLookupBoth ) {
|
||||||
// Left or Ctrl-b
|
// Left or Ctrl-b
|
||||||
if ( abe_test_action ( MOVE_CHAR_BACK, ev->xkey.state, key ) ) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tb->blink = old_blink;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ static gboolean x11_event_source_prepare ( GSource * base, gint * timeout )
|
||||||
{
|
{
|
||||||
X11EventSource *xs = (X11EventSource *) base;
|
X11EventSource *xs = (X11EventSource *) base;
|
||||||
*timeout = -1;
|
*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 )
|
static gboolean x11_event_source_check ( GSource * base )
|
||||||
|
|
|
@ -25,6 +25,9 @@ unsigned int normal_window_mode = 0;
|
||||||
Display *display = NULL;
|
Display *display = NULL;
|
||||||
Colormap map = None;
|
Colormap map = None;
|
||||||
XVisualInfo vinfo;
|
XVisualInfo vinfo;
|
||||||
|
void menu_state_queue_redraw ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
|
void error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue