|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "nsToolkit.h" |
|
7 #include "nsAppShell.h" |
|
8 #include "nsWindow.h" |
|
9 #include "nsWidgetsCID.h" |
|
10 #include "prmon.h" |
|
11 #include "prtime.h" |
|
12 #include "nsIServiceManager.h" |
|
13 #include "nsComponentManagerUtils.h" |
|
14 #include <objbase.h> |
|
15 #include "WinUtils.h" |
|
16 |
|
17 #include "nsUXThemeData.h" |
|
18 |
|
19 // unknwn.h is needed to build with WIN32_LEAN_AND_MEAN |
|
20 #include <unknwn.h> |
|
21 |
|
22 using namespace mozilla::widget; |
|
23 |
|
24 nsToolkit* nsToolkit::gToolkit = nullptr; |
|
25 HINSTANCE nsToolkit::mDllInstance = 0; |
|
26 static const unsigned long kD3DUsageDelay = 5000; |
|
27 |
|
28 static void |
|
29 StartAllowingD3D9(nsITimer *aTimer, void *aClosure) |
|
30 { |
|
31 if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { |
|
32 nsWindow::StartAllowingD3D9(true); |
|
33 } |
|
34 } |
|
35 |
|
36 MouseTrailer* nsToolkit::gMouseTrailer; |
|
37 |
|
38 //------------------------------------------------------------------------- |
|
39 // |
|
40 // constructor |
|
41 // |
|
42 //------------------------------------------------------------------------- |
|
43 nsToolkit::nsToolkit() |
|
44 { |
|
45 MOZ_COUNT_CTOR(nsToolkit); |
|
46 |
|
47 #if defined(MOZ_STATIC_COMPONENT_LIBS) |
|
48 nsToolkit::Startup(GetModuleHandle(nullptr)); |
|
49 #endif |
|
50 |
|
51 gMouseTrailer = &mMouseTrailer; |
|
52 |
|
53 if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { |
|
54 mD3D9Timer = do_CreateInstance("@mozilla.org/timer;1"); |
|
55 mD3D9Timer->InitWithFuncCallback(::StartAllowingD3D9, |
|
56 nullptr, |
|
57 kD3DUsageDelay, |
|
58 nsITimer::TYPE_ONE_SHOT); |
|
59 } |
|
60 } |
|
61 |
|
62 |
|
63 //------------------------------------------------------------------------- |
|
64 // |
|
65 // destructor |
|
66 // |
|
67 //------------------------------------------------------------------------- |
|
68 nsToolkit::~nsToolkit() |
|
69 { |
|
70 MOZ_COUNT_DTOR(nsToolkit); |
|
71 gMouseTrailer = nullptr; |
|
72 } |
|
73 |
|
74 void |
|
75 nsToolkit::Startup(HMODULE hModule) |
|
76 { |
|
77 nsToolkit::mDllInstance = hModule; |
|
78 WinUtils::Initialize(); |
|
79 nsUXThemeData::Initialize(); |
|
80 } |
|
81 |
|
82 void |
|
83 nsToolkit::Shutdown() |
|
84 { |
|
85 delete gToolkit; |
|
86 gToolkit = nullptr; |
|
87 } |
|
88 |
|
89 void |
|
90 nsToolkit::StartAllowingD3D9() |
|
91 { |
|
92 if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { |
|
93 nsToolkit::GetToolkit()->mD3D9Timer->Cancel(); |
|
94 nsWindow::StartAllowingD3D9(false); |
|
95 } |
|
96 } |
|
97 |
|
98 //------------------------------------------------------------------------- |
|
99 // |
|
100 // Return the nsToolkit for the current thread. If a toolkit does not |
|
101 // yet exist, then one will be created... |
|
102 // |
|
103 //------------------------------------------------------------------------- |
|
104 // static |
|
105 nsToolkit* nsToolkit::GetToolkit() |
|
106 { |
|
107 if (!gToolkit) { |
|
108 gToolkit = new nsToolkit(); |
|
109 } |
|
110 |
|
111 return gToolkit; |
|
112 } |
|
113 |
|
114 |
|
115 //------------------------------------------------------------------------- |
|
116 // |
|
117 // |
|
118 //------------------------------------------------------------------------- |
|
119 MouseTrailer::MouseTrailer() : mMouseTrailerWindow(nullptr), mCaptureWindow(nullptr), |
|
120 mIsInCaptureMode(false), mEnabled(true) |
|
121 { |
|
122 } |
|
123 //------------------------------------------------------------------------- |
|
124 // |
|
125 // |
|
126 //------------------------------------------------------------------------- |
|
127 MouseTrailer::~MouseTrailer() |
|
128 { |
|
129 DestroyTimer(); |
|
130 } |
|
131 //------------------------------------------------------------------------- |
|
132 // |
|
133 // |
|
134 //------------------------------------------------------------------------- |
|
135 void MouseTrailer::SetMouseTrailerWindow(HWND aWnd) |
|
136 { |
|
137 if (mMouseTrailerWindow != aWnd && mTimer) { |
|
138 // Make sure TimerProc is fired at least once for the old window |
|
139 TimerProc(nullptr, nullptr); |
|
140 } |
|
141 mMouseTrailerWindow = aWnd; |
|
142 CreateTimer(); |
|
143 } |
|
144 |
|
145 //------------------------------------------------------------------------- |
|
146 // |
|
147 // |
|
148 //------------------------------------------------------------------------- |
|
149 void MouseTrailer::SetCaptureWindow(HWND aWnd) |
|
150 { |
|
151 mCaptureWindow = aWnd; |
|
152 if (mCaptureWindow) { |
|
153 mIsInCaptureMode = true; |
|
154 } |
|
155 } |
|
156 |
|
157 //------------------------------------------------------------------------- |
|
158 // |
|
159 // |
|
160 //------------------------------------------------------------------------- |
|
161 nsresult MouseTrailer::CreateTimer() |
|
162 { |
|
163 if (mTimer || !mEnabled) { |
|
164 return NS_OK; |
|
165 } |
|
166 |
|
167 nsresult rv; |
|
168 mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); |
|
169 NS_ENSURE_SUCCESS(rv, rv); |
|
170 |
|
171 return mTimer->InitWithFuncCallback(TimerProc, nullptr, 200, |
|
172 nsITimer::TYPE_REPEATING_SLACK); |
|
173 } |
|
174 |
|
175 //------------------------------------------------------------------------- |
|
176 // |
|
177 // |
|
178 //------------------------------------------------------------------------- |
|
179 void MouseTrailer::DestroyTimer() |
|
180 { |
|
181 if (mTimer) { |
|
182 mTimer->Cancel(); |
|
183 mTimer = nullptr; |
|
184 } |
|
185 } |
|
186 |
|
187 //------------------------------------------------------------------------- |
|
188 // |
|
189 // |
|
190 //------------------------------------------------------------------------- |
|
191 void MouseTrailer::TimerProc(nsITimer* aTimer, void* aClosure) |
|
192 { |
|
193 MouseTrailer *mtrailer = nsToolkit::gMouseTrailer; |
|
194 NS_ASSERTION(mtrailer, "MouseTrailer still firing after deletion!"); |
|
195 |
|
196 // Check to see if we are in mouse capture mode, |
|
197 // Once capture ends we could still get back one more timer event. |
|
198 // Capture could end outside our window. |
|
199 // Also, for some reason when the mouse is on the frame it thinks that |
|
200 // it is inside the window that is being captured. |
|
201 if (mtrailer->mCaptureWindow) { |
|
202 if (mtrailer->mCaptureWindow != mtrailer->mMouseTrailerWindow) { |
|
203 return; |
|
204 } |
|
205 } else { |
|
206 if (mtrailer->mIsInCaptureMode) { |
|
207 // mMouseTrailerWindow could be bad from rolling over the frame, so clear |
|
208 // it if we were capturing and now this is the first timer callback |
|
209 // since we canceled the capture |
|
210 mtrailer->mMouseTrailerWindow = nullptr; |
|
211 mtrailer->mIsInCaptureMode = false; |
|
212 return; |
|
213 } |
|
214 } |
|
215 |
|
216 if (mtrailer->mMouseTrailerWindow && ::IsWindow(mtrailer->mMouseTrailerWindow)) { |
|
217 POINT mp; |
|
218 DWORD pos = ::GetMessagePos(); |
|
219 mp.x = GET_X_LPARAM(pos); |
|
220 mp.y = GET_Y_LPARAM(pos); |
|
221 HWND mouseWnd = ::WindowFromPoint(mp); |
|
222 if (mtrailer->mMouseTrailerWindow != mouseWnd) { |
|
223 // Notify someone that a mouse exit happened. |
|
224 PostMessage(mtrailer->mMouseTrailerWindow, WM_MOUSELEAVE, 0, 0); |
|
225 |
|
226 // we are out of this window, destroy timer |
|
227 mtrailer->DestroyTimer(); |
|
228 mtrailer->mMouseTrailerWindow = nullptr; |
|
229 } |
|
230 } else { |
|
231 mtrailer->DestroyTimer(); |
|
232 mtrailer->mMouseTrailerWindow = nullptr; |
|
233 } |
|
234 } |
|
235 |