NPAPI繪圖和事件處理

https://developer.mozilla.org/en-US/docs/Plugins/Guide/Drawing_and_Event_Handling

本章介紹如何確定插件實例是窗口化還是無窗口化,如何繪製和重繪插件,以及如何處理插件事件。

在確定插件實例在網頁中的顯示方式時,您(以及網頁作者)有很多選項。編寫網頁的內容提供商確定其顯示模式:插件是嵌入式還是顯示在其自己的單獨頁面中。您可以通過定義插件本身的方式來確定插件是窗口化還是無窗口化。

  • 窗口化插件被繪製到網頁上的其本機窗口(或本機窗口的一部分)中。窗口插件是不透明的,將頁面的一部分隱藏在其顯示窗口下方。這種類型的插件決定了它何時自行繪製。
  • 無窗口插件不需要本機窗口。它繪製在一個名爲drawable的目標中,該目標對應於瀏覽器窗口或屏幕外位圖。可以通過多種方式定義drawable,具體取決於平臺。無窗口插件可以是不透明或透明的。無窗口插件僅在響應來自瀏覽器的繪製消息時自行繪製。

有關HTML確定插件顯示模式的方式的信息,請參閱使用HTML顯示插件

注意:在Gecko 1.9 Alpha 7之前的X Window System平臺上不支持無窗口插件(錯誤137189)。

NPWindow結構部分

加載插件時,會將其繪製到目標區域。此目標是窗口插件的本機窗口,或無窗口插件的drawable。NPWindow結構表示任一天然窗口或可拉伸。此結構包含有關座標位置,大小,插件狀態(窗口或無窗口)以及某些特定於平臺的信息的信息。

注意:當插件被繪製到窗口時,插件負責保留狀態信息並確保恢復原始狀態。

對於無窗口插件,瀏覽器使用表示可繪製NPWindow結構調用NPP_SetWindow方法對於窗口化插件,瀏覽器使用表示窗口結構調用方法NPP_SetWindowNPWindow

//The NPWindow Structure


typedef enum {

NPWindowTypeWindow = 1,
NPWindowTypeDrawable

} NPWindowType;


 
typedef struct _NPWindow
{
void*   window;   /* Platform-specific handle      */
uint32  x;        /* Position of top-left corner   */
uint32  y;        /*   relative to a Netscape page */
uint32  width;    /* Maximum window size           */
uint32  height;
NPRect  clipRect; /* Clipping rectangle in port coordinates */

#ifdef XP_UNIX
void *  ws_info;  /* Platform-dependent additional data     */
#endif /* XP_UNIX */
 
NPWindowType  type;   /* Whether this is a window or a drawable */
} NPWindow;

window參數是Windows和Unix上瀏覽器窗口層次結構中本機窗口元素的特定於平臺的句柄。在Mac OS上,window是指向NP_Port的指針

xy字段指定插件相對於頁面的左上角。

widthheight字段指定插件區域的尺寸。插件不應修改這些值。

clipRect字段在座標系中定義插件的剪切矩形,其中原點是可繪製或窗口的左上角。只要drawable發生變化,瀏覽器就會調用NPP_SetWindow對於無窗口插件,插件不可見clipRect0,0,0,0信號。

type字段表示NPWindow目標區域類型:

  • NPWindowTypeWindow:窗口插件。窗口字段包含窗口的特定於平臺的句柄。
  • NPWindowTypeDrawable:無窗口插件。窗口字段包含一個特定於平臺的可繪製句柄,如下所示:
    • Windows:HDC
    • Mac OS:指向NP_Port結構的指針
    • Unix / X11:沒用過。(繪圖信息中提供了drawable。見下文。)

在這兩種情況下,drawable都可以是一個離屏像素圖。

繪圖插件部分

本節介紹在繪製窗口插件和無窗口插件時使用的方法和過程。以下各節介紹了僅適用於其中一種插件類型的進程。

插件使用這些方法來繪製插件和處理事件:

瀏覽器調用的插件方法:

瀏覽器端方法,由插件調用:

打印插件

瀏覽器調用該NPP_Print方法來請求插件實例自行打印。

void NPP_Print(NPP instance, NPPrint *printInfo);

instance參數表示當前插件。

PrintInfo參數確定打印模式。它被設置爲NP_FULL指示整頁插件打印,或者NP_EMBED是否是嵌入式插件,作爲嵌入其中的窗口的一部分打印。

  • 嵌入式插件與瀏覽器共享打印。插件打印它佔用的頁面部分,瀏覽器處理剩餘的打印過程,包括顯示打印對話框,獲取打印機設備上下文,當然還有打印頁面的其餘部分。

嵌入式插件可以將pluginPrintedPrintInfo參數中字段設置爲false(默認值)。這是_NPFullPrint結構的子結構的一個領域NPPrint瀏覽器顯示必要的打印對話框並NPP_Print再次調用這個時候,PrintInfo->mode應該設置爲NP_EMBED

  • 整頁插件可根據需要處理打印對話框和打印過程。在這種情況下,在瀏覽器顯示任何打印對話框之前,NPP_Print調用PrintInfo->mode等於NP_FULL在Mac OS上,整頁打印要求PrintInfo字段包含標準Mac OS THPrint(請參閱參考資料Printing.h)。

當然,NPP_PrintPrintInfo->mode可以NP_EMBED在嵌入實例時調用它。在這種情況下,platformPrint->embedPrint.window包含應該打印插件的窗口。

在MS Windows上,請注意窗口矩形的座標是TWIPS格式。因此,DPtoLP在輸出文本時,需要使用Windows API調用轉換x和y座標

設置窗口

瀏覽器調用該NPP_SetWindow函數來設置插件繪製或返回錯誤代碼的窗口。此窗口對實例的生命週期有效,或直到NPP_SetWindow使用不同的值再次調用。

NPP_SetWindow對給定實例的後續調用通常意味着窗口已調整大小。如果任一窗口或window->window爲null,則插件不得在窗口上執行任何其他圖形操作,並且應釋放任何相關資源。

NPError NPP_SetWindow(NPP instance, NPWindow *window);

instance參數表示當前插件。

window參數是指向插件的繪圖目標的指針。對於無窗口插件,指定的特定於平臺的窗口信息window->window是drawable的特定平臺的句柄。

MS Windows和Unix

對於MS Windows和Unix上的窗口插件,該window->window字段是Netscape窗口層次結構的子窗口的句柄。

蘋果系統

window->window字段指向一個NP_Port結構。

獲取資訊

要從瀏覽器接收信息,插件會調用該NPN_GetValue方法。

NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value);

instance參數表示當前插件。

Unix和MS Windows

查詢的信息在變量參數中返回。此參數僅對Unix和MS Windows平臺有效。對於Unix,值是當前display(NPNVxDisplay)或應用程序的context(NPNVxtAppContext)。對於MS Windows,該值是發生插件繪圖的本機窗口(NPNVnetscapeWindow)。

value參數包含插件的名稱。

您還可以使用它NPN_GetValue來幫助創建無窗口插件的菜單或對話框。

窗口插件部分

瀏覽器爲每個窗口插件提供了自己的本機窗口,通常是瀏覽器窗口本身的子窗口,用於繪製。該插件可完全控制該窗口內的繪圖和事件處理。

在Mac OS上,瀏覽器不爲窗口插件提供本機窗口,因爲Mac OS平臺不支持子窗口。相反,窗口插件在瀏覽器指定的偏移處繪製到與瀏覽器窗口關聯的圖形端口。

在MS Windows和Unix上,瀏覽器爲每個插件實例創建一個子窗口,並向其傳遞一個窗口NPP_SetWindow在Mac OS上,應用程序使用NPP_SetWindow將其圖形端口的矩形部分專用於每個實例。在任何平臺上,瀏覽器都應該小心不要插入插件區域,反之亦然。傳入的數據結構NPP_SetWindow是一個NPWindow對象,它包含實例區域的座標和各種特定於平臺的數據。

通常,瀏覽器NPP_SetWindow在創建實例後調用,以便插件可以立即開始繪製。但是,瀏覽器可以創建NPP_SetWindow從不調用的不可見實例,並且永遠不會創建窗口。當使用object已使用CSS規則隱藏的HTML 元素(請參閱簡介中的插件顯示模式)或使用已設置embedhidden屬性元素調用插件時,會發生這種情況

NPP_SetWindow只要實例的大小或位置發生變化,瀏覽器就應該再次調用,每次都傳遞相同的NPWindow對象,但值不同。

瀏覽器還可以NPP_SetWindow使用窗口的不同值多次調用,包括null。例如,如果用戶從頁面中刪除實例,則瀏覽器應調用NPP_SetWindow窗口值爲null。此值可防止實例進一步繪製,直到將其粘貼回頁面並NPP_SetWindow再次使用新值進行調用。

蘋果系統

在Mac OS上,瀏覽器傳遞NP_Port結構窗口字段中的NPWindow結構。此結構包含指向CGraphPtr插件實例應繪製到的圖形端口(的指針以及此端口左上角的x和y座標。插件可以使用這些座標調用SetOrigin(portx, porty),將其矩形的左上角放在(0,0)處。Mac OS GrafPort結構的clipRgn字段應設置爲端口座標中實例的剪切矩形。

由於插件和瀏覽器共享相同的圖形端口,因此它們共同負責正確管理它。瀏覽器在以兩種方式傳遞插件更新事件之前設置插件的端口:

  • 瀏覽器調用SetOrigin(npport->portx, npport->porty)此方法使實例的左上角座標等於(0,0)。
  • 瀏覽器將端口的剪輯區域設置爲當前可見的插件區域(不滾動頁面,浮動調色板遮擋或隱藏)。

但是,要使插件在任何其他時間繪製,例如,要在鼠標按下事件時突出顯示或在空閒時繪製動畫,它必須保存端口的當前設置,並根據需要設置其繪圖環境,繪製,然後將端口還原到以前的設置。在這種情況下,插件使瀏覽器無需在每次調用插件之前和之後保存和恢復其端口設置。

瀏覽器和插件都可以爲共享端口安裝Drag Manager處理程序。因爲無論光標位於何處,Drag Manager都會調用兩個處理程序,當光標位於實例矩形上時,瀏覽器不會顯示拖動突出顯示。此外,當實例矩形內發生丟棄時,瀏覽器不執行任何操作。然後,插件可以在實例矩形中顯示拖動突出顯示和處理丟棄。

瀏覽器還負責向插件發送針對實例的所有事件,例如當光標位於實例矩形內時單擊鼠標,或者在應用程序打開和關閉時暫停和恢復事件。通過調用將事件發送到插件NPP_HandleEvent有關事件類型的完整列表,請參閱參考條目NPEvent

視窗

在Windows上,瀏覽器註冊一個窗口類,併爲插件實例創建該類的實例。然後,插件可以對窗口進行子類化以接收所需的任何事件。如果插件需要接收週期性時間消息(例如,對於動畫),則應使用計時器或單獨的線程。

Unix的

在Unix上,瀏覽器爲實例創建Motif繪圖區域窗口小部件,並在窗口字段中傳遞窗口小部件的窗口ID NPWindow此外,瀏覽器創建一個NPSetWindowCallbackStruct對象,並將它在ws_info的領域NPWindow與在Windows上一樣,插件可以接收實例的所有事件,在本例中是通過窗口小部件。如果插件需要接收定期時間消息,則應安裝定時器或分叉線程。

窗口插件的事件處理

窗口化插件實例的所有成像和用戶界面事件都根據其本機平臺的窗口系統進行處理。插件API提供了一個本機窗口句柄,實例通過API調用在其中繪製NPP_SetWindowNPP_SetWindow將實例傳遞給NPWindow包含本機窗口句柄對象。

在Windows和Unix上,每個實例在瀏覽器窗口層次結構中接收自己的子窗口,並且映像和事件處理與此窗口相關。Mac OS不支持子窗口。本機窗口在實例和瀏覽器之間共享。實例必須將其繪圖限制爲共享窗口的指定區域,並且必須始終保存當前設置,設置繪圖環境並將共享繪圖環境恢復爲先前的設置。在Mac OS上,事件通過顯式提供給實例NPP_HandleEvent

無窗口插件部分

無窗口插件不需要繪製本機窗口。相反,它會繪製成一個可繪製的(HDC在Windows或CGrafPtrMac OS上),可以在屏幕上或屏幕外。

無窗口插件爲插件編寫器提供了一些重要的設計可能性:

  • 您可以在一個部分中放置一個無窗口插件; 其他部分可以存在於其上方和下方。
  • 您可以創建透明插件。在這種情況下,瀏覽器繪製插件後面的頁面部分。無窗口插件僅繪製不透明的部分。這樣,插件可以在現有背景上繪製不規則形狀的區域,例如圖形或文本。
  • 瀏覽器支持插件的屏幕外繪製。這使得可以操縱插件內容。例如,3D應用程序可以使用插件的內容作爲紋理貼圖。

由於無窗口插件可以分層或繪製到任意drawables,因此瀏覽器(與本機窗口系統相對)負責控制其繪圖和事件處理。

有關控制插件實例的繪製的更多信息,請參閱以下各項:

指定插件是無窗口的

要指定插件是無窗口的,請使用該NPN_SetValue方法。

instance參數表示當前插件。變量參數包含要設置的插件信息。value參數返回插件的名稱。

要指定插件是無窗口的,請使用NPN_SetValuewith NPPVpluginWindowBool作爲variable的值,使用false作爲value的值。該插件通過它進行此調用NPP_New method如果插件沒有進行此調用,則會將其視爲窗口插件。

Mac OS X上的插件始終沒有窗口。

NPError NPP_New(NPMIMEType    pluginType,
                NPP instance, uint16 mode,
                int16 argc,   char *argn[],
                char *argv[], NPSavedData *saved)
{
  ...
  NPError result = NPN_SetValue(instance, NPPVpluginWindowBool, (void*)false);
}

使繪圖區無效

在重繪或刷新部分繪圖區域之前,無窗口插件必須首先使用以下任一瀏覽器方法使區域無效:NPN_InvalidateRectNPN_InvalidateRegion兩種方法都執行相同的操作:

  • 它們在重新繪製或刷新之前使指定的繪圖區域無效。
  • 它們將更新事件或繪製消息傳遞給插件。

瀏覽器以定時的間隔重繪文檔的無效區域和無窗口插件。要強制繪製消息,插件可以NPN_ForceRedraw在調用其中一個invalidate方法後調用。如果插件調用其中一種方法,它會異步接收繪製消息。

void NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);

instance參數表示當前插件。invalidRectinvalidRegion參數表示無效區域,在座標系的原點是在插件頂部左指定。

這兩種方法都會導致該NPP_HandleEvent方法將更新事件或繪製消息傳遞給插件。

#ifdef XP_MAC
 
typedef RgnHandle NPRegion;
 
#elif defined(XP_WIN)
 
typedef HRGN NPRegion;
 
#elif defined(XP_UNIX)
 
typedef Region NPRegion;
 
#else
 
typedef void* NPRegion;
 
#endif /* XP_MAC */
 
void NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);

強制繪製消息

窗口和無窗口插件具有不同的繪圖模型。窗口插件確定何時繪製,而無窗口插件繪製以響應來自瀏覽器的繪製消息。NPN_ForceRedraw()一旦使用NPN_InvalidateRect()使區域無效,插件可以調用同步強制繪製消息NPN_InvalidateRegion()

void NPN_ForceRedraw(NPP instance);//再某些瀏覽器上不支持改消息 by_songgp add

此方法導致插件的同步更新事件或繪製消息。

注意:某些瀏覽器(包括Firefox 4)可能會忽略對其的調用NPN_ForceRedraw()

收到油漆信息

除非接收到繪製消息,否則插件不得繪製到其drawable中。它不需要調用特定於平臺的函數來開始在窗口中繪製。也就是說,插件不會BeginPaint在Windows或BeginUpdateMac OS上調用

視窗

插件會收到一條WM_PAINT消息。lParam參數WM_PAINT保存指向RECT指定更新區域的邊界框的結構的指針但是,有些插件會選擇忽略這個paint rect,而是總是更新整個插件窗口。此外,由於插件和瀏覽器共享相同的HDC,插件必須將當前設置保存在HDC上,設置自己的環境,自行繪製,並將HDC恢復到以前的設置。每當控件返回瀏覽器時,必須在從NPP_HandleEvent調用與繪圖相關的瀏覽器端方法之前或之後返回之前恢復HDC設置

蘋果系統

插件接收更新事件。drawable CGrafPtr端口的剪輯區域設置爲更新區域。與Mac OS上的窗口插件一樣,插件必須首先保存端口的當前設置,根據需要設置繪圖環境,繪製並將端口恢復到先前的設置。這應該在插件從NP_HandleEvent插件調用與繪圖相關的瀏覽器方法之前或之後返回之前發生

的Unix / X11

插件接收GraphicsExpose事件。XGraphicsExposeEvent結構包含Xlib Drawable(它是一個offscreen pixmap),它Display和相對於drawable左上角指定的髒矩形(可選剪輯矩形)。

插件應繪製到NPWindow結構成員中Drawable指定的偏移量,x並在y成員中指定剪輯矩形,並成員中指定指定clipRectVisualColormapws_info

製作插件不透明

如果沒有透明區域,無窗口插件是不透明的。當瀏覽器爲插件生成繪製消息時,它假定插件負責繪製要更新的整個區域。由於瀏覽器不需要在插件後面繪製背景,因此不透明的無窗口插件比透明插件更有效。

默認情況下,無窗口插件是透明的。要使透明插件不透明,請調用NPN_SetValue設置NPPVpluginTransparentBool爲false。插件可以在指定它是無窗口插件後隨時調用此方法。

使插件透明化

如果窗口具有透明區域,則它是透明的。以下是兩個具有透明區域的插件示例:

  • 一個小於封閉objectembed元素指定區域的插件
  • 一個非矩形邊界的插件

瀏覽器負責呈現透明無窗口插件的背景。在爲插件生成繪製消息之前,瀏覽器會確保已將背景繪製到要更新的區域中。然後,插件可以繪製與其不透明區域對應的更新區域的一部分。這可確保插件的透明區域始終有效。

默認情況下,無窗口插件是透明的。如果要使不透明的無窗口插件透明,請調用該NPN_SetValue方法並將NPPVpluginTransparentBool設置爲true。插件可以在指定它是無窗口插件後隨時調用此方法。

創建彈出菜單和對話框

僅限MS Windows和Unix / X11

無窗口插件不會在其自己的本機窗口中繪製。相反,它直接繪製給它的drawable。如果您需要在插件中顯示彈出菜單和模式對話框,則此行爲會出現問題; 插件需要父窗口才能創建這樣的窗口。

要解決此問題,請使用NPN_GetValue以找出插件的繪製位置。使用NPNVnetscapeWindow作爲變量參數的值。

NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value);

instance參數表示當前插件。變量參數包含調用請求的信息,在這種情況下NPNVnetscapeWindow(發生插件繪圖的本機窗口)。

視窗

請求的信息(HWND類型的值)值參數中的NPN_GetValue返回

在許多情況下,插件可能仍然必須創建自己的窗口(瀏覽器窗口的透明子窗口),以充當彈出菜單和模式對話框的所有者窗口。您可以爲此透明子窗口提供自己的WindowProc進程。插件可以使用它來處理WM_COMMAND由於跟蹤彈出菜單或模式對話框而發送給它的消息。

的Unix / X11

NPN_GetValue的value參數必須指向Xlib Window成功返回後,它將包含瀏覽器頂層窗口。使用此選項Window可在對話框上設置WM_TRANSIENT_FOR屬性。

無窗口插件的事件處理

在所有平臺上,特定於平臺的事件都通過該NPP_HandleEvent方法傳遞給無窗口插件插件必須NPP_HandleEvent在處理事件時返回true,否則返回false。Mac OS將這種機制用於窗口插件和無窗口插件; 在此平臺上,NPP_HandleEvent插件是唯一可以從其主機應用程序接收事件的方式。

int16 NPP_HandleEvent(NPP instance, NPEvent *event);

instance參數表示當前插件。有關事件類型的列表,應用程序負責傳遞給插件,請參閱NPEvent結構。

此代碼顯示通過此方法爲每個平臺傳遞的特定數據:

#ifdef XP_MAC
 
typedef EventRecord NPEvent;
 
#elif defined(XP_WIN)
 
typedef struct _NPEvent {
int16    event;
int16    wParam;
int32    lParam;
} NPEvent;
 
#elif defined(XP_UNIX)
 
typedef XEvent NPEvent;
 
#else
 
typedef void NPEvent;
 
#endif /* XP_MAC */
 
int16 NPP_HandleEvent(NPP instance, NPEvent* event);

在Mac OS上,NPP_HandleEvent調用時,正確設置當前端口,使其原點與插件的左上角匹配。插件不需要設置當前端口以進行鼠標座標轉換。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章