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)); } }
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); }
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; }
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; } }
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)); }
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); }
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); }
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; } }
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; } }