diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-15 17:47:10 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-15 17:47:10 +0000 |
commit | 31fbcd953ebbfec6489ef4076cf816a56c4eab30 (patch) | |
tree | 49c6ec09149f1678b95e0ea298157203aab52025 /ui/platform_window | |
parent | 559f2b2959879ce098e03454df8ccc7b8736b7cd (diff) | |
download | chromium_src-31fbcd953ebbfec6489ef4076cf816a56c4eab30.zip chromium_src-31fbcd953ebbfec6489ef4076cf816a56c4eab30.tar.gz chromium_src-31fbcd953ebbfec6489ef4076cf816a56c4eab30.tar.bz2 |
ui/platform_window: Introduce PlatformWindow for windowing primitives.
Instead of implementing the native windowing primitives for aura, mojo, ozone
etc., have a single implementation in ui/platform_window, and use that in the
rest of the places. To start off, this CL provides an X11 implementation of
the new interface, and use it for mojo native-viewport.
BUG=361137
R=ben@chromium.org, spang@chromium.org
Review URL: https://codereview.chromium.org/391583002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283213 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/platform_window')
-rw-r--r-- | ui/platform_window/DEPS | 3 | ||||
-rw-r--r-- | ui/platform_window/platform_window.gyp | 19 | ||||
-rw-r--r-- | ui/platform_window/platform_window.h | 47 | ||||
-rw-r--r-- | ui/platform_window/platform_window_delegate.h | 52 | ||||
-rw-r--r-- | ui/platform_window/platform_window_export.h | 29 | ||||
-rw-r--r-- | ui/platform_window/x11/DEPS | 4 | ||||
-rw-r--r-- | ui/platform_window/x11/x11_window.cc | 302 | ||||
-rw-r--r-- | ui/platform_window/x11/x11_window.gyp | 29 | ||||
-rw-r--r-- | ui/platform_window/x11/x11_window.h | 66 | ||||
-rw-r--r-- | ui/platform_window/x11/x11_window_export.h | 30 |
10 files changed, 581 insertions, 0 deletions
diff --git a/ui/platform_window/DEPS b/ui/platform_window/DEPS new file mode 100644 index 0000000..b273ae3 --- /dev/null +++ b/ui/platform_window/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ui/gfx", +] diff --git a/ui/platform_window/platform_window.gyp b/ui/platform_window/platform_window.gyp new file mode 100644 index 0000000..15162bf --- /dev/null +++ b/ui/platform_window/platform_window.gyp @@ -0,0 +1,19 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [{ + 'target_name': 'platform_window', + 'type': '<(component)', + 'defines': [ 'PLATFORM_WINDOW_IMPLEMENTATION' ], + 'sources': [ + 'platform_window.h', + 'platform_window_delegate.h', + 'platform_window_export.h', + ], + }], +} diff --git a/ui/platform_window/platform_window.h b/ui/platform_window/platform_window.h new file mode 100644 index 0000000..755e1f1 --- /dev/null +++ b/ui/platform_window/platform_window.h @@ -0,0 +1,47 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_H_ + +#include "base/memory/scoped_ptr.h" +#include "ui/platform_window/platform_window_export.h" + +namespace gfx { +class Rect; +} + +namespace ui { + +class PlatformWindowDelegate; + +// Platform window. +// +// Each instance of PlatformWindow represents a single window in the +// underlying platform windowing system (i.e. X11/Win/OSX). +class PLATFORM_WINDOW_EXPORT PlatformWindow { + public: + virtual ~PlatformWindow() {} + + virtual void Show() = 0; + virtual void Hide() = 0; + virtual void Close() = 0; + + // Sets and gets the bounds of the platform-window. Note that the bounds is in + // physical pixel coordinates. + virtual void SetBounds(const gfx::Rect& bounds) = 0; + virtual gfx::Rect GetBounds() = 0; + + virtual void SetCapture() = 0; + virtual void ReleaseCapture() = 0; + + virtual void ToggleFullscreen() = 0; + virtual void Maximize() = 0; + virtual void Minimize() = 0; + virtual void Restore() = 0; +}; + +} // namespace ui + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_H_ diff --git a/ui/platform_window/platform_window_delegate.h b/ui/platform_window/platform_window_delegate.h new file mode 100644 index 0000000..bf5d0a1 --- /dev/null +++ b/ui/platform_window/platform_window_delegate.h @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_ + +#include "ui/gfx/native_widget_types.h" +#include "ui/platform_window/platform_window_export.h" + +namespace gfx { +class Rect; +} + +namespace ui { + +class Event; + +enum PlatformWindowState { + PLATFORM_WINDOW_STATE_UNKNOWN, + PLATFORM_WINDOW_STATE_MAXIMIZED, + PLATFORM_WINDOW_STATE_MINIMIZED, + PLATFORM_WINDOW_STATE_NORMAL, + PLATFORM_WINDOW_STATE_FULLSCREEN, +}; + +class PLATFORM_WINDOW_EXPORT PlatformWindowDelegate { + public: + virtual ~PlatformWindowDelegate() {} + + // Note that |new_bounds| is in physical screen coordinates. + virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0; + + // Note that |damaged_region| is in the platform-window's coordinates, in + // physical pixels. + virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0; + + virtual void DispatchEvent(Event* event) = 0; + + virtual void OnCloseRequest() = 0; + virtual void OnClosed() = 0; + + virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0; + + virtual void OnLostCapture() = 0; + + virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0; +}; + +} // namespace ui + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_ diff --git a/ui/platform_window/platform_window_export.h b/ui/platform_window/platform_window_export.h new file mode 100644 index 0000000..45f434a --- /dev/null +++ b/ui/platform_window/platform_window_export.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_EXPORT_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(PLATFORM_WINDOW_IMPLEMENTATION) +#define PLATFORM_WINDOW_EXPORT __declspec(dllexport) +#else +#define PLATFORM_WINDOW_EXPORT __declspec(dllimport) +#endif // defined(PLATFORM_WINDOW_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(PLATFORM_WINDOW_IMPLEMENTATION) +#define PLATFORM_WINDOW_EXPORT __attribute__((visibility("default"))) +#else +#define PLATFORM_WINDOW_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define PLATFORM_WINDOW_EXPORT +#endif + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_EXPORT_H_ diff --git a/ui/platform_window/x11/DEPS b/ui/platform_window/x11/DEPS new file mode 100644 index 0000000..8cb61f5 --- /dev/null +++ b/ui/platform_window/x11/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+ui/events", + "+ui/gfx", +] diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc new file mode 100644 index 0000000..ce75a17 --- /dev/null +++ b/ui/platform_window/x11/x11_window.cc @@ -0,0 +1,302 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/platform_window/x11/x11_window.h" + +#include <X11/extensions/XInput2.h> +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/events/platform/platform_event_source.h" +#include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/x11_types.h" +#include "ui/platform_window/platform_window_delegate.h" + +namespace ui { + +namespace { + +const char* kAtomsToCache[] = { + "WM_DELETE_WINDOW", + "_NET_WM_PING", + "_NET_WM_PID", + NULL +}; + +XID FindXEventTarget(XEvent* xevent) { + XID target = xevent->xany.window; + if (xevent->type == GenericEvent) + target = static_cast<XIDeviceEvent*>(xevent->xcookie.data)->event; + return target; +} + +} // namespace + +X11Window::X11Window(PlatformWindowDelegate* delegate) + : delegate_(delegate), + xdisplay_(gfx::GetXDisplay()), + xwindow_(None), + xroot_window_(DefaultRootWindow(xdisplay_)), + atom_cache_(xdisplay_, kAtomsToCache), + window_mapped_(false) { + CHECK(delegate_); +} + +X11Window::~X11Window() { + Destroy(); +} + +void X11Window::Destroy() { + if (xwindow_ == None) + return; + + // Stop processing events. + PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); + XDestroyWindow(xdisplay_, xwindow_); + xwindow_ = None; +} + +void X11Window::Show() { + if (window_mapped_) + return; + + CHECK(PlatformEventSource::GetInstance()); + PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); + + XSetWindowAttributes swa; + memset(&swa, 0, sizeof(swa)); + swa.background_pixmap = None; + swa.override_redirect = False; + xwindow_ = XCreateWindow(xdisplay_, + xroot_window_, + requested_bounds_.x(), + requested_bounds_.y(), + requested_bounds_.width(), + requested_bounds_.height(), + 0, // border width + CopyFromParent, // depth + InputOutput, + CopyFromParent, // visual + CWBackPixmap | CWOverrideRedirect, + &swa); + + long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | + KeyPressMask | KeyReleaseMask | EnterWindowMask | + LeaveWindowMask | ExposureMask | VisibilityChangeMask | + StructureNotifyMask | PropertyChangeMask | + PointerMotionMask; + XSelectInput(xdisplay_, xwindow_, event_mask); + + unsigned char mask[XIMaskLen(XI_LASTEVENT)]; + memset(mask, 0, sizeof(mask)); + + XISetMask(mask, XI_TouchBegin); + XISetMask(mask, XI_TouchUpdate); + XISetMask(mask, XI_TouchEnd); + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); + + XIEventMask evmask; + evmask.deviceid = XIAllDevices; + evmask.mask_len = sizeof(mask); + evmask.mask = mask; + XISelectEvents(xdisplay_, xwindow_, &evmask, 1); + XFlush(xdisplay_); + + ::Atom protocols[2]; + protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); + protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); + XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); + + // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with + // the desktop environment. + XSetWMProperties( + xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL); + + // Likewise, the X server needs to know this window's pid so it knows which + // program to kill if the window hangs. + // XChangeProperty() expects "pid" to be long. + COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t), pid_t_bigger_than_long); + long pid = getpid(); + XChangeProperty(xdisplay_, + xwindow_, + atom_cache_.GetAtom("_NET_WM_PID"), + XA_CARDINAL, + 32, + PropModeReplace, + reinterpret_cast<unsigned char*>(&pid), + 1); + // Before we map the window, set size hints. Otherwise, some window managers + // will ignore toplevel XMoveWindow commands. + XSizeHints size_hints; + size_hints.flags = PPosition | PWinGravity; + size_hints.x = requested_bounds_.x(); + size_hints.y = requested_bounds_.y(); + // Set StaticGravity so that the window position is not affected by the + // frame width when running with window manager. + size_hints.win_gravity = StaticGravity; + XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); + + delegate_->OnAcceleratedWidgetAvailable(xwindow_); + + XMapWindow(xdisplay_, xwindow_); + + // We now block until our window is mapped. Some X11 APIs will crash and + // burn if passed |xwindow_| before the window is mapped, and XMapWindow is + // asynchronous. + if (X11EventSource::GetInstance()) + X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_); + window_mapped_ = true; +} + +void X11Window::Hide() { + if (!window_mapped_) + return; + XWithdrawWindow(xdisplay_, xwindow_, 0); + window_mapped_ = false; +} + +void X11Window::Close() { + Destroy(); +} + +void X11Window::SetBounds(const gfx::Rect& bounds) { + requested_bounds_ = bounds; + if (!window_mapped_) + return; + XWindowChanges changes = {0}; + unsigned value_mask = CWX | CWY | CWWidth | CWHeight; + changes.x = bounds.x(); + changes.y = bounds.y(); + changes.width = bounds.width(); + changes.height = bounds.height(); + XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); +} + +gfx::Rect X11Window::GetBounds() { + return confirmed_bounds_; +} + +void X11Window::SetCapture() {} + +void X11Window::ReleaseCapture() {} + +void X11Window::ToggleFullscreen() {} + +void X11Window::Maximize() {} + +void X11Window::Minimize() {} + +void X11Window::Restore() {} + +bool X11Window::CanDispatchEvent(const PlatformEvent& event) { + return FindXEventTarget(event) == xwindow_; +} + +uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { + XEvent* xev = event; + switch (xev->type) { + case EnterNotify: { + // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is + // not real mouse move event. + MouseEvent mouse_event(xev); + CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type()); + mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED); + delegate_->DispatchEvent(&mouse_event); + break; + } + case LeaveNotify: { + MouseEvent mouse_event(xev); + delegate_->DispatchEvent(&mouse_event); + break; + } + + case Expose: { + gfx::Rect damage_rect(xev->xexpose.x, + xev->xexpose.y, + xev->xexpose.width, + xev->xexpose.height); + delegate_->OnDamageRect(damage_rect); + break; + } + + case KeyPress: + case KeyRelease: { + KeyEvent key_event(xev, false); + delegate_->DispatchEvent(&key_event); + break; + } + + case ButtonPress: + case ButtonRelease: { + switch (EventTypeFromNative(xev)) { + case ET_MOUSEWHEEL: { + MouseWheelEvent mouseev(xev); + delegate_->DispatchEvent(&mouseev); + break; + } + case ET_MOUSE_PRESSED: + case ET_MOUSE_RELEASED: { + MouseEvent mouseev(xev); + delegate_->DispatchEvent(&mouseev); + break; + } + case ET_UNKNOWN: + // No event is created for X11-release events for mouse-wheel + // buttons. + break; + default: + NOTREACHED(); + } + break; + } + + case FocusOut: + if (xev->xfocus.mode != NotifyGrab) + delegate_->OnLostCapture(); + break; + + case ConfigureNotify: { + DCHECK_EQ(xwindow_, xev->xconfigure.event); + DCHECK_EQ(xwindow_, xev->xconfigure.window); + gfx::Rect bounds(xev->xconfigure.x, + xev->xconfigure.y, + xev->xconfigure.width, + xev->xconfigure.height); + if (confirmed_bounds_ != bounds) { + confirmed_bounds_ = bounds; + delegate_->OnBoundsChanged(confirmed_bounds_); + } + break; + } + + case ClientMessage: { + Atom message = static_cast<Atom>(xev->xclient.data.l[0]); + if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) { + delegate_->OnCloseRequest(); + } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) { + XEvent reply_event = *xev; + reply_event.xclient.window = xroot_window_; + + XSendEvent(xdisplay_, + reply_event.xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &reply_event); + XFlush(xdisplay_); + } + break; + } + } + return POST_DISPATCH_STOP_PROPAGATION; +} + +} // namespace ui diff --git a/ui/platform_window/x11/x11_window.gyp b/ui/platform_window/x11/x11_window.gyp new file mode 100644 index 0000000..efb86c8 --- /dev/null +++ b/ui/platform_window/x11/x11_window.gyp @@ -0,0 +1,29 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + 'use_x11': 1, + }, + 'targets': [{ + 'target_name': 'x11_window', + 'type': '<(component)', + 'dependencies': [ + '../../../base/base.gyp:base', + '../../../build/linux/system.gyp:x11', + '../../../skia/skia.gyp:skia', + '../../events/events.gyp:events', + '../../events/platform/x11/x11_events_platform.gyp:x11_events_platform', + '../../gfx/x/gfx_x11.gyp:gfx_x11', + '../platform_window.gyp:platform_window', + ], + 'defines': [ 'X11_WINDOW_IMPLEMENTATION' ], + 'sources': [ + 'x11_window.cc', + 'x11_window.h', + 'x11_window_export.h', + ], + }], +} diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h new file mode 100644 index 0000000..8e49bcf --- /dev/null +++ b/ui/platform_window/x11/x11_window.h @@ -0,0 +1,66 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_ +#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_ + +#include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/x/x11_atom_cache.h" +#include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_delegate.h" +#include "ui/platform_window/x11/x11_window_export.h" + +typedef struct _XDisplay XDisplay; +typedef unsigned long XID; + +namespace ui { + +class X11_WINDOW_EXPORT X11Window : public PlatformWindow, + public PlatformEventDispatcher { + public: + explicit X11Window(PlatformWindowDelegate* delegate); + virtual ~X11Window(); + + private: + void Destroy(); + + // PlatformWindow: + virtual void Show() OVERRIDE; + virtual void Hide() OVERRIDE; + virtual void Close() OVERRIDE; + virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE; + virtual gfx::Rect GetBounds() OVERRIDE; + virtual void SetCapture() OVERRIDE; + virtual void ReleaseCapture() OVERRIDE; + virtual void ToggleFullscreen() OVERRIDE; + virtual void Maximize() OVERRIDE; + virtual void Minimize() OVERRIDE; + virtual void Restore() OVERRIDE; + + // PlatformEventDispatcher: + virtual bool CanDispatchEvent(const PlatformEvent& event) OVERRIDE; + virtual uint32_t DispatchEvent(const PlatformEvent& event) OVERRIDE; + + PlatformWindowDelegate* delegate_; + + XDisplay* xdisplay_; + XID xwindow_; + XID xroot_window_; + X11AtomCache atom_cache_; + + // Setting the bounds is an asynchronous operation in X11. |requested_bounds_| + // is the bounds requested using XConfigureWindow, and |confirmed_bounds_| is + // the bounds the X11 server has set on the window. + gfx::Rect requested_bounds_; + gfx::Rect confirmed_bounds_; + + bool window_mapped_; + + DISALLOW_COPY_AND_ASSIGN(X11Window); +}; + +} // namespace ui + +#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_ diff --git a/ui/platform_window/x11/x11_window_export.h b/ui/platform_window/x11/x11_window_export.h new file mode 100644 index 0000000..ab8c004 --- /dev/null +++ b/ui/platform_window/x11/x11_window_export.h @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_EXPORT_H_ +#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(X11_WINDOW_IMPLEMENTATION) +#define X11_WINDOW_EXPORT __declspec(dllexport) +#else +#define X11_WINDOW_EXPORT __declspec(dllimport) +#endif // defined(X11_WINDOW_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(X11_WINDOW_IMPLEMENTATION) +#define X11_WINDOW_EXPORT __attribute__((visibility("default"))) +#else +#define X11_WINDOW_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define X11_WINDOW_EXPORT +#endif + +#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_EXPORT_H + |