15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/child/npapi/webplugin_delegate_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdkx.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h"
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/child/npapi/plugin_instance.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/child/npapi/webplugin.h"
164311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "content/public/common/content_constants.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_canvas.h"
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebInputEvent.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_compat.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/blit.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/common/cursors/webcursor.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/npapi/bindings/npapi_x11.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebKeyboardEvent;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebInputEvent;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebMouseEvent;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace content {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebPluginDelegateImpl::WebPluginDelegateImpl(
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PluginInstance* instance)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : windowed_handle_(0),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowed_did_set_window_(false),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowless_(false),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      plugin_(NULL),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_(instance),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowless_shm_pixmap_(None),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pixmap_(NULL),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_event_time_(-1.0),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      plug_(NULL),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket_(NULL),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      quirks_(0),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle_event_depth_(0),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_set_window_call_(true),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      plugin_has_focus_(false),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_webkit_focus_(false),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      containing_view_has_focus_(true),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      creation_succeeded_(false) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&window_, 0, sizeof(window_));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance_->mime_type() == kFlashPluginSwfMimeType) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Flash is tied to Firefox's whacky behavior with windowless plugins. See
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // comments in WindowlessPaint.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(viettrungluu): PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK: Don't allow
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // right-clicks in windowless content since Flash 10.1 (initial release, at
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // least) hangs in that case. Remove this once Flash is fixed.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quirks_ |= PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        | PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        | PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(evanm): I played with this for quite a while but couldn't
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // figure out a way to make Flash not crash unless I didn't call
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPP_SetWindow.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, after piman's grand refactor of windowed plugins, maybe
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is no longer necessary.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebPluginDelegateImpl::~WebPluginDelegateImpl() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DestroyInstance();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!windowless_)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WindowedDestroyWindow();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_.ws_info) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only ever use ws_info as an NPSetWindowCallbackStruct.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete static_cast<NPSetWindowCallbackStruct*>(window_.ws_info);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pixmap_) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_object_unref(pixmap_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pixmap_ = NULL;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebPluginDelegateImpl::PlatformInitialize() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::PluginWindowHandle handle =
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowless_ ? 0 : gtk_plug_get_id(GTK_PLUG(plug_));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugin_->SetWindow(handle);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::PlatformDestroyInstance() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing to do here.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::Paint(WebKit::WebCanvas* canvas,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const gfx::Rect& rect) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!windowless_ || !skia::SupportsPlatformPaint(canvas))
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  skia::ScopedPlatformPaint scoped_platform_paint(canvas);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_t* context = scoped_platform_paint.GetPlatformSurface();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowlessPaint(context, rect);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebPluginDelegateImpl::WindowedCreatePlugin() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!windowed_handle_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!plug_);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPP_GetValue() might write 4 bytes of data to this variable.  Don't use a
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // single byte bool, use an int instead and make sure it is initialized.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int xembed = 0;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPError err = instance_->NPP_GetValue(NPPVpluginNeedsXEmbed, &xembed);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != NPERR_NO_ERROR || !xembed) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTIMPLEMENTED() << " windowed plugin but without xembed. "
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "See http://code.google.com/p/chromium/issues/detail?id=38229";
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Passing 0 as the socket XID creates a plug without plugging it in a socket
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // yet, so that it can be latter added with gtk_socket_add_id().
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plug_ = gtk_plug_new(0);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_widget_show(plug_);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_ = gtk_socket_new();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_widget_show(socket_);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_container_add(GTK_CONTAINER(plug_), socket_);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_widget_show_all(plug_);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent the plug from being destroyed if the browser kills the container
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_signal_connect(plug_, "delete-event", G_CALLBACK(gtk_true), NULL);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent the socket from being destroyed when the plugin removes itself.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_signal_connect(socket_, "plug_removed", G_CALLBACK(gtk_true), NULL);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowed_handle_ = gtk_socket_get_id(GTK_SOCKET(socket_));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.window = reinterpret_cast<void*>(windowed_handle_);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window_.ws_info)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.ws_info = new NPSetWindowCallbackStruct;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPSetWindowCallbackStruct* extra =
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<NPSetWindowCallbackStruct*>(window_.ws_info);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->type = NP_SETWINDOW;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->display = GDK_DISPLAY();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int screen = DefaultScreen(GDK_DISPLAY());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->visual = DefaultVisual(GDK_DISPLAY(), screen);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->depth = DefaultDepth(GDK_DISPLAY(), screen);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->colormap = DefaultColormap(GDK_DISPLAY(), screen);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::WindowedDestroyWindow() {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (plug_) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_->WillDestroyWindow(gtk_plug_get_id(GTK_PLUG(plug_)));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gtk_widget_destroy(plug_);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plug_ = NULL;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_ = NULL;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    windowed_handle_ = 0;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebPluginDelegateImpl::WindowedReposition(
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& window_rect,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& clip_rect) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_rect == window_rect_ && clip_rect == clip_rect_)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_rect_ = window_rect;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clip_rect_ = clip_rect;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::WindowedSetWindow() {
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!instance_.get())
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!windowed_handle_) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See https://bugzilla.mozilla.org/show_bug.cgi?id=108347
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we call NPP_SetWindow with a <= 0 width or height, problems arise in
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flash (and possibly other plugins).
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(piman): the Mozilla code suggests that for the Java plugin, we should
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // still call NPP_SetWindow in that case. We need to verify that.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_rect_.width() <= 0 || window_rect_.height() <= 0) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance()->set_window_handle(windowed_handle_);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!instance()->windowless());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.top = clip_rect_.y();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.left = clip_rect_.x();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.height = window_rect_.height();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.width = window_rect_.width();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.x = window_rect_.x();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.y = window_rect_.y();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.type = NPWindowTypeWindow;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset this flag before entering the instance in case of side-effects.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowed_did_set_window_ = true;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPError err = instance()->NPP_SetWindow(&window_);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(err == NPERR_NO_ERROR);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::WindowlessUpdateGeometry(
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& window_rect,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& clip_rect) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only resend to the instance if the geometry has changed.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_rect == window_rect_ && clip_rect == clip_rect_)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clip_rect_ = clip_rect;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_rect_ = window_rect;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowlessSetWindow();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::EnsurePixmapAtLeastSize(int width, int height) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pixmap_) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gint cur_width, cur_height;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gdk_pixmap_get_size(pixmap_, &cur_width, &cur_height);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_width >= width && cur_height >= height)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // We are already the appropriate size.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise, we need to recreate ourselves.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_object_unref(pixmap_);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pixmap_ = NULL;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |sys_visual| is owned by gdk; we shouldn't free it.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GdkVisual* sys_visual = gdk_visual_get_system();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pixmap_ = gdk_pixmap_new(NULL,  // use width/height/depth params
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           std::max(1, width), std::max(1, height),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sys_visual->depth);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erg): Replace this with GdkVisual when we move to GTK3.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(),
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           FALSE);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gdk_drawable_set_colormap(pixmap_, colormap);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The GdkDrawable now owns the GdkColormap.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_object_unref(colormap);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_RECTANGLES
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Draw a rectangle on a Cairo context.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Useful for debugging various rectangles involved in drawing plugins.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DrawDebugRectangle(cairo_t* cairo,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const gfx::Rect& rect,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        float r, float g, float b) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_set_source_rgba(cairo, r, g, b, 0.5);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_rectangle(cairo, rect.x(), rect.y(),
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  rect.width(), rect.height());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cairo_stroke(cairo);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::WindowlessPaint(cairo_t* context,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const gfx::Rect& damage_rect) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compare to:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // nsPluginInstanceOwner::Renderer::NativeDraw().
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): we should avoid calling NPP_SetWindow here since it may
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cause page layout to be invalidated.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The actual dirty region is just the intersection of the plugin window and
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the clip window with the damage region. However, the plugin wants to draw
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // relative to the containing window's origin, so our pixmap must be from the
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window's origin down to the bottom-right edge of the dirty region.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Typical case:
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X-----------------------------------+-----------------------------+
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |                                   |                             |
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |    pixmap     +-------------------+                             |
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               |   damage          |                window       |
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               |                   |                             |
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |           +---+-------------------+-------------+               |
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |           |   |                   |   clip      |               |
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       +---+---+-------------------+----------+  |               |
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |   |   |                   |          |  |               |
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |   |   | draw              |          |  |               |
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |   |   |                   |          |  |               |
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // +-------+---+---+-------------------+----------+--+               |
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |       |                   |          |                  |
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |       +-------------------+          |                  |
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |                                      |                  |
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |        plugin                        |                  |
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       +--------------------------------------+                  |
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |                                                                 |
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |                                                                 |
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // +-----------------------------------------------------------------+
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X = origin
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPAPI doesn't properly define which coordinates each of
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - window.clipRect, window.x and window.y in the SetWindow call
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - x and y in GraphicsExpose HandleEvent call
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are relative to, nor does it define what the pixmap is relative to.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Any sane values for them just don't work with the flash plugin. Firefox
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has some interesting behavior. Experiments showed that:
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - window.clipRect is always in the same space as window.x and window.y
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - in the first SetWindow call, or when scrolling, window.x and window.y are
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the coordinates of the plugin relative to the window.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - whenever only a part of the plugin is drawn, Firefox issues a SetWindow
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // call before each GraphicsExpose event, that sets the drawing origin to
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (0, 0) as if the plugin was scrolled to be partially out of the view. The
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GraphicsExpose event has coordinates relative to the "window" (assuming
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that virtual scroll). The pixmap is also relative to the window. It always
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sets the clip rect to the draw rect.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to deviate from that makes Flash render at the wrong place in the
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pixmap, or render the wrong pixels.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flash plugin:
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X-----------------------------------------------------------------+
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |                                                                 |
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               +-------------------+        "real" window        |
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               |   damage          |                             |
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               |                   |                             |
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |           +---+-------------------+-------------+               |
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |           |   |                   | "real" clip |               |
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       +---+---O===================#==========#==#===============#
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |   |   H draw              |          |  |               H
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |   |   H = pixmap          |          |  |               H
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |   |   H = "apparent" clip |          |  |               H
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       +   +---#-------------------+----------+--+               H
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |       H                   |          |                  H
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |       H-------------------+          |                  H
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |       H                              |                  H
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       |       H  plugin                      |                  H
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |       +-------#------------------------------+                  H
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               H                                                 H
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |               H                  "apparent" window              H
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // +---------------#=================================================#
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // X = "real" origin
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // O = "apparent" origin
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "real" means as seen by Chrome
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "apparent" means as seen by the plugin.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect draw_rect = gfx::IntersectRects(window_rect_, damage_rect);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clip_rect_ is relative to the plugin
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect clip_rect_window = clip_rect_;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clip_rect_window.Offset(window_rect_.x(), window_rect_.y());
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  draw_rect.Intersect(clip_rect_window);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These offsets represent by how much the view is shifted to accomodate
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flash (the coordinates of X relative to O in the diagram above).
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int offset_x = 0;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int offset_y = 0;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (quirks_ & PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset_x = -draw_rect.x();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset_y = -draw_rect.y();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.clipRect.top = 0;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.clipRect.left = 0;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.clipRect.bottom = draw_rect.height();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.clipRect.right = draw_rect.width();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.height = window_rect_.height();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.width = window_rect_.width();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.x = window_rect_.x() - draw_rect.x();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.y = window_rect_.y() - draw_rect.y();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.type = NPWindowTypeDrawable;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(window_.ws_info);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NPError err = instance()->NPP_SetWindow(&window_);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(err, NPERR_NO_ERROR);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect pixmap_draw_rect = draw_rect;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pixmap_draw_rect.Offset(offset_x, offset_y);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect pixmap_rect(0, 0,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        pixmap_draw_rect.right(),
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        pixmap_draw_rect.bottom());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the paint message, targeting the pixmap.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPEvent np_event = {0};
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XGraphicsExposeEvent& event = np_event.xgraphicsexpose;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.type = GraphicsExpose;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.x = pixmap_draw_rect.x();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.y = pixmap_draw_rect.y();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.width = pixmap_draw_rect.width();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.height = pixmap_draw_rect.height();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.display = GDK_DISPLAY();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (windowless_shm_pixmap_ != None) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pixmap pixmap = None;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GC xgc = NULL;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Display* display = event.display;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect plugin_draw_rect = draw_rect;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make plugin_draw_rect relative to the plugin window.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_draw_rect.Offset(-window_rect_.x(), -window_rect_.y());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In case the drawing area does not start with the plugin window origin,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we can not let the plugin directly draw over the shared memory pixmap.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plugin_draw_rect.x() != pixmap_draw_rect.x() ||
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        plugin_draw_rect.y() != pixmap_draw_rect.y()) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pixmap = XCreatePixmap(display, windowless_shm_pixmap_,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             std::max(1, pixmap_rect.width()),
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             std::max(1, pixmap_rect.height()),
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             DefaultDepth(display, DefaultScreen(display)));
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xgc = XCreateGC(display, windowless_shm_pixmap_, 0, NULL);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Copy the current image into the pixmap, so the plugin can draw over it.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XCopyArea(display, windowless_shm_pixmap_, pixmap, xgc,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                plugin_draw_rect.x(), plugin_draw_rect.y(),
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pixmap_draw_rect.width(), pixmap_draw_rect.height(),
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pixmap_draw_rect.x(), pixmap_draw_rect.y());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.drawable = pixmap;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.drawable = windowless_shm_pixmap_;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell the plugin to paint into the pixmap.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StatsRate plugin_paint("Plugin.Paint");
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StatsScope<base::StatsRate> scope(plugin_paint);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance()->NPP_HandleEvent(&np_event);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pixmap != None) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Copy the rendered image pixmap back into the shm pixmap
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and thus the drawing buffer.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XCopyArea(display, pixmap, windowless_shm_pixmap_, xgc,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pixmap_draw_rect.x(), pixmap_draw_rect.y(),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pixmap_draw_rect.width(), pixmap_draw_rect.height(),
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                plugin_draw_rect.x(), plugin_draw_rect.y());
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XSync(display, FALSE);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (xgc)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XFreeGC(display, xgc);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XFreePixmap(display, pixmap);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XSync(display, FALSE);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height());
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Copy the current image into the pixmap, so the plugin can draw over
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this background.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_t* cairo = gdk_cairo_create(pixmap_);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_destroy(cairo);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event.drawable = GDK_PIXMAP_XID(pixmap_);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell the plugin to paint into the pixmap.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StatsRate plugin_paint("Plugin.Paint");
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StatsScope<base::StatsRate> scope(plugin_paint);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instance()->NPP_HandleEvent(&np_event);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_save(context);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now copy the rendered image pixmap back into the drawing buffer.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_rectangle(context, draw_rect.x(), draw_rect.y(),
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    draw_rect.width(), draw_rect.height());
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_clip(context);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_paint(context);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_RECTANGLES
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Draw some debugging rectangles.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Pixmap rect = blue.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DrawDebugRectangle(context, pixmap_rect, 0, 0, 1);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Drawing rect = red.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DrawDebugRectangle(context, draw_rect, 1, 0, 0);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cairo_restore(context);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPluginDelegateImpl::WindowlessSetWindow() {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!instance())
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_rect_.IsEmpty())  // wait for geometry to be set.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(instance()->windowless());
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mozilla docs say that this window param is not used for windowless
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // plugins; rather, the window is passed during the GraphicsExpose event.
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(window_.window, static_cast<void*>(NULL));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.top = clip_rect_.y() + window_rect_.y();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.left = clip_rect_.x() + window_rect_.x();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.bottom =
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clip_rect_.y() + clip_rect_.height() + window_rect_.y();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.clipRect.right =
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clip_rect_.x() + clip_rect_.width() + window_rect_.x();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.height = window_rect_.height();
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.width = window_rect_.width();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.x = window_rect_.x();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.y = window_rect_.y();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window_.type = NPWindowTypeDrawable;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window_.ws_info)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_.ws_info = new NPSetWindowCallbackStruct;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPSetWindowCallbackStruct* extra =
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<NPSetWindowCallbackStruct*>(window_.ws_info);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->display = GDK_DISPLAY();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int screen = DefaultScreen(GDK_DISPLAY());
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->visual = DefaultVisual(GDK_DISPLAY(), screen);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->depth = DefaultDepth(GDK_DISPLAY(), screen);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra->colormap = DefaultColormap(GDK_DISPLAY(), screen);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPError err = instance()->NPP_SetWindow(&window_);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(err == NPERR_NO_ERROR);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (quirks_ & PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // After a NPP_SetWindow, Flash cancels its timer that generates the
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // invalidates until it gets a paint event, but doesn't explicitly call
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NPP_InvalidateRect.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_->InvalidateRect(clip_rect_);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(instance()->windowless());
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPEvent np_event = {0};
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFocusChangeEvent& event = np_event.xfocus;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.type = focused ? FocusIn : FocusOut;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.display = GDK_DISPLAY();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same values as Firefox. .serial and .window stay 0.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.mode = -1;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.detail = NotifyDetailNone;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance()->NPP_HandleEvent(&np_event);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts a WebInputEvent::Modifiers bitfield into a
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// corresponding X modifier state.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int GetXModifierState(int modifiers) {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x_state = 0;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::ControlKey)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= ControlMask;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::ShiftKey)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= ShiftMask;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::AltKey)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= Mod1Mask;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::MetaKey)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= Mod2Mask;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::LeftButtonDown)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= Button1Mask;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::MiddleButtonDown)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= Button2Mask;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modifiers & WebInputEvent::RightButtonDown)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x_state |= Button3Mask;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(piman@google.com): There are other modifiers, e.g. Num Lock, that
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be set (and Firefox does), but we didn't keep the information in
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the WebKit event.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return x_state;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool NPEventFromWebMouseEvent(const WebMouseEvent& event,
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     Time timestamp,
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     NPEvent* np_event) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  np_event->xany.display = GDK_DISPLAY();
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Firefox keeps xany.serial and xany.window as 0.
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int modifier_state = GetXModifierState(event.modifiers);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Window root = GDK_ROOT_WINDOW();
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event.type) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseMove: {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      np_event->type = MotionNotify;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XMotionEvent& motion_event = np_event->xmotion;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.root = root;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.time = timestamp;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.x = event.x;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.y = event.y;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.x_root = event.globalX;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.y_root = event.globalY;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.state = modifier_state;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.is_hint = NotifyNormal;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      motion_event.same_screen = True;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseLeave:
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseEnter: {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event.type == WebInputEvent::MouseEnter) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        np_event->type = EnterNotify;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        np_event->type = LeaveNotify;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XCrossingEvent& crossing_event = np_event->xcrossing;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.root = root;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.time = timestamp;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.x = event.x;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.y = event.y;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.x_root = event.globalX;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.y_root = event.globalY;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.mode = -1;  // This is what Firefox sets it to.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.detail = NotifyDetailNone;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.same_screen = True;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(piman@google.com): set this to the correct value. Firefox does. I
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // don't know where to get the information though, we get focus
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // notifications, but no unfocus.
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.focus = 0;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crossing_event.state = modifier_state;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseUp:
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseDown: {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event.type == WebInputEvent::MouseDown) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        np_event->type = ButtonPress;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        np_event->type = ButtonRelease;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XButtonEvent& button_event = np_event->xbutton;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.root = root;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.time = timestamp;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.x = event.x;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.y = event.y;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.x_root = event.globalX;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.y_root = event.globalY;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.state = modifier_state;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (event.button) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case WebMouseEvent::ButtonLeft:
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          button_event.button = Button1;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case WebMouseEvent::ButtonMiddle:
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          button_event.button = Button2;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case WebMouseEvent::ButtonRight:
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          button_event.button = Button3;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_event.same_screen = True;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Time timestamp,
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        NPEvent* np_event) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  np_event->xany.display = GDK_DISPLAY();
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Firefox keeps xany.serial and xany.window as 0.
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event.type) {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebKeyboardEvent::KeyDown:
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      np_event->type = KeyPress;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebKeyboardEvent::KeyUp:
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      np_event->type = KeyRelease;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XKeyEvent& key_event = np_event->xkey;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.send_event = False;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.display = GDK_DISPLAY();
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Firefox keeps xany.serial and xany.window as 0.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(piman@google.com): is this right for multiple screens ?
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.root = DefaultRootWindow(key_event.display);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.time = timestamp;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We don't have the correct information for x/y/x_root/y_root. Firefox
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // doesn't have it either, so we pass the same values.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.x = 0;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.y = 0;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.x_root = -1;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.y_root = -1;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.state = GetXModifierState(event.modifiers);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.keycode = event.nativeKeyCode;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_event.same_screen = True;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool NPEventFromWebInputEvent(const WebInputEvent& event,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     Time timestamp,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     NPEvent* np_event) {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event.type) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseMove:
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseLeave:
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseEnter:
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseDown:
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::MouseUp:
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event.size < sizeof(WebMouseEvent)) {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NPEventFromWebMouseEvent(
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *static_cast<const WebMouseEvent*>(&event), timestamp, np_event);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::KeyDown:
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WebInputEvent::KeyUp:
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event.size < sizeof(WebKeyboardEvent)) {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NPEventFromWebKeyboardEvent(
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *static_cast<const WebKeyboardEvent*>(&event), timestamp, np_event);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebPluginDelegateImpl::PlatformHandleInputEvent(
71690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_event_time_ < 0.0)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_event_time_ = event.timeStampSeconds;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time timestamp = static_cast<Time>(
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (event.timeStampSeconds - first_event_time_) * 1.0e3);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NPEvent np_event = {0};
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NPEventFromWebInputEvent(event, timestamp, &np_event)) {
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See comment about PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK in constructor.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (windowless_ &&
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (quirks_ & PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK) &&
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (np_event.type == ButtonPress || np_event.type == ButtonRelease) &&
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (np_event.xbutton.button == Button3)) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flash always returns false, even when the event is handled.
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ret = true;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event->event == WM_MOUSEMOVE) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Snag a reference to the current cursor ASAP in case the plugin modified
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it. There is a nasty race condition here with the multiprocess browser
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // as someone might be setting the cursor in the main process as well.
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cursor = current_windowless_cursor_;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace content
752