在GTK+中實現嵌入式視窗

李先靜發表於2020-04-06

Windows下的托盤(tray)是不是很酷呢?利用這種機制,你可以方便的把自己的應用程式嵌入到工作列裡。大多數時候,應用程式在後臺工作,不會干擾使用者,當使用者想檢視某些資訊時,只點一下這個小圖示就行了。應用程式在響應點選事件時,可以把應用程式提到前臺來,可以彈出一個對話方塊,可以顯示一個選單,或者做其它任何事情,這完全是應用程式自己的事,與工作列一點關係都沒有。

 

Linux下的桌面環境裡,不但有這個功能,而且功能更加強大。Linux下的桌面環境有好幾種,在PC上最為流行的當然是KDEGNOME。它們往往都有一套自己的機制,搞得不同桌面環境下開發的應用程式之間的相容性很差。為了讓這些應用程式之間能夠互相嵌入,當然得有一個標準才行。為此,freedesktop.org組織制定了一個XEBEDDED協議(http://www.freedesktop.org/wiki/Standards_2fxembed_2dspec)

 

只要遵守XEBEDDED協議,用Qt寫的應用程式可以嵌入到GNOME的工作列裡,用GTK+寫的應用程式可以嵌入到KDE的工作列裡。不但如此,在需要的情況下,兩個應用程式之間也可以任意嵌入,而不必關心它們是用哪個庫實現的。

 

雖然說這個協議很簡單,自己要從頭實現一個,未免太麻煩了。為了簡化應用程式開發,GTK+已經封裝一套函式。本文用一個簡單的例項,介紹如何開發這類應用。在此之前,我們先熟悉幾個概念:

 

插座(socket):這裡指宿主視窗,它可以讓其它應用程式,把視窗嵌入到它裡面。如,工作列就是一個插座(socket)

 

插頭(plug): 顧名思義,它就是被嵌入的視窗,可以插入到插座(socket)上。相對工作列而言,應用程式的視窗就是插頭(plug)

 

插頭(plug)/插座(socket)兩者可以在同一個應用中也可以在不同的應用程式中。在同一個應用程式裡,這種做法意義不大,而且可以說是自找麻煩。大多數情況下,它們分別位於不同的程式之中,一個插座(socket)視窗可以容納多個插頭(plug)視窗中,而一個插頭(plug)視窗只能處於一個插座(socket)視窗之中。

 

1.         插座(socket)端應用程式實現:

 

#include <stdlib.h>

#include <gtk/gtk.h>

 

int main( int   argc,

          char *argv[] )

{

    GtkWidget *window;

    GtkWidget *socket;

 

    gtk_init (&argc, &argv);

 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    gtk_widget_set_size_request(window, 80, 40);

 

    socket = gtk_socket_new();

    gtk_widget_show (socket);

    gtk_container_add (GTK_CONTAINER (window), socket);

    gtk_widget_show (window);

 

    g_message("socket_id=%d/n", gtk_socket_get_id(socket));

 

    gtk_main ();

 

    return 0;

}

 

2.         插頭(plug)端應用程式實現:

 

#include <stdlib.h>

#include <gtk/gtk.h>

 

int main( int   argc,

          char *argv[] )

{

    gint socket_id = 0;

    GtkWidget *window;

    GtkWidget *button;

 

    gtk_init (&argc, &argv);

 

    if(argc != 2)

    {

        g_message("usage: %s [socket]/n", argv[0]);

        return -1;

    }

    else

    {

        socket_id = atoi(argv[1]);

    }

 

    window = gtk_plug_new(socket_id);

    button = gtk_button_new ();

    gtk_widget_show (button);

    gtk_container_add (GTK_CONTAINER (window), button);

    gtk_widget_show (window);

 

    gtk_main ();

 

    return 0;

}

 

3.         Makefile

 

CC = gcc

 

CFLAGS = -Wall -Wunused         /

    -DG_DISABLE_DEPRECATED      /

    -DGDK_DISABLE_DEPRECATED    /

    -DGDK_PIXBUF_DISABLE_DEPRECATED /

    -DGTK_DISABLE_DEPRECATED

 

all: plug socket

 

plug: plug.c

    $(CC) plug.c -o plug.exe $(CFLAGS) `pkg-config gtk+-2.0 --cflags --libs`

 

socket: socket.c

    $(CC) socket.c -o socket.exe $(CFLAGS) `pkg-config gtk+-2.0 --cflags --libs`

 

clean:

    rm -f *.o *.exe

   

當然,這裡為了便於理解,程式寫得很簡單,實際的應用程式要比這複雜一些,它們的原理都是一樣的,大家可參考GTK+API手冊。

 

 

相關文章