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

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: update a few other gfx::Rect calls Created 9 years, 1 month 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
« no previous file with comments | « ui/aura/desktop_host.h ('k') | ui/aura/desktop_host_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Returns true if there's an X window manager present... in most cases. Some
202 // window managers (notably, ion3) don't implement enough of ICCCM for us to
203 // detect that they're there.
202 bool IsWindowManagerPresent(); 204 bool IsWindowManagerPresent();
203 205
204 Desktop* desktop_; 206 Desktop* desktop_;
205 207
206 // The display and the native X window hosting the desktop. 208 // The display and the native X window hosting the desktop.
207 Display* xdisplay_; 209 Display* xdisplay_;
208 ::Window xwindow_; 210 ::Window xwindow_;
209 211
210 // Current Aura cursor. 212 // Current Aura cursor.
211 gfx::NativeCursor current_cursor_; 213 gfx::NativeCursor current_cursor_;
212 214
213 // The size of |xwindow_|. 215 // The size of |xwindow_|.
214 gfx::Rect bounds_; 216 gfx::Size size_;
215
216 // True while we requested configure, but haven't recieved configure event
217 // yet.
218 bool expect_configure_event_;
219 217
220 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); 218 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux);
221 }; 219 };
222 220
223 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) 221 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds)
224 : desktop_(NULL), 222 : desktop_(NULL),
225 xdisplay_(NULL), 223 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
226 xwindow_(0), 224 xwindow_(0),
227 current_cursor_(aura::kCursorNull), 225 current_cursor_(aura::kCursorNull),
228 bounds_(bounds) { 226 size_(bounds.size()) {
229 // This assumes that the message-pump creates and owns the display.
230 xdisplay_ = base::MessagePumpX::GetDefaultXDisplay();
231
232 // Ingore the requested bounds and just cover the whole screen if there's no
233 // X window manager present.
234 if (!IsWindowManagerPresent())
235 bounds_.SetRect(
236 0, 0, DisplayWidth(xdisplay_, 0), DisplayHeight(xdisplay_, 0));
237
238 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), 227 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_),
239 bounds_.x(), bounds_.y(), 228 bounds.x(), bounds.y(),
240 bounds_.width(), bounds_.height(), 229 bounds.width(), bounds.height(),
241 0, 0, 0); 230 0, 0, 0);
242 231
243 long event_mask = ButtonPressMask | ButtonReleaseMask | 232 long event_mask = ButtonPressMask | ButtonReleaseMask |
244 KeyPressMask | KeyReleaseMask | 233 KeyPressMask | KeyReleaseMask |
245 ExposureMask | VisibilityChangeMask | 234 ExposureMask | VisibilityChangeMask |
246 StructureNotifyMask | PropertyChangeMask | 235 StructureNotifyMask | PropertyChangeMask |
247 PointerMotionMask; 236 PointerMotionMask;
248 XSelectInput(xdisplay_, xwindow_, event_mask); 237 XSelectInput(xdisplay_, xwindow_, event_mask);
249 XFlush(xdisplay_); 238 XFlush(xdisplay_);
250 239
(...skipping 24 matching lines...) Expand all
275 KeyEvent keyup_event(xev, false); 264 KeyEvent keyup_event(xev, false);
276 handled = desktop_->DispatchKeyEvent(&keyup_event); 265 handled = desktop_->DispatchKeyEvent(&keyup_event);
277 break; 266 break;
278 } 267 }
279 case ButtonPress: 268 case ButtonPress:
280 case ButtonRelease: { 269 case ButtonRelease: {
281 MouseEvent mouseev(xev); 270 MouseEvent mouseev(xev);
282 handled = desktop_->DispatchMouseEvent(&mouseev); 271 handled = desktop_->DispatchMouseEvent(&mouseev);
283 break; 272 break;
284 } 273 }
285 case MotionNotify: {
286 // Discard all but the most recent motion event that targets the same
287 // window with unchanged state.
288 XEvent last_event;
289 while (XPending(xev->xany.display)) {
290 XEvent next_event;
291 XPeekEvent(xev->xany.display, &next_event);
292 if (next_event.type == MotionNotify &&
293 next_event.xmotion.window == xev->xmotion.window &&
294 next_event.xmotion.subwindow == xev->xmotion.subwindow &&
295 next_event.xmotion.state == xev->xmotion.state) {
296 XNextEvent(xev->xany.display, &last_event);
297 xev = &last_event;
298 } else {
299 break;
300 }
301 }
302
303 MouseEvent mouseev(xev);
304 handled = desktop_->DispatchMouseEvent(&mouseev);
305 break;
306 }
307 case ConfigureNotify: { 274 case ConfigureNotify: {
308 DCHECK_EQ(xdisplay_, xev->xconfigure.display); 275 DCHECK_EQ(xdisplay_, xev->xconfigure.display);
309 DCHECK_EQ(xwindow_, xev->xconfigure.window); 276 DCHECK_EQ(xwindow_, xev->xconfigure.window);
310 DCHECK_EQ(xwindow_, xev->xconfigure.event); 277 DCHECK_EQ(xwindow_, xev->xconfigure.event);
311 278
312 // It's possible that the X window may be resized by some other means than 279 // It's possible that the X window may be resized by some other means than
313 // from within aura (e.g. the X window manager can change the size). Make 280 // from within aura (e.g. the X window manager can change the size). Make
314 // sure the desktop size is maintained properly. 281 // sure the desktop size is maintained properly.
315 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height); 282 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height);
316 if (bounds_.size() != size || expect_configure_event_) { 283 if (size_ != size) {
317 expect_configure_event_ = false; 284 size_ = size;
318 bounds_.set_size(size);
319 desktop_->OnHostResized(size); 285 desktop_->OnHostResized(size);
320 } 286 }
321 handled = true; 287 handled = true;
322 break; 288 break;
323 } 289 }
324
325 case GenericEvent: { 290 case GenericEvent: {
326 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 291 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
327 if (!factory->ShouldProcessXI2Event(xev)) 292 if (!factory->ShouldProcessXI2Event(xev))
328 break; 293 break;
329 294
330 // If this is a motion event we want to coalesce all pending motion 295 // If this is a motion event we want to coalesce all pending motion
331 // events that are at the top of the queue. 296 // events that are at the top of the queue.
332 XEvent last_event; 297 XEvent last_event;
333 int num_coalesced = 0; 298 int num_coalesced = 0;
334 if (xev->xgeneric.evtype == XI_Motion) { 299 if (xev->xgeneric.evtype == XI_Motion) {
(...skipping 25 matching lines...) Expand all
360 case ui::ET_UNKNOWN: 325 case ui::ET_UNKNOWN:
361 handled = false; 326 handled = false;
362 break; 327 break;
363 default: 328 default:
364 NOTREACHED(); 329 NOTREACHED();
365 } 330 }
366 331
367 // If we coalesced an event we need to free its cookie. 332 // If we coalesced an event we need to free its cookie.
368 if (num_coalesced > 0) 333 if (num_coalesced > 0)
369 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); 334 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
335 break;
336 }
337 case MapNotify: {
338 // If there's no window manager running, we need to assign the X input
339 // focus to our host window.
340 if (!IsWindowManagerPresent())
341 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
342 handled = true;
343 break;
344 }
345 case MotionNotify: {
346 // Discard all but the most recent motion event that targets the same
347 // window with unchanged state.
348 XEvent last_event;
349 while (XPending(xev->xany.display)) {
350 XEvent next_event;
351 XPeekEvent(xev->xany.display, &next_event);
352 if (next_event.type == MotionNotify &&
353 next_event.xmotion.window == xev->xmotion.window &&
354 next_event.xmotion.subwindow == xev->xmotion.subwindow &&
355 next_event.xmotion.state == xev->xmotion.state) {
356 XNextEvent(xev->xany.display, &last_event);
357 xev = &last_event;
358 } else {
359 break;
360 }
361 }
362
363 MouseEvent mouseev(xev);
364 handled = desktop_->DispatchMouseEvent(&mouseev);
365 break;
370 } 366 }
371 } 367 }
372 return handled ? EVENT_PROCESSED : EVENT_IGNORED; 368 return handled ? EVENT_PROCESSED : EVENT_IGNORED;
373 } 369 }
374 370
375 void DesktopHostLinux::SetDesktop(Desktop* desktop) { 371 void DesktopHostLinux::SetDesktop(Desktop* desktop) {
376 desktop_ = desktop; 372 desktop_ = desktop;
377 } 373 }
378 374
379 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() { 375 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() {
380 return xwindow_; 376 return xwindow_;
381 } 377 }
382 378
383 void DesktopHostLinux::Show() { 379 void DesktopHostLinux::Show() {
384 XMapWindow(xdisplay_, xwindow_); 380 XMapWindow(xdisplay_, xwindow_);
385
386 // If there's no window manager running, we need to assign the X input focus
387 // to our host window. (If there's no window manager running, it should also
388 // be safe to assume that the host window will have been mapped by the time
389 // that our SetInputFocus request is received.)
390 if (!IsWindowManagerPresent())
391 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
392
393 XFlush(xdisplay_);
394 } 381 }
395 382
396 gfx::Size DesktopHostLinux::GetSize() const { 383 gfx::Size DesktopHostLinux::GetSize() const {
397 return bounds_.size(); 384 return size_;
398 } 385 }
399 386
400 void DesktopHostLinux::SetSize(const gfx::Size& size) { 387 void DesktopHostLinux::SetSize(const gfx::Size& size) {
401 if (bounds_.size() == size) 388 if (size == size_)
402 return; 389 return;
403 expect_configure_event_ = true; 390
404 bounds_.set_size(size);
405 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); 391 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
392
393 // Assume that the resize will go through as requested, which should be the
394 // case if we're running without a window manager. If there's a window
395 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
396 // (possibly synthetic) ConfigureNotify about the actual size and correct
397 // |size_| later.
398 size_ = size;
399 desktop_->OnHostResized(size);
406 } 400 }
407 401
408 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { 402 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) {
409 if (current_cursor_ == cursor) 403 if (current_cursor_ == cursor)
410 return; 404 return;
411 current_cursor_ = cursor; 405 current_cursor_ = cursor;
412 // Custom web cursors are handled directly. 406 // Custom web cursors are handled directly.
413 if (cursor == kCursorCustom) 407 if (cursor == kCursorCustom)
414 return; 408 return;
415 int cursor_shape = CursorShapeFromNative(cursor); 409 int cursor_shape = CursorShapeFromNative(cursor);
416 ::Cursor xcursor = ui::GetXCursor(cursor_shape); 410 ::Cursor xcursor = ui::GetXCursor(cursor_shape);
417 XDefineCursor(xdisplay_, xwindow_, xcursor); 411 XDefineCursor(xdisplay_, xwindow_, xcursor);
418 } 412 }
419 413
420 gfx::Point DesktopHostLinux::QueryMouseLocation() { 414 gfx::Point DesktopHostLinux::QueryMouseLocation() {
421 ::Window root_return, child_return; 415 ::Window root_return, child_return;
422 int root_x_return, root_y_return, win_x_return, win_y_return; 416 int root_x_return, root_y_return, win_x_return, win_y_return;
423 unsigned int mask_return; 417 unsigned int mask_return;
424 XQueryPointer(xdisplay_, 418 XQueryPointer(xdisplay_,
425 xwindow_, 419 xwindow_,
426 &root_return, 420 &root_return,
427 &child_return, 421 &child_return,
428 &root_x_return, &root_y_return, 422 &root_x_return, &root_y_return,
429 &win_x_return, &win_y_return, 423 &win_x_return, &win_y_return,
430 &mask_return); 424 &mask_return);
431 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), 425 return gfx::Point(max(0, min(size_.width(), win_x_return)),
432 max(0, min(bounds_.height(), win_y_return))); 426 max(0, min(size_.height(), win_y_return)));
433 } 427 }
434 428
435 bool DesktopHostLinux::IsWindowManagerPresent() { 429 bool DesktopHostLinux::IsWindowManagerPresent() {
436 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 430 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
437 // of WM_Sn selections (where n is a screen number). 431 // of WM_Sn selections (where n is a screen number).
438 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); 432 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False);
439 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; 433 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None;
440 } 434 }
441 435
442 } // namespace 436 } // namespace
443 437
444 // static 438 // static
445 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { 439 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
446 return new DesktopHostLinux(bounds); 440 return new DesktopHostLinux(bounds);
447 } 441 }
448 442
443 // static
444 gfx::Size DesktopHost::GetNativeDisplaySize() {
445 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
446 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
447 }
448
449 } // namespace aura 449 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/desktop_host.h ('k') | ui/aura/desktop_host_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698