OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/aura/desktop_host.h" | 5 #include "ui/aura/desktop_host.h" |
6 | 6 |
7 #include <X11/cursorfont.h> | 7 #include <X11/cursorfont.h> |
8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
9 | 9 |
10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. | 10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 | 191 |
192 // DesktopHost Overrides. | 192 // DesktopHost Overrides. |
193 virtual void SetDesktop(Desktop* desktop) OVERRIDE; | 193 virtual void SetDesktop(Desktop* desktop) OVERRIDE; |
194 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; | 194 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; |
195 virtual void Show() OVERRIDE; | 195 virtual void Show() OVERRIDE; |
196 virtual gfx::Size GetSize() const OVERRIDE; | 196 virtual gfx::Size GetSize() const OVERRIDE; |
197 virtual void SetSize(const gfx::Size& size) OVERRIDE; | 197 virtual void SetSize(const gfx::Size& size) OVERRIDE; |
198 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; | 198 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
199 virtual gfx::Point QueryMouseLocation() OVERRIDE; | 199 virtual gfx::Point QueryMouseLocation() OVERRIDE; |
200 | 200 |
201 // Returns true if there's an X window manager present. | 201 // Handle notification from the X server that |xwindow_| has been resized. |
202 void HandleConfigureNotify(const gfx::Size& new_size); | |
203 | |
204 // Returns true if there's an X window manager present... in most cases. Some | |
205 // window managers (notably, ion3) don't implement enough of ICCCM for us to | |
206 // detect that they're there. | |
202 bool IsWindowManagerPresent(); | 207 bool IsWindowManagerPresent(); |
203 | 208 |
204 Desktop* desktop_; | 209 Desktop* desktop_; |
205 | 210 |
206 // The display and the native X window hosting the desktop. | 211 // The display and the native X window hosting the desktop. |
207 Display* xdisplay_; | 212 Display* xdisplay_; |
208 ::Window xwindow_; | 213 ::Window xwindow_; |
209 | 214 |
210 // Current Aura cursor. | 215 // Current Aura cursor. |
211 gfx::NativeCursor current_cursor_; | 216 gfx::NativeCursor current_cursor_; |
212 | 217 |
213 // The size of |xwindow_|. | 218 // The size of |xwindow_|. |
214 gfx::Rect bounds_; | 219 gfx::Size size_; |
Daniel Erat
2011/10/21 23:00:37
using a Rect here didn't make sense; we never need
sadrul
2011/10/22 18:53:04
Nice
| |
215 | 220 |
216 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); | 221 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); |
217 }; | 222 }; |
218 | 223 |
219 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) | 224 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
220 : desktop_(NULL), | 225 : desktop_(NULL), |
221 xdisplay_(NULL), | 226 xdisplay_(NULL), |
222 xwindow_(0), | 227 xwindow_(0), |
223 current_cursor_(aura::kCursorNull), | 228 current_cursor_(aura::kCursorNull), |
224 bounds_(bounds) { | 229 size_(bounds.size()) { |
225 // This assumes that the message-pump creates and owns the display. | 230 // This assumes that the message-pump creates and owns the display. |
226 xdisplay_ = base::MessagePumpX::GetDefaultXDisplay(); | 231 xdisplay_ = base::MessagePumpX::GetDefaultXDisplay(); |
227 | 232 |
228 // Ingore the requested bounds and just cover the whole screen if there's no | 233 // Ingore the requested bounds and just cover the whole screen if there's no |
229 // X window manager present. | 234 // X window manager present. |
230 if (!IsWindowManagerPresent()) | 235 gfx::Rect actual_bounds = bounds; |
231 bounds_.SetRect( | 236 if (!IsWindowManagerPresent()) { |
237 actual_bounds.SetRect( | |
232 0, 0, DisplayWidth(xdisplay_, 0), DisplayHeight(xdisplay_, 0)); | 238 0, 0, DisplayWidth(xdisplay_, 0), DisplayHeight(xdisplay_, 0)); |
sadrul
2011/10/22 18:53:04
I was thinking about this change ... perhaps we ar
Daniel Erat
2011/10/23 04:02:55
Yeah, I wasn't entirely convinced about this part.
sadrul
2011/10/23 20:45:02
I was thinking perhaps we can always to this for c
| |
239 size_ = actual_bounds.size(); | |
240 } | |
233 | 241 |
234 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), | 242 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), |
235 bounds_.x(), bounds_.y(), | 243 actual_bounds.x(), actual_bounds.y(), |
236 bounds_.width(), bounds_.height(), | 244 actual_bounds.width(), actual_bounds.height(), |
237 0, 0, 0); | 245 0, 0, 0); |
238 | 246 |
239 long event_mask = ButtonPressMask | ButtonReleaseMask | | 247 long event_mask = ButtonPressMask | ButtonReleaseMask | |
240 KeyPressMask | KeyReleaseMask | | 248 KeyPressMask | KeyReleaseMask | |
241 ExposureMask | VisibilityChangeMask | | 249 ExposureMask | VisibilityChangeMask | |
242 StructureNotifyMask | PropertyChangeMask | | 250 StructureNotifyMask | PropertyChangeMask | |
243 PointerMotionMask; | 251 PointerMotionMask; |
244 XSelectInput(xdisplay_, xwindow_, event_mask); | 252 XSelectInput(xdisplay_, xwindow_, event_mask); |
245 XFlush(xdisplay_); | 253 XFlush(xdisplay_); |
246 | 254 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
301 break; | 309 break; |
302 } | 310 } |
303 case ConfigureNotify: { | 311 case ConfigureNotify: { |
304 DCHECK_EQ(xdisplay_, xev->xconfigure.display); | 312 DCHECK_EQ(xdisplay_, xev->xconfigure.display); |
305 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 313 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
306 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 314 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
307 | 315 |
308 // It's possible that the X window may be resized by some other means than | 316 // It's possible that the X window may be resized by some other means than |
309 // from within aura (e.g. the X window manager can change the size). Make | 317 // from within aura (e.g. the X window manager can change the size). Make |
310 // sure the desktop size is maintained properly. | 318 // sure the desktop size is maintained properly. |
311 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height); | 319 HandleConfigureNotify( |
312 if (bounds_.size() != size) | 320 gfx::Size(xev->xconfigure.width, xev->xconfigure.height)); |
313 bounds_.set_size(size); | |
314 desktop_->OnHostResized(size); | |
315 handled = true; | 321 handled = true; |
316 break; | 322 break; |
317 } | 323 } |
318 | 324 |
319 case GenericEvent: { | 325 case GenericEvent: { |
320 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 326 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
321 if (!factory->ShouldProcessXI2Event(xev)) | 327 if (!factory->ShouldProcessXI2Event(xev)) |
322 break; | 328 break; |
323 | 329 |
324 // If this is a motion event we want to coalesce all pending motion | 330 // If this is a motion event we want to coalesce all pending motion |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 desktop_ = desktop; | 376 desktop_ = desktop; |
371 } | 377 } |
372 | 378 |
373 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() { | 379 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() { |
374 return xwindow_; | 380 return xwindow_; |
375 } | 381 } |
376 | 382 |
377 void DesktopHostLinux::Show() { | 383 void DesktopHostLinux::Show() { |
378 XMapWindow(xdisplay_, xwindow_); | 384 XMapWindow(xdisplay_, xwindow_); |
379 | 385 |
386 // Wait for notification that the window is mapped, which happens | |
387 // asynchronously if there's a window manager running. | |
388 gfx::Size new_size = size_; | |
389 while (true) { | |
390 XEvent event; | |
391 XWindowEvent(xdisplay_, xwindow_, StructureNotifyMask, &event); | |
392 if (event.type == ConfigureNotify) | |
393 new_size.SetSize(event.xconfigure.width, event.xconfigure.height); | |
394 else if (event.type == MapNotify) | |
395 break; | |
396 } | |
397 | |
380 // If there's no window manager running, we need to assign the X input focus | 398 // If there's no window manager running, we need to assign the X input focus |
381 // to our host window. (If there's no window manager running, it should also | 399 // to our host window. |
382 // be safe to assume that the host window will have been mapped by the time | 400 if (!IsWindowManagerPresent()) { |
383 // that our SetInputFocus request is received.) | |
384 if (!IsWindowManagerPresent()) | |
385 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); | 401 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); |
sadrul
2011/10/22 18:53:04
How about we just XMapWindow+XFlush here and retur
Daniel Erat
2011/10/23 04:02:55
Thanks, I like this more as well. Sounds fine, as
| |
402 XFlush(xdisplay_); | |
403 } | |
386 | 404 |
387 XFlush(xdisplay_); | 405 // If we removed any ConfigureNotify events from the queue, make sure that we |
406 // apply size changes mentioned in them. | |
407 if (new_size != size_) | |
408 HandleConfigureNotify(new_size); | |
388 } | 409 } |
389 | 410 |
390 gfx::Size DesktopHostLinux::GetSize() const { | 411 gfx::Size DesktopHostLinux::GetSize() const { |
391 return bounds_.size(); | 412 return size_; |
392 } | 413 } |
393 | 414 |
394 void DesktopHostLinux::SetSize(const gfx::Size& size) { | 415 void DesktopHostLinux::SetSize(const gfx::Size& size) { |
395 if (bounds_.size() == size) | 416 if (size_ != size) |
396 return; | 417 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
397 bounds_.set_size(size); | |
398 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); | |
399 } | 418 } |
400 | 419 |
401 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { | 420 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { |
402 if (current_cursor_ == cursor) | 421 if (current_cursor_ == cursor) |
403 return; | 422 return; |
404 current_cursor_ = cursor; | 423 current_cursor_ = cursor; |
405 // Custom web cursors are handled directly. | 424 // Custom web cursors are handled directly. |
406 if (cursor == kCursorCustom) | 425 if (cursor == kCursorCustom) |
407 return; | 426 return; |
408 int cursor_shape = CursorShapeFromNative(cursor); | 427 int cursor_shape = CursorShapeFromNative(cursor); |
409 ::Cursor xcursor = ui::GetXCursor(cursor_shape); | 428 ::Cursor xcursor = ui::GetXCursor(cursor_shape); |
410 XDefineCursor(xdisplay_, xwindow_, xcursor); | 429 XDefineCursor(xdisplay_, xwindow_, xcursor); |
411 } | 430 } |
412 | 431 |
413 gfx::Point DesktopHostLinux::QueryMouseLocation() { | 432 gfx::Point DesktopHostLinux::QueryMouseLocation() { |
414 ::Window root_return, child_return; | 433 ::Window root_return, child_return; |
415 int root_x_return, root_y_return, win_x_return, win_y_return; | 434 int root_x_return, root_y_return, win_x_return, win_y_return; |
416 unsigned int mask_return; | 435 unsigned int mask_return; |
417 XQueryPointer(xdisplay_, | 436 XQueryPointer(xdisplay_, |
418 xwindow_, | 437 xwindow_, |
419 &root_return, | 438 &root_return, |
420 &child_return, | 439 &child_return, |
421 &root_x_return, &root_y_return, | 440 &root_x_return, &root_y_return, |
422 &win_x_return, &win_y_return, | 441 &win_x_return, &win_y_return, |
423 &mask_return); | 442 &mask_return); |
424 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), | 443 return gfx::Point(max(0, min(size_.width(), win_x_return)), |
425 max(0, min(bounds_.height(), win_y_return))); | 444 max(0, min(size_.height(), win_y_return))); |
445 } | |
446 | |
447 void DesktopHostLinux::HandleConfigureNotify(const gfx::Size& size) { | |
448 if (size_ != size) | |
449 size_ = size; | |
450 desktop_->OnHostResized(size); | |
426 } | 451 } |
427 | 452 |
428 bool DesktopHostLinux::IsWindowManagerPresent() { | 453 bool DesktopHostLinux::IsWindowManagerPresent() { |
429 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 454 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
430 // of WM_Sn selections (where n is a screen number). | 455 // of WM_Sn selections (where n is a screen number). |
431 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); | 456 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); |
432 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; | 457 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
433 } | 458 } |
434 | 459 |
435 } // namespace | 460 } // namespace |
436 | 461 |
437 // static | 462 // static |
438 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { | 463 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { |
439 return new DesktopHostLinux(bounds); | 464 return new DesktopHostLinux(bounds); |
440 } | 465 } |
441 | 466 |
442 } // namespace aura | 467 } // namespace aura |
OLD | NEW |