mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
rofi: Convert to XCB events
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
parent
2eb63456db
commit
fe7ca2079d
12 changed files with 337 additions and 324 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "libgwater"]
|
||||||
|
path = libgwater
|
||||||
|
url = git://github.com/sardemff7/libgwater
|
|
@ -1,6 +1,11 @@
|
||||||
# Specify automake version.
|
# Specify automake version.
|
||||||
AUTOMAKE_OPTIONS = 1.11.3
|
AUTOMAKE_OPTIONS = 1.11.3
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I libgwater ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
|
noinst_LIBRARIES =
|
||||||
|
include $(top_srcdir)/libgwater-xcb-nolibtool.mk
|
||||||
|
|
||||||
##
|
##
|
||||||
# Rofi the program
|
# Rofi the program
|
||||||
##
|
##
|
||||||
|
@ -60,6 +65,7 @@ rofi_SOURCES=\
|
||||||
rofi_CFLAGS=\
|
rofi_CFLAGS=\
|
||||||
$(AM_CFLAGS)\
|
$(AM_CFLAGS)\
|
||||||
$(glib_CFLAGS)\
|
$(glib_CFLAGS)\
|
||||||
|
$(GW_XCB_CFLAGS)\
|
||||||
$(x11_CFLAGS)\
|
$(x11_CFLAGS)\
|
||||||
$(xinerama_CFLAGS)\
|
$(xinerama_CFLAGS)\
|
||||||
$(pango_CFLAGS)\
|
$(pango_CFLAGS)\
|
||||||
|
@ -73,6 +79,7 @@ rofi_CFLAGS=\
|
||||||
|
|
||||||
rofi_LDADD=\
|
rofi_LDADD=\
|
||||||
$(glib_LIBS)\
|
$(glib_LIBS)\
|
||||||
|
$(GW_XCB_LIBS)\
|
||||||
$(x11_LIBS)\
|
$(x11_LIBS)\
|
||||||
$(xinerama_LIBS)\
|
$(xinerama_LIBS)\
|
||||||
$(libsn_LIBS)\
|
$(libsn_LIBS)\
|
||||||
|
|
|
@ -30,6 +30,12 @@ dnl System extensions
|
||||||
dnl ---------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
|
||||||
|
dnl ---------------------------------------------------------------------
|
||||||
|
dnl Static libraries programs
|
||||||
|
dnl ---------------------------------------------------------------------
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
AM_PROG_AR
|
||||||
|
|
||||||
dnl ---------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------
|
||||||
dnl Base CFLAGS
|
dnl Base CFLAGS
|
||||||
dnl ---------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------
|
||||||
|
@ -77,7 +83,8 @@ dnl ---------------------------------------------------------------------
|
||||||
dnl X11, Glib, Xinerama, Pango, Cairo, libstartup notification
|
dnl X11, Glib, Xinerama, Pango, Cairo, libstartup notification
|
||||||
dnl ---------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------
|
||||||
PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.40])
|
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([xinerama], [xinerama])
|
||||||
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
||||||
PKG_CHECK_MODULES([cairo], [cairo cairo-xlib])
|
PKG_CHECK_MODULES([cairo], [cairo cairo-xlib])
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef ROFI_MAIN_H
|
#ifndef ROFI_MAIN_H
|
||||||
#define ROFI_MAIN_H
|
#define ROFI_MAIN_H
|
||||||
|
#include <xcb/xcb.h>
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <glib.h>
|
#include <glib.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)
|
* @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
|
* @param tb Handle to the textbox
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct RofiViewState
|
||||||
|
|
||||||
MenuFlags menu_flags;
|
MenuFlags menu_flags;
|
||||||
// Handlers.
|
// 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 );
|
void ( *finalize )( struct RofiViewState *state );
|
||||||
};
|
};
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -47,7 +47,7 @@ void rofi_view_finalize ( RofiViewState *state );
|
||||||
|
|
||||||
MenuReturn rofi_view_get_return_value ( const RofiViewState *state );
|
MenuReturn rofi_view_get_return_value ( const RofiViewState *state );
|
||||||
unsigned int rofi_view_get_next_position ( 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 );
|
unsigned int rofi_view_get_completed ( const RofiViewState *state );
|
||||||
const char * rofi_view_get_user_input ( const RofiViewState *state );
|
const char * rofi_view_get_user_input ( const RofiViewState *state );
|
||||||
|
|
||||||
|
|
1
libgwater
Submodule
1
libgwater
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 50a0f8a4bc2d762c412b6dd1823a14949de583aa
|
20
libgwater-xcb-nolibtool.mk
Normal file
20
libgwater-xcb-nolibtool.mk
Normal file
|
@ -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)
|
||||||
|
|
|
@ -34,9 +34,13 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_aux.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
@ -45,6 +49,8 @@
|
||||||
|
|
||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
|
|
||||||
|
#include <libgwater-xcb.h>
|
||||||
|
|
||||||
#define SN_API_NOT_YET_FROZEN
|
#define SN_API_NOT_YET_FROZEN
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
|
|
||||||
|
@ -63,13 +69,15 @@
|
||||||
|
|
||||||
gboolean daemon_mode = FALSE;
|
gboolean daemon_mode = FALSE;
|
||||||
// Pidfile.
|
// Pidfile.
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
const char *cache_dir = NULL;
|
const char *cache_dir = NULL;
|
||||||
SnDisplay *sndisplay = NULL;
|
SnDisplay *sndisplay = NULL;
|
||||||
SnLauncheeContext *sncontext = NULL;
|
SnLauncheeContext *sncontext = NULL;
|
||||||
Display *display = NULL;
|
xcb_connection_t *xcb_connection = NULL;
|
||||||
char *display_str = NULL;
|
xcb_screen_t *xcb_screen = NULL;
|
||||||
char *config_path = NULL;
|
Display *display = NULL;
|
||||||
|
char *display_str = NULL;
|
||||||
|
char *config_path = NULL;
|
||||||
// Array of modi.
|
// Array of modi.
|
||||||
Mode **modi = NULL;
|
Mode **modi = NULL;
|
||||||
unsigned int num_modi = 0;
|
unsigned int num_modi = 0;
|
||||||
|
@ -77,7 +85,7 @@ unsigned int num_modi = 0;
|
||||||
unsigned int curr_switcher = 0;
|
unsigned int curr_switcher = 0;
|
||||||
|
|
||||||
GMainLoop *main_loop = NULL;
|
GMainLoop *main_loop = NULL;
|
||||||
GSource *main_loop_source = NULL;
|
GWaterXcbSource *main_loop_source = NULL;
|
||||||
gboolean quiet = FALSE;
|
gboolean quiet = FALSE;
|
||||||
|
|
||||||
static int dmenu_mode = 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.
|
* Function that listens for global key-presses.
|
||||||
* This is only used when in daemon mode.
|
* 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;
|
int index;
|
||||||
KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
|
KeySym key = XkbKeycodeToKeysym ( display, ev->detail, 0, 0 );
|
||||||
index = locate_switcher ( key, ev->xkey.state );
|
index = locate_switcher ( key, ev->state );
|
||||||
if ( index >= 0 ) {
|
if ( index >= 0 ) {
|
||||||
run_switcher ( index );
|
run_switcher ( index );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf ( stderr,
|
fprintf ( stderr,
|
||||||
"Warning: Unhandled keypress in global keyhandler, keycode = %u mask = %u\n",
|
"Warning: Unhandled keypress in global keyhandler, keycode = %u mask = %u\n",
|
||||||
ev->xkey.keycode,
|
ev->detail,
|
||||||
ev->xkey.state );
|
ev->state );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +362,7 @@ static void cleanup ()
|
||||||
rofi_view_workers_finalize ();
|
rofi_view_workers_finalize ();
|
||||||
if ( main_loop != NULL ) {
|
if ( main_loop != NULL ) {
|
||||||
if ( main_loop_source ) {
|
if ( main_loop_source ) {
|
||||||
g_source_destroy ( main_loop_source );
|
g_water_xcb_source_unref ( main_loop_source );
|
||||||
}
|
}
|
||||||
g_main_loop_unref ( main_loop );
|
g_main_loop_unref ( main_loop );
|
||||||
main_loop = NULL;
|
main_loop = NULL;
|
||||||
|
@ -542,19 +550,14 @@ static void reload_configuration ()
|
||||||
/**
|
/**
|
||||||
* Process X11 events in the main-loop (gui-thread) of the application.
|
* 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 ();
|
RofiViewState *state = rofi_view_get_active ();
|
||||||
|
if ( sndisplay != NULL ) {
|
||||||
|
sn_xcb_display_process_event ( sndisplay, ev );
|
||||||
|
}
|
||||||
if ( state != NULL ) {
|
if ( state != NULL ) {
|
||||||
while ( XPending ( display ) ) {
|
rofi_view_itterrate ( state, ev );
|
||||||
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 );
|
|
||||||
}
|
|
||||||
if ( rofi_view_get_completed ( state ) ) {
|
if ( rofi_view_get_completed ( state ) ) {
|
||||||
// This menu is done.
|
// This menu is done.
|
||||||
rofi_view_finalize ( state );
|
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.
|
else {
|
||||||
while ( XPending ( display ) ) {
|
// X11 produced an event. Consume them.
|
||||||
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 );
|
|
||||||
}
|
|
||||||
// If we get an event that does not belong to a window:
|
// If we get an event that does not belong to a window:
|
||||||
// Ignore it.
|
// Ignore it.
|
||||||
if ( ev.xany.window == None ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// If keypress, handle it.
|
// If keypress, handle it.
|
||||||
if ( ev.type == KeyPress ) {
|
if ( ( ev->response_type & ~0x80 ) == XCB_KEY_PRESS ) {
|
||||||
handle_keypress ( &ev );
|
handle_keypress ( (xcb_key_press_event_t *) ev );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return G_SOURCE_CONTINUE;
|
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 the possibly new keybindings.
|
||||||
grab_global_keybindings ();
|
grab_global_keybindings ();
|
||||||
// We need to flush, otherwise the first key presses are not caught.
|
// We need to flush, otherwise the first key presses are not caught.
|
||||||
XFlush ( display );
|
xcb_flush ( xcb_connection );
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,8 +715,9 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data )
|
||||||
sn_launchee_context_complete ( sncontext );
|
sn_launchee_context_complete ( sncontext );
|
||||||
}
|
}
|
||||||
daemon_mode = TRUE;
|
daemon_mode = TRUE;
|
||||||
XSelectInput ( display, DefaultRootWindow ( display ), KeyPressMask );
|
uint32_t mask[] = { XCB_EVENT_MASK_KEY_PRESS };
|
||||||
XFlush ( display );
|
xcb_change_window_attributes ( xcb_connection, xcb_screen->root, XCB_CW_EVENT_MASK, mask );
|
||||||
|
xcb_flush ( xcb_connection );
|
||||||
}
|
}
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
|
@ -807,6 +801,9 @@ int main ( int argc, char *argv[] )
|
||||||
}
|
}
|
||||||
TICK_N ( "Open Display" );
|
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 );
|
main_loop = g_main_loop_new ( NULL, FALSE );
|
||||||
|
|
||||||
TICK_N ( "Setup mainloop" );
|
TICK_N ( "Setup mainloop" );
|
||||||
|
@ -856,8 +853,7 @@ int main ( int argc, char *argv[] )
|
||||||
}
|
}
|
||||||
|
|
||||||
x11_setup ( display );
|
x11_setup ( display );
|
||||||
main_loop_source = x11_event_source_new ( display );
|
main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb_connection, main_loop_x11_event_handler, NULL, NULL );
|
||||||
x11_event_source_set_callback ( main_loop_source, main_loop_x11_event_handler );
|
|
||||||
|
|
||||||
TICK_N ( "X11 Setup " );
|
TICK_N ( "X11 Setup " );
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
@ -532,7 +533,7 @@ static void textbox_cursor_del_word ( textbox *tb )
|
||||||
// 0 = unhandled
|
// 0 = unhandled
|
||||||
// 1 = handled
|
// 1 = handled
|
||||||
// -1 = handled and return pressed (finished)
|
// -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 ) ) {
|
if ( !( tb->flags & TB_EDITABLE ) ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -541,67 +542,67 @@ int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, int pad_len, KeySym k
|
||||||
tb->blink = 2;
|
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->state, key ) ) {
|
||||||
textbox_cursor_dec ( tb );
|
textbox_cursor_dec ( tb );
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
// Right or Ctrl-F
|
// 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 );
|
textbox_cursor_inc ( tb );
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl-U: Kill from the beginning to the end of the line.
|
// 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, "" );
|
textbox_text ( tb, "" );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// Ctrl-A
|
// 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 );
|
textbox_cursor ( tb, 0 );
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
// Ctrl-E
|
// 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 );
|
textbox_cursor_end ( tb );
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
// Ctrl-Alt-h
|
// 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 );
|
textbox_cursor_bkspc_word ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// Ctrl-Alt-d
|
// 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 );
|
textbox_cursor_del_word ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
} // Delete or Ctrl-D
|
} // 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 );
|
textbox_cursor_del ( tb );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// Alt-B
|
// 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 );
|
textbox_cursor_dec_word ( tb );
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
// Alt-F
|
// 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 );
|
textbox_cursor_inc_word ( tb );
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
// BackSpace, Ctrl-h
|
// 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 );
|
textbox_cursor_bkspc ( tb );
|
||||||
return 1;
|
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;
|
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;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
501
source/view.c
501
source/view.c
|
@ -308,9 +308,95 @@ unsigned int rofi_view_get_completed ( const RofiViewState *state )
|
||||||
return state->quit;
|
return state->quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rofi_view_itterrate ( RofiViewState *state, XEvent *event )
|
static void rofi_view_resize ( RofiViewState *state )
|
||||||
{
|
{
|
||||||
state->x11_event_loop ( state, event );
|
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 )
|
||||||
|
{
|
||||||
|
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 )
|
const char * rofi_view_get_user_input ( const RofiViewState *state )
|
||||||
|
@ -881,7 +967,7 @@ void rofi_view_update ( RofiViewState *state )
|
||||||
*
|
*
|
||||||
* Handle paste event.
|
* 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] ) {
|
if ( xse->property == netatoms[UTF8_STRING] ) {
|
||||||
gchar *text = window_get_text_prop ( display, main_window, 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 state Internal state of the menu.
|
||||||
* @param key the Key being pressed.
|
* @param key the Key being pressed.
|
||||||
|
@ -1047,32 +1074,32 @@ static int rofi_view_keyboard_navigation ( RofiViewState *state, KeySym key, uns
|
||||||
return 0;
|
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
|
// Scroll event
|
||||||
if ( xbe->button > 3 ) {
|
if ( xbe->detail > 3 ) {
|
||||||
if ( xbe->button == 4 ) {
|
if ( xbe->detail == 4 ) {
|
||||||
rofi_view_nav_up ( state );
|
rofi_view_nav_up ( state );
|
||||||
}
|
}
|
||||||
else if ( xbe->button == 5 ) {
|
else if ( xbe->detail == 5 ) {
|
||||||
rofi_view_nav_down ( state );
|
rofi_view_nav_down ( state );
|
||||||
}
|
}
|
||||||
else if ( xbe->button == 6 ) {
|
else if ( xbe->detail == 6 ) {
|
||||||
rofi_view_nav_left ( state );
|
rofi_view_nav_left ( state );
|
||||||
}
|
}
|
||||||
else if ( xbe->button == 7 ) {
|
else if ( xbe->detail == 7 ) {
|
||||||
rofi_view_nav_right ( state );
|
rofi_view_nav_right ( state );
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( state->scrollbar && widget_intersect ( &( state->scrollbar->widget ), xbe->x, xbe->y ) ) {
|
if ( state->scrollbar && widget_intersect ( &( state->scrollbar->widget ), xbe->event_x, xbe->event_y ) ) {
|
||||||
state->selected = scrollbar_clicked ( state->scrollbar, xbe->y );
|
state->selected = scrollbar_clicked ( state->scrollbar, xbe->event_y );
|
||||||
state->update = TRUE;
|
state->update = TRUE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ( unsigned int i = 0; config.sidebar_mode == TRUE && i < state->num_modi; i++ ) {
|
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->selected_line ) = 0;
|
||||||
state->retv = MENU_QUICK_SWITCH | ( i & MENU_LOWER_MASK );
|
state->retv = MENU_QUICK_SWITCH | ( i & MENU_LOWER_MASK );
|
||||||
state->quit = TRUE;
|
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++ ) {
|
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.
|
// Only allow items that are visible to be selected.
|
||||||
if ( ( state->last_offset + i ) >= state->filtered_lines ) {
|
if ( ( state->last_offset + i ) >= state->filtered_lines ) {
|
||||||
break;
|
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 ) {
|
switch ( ev->response_type & ~0x80 )
|
||||||
XRefreshKeyboardMapping ( &( ev->xmapping ) );
|
{
|
||||||
}
|
case XCB_FOCUS_IN:
|
||||||
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 ) {
|
|
||||||
if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
||||||
take_keyboard ( display, main_window );
|
take_keyboard ( display, main_window );
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if ( ev->type == FocusOut ) {
|
case XCB_FOCUS_OUT:
|
||||||
if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
||||||
release_keyboard ( display );
|
release_keyboard ( display );
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
// Handle event.
|
case XCB_MOTION_NOTIFY:
|
||||||
else if ( ev->type == Expose ) {
|
{
|
||||||
while ( XCheckTypedEvent ( display, Expose, ev ) ) {
|
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;
|
|
||||||
}
|
|
||||||
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 );
|
|
||||||
state->update = TRUE;
|
state->update = TRUE;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// Button press event.
|
case XCB_BUTTON_PRESS:
|
||||||
else if ( ev->type == ButtonPress ) {
|
rofi_view_mouse_navigation ( state, (xcb_button_press_event_t *) ev );
|
||||||
while ( XCheckTypedEvent ( display, ButtonPress, ev ) ) {
|
break;
|
||||||
;
|
|
||||||
}
|
|
||||||
rofi_view_mouse_navigation ( state, &( ev->xbutton ) );
|
|
||||||
}
|
|
||||||
// Paste event.
|
// Paste event.
|
||||||
else if ( ev->type == SelectionNotify ) {
|
case XCB_SELECTION_NOTIFY:
|
||||||
do {
|
rofi_view_paste ( state, (xcb_selection_notify_event_t *) ev );
|
||||||
rofi_view_paste ( state, &( ev->xselection ) );
|
break;
|
||||||
} while ( XCheckTypedEvent ( display, SelectionNotify, ev ) );
|
case XCB_KEY_PRESS:
|
||||||
}
|
{
|
||||||
// Key press event.
|
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) ev;
|
||||||
else if ( ev->type == KeyPress ) {
|
XEvent fake_event;
|
||||||
do {
|
fake_event.type = KeyPress;
|
||||||
// This is needed for letting the Input Method handle combined keys.
|
fake_event.xany.display = display;
|
||||||
// E.g. `e into è
|
fake_event.xany.window = xkpe->event;
|
||||||
if ( XFilterEvent ( ev, main_window ) ) {
|
fake_event.xkey.state = xkpe->state;
|
||||||
continue;
|
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;
|
else if ( abe_test_action ( PASTE_SECONDARY, xkpe->state, key ) ) {
|
||||||
char pad[32];
|
XConvertSelection ( display, netatoms[CLIPBOARD], netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window,
|
||||||
KeySym key; // = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
|
CurrentTime );
|
||||||
int len = Xutf8LookupString ( xic, &( ev->xkey ), pad, sizeof ( pad ), &key, &stat );
|
}
|
||||||
pad[len] = 0;
|
if ( abe_test_action ( SCREENSHOT, xkpe->state, key ) ) {
|
||||||
if ( stat == XLookupKeySym || stat == XLookupBoth ) {
|
menu_capture_screenshot ( );
|
||||||
// Handling of paste
|
break;
|
||||||
if ( abe_test_action ( PASTE_PRIMARY, ev->xkey.state, key ) ) {
|
}
|
||||||
XConvertSelection ( display, XA_PRIMARY, netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window, CurrentTime );
|
if ( abe_test_action ( TOGGLE_SORT, xkpe->state, key ) ) {
|
||||||
}
|
config.levenshtein_sort = !config.levenshtein_sort;
|
||||||
else if ( abe_test_action ( PASTE_SECONDARY, ev->xkey.state, key ) ) {
|
state->refilter = TRUE;
|
||||||
XConvertSelection ( display, netatoms[CLIPBOARD], netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window,
|
state->update = TRUE;
|
||||||
CurrentTime );
|
textbox_text ( state->case_indicator, get_matching_state () );
|
||||||
}
|
break;
|
||||||
if ( abe_test_action ( SCREENSHOT, ev->xkey.state, key ) ) {
|
}
|
||||||
menu_capture_screenshot ( );
|
else if ( abe_test_action ( MODE_PREVIOUS, xkpe->state, key ) ) {
|
||||||
break;
|
state->retv = MENU_PREVIOUS;
|
||||||
}
|
( state->selected_line ) = 0;
|
||||||
if ( abe_test_action ( TOGGLE_SORT, ev->xkey.state, key ) ) {
|
state->quit = TRUE;
|
||||||
config.levenshtein_sort = !config.levenshtein_sort;
|
break;
|
||||||
state->refilter = TRUE;
|
}
|
||||||
state->update = TRUE;
|
// Menu navigation.
|
||||||
textbox_text ( state->case_indicator, get_matching_state () );
|
else if ( abe_test_action ( MODE_NEXT, xkpe->state, key ) ) {
|
||||||
break;
|
state->retv = MENU_NEXT;
|
||||||
}
|
( state->selected_line ) = 0;
|
||||||
else if ( abe_test_action ( MODE_PREVIOUS, ev->xkey.state, key ) ) {
|
state->quit = TRUE;
|
||||||
state->retv = MENU_PREVIOUS;
|
break;
|
||||||
( state->selected_line ) = 0;
|
}
|
||||||
|
// Toggle case sensitivity.
|
||||||
|
else if ( abe_test_action ( TOGGLE_CASE_SENSITIVITY, xkpe->state, key ) ) {
|
||||||
|
config.case_sensitive = !config.case_sensitive;
|
||||||
|
( state->selected_line ) = 0;
|
||||||
|
state->refilter = TRUE;
|
||||||
|
state->update = TRUE;
|
||||||
|
textbox_text ( state->case_indicator, get_matching_state () );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Special delete entry command.
|
||||||
|
else if ( abe_test_action ( DELETE_ENTRY, xkpe->state, key ) ) {
|
||||||
|
if ( state->selected < state->filtered_lines ) {
|
||||||
|
( state->selected_line ) = state->line_map[state->selected];
|
||||||
|
state->retv = MENU_ENTRY_DELETE;
|
||||||
state->quit = TRUE;
|
state->quit = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Menu navigation.
|
|
||||||
else if ( abe_test_action ( MODE_NEXT, ev->xkey.state, key ) ) {
|
|
||||||
state->retv = MENU_NEXT;
|
|
||||||
( state->selected_line ) = 0;
|
|
||||||
state->quit = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Toggle case sensitivity.
|
|
||||||
else if ( abe_test_action ( TOGGLE_CASE_SENSITIVITY, ev->xkey.state, key ) ) {
|
|
||||||
config.case_sensitive = !config.case_sensitive;
|
|
||||||
( state->selected_line ) = 0;
|
|
||||||
state->refilter = TRUE;
|
|
||||||
state->update = TRUE;
|
|
||||||
textbox_text ( state->case_indicator, get_matching_state () );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Special delete entry command.
|
|
||||||
else if ( abe_test_action ( DELETE_ENTRY, ev->xkey.state, key ) ) {
|
|
||||||
if ( state->selected < state->filtered_lines ) {
|
|
||||||
( state->selected_line ) = state->line_map[state->selected];
|
|
||||||
state->retv = MENU_ENTRY_DELETE;
|
|
||||||
state->quit = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( unsigned int a = CUSTOM_1; a <= CUSTOM_19; a++ ) {
|
|
||||||
if ( abe_test_action ( a, ev->xkey.state, key ) ) {
|
|
||||||
state->selected_line = UINT32_MAX;
|
|
||||||
if ( state->selected < state->filtered_lines ) {
|
|
||||||
( state->selected_line ) = state->line_map[state->selected];
|
|
||||||
}
|
|
||||||
state->retv = MENU_QUICK_SWITCH | ( ( a - CUSTOM_1 ) & MENU_LOWER_MASK );
|
|
||||||
state->quit = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( rofi_view_keyboard_navigation ( state, key, ev->xkey.state ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
for ( unsigned int a = CUSTOM_1; a <= CUSTOM_19; a++ ) {
|
||||||
// Skip if we detected key before.
|
if ( abe_test_action ( a, xkpe->state, key ) ) {
|
||||||
if ( state->quit ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rc = textbox_keypress ( state->text, ev, pad, len, key, stat );
|
|
||||||
// Row is accepted.
|
|
||||||
if ( rc < 0 ) {
|
|
||||||
int shift = ( ( ev->xkey.state & ShiftMask ) == ShiftMask );
|
|
||||||
|
|
||||||
// If a valid item is selected, return that..
|
|
||||||
state->selected_line = UINT32_MAX;
|
state->selected_line = UINT32_MAX;
|
||||||
if ( state->selected < state->filtered_lines ) {
|
if ( state->selected < state->filtered_lines ) {
|
||||||
( state->selected_line ) = state->line_map[state->selected];
|
( state->selected_line ) = state->line_map[state->selected];
|
||||||
if ( strlen ( state->text->text ) > 0 && rc == -2 ) {
|
|
||||||
state->retv = MENU_CUSTOM_INPUT;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state->retv = MENU_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ( strlen ( state->text->text ) > 0 ) {
|
state->retv = MENU_QUICK_SWITCH | ( ( a - CUSTOM_1 ) & MENU_LOWER_MASK );
|
||||||
state->retv = MENU_CUSTOM_INPUT;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// Nothing entered and nothing selected.
|
|
||||||
state->retv = MENU_CUSTOM_INPUT;
|
|
||||||
}
|
|
||||||
if ( shift ) {
|
|
||||||
state->retv |= MENU_SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->quit = TRUE;
|
state->quit = TRUE;
|
||||||
}
|
break;
|
||||||
// Key press is handled by entry box.
|
|
||||||
else if ( rc == 1 ) {
|
|
||||||
state->refilter = TRUE;
|
|
||||||
state->update = TRUE;
|
|
||||||
}
|
|
||||||
else if ( rc == 2 ) {
|
|
||||||
// redraw.
|
|
||||||
state->update = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ( XCheckTypedEvent ( display, KeyPress, ev ) );
|
if ( rofi_view_keyboard_navigation ( state, key, xkpe->state ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Skip if we detected key before.
|
||||||
|
if ( state->quit ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = textbox_keypress ( state->text, xkpe, pad, len, key, stat );
|
||||||
|
// Row is accepted.
|
||||||
|
if ( rc < 0 ) {
|
||||||
|
int shift = ( ( xkpe->state & ShiftMask ) == ShiftMask );
|
||||||
|
|
||||||
|
// If a valid item is selected, return that..
|
||||||
|
state->selected_line = UINT32_MAX;
|
||||||
|
if ( state->selected < state->filtered_lines ) {
|
||||||
|
( state->selected_line ) = state->line_map[state->selected];
|
||||||
|
if ( strlen ( state->text->text ) > 0 && rc == -2 ) {
|
||||||
|
state->retv = MENU_CUSTOM_INPUT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state->retv = MENU_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( strlen ( state->text->text ) > 0 ) {
|
||||||
|
state->retv = MENU_CUSTOM_INPUT;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// Nothing entered and nothing selected.
|
||||||
|
state->retv = MENU_CUSTOM_INPUT;
|
||||||
|
}
|
||||||
|
if ( shift ) {
|
||||||
|
state->retv |= MENU_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->quit = TRUE;
|
||||||
|
}
|
||||||
|
// Key press is handled by entry box.
|
||||||
|
else if ( rc == 1 ) {
|
||||||
|
state->refilter = TRUE;
|
||||||
|
state->update = TRUE;
|
||||||
|
}
|
||||||
|
else if ( rc == 2 ) {
|
||||||
|
// redraw.
|
||||||
|
state->update = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Update if requested.
|
// Update if requested.
|
||||||
if ( state->refilter ) {
|
if ( state->refilter ) {
|
||||||
|
@ -1625,38 +1625,15 @@ RofiViewState *rofi_view_create ( Mode *sw,
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
static void __error_dialog_event_loop ( RofiViewState *state, XEvent *ev )
|
static void __error_dialog_event_loop ( RofiViewState *state, xcb_generic_event_t *ev )
|
||||||
{
|
{
|
||||||
// Handle event.
|
// Handle event.
|
||||||
if ( ev->type == Expose ) {
|
switch ( ev->response_type & ~0x80 )
|
||||||
while ( XCheckTypedEvent ( display, Expose, ev ) ) {
|
{
|
||||||
;
|
|
||||||
}
|
|
||||||
state->update = TRUE;
|
|
||||||
}
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Key press event.
|
// Key press event.
|
||||||
else if ( ev->type == KeyPress ) {
|
case XCB_KEY_PRESS:
|
||||||
while ( XCheckTypedEvent ( display, KeyPress, ev ) ) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
state->quit = TRUE;
|
state->quit = TRUE;
|
||||||
}
|
}
|
||||||
rofi_view_update ( state );
|
|
||||||
}
|
}
|
||||||
void process_result_error ( RofiViewState *state );
|
void process_result_error ( RofiViewState *state );
|
||||||
void rofi_view_error_dialog ( const char *msg, int markup )
|
void rofi_view_error_dialog ( const char *msg, int markup )
|
||||||
|
|
Loading…
Reference in a new issue