inz

gnome-terminal-uri-launch.patch (raw)

  1. Index: gnome-terminal-3.6.2/src/terminal-screen.c
  2. ===================================================================
  3. --- gnome-terminal-3.6.2.orig/src/terminal-screen.c
  4. +++ gnome-terminal-3.6.2/src/terminal-screen.c
  5. @@ -50,6 +50,7 @@
  6. #include "eggshell.h"
  7.  
  8. #define URL_MATCH_CURSOR (GDK_HAND2)
  9. +static const gchar *hints = "0123456789abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPQRSTUVWXYZ";
  10.  
  11. typedef struct
  12. {
  13. @@ -75,8 +76,16 @@ struct _TerminalScreenPrivate
  14. gboolean user_title; /* title was manually set */
  15. GSList *match_tags;
  16. guint launch_child_source_id;
  17. + GSList *urls;
  18. };
  19.  
  20. +typedef struct {
  21. + gchar *uri;
  22. + gint flavor;
  23. + guint x;
  24. + guint y;
  25. +} HintData;
  26. +
  27. enum
  28. {
  29. PROFILE_SET,
  30. @@ -115,11 +124,15 @@ static void terminal_screen_drag_data_re
  31. GtkSelectionData *selection_data,
  32. guint info,
  33. guint time);
  34. +static gboolean terminal_screen_draw (GtkWidget *widget,
  35. + cairo_t *cr);
  36. static void terminal_screen_system_font_notify_cb (TerminalApp *app,
  37. GParamSpec *pspec,
  38. TerminalScreen *screen);
  39. static void terminal_screen_change_font (TerminalScreen *screen);
  40. static gboolean terminal_screen_popup_menu (GtkWidget *widget);
  41. +static gboolean terminal_screen_key_press (GtkWidget *widget,
  42. + GdkEventKey *event);
  43. static gboolean terminal_screen_button_press (GtkWidget *widget,
  44. GdkEventButton *event);
  45. static void terminal_screen_launch_child_on_idle (TerminalScreen *screen);
  46. @@ -236,6 +249,28 @@ free_tag_data (TagData *tagdata)
  47. g_slice_free (TagData, tagdata);
  48. }
  49.  
  50. +static gint _hint_compare(gconstpointer a,
  51. + gconstpointer b)
  52. +{
  53. + const HintData *ah = a;
  54. + const HintData *bh = b;
  55. +
  56. + if (ah->y != bh->y)
  57. + {
  58. + return bh->y - ah->y;
  59. + }
  60. + return bh->x - ah->x;
  61. +}
  62. +
  63. +static void _hint_free(gpointer data)
  64. +{
  65. + const HintData *h = data;
  66. +
  67. + g_free (h->uri);
  68. + g_free (data);
  69. +}
  70. +
  71. +
  72. static void
  73. terminal_screen_class_enable_menu_bar_accel_notify_cb (TerminalApp *app,
  74. GParamSpec *pspec,
  75. @@ -525,7 +560,9 @@ terminal_screen_class_init (TerminalScre
  76. #endif
  77. widget_class->drag_data_received = terminal_screen_drag_data_received;
  78. widget_class->button_press_event = terminal_screen_button_press;
  79. + widget_class->key_press_event = terminal_screen_key_press;
  80. widget_class->popup_menu = terminal_screen_popup_menu;
  81. + widget_class->draw = terminal_screen_draw;
  82.  
  83. terminal_class->child_exited = terminal_screen_child_exited;
  84.  
  85. @@ -1600,10 +1637,52 @@ terminal_screen_popup_menu (GtkWidget *w
  86. }
  87.  
  88. static gboolean
  89. +terminal_screen_key_press (GtkWidget *widget,
  90. + GdkEventKey *event)
  91. +{
  92. + TerminalScreen *screen = TERMINAL_SCREEN (widget);
  93. + TerminalScreenPrivate *priv = screen->priv;
  94. +
  95. + if (priv->urls)
  96. + {
  97. + const gchar *i;
  98. + if (event->length == 1 && (i = strchr (hints, event->string[0])))
  99. + {
  100. + gboolean handled = FALSE;
  101. + char *matched_string;
  102. + int matched_flavor = 0;
  103. + HintData *h = g_slist_nth_data (priv->urls, i - hints);
  104. +
  105. + if (!h)
  106. + {
  107. + return TRUE;
  108. + }
  109. + g_signal_emit (screen, signals[MATCH_CLICKED], 0,
  110. + h->uri,
  111. + h->flavor,
  112. + 0,
  113. + &handled);
  114. + }
  115. + else if (event->keyval != GDK_KEY_Escape)
  116. + {
  117. + return TRUE;
  118. + }
  119. + g_slist_free_full (priv->urls, _hint_free);
  120. + priv->urls = NULL;
  121. + gtk_widget_queue_draw (widget);
  122. +
  123. + return TRUE;
  124. + }
  125. +
  126. + return GTK_WIDGET_CLASS (terminal_screen_parent_class)->key_press_event (widget, event);
  127. +}
  128. +
  129. +static gboolean
  130. terminal_screen_button_press (GtkWidget *widget,
  131. GdkEventButton *event)
  132. {
  133. TerminalScreen *screen = TERMINAL_SCREEN (widget);
  134. + TerminalScreenPrivate *priv = screen->priv;
  135. gboolean (* button_press_event) (GtkWidget*, GdkEventButton*) =
  136. GTK_WIDGET_CLASS (terminal_screen_parent_class)->button_press_event;
  137. int char_width, char_height, row, col;
  138. @@ -1612,6 +1691,13 @@ terminal_screen_button_press (GtkWidget
  139. guint state;
  140. GtkBorder *inner_border = NULL;
  141.  
  142. + if (priv->urls)
  143. + {
  144. + g_object_unref (priv->urls);
  145. + priv->urls = NULL;
  146. + gtk_widget_queue_draw (widget);
  147. + }
  148. +
  149. state = event->state & gtk_accelerator_get_default_mod_mask ();
  150.  
  151. terminal_screen_get_cell_size (screen, &char_width, &char_height);
  152. @@ -2329,3 +2415,122 @@ terminal_screen_has_foreground_process (
  153. return TRUE;
  154. #endif
  155. }
  156. +
  157. +void
  158. +terminal_screen_uri_launch (TerminalScreen *screen)
  159. +{
  160. + TerminalScreenPrivate *priv = screen->priv;
  161. + GArray *attrs = g_array_new (FALSE, TRUE, sizeof (VteCharAttributes));
  162. +
  163. + guint i = 0;
  164. +
  165. + gchar *tmp = vte_terminal_get_text (VTE_TERMINAL (screen),
  166. + NULL, NULL, attrs);
  167. + long r0 = g_array_index (attrs, VteCharAttributes, 0).row;
  168. +
  169. + for (i = 0; i < n_url_regexes; ++i)
  170. + {
  171. + GMatchInfo *match = NULL;
  172. + g_regex_match (url_regexes[i],
  173. + tmp,
  174. + 0,
  175. + &match);
  176. + while (g_match_info_matches (match))
  177. + {
  178. + gint s, e;
  179. + HintData *hint = g_new0 (HintData, 1);
  180. + VteCharAttributes *attr;
  181. +
  182. + g_match_info_fetch_pos (match, 0, &s, &e);
  183. + attr = &g_array_index (attrs, VteCharAttributes, s);
  184. +
  185. + hint->uri = g_match_info_fetch (match, 0);
  186. + hint->x = attr->column;
  187. + hint->y = attr->row - r0;
  188. + hint->flavor = url_regex_patterns[i].flavor;
  189. +
  190. + priv->urls = g_slist_insert_sorted (priv->urls,
  191. + hint,
  192. + _hint_compare);
  193. +
  194. + g_match_info_next (match, NULL);
  195. + }
  196. + g_match_info_free (match);
  197. + }
  198. +
  199. + if (priv->urls)
  200. + {
  201. + gtk_widget_queue_draw (GTK_WIDGET (screen));
  202. + }
  203. +
  204. + g_free (tmp);
  205. + g_array_free (attrs, TRUE);
  206. +}
  207. +
  208. +static gboolean
  209. +terminal_screen_draw (GtkWidget* widget,
  210. + cairo_t* cr)
  211. +{
  212. + TerminalScreen *screen = TERMINAL_SCREEN (widget);
  213. + TerminalScreenPrivate *priv = screen->priv;
  214. +
  215. + GTK_WIDGET_CLASS (terminal_screen_parent_class)->draw (widget, cr);
  216. +
  217. + if (priv->urls)
  218. + {
  219. + GSList *iter;
  220. +
  221. + GtkWidgetPath *path = gtk_widget_path_new ();
  222. + GtkStyleContext *context = gtk_style_context_new ();
  223. + int char_width, char_height;
  224. + GtkBorder *inner_border;
  225. + guint i = 0;
  226. +
  227. + gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
  228. +
  229. + gtk_style_context_set_path (context, path);
  230. + gtk_widget_path_unref (path);
  231. +
  232. + gtk_style_context_set_screen (context, gtk_widget_get_screen (widget));
  233. + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOOLTIP);
  234. +
  235. + terminal_screen_get_cell_size (screen, &char_width, &char_height);
  236. +
  237. + gtk_widget_style_get (widget, "inner-border", &inner_border, NULL);
  238. +
  239. + for (iter = priv->urls; iter != NULL && hints[i] != '\0'; iter = g_slist_next (iter))
  240. + {
  241. + HintData *h = iter->data;
  242. + gint x, y;
  243. + PangoLayout *layout;
  244. + gchar hint[2] = " ";
  245. + hint[0] = hints[i++];
  246. +
  247. + x = h->x;
  248. + y = h->y;
  249. +
  250. + layout = gtk_widget_create_pango_layout (widget, hint);
  251. + pango_layout_set_font_description (layout,
  252. + vte_terminal_get_font (VTE_TERMINAL (widget)));
  253. +
  254. + gtk_render_background (context, cr,
  255. + (inner_border ? inner_border->left : 0) + x * char_width - 6,
  256. + (inner_border ? inner_border->top : 0) + y * char_height - 6,
  257. + char_width + 12, char_height + 12);
  258. + gtk_render_frame (context, cr,
  259. + (inner_border ? inner_border->left : 0) + x * char_width - 6,
  260. + (inner_border ? inner_border->top : 0) + y * char_height - 6,
  261. + char_width + 12, char_height + 12);
  262. +
  263. + gtk_render_layout (context, cr,
  264. + (inner_border ? inner_border->left : 0) + x * char_width,
  265. + (inner_border ? inner_border->top : 0) + y * char_height,
  266. + layout);
  267. + g_object_unref (layout);
  268. + }
  269. +
  270. + g_object_unref (context);
  271. + }
  272. +
  273. + return FALSE;
  274. +}
  275. Index: gnome-terminal-3.6.2/src/terminal-screen.h
  276. ===================================================================
  277. --- gnome-terminal-3.6.2.orig/src/terminal-screen.h
  278. +++ gnome-terminal-3.6.2/src/terminal-screen.h
  279. @@ -155,6 +155,8 @@ TerminalScreenPopupInfo *terminal_screen
  280.  
  281. void terminal_screen_popup_info_unref (TerminalScreenPopupInfo *info);
  282.  
  283. +void terminal_screen_uri_launch (TerminalScreen *screen);
  284. +
  285. G_END_DECLS
  286.  
  287. #endif /* TERMINAL_SCREEN_H */
  288. Index: gnome-terminal-3.6.2/src/terminal-window.c
  289. ===================================================================
  290. --- gnome-terminal-3.6.2.orig/src/terminal-window.c
  291. +++ gnome-terminal-3.6.2/src/terminal-window.c
  292. @@ -204,6 +204,8 @@ static void search_find_prev_callback
  293. TerminalWindow *window);
  294. static void search_clear_highlight_callback (GtkAction *action,
  295. TerminalWindow *window);
  296. +static void search_launch_urls_callback (GtkAction *action,
  297. + TerminalWindow *window);
  298. static void terminal_set_title_callback (GtkAction *action,
  299. TerminalWindow *window);
  300. static void terminal_add_encoding_callback (GtkAction *action,
  301. @@ -1885,6 +1887,9 @@ terminal_window_init (TerminalWindow *wi
  302. { "SearchClearHighlight", NULL, N_("_Clear Highlight"), "<shift><control>J",
  303. NULL,
  304. G_CALLBACK (search_clear_highlight_callback) },
  305. + { "SearchLaunchUrls", NULL, N_("_Launch URL"), "<shift><control>L",
  306. + NULL,
  307. + G_CALLBACK (search_launch_urls_callback) },
  308. #if 0
  309. { "SearchGoToLine", GTK_STOCK_JUMP_TO, N_("Go to _Line..."), "<shift><control>I",
  310. NULL,
  311. @@ -3822,6 +3827,19 @@ search_clear_highlight_callback (GtkActi
  312. }
  313.  
  314. static void
  315. +search_launch_urls_callback (GtkAction *action,
  316. + TerminalWindow *window)
  317. +{
  318. + GtkTreeModel *urls;
  319. + GtkTreeIter iter;
  320. +
  321. + if (G_UNLIKELY (!window->priv->active_screen))
  322. + return;
  323. +
  324. + terminal_screen_uri_launch (window->priv->active_screen);
  325. +}
  326. +
  327. +static void
  328. terminal_set_title_dialog_response_cb (GtkWidget *dialog,
  329. int response,
  330. TerminalScreen *screen)
  331. Index: gnome-terminal-3.6.2/src/terminal.xml
  332. ===================================================================
  333. --- gnome-terminal-3.6.2.orig/src/terminal.xml
  334. +++ gnome-terminal-3.6.2/src/terminal.xml
  335. @@ -35,6 +35,7 @@
  336. <menuitem action="SearchFind"/>
  337. <menuitem action="SearchFindNext"/>
  338. <menuitem action="SearchFindPrevious"/>
  339. + <menuitem action="SearchLaunchUrls"/>
  340. <!--
  341. <menuitem action="SearchIncrementalSearch"/>
  342. -->
  343.