From 5ff761c012fca4cfc925de1511afca90c08d5d74 Mon Sep 17 00:00:00 2001 From: Tommi Komulainen Date: Tue, 25 Aug 2009 17:15:03 +0000 Subject: browser-plugin: implement search Changed the API to be better match for find as you type. Using property access workaround. Example: plugin.findTerms = "hello"; begin searching and highlights all matches in the document plugin.findNext = 42; (workaround) jump to next match plugin.findPrevious = 42; (workaround) jump to previous match --- diff --git a/browser-plugin/plugin.cpp b/browser-plugin/plugin.cpp index 88893c8..541e9d9 100644 --- a/browser-plugin/plugin.cpp +++ b/browser-plugin/plugin.cpp @@ -26,7 +26,9 @@ Plugin::Plugin (NPP instance) : mInstance (instance), mScriptableObject (0), mWindow (0), + mDocument (0), mLoadJob (0), + mFindJob (0), mTitle (0), mHasSelection (false) { @@ -52,6 +54,8 @@ Plugin::Plugin (NPP instance) : mInstance (instance), used only to calculate the minimum and maximux allowed zoom level. */ ev_view_set_screen_dpi (EV_VIEW(mView), 96); + ev_view_find_set_highlight_search (EV_VIEW (mView), TRUE); + gtk_container_add (GTK_CONTAINER(mScrolledWindow), mView); gtk_widget_show (mView); @@ -61,6 +65,7 @@ Plugin::Plugin (NPP instance) : mInstance (instance), Plugin::~Plugin () { ClearLoadJob (); + ClearFindJob (); g_free (mTitle); @@ -98,13 +103,58 @@ Plugin::GetZoom (void) const } void -Plugin::FindNext (const char *text) +Plugin::ClearFindJob () { + if (!mFindJob) + return; + + if (!ev_job_is_finished (mFindJob)) + ev_job_cancel (mFindJob); + + g_signal_handlers_disconnect_by_func (mFindJob, + (gpointer)Plugin::FindJobUpdatedCallback, + reinterpret_cast (this)); + + g_object_unref (mFindJob); + mFindJob = 0; } void -Plugin::FindPrevious (const char *text) +Plugin::Find (const char *text) { + if (!mDocument || !EV_IS_DOCUMENT_FIND (mDocument)) + return; + + ev_view_find_search_changed (EV_VIEW (mView)); + + ClearFindJob (); + + if (text && text[0]) { + EvPageCache *page_cache = ev_page_cache_get (mDocument); + + mFindJob = ev_job_find_new (mDocument, + ev_page_cache_get_current_page (page_cache), + ev_page_cache_get_n_pages (page_cache), + text, /*case_sensitive=*/ FALSE); + g_signal_connect (mFindJob, "updated", + G_CALLBACK (Plugin::FindJobUpdatedCallback), + reinterpret_cast (this)); + ev_job_scheduler_push_job (mFindJob, EV_JOB_PRIORITY_NONE); + } else { + gtk_widget_queue_draw (mView); + } +} + +void +Plugin::FindNext () +{ + ev_view_find_next (EV_VIEW (mView)); +} + +void +Plugin::FindPrevious () +{ + ev_view_find_previous (EV_VIEW (mView)); } void @@ -275,10 +325,13 @@ Plugin::LoadJobFinishedCallback (EvJob *job, gpointer data) Plugin *plugin = reinterpret_cast (data); if (!ev_job_is_failed (job)) { + // let EvView own the document and mDocument have weak ref + plugin->mDocument = EV_JOB (job)->document; + ev_view_set_document (EV_VIEW(plugin->mView), - EV_JOB (job)->document); + plugin->mDocument); - EvDocumentInfo *doc_info = ev_document_get_info (EV_JOB (job)->document); + EvDocumentInfo *doc_info = ev_document_get_info (plugin->mDocument); if (doc_info) { if (doc_info->fields_mask & EV_DOCUMENT_INFO_TITLE) { @@ -290,8 +343,22 @@ Plugin::LoadJobFinishedCallback (EvJob *job, gpointer data) ev_document_info_free (doc_info); } } else { + plugin->mDocument = 0; + plugin->ShowLoadingError (); } plugin->ClearLoadJob (); } + +void +Plugin::FindJobUpdatedCallback (EvJobFind *job, gint page, gpointer data) +{ + Plugin *plugin = reinterpret_cast (data); + + // FIXME: enable/disable find next/prev actions + + ev_view_find_changed (EV_VIEW (plugin->mView), + ev_job_find_get_results (job), + page); +} diff --git a/browser-plugin/plugin.h b/browser-plugin/plugin.h index 7da0aa3..96089ba 100644 --- a/browser-plugin/plugin.h +++ b/browser-plugin/plugin.h @@ -37,8 +37,9 @@ class Plugin { void ZoomOut (); double GetZoom () const; void SetZoom (double); - void FindNext (const char *text); - void FindPrevious (const char *text); + void Find (const char *text); + void FindNext (); + void FindPrevious (); void CopyClipboard (); void ShowLoadingError (); NPObject *GetScriptableNPObject (); @@ -46,6 +47,7 @@ class Plugin { private: void UpdateSizingMode (); void ClearLoadJob (); + void ClearFindJob (); void CallBrowser (const char *function_name); @@ -60,13 +62,18 @@ class Plugin { gpointer data); static void LoadJobFinishedCallback (EvJob *job, gpointer data); + static void FindJobUpdatedCallback (EvJobFind *job, + int page, + gpointer data); NPP mInstance; NPObject *mScriptableObject; GdkNativeWindow mWindow; GtkWidget *mScrolledWindow; GtkWidget *mView; + EvDocument *mDocument; EvJob *mLoadJob; + EvJob *mFindJob; public: char *mTitle; diff --git a/browser-plugin/scriptable.cpp b/browser-plugin/scriptable.cpp index 81caeb0..833d24f 100644 --- a/browser-plugin/scriptable.cpp +++ b/browser-plugin/scriptable.cpp @@ -23,6 +23,10 @@ #include "plugin.h" #include +// FIXME: attempts to call methods are resulting in +// Error: NPMethod called on non-NPObject wrapped JSObject! +#define CAN_CALL_METHODS 0 + void ScriptablePluginObjectBase::Invalidate () { @@ -203,6 +207,7 @@ ScriptablePluginObject::ScriptablePluginObject (NPP npp) : mZoomInID = NPN_GetStringIdentifier ("zoomIn"); mZoomOutID = NPN_GetStringIdentifier ("zoomOut"); + mFindTermsID = NPN_GetStringIdentifier ("findTerms"); mFindPreviousID = NPN_GetStringIdentifier ("findPrevious"); mFindNextID = NPN_GetStringIdentifier ("findNext"); } @@ -210,6 +215,7 @@ ScriptablePluginObject::ScriptablePluginObject (NPP npp) : bool ScriptablePluginObject::HasMethod (NPIdentifier name) { +#if CAN_CALL_METHODS NPIdentifier methods[] = { mZoomInID, mZoomOutID, @@ -222,6 +228,7 @@ ScriptablePluginObject::HasMethod (NPIdentifier name) return true; } } +#endif return false; } @@ -230,6 +237,11 @@ bool ScriptablePluginObject::HasProperty (NPIdentifier name) { NPIdentifier properties[] = { +#if !CAN_CALL_METHODS + mFindTermsID, + mFindNextID, + mFindPreviousID, +#endif mTitleID, mZoomID, mCanCopyID, @@ -325,6 +337,22 @@ ScriptablePluginObject::SetProperty (NPIdentifier name, const NPVariant *value) plugin->CopyClipboard (); return true; +#if !CAN_CALL_METHODS + } else if (name == mFindTermsID) { + if (!NPVARIANT_IS_STRING (*value)) { + NPN_SetException (this, "Invalid type for findTerms, expected a string"); + return false; + } + + plugin->Find (NPVARIANT_TO_STRING (*value).utf8characters); + return true; + } else if (name == mFindNextID) { + plugin->FindNext (); + return true; + } else if (name == mFindPreviousID) { + plugin->FindPrevious (); + return true; +#endif } return false; @@ -358,6 +386,7 @@ ScriptablePluginObject::Invoke (NPIdentifier name, const NPVariant *args, } else if (name == mZoomOutID) { plugin->ZoomOut (); return true; +#if CAN_CALL_METHODS } else if (name == mFindNextID) { if (argCount < 1 || !NPVARIANT_IS_STRING (args[0])) { return false; @@ -370,6 +399,7 @@ ScriptablePluginObject::Invoke (NPIdentifier name, const NPVariant *args, } plugin->FindPrevious(NPVARIANT_TO_STRING (args[0]).utf8characters); return true; +#endif } return false; diff --git a/browser-plugin/scriptable.h b/browser-plugin/scriptable.h index 763ead2..f534149 100644 --- a/browser-plugin/scriptable.h +++ b/browser-plugin/scriptable.h @@ -99,6 +99,7 @@ class ScriptablePluginObject : public ScriptablePluginObjectBase NPIdentifier mZoomInID; NPIdentifier mZoomOutID; + NPIdentifier mFindTermsID; NPIdentifier mFindPreviousID; NPIdentifier mFindNextID; -- cgit v0.9.1