編寫你的應用程序(十)、視圖更改、焦點、輸入事件

原文連接:https://developer.chrome.com/native-client/devguide/coding/view-focus-input-events html

注意:已針對ChromeOS之外的平臺公佈了此處所述技術的棄用。
請訪問咱們的 遷移指南 瞭解詳情。
chrome


視圖更改,焦點和輸入事件

本節介紹Native Client模塊的視圖更改,焦點和輸入事件處理。本節假定您熟悉技術概述中提供的材料。編程

本節中使用了兩個示例來講明基本編程技術。該input_events示例用於說明您的模塊如何對鍵盤和鼠標輸入事件作出反應。該mouse_lock示例用於說明您的模塊如何響應以查看更改事件。您能夠在Native Client SDK 中的/pepper_<version>/examples/api/input_event/pepper_<version>/examples/api/mouse_lock目錄中找到這些示例 。還有ppapi_simple庫可用於實現大部分鍋爐板。該pi_generator示例 /pepper_<version>/examples/demo/pi_generator使用ppapi_simple來管理視圖更改事件和2D圖形。api

概觀

當用戶使用鍵盤,鼠標或其餘輸入設備與網頁交互時,瀏覽器會生成輸入事件。在傳統的Web應用程序中,這些輸入事件一般經過事件偵聽器和事件處理程序傳遞給JavaScript並在JavaScript中處理。在Native Client應用程序中,用戶與模塊實例的交互(例如,在模塊管理的矩形內部單擊)也會生成輸入事件,這些事件將傳遞給模塊。瀏覽器還將影響模塊實例的視圖更改和焦點事件傳遞給模塊。Native Client模塊能夠覆蓋pp :: Instance類中的某些函數來處理輸入和瀏覽器事件。這些功能列於下表中:瀏覽器

功能 使用

DidChangeView網絡

在瀏覽器中模塊實例的位置,大小或剪切矩形發生更改時調用。調整瀏覽器窗口大小或滾動鼠標滾輪時也會發生此事件。ide

此函數的實現可能會檢查模塊實例的矩形的大小是否已更改,並在收到不一樣大小時從新分配graphcs上下文。

DidChangeFocus函數

當模塊在瀏覽器中的實例進入或失焦時調用(一般經過單擊模塊實例的內部或外部)。擁有焦點意味着鍵盤事件將被髮送到模塊實例。實例的默認條件是它沒有焦點。動畫

此函數的實現可能會啓動或中止動畫或閃爍的光標。

HandleDocumentLoadui

pp::Instance::Init()對於基於DOMWindow導航的MIME類型實例化的全幀模塊實例。這種狀況僅適用於預先註冊以處理某些MIME類型的模塊。若是您沒有專門註冊處理MIME類型或不是確定的,這適用於您,您的此函數的實現只能返回false。

只有在您編寫擴展程序以加強Chrome網絡瀏覽器的功能時,此API才適用。例如,PDF查看器可能會實現此功能如下載和顯示PDF文件。

HandleInputEvent

當用戶使用輸入設備(如鼠標或鍵盤)與瀏覽器中的模塊實例進行交互時調用。 在重寫此功能以前,必須註冊模塊以接受RequestInputEvents() 用於鼠標事件和RequestFilteringInputEvents()鍵盤事件的輸入事件。

此函數的實現檢查輸入事件類型並相應地分支。

這些接口位於pp :: Instance類中。如下部分提供瞭如何處理這些事件的示例。

處理瀏覽器事件

DidChangeView()

在該mouse_lock示例中,DidChangeView()檢查實例的矩形的先前大小與新大小。它還會比較其餘狀態,例如應用程序是否以全屏模式運行。若是狀態實際上沒有變化,則不須要採起任何措施。可是,若是視圖或其餘狀態的大小已更改,則會釋放舊的圖形上下文並分配新的圖形上下文。

void MouseLockInstance::DidChangeView(const pp::View& view) {
  // DidChangeView can get called for many reasons, so we only want to
  // rebuild the device context if we really need to.
  if ((size_ == view.GetRect().size()) &&
      (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) {
    return;
  }

  // ...

  // Reallocate the graphics context.
  size_ = view.GetRect().size();
  device_context_ = pp::Graphics2D(this, size_, false);
  waiting_for_flush_completion_ = false;

  is_context_bound_ = BindGraphics(device_context_);
  // ...

  // Remember if we are fullscreen or not
  was_fullscreen_ = view.IsFullscreen();
  // ...
}

有關圖形上下文以及如何操做圖像的更多信息,請參閱:

DidChangeFocus()

DidChangeFocus()單擊網頁中模塊實例的內部或外部時調用。當實例失焦時(單擊實例外部),您可能會執行諸如中止動畫之類的操做。當實例從新得到焦點時,您能夠從新啓動動畫。

void DidChangeFocus(bool focus) {
  // Do something like stopping animation or a blinking cursor in
  // the instance.
}

處理輸入事件

輸入事件是當用戶使用鼠標,鍵盤或其餘輸入設備(例如,觸摸屏)與模塊實例交互時發生的事件。本節介紹input_events 示例如何處理輸入事件。

註冊模塊以接受輸入事件

在模塊處理這些事件以前,必須註冊模塊以接受RequestInputEvents()用於鼠標事件和RequestFilteringInputEvents()鍵盤事件的輸入事件。對於 input_events例如,這是在的構造函數中完成InputEventInstance等級:

class InputEventInstance : public pp::Instance {
 public:
  explicit InputEventInstance(PP_Instance instance)
      : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) {
    RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL |
                       PP_INPUTEVENT_CLASS_TOUCH);
    RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
  }
  // ...
};

RequestInputEvents()RequestFilteringInputEvents()接受標識的組合,這些標誌標識實例請求接收的事件類。輸入事件類在ppb_input_event.h中的 PP_InputEvent_Class 枚舉中定義

肯定和分支事件類型

在典型的實現中,該HandleInputEvent()函數使用類中的函數肯定每一個事件GetType()InputEvent 類型。HandleInputEvent()而後,該函數使用switch語句來分支輸入事件的類型。輸入事件在ppb_input_event.h中的PP_InputEvent_Type 枚舉中定義

virtual bool HandleInputEvent(const pp::InputEvent& event) {
  Event* event_ptr = NULL;
  switch (event.GetType()) {
    case PP_INPUTEVENT_TYPE_UNDEFINED:
      break;
    case PP_INPUTEVENT_TYPE_MOUSEDOWN:
    case PP_INPUTEVENT_TYPE_MOUSEUP:
    case PP_INPUTEVENT_TYPE_MOUSEMOVE:
    case PP_INPUTEVENT_TYPE_MOUSEENTER:
    case PP_INPUTEVENT_TYPE_MOUSELEAVE:
    case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
      pp::MouseInputEvent mouse_event(event);
      PP_InputEvent_MouseButton pp_button = mouse_event.GetButton();
      MouseEvent::MouseButton mouse_button = MouseEvent::kNone;
      switch (pp_button) {
        case PP_INPUTEVENT_MOUSEBUTTON_NONE:
          mouse_button = MouseEvent::kNone;
          break;
        case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
          mouse_button = MouseEvent::kLeft;
          break;
        case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
          mouse_button = MouseEvent::kMiddle;
          break;
        case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
          mouse_button = MouseEvent::kRight;
          break;
      }
      event_ptr =
          new MouseEvent(ConvertEventModifier(mouse_event.GetModifiers()),
                         mouse_button,
                         mouse_event.GetPosition().x(),
                         mouse_event.GetPosition().y(),
                         mouse_event.GetClickCount(),
                         mouse_event.GetTimeStamp(),
                         event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU);
    } break;
    case PP_INPUTEVENT_TYPE_WHEEL: {
      pp::WheelInputEvent wheel_event(event);
      event_ptr =
          new WheelEvent(ConvertEventModifier(wheel_event.GetModifiers()),
                         wheel_event.GetDelta().x(),
                         wheel_event.GetDelta().y(),
                         wheel_event.GetTicks().x(),
                         wheel_event.GetTicks().y(),
                         wheel_event.GetScrollByPage(),
                         wheel_event.GetTimeStamp());
    } break;
    case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
    case PP_INPUTEVENT_TYPE_KEYDOWN:
    case PP_INPUTEVENT_TYPE_KEYUP:
    case PP_INPUTEVENT_TYPE_CHAR: {
      pp::KeyboardInputEvent key_event(event);
      event_ptr = new KeyEvent(ConvertEventModifier(key_event.GetModifiers()),
                               key_event.GetKeyCode(),
                               key_event.GetTimeStamp(),
                               key_event.GetCharacterText().DebugString());
    } break;
    default: {
      // For any unhandled events, send a message to the browser
      // so that the user is aware of these and can investigate.
      std::stringstream oss;
      oss << "Default (unhandled) event, type=" << event.GetType();
      PostMessage(oss.str());
    } break;
  }
  event_queue_.Push(event_ptr);
  return true;
}

請注意,在肯定事件類型後,將InputEvent收到的通用HandleInputEvent()轉換爲特定類型。在示例代碼處理的事件類型是 MouseInputEventWheelInputEvent,和KeyboardInputEvent,還有TouchInputEvents。有關事件類型的最新列表,請參閱InputEvent文檔。有關這些事件類的參考信息,請參閱如下文檔:

線程和阻塞

HandleInputEvent()在此示例中,在主模塊線程上運行。可是,大部分工做都發生在一個單獨的工做線程上(請參閱參考資料 ProcessEventOnWorkerThread)。HandleInputEvent()將事件放入event_queue_而且工做線程從中獲取事件 event_queue_。此處理獨立於主線程發生,以避免減慢瀏覽器的速度。

CC-By 3.0許可下提供的內容

相關文章
相關標籤/搜索