Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: webkit/glue/plugins/webplugin_delegate_impl_gtk.cc

Issue 115330: linux: Adding events to windowless plugins on Linux (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // HACK: we need this #define in place before npapi.h is included for
6 // plugins to work. However, all sorts of headers include npapi.h, so
7 // the only way to be certain the define is in place is to put it
8 // here. You might ask, "Why not set it in npapi.h directly, or in
9 // this directory's SConscript, then?" but it turns out this define
10 // makes npapi.h include Xlib.h, which in turn defines a ton of symbols
11 // like None and Status, causing conflicts with the aforementioned
12 // many headers that include npapi.h. Ugh.
13 // See also plugin_host.cc.
14 #define MOZ_X11 1
15
16 #include "webkit/glue/plugins/webplugin_delegate_impl.h" 5 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
17 6
18 #include <string> 7 #include <string>
19 #include <vector> 8 #include <vector>
20 9
21 #include <gtk/gtk.h> 10 #include <gtk/gtk.h>
22 #include <gdk/gdkx.h> 11 #include <gdk/gdkx.h>
23 12
24 #include "base/basictypes.h" 13 #include "base/basictypes.h"
25 #include "base/file_util.h" 14 #include "base/file_util.h"
26 #include "base/message_loop.h" 15 #include "base/message_loop.h"
27 #include "base/process_util.h" 16 #include "base/process_util.h"
28 #include "base/stats_counters.h" 17 #include "base/stats_counters.h"
29 #include "base/string_util.h" 18 #include "base/string_util.h"
19 #include "webkit/api/public/WebInputEvent.h"
30 // #include "webkit/default_plugin/plugin_impl.h" 20 // #include "webkit/default_plugin/plugin_impl.h"
31 #include "webkit/glue/glue_util.h" 21 #include "webkit/glue/glue_util.h"
32 #include "webkit/glue/webplugin.h" 22 #include "webkit/glue/webplugin.h"
33 #include "webkit/glue/plugins/plugin_constants_win.h" 23 #include "webkit/glue/plugins/plugin_constants_win.h"
34 #include "webkit/glue/plugins/plugin_instance.h" 24 #include "webkit/glue/plugins/plugin_instance.h"
35 #include "webkit/glue/plugins/plugin_lib.h" 25 #include "webkit/glue/plugins/plugin_lib.h"
36 #include "webkit/glue/plugins/plugin_list.h" 26 #include "webkit/glue/plugins/plugin_list.h"
37 #include "webkit/glue/plugins/plugin_stream_url.h" 27 #include "webkit/glue/plugins/plugin_stream_url.h"
38 #include "webkit/glue/webkit_glue.h" 28 #include "webkit/glue/webkit_glue.h"
29 #if defined(OS_LINUX)
30 #include "third_party/npapi/bindings/npapi_x11.h"
31 #endif
32
33 using WebKit::WebKeyboardEvent;
34 using WebKit::WebInputEvent;
35 using WebKit::WebMouseEvent;
39 36
40 WebPluginDelegate* WebPluginDelegate::Create( 37 WebPluginDelegate* WebPluginDelegate::Create(
41 const FilePath& filename, 38 const FilePath& filename,
42 const std::string& mime_type, 39 const std::string& mime_type,
43 gfx::NativeView containing_view) { 40 gfx::NativeView containing_view) {
44 scoped_refptr<NPAPI::PluginLib> plugin = 41 scoped_refptr<NPAPI::PluginLib> plugin =
45 NPAPI::PluginLib::CreatePluginLib(filename); 42 NPAPI::PluginLib::CreatePluginLib(filename);
46 if (plugin.get() == NULL) 43 if (plugin.get() == NULL)
47 return NULL; 44 return NULL;
48 45
49 NPError err = plugin->NP_Initialize(); 46 NPError err = plugin->NP_Initialize();
50 if (err != NPERR_NO_ERROR) 47 if (err != NPERR_NO_ERROR)
51 return NULL; 48 return NULL;
52 49
53 scoped_refptr<NPAPI::PluginInstance> instance = 50 scoped_refptr<NPAPI::PluginInstance> instance =
54 plugin->CreateInstance(mime_type); 51 plugin->CreateInstance(mime_type);
55 return new WebPluginDelegateImpl(containing_view, instance.get()); 52 return new WebPluginDelegateImpl(containing_view, instance.get());
56 } 53 }
57 54
58 WebPluginDelegateImpl::WebPluginDelegateImpl( 55 WebPluginDelegateImpl::WebPluginDelegateImpl(
59 gfx::NativeView containing_view, 56 gfx::NativeView containing_view,
60 NPAPI::PluginInstance *instance) 57 NPAPI::PluginInstance *instance)
61 : 58 :
62 windowed_handle_(0), 59 windowed_handle_(0),
63 windowed_did_set_window_(false), 60 windowed_did_set_window_(false),
64 windowless_(false), 61 windowless_(false),
65 plugin_(NULL), 62 plugin_(NULL),
63 windowless_needs_set_window_(true),
66 instance_(instance), 64 instance_(instance),
67 pixmap_(NULL), 65 pixmap_(NULL),
66 first_event_time_(-1.0),
68 parent_(containing_view), 67 parent_(containing_view),
69 quirks_(0) 68 quirks_(0) {
70 {
71 memset(&window_, 0, sizeof(window_)); 69 memset(&window_, 0, sizeof(window_));
72
73 } 70 }
74 71
75 WebPluginDelegateImpl::~WebPluginDelegateImpl() { 72 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
76 DestroyInstance(); 73 DestroyInstance();
77 74
78 if (!windowless_) 75 if (!windowless_)
79 WindowedDestroyWindow(); 76 WindowedDestroyWindow();
80 77
81 if (window_.ws_info) { 78 if (window_.ws_info) {
82 // We only ever use ws_info as an NPSetWindowCallbackStruct. 79 // We only ever use ws_info as an NPSetWindowCallbackStruct.
(...skipping 30 matching lines...) Expand all
113 if (!start_result) 110 if (!start_result)
114 return false; 111 return false;
115 112
116 windowless_ = instance_->windowless(); 113 windowless_ = instance_->windowless();
117 if (windowless_) { 114 if (windowless_) {
118 // For windowless plugins we should set the containing window handle 115 // For windowless plugins we should set the containing window handle
119 // as the instance window handle. This is what Safari does. Not having 116 // as the instance window handle. This is what Safari does. Not having
120 // a valid window handle causes subtle bugs with plugins which retreive 117 // a valid window handle causes subtle bugs with plugins which retreive
121 // the window handle and validate the same. The window handle can be 118 // the window handle and validate the same. The window handle can be
122 // retreived via NPN_GetValue of NPNVnetscapeWindow. 119 // retreived via NPN_GetValue of NPNVnetscapeWindow.
123 // instance_->set_window_handle(parent_); 120 instance_->set_window_handle(parent_);
124 // CreateDummyWindowForActivation(); 121 // CreateDummyWindowForActivation();
125 // handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); 122 // handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
126 } else { 123 } else {
127 if (!WindowedCreatePlugin()) 124 if (!WindowedCreatePlugin())
128 return false; 125 return false;
129 } 126 }
130 127
131 plugin->SetWindow(windowed_handle_); 128 plugin->SetWindow(windowed_handle_);
132 plugin_url_ = url.spec(); 129 plugin_url_ = url.spec();
133 130
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 383
387 void WebPluginDelegateImpl::WindowedSetWindow() { 384 void WebPluginDelegateImpl::WindowedSetWindow() {
388 if (!instance_) 385 if (!instance_)
389 return; 386 return;
390 387
391 if (!windowed_handle_) { 388 if (!windowed_handle_) {
392 NOTREACHED(); 389 NOTREACHED();
393 return; 390 return;
394 } 391 }
395 392
396 // XXX instance()->set_window_handle(windowed_handle_); 393 instance()->set_window_handle(windowed_handle_);
397 394
398 DCHECK(!instance()->windowless()); 395 DCHECK(!instance()->windowless());
399 396
400 window_.clipRect.top = clip_rect_.y(); 397 window_.clipRect.top = clip_rect_.y();
401 window_.clipRect.left = clip_rect_.x(); 398 window_.clipRect.left = clip_rect_.x();
402 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); 399 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
403 window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); 400 window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
404 window_.height = window_rect_.height(); 401 window_.height = window_rect_.height();
405 window_.width = window_rect_.width(); 402 window_.width = window_rect_.width();
406 window_.x = window_rect_.x(); 403 window_.x = window_rect_.x();
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 // this background. 535 // this background.
539 cairo_t* cairo = gdk_cairo_create(pixmap_); 536 cairo_t* cairo = gdk_cairo_create(pixmap_);
540 cairo_set_source_surface(cairo, context, 0, 0); 537 cairo_set_source_surface(cairo, context, 0, 0);
541 cairo_rectangle(cairo, draw_rect.x(), draw_rect.y(), 538 cairo_rectangle(cairo, draw_rect.x(), draw_rect.y(),
542 draw_rect.width(), draw_rect.height()); 539 draw_rect.width(), draw_rect.height());
543 cairo_clip(cairo); 540 cairo_clip(cairo);
544 cairo_paint(cairo); 541 cairo_paint(cairo);
545 cairo_destroy(cairo); 542 cairo_destroy(cairo);
546 543
547 // Construct the paint message, targeting the pixmap. 544 // Construct the paint message, targeting the pixmap.
548 XGraphicsExposeEvent event = {0}; 545 NPEvent np_event = {0};
546 XGraphicsExposeEvent &event = np_event.xgraphicsexpose;
549 event.type = GraphicsExpose; 547 event.type = GraphicsExpose;
550 event.display = GDK_DISPLAY(); 548 event.display = GDK_DISPLAY();
551 event.drawable = GDK_PIXMAP_XID(pixmap_); 549 event.drawable = GDK_PIXMAP_XID(pixmap_);
552 event.x = draw_rect.x(); 550 event.x = draw_rect.x();
553 event.y = draw_rect.y(); 551 event.y = draw_rect.y();
554 event.width = draw_rect.width(); 552 event.width = draw_rect.width();
555 event.height = draw_rect.height(); 553 event.height = draw_rect.height();
556 554
557 // Tell the plugin to paint into the pixmap. 555 // Tell the plugin to paint into the pixmap.
558 static StatsRate plugin_paint("Plugin.Paint"); 556 static StatsRate plugin_paint("Plugin.Paint");
559 StatsScope<StatsRate> scope(plugin_paint); 557 StatsScope<StatsRate> scope(plugin_paint);
560 NPError err = instance()->NPP_HandleEvent(reinterpret_cast<XEvent*>(&event)); 558 NPError err = instance()->NPP_HandleEvent(&np_event);
561 DCHECK_EQ(err, NPERR_NO_ERROR); 559 DCHECK_EQ(err, NPERR_NO_ERROR);
562 560
563 // Now copy the rendered image pixmap back into the drawing buffer. 561 // Now copy the rendered image pixmap back into the drawing buffer.
564 cairo = cairo_create(context); 562 cairo = cairo_create(context);
565 gdk_cairo_set_source_pixmap(cairo, pixmap_, 0, 0); 563 gdk_cairo_set_source_pixmap(cairo, pixmap_, 0, 0);
566 cairo_rectangle(cairo, draw_rect.x(), draw_rect.y(), 564 cairo_rectangle(cairo, draw_rect.x(), draw_rect.y(),
567 draw_rect.width(), draw_rect.height()); 565 draw_rect.width(), draw_rect.height());
568 cairo_clip(cairo); 566 cairo_clip(cairo);
569 cairo_paint(cairo); 567 cairo_paint(cairo);
570 cairo_destroy(cairo); 568 cairo_destroy(cairo);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 if (!force_set_window) 612 if (!force_set_window)
615 windowless_needs_set_window_ = false; 613 windowless_needs_set_window_ = false;
616 614
617 NPError err = instance()->NPP_SetWindow(&window_); 615 NPError err = instance()->NPP_SetWindow(&window_);
618 DCHECK(err == NPERR_NO_ERROR); 616 DCHECK(err == NPERR_NO_ERROR);
619 } 617 }
620 618
621 void WebPluginDelegateImpl::SetFocus() { 619 void WebPluginDelegateImpl::SetFocus() {
622 DCHECK(instance()->windowless()); 620 DCHECK(instance()->windowless());
623 621
624 NOTIMPLEMENTED(); 622 NPEvent np_event = {0};
625 /* NPEvent focus_event; 623 XFocusChangeEvent &event = np_event.xfocus;
626 focus_event.event = WM_SETFOCUS; 624 event.type = FocusIn;
627 focus_event.wParam = 0; 625 event.display = GDK_DISPLAY();
628 focus_event.lParam = 0; 626 // Same values as Firefox. .serial and .window stay 0.
629 627 event.mode = -1;
630 instance()->NPP_HandleEvent(&focus_event);*/ 628 event.detail = NotifyDetailNone;
631 } 629 instance()->NPP_HandleEvent(&np_event);
632 630 }
633 bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, 631
634 WebCursor* cursor) { 632 // Converts a WebInputEvent::Modifiers bitfield into a
635 bool ret = instance()->NPP_HandleEvent(event) != 0; 633 // corresponding X modifier state.
634 static int GetXModifierState(int modifiers) {
635 int x_state = 0;
636 if (modifiers & WebInputEvent::ControlKey)
637 x_state |= ControlMask;
638 if (modifiers & WebInputEvent::ShiftKey)
639 x_state |= ShiftMask;
640 if (modifiers & WebInputEvent::AltKey)
641 x_state |= Mod1Mask;
642 if (modifiers & WebInputEvent::MetaKey)
643 x_state |= Mod2Mask;
644 if (modifiers & WebInputEvent::LeftButtonDown)
645 x_state |= Button1Mask;
646 if (modifiers & WebInputEvent::MiddleButtonDown)
647 x_state |= Button2Mask;
648 if (modifiers & WebInputEvent::RightButtonDown)
649 x_state |= Button3Mask;
650 // TODO(piman@google.com): There are other modifiers, e.g. Num Lock, that
651 // should be set (and Firefox does), but we didn't keep the information in
652 // the WebKit event.
653 return x_state;
654 }
655
656 static bool NPEventFromWebMouseEvent(const WebMouseEvent& event,
657 Time timestamp,
658 NPEvent *np_event) {
659 np_event->xany.display = GDK_DISPLAY();
660 // NOTE: Firefox keeps xany.serial and xany.window as 0.
661
662 int modifier_state = GetXModifierState(event.modifiers);
663
664 Window root = GDK_ROOT_WINDOW();
665 switch (event.type) {
666 case WebInputEvent::MouseMove: {
667 np_event->type = MotionNotify;
668 XMotionEvent &motion_event = np_event->xmotion;
669 motion_event.root = root;
670 motion_event.time = timestamp;
671 motion_event.x = event.x;
672 motion_event.y = event.y;
673 motion_event.x_root = event.globalX;
674 motion_event.y_root = event.globalY;
675 motion_event.state = modifier_state;
676 motion_event.is_hint = NotifyNormal;
677 motion_event.same_screen = True;
678 break;
679 }
680 case WebInputEvent::MouseLeave:
681 case WebInputEvent::MouseEnter: {
682 if (event.type == WebInputEvent::MouseEnter) {
683 np_event->type = EnterNotify;
684 } else {
685 np_event->type = LeaveNotify;
686 }
687 XCrossingEvent &crossing_event = np_event->xcrossing;
688 crossing_event.root = root;
689 crossing_event.time = timestamp;
690 crossing_event.x = event.x;
691 crossing_event.y = event.y;
692 crossing_event.x_root = event.globalX;
693 crossing_event.y_root = event.globalY;
694 crossing_event.mode = -1; // This is what Firefox sets it to.
695 crossing_event.detail = NotifyDetailNone;
696 crossing_event.same_screen = True;
697 // TODO(piman@google.com): set this to the correct value. Firefox does. I
698 // don't know where to get the information though, we get focus
699 // notifications, but no unfocus.
700 crossing_event.focus = 0;
701 crossing_event.state = modifier_state;
702 break;
703 }
704 case WebInputEvent::MouseUp:
705 case WebInputEvent::MouseDown: {
706 if (event.type == WebInputEvent::MouseDown) {
707 np_event->type = ButtonPress;
708 } else {
709 np_event->type = ButtonRelease;
710 }
711 XButtonEvent &button_event = np_event->xbutton;
712 button_event.root = root;
713 button_event.time = timestamp;
714 button_event.x = event.x;
715 button_event.y = event.y;
716 button_event.x_root = event.globalX;
717 button_event.y_root = event.globalY;
718 button_event.state = modifier_state;
719 switch (event.button) {
720 case WebMouseEvent::ButtonLeft:
721 button_event.button = Button1;
722 break;
723 case WebMouseEvent::ButtonMiddle:
724 button_event.button = Button2;
725 break;
726 case WebMouseEvent::ButtonRight:
727 button_event.button = Button3;
728 break;
729 }
730 button_event.same_screen = True;
731 break;
732 }
733 default:
734 NOTREACHED();
735 return false;
736 }
737 return true;
738 }
739
740 static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event,
741 Time timestamp,
742 NPEvent *np_event) {
743 np_event->xany.display = GDK_DISPLAY();
744 // NOTE: Firefox keeps xany.serial and xany.window as 0.
745
746 switch (event.type) {
747 case WebKeyboardEvent::KeyDown:
748 np_event->type = KeyPress;
749 break;
750 case WebKeyboardEvent::KeyUp:
751 np_event->type = KeyRelease;
752 break;
753 default:
754 NOTREACHED();
755 return false;
756 }
757 XKeyEvent &key_event = np_event->xkey;
758 key_event.send_event = False;
759 key_event.display = GDK_DISPLAY();
760 // NOTE: Firefox keeps xany.serial and xany.window as 0.
761 // TODO(piman@google.com): is this right for multiple screens ?
762 key_event.root = DefaultRootWindow(key_event.display);
763 key_event.time = timestamp;
764 // NOTE: We don't have the correct information for x/y/x_root/y_root. Firefox
765 // doesn't have it either, so we pass the same values.
766 key_event.x = 0;
767 key_event.y = 0;
768 key_event.x_root = -1;
769 key_event.y_root = -1;
770 key_event.state = GetXModifierState(event.modifiers);
771 key_event.keycode = event.nativeKeyCode;
772 key_event.same_screen = True;
773 return true;
774 }
775
776 static bool NPEventFromWebInputEvent(const WebInputEvent& event,
777 Time timestamp,
778 NPEvent* np_event) {
779 switch (event.type) {
780 case WebInputEvent::MouseMove:
781 case WebInputEvent::MouseLeave:
782 case WebInputEvent::MouseEnter:
783 case WebInputEvent::MouseDown:
784 case WebInputEvent::MouseUp:
785 if (event.size < sizeof(WebMouseEvent)) {
786 NOTREACHED();
787 return false;
788 }
789 return NPEventFromWebMouseEvent(
790 *static_cast<const WebMouseEvent*>(&event), timestamp, np_event);
791 case WebInputEvent::KeyDown:
792 case WebInputEvent::KeyUp:
793 if (event.size < sizeof(WebKeyboardEvent)) {
794 NOTREACHED();
795 return false;
796 }
797 return NPEventFromWebKeyboardEvent(
798 *static_cast<const WebKeyboardEvent*>(&event), timestamp, np_event);
799 default:
800 return false;
801 }
802 }
803
804 bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event,
805 WebCursor* cursor) {
806 DCHECK(windowless_) << "events should only be received in windowless mode";
807
808 if (first_event_time_ < 0.0)
809 first_event_time_ = event.timeStampSeconds;
810 Time timestamp = static_cast<Time>(
811 (event.timeStampSeconds - first_event_time_) * 1.0e3);
812 NPEvent np_event = {0};
813 if (!NPEventFromWebInputEvent(event, timestamp, &np_event)) {
814 return false;
815 }
816 bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
636 817
637 #if 0 818 #if 0
638 if (event->event == WM_MOUSEMOVE) { 819 if (event->event == WM_MOUSEMOVE) {
639 // Snag a reference to the current cursor ASAP in case the plugin modified 820 // Snag a reference to the current cursor ASAP in case the plugin modified
640 // it. There is a nasty race condition here with the multiprocess browser 821 // it. There is a nasty race condition here with the multiprocess browser
641 // as someone might be setting the cursor in the main process as well. 822 // as someone might be setting the cursor in the main process as well.
642 *cursor = current_windowless_cursor_; 823 *cursor = current_windowless_cursor_;
643 } 824 }
644 #endif 825 #endif
645 826
(...skipping 24 matching lines...) Expand all
670 return stream; 851 return stream;
671 } 852 }
672 853
673 void WebPluginDelegateImpl::URLRequestRouted(const std::string&url, 854 void WebPluginDelegateImpl::URLRequestRouted(const std::string&url,
674 bool notify_needed, 855 bool notify_needed,
675 intptr_t notify_data) { 856 intptr_t notify_data) {
676 if (notify_needed) { 857 if (notify_needed) {
677 instance()->SetURLLoadData(GURL(url.c_str()), notify_data); 858 instance()->SetURLLoadData(GURL(url.c_str()), notify_data);
678 } 859 }
679 } 860 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.cc ('k') | webkit/glue/plugins/webplugin_delegate_impl_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698