mirror of https://github.com/davatorium/rofi.git
Issue: #381: Try to handle X11 input and UTF-8 better.
In window_get_text_prop do conversion when input is of type STRING. (latin1) to utf8. Dmenu: don't skip invalid lines, but try to display as much as possible. Window mode: Double check all input from X.
This commit is contained in:
parent
c3b236db28
commit
e54e012500
|
@ -166,5 +166,10 @@ void cmd_set_arguments ( int argc, char **argv );
|
||||||
char *rofi_expand_path ( const char *input );
|
char *rofi_expand_path ( const char *input );
|
||||||
unsigned int levenshtein ( const char *needle, const char *haystack );
|
unsigned int levenshtein ( const char *needle, const char *haystack );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert string to valid utf-8, replacing invalid parts with replacement character.
|
||||||
|
*/
|
||||||
|
char * rofi_force_utf8 ( gchar *data );
|
||||||
|
char * rofi_latin_to_utf8_strdup ( const char *input, gssize length );
|
||||||
/*@}*/
|
/*@}*/
|
||||||
#endif // ROFI_HELPER_H
|
#endif // ROFI_HELPER_H
|
||||||
|
|
|
@ -36,6 +36,8 @@ void window_set_atom_prop ( xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms,
|
||||||
#define EWMH_ATOMS( X ) \
|
#define EWMH_ATOMS( X ) \
|
||||||
X ( _NET_WM_WINDOW_OPACITY ), \
|
X ( _NET_WM_WINDOW_OPACITY ), \
|
||||||
X ( I3_SOCKET_PATH ), \
|
X ( I3_SOCKET_PATH ), \
|
||||||
|
X ( UTF8_STRING ), \
|
||||||
|
X ( STRING ), \
|
||||||
X ( WM_WINDOW_ROLE )
|
X ( WM_WINDOW_ROLE )
|
||||||
|
|
||||||
enum { EWMH_ATOMS ( ATOM_ENUM ), NUM_NETATOMS };
|
enum { EWMH_ATOMS ( ATOM_ENUM ), NUM_NETATOMS };
|
||||||
|
|
|
@ -92,10 +92,8 @@ static char **get_dmenu ( DmenuModePrivateData *pd, FILE *fd, unsigned int *leng
|
||||||
data[l - 1] = '\0';
|
data[l - 1] = '\0';
|
||||||
l--;
|
l--;
|
||||||
}
|
}
|
||||||
if ( !g_utf8_validate ( data, l, NULL ) ) {
|
data = rofi_force_utf8 ( data );
|
||||||
fprintf ( stderr, "String: '%s' is not valid utf-8\n", data );
|
printf ( "data: %s\n", data );
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
retv[( *length )] = data;
|
retv[( *length )] = data;
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
|
@ -53,8 +53,6 @@
|
||||||
|
|
||||||
#define WINLIST 32
|
#define WINLIST 32
|
||||||
|
|
||||||
#define CLIENTTITLE 100
|
|
||||||
#define CLIENTCLASS 50
|
|
||||||
#define CLIENTSTATE 10
|
#define CLIENTSTATE 10
|
||||||
#define CLIENTWINDOWTYPE 10
|
#define CLIENTWINDOWTYPE 10
|
||||||
#define CLIENTROLE 50
|
#define CLIENTROLE 50
|
||||||
|
@ -285,7 +283,8 @@ static client* window_client ( xcb_window_t win )
|
||||||
cky = xcb_icccm_get_wm_class ( xcb->connection, c->window );
|
cky = xcb_icccm_get_wm_class ( xcb->connection, c->window );
|
||||||
xcb_icccm_get_wm_class_reply_t wcr;
|
xcb_icccm_get_wm_class_reply_t wcr;
|
||||||
if ( xcb_icccm_get_wm_class_reply ( xcb->connection, cky, &wcr, NULL ) ) {
|
if ( xcb_icccm_get_wm_class_reply ( xcb->connection, cky, &wcr, NULL ) ) {
|
||||||
c->class = g_strdup ( wcr.class_name );
|
c->class = rofi_latin_to_utf8_strdup ( wcr.class_name, -1 );
|
||||||
|
c->name = rofi_latin_to_utf8_strdup ( wcr.instance_name, -1 );
|
||||||
xcb_icccm_get_wm_class_reply_wipe ( &wcr );
|
xcb_icccm_get_wm_class_reply_wipe ( &wcr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +294,14 @@ static client* window_client ( xcb_window_t win )
|
||||||
c->hint_flags = r.flags;
|
c->hint_flags = r.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Do UTF-8 Check, should not be needed, does not hurt here to be paranoid. */
|
||||||
|
{
|
||||||
|
c->title = rofi_force_utf8 ( c->title );
|
||||||
|
c->class = rofi_force_utf8 ( c->class );
|
||||||
|
c->name = rofi_force_utf8 ( c->name );
|
||||||
|
c->role = rofi_force_utf8 ( c->role );
|
||||||
|
}
|
||||||
|
|
||||||
winlist_append ( cache_client, c->window, c );
|
winlist_append ( cache_client, c->window, c );
|
||||||
g_free ( attr );
|
g_free ( attr );
|
||||||
return c;
|
return c;
|
||||||
|
|
|
@ -659,3 +659,42 @@ unsigned int levenshtein ( const char *needle, const char *haystack )
|
||||||
}
|
}
|
||||||
return column[needlelen];
|
return column[needlelen];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * rofi_latin_to_utf8_strdup ( const char *input, gssize length )
|
||||||
|
{
|
||||||
|
gsize slength = 0;
|
||||||
|
return g_convert_with_fallback ( input, length, "UTF-8", "latin1", "\uFFFD", NULL, &slength, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
char * rofi_force_utf8 ( gchar *start )
|
||||||
|
{
|
||||||
|
if ( start == NULL ) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const char *data = start;
|
||||||
|
const char *end;
|
||||||
|
gsize length = strlen ( data );
|
||||||
|
GString *string;
|
||||||
|
|
||||||
|
if ( g_utf8_validate ( data, length, &end ) ) {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
string = g_string_sized_new ( length + 16 );
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Valid part of the string */
|
||||||
|
g_string_append_len ( string, data, end - data );
|
||||||
|
/* Replacement character */
|
||||||
|
g_string_append ( string, "\uFFFD" );
|
||||||
|
length -= ( end - data ) + 1;
|
||||||
|
data = end + 1;
|
||||||
|
} while ( !g_utf8_validate ( data, length, &end ) );
|
||||||
|
|
||||||
|
if ( length ) {
|
||||||
|
g_string_append_len ( string, data, length );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free input string.
|
||||||
|
g_free ( start );
|
||||||
|
return g_string_free ( string, FALSE );
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "xcb-internal.h"
|
#include "xcb-internal.h"
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
#include <rofi.h>
|
#include <rofi.h>
|
||||||
#define OVERLAP( a, b, c, \
|
#define OVERLAP( a, b, c, \
|
||||||
|
@ -90,9 +91,17 @@ char* window_get_text_prop ( xcb_window_t w, xcb_atom_t atom )
|
||||||
xcb_get_property_reply_t *r = xcb_get_property_reply ( xcb->connection, c, NULL );
|
xcb_get_property_reply_t *r = xcb_get_property_reply ( xcb->connection, c, NULL );
|
||||||
if ( r ) {
|
if ( r ) {
|
||||||
if ( xcb_get_property_value_length ( r ) > 0 ) {
|
if ( xcb_get_property_value_length ( r ) > 0 ) {
|
||||||
char *str = g_malloc ( xcb_get_property_value_length ( r ) + 1 );
|
char *str = NULL;
|
||||||
memcpy ( str, xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
|
if ( r->type == netatoms[UTF8_STRING] ) {
|
||||||
str[xcb_get_property_value_length ( r )] = '\0';
|
str = g_strndup ( xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
|
||||||
|
}
|
||||||
|
else if ( r->type == netatoms[STRING] ) {
|
||||||
|
str = rofi_latin_to_utf8_strdup ( xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = g_strdup ( "Invalid encoding." );
|
||||||
|
}
|
||||||
|
|
||||||
free ( r );
|
free ( r );
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue