evince 的程序入口在shell/Main.c中;
- int main (int argc, char *argv[])
-
{
-
GOptionContext *context;
-
GError *error = NULL;
GOptionContext用于处理命令行传递的参数。
命令行参数处理完成后进入
- if (!ev_init ())
-
return 1;
ev_init()函数用于backend相关的处理,evince 支持pdf,xps,odf等等backend;
-
-
#if defined(WITH_SMCLIENT) && defined(GDK_WINDOWING_X11)
-
egg_set_desktop_file (GNOMEDATADIR "/applications/evince.desktop");
-
#else
-
/* Manually set name and icon */
-
g_set_application_name (_("Document Viewer"));
-
gtk_window_set_default_icon_name ("evince");
-
#endif /* WITH_SMCLIENT && GDK_WINDOWING_X11 */
-
-
ev_application_load_session (EV_APP);
-
load_files (file_arguments);
然后调用ev_application_load_session,此函数完成了创建窗体,并且显示文档。EV_APP是一个函数宏,些函数完成了application的创建。
- #define EV_APP (ev_application_get_instance ())
- /**
-
* ev_application_get_instance:
-
*
-
* Checks for #EvApplication instance, if it doesn't exist it does create it.
-
*
-
* Returns: an instance of the #EvApplication data.
-
*/
-
EvApplication *
-
ev_application_get_instance (void)
-
{
-
if (!instance) {
-
instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
-
}
-
-
return instance;
-
}
直接创建了一个Application对象的instance。
ev_application_load_session,顾名,猜测其主要用于加载会话(session).
- /* Session */
-
gboolean ev_application_load_session (EvApplication *application)
-
{
-
GKeyFile *state_file;
-
gchar *uri;
-
-
#ifdef WITH_SMCLIENT
-
if (egg_sm_client_is_resumed (application->smclient)) {
-
state_file = egg_sm_client_get_state_file (application->smclient);
-
if (!state_file)
-
return FALSE;
-
} else
-
#endif /* WITH_SMCLIENT */
-
return FALSE;
-
-
uri = g_key_file_get_string (state_file, "Evince", "uri", NULL);
-
if (!uri)
-
return FALSE;
-
-
ev_application_open_uri_at_dest (application, uri,
-
gdk_screen_get_default (),
-
NULL, 0, NULL,
-
GDK_CURRENT_TIME);
-
g_free (uri);
-
g_key_file_free (state_file);
-
-
return TRUE;
-
}
如果没有#define
WITH_SMCLIENT,即证明没有会话可加载,则函数直接返回为FALSE;如果定义,则检测保存在application中的smclient所
指向的state_file是否存在,不存在,也直接返回;然后根据stat_file获取Evince组的session 的uri.
然后调用
- ev_application_open_uri_at_dest
此函数是真正完成工作的函数。它根据给定的application, uri,绘制窗体,加载文件。在load_file函数中也会对它进行调用。
- void ev_application_open_uri_at_dest (EvApplication *application,
-
const char *uri,
-
GdkScreen *screen,
-
EvLinkDest *dest,
-
EvWindowRunMode mode,
-
const gchar *search_string,
-
guint timestamp)
-
{
-
g_return_if_fail (uri != NULL);
-
-
if (application->uri && strcmp (application->uri, uri) != 0) {
-
/* spawn a new evince process */
-
ev_spawn (uri, screen, dest, mode, search_string, timestamp);
-
return;
-
} else if (!application->uri) {
-
application->uri = g_strdup (uri);
-
}
-
-
#ifdef ENABLE_DBUS
-
/* Register the uri or send Reload to
-
* remote instance if already registered
-
*/
-
ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
-
#else
-
_ev_application_open_uri_at_dest (application, uri, screen, dest, mode, search_string, timestamp);
-
#endif /* ENABLE_DBUS */
-
}
如果application有一个uri,并且跟现在的uri不同则创建一个新的evince进程。如果没有,则把当前的uri赋值给application->uri。
假如未启用dbus,程序则进入:
- _ev_application_open_uri_at_dest (application, uri, screen, dest, mode, search_string, timestamp);
原型如下:
- static void
-
_ev_application_open_uri_at_dest (EvApplication *application,
-
const gchar *uri,
-
GdkScreen *screen,
-
EvLinkDest *dest,
-
EvWindowRunMode mode,
-
const gchar *search_string,
-
guint timestamp)
-
{
-
EvWindow *ev_window;
-
-
ev_window = ev_application_get_empty_window (application, screen);
-
if (!ev_window)
-
ev_window = EV_WINDOW (ev_window_new ());
-
-
ev_application_open_uri_in_window (application, uri, ev_window,
-
screen, dest, mode,
-
search_string,
-
timestamp);
-
}
此函数先找到一个空的窗体,分为两种情况,
1.直接在application结构体中的windows list 中寻找空的窗体。
2.查找不成功,调用ev_window_new 创建一个新的窗体。
窗体创建成功后进入
- ev_application_open_uri_in_window
- static void
-
ev_application_open_uri_in_window (EvApplication *application,
-
const char *uri,
-
EvWindow *ev_window,
-
GdkScreen *screen,
-
EvLinkDest *dest,
-
EvWindowRunMode mode,
-
const gchar *search_string,
-
guint timestamp)
-
{
-
#ifdef GDK_WINDOWING_X11
-
GdkWindow *gdk_window;
-
#endif
-
-
if (screen) {
-
ev_stock_icons_set_screen (screen);
-
gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
-
}
-
-
/* We need to load uri before showing the window, so
-
we can restore window size without flickering */
-
ev_window_open_uri (ev_window, uri, dest, mode, search_string);
-
-
if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
-
gtk_widget_realize (GTK_WIDGET (ev_window));
-
-
#ifdef GDK_WINDOWING_X11
-
gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
-
-
if (timestamp <= 0)
-
timestamp = gdk_x11_get_server_time (gdk_window);
-
gdk_x11_window_set_user_time (gdk_window, timestamp);
-
-
gtk_window_present (GTK_WINDOW (ev_window));
-
#else
-
gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
-
#endif /* GDK_WINDOWING_X11 */
-
}
函数主要做2件事情 :
1、调用ev_window_open_uri
(ev_window
, uri
, dest
, mode
, search_string
)打开文档;
2、调用gtk_window_present(GTK_WINDOW(ev_window))显示。
阅读(1889) | 评论(0) | 转发(0) |