上一页 下一页

GNOME Desktop

GNOME的桌面中绝大多数应用既是CORBA的Server,同时也有自己的GUI,即它们提供的服务(引出的方法)需要画出图形以供用户访问它们的服务。所以我把GNOME上的应用分成五大类:

对于一般的GNOME Desktop应用来说,好在问题没这么复杂。因为GNOME已经用C语言将大量的CORBA接口包裹了起来,你只需要简单象写GTK+程序一样方便地调用。

举例说明

GNOME Panel

GNOME Panel是方便用户的一个控制桌面环境的接口,panel的功能相当丰富,用户可以通过点击它上面的菜单或图标来启动一个应用,甚至可以在它上面嵌仍诵须一些应用(被称作applet)。我们下面就看一下一个applet是如何写的。

一般的非applet程序

 #include 
 int main(int argc, char **argv)
 {
    /* ... we build the user interface ... */
    gtk_init(&argc, &argv); /* #1 */
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* #2 */
    gtk_window_set_title(GTK_WINDOW(window), PACKAGE);
    /* controls is the name of the container all our widgets are in */
    gtk_container_add(GTK_CONTAINER(window), controls); /* #3 */
    gtk_widget_show(window);

    /* Everything's ready to begin our main loop */
    gtk_main(); /* #4 */
    return 0;
 }

将其改造为一个applet

 #include 
 int main(int argc, char **argv)
 {
    applet_widget_init(PACKAGE, VERSION, argc, argv,
                       NULL, 0, NULL); /* #1 */
    GtkWidget* applet = applet_widget_new(PACKAGE); /* #2 */
    applet_widget_add(APPLET_WIDGET(applet), controls); /* #3 */
    gtk_widget_show(applet);
    applet_widget_gtk_main(); /* #4 */
    return 0;
 }
	

通过下面这个函数为你的applet添加右键菜单:

void applet_widget_register_callback(AppletWidget *applet, char *name, char *menutext, AppletCallbackFunc func, gpointer data);

这样,编译后,在命令行象启动一个普通的GTK应用一样运行它。它会自动出现在你的Panel上,就象普通GTK应用会自动出现在你的GNOME桌面上一样简单。

如果你希望别的程序也可以访问你的applet,就要把它注册到GOAD中。办法是保存一个.gnorba文件,内容可以如下。这个道理我们在前面已经讲过了。

	[my_applet]
	type=exe
	repo_id=IDL:GNOME/Applet:1.0
	description=Example panel applet
	location_info=my_applet

applet的CORBA实现原理

为了实现GNOME Panel,定义了三个标准的IDL接口:: GNOME::Panel, GNOME::PanelSpot 和 GNOME::Applet。前两个是由panel实现的,第三个由applet实现。Panel接口初始化一个PanelSpot接口供Applet调用。

基本思想是:applet生成一个控件需要显示出来,而panel则提供给这个applet一个画这个控件的窗口。另外applet还要通过Panel的接口告诉它自己的右键菜单。

下面是这三个接口的示意IDL:

module GNOME {
  struct Color {
    unsigned short red, green, blue;
  };
  typedef short AppletId;
  typedef short PanelId;

  interface Panel {
    enum OrientType {
      ORIENT_UP,
      ORIENT_DOWN,
      ORIENT_LEFT,
      ORIENT_RIGHT	
    };
    enum BackType {
      BACK_NONE,
      BACK_COLOR,
      BACK_PIXMAP
    };
    union BackInfoType switch(BackType) {
      case BACK_COLOR: Color c;
      case BACK_PIXMAP: string pmap;
    };
    enum SizeType {
      SIZE_TINY,
      SIZE_STANDARD,
      SIZE_LARGE,
      SIZE_HUGE	
    };

    PanelSpot add_applet(in Applet panel_applet,
                         in string goad_id,
                         out string cfgpath,
                         out string globcfgpath,
                         out unsigned long winid);
    
    oneway void quit ();

    readonly attribute boolean in_drag;
  };
  
  interface PanelSpot {
    // gosh !! i removed many things from here !!
    oneway void add_callback (in string callback_name,
    in string stock_item,
    in string menuitem_text);
    oneway void remove_callback (in string callback_name);
  };

  interface Applet {
    // gosh !! i removed many things from here !!
    oneway void do_callback (in string callback_name);
  };

};

applet设计的一个技巧是利用了GTK+的Plug和Socket控件。Socket是生成一个绘图窗口;GTK_WINDOW_XWINDOW(widget)将这个控件转换为一个winid;而Plug又将这个winid转回为一个GTK的控件。工作过程如下:

大家看到了生成一个applet的实际过程,其复杂性实在令人头疼。好在已经全被C包裹了。

上一页 下一页