OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h" | 5 #include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h" |
6 | 6 |
7 #include <X11/extensions/shape.h> | 7 #include <X11/extensions/shape.h> |
8 #include <X11/extensions/XInput2.h> | 8 #include <X11/extensions/XInput2.h> |
9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
10 #include <X11/Xregion.h> | 10 #include <X11/Xregion.h> |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "ui/views/ime/input_method.h" | 34 #include "ui/views/ime/input_method.h" |
35 #include "ui/views/widget/desktop_aura/desktop_activation_client.h" | 35 #include "ui/views/widget/desktop_aura/desktop_activation_client.h" |
36 #include "ui/views/widget/desktop_aura/desktop_capture_client.h" | 36 #include "ui/views/widget/desktop_aura/desktop_capture_client.h" |
37 #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.h" | 37 #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurax11.h" |
38 #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" | 38 #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" |
39 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" | 39 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h" |
40 #include "ui/views/widget/desktop_aura/desktop_focus_rules.h" | 40 #include "ui/views/widget/desktop_aura/desktop_focus_rules.h" |
41 #include "ui/views/widget/desktop_aura/desktop_layout_manager.h" | 41 #include "ui/views/widget/desktop_aura/desktop_layout_manager.h" |
42 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" | 42 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" |
43 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" | 43 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
| 44 #include "ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h" |
44 #include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" | 45 #include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" |
45 #include "ui/views/widget/desktop_aura/x11_desktop_handler.h" | 46 #include "ui/views/widget/desktop_aura/x11_desktop_handler.h" |
46 #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h" | 47 #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h" |
47 #include "ui/views/widget/desktop_aura/x11_window_event_filter.h" | 48 #include "ui/views/widget/desktop_aura/x11_window_event_filter.h" |
48 | 49 |
49 namespace views { | 50 namespace views { |
50 | 51 |
51 DesktopRootWindowHostX11* DesktopRootWindowHostX11::g_current_capture = | 52 DesktopRootWindowHostX11* DesktopRootWindowHostX11::g_current_capture = |
52 NULL; | 53 NULL; |
53 std::list<XID>* DesktopRootWindowHostX11::open_windows_ = NULL; | 54 std::list<XID>* DesktopRootWindowHostX11::open_windows_ = NULL; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 | 129 |
129 DesktopRootWindowHostX11::~DesktopRootWindowHostX11() { | 130 DesktopRootWindowHostX11::~DesktopRootWindowHostX11() { |
130 root_window_->ClearProperty(kHostForRootWindow); | 131 root_window_->ClearProperty(kHostForRootWindow); |
131 if (corewm::UseFocusControllerOnDesktop()) { | 132 if (corewm::UseFocusControllerOnDesktop()) { |
132 aura::client::SetFocusClient(root_window_, NULL); | 133 aura::client::SetFocusClient(root_window_, NULL); |
133 aura::client::SetActivationClient(root_window_, NULL); | 134 aura::client::SetActivationClient(root_window_, NULL); |
134 } | 135 } |
135 } | 136 } |
136 | 137 |
137 // static | 138 // static |
138 ui::NativeTheme* DesktopRootWindowHost::GetNativeTheme(aura::Window* window) { | |
139 const ui::LinuxUI* linux_ui = ui::LinuxUI::instance(); | |
140 if (linux_ui) { | |
141 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(); | |
142 if (native_theme) | |
143 return native_theme; | |
144 } | |
145 | |
146 return ui::NativeTheme::instance(); | |
147 } | |
148 | |
149 //////////////////////////////////////////////////////////////////////////////// | |
150 // DesktopRootWindowHostX11, private: | |
151 | |
152 void DesktopRootWindowHostX11::InitX11Window( | |
153 const Widget::InitParams& params) { | |
154 unsigned long attribute_mask = CWBackPixmap; | |
155 XSetWindowAttributes swa; | |
156 memset(&swa, 0, sizeof(swa)); | |
157 swa.background_pixmap = None; | |
158 | |
159 ::Atom window_type; | |
160 switch (params.type) { | |
161 case Widget::InitParams::TYPE_MENU: | |
162 swa.override_redirect = True; | |
163 attribute_mask |= CWOverrideRedirect; | |
164 window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU"); | |
165 break; | |
166 case Widget::InitParams::TYPE_TOOLTIP: | |
167 window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"); | |
168 break; | |
169 default: | |
170 window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_NORMAL"); | |
171 break; | |
172 } | |
173 | |
174 xwindow_ = XCreateWindow( | |
175 xdisplay_, x_root_window_, | |
176 params.bounds.x(), params.bounds.y(), | |
177 params.bounds.width(), params.bounds.height(), | |
178 0, // border width | |
179 CopyFromParent, // depth | |
180 InputOutput, | |
181 CopyFromParent, // visual | |
182 attribute_mask, | |
183 &swa); | |
184 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); | |
185 open_windows().push_back(xwindow_); | |
186 | |
187 // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). | |
188 | |
189 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | |
190 KeyPressMask | KeyReleaseMask | | |
191 EnterWindowMask | LeaveWindowMask | | |
192 ExposureMask | VisibilityChangeMask | | |
193 StructureNotifyMask | PropertyChangeMask | | |
194 PointerMotionMask; | |
195 XSelectInput(xdisplay_, xwindow_, event_mask); | |
196 XFlush(xdisplay_); | |
197 | |
198 if (base::MessagePumpForUI::HasXInput2()) | |
199 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | |
200 | |
201 // TODO(erg): We currently only request window deletion events. We also | |
202 // should listen for activation events and anything else that GTK+ listens | |
203 // for, and do something useful. | |
204 ::Atom protocols[2]; | |
205 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); | |
206 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); | |
207 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); | |
208 | |
209 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with | |
210 // the desktop environment. | |
211 XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL); | |
212 | |
213 // Likewise, the X server needs to know this window's pid so it knows which | |
214 // program to kill if the window hangs. | |
215 pid_t pid = getpid(); | |
216 XChangeProperty(xdisplay_, | |
217 xwindow_, | |
218 atom_cache_.GetAtom("_NET_WM_PID"), | |
219 XA_CARDINAL, | |
220 32, | |
221 PropModeReplace, | |
222 reinterpret_cast<unsigned char*>(&pid), 1); | |
223 | |
224 XChangeProperty(xdisplay_, | |
225 xwindow_, | |
226 atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE"), | |
227 XA_ATOM, | |
228 32, | |
229 PropModeReplace, | |
230 reinterpret_cast<unsigned char*>(&window_type), 1); | |
231 | |
232 // Remove popup windows from taskbar. | |
233 if (params.type == Widget::InitParams::TYPE_POPUP || | |
234 params.type == Widget::InitParams::TYPE_BUBBLE) { | |
235 Atom atom = atom_cache_.GetAtom("_NET_WM_STATE_SKIP_TASKBAR"); | |
236 | |
237 // Setting _NET_WM_STATE by sending a message to the root_window (with | |
238 // SetWMSpecState) has no effect here since the window has not yet been | |
239 // mapped. So we manually change the state. | |
240 XChangeProperty (xdisplay_, | |
241 xwindow_, | |
242 atom_cache_.GetAtom("_NET_WM_STATE"), | |
243 XA_ATOM, | |
244 32, | |
245 PropModeAppend, | |
246 reinterpret_cast<unsigned char*>(&atom), 1); | |
247 } | |
248 } | |
249 | |
250 // static | |
251 aura::Window* DesktopRootWindowHostX11::GetContentWindowForXID(XID xid) { | 139 aura::Window* DesktopRootWindowHostX11::GetContentWindowForXID(XID xid) { |
252 aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(xid); | 140 aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(xid); |
253 return root ? root->GetProperty(kViewsWindowForRootWindow) : NULL; | 141 return root ? root->GetProperty(kViewsWindowForRootWindow) : NULL; |
254 } | 142 } |
255 | 143 |
256 // static | 144 // static |
257 DesktopRootWindowHostX11* DesktopRootWindowHostX11::GetHostForXID(XID xid) { | 145 DesktopRootWindowHostX11* DesktopRootWindowHostX11::GetHostForXID(XID xid) { |
258 aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(xid); | 146 aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(xid); |
259 return root ? root->GetProperty(kHostForRootWindow) : NULL; | 147 return root ? root->GetProperty(kHostForRootWindow) : NULL; |
260 } | 148 } |
261 | 149 |
262 // static | 150 // static |
263 std::vector<aura::Window*> DesktopRootWindowHostX11::GetAllOpenWindows() { | 151 std::vector<aura::Window*> DesktopRootWindowHostX11::GetAllOpenWindows() { |
264 std::vector<aura::Window*> windows(open_windows().size()); | 152 std::vector<aura::Window*> windows(open_windows().size()); |
265 std::transform(open_windows().begin(), | 153 std::transform(open_windows().begin(), |
266 open_windows().end(), | 154 open_windows().end(), |
267 windows.begin(), | 155 windows.begin(), |
268 GetContentWindowForXID); | 156 GetContentWindowForXID); |
269 return windows; | 157 return windows; |
270 } | 158 } |
271 | 159 |
272 void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged( | 160 void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged( |
273 bool active) { | 161 bool active) { |
274 native_widget_delegate_->OnNativeWidgetActivationChanged(active); | 162 native_widget_delegate_->OnNativeWidgetActivationChanged(active); |
275 native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint(); | 163 native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint(); |
276 } | 164 } |
277 | 165 |
| 166 void DesktopRootWindowHostX11::AddObserver( |
| 167 views::DesktopRootWindowHostObserverX11* observer) { |
| 168 observer_list_.AddObserver(observer); |
| 169 } |
| 170 |
| 171 void DesktopRootWindowHostX11::RemoveObserver( |
| 172 views::DesktopRootWindowHostObserverX11* observer) { |
| 173 observer_list_.RemoveObserver(observer); |
| 174 } |
| 175 |
278 void DesktopRootWindowHostX11::CleanUpWindowList() { | 176 void DesktopRootWindowHostX11::CleanUpWindowList() { |
279 delete open_windows_; | 177 delete open_windows_; |
280 open_windows_ = NULL; | 178 open_windows_ = NULL; |
281 } | 179 } |
282 | 180 |
283 // TODO(erg): This method should basically be everything I need form | |
284 // RootWindowHostX11::RootWindowHostX11(). | |
285 aura::RootWindow* DesktopRootWindowHostX11::InitRootWindow( | |
286 const Widget::InitParams& params) { | |
287 bounds_ = params.bounds; | |
288 | |
289 aura::RootWindow::CreateParams rw_params(bounds_); | |
290 rw_params.host = this; | |
291 root_window_ = new aura::RootWindow(rw_params); | |
292 root_window_->Init(); | |
293 root_window_->AddChild(content_window_); | |
294 root_window_->SetLayoutManager(new DesktopLayoutManager(root_window_)); | |
295 root_window_->SetProperty(kViewsWindowForRootWindow, content_window_); | |
296 root_window_->SetProperty(kHostForRootWindow, this); | |
297 root_window_host_delegate_ = root_window_; | |
298 | |
299 // If we're given a parent, we need to mark ourselves as transient to another | |
300 // window. Otherwise activation gets screwy. | |
301 gfx::NativeView parent = params.parent; | |
302 if (!params.child && params.parent) | |
303 parent->AddTransientChild(content_window_); | |
304 | |
305 native_widget_delegate_->OnNativeWidgetCreated(true); | |
306 | |
307 capture_client_.reset(new views::DesktopCaptureClient(root_window_)); | |
308 aura::client::SetCaptureClient(root_window_, capture_client_.get()); | |
309 | |
310 // Ensure that the X11DesktopHandler exists so that it dispatches activation | |
311 // messages to us. | |
312 X11DesktopHandler::get(); | |
313 | |
314 if (corewm::UseFocusControllerOnDesktop()) { | |
315 corewm::FocusController* focus_controller = | |
316 new corewm::FocusController(new DesktopFocusRules); | |
317 focus_client_.reset(focus_controller); | |
318 aura::client::SetFocusClient(root_window_, focus_controller); | |
319 aura::client::SetActivationClient(root_window_, focus_controller); | |
320 root_window_->AddPreTargetHandler(focus_controller); | |
321 } else { | |
322 focus_client_.reset(new aura::FocusManager); | |
323 aura::client::SetFocusClient(root_window_, focus_client_.get()); | |
324 activation_client_.reset(new DesktopActivationClient(root_window_)); | |
325 } | |
326 | |
327 dispatcher_client_.reset(new DesktopDispatcherClient); | |
328 aura::client::SetDispatcherClient(root_window_, | |
329 dispatcher_client_.get()); | |
330 | |
331 views::DesktopNativeCursorManager* desktop_native_cursor_manager = | |
332 new views::DesktopNativeCursorManager( | |
333 root_window_, | |
334 scoped_ptr<DesktopCursorLoaderUpdater>( | |
335 new DesktopCursorLoaderUpdaterAuraX11)); | |
336 cursor_client_.reset( | |
337 new views::corewm::CursorManager( | |
338 scoped_ptr<corewm::NativeCursorManager>( | |
339 desktop_native_cursor_manager))); | |
340 aura::client::SetCursorClient(root_window_, | |
341 cursor_client_.get()); | |
342 | |
343 position_client_.reset(new DesktopScreenPositionClient); | |
344 aura::client::SetScreenPositionClient(root_window_, | |
345 position_client_.get()); | |
346 | |
347 desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_); | |
348 | |
349 drag_drop_client_.reset(new DesktopDragDropClientAuraX11( | |
350 this, root_window_, desktop_native_cursor_manager, xdisplay_, xwindow_)); | |
351 aura::client::SetDragDropClient(root_window_, drag_drop_client_.get()); | |
352 | |
353 // TODO(erg): Unify this code once the other consumer goes away. | |
354 x11_window_event_filter_.reset( | |
355 new X11WindowEventFilter(root_window_, activation_client_.get())); | |
356 x11_window_event_filter_->SetUseHostWindowBorders(false); | |
357 desktop_native_widget_aura_->root_window_event_filter()->AddHandler( | |
358 x11_window_event_filter_.get()); | |
359 | |
360 x11_window_move_client_.reset(new X11DesktopWindowMoveClient); | |
361 aura::client::SetWindowMoveClient(root_window_, | |
362 x11_window_move_client_.get()); | |
363 | |
364 focus_client_->FocusWindow(content_window_); | |
365 return root_window_; | |
366 } | |
367 | |
368 bool DesktopRootWindowHostX11::IsWindowManagerPresent() { | |
369 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | |
370 // of WM_Sn selections (where n is a screen number). | |
371 return XGetSelectionOwner( | |
372 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; | |
373 } | |
374 | |
375 void DesktopRootWindowHostX11::SetWMSpecState(bool enabled, | |
376 ::Atom state1, | |
377 ::Atom state2) { | |
378 XEvent xclient; | |
379 memset(&xclient, 0, sizeof(xclient)); | |
380 xclient.type = ClientMessage; | |
381 xclient.xclient.window = xwindow_; | |
382 xclient.xclient.message_type = atom_cache_.GetAtom("_NET_WM_STATE"); | |
383 xclient.xclient.format = 32; | |
384 xclient.xclient.data.l[0] = | |
385 enabled ? k_NET_WM_STATE_ADD : k_NET_WM_STATE_REMOVE; | |
386 xclient.xclient.data.l[1] = state1; | |
387 xclient.xclient.data.l[2] = state2; | |
388 xclient.xclient.data.l[3] = 1; | |
389 xclient.xclient.data.l[4] = 0; | |
390 | |
391 XSendEvent(xdisplay_, x_root_window_, False, | |
392 SubstructureRedirectMask | SubstructureNotifyMask, | |
393 &xclient); | |
394 } | |
395 | |
396 bool DesktopRootWindowHostX11::HasWMSpecProperty(const char* property) const { | |
397 return window_properties_.find(atom_cache_.GetAtom(property)) != | |
398 window_properties_.end(); | |
399 } | |
400 | |
401 //////////////////////////////////////////////////////////////////////////////// | 181 //////////////////////////////////////////////////////////////////////////////// |
402 // DesktopRootWindowHostX11, DesktopRootWindowHost implementation: | 182 // DesktopRootWindowHostX11, DesktopRootWindowHost implementation: |
403 | 183 |
404 aura::RootWindow* DesktopRootWindowHostX11::Init( | 184 aura::RootWindow* DesktopRootWindowHostX11::Init( |
405 aura::Window* content_window, | 185 aura::Window* content_window, |
406 const Widget::InitParams& params) { | 186 const Widget::InitParams& params) { |
407 content_window_ = content_window; | 187 content_window_ = content_window; |
408 | 188 |
409 // TODO(erg): Check whether we *should* be building a RootWindowHost here, or | 189 // TODO(erg): Check whether we *should* be building a RootWindowHost here, or |
410 // whether we should be proxying requests to another DRWHL. | 190 // whether we should be proxying requests to another DRWHL. |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 | 398 |
619 bool DesktopRootWindowHostX11::IsMaximized() const { | 399 bool DesktopRootWindowHostX11::IsMaximized() const { |
620 return (HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_VERT") || | 400 return (HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_VERT") || |
621 HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_HORZ")); | 401 HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_HORZ")); |
622 } | 402 } |
623 | 403 |
624 bool DesktopRootWindowHostX11::IsMinimized() const { | 404 bool DesktopRootWindowHostX11::IsMinimized() const { |
625 return HasWMSpecProperty("_NET_WM_STATE_HIDDEN"); | 405 return HasWMSpecProperty("_NET_WM_STATE_HIDDEN"); |
626 } | 406 } |
627 | 407 |
628 void DesktopRootWindowHostX11::OnCaptureReleased() { | |
629 native_widget_delegate_->OnMouseCaptureLost(); | |
630 g_current_capture = NULL; | |
631 } | |
632 | |
633 void DesktopRootWindowHostX11::DispatchMouseEvent(ui::MouseEvent* event) { | |
634 if (!g_current_capture || g_current_capture == this) { | |
635 root_window_host_delegate_->OnHostMouseEvent(event); | |
636 } else { | |
637 // Another DesktopRootWindowHostX11 has installed itself as | |
638 // capture. Translate the event's location and dispatch to the other. | |
639 event->ConvertLocationToTarget(root_window_, | |
640 g_current_capture->root_window_); | |
641 g_current_capture->root_window_host_delegate_->OnHostMouseEvent(event); | |
642 } | |
643 } | |
644 | |
645 std::list<XID>& DesktopRootWindowHostX11::open_windows() { | |
646 if (!open_windows_) | |
647 open_windows_ = new std::list<XID>(); | |
648 return *open_windows_; | |
649 } | |
650 | 408 |
651 bool DesktopRootWindowHostX11::HasCapture() const { | 409 bool DesktopRootWindowHostX11::HasCapture() const { |
652 return g_current_capture == this; | 410 return g_current_capture == this; |
653 } | 411 } |
654 | 412 |
655 void DesktopRootWindowHostX11::SetAlwaysOnTop(bool always_on_top) { | 413 void DesktopRootWindowHostX11::SetAlwaysOnTop(bool always_on_top) { |
656 SetWMSpecState(always_on_top, | 414 SetWMSpecState(always_on_top, |
657 atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"), | 415 atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"), |
658 None); | 416 None); |
659 } | 417 } |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 } | 757 } |
1000 | 758 |
1001 void DesktopRootWindowHostX11::OnDeviceScaleFactorChanged( | 759 void DesktopRootWindowHostX11::OnDeviceScaleFactorChanged( |
1002 float device_scale_factor) { | 760 float device_scale_factor) { |
1003 } | 761 } |
1004 | 762 |
1005 void DesktopRootWindowHostX11::PrepareForShutdown() { | 763 void DesktopRootWindowHostX11::PrepareForShutdown() { |
1006 } | 764 } |
1007 | 765 |
1008 //////////////////////////////////////////////////////////////////////////////// | 766 //////////////////////////////////////////////////////////////////////////////// |
| 767 // DesktopRootWindowHostX11, private: |
| 768 |
| 769 void DesktopRootWindowHostX11::InitX11Window( |
| 770 const Widget::InitParams& params) { |
| 771 unsigned long attribute_mask = CWBackPixmap; |
| 772 XSetWindowAttributes swa; |
| 773 memset(&swa, 0, sizeof(swa)); |
| 774 swa.background_pixmap = None; |
| 775 |
| 776 ::Atom window_type; |
| 777 switch (params.type) { |
| 778 case Widget::InitParams::TYPE_MENU: |
| 779 swa.override_redirect = True; |
| 780 attribute_mask |= CWOverrideRedirect; |
| 781 window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU"); |
| 782 break; |
| 783 case Widget::InitParams::TYPE_TOOLTIP: |
| 784 window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"); |
| 785 break; |
| 786 default: |
| 787 window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_NORMAL"); |
| 788 break; |
| 789 } |
| 790 |
| 791 xwindow_ = XCreateWindow( |
| 792 xdisplay_, x_root_window_, |
| 793 params.bounds.x(), params.bounds.y(), |
| 794 params.bounds.width(), params.bounds.height(), |
| 795 0, // border width |
| 796 CopyFromParent, // depth |
| 797 InputOutput, |
| 798 CopyFromParent, // visual |
| 799 attribute_mask, |
| 800 &swa); |
| 801 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); |
| 802 |
| 803 // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). |
| 804 |
| 805 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
| 806 KeyPressMask | KeyReleaseMask | |
| 807 EnterWindowMask | LeaveWindowMask | |
| 808 ExposureMask | VisibilityChangeMask | |
| 809 StructureNotifyMask | PropertyChangeMask | |
| 810 PointerMotionMask; |
| 811 XSelectInput(xdisplay_, xwindow_, event_mask); |
| 812 XFlush(xdisplay_); |
| 813 |
| 814 if (base::MessagePumpForUI::HasXInput2()) |
| 815 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
| 816 |
| 817 // TODO(erg): We currently only request window deletion events. We also |
| 818 // should listen for activation events and anything else that GTK+ listens |
| 819 // for, and do something useful. |
| 820 ::Atom protocols[2]; |
| 821 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); |
| 822 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); |
| 823 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); |
| 824 |
| 825 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with |
| 826 // the desktop environment. |
| 827 XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL); |
| 828 |
| 829 // Likewise, the X server needs to know this window's pid so it knows which |
| 830 // program to kill if the window hangs. |
| 831 pid_t pid = getpid(); |
| 832 XChangeProperty(xdisplay_, |
| 833 xwindow_, |
| 834 atom_cache_.GetAtom("_NET_WM_PID"), |
| 835 XA_CARDINAL, |
| 836 32, |
| 837 PropModeReplace, |
| 838 reinterpret_cast<unsigned char*>(&pid), 1); |
| 839 |
| 840 XChangeProperty(xdisplay_, |
| 841 xwindow_, |
| 842 atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE"), |
| 843 XA_ATOM, |
| 844 32, |
| 845 PropModeReplace, |
| 846 reinterpret_cast<unsigned char*>(&window_type), 1); |
| 847 |
| 848 // Remove popup windows from taskbar. |
| 849 if (params.type == Widget::InitParams::TYPE_POPUP || |
| 850 params.type == Widget::InitParams::TYPE_BUBBLE) { |
| 851 Atom atom = atom_cache_.GetAtom("_NET_WM_STATE_SKIP_TASKBAR"); |
| 852 |
| 853 // Setting _NET_WM_STATE by sending a message to the root_window (with |
| 854 // SetWMSpecState) has no effect here since the window has not yet been |
| 855 // mapped. So we manually change the state. |
| 856 XChangeProperty (xdisplay_, |
| 857 xwindow_, |
| 858 atom_cache_.GetAtom("_NET_WM_STATE"), |
| 859 XA_ATOM, |
| 860 32, |
| 861 PropModeAppend, |
| 862 reinterpret_cast<unsigned char*>(&atom), 1); |
| 863 } |
| 864 } |
| 865 |
| 866 // TODO(erg): This method should basically be everything I need form |
| 867 // RootWindowHostX11::RootWindowHostX11(). |
| 868 aura::RootWindow* DesktopRootWindowHostX11::InitRootWindow( |
| 869 const Widget::InitParams& params) { |
| 870 bounds_ = params.bounds; |
| 871 |
| 872 aura::RootWindow::CreateParams rw_params(bounds_); |
| 873 rw_params.host = this; |
| 874 root_window_ = new aura::RootWindow(rw_params); |
| 875 root_window_->Init(); |
| 876 root_window_->AddChild(content_window_); |
| 877 root_window_->SetLayoutManager(new DesktopLayoutManager(root_window_)); |
| 878 root_window_->SetProperty(kViewsWindowForRootWindow, content_window_); |
| 879 root_window_->SetProperty(kHostForRootWindow, this); |
| 880 root_window_host_delegate_ = root_window_; |
| 881 |
| 882 // If we're given a parent, we need to mark ourselves as transient to another |
| 883 // window. Otherwise activation gets screwy. |
| 884 gfx::NativeView parent = params.parent; |
| 885 if (!params.child && params.parent) |
| 886 parent->AddTransientChild(content_window_); |
| 887 |
| 888 native_widget_delegate_->OnNativeWidgetCreated(true); |
| 889 |
| 890 capture_client_.reset(new views::DesktopCaptureClient(root_window_)); |
| 891 aura::client::SetCaptureClient(root_window_, capture_client_.get()); |
| 892 |
| 893 // Ensure that the X11DesktopHandler exists so that it dispatches activation |
| 894 // messages to us. |
| 895 X11DesktopHandler::get(); |
| 896 |
| 897 if (corewm::UseFocusControllerOnDesktop()) { |
| 898 corewm::FocusController* focus_controller = |
| 899 new corewm::FocusController(new DesktopFocusRules); |
| 900 focus_client_.reset(focus_controller); |
| 901 aura::client::SetFocusClient(root_window_, focus_controller); |
| 902 aura::client::SetActivationClient(root_window_, focus_controller); |
| 903 root_window_->AddPreTargetHandler(focus_controller); |
| 904 } else { |
| 905 focus_client_.reset(new aura::FocusManager); |
| 906 aura::client::SetFocusClient(root_window_, focus_client_.get()); |
| 907 activation_client_.reset(new DesktopActivationClient(root_window_)); |
| 908 } |
| 909 |
| 910 dispatcher_client_.reset(new DesktopDispatcherClient); |
| 911 aura::client::SetDispatcherClient(root_window_, |
| 912 dispatcher_client_.get()); |
| 913 |
| 914 views::DesktopNativeCursorManager* desktop_native_cursor_manager = |
| 915 new views::DesktopNativeCursorManager( |
| 916 root_window_, |
| 917 scoped_ptr<DesktopCursorLoaderUpdater>( |
| 918 new DesktopCursorLoaderUpdaterAuraX11)); |
| 919 cursor_client_.reset( |
| 920 new views::corewm::CursorManager( |
| 921 scoped_ptr<corewm::NativeCursorManager>( |
| 922 desktop_native_cursor_manager))); |
| 923 aura::client::SetCursorClient(root_window_, |
| 924 cursor_client_.get()); |
| 925 |
| 926 position_client_.reset(new DesktopScreenPositionClient); |
| 927 aura::client::SetScreenPositionClient(root_window_, |
| 928 position_client_.get()); |
| 929 |
| 930 desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_); |
| 931 |
| 932 drag_drop_client_.reset(new DesktopDragDropClientAuraX11( |
| 933 this, root_window_, desktop_native_cursor_manager, xdisplay_, xwindow_)); |
| 934 aura::client::SetDragDropClient(root_window_, drag_drop_client_.get()); |
| 935 |
| 936 // TODO(erg): Unify this code once the other consumer goes away. |
| 937 x11_window_event_filter_.reset( |
| 938 new X11WindowEventFilter(root_window_, activation_client_.get())); |
| 939 x11_window_event_filter_->SetUseHostWindowBorders(false); |
| 940 desktop_native_widget_aura_->root_window_event_filter()->AddHandler( |
| 941 x11_window_event_filter_.get()); |
| 942 |
| 943 x11_window_move_client_.reset(new X11DesktopWindowMoveClient); |
| 944 aura::client::SetWindowMoveClient(root_window_, |
| 945 x11_window_move_client_.get()); |
| 946 |
| 947 focus_client_->FocusWindow(content_window_); |
| 948 return root_window_; |
| 949 } |
| 950 |
| 951 bool DesktopRootWindowHostX11::IsWindowManagerPresent() { |
| 952 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
| 953 // of WM_Sn selections (where n is a screen number). |
| 954 return XGetSelectionOwner( |
| 955 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
| 956 } |
| 957 |
| 958 void DesktopRootWindowHostX11::SetWMSpecState(bool enabled, |
| 959 ::Atom state1, |
| 960 ::Atom state2) { |
| 961 XEvent xclient; |
| 962 memset(&xclient, 0, sizeof(xclient)); |
| 963 xclient.type = ClientMessage; |
| 964 xclient.xclient.window = xwindow_; |
| 965 xclient.xclient.message_type = atom_cache_.GetAtom("_NET_WM_STATE"); |
| 966 xclient.xclient.format = 32; |
| 967 xclient.xclient.data.l[0] = |
| 968 enabled ? k_NET_WM_STATE_ADD : k_NET_WM_STATE_REMOVE; |
| 969 xclient.xclient.data.l[1] = state1; |
| 970 xclient.xclient.data.l[2] = state2; |
| 971 xclient.xclient.data.l[3] = 1; |
| 972 xclient.xclient.data.l[4] = 0; |
| 973 |
| 974 XSendEvent(xdisplay_, x_root_window_, False, |
| 975 SubstructureRedirectMask | SubstructureNotifyMask, |
| 976 &xclient); |
| 977 } |
| 978 |
| 979 bool DesktopRootWindowHostX11::HasWMSpecProperty(const char* property) const { |
| 980 return window_properties_.find(atom_cache_.GetAtom(property)) != |
| 981 window_properties_.end(); |
| 982 } |
| 983 |
| 984 void DesktopRootWindowHostX11::OnCaptureReleased() { |
| 985 native_widget_delegate_->OnMouseCaptureLost(); |
| 986 g_current_capture = NULL; |
| 987 } |
| 988 |
| 989 void DesktopRootWindowHostX11::DispatchMouseEvent(ui::MouseEvent* event) { |
| 990 if (!g_current_capture || g_current_capture == this) { |
| 991 root_window_host_delegate_->OnHostMouseEvent(event); |
| 992 } else { |
| 993 // Another DesktopRootWindowHostX11 has installed itself as |
| 994 // capture. Translate the event's location and dispatch to the other. |
| 995 event->ConvertLocationToTarget(root_window_, |
| 996 g_current_capture->root_window_); |
| 997 g_current_capture->root_window_host_delegate_->OnHostMouseEvent(event); |
| 998 } |
| 999 } |
| 1000 |
| 1001 std::list<XID>& DesktopRootWindowHostX11::open_windows() { |
| 1002 if (!open_windows_) |
| 1003 open_windows_ = new std::list<XID>(); |
| 1004 return *open_windows_; |
| 1005 } |
| 1006 |
| 1007 //////////////////////////////////////////////////////////////////////////////// |
1009 // DesktopRootWindowHostX11, MessageLoop::Dispatcher implementation: | 1008 // DesktopRootWindowHostX11, MessageLoop::Dispatcher implementation: |
1010 | 1009 |
1011 bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) { | 1010 bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) { |
1012 XEvent* xev = event; | 1011 XEvent* xev = event; |
1013 | 1012 |
1014 // May want to factor CheckXEventForConsistency(xev); into a common location | 1013 // May want to factor CheckXEventForConsistency(xev); into a common location |
1015 // since it is called here. | 1014 // since it is called here. |
1016 switch (xev->type) { | 1015 switch (xev->type) { |
1017 case EnterNotify: | 1016 case EnterNotify: |
1018 case LeaveNotify: { | 1017 case LeaveNotify: { |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 // If we coalesced an event we need to free its cookie. | 1174 // If we coalesced an event we need to free its cookie. |
1176 if (num_coalesced > 0) | 1175 if (num_coalesced > 0) |
1177 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); | 1176 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); |
1178 break; | 1177 break; |
1179 } | 1178 } |
1180 case MapNotify: { | 1179 case MapNotify: { |
1181 // If there's no window manager running, we need to assign the X input | 1180 // If there's no window manager running, we need to assign the X input |
1182 // focus to our host window. | 1181 // focus to our host window. |
1183 if (!IsWindowManagerPresent() && focus_when_shown_) | 1182 if (!IsWindowManagerPresent() && focus_when_shown_) |
1184 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); | 1183 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); |
| 1184 |
| 1185 FOR_EACH_OBSERVER(DesktopRootWindowHostObserverX11, |
| 1186 observer_list_, |
| 1187 OnWindowMapped(xwindow_)); |
| 1188 break; |
| 1189 } |
| 1190 case UnmapNotify: { |
| 1191 FOR_EACH_OBSERVER(DesktopRootWindowHostObserverX11, |
| 1192 observer_list_, |
| 1193 OnWindowUnmapped(xwindow_)); |
1185 break; | 1194 break; |
1186 } | 1195 } |
1187 case ClientMessage: { | 1196 case ClientMessage: { |
1188 Atom message_type = xev->xclient.message_type; | 1197 Atom message_type = xev->xclient.message_type; |
1189 if (message_type == atom_cache_.GetAtom("WM_PROTOCOLS")) { | 1198 if (message_type == atom_cache_.GetAtom("WM_PROTOCOLS")) { |
1190 Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]); | 1199 Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]); |
1191 if (protocol == atom_cache_.GetAtom("WM_DELETE_WINDOW")) { | 1200 if (protocol == atom_cache_.GetAtom("WM_DELETE_WINDOW")) { |
1192 // We have received a close message from the window manager. | 1201 // We have received a close message from the window manager. |
1193 root_window_->OnRootWindowHostCloseRequested(); | 1202 root_window_->OnRootWindowHostCloseRequested(); |
1194 } else if (protocol == atom_cache_.GetAtom("_NET_WM_PING")) { | 1203 } else if (protocol == atom_cache_.GetAtom("_NET_WM_PING")) { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 // static | 1321 // static |
1313 DesktopRootWindowHost* DesktopRootWindowHost::Create( | 1322 DesktopRootWindowHost* DesktopRootWindowHost::Create( |
1314 internal::NativeWidgetDelegate* native_widget_delegate, | 1323 internal::NativeWidgetDelegate* native_widget_delegate, |
1315 DesktopNativeWidgetAura* desktop_native_widget_aura, | 1324 DesktopNativeWidgetAura* desktop_native_widget_aura, |
1316 const gfx::Rect& initial_bounds) { | 1325 const gfx::Rect& initial_bounds) { |
1317 return new DesktopRootWindowHostX11(native_widget_delegate, | 1326 return new DesktopRootWindowHostX11(native_widget_delegate, |
1318 desktop_native_widget_aura, | 1327 desktop_native_widget_aura, |
1319 initial_bounds); | 1328 initial_bounds); |
1320 } | 1329 } |
1321 | 1330 |
| 1331 // static |
| 1332 ui::NativeTheme* DesktopRootWindowHost::GetNativeTheme(aura::Window* window) { |
| 1333 const ui::LinuxUI* linux_ui = ui::LinuxUI::instance(); |
| 1334 if (linux_ui) { |
| 1335 ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(); |
| 1336 if (native_theme) |
| 1337 return native_theme; |
| 1338 } |
| 1339 |
| 1340 return ui::NativeTheme::instance(); |
| 1341 } |
| 1342 |
1322 } // namespace views | 1343 } // namespace views |
OLD | NEW |