static void
iti_draw_cursor (MateIconTextItem *iti, GdkDrawable *drawable,
                 int x, int y)
{
    int stem_width;
    int i;
    int cursor_offset;
    PangoRectangle pos;
    GtkEntry *entry;

    g_return_if_fail (iti->_priv->cursor_gc != NULL);

    entry = GTK_ENTRY (iti->_priv->entry);
    cursor_offset = gtk_editable_get_position (GTK_EDITABLE (entry));
    pango_layout_get_cursor_pos (iti->_priv->layout,
                                 g_utf8_offset_to_pointer (entry->text, cursor_offset) - entry->text,
                                 &pos, NULL);
    stem_width = PANGO_PIXELS (pos.height) / 30 + 1;
    for (i = 0; i < stem_width; i++) {
        gdk_draw_line (drawable, iti->_priv->cursor_gc,
                       x + PANGO_PIXELS (pos.x) + i - stem_width / 2,
                       y + PANGO_PIXELS (pos.y),
                       x + PANGO_PIXELS (pos.x) + i - stem_width / 2,
                       y + PANGO_PIXELS (pos.y) + PANGO_PIXELS (pos.height));
    }
}
示例#2
0
文件: editor.c 项目: etrunko/weston
static void
text_entry_get_cursor_rectangle(struct text_entry *entry, struct rectangle *rectangle)
{
	struct rectangle allocation;
	PangoRectangle extents;
	PangoRectangle cursor_pos;

	widget_get_allocation(entry->widget, &allocation);

	if (entry->preedit.text && entry->preedit.cursor < 0) {
		rectangle->x = 0;
		rectangle->y = 0;
		rectangle->width = 0;
		rectangle->height = 0;
		return;
	}


	pango_layout_get_extents(entry->layout, &extents, NULL);
	pango_layout_get_cursor_pos(entry->layout,
				    entry->cursor + entry->preedit.cursor,
				    &cursor_pos, NULL);

	rectangle->x = allocation.x + (allocation.height / 2) + PANGO_PIXELS(cursor_pos.x);
	rectangle->y = allocation.y + 10 + PANGO_PIXELS(cursor_pos.y);
	rectangle->width = PANGO_PIXELS(cursor_pos.width);
	rectangle->height = PANGO_PIXELS(cursor_pos.height);
}
示例#3
0
static VALUE
rg_get_cursor_pos(VALUE self, VALUE index)
{
    PangoRectangle strong_pos, weak_pos;
    pango_layout_get_cursor_pos(_SELF(self), NUM2INT(index), &strong_pos, &weak_pos);
    return rb_ary_new3(2, BOXED2RVAL(&strong_pos, PANGO_TYPE_RECTANGLE),
                       BOXED2RVAL(&weak_pos, PANGO_TYPE_RECTANGLE));
}
static gboolean
draw_text_cursor_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
    GtkEditable *editable = GTK_EDITABLE(widget);
    GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(widget));
    gint height = gtk_widget_get_allocated_height (widget);
    const gchar *text;
    GdkRGBA *fg_color;
    GdkRGBA color;
    gint x_offset;
    gint cursor_x = 0;

    // Get the layout x offset
    gtk_entry_get_layout_offsets (GTK_ENTRY(widget), &x_offset, NULL);

    // Get the foreground color
    gdk_rgba_parse (&color, "black");
    gtk_style_context_get_color (stylectxt, GTK_STATE_FLAG_NORMAL, &color);
    fg_color = &color;

    text = gtk_entry_get_text (GTK_ENTRY (widget));

    if ((text != NULL) && (*text != '\0'))
    {
        PangoLayout *layout;
        PangoRectangle strong_pos;
        gint start_pos, end_pos, cursor_pos, cursor_byte_pos;

        cursor_pos = gtk_editable_get_position (editable);
        cursor_byte_pos = g_utf8_offset_to_pointer (text, cursor_pos) - text;

        gtk_editable_get_selection_bounds (editable, &start_pos, &end_pos);

        layout = gtk_entry_get_layout (GTK_ENTRY(widget));
        pango_layout_get_cursor_pos (layout, cursor_byte_pos, &strong_pos, NULL);
        cursor_x = x_offset + PANGO_PIXELS (strong_pos.x);
    }
    else
        cursor_x = x_offset;

    // Now draw a vertical line
    cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
    cairo_set_line_width (cr, 1.0);
    cairo_move_to (cr, cursor_x + 0.5, 2);
    cairo_rel_line_to (cr, 0, height - 4);
    cairo_stroke (cr);

    return FALSE;
}
示例#5
0
static void tab_completion_popup_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
{
	TabCompData *td = data;
	gint height;
	PangoLayout *layout;
	PangoRectangle strong_pos, weak_pos;
	gint length;
	gint xoffset, yoffset;
	GtkRequisition req;
	GdkScreen *screen;
	gint monitor_num;
	GdkRectangle monitor;
	GtkRequisition requisition;
	GtkAllocation allocation;

	gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(td->entry)), x, y);

	screen = gtk_widget_get_screen(GTK_WIDGET(menu));
	monitor_num = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(GTK_WIDGET(td->entry)));
	gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);

	gtk_widget_size_request(GTK_WIDGET(menu), &req);

	length = strlen(gtk_entry_get_text(GTK_ENTRY(td->entry)));
	gtk_entry_get_layout_offsets(GTK_ENTRY(td->entry), &xoffset, &yoffset);

	layout = gtk_entry_get_layout(GTK_ENTRY(td->entry));
	pango_layout_get_cursor_pos(layout, length, &strong_pos, &weak_pos);

	*x += strong_pos.x / PANGO_SCALE + xoffset;

	gtk_widget_get_requisition(td->entry, &requisition);
	gtk_widget_get_allocation(td->entry, &allocation);

	height = MIN(requisition.height, allocation.height);

	if (req.height > monitor.y + monitor.height - *y - height &&
	    *y - monitor.y >  monitor.y + monitor.height - *y)
		{
		height = MIN(*y - monitor.y, req.height);
		gtk_widget_set_size_request(GTK_WIDGET(menu), -1, height);
		*y -= height;
		}
	else
		{
		*y += height;
		}
}
示例#6
0
gui2::tpoint ttext::get_cursor_position(
		const unsigned column, const unsigned line) const
{
	recalculate();

	// First we need to determine the byte offset, if more routines need it it
	// would be a good idea to make it a separate function.
	titor itor(layout_);

	// Go the wanted line.
	if(line != 0) {
		if(pango_layout_get_line_count(layout_) >= static_cast<int>(line)) {
			return gui2::tpoint(0, 0);
		}

		for(size_t i = 0; i < line; ++i) {
			pango_layout_iter_next_line(itor);
		}
	}

	// Go the wanted column.
	for(size_t i = 0; i < column; ++i) {
		if(!pango_layout_iter_next_char(itor)) {
			// It seems that the documentation is wrong and causes and off by
			// one error... the result should be false if already at the end of
			// the data when started.
			if(i + 1 == column) {
				break;
			}
			// We are beyond data.
			return gui2::tpoint(0, 0);
		}
	}

	// Get the byte offset
	const int offset = pango_layout_iter_get_index(itor);

	// Convert the byte offset in a position.
	PangoRectangle rect;
	pango_layout_get_cursor_pos(layout_, offset, &rect, nullptr);

	return gui2::tpoint(PANGO_PIXELS(rect.x), PANGO_PIXELS(rect.y));
}
示例#7
0
文件: editor.c 项目: etrunko/weston
static void
text_entry_draw_cursor(struct text_entry *entry, cairo_t *cr)
{
	PangoRectangle extents;
	PangoRectangle cursor_pos;

	if (entry->preedit.text && entry->preedit.cursor < 0)
		return;

	pango_layout_get_extents(entry->layout, &extents, NULL);
	pango_layout_get_cursor_pos(entry->layout,
				    entry->cursor + entry->preedit.cursor,
				    &cursor_pos, NULL);

	cairo_set_line_width(cr, 1.0);
	cairo_move_to(cr, PANGO_PIXELS(cursor_pos.x), PANGO_PIXELS(extents.height) + 2);
	cairo_line_to(cr, PANGO_PIXELS(cursor_pos.x), - 2);
	cairo_stroke(cr);
}
示例#8
0
void
gimp_text_tool_editor_get_cursor_rect (GimpTextTool   *text_tool,
                                       gboolean        overwrite,
                                       PangoRectangle *cursor_rect)
{
  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer);
  PangoLayout   *layout;
  gint           offset_x;
  gint           offset_y;
  GtkTextIter    cursor;
  gint           cursor_index;

  g_return_if_fail (GIMP_IS_TEXT_TOOL (text_tool));
  g_return_if_fail (cursor_rect != NULL);

  gtk_text_buffer_get_iter_at_mark (buffer, &cursor,
                                    gtk_text_buffer_get_insert (buffer));
  cursor_index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor,
                                                  TRUE);

  gimp_text_tool_ensure_layout (text_tool);

  layout = gimp_text_layout_get_pango_layout (text_tool->layout);

  gimp_text_layout_get_offsets (text_tool->layout, &offset_x, &offset_y);

  if (overwrite)
    pango_layout_index_to_pos (layout, cursor_index, cursor_rect);
  else
    pango_layout_get_cursor_pos (layout, cursor_index, cursor_rect, NULL);

  gimp_text_layout_transform_rect (text_tool->layout, cursor_rect);

  cursor_rect->x      = PANGO_PIXELS (cursor_rect->x) + offset_x;
  cursor_rect->y      = PANGO_PIXELS (cursor_rect->y) + offset_y;
  cursor_rect->width  = PANGO_PIXELS (cursor_rect->width);
  cursor_rect->height = PANGO_PIXELS (cursor_rect->height);
}
示例#9
0
文件: textbox.c 项目: guyhughes/rofi
static void texbox_update ( textbox *tb )
{
    if ( tb->update ) {
        if ( tb->main_surface ) {
            cairo_destroy ( tb->main_draw );
            cairo_surface_destroy ( tb->main_surface );
            tb->main_draw    = NULL;
            tb->main_surface = NULL;
        }
        tb->main_surface = cairo_image_surface_create ( get_format (), tb->w, tb->h );
        tb->main_draw    = cairo_create ( tb->main_surface );
        PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font );
        pango_font_description_free ( pfd );
        cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_SOURCE );

        pango_cairo_update_layout ( tb->main_draw, tb->layout );
        char *text       = tb->text ? tb->text : "";
        int  text_len    = strlen ( text );
        int  font_height = textbox_get_font_height ( tb );

        int  cursor_x     = 0;
        int  cursor_width = MAX ( 2, font_height / 10 );

        if ( tb->changed ) {
            if ( tb->flags & TB_MARKUP ) {
                pango_layout_set_markup ( tb->layout, text, text_len );
            }
            else{
                pango_layout_set_text ( tb->layout, text, text_len );
            }
        }

        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 = pos.x / PANGO_SCALE;
        }

        // Skip the side MARGIN on the X axis.
        int x = SIDE_MARGIN;
        int y = 0;

        if ( tb->flags & TB_RIGHT ) {
            int line_width = 0;
            // Get actual width.
            pango_layout_get_pixel_size ( tb->layout, &line_width, NULL );
            x = ( tb->w - line_width - SIDE_MARGIN );
        }
        else if ( tb->flags & TB_CENTER ) {
            int tw = textbox_get_font_width ( tb );
            x = (  ( tb->w - tw - 2 * SIDE_MARGIN ) ) / 2;
        }
        short fh = textbox_get_font_height ( tb );
        if ( fh > tb->h ) {
            y = 0;
        }
        else {
            y = (   ( tb->h - fh ) ) / 2;
        }

        // Set ARGB
        Color col = tb->color_bg;
        cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha );
        cairo_paint ( tb->main_draw );

        // Set ARGB
        col = tb->color_fg;
        cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha );
        cairo_move_to ( tb->main_draw, x, y );
        pango_cairo_show_layout ( tb->main_draw, tb->layout );

        //cairo_fill(tb->draw);
        // draw the cursor
        if ( tb->flags & TB_EDITABLE ) {
            cairo_rectangle ( tb->main_draw, x + cursor_x, y, cursor_width, font_height );
            cairo_fill ( tb->main_draw );
        }

        tb->update = FALSE;
    }
}
示例#10
0
static void texbox_update ( textbox *tb )
{
    if ( tb->update ) {
        unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
        if ( tb->main_surface ) {
            cairo_destroy ( tb->main_draw );
            cairo_surface_destroy ( tb->main_surface );
            tb->main_draw    = NULL;
            tb->main_surface = NULL;
        }
        tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
        tb->main_draw    = cairo_create ( tb->main_surface );
        cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );

        pango_cairo_update_layout ( tb->main_draw, tb->layout );
        int font_height = textbox_get_font_height ( tb );

        int cursor_x      = 0;
        int cursor_y      = 0;
        int cursor_width  = 2; //MAX ( 2, font_height / 10 );
        int cursor_height = font_height;

        if ( tb->changed ) {
            __textbox_update_pango_text ( tb );
        }

        if ( tb->flags & TB_EDITABLE ) {
            // We want to place the cursor based on the text shown.
            const char     *text = pango_layout_get_text ( tb->layout );
            // Clamp the position, should not be needed, but we are paranoid.
            int            cursor_offset = MIN ( tb->cursor, g_utf8_strlen ( text, -1 ) );
            PangoRectangle pos;
            // convert to byte location.
            char           *offset = g_utf8_offset_to_pointer ( text, cursor_offset );
            pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL );
            cursor_x      = pos.x / PANGO_SCALE;
            cursor_y      = pos.y / PANGO_SCALE;
            cursor_height = pos.height / PANGO_SCALE;
        }

        // Skip the side MARGIN on the X axis.
        int x = widget_padding_get_left ( WIDGET ( tb ) ) + offset;
        int y = 0;

        if ( tb->flags & TB_RIGHT ) {
            int line_width = 0;
            // Get actual width.
            pango_layout_get_pixel_size ( tb->layout, &line_width, NULL );
            x = ( tb->widget.w - line_width - widget_padding_get_right ( WIDGET ( tb ) ) - offset );
        }
        else if ( tb->flags & TB_CENTER ) {
            int tw = textbox_get_font_width ( tb );
            x = (  ( tb->widget.w - tw - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) ) / 2;
        }
        y = widget_padding_get_top ( WIDGET ( tb ) ) + ( pango_font_metrics_get_ascent ( p_metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE;

        rofi_theme_get_color ( WIDGET ( tb ), "foreground", tb->main_draw );
        // Text
        rofi_theme_get_color ( WIDGET ( tb ), "text", tb->main_draw );
        // draw the cursor
        if ( tb->flags & TB_EDITABLE && tb->blink ) {
            cairo_rectangle ( tb->main_draw, x + cursor_x, y + cursor_y, cursor_width, cursor_height );
            cairo_fill ( tb->main_draw );
        }

        // Set ARGB
        // We need to set over, otherwise subpixel hinting wont work.
        //cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );
        cairo_move_to ( tb->main_draw, x, y );
        pango_cairo_show_layout ( tb->main_draw, tb->layout );

        if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED ) ) ) {
            cairo_arc ( tb->main_draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI );
            cairo_fill ( tb->main_draw );
        }

        tb->update = FALSE;
    }
}