Home | History | Annotate | Download | only in native_viewport
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "mojo/services/native_viewport/native_viewport.h"
      6 
      7 #include <X11/Xlib.h>
      8 #include <X11/Xutil.h>
      9 
     10 #include "base/message_loop/message_loop.h"
     11 #include "ui/events/event.h"
     12 #include "ui/events/platform/platform_event_dispatcher.h"
     13 #include "ui/events/platform/platform_event_source.h"
     14 #include "ui/events/platform/x11/x11_event_source.h"
     15 #include "ui/gfx/rect.h"
     16 #include "ui/gfx/x/x11_types.h"
     17 
     18 namespace mojo {
     19 namespace services {
     20 
     21 class NativeViewportX11 : public NativeViewport,
     22                           public ui::PlatformEventDispatcher {
     23  public:
     24   NativeViewportX11(NativeViewportDelegate* delegate)
     25       : delegate_(delegate) {
     26   }
     27 
     28   virtual ~NativeViewportX11() {
     29     event_source_->RemovePlatformEventDispatcher(this);
     30 
     31     XDestroyWindow(gfx::GetXDisplay(), window_);
     32   }
     33 
     34  private:
     35   // Overridden from NativeViewport:
     36   virtual void Init(const gfx::Rect& bounds) OVERRIDE {
     37     XDisplay* display = gfx::GetXDisplay();
     38 
     39     XSetWindowAttributes swa;
     40     memset(&swa, 0, sizeof(swa));
     41     swa.override_redirect = False;
     42 
     43     bounds_ = bounds;
     44     window_ = XCreateWindow(
     45         display,
     46         DefaultRootWindow(display),
     47         bounds_.x(), bounds_.y(), bounds_.width(), bounds_.height(),
     48         0,  // border width
     49         CopyFromParent,  // depth
     50         InputOutput,
     51         CopyFromParent,  // visual
     52         CWBackPixmap | CWOverrideRedirect,
     53         &swa);
     54 
     55     atom_wm_protocols_ = XInternAtom(display, "WM_PROTOCOLS", 1);
     56     atom_wm_delete_window_ = XInternAtom(display, "WM_DELETE_WINDOW", 1);
     57     XSetWMProtocols(display, window_, &atom_wm_delete_window_, 1);
     58 
     59     event_source_ = ui::PlatformEventSource::CreateDefault();
     60     event_source_->AddPlatformEventDispatcher(this);
     61 
     62     long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
     63         KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask |
     64         ExposureMask | VisibilityChangeMask | StructureNotifyMask |
     65         PropertyChangeMask | PointerMotionMask;
     66     XSelectInput(display, window_, event_mask);
     67 
     68     // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
     69     // the desktop environment.
     70     XSetWMProperties(display, window_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
     71 
     72     // TODO(aa): Setup xinput2 events.
     73     // See desktop_aura/desktop_window_tree_host_x11.cc.
     74 
     75     delegate_->OnAcceleratedWidgetAvailable(window_);
     76   }
     77 
     78   virtual void Show() OVERRIDE {
     79     XDisplay* display = gfx::GetXDisplay();
     80     XMapWindow(display, window_);
     81     static_cast<ui::X11EventSource*>(
     82         event_source_.get())->BlockUntilWindowMapped(window_);
     83     XFlush(display);
     84   }
     85 
     86   virtual void Hide() OVERRIDE {
     87     XWithdrawWindow(gfx::GetXDisplay(), window_, 0);
     88   }
     89 
     90   virtual void Close() OVERRIDE {
     91     // TODO(beng): perform this in response to XWindow destruction.
     92     delegate_->OnDestroyed();
     93   }
     94 
     95   virtual gfx::Size GetSize() OVERRIDE {
     96     return bounds_.size();
     97   }
     98 
     99   virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE {
    100     NOTIMPLEMENTED();
    101   }
    102 
    103   virtual void SetCapture() OVERRIDE {
    104     NOTIMPLEMENTED();
    105   }
    106 
    107   virtual void ReleaseCapture() OVERRIDE {
    108     NOTIMPLEMENTED();
    109   }
    110 
    111   // ui::PlatformEventDispatcher:
    112   virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE {
    113     // TODO(aa): This is going to have to be thought through more carefully.
    114     // Which events are appropriate to pass to clients?
    115     switch (event->type) {
    116       case KeyPress:
    117       case KeyRelease:
    118       case ButtonPress:
    119       case ButtonRelease:
    120       case MotionNotify:
    121         return true;
    122       case ClientMessage:
    123         return event->xclient.message_type == atom_wm_protocols_;
    124       default:
    125         return false;
    126     }
    127   }
    128 
    129   virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE {
    130     if (event->type == ClientMessage) {
    131       Atom protocol = static_cast<Atom>(event->xclient.data.l[0]);
    132       if (protocol == atom_wm_delete_window_)
    133         delegate_->OnDestroyed();
    134     } else if (event->type == KeyPress || event->type == KeyRelease) {
    135       ui::KeyEvent key_event(event, false);
    136       delegate_->OnEvent(&key_event);
    137     } else if (event->type == ButtonPress || event->type == ButtonRelease ||
    138                event->type == MotionNotify) {
    139       ui::MouseEvent mouse_event(event);
    140       delegate_->OnEvent(&mouse_event);
    141     }
    142     return ui::POST_DISPATCH_NONE;
    143   }
    144 
    145   scoped_ptr<ui::PlatformEventSource> event_source_;
    146   NativeViewportDelegate* delegate_;
    147   gfx::Rect bounds_;
    148   XID window_;
    149   Atom atom_wm_protocols_;
    150   Atom atom_wm_delete_window_;
    151 
    152   DISALLOW_COPY_AND_ASSIGN(NativeViewportX11);
    153 };
    154 
    155 // static
    156 scoped_ptr<NativeViewport> NativeViewport::Create(
    157     shell::Context* context,
    158     NativeViewportDelegate* delegate) {
    159   return scoped_ptr<NativeViewport>(new NativeViewportX11(delegate)).Pass();
    160 }
    161 
    162 }  // namespace services
    163 }  // namespace mojo
    164