Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: ui/aura/desktop_host_linux.cc

Issue 8374005: aura: Try to make Linux host resize code more reliable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reset host win position when wm isn't running Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW
« ui/aura/desktop.h ('K') | « ui/aura/desktop.h ('k') | ui/aura/window_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698