FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
PluginWindowWin.cpp
1 /**********************************************************\
2 Original Author: Richard Bateman (taxilian)
3 
4 Created: Nov 24, 2009
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2009 Richard Bateman, Firebreath development team
13 \**********************************************************/
14 
15 #include "win_common.h"
16 #include <ShlGuid.h>
17 #include "logging.h"
18 #include "Win/KeyCodesWin.h"
19 #include "AsyncFunctionCall.h"
20 
21 #include "PluginEvents/WindowsEvent.h"
22 #include "PluginEvents/GeneralEvents.h"
23 #include "PluginEvents/DrawingEvents.h"
24 #include "PluginEvents/MouseEvents.h"
25 #include "PluginEvents/KeyboardEvents.h"
26 #include "PluginWindowWin.h"
27 
28 #include "ConstructDefaultPluginWindows.h"
29 #include "precompiled_headers.h" // On windows, everything above this line in PCH
30 
31 #define WM_ASYNCTHREADINVOKE WM_USER + 1
32 
33 using namespace FB;
34 
35 extern HINSTANCE gInstance;
36 
37 PluginWindowWin::PluginWindowMap FB::PluginWindowWin::m_windowMap;
38 
39 FB::PluginWindowWin* FB::createPluginWindowWin(const FB::WindowContextWin& ctx)
40 {
41  return new PluginWindowWin(ctx);
42 }
43 
44 PluginWindowWin::PluginWindowWin(const WindowContextWin& ctx)
45  : m_hWnd(ctx.handle)
46  , m_browserhWnd(NULL)
47  , lpOldWinProc(NULL)
48  , m_callOldWinProc(false)
49  , m_suppressEraseBackground(false)
50 {
51  // subclass window so we can intercept window messages
52  lpOldWinProc = SubclassWindow(m_hWnd, (WNDPROC)&PluginWindowWin::_WinProc);
53  // associate window with this object so that we can route events properly
54  m_windowMap[static_cast<void*>(m_hWnd)] = this;
55 }
56 
57 PluginWindowWin::~PluginWindowWin()
58 {
59  // Unsubclass the window so that everything is as it was before we got it
60  // Some browsers, like Chrome, unsubclass it for us and then proxy to us. Creepy, no?
61  WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
62  GetWindowLongPtr(m_hWnd, GWLP_WNDPROC));
63  if (current_wnd_proc == &PluginWindowWin::_WinProc)
64  SubclassWindow(m_hWnd, lpOldWinProc);
65 
66  PluginWindowMap::iterator it = m_windowMap.find(static_cast<void*>(m_hWnd));
67  if (it != m_windowMap.end())
68  m_windowMap.erase(it);
69 }
70 
71 bool PluginWindowWin::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT & lRes)
72 {
73  lRes = 0;
74  // Before all else, give the plugin a chance to handle the platform specific event;
75  // Then give the custom winproc the chance
76  if (CustomWinProc(hWnd, uMsg, wParam, lParam, lRes))
77  return true;
78  WindowsEvent ev(hWnd, uMsg, wParam, lParam, lRes);
79  if (SendEvent(&ev)) {
80  return true;
81  }
82 
83  unsigned int modifierState = (GetKeyState(VK_SHIFT) & 0x8000) != 0 ? MouseButtonEvent::ModifierState_Shift : 0;
84  modifierState += (GetKeyState(VK_CONTROL) & 0x8000) != 0 ? MouseButtonEvent::ModifierState_Control : 0;
85  modifierState += (GetKeyState(VK_MENU) & 0x8000) != 0 ? MouseButtonEvent::ModifierState_Menu : 0;
86  switch(uMsg) {
87  case WM_MOUSEACTIVATE:
88  {
96 #ifdef _DEBUG
97  std::stringstream ss;
98  FBLOG_INFO("PluginWindowWin::WinProc: ",
99  "WM_MOUSEACTIVATE Forcing setting focus to hWnd=0x"
100  << std::hex << hWnd << " and returning MA_ACTIVATE value.");
101 #endif
102  SetFocus( m_hWnd ); // get key focus when the mouse is clicked on our plugin
103  lRes = MA_ACTIVATE; // returns activation code (for normal scenarios should return
104  // MA_ACTIVATE value, please review msdn documentation about
105  // available return values)
106  return true;
107  }
108  case WM_GETDLGCODE:
109  {
110  lRes = DLGC_WANTALLKEYS // All keyboard input.
111  | DLGC_WANTARROWS // Direction keys.
112  | DLGC_WANTCHARS // WM_CHAR messages.
113  | DLGC_WANTMESSAGE // All keyboard input (the application passes this message
114  // in the MSG structure to the control).
115  | DLGC_WANTTAB; // TAB key.
116 #ifdef _DEBUG
117  std::stringstream ss;
118  FBLOG_INFO("PluginWindowWin::WinProc: ",
119  "WM_GETDLGCODE Forcing to return " << lRes
120  << " value for hWnd=0x" << std::hex << hWnd);
121 #endif
122  return true;
123  }
124  case WM_LBUTTONDOWN:
125  {
126  MouseDownEvent ev(MouseButtonEvent::MouseButton_Left,
127  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
128  if(SendEvent(&ev))
129  return true;
130  break;
131  }
132  case WM_RBUTTONDOWN:
133  {
134  MouseDownEvent ev(MouseButtonEvent::MouseButton_Right,
135  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
136  if(SendEvent(&ev))
137  return true;
138  break;
139  }
140  case WM_MBUTTONDOWN:
141  {
142  MouseDownEvent ev(MouseButtonEvent::MouseButton_Middle,
143  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
144  if(SendEvent(&ev))
145  return true;
146  break;
147  }
148  case WM_LBUTTONDBLCLK:
149  {
150  MouseDoubleClickEvent ev(MouseButtonEvent::MouseButton_Left,
151  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
152  if(SendEvent(&ev))
153  return true;
154  break;
155  }
156  case WM_RBUTTONDBLCLK:
157  {
158  MouseDoubleClickEvent ev(MouseButtonEvent::MouseButton_Right,
159  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
160  if(SendEvent(&ev))
161  return true;
162  break;
163  }
164  case WM_MBUTTONDBLCLK:
165  {
166  MouseDoubleClickEvent ev(MouseButtonEvent::MouseButton_Middle,
167  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
168  if(SendEvent(&ev))
169  return true;
170  break;
171  }
172  case WM_LBUTTONUP:
173  {
174  MouseUpEvent ev(MouseButtonEvent::MouseButton_Left,
175  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
176  if(SendEvent(&ev))
177  return true;
178  break;
179  }
180  case WM_RBUTTONUP:
181  {
182  MouseUpEvent ev(MouseButtonEvent::MouseButton_Right,
183  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
184  if(SendEvent(&ev))
185  return true;
186  break;
187  }
188  case WM_MBUTTONUP:
189  {
190  MouseUpEvent ev(MouseButtonEvent::MouseButton_Middle,
191  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), modifierState);
192  if(SendEvent(&ev))
193  return true;
194  break;
195  }
196  case WM_MOUSEMOVE:
197  {
198  MouseMoveEvent ev(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
199  if(SendEvent(&ev))
200  return true;
201  break;
202  }
203  case WM_MOUSEWHEEL:
204  {
205  POINT p;
206  p.x = GET_X_LPARAM(lParam);
207  p.y = GET_Y_LPARAM(lParam);
208  ScreenToClient(hWnd, &p);
209 
210  MouseScrollEvent ev(p.x, p.y,
211  0, GET_WHEEL_DELTA_WPARAM(wParam) / (double) WHEEL_DELTA, modifierState);
212  if(SendEvent(&ev))
213  return true;
214  break;
215  }
216 #if _WIN32_WINNT > 0x0600
217  case WM_MOUSEHWHEEL:
218  {
219  POINT p;
220  p.x = GET_X_LPARAM(lParam);
221  p.y = GET_Y_LPARAM(lParam);
222  ScreenToClient(hWnd, &p);
223 
224  MouseScrollEvent ev(p.x, p.y,
225  GET_WHEEL_DELTA_WPARAM(wParam) / (double) WHEEL_DELTA, 0, modifierState);
226  if(SendEvent(&ev))
227  return true;
228  break;
229  }
230 #endif
231  case WM_ERASEBKGND:
232  {
233  if (getSuppressEraseBackground())
234  return 1;
235  return 0;
236  }
237  case WM_PAINT:
238  {
239  FB::Rect bounds = getWindowPosition();
240  bounds.bottom -= bounds.top;
241  bounds.top = 0;
242  bounds.right -= bounds.left;
243  bounds.left = 0;
244  RefreshEvent ev(bounds);
245  if (!SendEvent(&ev)) {
246  HDC hdc;
247  PAINTSTRUCT ps;
248  hdc = BeginPaint(m_hWnd, &ps);
249  // Release the device context
250  EndPaint(m_hWnd, &ps);
251  return true;
252  }
253  break;
254  }
255  case WM_TIMER:
256  {
257  TimerEvent ev((unsigned int)wParam, (void*)lParam);
258  if(SendEvent(&ev))
259  return true;
260  break;
261  }
262  case WM_SETCURSOR:
263  SetCursor(LoadCursor(NULL, IDC_ARROW));
264  break;
265  case WM_KEYUP:
266  {
267  FBKeyCode fb_key = WinKeyCodeToFBKeyCode((unsigned int)wParam);
268  KeyUpEvent ev(fb_key, (unsigned int)wParam);
269  if(SendEvent(&ev))
270  return true;
271  break;
272  }
273  case WM_KEYDOWN:
274  {
275  FBKeyCode fb_key = WinKeyCodeToFBKeyCode((unsigned int)wParam);
276  KeyDownEvent ev(fb_key, (unsigned int)wParam);
277  if(SendEvent(&ev))
278  return true;
279  break;
280  }
281  case WM_SIZE:
282  {
283  ResizedEvent ev;
284  if(SendEvent(&ev))
285  return true;
286  break;
287  }
288  }
289 
290  return false;
291 }
292 
293 LRESULT CALLBACK PluginWindowWin::_WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
294 {
295  PluginWindowMap::iterator it = m_windowMap.find(static_cast<void*>(hWnd));
296  if (it == m_windowMap.end())
297  // This could happen if we're using this as a message-only window
298  return DefWindowProc(hWnd, uMsg, wParam, lParam);
299  PluginWindowWin *win = it->second;
300 
301 
302  LRESULT lResult(0);
303  // Try to handle the event through the plugin instace; if that doesn't work, handle it through the default winproc
304  if (win->WinProc(hWnd, uMsg, wParam, lParam, lResult))
305  return lResult;
306  else if (win->m_callOldWinProc)
307  return win->lpOldWinProc(hWnd, uMsg, wParam, lParam);
308  else
309  return DefWindowProc(hWnd, uMsg, wParam, lParam);
310  return 0;
311 }
312 
314 {
315  InvalidateRect(m_hWnd, NULL, true);
316 }
317 
319 {
320  RECT rect;
321  ::GetWindowRect(m_hWnd, &rect);
322  FB::Rect out = {
323  boost::numeric_cast<int32_t>(rect.top),
324  boost::numeric_cast<int32_t>(rect.left),
325  boost::numeric_cast<int32_t>(rect.bottom),
326  boost::numeric_cast<int32_t>(rect.right)};
327  return out;
328 }
329 
331 {
332  return getWindowPosition();
333 }
334 
336 {
337  FB::Rect pos = getWindowPosition();
338  return pos.right - pos.left;
339 }
340 
342 {
343  FB::Rect pos = getWindowPosition();
344  return pos.bottom - pos.top;
345 }
346 
virtual FB::Rect getWindowPosition() const
Gets the position rect of the window.
Fired for a key down event.
Fired when the user moves the scrollwheel.
Definition: MouseEvents.h:116
virtual FB::Rect getWindowClipping() const
Gets the clipping rect of the window.
Fired when the mouse moves.
Definition: MouseEvents.h:50
virtual uint32_t getWindowWidth() const
Gets the width of the window.
Generic windows event. All windows events going through the winproc get first fired as a WindowEvent ...
Definition: WindowsEvent.h:36
Fired when a mouse up event occurs.
Definition: MouseEvents.h:105
virtual uint32_t getWindowHeight() const
Gets the height of the window.
Fired when a timer event is received; currently this only works on windows and is fired when WM_TIMER...
Definition: GeneralEvents.h:29
Fired for a key up event.
FBKeyCode WinKeyCodeToFBKeyCode(unsigned int wparam)
Converts a windows key code to a FireBreath key code.
Definition: KeyCodesWin.cpp:22
FBKeyCode
Values that represent different keys in a platform agnostic way.
Definition: KeyCodes.h:26
Fired when a mouse down event occurs.
Definition: MouseEvents.h:83
Windows specific implementation of PluginWindow.
Fired when the plugin should repaint itself (such as on windows when WM_PAINT is received) ...
Definition: DrawingEvents.h:55
virtual void InvalidateWindow() const
Invalidate window. This should tell the OS to send a REFRESH event.
virtual bool SendEvent(PluginEvent *evt)
Sends an event to all attached sinks.
Fired when a mouse double click event occurs.
Definition: MouseEvents.h:94
Fired when the plugin window is resized.
Definition: DrawingEvents.h:36