Gtk事件與信号關系
--分析中相關的源碼包 gtk+2.0-2.12.9 Gtk所提供的工具庫與Gtk應用程式與都是基于事件觸發機制來管理。所有的Gtk應用程式都是基于事件驅動,如果沒有事件發生,應用程式将處于等待狀态,不會執行任何操作,一旦事件發生,将根據不同的事件做出相應的處理。在GTK+中,一個事件就是從X Server傳出來的一個資訊。當一個事件發生時,Gtk程式就會通過發送一個信号來通知應用程式執行相關的操作,即調用指定控件與這一信号進行綁定的回調函數,來完成一次由事件所觸發的行動。 一、通過對源代碼分析,解決了解過程中所産生的問題: 1、Gtk應用程式如何能接收到來至XServer端的事件: 根據以前的分析可知,GDK層所提供的事件循環對XServer端傳過來的事件進行管理,并将其轉化為GDK層的事件,通過對具體源代碼的分析,可以知道Gtk應用程式能接收的事件,便是來自GDK層進行加工過的Gdk事件。 在程式中可以得知,當有事件需要處理時,Gdk層對XServer端的事件以隊列的形式進行管理(_gdk_events_queue),并将X事件通過(gdk_event_translate)轉換為GDK事件,将轉換後的事件放入隊列中,每次從隊列中取出隊首的事件(_gdk_event_unqueue),如果事件不為空,這時程式中的處理是将GDK事件GdkEvent交給了_gdk_event_func函數進行處理,到這我們可以知道,由XServer端産生的事件經過GDK層後将事件由一個函數_gdk_event_func來處理。 進一步分析知道,_gdk_event_func這一函數指針做為一個GDK提供給外部的一個接口,外部程式如果實作這一接口,便可以接收來自GDK層轉換XServer端産生的事件,在對Gtk的分析過程中,該接口是由Gtk來實作(gtk_main_do_event),也就是Gtk程式通過這一函數來處理事件。 當程式在調用gtk_init時對_gdk_event_func進行設定。 2、Gtk應用程式接收到事件後如何對事件進行處理: 在進一步的分析中,Gtk應用程式采用了信号的機制,通過信号的方式,通知Gtk其它的控件做出相應的動作。每一個控件都有自己定義的信号,每一個信号都可以綁定到一個指定的回調函數上。 從gtk_main_do_event函數中,通過調用内部函數(如:gtk_widget_event_internal)将GDK事件關聯到Gtk自身定義的信号上,并将信号發出,綁定這一信号的控件便可以接收到,這樣根據信号的定義執行相應的回調函數。 二、以對GtkButton控件的點選事件(press-release-click)為例,進行分析: 當滑鼠點選在GtkButton上時,系統做出了以下的反應: 由于XServer實時接收着來至輸入裝置的操作,當滑鼠點選後,XServer立即生成一個XEvent結構,裡面描述着所點選的控件,XEvent産生的事件類型等具體資訊,這時将這一事件傳給GDK層,GDK層通過将XEvent事件轉化為GdkEvent,将轉化後的事件交給函數接口(_gdk_event_func)處理,即gtk_main_do_event。經過幾層函數調用的處理,在函數gtk_widget_event中調用gtk_widget_event_internal,将事件轉化成為Gtk中的信号類型,并通過g_signal_emit将GtkButton的信号BUTTON_PRESS_EVENT發送出去。 在gtkwindow.c檔案中,對GtkWidgetClass建立了BUTTON_PRESS_EVENT、BUTTON_RELEASE_EVENT等類型信号,BUTTON_PRESS_EVENT與 函數button_press_event關聯,GtkButton類型繼承了父類GtkWidget的信号,并将函數button_press_event進行重載為gtk_button_button_press。在GtkButton結構中定義自己的信号"PRESSED",關聯函數為gtk_real_button_pressed。 在GtkButton中定義了與單擊按鈕時關聯的信号類型為: PRESSED,RELEASED,CLICKED。 通過分析源碼,信号的流程是在gtk_widget_event_internal函數中所發出的信号由GtkWidget所接收(所有widget的父類,如GtkButton), 再由GtkWidget中對這一信号所關聯的回調函數(gtk_button_button_press),來發出由GtkWidget子類所定義的信号,最終的操作在于GtkWidget子類中信号的定義。即最終信号的發出是gtk_button_pressed調用g_signal_emit将“PRESSED”信号發出,調用回調函數gtk_real_button_pressed修改GtkButton的屬性。 以同樣的方式,處理滑鼠對按鈕的釋放(release)事件,當RELEASED信号發出後,調用與RELEASED信号相關聯的回調函數,根據目前GtkButton的屬性進行判斷如果目前按鈕滿足一定的條件,如目前按鈕是否處于按下(down)狀态等,則由gtk_button_clicked,發出一個"CLICKED"信号,調用與"CLICKED"關聯的回調函數執行click事件的操作。 三、參考資料 http://library.gnome.org/devel/gtk-tutorial/stable/ No.Starch.Press.The.Official.GNOME.2.Developers.Guide.eBook-LiB.pdf |
借花獻佛,我做個總結:
1. 程式初始化時,放個鈎子下去,釣魚
2. 有按鍵後,由Xserver/或者DirectFB Master層傳到GDK層
3. GDK層把X/DFB事件轉換為GDK事件
4. GTK層把GDK事件轉換為Gtk信号,并發出去
5. 然後GObject會調用Gtk信号對應的回調函數,完成對事件的響應
6. 在回調函數裡面,有可能做些界面更新的操作
http://blog.csdn.net/cuijpus/article/details/4420033