注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

Stardic中屏幕取词原理 (GTK selections用法)  

2011-08-05 14:20:41|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
    startdic星际译王辞典在你屏幕上任意一个地方选中一个单词,他是会自动弹出一个漂浮的翻译框显示单词解释的。下载了startdic的源码来看一下,不像windows平台的屏幕取词都是通过hook textout等几个api来实现。linux平台的这个功能是靠x window的selection功能来实现的。Xwindow框架提供的这个功能,可以让“选中”内容在不同的程序之间进行传递交互(可以自定义发送和接受“选中”通知。),调用xlib里面函数XConvertSelection就可以请求当前被选中的对象,然后xwindow用一种atom来描述不同的选中内容的"类型"。 GTK 构架在XWindow之上,也是支持XWindow的这个功能的。gtk自己的文本输入框等控件都实现了xwindow的这个selection功能,比如你在文本中选中一个单词,它应该是默认会向外部发送这个选中事件的了。
    在GTK上面实现这个功能支持的话,只要调用gtk_selection_convert 请求指定类型的选中内容,然后注册"selection_received"信号的处理程序就可以了,像下面注册GDK_TARGET_STRING 类型后,在信号处理函数里调用gtk_selection_data_get_text 既可以解出选中的文本串。
        
//例子来自Retrieving the selection  http://www.gtk.org/tutorial1.2/gtk_tut-19.html
  原版里有个gtkwidget的不对的问题不能正常工作,根据网上例子修改传递window指针后才能正确接收信号。
     
GTK的Selections 的API可以参考下面这些网站
//http://developer.gnome.org/gtk3/stable/gtk3-Selections.html
//http://developer.gnome.org/gdk3/stable/gdk3-Selections.html
//XConvertSelection().  http://tronche.com/gui/x/xlib/window-information/selection.html
// /usr/include/gtk-2.0/gtk/gtkselection.h




/* example-start selection gettargets.c */

#include <gtk/gtk.h>

/* Signal handler invoked when user clicks on the "Get Targets" button */
void get_targets( GtkWidget *widget,
                  gpointer data )
{
static GdkAtom targets_atom = GDK_NONE;
GtkWidget *window = (GtkWidget *)data;


  /* Get the atom corresponding to the string "TARGETS" */
  if (targets_atom == GDK_NONE)
    targets_atom = gdk_atom_intern ("TARGETS", FALSE);    //这个兼容所有选择

    //startdic 里面尝试了这几种类型, 获取gedit或者firefox中的选中文本使用GDK_TARGET_STRING 就够用了。
    //startdic 里面是搞个定时器,不停的新建window和注册selection_received事件,好像是说有的时候这个事件接收有点问题吧
    
    //targets_atom = gdk_atom_intern("UTF8_STRING",FALSE);
    //targets_atom = gdk_atom_intern("COMPOUND_TEXT",FALSE);
   targets_atom = GDK_TARGET_STRING;
   
   

    /* And request the "TARGETS" target for the primary selection */
    if  (TRUE ==gtk_selection_convert (window, GDK_SELECTION_PRIMARY, targets_atom,
                         GDK_CURRENT_TIME))  {           
              g_print ("set argets and start request ok\n");               
    }  
}

/* Signal handler called when the selections owner returns the data */
void selection_received( GtkWidget        *widget,
                         GtkSelectionData *selection_data,
                         gpointer          data )
{
  GdkAtom *atoms;
  GList *item_list;
  int i;

 gchar *result;
 result = (gchar *)gtk_selection_data_get_text (selection_data);
 
 if (result) {
  g_printf ("选中的文本是:%s\n",result);
    g_free (result);
 } else {
  g_print ("unknown text\n");
 }
 
 return;
 
  /* **** IMPORTANT **** Check to see if retrieval succeeded  */
  if (selection_data->length < 0)
    {
      g_print ("Selection retrieval failed\n");
      return;
    }
  /* Make sure we got the data in the expected form */
  if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
    {
      g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
      return;
    }
 
  /* Print out the atoms we received */
  atoms = (GdkAtom *)selection_data->data;


  item_list = NULL;
  for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
    {
      char *name;
      name = gdk_atom_name (atoms[i]);
      if (name != NULL)
        g_print ("%s\n",name);
      else
        g_print ("(bad atom)\n");
    }


/*打印出来的有

TIMESTAMP
TARGETS
MULTIPLE
UTF8_STRING
COMPOUND_TEXT
TEXT
STRING
text/plain;charset=utf-8
text/plain
*/
  return;
}

int main( int   argc,
          char *argv[] )
{
  GtkWidget *window;
  GtkWidget *button;
 
  gtk_init (&argc, &argv);

  /* Create the toplevel window */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Event Box");
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);

  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  /* Create a button the user can click to get targets */

  button = gtk_button_new_with_label ("Get Targets");
  gtk_container_add (GTK_CONTAINER (window), button);

  gtk_signal_connect (GTK_OBJECT(button), "clicked",
                      G_CALLBACK (get_targets), window);
  gtk_signal_connect (GTK_OBJECT(window), "selection_received",
                      G_CALLBACK (selection_received), NULL);


  gtk_widget_show (button);
  gtk_widget_show (window);
 
  gtk_main ();
 
  return 0;
}
/* example-end */



编译
 gcc test.c  `pkg-config --cflags gtk+-2.0`  `pkg-config --libs gtk+-2.0` `pkg-config --libs gmodule-2.0`

测试一下,在其他程序选中的文本,在这个程序里面都可以收的到信号了。

widebright@:~/桌面$ ./a.out
widebright@:~/桌面$ gcc test.c  `pkg-config --cflags gtk+-2.0`  `pkg-config --libs gtk+-2.0` `pkg-config --libs gmodule-2.0`
widebright@:~/桌面$
widebright@:~/桌面$
widebright@:~/桌面$ ./a.out
set argets and start request ok
unknown text
set argets and start request ok
unknown text
set argets and start request ok
选中的文本是:targets
set argets and start request ok
选中的文本是:GdkAtom targets
set argets and start request ok
选中的文本是:    if  (TRUE ==gtk_selection_convert (window, GDK_SELECTION_PRIMARY, targets_atom,
                         GDK_CURRENT_TIME))  {           
              g_print ("set argets and start request ok\n");
set argets and start request ok
选中的文本是:gtk_main ();
set argets and start request ok
选中的文本是:/* Signal handler called when the selections owner returns the data */
void selection_received( GtkWidget        *widget,
                         GtkSelectionData *selection_data,
                         gpointer          data )
set argets and start request ok
选中的文本是:/* Signal handler called when the selections owner returns the data */
void selection_received( GtkWidget        *widget,
                         GtkSelectionData *selection_data,
                         gpointer          data )
set argets and start request ok
选中的文本是:data
  评论这张
 
阅读(1105)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017