mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
xcb: Move (most) event handling to xcb.c
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
parent
4792a16593
commit
93cb04e30f
6 changed files with 210 additions and 156 deletions
|
@ -77,6 +77,8 @@ void rofi_add_error_message ( GString *str );
|
|||
*/
|
||||
void rofi_set_return_code ( int code );
|
||||
|
||||
void rofi_quit_main_loop ( void );
|
||||
|
||||
/**
|
||||
* @param name Search for mode with this name.
|
||||
*
|
||||
|
|
|
@ -93,12 +93,33 @@ MenuReturn rofi_view_get_return_value ( const RofiViewState *state );
|
|||
unsigned int rofi_view_get_next_position ( const RofiViewState *state );
|
||||
/**
|
||||
* @param state the Menu handle
|
||||
* @param event the event to handle
|
||||
* @param xkb the keyboard handle
|
||||
* @param text The text to add to the input box
|
||||
*
|
||||
* Process an Xevent.
|
||||
* Update the state if needed.
|
||||
*/
|
||||
void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, NkBindingsSeat *seat );
|
||||
void rofi_view_handle_text ( RofiViewState *state, char *text );
|
||||
/**
|
||||
* @param state the Menu handle
|
||||
* @param x The X coordinates of the motion
|
||||
* @param x The Y coordinates of the motion
|
||||
*
|
||||
* Update the state if needed.
|
||||
*/
|
||||
void rofi_view_handle_mouse_motion( RofiViewState *state, gint x, gint y );
|
||||
/**
|
||||
* @param state the Menu handle
|
||||
*
|
||||
* Update the state if needed.
|
||||
*/
|
||||
void rofi_view_maybe_update ( RofiViewState *state );
|
||||
void rofi_view_temp_configure_notify ( RofiViewState *state, xcb_configure_notify_event_t *xce );
|
||||
void rofi_view_temp_click_to_exit ( RofiViewState *state, xcb_window_t target );
|
||||
/**
|
||||
* @param state the Menu handle
|
||||
*
|
||||
* Update the state if needed.
|
||||
*/
|
||||
void rofi_view_frame_callback ( void );
|
||||
/**
|
||||
* @param state the Menu handle
|
||||
*
|
||||
|
|
|
@ -60,6 +60,7 @@ struct _xcb_stuff
|
|||
} xkb;
|
||||
NkBindings *bindings;
|
||||
NkBindingsSeat *bindings_seat;
|
||||
gboolean mouse_seen;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -591,6 +591,11 @@ static gboolean setup_modi ( void )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void rofi_quit_main_loop ( void )
|
||||
{
|
||||
g_main_loop_quit ( main_loop );
|
||||
}
|
||||
|
||||
static gboolean main_loop_signal_handler_int ( G_GNUC_UNUSED gpointer data )
|
||||
{
|
||||
// Break out of loop.
|
||||
|
|
207
source/view.c
207
source/view.c
|
@ -972,40 +972,6 @@ void rofi_view_update ( RofiViewState *state, gboolean qr )
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state Internal state of the menu.
|
||||
* @param xse X selection event.
|
||||
*
|
||||
* Handle paste event.
|
||||
*/
|
||||
static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t *xse )
|
||||
{
|
||||
if ( xse->property == XCB_ATOM_NONE ) {
|
||||
g_warning ( "Failed to convert selection" );
|
||||
}
|
||||
else if ( xse->property == xcb->ewmh.UTF8_STRING ) {
|
||||
gchar *text = window_get_text_prop ( CacheState.main_window, xcb->ewmh.UTF8_STRING );
|
||||
if ( text != NULL && text[0] != '\0' ) {
|
||||
unsigned int dl = strlen ( text );
|
||||
// Strip new line
|
||||
for ( unsigned int i = 0; i < dl; i++ ) {
|
||||
if ( text[i] == '\n' ) {
|
||||
dl = i;
|
||||
}
|
||||
}
|
||||
// Insert string move cursor.
|
||||
textbox_insert ( state->text, state->text->cursor, text, dl );
|
||||
textbox_cursor ( state->text, state->text->cursor + g_utf8_strlen ( text, -1 ) );
|
||||
// Force a redraw and refiltering of the text.
|
||||
state->refilter = TRUE;
|
||||
}
|
||||
g_free ( text );
|
||||
}
|
||||
else {
|
||||
g_warning ( "Failed" );
|
||||
}
|
||||
}
|
||||
|
||||
static void _rofi_view_reload_row ( RofiViewState *state )
|
||||
{
|
||||
g_free ( state->line_map );
|
||||
|
@ -1382,122 +1348,83 @@ gboolean rofi_view_trigger_action ( RofiViewState *state, BindingsScope scope, g
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, NkBindingsSeat *seat )
|
||||
void rofi_view_handle_text ( RofiViewState *state, char *text )
|
||||
{
|
||||
switch ( event->response_type & ~0x80 )
|
||||
{
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
{
|
||||
xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
|
||||
if ( xce->window == CacheState.main_window ) {
|
||||
if ( state->x != xce->x || state->y != xce->y ) {
|
||||
state->x = xce->x;
|
||||
state->y = xce->y;
|
||||
widget_queue_redraw ( WIDGET ( state->main_window ) );
|
||||
}
|
||||
if ( state->width != xce->width || state->height != xce->height ) {
|
||||
state->width = xce->width;
|
||||
state->height = xce->height;
|
||||
if ( textbox_append_text ( state->text, text, strlen ( text ) ) ) {
|
||||
state->refilter = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_destroy ( CacheState.edit_draw );
|
||||
cairo_surface_destroy ( CacheState.edit_surf );
|
||||
void rofi_view_handle_mouse_motion( RofiViewState *state, gint x, gint y )
|
||||
{
|
||||
state->mouse.x = x;
|
||||
state->mouse.y = y;
|
||||
if ( state->mouse.motion_target != NULL ) {
|
||||
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
|
||||
widget_motion_notify ( state->mouse.motion_target, x, y );
|
||||
}
|
||||
}
|
||||
|
||||
xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
|
||||
CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
|
||||
xcb_create_pixmap ( xcb->connection, depth->depth, CacheState.edit_pixmap, CacheState.main_window,
|
||||
state->width, state->height );
|
||||
void rofi_view_maybe_update ( RofiViewState *state )
|
||||
{
|
||||
if ( rofi_view_get_completed ( state ) ) {
|
||||
// This menu is done.
|
||||
rofi_view_finalize ( state );
|
||||
// cleanup
|
||||
if ( rofi_view_get_active () == NULL ) {
|
||||
rofi_quit_main_loop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
|
||||
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
|
||||
g_debug ( "Re-size window based external request: %d %d", state->width, state->height );
|
||||
widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_MOTION_NOTIFY:
|
||||
{
|
||||
if ( config.click_to_exit == TRUE ) {
|
||||
state->mouse_seen = TRUE;
|
||||
}
|
||||
xcb_motion_notify_event_t xme = *( (xcb_motion_notify_event_t *) event );
|
||||
state->mouse.x = xme.event_x;
|
||||
state->mouse.y = xme.event_y;
|
||||
if ( state->mouse.motion_target != NULL ) {
|
||||
gint x = state->mouse.x;
|
||||
gint y = state->mouse.y;
|
||||
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
|
||||
widget_motion_notify ( state->mouse.motion_target, x, y );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_BUTTON_PRESS:
|
||||
{
|
||||
xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
|
||||
state->mouse.x = bpe->event_x;
|
||||
state->mouse.y = bpe->event_y;
|
||||
nk_bindings_seat_handle_button ( seat, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
|
||||
break;
|
||||
}
|
||||
case XCB_BUTTON_RELEASE:
|
||||
{
|
||||
xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
|
||||
nk_bindings_seat_handle_button ( seat, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
|
||||
if ( config.click_to_exit == TRUE ) {
|
||||
if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
||||
if ( ( state->mouse_seen == FALSE ) && ( bre->event != CacheState.main_window ) ) {
|
||||
state->quit = TRUE;
|
||||
state->retv = MENU_CANCEL;
|
||||
}
|
||||
}
|
||||
state->mouse_seen = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Paste event.
|
||||
case XCB_SELECTION_NOTIFY:
|
||||
rofi_view_paste ( state, (xcb_selection_notify_event_t *) event );
|
||||
break;
|
||||
case XCB_KEYMAP_NOTIFY:
|
||||
{
|
||||
xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *) event;
|
||||
for ( gint32 by = 0; by < 31; ++by ) {
|
||||
for ( gint8 bi = 0; bi < 7; ++bi ) {
|
||||
if ( kne->keys[by] & ( 1 << bi ) ) {
|
||||
// X11 keycodes starts at 8
|
||||
nk_bindings_seat_handle_key ( seat, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_PRESS:
|
||||
{
|
||||
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
|
||||
gchar *text;
|
||||
|
||||
text = nk_bindings_seat_handle_key ( seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
|
||||
if ( ( text != NULL ) && ( textbox_append_text ( state->text, text, strlen ( text ) ) ) ) {
|
||||
state->refilter = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE:
|
||||
{
|
||||
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
|
||||
nk_bindings_seat_handle_key ( seat, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Update if requested.
|
||||
if ( state->refilter ) {
|
||||
rofi_view_refilter ( state );
|
||||
}
|
||||
rofi_view_update ( state, TRUE );
|
||||
}
|
||||
|
||||
if ( ( event->response_type & ~0x80 ) == XCB_EXPOSE && CacheState.repaint_source == 0 ) {
|
||||
void rofi_view_temp_configure_notify ( RofiViewState *state, xcb_configure_notify_event_t *xce )
|
||||
{
|
||||
if ( xce->window == CacheState.main_window ) {
|
||||
if ( state->x != xce->x || state->y != xce->y ) {
|
||||
state->x = xce->x;
|
||||
state->y = xce->y;
|
||||
widget_queue_redraw ( WIDGET ( state->main_window ) );
|
||||
}
|
||||
if ( state->width != xce->width || state->height != xce->height ) {
|
||||
state->width = xce->width;
|
||||
state->height = xce->height;
|
||||
|
||||
cairo_destroy ( CacheState.edit_draw );
|
||||
cairo_surface_destroy ( CacheState.edit_surf );
|
||||
|
||||
xcb_free_pixmap ( xcb->connection, CacheState.edit_pixmap );
|
||||
CacheState.edit_pixmap = xcb_generate_id ( xcb->connection );
|
||||
xcb_create_pixmap ( xcb->connection, depth->depth, CacheState.edit_pixmap, CacheState.main_window,
|
||||
state->width, state->height );
|
||||
|
||||
CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
|
||||
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
|
||||
g_debug ( "Re-size window based external request: %d %d", state->width, state->height );
|
||||
widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rofi_view_temp_click_to_exit ( RofiViewState *state, xcb_window_t target )
|
||||
{
|
||||
if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
||||
if ( target != CacheState.main_window ) {
|
||||
state->quit = TRUE;
|
||||
state->retv = MENU_CANCEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rofi_view_frame_callback ( void )
|
||||
{
|
||||
if ( CacheState.repaint_source == 0 ) {
|
||||
CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
|
122
source/xcb.c
122
source/xcb.c
|
@ -557,23 +557,123 @@ int monitor_active ( workarea *mon )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state Internal state of the menu.
|
||||
* @param xse X selection event.
|
||||
*
|
||||
* Handle paste event.
|
||||
*/
|
||||
static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t *xse )
|
||||
{
|
||||
if ( xse->property == XCB_ATOM_NONE ) {
|
||||
g_warning ( "Failed to convert selection" );
|
||||
}
|
||||
else if ( xse->property == xcb->ewmh.UTF8_STRING ) {
|
||||
gchar *text = window_get_text_prop ( xse->requestor, xcb->ewmh.UTF8_STRING );
|
||||
if ( text != NULL && text[0] != '\0' ) {
|
||||
unsigned int dl = strlen ( text );
|
||||
// Strip new line
|
||||
for ( unsigned int i = 0; i < dl; i++ ) {
|
||||
if ( text[i] == '\n' ) {
|
||||
text[i] = '\0';
|
||||
}
|
||||
}
|
||||
rofi_view_handle_text ( state, text );
|
||||
}
|
||||
g_free ( text );
|
||||
}
|
||||
else {
|
||||
g_warning ( "Failed" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process X11 events in the main-loop (gui-thread) of the application.
|
||||
*/
|
||||
static void main_loop_x11_event_handler_view ( xcb_generic_event_t *ev )
|
||||
static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event )
|
||||
{
|
||||
RofiViewState *state = rofi_view_get_active ();
|
||||
if ( state != NULL ) {
|
||||
rofi_view_itterrate ( state, ev, xcb->bindings_seat );
|
||||
if ( rofi_view_get_completed ( state ) ) {
|
||||
// This menu is done.
|
||||
rofi_view_finalize ( state );
|
||||
// cleanup
|
||||
if ( rofi_view_get_active () == NULL ) {
|
||||
g_main_loop_quit ( xcb->main_loop );
|
||||
if ( state == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( event->response_type & ~0x80 )
|
||||
{
|
||||
case XCB_EXPOSE:
|
||||
rofi_view_frame_callback ();
|
||||
break;
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
{
|
||||
xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
|
||||
rofi_view_temp_configure_notify ( state, xce );
|
||||
break;
|
||||
}
|
||||
case XCB_MOTION_NOTIFY:
|
||||
{
|
||||
if ( config.click_to_exit == TRUE ) {
|
||||
xcb->mouse_seen = TRUE;
|
||||
}
|
||||
xcb_motion_notify_event_t *xme = (xcb_motion_notify_event_t *) event;
|
||||
rofi_view_handle_mouse_motion ( state, xme->event_x, xme->event_y );
|
||||
break;
|
||||
}
|
||||
case XCB_BUTTON_PRESS:
|
||||
{
|
||||
xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
|
||||
rofi_view_handle_mouse_motion ( state, bpe->event_x, bpe->event_y );
|
||||
nk_bindings_seat_handle_button ( xcb->bindings_seat, bpe->detail, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
|
||||
break;
|
||||
}
|
||||
case XCB_BUTTON_RELEASE:
|
||||
{
|
||||
xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
|
||||
nk_bindings_seat_handle_button ( xcb->bindings_seat, bre->detail, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
|
||||
if ( config.click_to_exit == TRUE ) {
|
||||
if ( ! xcb->mouse_seen ) {
|
||||
rofi_view_temp_click_to_exit ( state, bre->event );
|
||||
}
|
||||
xcb->mouse_seen = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Paste event.
|
||||
case XCB_SELECTION_NOTIFY:
|
||||
rofi_view_paste ( state, (xcb_selection_notify_event_t *) event );
|
||||
break;
|
||||
case XCB_KEYMAP_NOTIFY:
|
||||
{
|
||||
xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *) event;
|
||||
for ( gint32 by = 0; by < 31; ++by ) {
|
||||
for ( gint8 bi = 0; bi < 7; ++bi ) {
|
||||
if ( kne->keys[by] & ( 1 << bi ) ) {
|
||||
// X11 keycodes starts at 8
|
||||
nk_bindings_seat_handle_key ( xcb->bindings_seat, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_PRESS:
|
||||
{
|
||||
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
|
||||
gchar *text;
|
||||
|
||||
text = nk_bindings_seat_handle_key ( xcb->bindings_seat, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
|
||||
if ( text != NULL ) {
|
||||
rofi_view_handle_text ( state, text );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE:
|
||||
{
|
||||
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
|
||||
nk_bindings_seat_handle_key ( xcb->bindings_seat, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rofi_view_maybe_update ( state );
|
||||
}
|
||||
|
||||
static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer user_data )
|
||||
|
@ -613,9 +713,7 @@ static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UN
|
|||
ksne->baseGroup,
|
||||
ksne->latchedGroup,
|
||||
ksne->lockedGroup );
|
||||
xcb_generic_event_t dev;
|
||||
dev.response_type = 0;
|
||||
main_loop_x11_event_handler_view ( &dev );
|
||||
rofi_view_maybe_update ( rofi_view_get_active () );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue