mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
Pango testing.
This commit is contained in:
parent
f87b55dde9
commit
6a45a18a4e
5 changed files with 101 additions and 71 deletions
|
@ -7,13 +7,15 @@ LIBS=\
|
|||
@xft_LIBS@\
|
||||
@x11_LIBS@\
|
||||
@xdgbasedir_LIBS@\
|
||||
@xinerama_LIBS@
|
||||
@xinerama_LIBS@\
|
||||
@pango_LIBS@
|
||||
|
||||
AM_CFLAGS=\
|
||||
@xft_CFLAGS@\
|
||||
@x11_CFLAGS@\
|
||||
@xdgbasedir_CFLAGS@\
|
||||
@xinerama_CFLAGS@\
|
||||
@pango_CFLAGS@\
|
||||
-DMANPAGE_PATH="\"$(mandir)/man1/rofi.1\""\
|
||||
-I$(top_srcdir)/include/\
|
||||
-I$(top_srcdir)/config/\
|
||||
|
|
|
@ -31,6 +31,7 @@ PKG_CHECK_MODULES([xft], [xft])
|
|||
PKG_CHECK_MODULES([x11], [x11])
|
||||
PKG_CHECK_MODULES([xinerama], [xinerama])
|
||||
PKG_CHECK_MODULES([xdgbasedir], [libxdg-basedir])
|
||||
PKG_CHECK_MODULES([pango], [pango pangoxft])
|
||||
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
|
|
|
@ -2,18 +2,21 @@
|
|||
#define __TEXTBOX_H__
|
||||
#include <X11/Xft/Xft.h>
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <pango/pangoxft.h>
|
||||
#include <pango/pango-fontmap.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long flags;
|
||||
Window window, parent;
|
||||
short x, y, w, h;
|
||||
short cursor;
|
||||
XftFont *font;
|
||||
XftColor color_fg, color_bg;
|
||||
char *text;
|
||||
XIM xim;
|
||||
XIC xic;
|
||||
XGlyphInfo extents;
|
||||
PangoLayout *layout;
|
||||
} textbox;
|
||||
|
||||
|
||||
|
@ -76,7 +79,6 @@ void textbox_hide ( textbox *tb );
|
|||
* Clean with textbox_cleanup()
|
||||
*/
|
||||
void textbox_setup (
|
||||
const char *font_str, const char *font_active_str,
|
||||
const char *bg, const char *fg,
|
||||
const char *hlbg, const char *hlfg
|
||||
);
|
||||
|
@ -86,4 +88,9 @@ void textbox_setup (
|
|||
*/
|
||||
void textbox_cleanup ();
|
||||
|
||||
int textbox_get_height ( textbox *tb );
|
||||
int textbox_get_width ( textbox *tb );
|
||||
int textbox_get_font_height ( textbox *tb );
|
||||
int textbox_get_font_width ( textbox *tb );
|
||||
|
||||
#endif //__TEXTBOX_H__
|
||||
|
|
|
@ -1123,14 +1123,15 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
|
|||
0, 0, NORMAL, prompt );
|
||||
|
||||
textbox *text = textbox_create ( main_window, TB_AUTOHEIGHT | TB_EDITABLE,
|
||||
( config.padding ) + prompt_tb->w,
|
||||
( config.padding ) + textbox_get_width ( prompt_tb ),
|
||||
( config.padding ),
|
||||
( ( config.hmode == TRUE ) ?
|
||||
element_width : ( w - ( 2 * ( config.padding ) ) ) ) - prompt_tb->w, 1,
|
||||
element_width : ( w - ( 2 * ( config.padding ) ) ) )
|
||||
- textbox_get_width ( prompt_tb ), 1,
|
||||
NORMAL,
|
||||
( input != NULL ) ? *input : "" );
|
||||
|
||||
int line_height = text->font->ascent + text->font->descent;
|
||||
int line_height = textbox_get_height ( text ); //text->font->ascent + text->font->descent;
|
||||
|
||||
textbox_show ( text );
|
||||
textbox_show ( prompt_tb );
|
||||
|
@ -1722,10 +1723,10 @@ static void run_switcher ( int do_fork, SwitcherMode mode )
|
|||
}
|
||||
// Because of the above fork, we want to do this here.
|
||||
// Make sure this is isolated to its own thread.
|
||||
textbox_setup ( config.menu_font, active_font,
|
||||
config.menu_bg, config.menu_fg,
|
||||
config.menu_hlbg,
|
||||
config.menu_hlfg );
|
||||
textbox_setup (
|
||||
config.menu_bg, config.menu_fg,
|
||||
config.menu_hlbg,
|
||||
config.menu_hlfg );
|
||||
char *input = NULL;
|
||||
// Dmenu is a special mode. You can cycle away from it.
|
||||
if ( mode == DMENU_DIALOG ) {
|
||||
|
|
139
source/textbox.c
139
source/textbox.c
|
@ -37,22 +37,25 @@
|
|||
#include <X11/Xft/Xft.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#include "rofi.h"
|
||||
#include "textbox.h"
|
||||
#define SIDE_MARGIN 2
|
||||
|
||||
|
||||
extern Display *display;
|
||||
|
||||
/**
|
||||
* Font + font color cache.
|
||||
* Avoid re-loading font on every change on every textbox.
|
||||
*/
|
||||
XftFont *font = NULL;
|
||||
XftFont *font_active = NULL;
|
||||
XftColor color_fg;
|
||||
XftColor color_bg;
|
||||
XftColor color_hlfg;
|
||||
XftColor color_hlbg;
|
||||
XftColor color_fg;
|
||||
XftColor color_bg;
|
||||
XftColor color_hlfg;
|
||||
XftColor color_hlbg;
|
||||
|
||||
PangoContext *p_context = NULL;
|
||||
|
||||
|
||||
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h );
|
||||
|
||||
|
@ -73,6 +76,12 @@ textbox* textbox_create ( Window parent,
|
|||
tb->w = MAX ( 1, w );
|
||||
tb->h = MAX ( 1, h );
|
||||
|
||||
tb->layout = pango_layout_new ( p_context );
|
||||
|
||||
PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font );
|
||||
pango_layout_set_font_description ( tb->layout, pfd );
|
||||
pango_font_description_free ( pfd );
|
||||
|
||||
unsigned int cp = ( tbft == NORMAL ) ? color_bg.pixel : color_hlbg.pixel;
|
||||
|
||||
tb->window = XCreateSimpleWindow ( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
|
||||
|
@ -98,36 +107,36 @@ textbox* textbox_create ( Window parent,
|
|||
// set an Xft font by name
|
||||
void textbox_font ( textbox *tb, TextBoxFontType tbft )
|
||||
{
|
||||
PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font );
|
||||
switch ( tbft )
|
||||
{
|
||||
case HIGHLIGHT:
|
||||
tb->font = font;
|
||||
tb->color_bg = color_hlbg;
|
||||
tb->color_fg = color_hlfg;
|
||||
break;
|
||||
case ACTIVE:
|
||||
tb->font = font_active;
|
||||
pango_font_description_set_style ( pfd, PANGO_STYLE_ITALIC );
|
||||
tb->color_bg = color_bg;
|
||||
tb->color_fg = color_fg;
|
||||
break;
|
||||
case ACTIVE_HIGHLIGHT:
|
||||
tb->font = font_active;
|
||||
pango_font_description_set_style ( pfd, PANGO_STYLE_ITALIC );
|
||||
tb->color_bg = color_hlbg;
|
||||
tb->color_fg = color_hlfg;
|
||||
break;
|
||||
case NORMAL:
|
||||
default:
|
||||
tb->font = font;
|
||||
tb->color_bg = color_bg;
|
||||
tb->color_fg = color_fg;
|
||||
break;
|
||||
}
|
||||
pango_layout_set_font_description ( tb->layout, pfd );
|
||||
pango_font_description_free ( pfd );
|
||||
}
|
||||
|
||||
// outer code may need line height, width, etc
|
||||
void textbox_extents ( textbox *tb )
|
||||
{
|
||||
XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) tb->text, strlen ( tb->text ), &tb->extents );
|
||||
}
|
||||
|
||||
// set the default text to display
|
||||
|
@ -137,7 +146,9 @@ void textbox_text ( textbox *tb, char *text )
|
|||
free ( tb->text );
|
||||
}
|
||||
|
||||
tb->text = strdup ( text );
|
||||
tb->text = strdup ( text );
|
||||
pango_layout_set_text ( tb->layout, tb->text, strlen ( tb->text ) );
|
||||
|
||||
tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( text ), tb->cursor ) );
|
||||
textbox_extents ( tb );
|
||||
}
|
||||
|
@ -154,17 +165,21 @@ void textbox_move ( textbox *tb, int x, int y )
|
|||
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
|
||||
{
|
||||
if ( tb->flags & TB_AUTOHEIGHT ) {
|
||||
h = tb->font->ascent + tb->font->descent;
|
||||
h = textbox_get_font_height ( tb );
|
||||
}
|
||||
|
||||
if ( tb->flags & TB_AUTOWIDTH ) {
|
||||
if ( w > 1 ) {
|
||||
w = MIN ( w, tb->extents.width + 2 * SIDE_MARGIN );
|
||||
w = MIN ( w, textbox_get_font_width ( tb ) + 2 * SIDE_MARGIN );
|
||||
}
|
||||
else{
|
||||
w = tb->extents.width + 2 * SIDE_MARGIN;
|
||||
w = textbox_get_font_width ( tb ) + 2 * SIDE_MARGIN;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set ellipsize
|
||||
pango_layout_set_ellipsize ( tb->layout, PANGO_ELLIPSIZE_END );
|
||||
}
|
||||
|
||||
if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h ) {
|
||||
tb->x = x;
|
||||
|
@ -199,6 +214,9 @@ void textbox_free ( textbox *tb )
|
|||
if ( tb->text ) {
|
||||
free ( tb->text );
|
||||
}
|
||||
if ( tb->layout == NULL ) {
|
||||
g_object_unref ( tb->layout );
|
||||
}
|
||||
|
||||
XDestroyWindow ( display, tb->window );
|
||||
free ( tb );
|
||||
|
@ -206,11 +224,9 @@ void textbox_free ( textbox *tb )
|
|||
|
||||
void textbox_draw ( textbox *tb )
|
||||
{
|
||||
XGlyphInfo extents;
|
||||
|
||||
GC context = XCreateGC ( display, tb->window, 0, 0 );
|
||||
Pixmap canvas = XCreatePixmap ( display, tb->window, tb->w, tb->h, DefaultDepth ( display, DefaultScreen ( display ) ) );
|
||||
XftDraw *draw = XftDrawCreate ( display, canvas, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ) );
|
||||
GC context = XCreateGC ( display, tb->window, 0, 0 );
|
||||
Pixmap canvas = XCreatePixmap ( display, tb->window, tb->w, tb->h, DefaultDepth ( display, DefaultScreen ( display ) ) );
|
||||
XftDraw *draw = XftDrawCreate ( display, canvas, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ) );
|
||||
|
||||
// clear canvas
|
||||
XftDrawRect ( draw, &tb->color_bg, 0, 0, tb->w, tb->h );
|
||||
|
@ -218,46 +234,26 @@ void textbox_draw ( textbox *tb )
|
|||
char *text = tb->text ? tb->text : "";
|
||||
int text_len = strlen ( text );
|
||||
int length = text_len;
|
||||
int line_height = tb->font->ascent + tb->font->descent;
|
||||
int line_height = textbox_get_font_height ( tb );
|
||||
int line_width = 0;
|
||||
|
||||
int cursor_x = 0;
|
||||
int cursor_width = MAX ( 2, line_height / 10 );
|
||||
|
||||
if ( tb->flags & TB_EDITABLE ) {
|
||||
int cursor_offset = 0;
|
||||
cursor_offset = MIN ( tb->cursor, text_len );
|
||||
pango_layout_set_text ( tb->layout, tb->text, strlen ( tb->text ) );
|
||||
|
||||
// Trailing spaces still go wrong....
|
||||
// The replace by _ is needed, one way or the other.
|
||||
// Make a copy, and replace all trailing spaces.
|
||||
char *test = strdup ( text );
|
||||
for ( int iter = strlen ( text ) - 1; iter >= 0 && test[iter] == ' '; iter-- ) {
|
||||
test[iter] = '_';
|
||||
}
|
||||
// calc cursor position
|
||||
XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) test, cursor_offset, &extents );
|
||||
if ( tb->flags & TB_EDITABLE ) {
|
||||
PangoRectangle pos;
|
||||
int cursor_offset = 0;
|
||||
cursor_offset = MIN ( tb->cursor, text_len );
|
||||
pango_layout_get_cursor_pos ( tb->layout, cursor_offset, &pos, NULL );
|
||||
// Add a small 4px offset between cursor and last glyph.
|
||||
cursor_x = extents.width + ( ( extents.width > 0 ) ? 2 : 0 );
|
||||
free ( test );
|
||||
cursor_x = pos.x / PANGO_SCALE;
|
||||
}
|
||||
|
||||
// calc full input text width
|
||||
// Calculate the right size, so no characters are cut off.
|
||||
// TODO: Check performance of this.
|
||||
do {
|
||||
XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) text, length, &extents );
|
||||
line_width = extents.width;
|
||||
if ( line_width <= ( tb->w - 2 * SIDE_MARGIN ) ) {
|
||||
break;
|
||||
}
|
||||
pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tb->w - 2 * SIDE_MARGIN ) );
|
||||
|
||||
for ( length -= 1; length > 0 && ( text[length] & 0xc0 ) == 0x80; length -= 1 ) {
|
||||
;
|
||||
}
|
||||
} while ( line_width > 0 );
|
||||
|
||||
int x = SIDE_MARGIN, y = tb->font->ascent;
|
||||
int x = SIDE_MARGIN, y = 0;
|
||||
|
||||
if ( tb->flags & TB_RIGHT ) {
|
||||
x = tb->w - line_width;
|
||||
|
@ -268,7 +264,9 @@ void textbox_draw ( textbox *tb )
|
|||
}
|
||||
|
||||
// draw the text.
|
||||
XftDrawStringUtf8 ( draw, &tb->color_fg, tb->font, x, y, ( unsigned char * ) text, length );
|
||||
// XftDrawStringUtf8 ( draw, &tb->color_fg, tb->font, x, y, ( unsigned char * ) text, length );
|
||||
|
||||
pango_xft_render_layout ( draw, &( tb->color_fg ), tb->layout, x, y );
|
||||
|
||||
// draw the cursor
|
||||
if ( tb->flags & TB_EDITABLE ) {
|
||||
|
@ -422,38 +420,59 @@ int textbox_keypress ( textbox *tb, XEvent *ev )
|
|||
*/
|
||||
|
||||
void textbox_setup (
|
||||
const char *font_str, const char *font_active_str,
|
||||
const char *bg, const char *fg,
|
||||
const char *hlbg, const char *hlfg
|
||||
)
|
||||
{
|
||||
Visual *visual = DefaultVisual ( display, DefaultScreen ( display ) );
|
||||
Colormap colormap = DefaultColormap ( display, DefaultScreen ( display ) );
|
||||
font = XftFontOpenName ( display, DefaultScreen ( display ), font_str );
|
||||
font_active = XftFontOpenName ( display, DefaultScreen ( display ), font_active_str );
|
||||
|
||||
XftColorAllocName ( display, visual, colormap, fg, &color_fg );
|
||||
XftColorAllocName ( display, visual, colormap, bg, &color_bg );
|
||||
XftColorAllocName ( display, visual, colormap, hlfg, &color_hlfg );
|
||||
XftColorAllocName ( display, visual, colormap, hlbg, &color_hlbg );
|
||||
|
||||
PangoFontMap *font_map = pango_xft_get_font_map ( display, DefaultScreen ( display ) );
|
||||
p_context = pango_font_map_create_context ( font_map );
|
||||
}
|
||||
|
||||
|
||||
void textbox_cleanup ()
|
||||
{
|
||||
if ( font != NULL ) {
|
||||
if ( p_context ) {
|
||||
Visual *visual = DefaultVisual ( display, DefaultScreen ( display ) );
|
||||
Colormap colormap = DefaultColormap ( display, DefaultScreen ( display ) );
|
||||
|
||||
XftFontClose ( display, font );
|
||||
font = NULL;
|
||||
|
||||
XftFontClose ( display, font_active );
|
||||
font_active = NULL;
|
||||
|
||||
XftColorFree ( display, visual, colormap, &color_fg );
|
||||
XftColorFree ( display, visual, colormap, &color_bg );
|
||||
XftColorFree ( display, visual, colormap, &color_hlfg );
|
||||
XftColorFree ( display, visual, colormap, &color_hlbg );
|
||||
g_object_unref ( p_context );
|
||||
p_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int textbox_get_width ( textbox *tb )
|
||||
{
|
||||
return textbox_get_font_width ( tb ) + 2 * SIDE_MARGIN;
|
||||
}
|
||||
|
||||
int textbox_get_height ( textbox *tb )
|
||||
{
|
||||
return textbox_get_font_height ( tb );
|
||||
}
|
||||
|
||||
int textbox_get_font_height ( textbox *tb )
|
||||
{
|
||||
int height;
|
||||
pango_layout_get_pixel_size ( tb->layout, NULL, &height );
|
||||
return height;
|
||||
}
|
||||
|
||||
int textbox_get_font_width ( textbox *tb )
|
||||
{
|
||||
int width;
|
||||
pango_layout_get_pixel_size ( tb->layout, &width, NULL );
|
||||
return width;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue