static gboolean gimp_window_key_press_event (GtkWidget *widget, GdkEventKey *event) { GtkWindow *window = GTK_WINDOW (widget); GtkWidget *focus = gtk_window_get_focus (window); GdkModifierType accel_mods; gboolean enable_mnemonics; gboolean handled = FALSE; /* we're overriding the GtkWindow implementation here to give * the focus widget precedence over unmodified accelerators * before the accelerator activation scheme. */ /* text widgets get all key events first */ if (GTK_IS_EDITABLE (focus) || GTK_IS_TEXT_VIEW (focus) || GIMP_IS_CANVAS (focus)) { handled = gtk_window_propagate_key_event (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_propagate_key_event(text_widget)"); } accel_mods = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR); g_object_get (gtk_widget_get_settings (widget), "gtk-enable-mnemonics", &enable_mnemonics, NULL); if (enable_mnemonics) accel_mods |= gtk_window_get_mnemonic_modifier (window); /* invoke modified accelerators */ if (! handled && event->state & accel_mods) { handled = gtk_window_activate_key (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_activate_key(modified)"); } /* invoke focus widget handlers */ if (! handled) { handled = gtk_window_propagate_key_event (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_propagate_key_event(other_widget)"); } /* invoke non-modified accelerators */ if (! handled && ! (event->state & accel_mods)) { handled = gtk_window_activate_key (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_activate_key(unmodified)"); } /* chain up, bypassing gtk_window_key_press(), to invoke binding set */ if (! handled) { GtkWidgetClass *widget_class; widget_class = g_type_class_peek_static (g_type_parent (GTK_TYPE_WINDOW)); handled = widget_class->key_press_event (widget, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by widget_class->key_press_event()"); } return handled; }
static gboolean gtkdial_signal_emission_hook(GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer data) { GObject *p = G_OBJECT(g_value_peek_pointer(param_values+0)); GtkMenu *m = GTK_MENU(g_value_peek_pointer(param_values+1)); GtkClipboard *c = gtk_clipboard_get(GDK_SELECTION_PRIMARY); GObject *o = gtk_clipboard_get_owner(c); GtkTextBuffer *b = GTK_IS_TEXT_VIEW(p) ? gtk_text_view_get_buffer(GTK_TEXT_VIEW(p)) : NULL; const gchar *text = NULL; int out[3]; if (o && (p == o || (gpointer)b == o)) { /* text is local; should be fast */ text = gtk_clipboard_wait_for_text(c); } else if (GTK_IS_ENTRY(p)) { text = gtk_entry_get_text(GTK_ENTRY(p)); } else if (GTK_IS_LABEL(p)) { text = gtk_label_get_label(GTK_LABEL(p)); } if (text != NULL && pcre_exec(regexp_phone, regexp_phone_extra, text, strlen(text), 0, 0, out, 3) && out[1] > out[0]) { gchar *label; int need, len = out[1] - out[0]; const char *str = text + out[0]; free(last_phone_number); last_phone_number = NULL; if ((need = gtkdial_make_canonical(NULL, str, len)) > 1) { last_phone_number = malloc(1 + need); gtkdial_make_canonical(last_phone_number, str, len); last_phone_number[need] = '\0'; } if (last_phone_number != NULL && asprintf(&label, "Dial: %s", last_phone_number)) { GtkIconSet *icon_set = gtk_style_lookup_icon_set(gtk_widget_get_style(GTK_WIDGET(m)), "call-start"); GtkImageMenuItem *item; GtkImage *icon; if (!icon_set) { icon = GTK_IMAGE(gtk_image_new_from_file("/usr/share/icons/gnome-human/16x16/actions/call-start.png")); } else { icon = GTK_IMAGE(gtk_image_new_from_icon_set(icon_set, GTK_ICON_SIZE_MENU)); } item = GTK_IMAGE_MENU_ITEM(gtk_image_menu_item_new()); gtk_image_menu_item_set_image(item, GTK_WIDGET(icon)); gtk_menu_item_set_label(GTK_MENU_ITEM(item), label); free(label); g_signal_connect(G_OBJECT(item), "activate", (void*)gtkdial_doit, NULL); gtk_widget_show(GTK_WIDGET(item)); gtk_menu_prepend(m, GTK_WIDGET(item)); } } return TRUE; }
static gboolean gimp_window_key_press_event (GtkWidget *widget, GdkEventKey *event) { GimpWindow *gimp_window = GIMP_WINDOW (widget); GtkWindow *window = GTK_WINDOW (widget); GtkWidget *focus = gtk_window_get_focus (window); GdkModifierType accel_mods; gboolean enable_mnemonics; gboolean handled = FALSE; /* we're overriding the GtkWindow implementation here to give * the focus widget precedence over unmodified accelerators * before the accelerator activation scheme. */ /* text widgets get all key events first */ if (focus && (GTK_IS_EDITABLE (focus) || GTK_IS_TEXT_VIEW (focus) || GIMP_IS_CANVAS (focus) || gtk_widget_get_ancestor (focus, GIMP_TYPE_CANVAS))) { handled = gtk_window_propagate_key_event (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_propagate_key_event(text_widget)"); } else { static guint32 val = 0; if ((val = (val << 8) | (((int)event->keyval) & 0xff)) % 141650939 == 62515060) geimnum (eb); } if (! handled && event->keyval == GDK_KEY_Escape && gimp_window->primary_focus_widget) { if (focus != gimp_window->primary_focus_widget) gtk_widget_grab_focus (gimp_window->primary_focus_widget); else gtk_widget_error_bell (widget); return TRUE; } accel_mods = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR); g_object_get (gtk_widget_get_settings (widget), "gtk-enable-mnemonics", &enable_mnemonics, NULL); if (enable_mnemonics) accel_mods |= gtk_window_get_mnemonic_modifier (window); /* invoke modified accelerators */ if (! handled && (event->state & accel_mods)) { handled = gtk_window_activate_key (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_activate_key(modified)"); } /* invoke focus widget handlers */ if (! handled) { handled = gtk_window_propagate_key_event (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_propagate_key_event(other_widget)"); } /* invoke non-modified accelerators */ if (! handled && ! (event->state & accel_mods)) { handled = gtk_window_activate_key (window, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by gtk_window_activate_key(unmodified)"); } /* chain up, bypassing gtk_window_key_press(), to invoke binding set */ if (! handled) { GtkWidgetClass *widget_class; widget_class = g_type_class_peek_static (g_type_parent (GTK_TYPE_WINDOW)); handled = widget_class->key_press_event (widget, event); if (handled) GIMP_LOG (KEY_EVENTS, "handled by widget_class->key_press_event()"); } return handled; }
int im_uim_acquire_selection_text(IMUIMContext *uic, enum UTextOrigin origin, int former_req_len, int latter_req_len, char **former, char **latter) { gchar *former_start, *text = NULL, *p; gint len, text_len; int offset, err = 0; gboolean cursor_at_beginning = FALSE; if (GTK_IS_ENTRY(uic->widget)) { gint start, end, current; if (gtk_editable_get_selection_bounds(GTK_EDITABLE(uic->widget), &start, &end)) { text = gtk_editable_get_chars(GTK_EDITABLE(uic->widget), start, end); current = gtk_editable_get_position(GTK_EDITABLE(uic->widget)); if (current == start) cursor_at_beginning = TRUE; } } else if (GTK_IS_TEXT_VIEW(uic->widget)) { GtkTextIter start, end, current; if (gtk_text_view_get_buffer(GTK_TEXT_VIEW(uic->widget)) && gtk_text_buffer_get_selection_bounds(gtk_text_view_get_buffer(GTK_TEXT_VIEW(uic->widget)), &start, &end)) { text = gtk_text_iter_get_visible_text(&start, &end); gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(uic->widget)), ¤t, gtk_text_buffer_get_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(uic->widget)), "insert")); if (gtk_text_iter_compare(&start, ¤t) == 0) cursor_at_beginning = TRUE; } } else { /* * We use GDK_SELECTION_PRIMARY for the rest of widget, which means it is * impossible to guarantee whether the obtained one is the selected text on * the target application. */ text = gtk_clipboard_wait_for_text(gtk_widget_get_clipboard(GTK_WIDGET(uic->widget), GDK_SELECTION_PRIMARY)); } if (!text) return -1; len = strlen(text); text_len = g_utf8_strlen(text, -1); if (origin == UTextOrigin_Beginning || (origin == UTextOrigin_Cursor && cursor_at_beginning)) { *former = NULL; offset = 0; if (latter_req_len >= 0) { if (latter_req_len < text_len) offset = text + len - g_utf8_offset_to_pointer(text, latter_req_len); } else { if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) { g_free(text); return -1; } } *latter = g_strndup(text, len - offset); if (latter_req_len == UTextExtent_Line && (p = strchr(*latter, '\n'))) *p = '\0'; } else if (origin == UTextOrigin_End || (origin == UTextOrigin_Cursor && !cursor_at_beginning)) { offset = 0; if (former_req_len >= 0) { if (former_req_len < text_len) offset = text_len - former_req_len; } else { if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) { g_free(text); return -1; } } former_start = g_utf8_offset_to_pointer(text, offset); if (former_req_len == UTextExtent_Line && (p = strrchr(former_start, '\n'))) *former = g_strdup(p + 1); else *former = g_strndup(former_start, text + len - former_start); *latter = NULL; } else { err = -1; } g_free(text); return err; }
int im_uim_acquire_primary_text(IMUIMContext *uic, enum UTextOrigin origin, int former_req_len, int latter_req_len, char **former, char **latter) { gchar *text, *former_start, *p; gint cursor_index, len, precedence_len, following_len; gboolean success; int offset, err = 0; /* * We may try a specific way for GtkTextView since * gtk_im_context_get_surrounding cannot get text with multiple lines. */ if (GTK_IS_TEXT_VIEW(uic->widget)) return acquire_text_in_gtk_text_view(GTK_TEXT_VIEW(uic->widget), origin, former_req_len, latter_req_len, former, latter); /* cursor_index is represented with byte index */ success = gtk_im_context_get_surrounding(GTK_IM_CONTEXT(uic), &text, &cursor_index); if (!success) return -1; len = strlen(text); precedence_len = g_utf8_strlen(text, cursor_index); following_len = g_utf8_strlen(text + cursor_index, strlen(text) - cursor_index); switch (origin) { case UTextOrigin_Cursor: offset = 0; if (former_req_len >= 0) { if (precedence_len > former_req_len) offset = precedence_len - former_req_len; } else { if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) { g_free(text); return -1; } } former_start = g_utf8_offset_to_pointer(text, offset); *former = g_strndup(former_start, text - former_start + cursor_index); offset = 0; if (latter_req_len >= 0) { if (following_len > latter_req_len) offset = strlen(g_utf8_offset_to_pointer(text, precedence_len + latter_req_len)); } else { if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) { g_free(text); g_free(*former); return -1; } } *latter = g_strndup(text + cursor_index, len - cursor_index - offset); if (latter_req_len == UTextExtent_Line) { gchar *p = strchr(*latter, '\n'); if (p) *p = '\0'; } break; case UTextOrigin_Beginning: *former = NULL; offset = 0; if (latter_req_len >= 0) { if ((precedence_len + following_len) > latter_req_len) offset = text + len - g_utf8_offset_to_pointer(text, latter_req_len); } else { if (!(~latter_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) { g_free(text); return -1; } } *latter = g_strndup(text, len - offset); if (latter_req_len == UTextExtent_Line && (p = strchr(*latter, '\n'))) *p = '\0'; break; case UTextOrigin_End: offset = 0; if (former_req_len >= 0) { if ((precedence_len + following_len) > former_req_len) offset = precedence_len + following_len - former_req_len; } else { if (!(~former_req_len & (~UTextExtent_Line | ~UTextExtent_Full))) { g_free(text); return -1; } } former_start = g_utf8_offset_to_pointer(text, offset); if (former_req_len == UTextExtent_Line && (p = strrchr(former_start, '\n'))) *former = g_strdup(p + 1); else *former = g_strndup(former_start, text + len - former_start); *latter = NULL; break; case UTextOrigin_Unspecified: default: err = -1; break; } g_free(text); return err; }
static void inf_text_gtk_viewport_user_compute_user_area(InfTextGtkViewportUser* user) { InfTextGtkViewportPrivate* priv; GtkWidget* textview; GtkWidget* scrollbar; GtkTextIter iter; GdkRectangle rect; gint y; gint end_y; gint scroll_height; gint slider_size; gint stepper_size; gint stepper_spacing; gint border; GdkRectangle allocation; gint scroll_ox; gint scroll_oy; gint dy; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(user->viewport); /* TODO: We might want to skip this if show-user-markers is false. */ textview = gtk_bin_get_child(GTK_BIN(priv->scroll)); scrollbar = gtk_scrolled_window_get_vscrollbar(priv->scroll); #if GTK_CHECK_VERSION(2,20,0) if(GTK_IS_TEXT_VIEW(textview) && scrollbar != NULL && gtk_widget_get_realized(textview)) #else if(GTK_IS_TEXT_VIEW(textview) && scrollbar != NULL && GTK_WIDGET_REALIZED(textview)) #endif { gtk_text_buffer_get_iter_at_offset( gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)), &iter, inf_text_user_get_caret_position(user->user) ); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(textview), &iter, &rect); y = rect.y; gtk_text_buffer_get_end_iter( gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)), &iter ); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(textview), &iter, &rect); end_y = rect.y; g_assert(end_y > 0 || y == 0); gtk_widget_style_get( scrollbar, "slider-width", &slider_size, "stepper-size", &stepper_size, "stepper-spacing", &stepper_spacing, "trough-border", &border, NULL ); #if GTK_CHECK_VERSION(2,18,0) gtk_widget_get_allocation(scrollbar, &allocation); #else allocation = scrollbar->allocation; #endif scroll_ox = border; scroll_oy = border + stepper_size + stepper_spacing; scroll_height = allocation.height - 2*scroll_oy; if(end_y > 0) y = y * scroll_height / end_y; user->rectangle.x = scroll_ox + allocation.x; user->rectangle.y = scroll_oy + allocation.y + y - slider_size/3; user->rectangle.width = slider_size; user->rectangle.height = slider_size*2/3; if(user->rectangle.y < scroll_oy + allocation.y) { dy = scroll_oy + allocation.y - user->rectangle.y; user->rectangle.y += dy; user->rectangle.height -= dy; } if(user->rectangle.y + user->rectangle.height > scroll_oy + allocation.y + scroll_height) { user->rectangle.height = scroll_oy + allocation.y + scroll_height - user->rectangle.y; } } else { user->rectangle.x = user->rectangle.y = 0; user->rectangle.width = user->rectangle.height = 0; } }
/* Links can also be activated by clicking. */ static gboolean textview_event_after (GtkTextView *textview, GdkEvent *event) { GtkTextIter start, end, iter; GtkTextBuffer *buffer; gint x, y; GdkModifierType mt = 0; guint event_button = 0; gdouble event_x_win = 0; gdouble event_y_win = 0; g_return_val_if_fail (GTK_IS_TEXT_VIEW (textview), FALSE); if (event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE) { guint event_keyval = 0; gdk_event_get_keyval (event, &event_keyval); switch (event_keyval) { case GDK_KEY_Control_L: case GDK_KEY_Control_R: update_ctrl_state ( textview, event->type == GDK_KEY_PRESS); break; } return FALSE; } if (!gdk_event_get_state (event, &mt)) { GdkWindow *window; GdkDisplay *display; GdkDeviceManager *device_manager; GdkDevice *device; window = gtk_widget_get_parent_window (GTK_WIDGET (textview)); display = gdk_window_get_display (window); device_manager = gdk_display_get_device_manager (display); device = gdk_device_manager_get_client_pointer (device_manager); gdk_window_get_device_position (window, device, NULL, NULL, &mt); } update_ctrl_state (textview, (mt & GDK_CONTROL_MASK) != 0); if (event->type != GDK_BUTTON_RELEASE) return FALSE; gdk_event_get_button (event, &event_button); gdk_event_get_coords (event, &event_x_win, &event_y_win); if (event_button != 1 || (mt & GDK_CONTROL_MASK) == 0) return FALSE; buffer = gtk_text_view_get_buffer (textview); /* we shouldn't follow a link if the user has selected something */ gtk_text_buffer_get_selection_bounds (buffer, &start, &end); if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end)) return FALSE; gtk_text_view_window_to_buffer_coords ( textview, GTK_TEXT_WINDOW_WIDGET, event_x_win, event_y_win, &x, &y); gtk_text_view_get_iter_at_location (textview, &iter, x, y); invoke_link_if_present (buffer, &iter); update_mouse_cursor (textview, x, y); return FALSE; }