1 /****************************************************************************
2 **
3 ** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved.
4 **
5 ** This file is part of a Qt Solutions component.
6 **
7 ** This file may be used under the terms of the GNU General Public
8 ** License version 2.0 as published by the Free Software Foundation
9 ** and appearing in the file LICENSE.GPL included in the packaging of
10 ** this file.  Please review the following information to ensure GNU
11 ** General Public Licensing requirements will be met:
12 ** http://www.trolltech.com/products/qt/opensource.html
13 **
14 ** If you are unsure which license is appropriate for your use, please
15 ** review the following information:
16 ** http://www.trolltech.com/products/qt/licensing.html or contact the
17 ** Trolltech sales department at sales@trolltech.com.
18 **
19 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 **
22 ****************************************************************************/
23 #include <QtGui>
24 
25 #include "qtbrowserplugin.h"
26 #include "qtbrowserplugin_p.h"
27 
28 #include <windows.h>
29 #include "qtnpapi.h"
30 
31 #if QT_VERSION >= 0x050000
32 # define QT_WA(unicode, ansi) unicode
33 #endif
34 
35 static HHOOK hhook = 0;
36 static bool ownsqapp = false;
37 
38 
39 static const uint keytbl[256] = {  // Keyboard mapping table
40   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_Cancel,
41   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
42   Qt::Key_Backspace, Qt::Key_Tab, Qt::Key_unknown, Qt::Key_unknown,
43   Qt::Key_Clear, Qt::Key_Return, Qt::Key_unknown, Qt::Key_unknown,
44   Qt::Key_Shift, Qt::Key_Control, Qt::Key_Alt, Qt::Key_Pause,
45   Qt::Key_CapsLock, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
46   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_Escape,
47   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_Mode_switch,
48   Qt::Key_Space, Qt::Key_PageUp, Qt::Key_PageDown, Qt::Key_End,
49   Qt::Key_Home, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right,
50   Qt::Key_Down, Qt::Key_Select, Qt::Key_Printer, Qt::Key_Execute,
51   Qt::Key_Print, Qt::Key_Insert, Qt::Key_Delete, Qt::Key_Help,
52   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
53   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
54   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
55   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
56   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
57   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
58   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
59   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
60   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
61   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
62   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_Meta,
63   Qt::Key_Meta, Qt::Key_Menu, Qt::Key_unknown, Qt::Key_Sleep,
64   Qt::Key_0, Qt::Key_1, Qt::Key_2, Qt::Key_3,
65   Qt::Key_4, Qt::Key_5, Qt::Key_6, Qt::Key_7,
66   Qt::Key_8, Qt::Key_9, Qt::Key_Asterisk, Qt::Key_Plus,
67   Qt::Key_Comma, Qt::Key_Minus, Qt::Key_Period, Qt::Key_Slash,
68   Qt::Key_F1, Qt::Key_F2, Qt::Key_F3, Qt::Key_F4,
69   Qt::Key_F5, Qt::Key_F6, Qt::Key_F7, Qt::Key_F8,
70   Qt::Key_F9, Qt::Key_F10, Qt::Key_F11, Qt::Key_F12,
71   Qt::Key_F13, Qt::Key_F14, Qt::Key_F15, Qt::Key_F16,
72   Qt::Key_F17, Qt::Key_F18, Qt::Key_F19, Qt::Key_F20,
73   Qt::Key_F21, Qt::Key_F22, Qt::Key_F23, Qt::Key_F24,
74   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
75   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
76   Qt::Key_NumLock, Qt::Key_ScrollLock, Qt::Key_unknown, Qt::Key_Massyo,
77   Qt::Key_Touroku, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
78   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
79   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
80   Qt::Key_Shift, Qt::Key_Shift, Qt::Key_Control, Qt::Key_Control,
81   Qt::Key_Alt, Qt::Key_Alt, Qt::Key_Back, Qt::Key_Forward,
82   Qt::Key_Refresh, Qt::Key_Stop, Qt::Key_Search, Qt::Key_Favorites,
83   Qt::Key_HomePage, Qt::Key_VolumeMute, Qt::Key_VolumeDown, Qt::Key_VolumeUp,
84   Qt::Key_MediaNext, Qt::Key_MediaPrevious, Qt::Key_MediaStop, Qt::Key_MediaPlay,
85   Qt::Key_LaunchMail, Qt::Key_LaunchMedia, Qt::Key_Launch0, Qt::Key_Launch1,
86   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
87   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
88   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
89   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
90   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
91   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
92   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
93   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
94   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
95   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
96   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
97   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
98   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
99   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
100   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
101   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown, Qt::Key_unknown,
102   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_Play, Qt::Key_Zoom,
103   Qt::Key_unknown, Qt::Key_unknown, Qt::Key_Clear, 0
104 };
105 
qt_translateKeyCode(int vk)106 static int qt_translateKeyCode(int vk)
107 {
108   if (vk >= 0 && vk <= 255)
109     return keytbl[vk];
110   return Qt::Key_unknown;
111 }
112 
FilterProc(int nCode,WPARAM wParam,LPARAM lParam)113 LRESULT CALLBACK FilterProc( int nCode, WPARAM wParam, LPARAM lParam )
114 {
115     if (qApp)
116 	qApp->sendPostedEvents(0, -1);
117     if (nCode < 0 || !(wParam & PM_REMOVE))
118         return CallNextHookEx(hhook, nCode, wParam, lParam);
119     MSG *msg = (MSG*)lParam;
120     bool processed = false;
121     // (some) support for key-sequences via QAction and QShortcut
122     if(msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN) {
123       QWidget *focusWidget = QWidget::find(msg->hwnd);
124         if (focusWidget) {
125             int key = msg->wParam;
126             if (!(key >= 'A' && key <= 'Z') && !(key >= '0' && key <= '9'))
127                 key = qt_translateKeyCode(msg->wParam);
128             Qt::KeyboardModifiers modifiers = 0;
129             int modifierKey = 0;
130             if (GetKeyState(VK_SHIFT) < 0) {
131                 modifierKey |= Qt::SHIFT;
132                 modifiers |= Qt::ShiftModifier;
133             }
134             if (GetKeyState(VK_CONTROL) < 0) {
135                 modifierKey |= Qt::CTRL;
136                 modifiers |= Qt::ControlModifier;
137             }
138             if (GetKeyState(VK_MENU) < 0) {
139                 modifierKey |= Qt::ALT;
140                 modifiers |= Qt::AltModifier;
141             }
142             QKeyEvent override(QEvent::ShortcutOverride, key, modifiers);
143             override.ignore();
144             QApplication::sendEvent(focusWidget, &override);
145             processed = override.isAccepted();
146             QKeySequence shortcutKey(modifierKey + key);
147             if (!processed) {
148                 QList<QAction*> actions = focusWidget->window()->findChildren<QAction*>();
149                 for (int i = 0; i < actions.count() && !processed; ++i) {
150                     QAction *action = actions.at(i);
151                     if (!action->isEnabled() || action->shortcut() != shortcutKey)
152                         continue;
153                     QShortcutEvent event(shortcutKey, 0);
154                     processed = QApplication::sendEvent(action, &event);
155                 }
156             }
157             if (!processed) {
158                 QList<QShortcut*> shortcuts = focusWidget->window()->findChildren<QShortcut*>();
159                 for (int i = 0; i < shortcuts.count() && !processed; ++i) {
160                     QShortcut *shortcut = shortcuts.at(i);
161                     if (!shortcut->isEnabled() || shortcut->key() != shortcutKey)
162                         continue;
163                     QShortcutEvent event(shortcutKey, shortcut->id());
164                     processed = QApplication::sendEvent(shortcut, &event);
165                 }
166             }
167         }
168     }
169     return CallNextHookEx(hhook, nCode, wParam, lParam);
170 }
171 
qtns_event(QtNPInstance *,NPEvent *)172 extern "C" bool qtns_event(QtNPInstance *, NPEvent *)
173 {
174     return false;
175 }
176 
qtns_initialize(QtNPInstance *)177 extern "C" void qtns_initialize(QtNPInstance*)
178 {
179     if (!qApp) {
180         ownsqapp = true;
181 	static int argc=0;
182 	static char **argv={ 0 };
183 	(void)new QApplication(argc, argv);
184         QT_WA({
185 	    hhook = SetWindowsHookExW( WH_GETMESSAGE, FilterProc, 0, GetCurrentThreadId() );
186         }, {
187 	    hhook = SetWindowsHookExA( WH_GETMESSAGE, FilterProc, 0, GetCurrentThreadId() );
188         });
189     }
190 }
191 
qtns_destroy(QtNPInstance *)192 extern "C" void qtns_destroy(QtNPInstance *)
193 {
194 }
195 
qtns_shutdown()196 extern "C" void qtns_shutdown()
197 {
198     if (!ownsqapp)
199         return;
200 
201     // check if qApp still runs widgets (in other DLLs)
202     QWidgetList widgets = qApp->allWidgets();
203     int count = widgets.count();
204     for (int w = 0; w < widgets.count(); ++w) {
205         // ignore all Qt generated widgets
206         QWidget *widget = widgets.at(w);
207         if (widget->windowFlags() & Qt::Desktop)
208             count--;
209     }
210     if (count) // qApp still used
211         return;
212 
213     delete qApp;
214     ownsqapp = false;
215     if ( hhook )
216         UnhookWindowsHookEx( hhook );
217     hhook = 0;
218 }
219 
qtns_embed(QtNPInstance * This)220 extern "C" void qtns_embed(QtNPInstance *This)
221 {
222     Q_ASSERT(qobject_cast<QWidget*>(This->qt.object));
223 
224     LONG oldLong = GetWindowLong(This->window, GWL_STYLE);
225     ::SetWindowLong(This->window, GWL_STYLE, oldLong | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
226     ::SetWindowLong(This->qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
227     ::SetParent(This->qt.widget->winId(), This->window);
228 }
229 
qtns_setGeometry(QtNPInstance * This,const QRect & rect,const QRect &)230 extern "C" void qtns_setGeometry(QtNPInstance *This, const QRect &rect, const QRect &)
231 {
232     Q_ASSERT(qobject_cast<QWidget*>(This->qt.object));
233 
234     This->qt.widget->setGeometry(QRect(0, 0, rect.width(), rect.height()));
235 }
236 
237 /*
238 extern "C" void qtns_print(QtNPInstance * This, NPPrint *printInfo)
239 {
240     NPWindow* printWindow = &(printInfo->print.embedPrint.window);
241     void* platformPrint = printInfo->print.embedPrint.platformPrint;
242     // #### Nothing yet.
243 }
244 */
245