summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile.am7
-rw-r--r--configure.ac9
-rw-r--r--include/rofi.h1
-rw-r--r--include/textbox.h2
-rw-r--r--include/view-internal.h2
-rw-r--r--include/view.h2
m---------libgwater0
-rw-r--r--libgwater-xcb-nolibtool.mk20
-rw-r--r--source/rofi.c82
-rw-r--r--source/textbox.c31
-rw-r--r--source/view.c489
12 files changed, 330 insertions, 318 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..2034529a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "libgwater"]
+ path = libgwater
+ url = git://github.com/sardemff7/libgwater
diff --git a/Makefile.am b/Makefile.am
index bdfff8e9..62e42824 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,11 @@
# Specify automake version.
AUTOMAKE_OPTIONS = 1.11.3
+ACLOCAL_AMFLAGS = -I libgwater ${ACLOCAL_FLAGS}
+
+noinst_LIBRARIES =
+include $(top_srcdir)/libgwater-xcb-nolibtool.mk
+
##
# Rofi the program
##
@@ -60,6 +65,7 @@ rofi_SOURCES=\
rofi_CFLAGS=\
$(AM_CFLAGS)\
$(glib_CFLAGS)\
+ $(GW_XCB_CFLAGS)\
$(x11_CFLAGS)\
$(xinerama_CFLAGS)\
$(pango_CFLAGS)\
@@ -73,6 +79,7 @@ rofi_CFLAGS=\
rofi_LDADD=\
$(glib_LIBS)\
+ $(GW_XCB_LIBS)\
$(x11_LIBS)\
$(xinerama_LIBS)\
$(libsn_LIBS)\
diff --git a/configure.ac b/configure.ac
index 0fa89fd6..d7f711fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,12 @@ dnl ---------------------------------------------------------------------
AC_USE_SYSTEM_EXTENSIONS
dnl ---------------------------------------------------------------------
+dnl Static libraries programs
+dnl ---------------------------------------------------------------------
+AC_PROG_RANLIB
+AM_PROG_AR
+
+dnl ---------------------------------------------------------------------
dnl Base CFLAGS
dnl ---------------------------------------------------------------------
AM_CFLAGS="-Wall -Wextra -Wparentheses -Winline -pedantic"
@@ -77,7 +83,8 @@ dnl ---------------------------------------------------------------------
dnl X11, Glib, Xinerama, Pango, Cairo, libstartup notification
dnl ---------------------------------------------------------------------
PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.40])
-PKG_CHECK_MODULES([x11], [x11])
+GW_CHECK_XCB([xcb-aux xkbcommon xkbcommon-x11])
+PKG_CHECK_MODULES([x11], [x11 x11-xcb])
PKG_CHECK_MODULES([xinerama], [xinerama])
PKG_CHECK_MODULES([pango], [pango pangocairo])
PKG_CHECK_MODULES([cairo], [cairo cairo-xlib])
diff --git a/include/rofi.h b/include/rofi.h
index ef717cbc..411acb37 100644
--- a/include/rofi.h
+++ b/include/rofi.h
@@ -1,5 +1,6 @@
#ifndef ROFI_MAIN_H
#define ROFI_MAIN_H
+#include <xcb/xcb.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <glib.h>
diff --git a/include/textbox.h b/include/textbox.h
index 757b1c62..c4caa7ca 100644
--- a/include/textbox.h
+++ b/include/textbox.h
@@ -113,7 +113,7 @@ void textbox_draw ( textbox *tb, cairo_t *draw );
*
* @returns if the key was handled (1), unhandled(0) or handled and return was pressed (-1)
*/
-int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, int pad_len, KeySym key, Status stat );
+int textbox_keypress ( textbox *tb, xcb_key_press_event_t *ev, char *pad, int pad_len, KeySym key, Status stat );
/**
* @param tb Handle to the textbox
diff --git a/include/view-internal.h b/include/view-internal.h
index 27ee8a00..6dd61ba2 100644
--- a/include/view-internal.h
+++ b/include/view-internal.h
@@ -69,7 +69,7 @@ struct RofiViewState
MenuFlags menu_flags;
// Handlers.
- void ( *x11_event_loop )( struct RofiViewState *state, XEvent *ev );
+ void ( *x11_event_loop )( struct RofiViewState *state, xcb_generic_event_t *ev );
void ( *finalize )( struct RofiViewState *state );
};
/** @} */
diff --git a/include/view.h b/include/view.h
index f9763b83..d6a3aa19 100644
--- a/include/view.h
+++ b/include/view.h
@@ -47,7 +47,7 @@ void rofi_view_finalize ( RofiViewState *state );
MenuReturn rofi_view_get_return_value ( const RofiViewState *state );
unsigned int rofi_view_get_next_position ( const RofiViewState *state );
-void rofi_view_itterrate ( RofiViewState *state, XEvent *event );
+void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event );
unsigned int rofi_view_get_completed ( const RofiViewState *state );
const char * rofi_view_get_user_input ( const RofiViewState *state );
diff --git a/libgwater b/libgwater
new file mode 160000
+Subproject 50a0f8a4bc2d762c412b6dd1823a14949de583a
diff --git a/libgwater-xcb-nolibtool.mk b/libgwater-xcb-nolibtool.mk
new file mode 100644
index 00000000..e4e07eb7
--- /dev/null
+++ b/libgwater-xcb-nolibtool.mk
@@ -0,0 +1,20 @@
+noinst_LIBRARIES += \
+ libgwater/libgwater-xcb.a
+
+libgwater_libgwater_xcb_a_SOURCES = \
+ libgwater/xcb/libgwater-xcb.c \
+ libgwater/xcb/libgwater-xcb.h
+
+libgwater_libgwater_xcb_a_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(GW_XCB_INTERNAL_CFLAGS)
+
+
+GW_XCB_CFLAGS = \
+ -I$(srcdir)/libgwater/xcb \
+ $(GW_XCB_INTERNAL_CFLAGS)
+
+GW_XCB_LIBS = \
+ libgwater/libgwater-xcb.a \
+ $(GW_XCB_INTERNAL_LIBS)
+
diff --git a/source/rofi.c b/source/rofi.c
index 66b10f32..f3e2557e 100644
--- a/source/rofi.c
+++ b/source/rofi.c
@@ -34,9 +34,13 @@
#include <errno.h>
#include <time.h>
#include <locale.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <xkbcommon/xkbcommon.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/keysym.h>
@@ -45,6 +49,8 @@
#include <glib-unix.h>
+#include <libgwater-xcb.h>
+
#define SN_API_NOT_YET_FROZEN
#include <libsn/sn.h>
@@ -63,13 +69,15 @@
gboolean daemon_mode = FALSE;
// Pidfile.
-char *pidfile = NULL;
-const char *cache_dir = NULL;
-SnDisplay *sndisplay = NULL;
-SnLauncheeContext *sncontext = NULL;
-Display *display = NULL;
-char *display_str = NULL;
-char *config_path = NULL;
+char *pidfile = NULL;
+const char *cache_dir = NULL;
+SnDisplay *sndisplay = NULL;
+SnLauncheeContext *sncontext = NULL;
+xcb_connection_t *xcb_connection = NULL;
+xcb_screen_t *xcb_screen = NULL;
+Display *display = NULL;
+char *display_str = NULL;
+char *config_path = NULL;
// Array of modi.
Mode **modi = NULL;
unsigned int num_modi = 0;
@@ -77,7 +85,7 @@ unsigned int num_modi = 0;
unsigned int curr_switcher = 0;
GMainLoop *main_loop = NULL;
-GSource *main_loop_source = NULL;
+GWaterXcbSource *main_loop_source = NULL;
gboolean quiet = FALSE;
static int dmenu_mode = FALSE;
@@ -277,19 +285,19 @@ int show_error_message ( const char *msg, int markup )
* Function that listens for global key-presses.
* This is only used when in daemon mode.
*/
-static void handle_keypress ( XEvent *ev )
+static void handle_keypress ( xcb_key_press_event_t *ev )
{
int index;
- KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
- index = locate_switcher ( key, ev->xkey.state );
+ KeySym key = XkbKeycodeToKeysym ( display, ev->detail, 0, 0 );
+ index = locate_switcher ( key, ev->state );
if ( index >= 0 ) {
run_switcher ( index );
}
else {
fprintf ( stderr,
"Warning: Unhandled keypress in global keyhandler, keycode = %u mask = %u\n",
- ev->xkey.keycode,
- ev->xkey.state );
+ ev->detail,
+ ev->state );
}
}
@@ -354,7 +362,7 @@ static void cleanup ()
rofi_view_workers_finalize ();
if ( main_loop != NULL ) {
if ( main_loop_source ) {
- g_source_destroy ( main_loop_source );
+ g_water_xcb_source_unref ( main_loop_source );
}
g_main_loop_unref ( main_loop );
main_loop = NULL;
@@ -542,19 +550,14 @@ static void reload_configuration ()
/**
* Process X11 events in the main-loop (gui-thread) of the application.
*/
-static gboolean main_loop_x11_event_handler ( G_GNUC_UNUSED gpointer data )
+static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer data )
{
RofiViewState *state = rofi_view_get_active ();
+ if ( sndisplay != NULL ) {
+ sn_xcb_display_process_event ( sndisplay, ev );
+ }
if ( state != NULL ) {
- while ( XPending ( display ) ) {
- XEvent ev;
- // Read event, we know this won't block as we checked with XPending.
- XNextEvent ( display, &ev );
- if ( sndisplay != NULL ) {
- sn_display_process_event ( sndisplay, &ev );
- }
- rofi_view_itterrate ( state, &ev );
- }
+ rofi_view_itterrate ( state, ev );
if ( rofi_view_get_completed ( state ) ) {
// This menu is done.
rofi_view_finalize ( state );
@@ -566,24 +569,14 @@ static gboolean main_loop_x11_event_handler ( G_GNUC_UNUSED gpointer data )
}
}
}
- return G_SOURCE_CONTINUE;
}
- // X11 produced an event. Consume them.
- while ( XPending ( display ) ) {
- XEvent ev;
- // Read event, we know this won't block as we checked with XPending.
- XNextEvent ( display, &ev );
- if ( sndisplay != NULL ) {
- sn_display_process_event ( sndisplay, &ev );
- }
+ else {
+ // X11 produced an event. Consume them.
// If we get an event that does not belong to a window:
// Ignore it.
- if ( ev.xany.window == None ) {
- continue;
- }
// If keypress, handle it.
- if ( ev.type == KeyPress ) {
- handle_keypress ( &ev );
+ if ( ( ev->response_type & ~0x80 ) == XCB_KEY_PRESS ) {
+ handle_keypress ( (xcb_key_press_event_t *) ev );
}
}
return G_SOURCE_CONTINUE;
@@ -606,7 +599,7 @@ static gboolean main_loop_signal_handler_hup ( G_GNUC_UNUSED gpointer data )
// Grab the possibly new keybindings.
grab_global_keybindings ();
// We need to flush, otherwise the first key presses are not caught.
- XFlush ( display );
+ xcb_flush ( xcb_connection );
return G_SOURCE_CONTINUE;
}
@@ -722,8 +715,9 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data )
sn_launchee_context_complete ( sncontext );
}
daemon_mode = TRUE;
- XSelectInput ( display, DefaultRootWindow ( display ), KeyPressMask );
- XFlush ( display );
+ uint32_t mask[] = { XCB_EVENT_MASK_KEY_PRESS };
+ xcb_change_window_attributes ( xcb_connection, xcb_screen->root, XCB_CW_EVENT_MASK, mask );
+ xcb_flush ( xcb_connection );
}
return G_SOURCE_REMOVE;
@@ -807,6 +801,9 @@ int main ( int argc, char *argv[] )
}
TICK_N ( "Open Display" );
+ xcb_connection = XGetXCBConnection ( display );
+ xcb_screen = xcb_aux_get_screen ( xcb_connection, DefaultScreen ( display ) );
+
main_loop = g_main_loop_new ( NULL, FALSE );
TICK_N ( "Setup mainloop" );
@@ -856,8 +853,7 @@ int main ( int argc, char *argv[] )
}
x11_setup ( display );
- main_loop_source = x11_event_source_new ( display );
- x11_event_source_set_callback ( main_loop_source, main_loop_x11_event_handler );
+ main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb_connection, main_loop_x11_event_handler, NULL, NULL );
TICK_N ( "X11 Setup " );
diff --git a/source/textbox.c b/source/textbox.c
index 4a456a56..bb784eb8 100644
--- a/source/textbox.c
+++ b/source/textbox.c
@@ -24,6 +24,7 @@
*/
#include <config.h>
+#include <xcb/xcb.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
@@ -532,7 +533,7 @@ static void textbox_cursor_del_word ( textbox *tb )
// 0 = unhandled
// 1 = handled
// -1 = handled and return pressed (finished)
-int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, int pad_len, KeySym key, Status stat )
+int textbox_keypress ( textbox *tb, xcb_key_press_event_t *ev, char *pad, int pad_len, KeySym key, Status stat )
{
if ( !( tb->flags & TB_EDITABLE ) ) {
return 0;
@@ -541,67 +542,67 @@ int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, int pad_len, KeySym k
tb->blink = 2;
if ( stat == XLookupKeySym || stat == XLookupBoth ) {
// Left or Ctrl-b
- if ( abe_test_action ( MOVE_CHAR_BACK, ev->xkey.state, key ) ) {
+ if ( abe_test_action ( MOVE_CHAR_BACK, ev->state, key ) ) {
textbox_cursor_dec ( tb );
return 2;
}
// Right or Ctrl-F
- else if ( abe_test_action ( MOVE_CHAR_FORWARD, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( MOVE_CHAR_FORWARD, ev->state, key ) ) {
textbox_cursor_inc ( tb );
return 2;
}
// Ctrl-U: Kill from the beginning to the end of the line.
- else if ( abe_test_action ( CLEAR_LINE, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( CLEAR_LINE, ev->state, key ) ) {
textbox_text ( tb, "" );
return 1;
}
// Ctrl-A
- else if ( abe_test_action ( MOVE_FRONT, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( MOVE_FRONT, ev->state, key ) ) {
textbox_cursor ( tb, 0 );
return 2;
}
// Ctrl-E
- else if ( abe_test_action ( MOVE_END, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( MOVE_END, ev->state, key ) ) {
textbox_cursor_end ( tb );
return 2;
}
// Ctrl-Alt-h
- else if ( abe_test_action ( REMOVE_WORD_BACK, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( REMOVE_WORD_BACK, ev->state, key ) ) {
textbox_cursor_bkspc_word ( tb );
return 1;
}
// Ctrl-Alt-d
- else if ( abe_test_action ( REMOVE_WORD_FORWARD, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( REMOVE_WORD_FORWARD, ev->state, key ) ) {
textbox_cursor_del_word ( tb );
return 1;
} // Delete or Ctrl-D
- else if ( abe_test_action ( REMOVE_CHAR_FORWARD, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( REMOVE_CHAR_FORWARD, ev->state, key ) ) {
textbox_cursor_del ( tb );
return 1;
}
// Alt-B
- else if ( abe_test_action ( MOVE_WORD_BACK, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( MOVE_WORD_BACK, ev->state, key ) ) {
textbox_cursor_dec_word ( tb );
return 2;
}
// Alt-F
- else if ( abe_test_action ( MOVE_WORD_FORWARD, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( MOVE_WORD_FORWARD, ev->state, key ) ) {
textbox_cursor_inc_word ( tb );
return 2;
}
// BackSpace, Ctrl-h
- else if ( abe_test_action ( REMOVE_CHAR_BACK, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( REMOVE_CHAR_BACK, ev->state, key ) ) {
textbox_cursor_bkspc ( tb );
return 1;
}
- else if ( abe_test_action ( ACCEPT_CUSTOM, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( ACCEPT_CUSTOM, ev->state, key ) ) {
return -2;
}
- else if ( abe_test_action ( ACCEPT_ENTRY_CONTINUE, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( ACCEPT_ENTRY_CONTINUE, ev->state, key ) ) {
return -3;
}
- else if ( abe_test_action ( ACCEPT_ENTRY, ev->xkey.state, key ) ) {
+ else if ( abe_test_action ( ACCEPT_ENTRY, ev->state, key ) ) {
return -1;
}
}
diff --git a/source/view.c b/source/view.c
index d9aeaf86..c5ef9b84 100644
--- a/source/view.c
+++ b/source/view.c
@@ -308,9 +308,95 @@ unsigned int rofi_view_get_completed ( const RofiViewState *state )
return state->quit;
}
-void rofi_view_itterrate ( RofiViewState *state, XEvent *event )
+static void rofi_view_resize ( RofiViewState *state )
+{
+ unsigned int sbw = config.line_margin + 8;
+ widget_move ( WIDGET ( state->scrollbar ), state->w - state->border - sbw, state->top_offset );
+ if ( config.sidebar_mode == TRUE ) {
+ int width = ( state->w - ( 2 * ( state->border ) + ( state->num_modi - 1 ) * config.line_margin ) ) / state->num_modi;
+ for ( unsigned int j = 0; j < state->num_modi; j++ ) {
+ textbox_moveresize ( state->modi[j],
+ state->border + j * ( width + config.line_margin ), state->h - state->line_height - state->border,
+ width, state->line_height );
+ textbox_draw ( state->modi[j], draw );
+ }
+ }
+ int entrybox_width = state->w - ( 2 * ( state->border ) ) - textbox_get_width ( state->prompt_tb )
+ - textbox_get_width ( state->case_indicator );
+ textbox_moveresize ( state->text, state->text->widget.x, state->text->widget.y, entrybox_width, state->line_height );
+ widget_move ( WIDGET ( state->case_indicator ), state->w - state->border - textbox_get_width ( state->case_indicator ), state->border );
+ /**
+ * Resize in Height
+ */
+ {
+ unsigned int last_length = state->max_elements;
+ int element_height = state->line_height * config.element_height + config.line_margin;
+ // Calculated new number of boxes.
+ int h = ( state->h - state->top_offset - config.padding );
+ if ( config.sidebar_mode == TRUE ) {
+ h -= state->line_height + config.line_margin;
+ }
+ if ( h < 0 ) {
+ fprintf ( stderr, "Current padding %u (on each side) does not fit within visible window %u.\n", config.padding, state->h );
+ h = ( state->h - state->top_offset - state->h / 3 );
+ if ( config.sidebar_mode == TRUE ) {
+ h -= state->line_height + config.line_margin;
+ }
+ }
+ state->max_rows = MAX ( 1, ( h / element_height ) );
+ state->menu_lines = state->max_rows;
+ state->max_elements = state->max_rows * config.menu_columns;
+ // Free boxes no longer needed.
+ for ( unsigned int i = state->max_elements; i < last_length; i++ ) {
+ textbox_free ( state->boxes[i] );
+ }
+ // resize array.
+ state->boxes = g_realloc ( state->boxes, state->max_elements * sizeof ( textbox* ) );
+
+ int y_offset = state->top_offset;
+ int x_offset = state->border;
+ // Add newly added boxes.
+ for ( unsigned int i = last_length; i < state->max_elements; i++ ) {
+ state->boxes[i] = textbox_create ( 0, x_offset, y_offset,
+ state->element_width, element_height, NORMAL, "" );
+ }
+ scrollbar_resize ( state->scrollbar, -1, ( state->max_rows ) * ( element_height ) - config.line_margin );
+ }
+
+ state->rchanged = TRUE;
+ state->update = TRUE;
+}
+
+void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event )
{
- state->x11_event_loop ( state, event );
+ uint8_t type = event->response_type & ~0x80;
+ switch ( type )
+ {
+ case XCB_EXPOSE:
+ state->update = TRUE;
+ break;
+ case XCB_CONFIGURE_NOTIFY:
+ {
+ xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
+ if ( xce->window == main_window ) {
+ if ( state->x != xce->x || state->y != xce->y ) {
+ state->x = xce->x;
+ state->y = xce->y;
+ state->update = TRUE;
+ }
+ if ( state->w != xce->width || state->h != xce->height ) {
+ state->w = xce->width;
+ state->h = xce->height;
+ cairo_xlib_surface_set_size ( surface, state->w, state->h );
+ rofi_view_resize ( state );
+ }
+ }
+ }
+ break;
+ default:
+ state->x11_event_loop ( state, event, xkb );
+ }
+ rofi_view_update ( state );
}
const char * rofi_view_get_user_input ( const RofiViewState *state )
@@ -881,7 +967,7 @@ void rofi_view_update ( RofiViewState *state )
*
* Handle paste event.
*/
-static void rofi_view_paste ( RofiViewState *state, XSelectionEvent *xse )
+static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t *xse )
{
if ( xse->property == netatoms[UTF8_STRING] ) {
gchar *text = window_get_text_prop ( display, main_window, netatoms[UTF8_STRING] );
@@ -903,65 +989,6 @@ static void rofi_view_paste ( RofiViewState *state, XSelectionEvent *xse )
}
}
-static void rofi_view_resize ( RofiViewState *state )
-{
- unsigned int sbw = config.line_margin + 8;
- widget_move ( WIDGET ( state->scrollbar ), state->w - state->border - sbw, state->top_offset );
- if ( config.sidebar_mode == TRUE ) {
- int width = ( state->w - ( 2 * ( state->border ) + ( state->num_modi - 1 ) * config.line_margin ) ) / state->num_modi;
- for ( unsigned int j = 0; j < state->num_modi; j++ ) {
- textbox_moveresize ( state->modi[j],
- state->border + j * ( width + config.line_margin ), state->h - state->line_height - state->border,
- width, state->line_height );
- textbox_draw ( state->modi[j], draw );
- }
- }
- int entrybox_width = state->w - ( 2 * ( state->border ) ) - textbox_get_width ( state->prompt_tb )
- - textbox_get_width ( state->case_indicator );
- textbox_moveresize ( state->text, state->text->widget.x, state->text->widget.y, entrybox_width, state->line_height );
- widget_move ( WIDGET ( state->case_indicator ), state->w - state->border - textbox_get_width ( state->case_indicator ), state->border );
- /**
- * Resize in Height
- */
- {
- unsigned int last_length = state->max_elements;
- int element_height = state->line_height * config.element_height + config.line_margin;
- // Calculated new number of boxes.
- int h = ( state->h - state->top_offset - config.padding );
- if ( config.sidebar_mode == TRUE ) {
- h -= state->line_height + config.line_margin;
- }
- if ( h < 0 ) {
- fprintf ( stderr, "Current padding %u (on each side) does not fit within visible window %u.\n", config.padding, state->h );
- h = ( state->h - state->top_offset - state->h / 3 );
- if ( config.sidebar_mode == TRUE ) {
- h -= state->line_height + config.line_margin;
- }
- }
- state->max_rows = MAX ( 1, ( h / element_height ) );
- state->menu_lines = state->max_rows;
- state->max_elements = state->max_rows * config.menu_columns;
- // Free boxes no longer needed.
- for ( unsigned int i = state->max_elements; i < last_length; i++ ) {
- textbox_free ( state->boxes[i] );
- }
- // resize array.
- state->boxes = g_realloc ( state->boxes, state->max_elements * sizeof ( textbox* ) );
-
- int y_offset = state->top_offset;
- int x_offset = state->border;
- // Add newly added boxes.
- for ( unsigned int i = last_length; i < state->max_elements; i++ ) {
- state->boxes[i] = textbox_create ( 0, x_offset, y_offset,
- state->element_width, element_height, NORMAL, "" );
- }
- scrollbar_resize ( state->scrollbar, -1, ( state->max_rows ) * ( element_height ) - config.line_margin );
- }
-
- state->rchanged = TRUE;
- state->update = TRUE;
-}
-
/**
* @param state Internal state of the menu.
* @param key the Key being pressed.
@@ -1047,32 +1074,32 @@ static int rofi_view_keyboard_navigation ( RofiViewState *state, KeySym key, uns
return 0;
}
-static void rofi_view_mouse_navigation ( RofiViewState *state, XButtonEvent *xbe )
+static void rofi_view_mouse_navigation ( RofiViewState *state, xcb_button_press_event_t *xbe )
{
// Scroll event
- if ( xbe->button > 3 ) {
- if ( xbe->button == 4 ) {
+ if ( xbe->detail > 3 ) {
+ if ( xbe->detail == 4 ) {
rofi_view_nav_up ( state );
}
- else if ( xbe->button == 5 ) {
+ else if ( xbe->detail == 5 ) {
rofi_view_nav_down ( state );
}
- else if ( xbe->button == 6 ) {
+ else if ( xbe->detail == 6 ) {
rofi_view_nav_left ( state );
}
- else if ( xbe->button == 7 ) {
+ else if ( xbe->detail == 7 ) {
rofi_view_nav_right ( state );
}
return;
}
else {
- if ( state->scrollbar && widget_intersect ( &( state->scrollbar->widget ), xbe->x, xbe->y ) ) {
- state->selected = scrollbar_clicked ( state->scrollbar, xbe->y );
+ if ( state->scrollbar && widget_intersect ( &( state->scrollbar->widget ), xbe->event_x, xbe->event_y ) ) {
+ state->selected = scrollbar_clicked ( state->scrollbar, xbe->event_y );
state->update = TRUE;
return;
}
for ( unsigned int i = 0; config.sidebar_mode == TRUE && i < state->num_modi; i++ ) {
- if ( widget_intersect ( &( state->modi[i]->widget ), xbe->x, xbe->y ) ) {
+ if ( widget_intersect ( &( state->modi[i]->widget ), xbe->event_x, xbe->event_y ) ) {
( state->selected_line ) = 0;
state->retv = MENU_QUICK_SWITCH | ( i & MENU_LOWER_MASK );
state->quit = TRUE;
@@ -1081,7 +1108,7 @@ static void rofi_view_mouse_navigation ( RofiViewState *state, XButtonEvent *xbe
}
}
for ( unsigned int i = 0; i < state->max_elements; i++ ) {
- if ( widget_intersect ( &( state->boxes[i]->widget ), xbe->x, xbe->y ) ) {
+ if ( widget_intersect ( &( state->boxes[i]->widget ), xbe->event_x, xbe->event_y ) ) {
// Only allow items that are visible to be selected.
if ( ( state->last_offset + i ) >= state->filtered_lines ) {
break;
@@ -1219,192 +1246,165 @@ void rofi_view_setup_fake_transparency ( Display *display, RofiViewState *state
}
}
-static void rofi_view_mainloop_iter ( RofiViewState *state, XEvent *ev )
+static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t *ev )
{
- if ( ev->type == KeymapNotify ) {
- XRefreshKeyboardMapping ( &( ev->xmapping ) );
- }
- else if ( ev->type == ConfigureNotify ) {
- XConfigureEvent xce = ev->xconfigure;
- if ( xce.window == main_window ) {
- if ( state->x != (int ) xce.x || state->y != (int) xce.y ) {
- state->x = xce.x;
- state->y = xce.y;
- state->update = TRUE;
- }
- if ( state->w != (unsigned int) xce.width || state->h != (unsigned int ) xce.height ) {
- state->w = xce.width;
- state->h = xce.height;
- cairo_xlib_surface_set_size ( surface, state->w, state->h );
- rofi_view_resize ( state );
- }
- }
- }
- else if ( ev->type == FocusIn ) {
+ switch ( ev->response_type & ~0x80 )
+ {
+ case XCB_FOCUS_IN:
if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) {
take_keyboard ( display, main_window );
}
- }
- else if ( ev->type == FocusOut ) {
+ break;
+ case XCB_FOCUS_OUT:
if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) {
release_keyboard ( display );
}
- }
- // Handle event.
- else if ( ev->type == Expose ) {
- while ( XCheckTypedEvent ( display, Expose, ev ) ) {
- ;
- }
- state->update = TRUE;
- }
- else if ( ev->type == MotionNotify ) {
- while ( XCheckTypedEvent ( display, MotionNotify, ev ) ) {
- ;
- }
- XMotionEvent xme = ev->xmotion;
- if ( xme.x >= state->scrollbar->widget.x && xme.x < ( state->scrollbar->widget.x + state->scrollbar->widget.w ) ) {
- state->selected = scrollbar_clicked ( state->scrollbar, xme.y );
+ break;
+ case XCB_MOTION_NOTIFY:
+ {
+ xcb_motion_notify_event_t *xme = (xcb_motion_notify_event_t *) ev;
+ if ( xme->event_x >= state->scrollbar->widget.x && xme->event_x < ( state->scrollbar->widget.x + state->scrollbar->widget.w ) ) {
+ state->selected = scrollbar_clicked ( state->scrollbar, xme->event_y );
state->update = TRUE;
}
+ break;
}
- // Button press event.
- else if ( ev->type == ButtonPress ) {
- while ( XCheckTypedEvent ( display, ButtonPress, ev ) ) {
- ;
- }
- rofi_view_mouse_navigation ( state, &( ev->xbutton ) );
- }
+ case XCB_BUTTON_PRESS:
+ rofi_view_mouse_navigation ( state, (xcb_button_press_event_t *) ev );
+ break;
// Paste event.
- else if ( ev->type == SelectionNotify ) {
- do {
- rofi_view_paste ( state, &( ev->xselection ) );
- } while ( XCheckTypedEvent ( display, SelectionNotify, ev ) );
- }
- // Key press event.
- else if ( ev->type == KeyPress ) {
- do {
- // This is needed for letting the Input Method handle combined keys.
- // E.g. `e into è
- if ( XFilterEvent ( ev, main_window ) ) {
- continue;
+ case XCB_SELECTION_NOTIFY:
+ rofi_view_paste ( state, (xcb_selection_notify_event_t *) ev );
+ break;
+ case XCB_KEY_PRESS:
+ {
+ xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) ev;
+ XEvent fake_event;
+ fake_event.type = KeyPress;
+ fake_event.xany.display = display;
+ fake_event.xany.window = xkpe->event;
+ fake_event.xkey.state = xkpe->state;
+ fake_event.xkey.keycode = xkpe->detail;
+ // This is needed for letting the Input Method handle combined keys.
+ // E.g. `e into è
+ Status stat;
+ char pad[32];
+ KeySym key; // = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
+ int len = Xutf8LookupString ( xic, &( fake_event.xkey ), pad, sizeof ( pad ), &key, &stat );
+ pad[len] = 0;
+ if ( stat == XLookupKeySym || stat == XLookupBoth ) {
+ // Handling of paste
+ if ( abe_test_action ( PASTE_PRIMARY, xkpe->state, key ) ) {
+ XConvertSelection ( display, XA_PRIMARY, netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window, CurrentTime );
}
- Status stat;
- char pad[32];
- KeySym key; // = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
- int len = Xutf8LookupString ( xic, &( ev->xkey ), pad, sizeof ( pad ), &key, &stat );
- pad[len] = 0;
- if ( stat == XLookupKeySym || stat == XLookupBoth ) {
- // Handling of paste
- if ( abe_test_action ( PASTE_PRIMARY, ev->xkey.state, key ) ) {
- XConvertSelection ( display, XA_PRIMARY, netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window, CurrentTime );
- }
- else if ( abe_test_action ( PASTE_SECONDARY, ev->xkey.state, key ) ) {
- XConvertSelection ( display, netatoms[CLIPBOARD], netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window,
- CurrentTime );
- }
- if ( abe_test_action ( SCREENSHOT, ev->xkey.state, key ) ) {
- menu_capture_screenshot ( );
- break;
- }
- if ( abe_test_action ( TOGGLE_SORT, ev->xkey.state, key ) ) {
- config.levenshtein_sort = !config.levenshtein_sort;
- state->refilter = TRUE;
- state->update = TRUE;
- textbox_text ( state->case_indicator, get_matching_state () );
- break;
- }
- else if ( abe_test_action ( MODE_PREVIOUS, ev->xkey.state, key ) ) {
- state->retv = MENU_PREVIOUS;
- ( state->selected_line ) = 0;
- state->quit = TRUE;
- break;
- }
- // Menu navigation.
- else if ( abe_test_action ( MODE_NEXT, ev->xkey.state, key ) ) {
- state->retv = MENU_NEXT;
- ( state->selected_line ) = 0;
+ else if ( abe_test_action ( PASTE_SECONDARY, xkpe->state, key ) ) {
+ XConvertSelection ( display, netatoms[CLIPBOARD], netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window,
+ CurrentTime );
+ }
+ if ( abe_test_action ( SCREENSHOT, xkpe->state, key ) ) {
+ menu_capture_screenshot ( );
+ break;
+ }
+ if ( abe_test_action ( TOGGLE_SORT, xkpe->state, key ) ) {
+ config.levenshtein_sort = !config.levenshtein_sort;
+ state->refilter = TRUE;
+ state->update = TRUE;
+ textbox_text ( state->case_indicator, get_matching_state () );
+ break;
+ }
+ else if ( abe_test_action ( MODE_PR