platform_view_glfw.cc 5.9 KB
Newer Older
1 2 3 4 5
// Copyright 2016 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 "flutter/shell/platform/linux/platform_view_glfw.h"
A
Adam Barth 已提交
6 7

#include "flutter/common/threads.h"
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
#include "flutter/shell/platform/linux/glfw_service_provider.h"

#include <GLFW/glfw3.h>

namespace shell {

inline PlatformViewGLFW* ToPlatformView(GLFWwindow* window) {
  return static_cast<PlatformViewGLFW*>(glfwGetWindowUserPointer(window));
}

PlatformViewGLFW::PlatformViewGLFW()
    : valid_(false), glfw_window_(nullptr), buttons_(0), weak_factory_(this) {
  if (!glfwInit()) {
    return;
  }

  glfw_window_ = glfwCreateWindow(640, 480, "Flutter", NULL, NULL);
  if (glfw_window_ == nullptr) {
    return;
  }

  glfwSetWindowUserPointer(glfw_window_, this);

  glfwSetWindowSizeCallback(
      glfw_window_, [](GLFWwindow* window, int width, int height) {
        ToPlatformView(window)->OnWindowSizeChanged(width, height);
      });

  glfwSetMouseButtonCallback(
      glfw_window_, [](GLFWwindow* window, int button, int action, int mods) {
        ToPlatformView(window)->OnMouseButtonChanged(button, action, mods);
      });

  glfwSetKeyCallback(glfw_window_, [](GLFWwindow* window, int key, int scancode,
                                      int action, int mods) {
    ToPlatformView(window)->OnKeyEvent(key, scancode, action, mods);
  });

  valid_ = true;
}

PlatformViewGLFW::~PlatformViewGLFW() {
  if (glfw_window_ != nullptr) {
    glfwSetWindowUserPointer(glfw_window_, nullptr);
    glfwDestroyWindow(glfw_window_);
    glfw_window_ = nullptr;
  }

  glfwTerminate();
}

void PlatformViewGLFW::ConnectToEngineAndSetupServices() {
  ConnectToEngine(mojo::GetProxy(&engine_));

  mojo::ServiceProviderPtr platform_service_provider;
  new GLFWServiceProvider(mojo::GetProxy(&platform_service_provider));

  sky::ServicesDataPtr services = sky::ServicesData::New();
  services->incoming_services = platform_service_provider.Pass();
  engine_->SetServices(services.Pass());
}

sky::SkyEnginePtr& PlatformViewGLFW::EngineProxy() {
  return engine_;
}

bool PlatformViewGLFW::IsValid() const {
  return valid_;
}

ftl::WeakPtr<PlatformView> PlatformViewGLFW::GetWeakViewPtr() {
  return weak_factory_.GetWeakPtr();
}

uint64_t PlatformViewGLFW::DefaultFramebuffer() const {
  // The default window bound FBO.
  return 0;
}

bool PlatformViewGLFW::ContextMakeCurrent() {
  glfwMakeContextCurrent(glfw_window_);
  return true;
}

bool PlatformViewGLFW::ResourceContextMakeCurrent() {
  // Resource loading contexts are not supported on this platform.
  return false;
}

bool PlatformViewGLFW::SwapBuffers() {
  glfwSwapBuffers(glfw_window_);
  return true;
}

void PlatformViewGLFW::RunFromSource(const std::string& main,
                                     const std::string& packages,
                                     const std::string& assets_directory) {}

void PlatformViewGLFW::OnWindowSizeChanged(int width, int height) {
  auto metrics = sky::ViewportMetrics::New();
  metrics->physical_width = width;
  metrics->physical_height = height;
  metrics->device_pixel_ratio = 1.0;
  engine_->OnViewportMetricsChanged(metrics.Pass());
}

void PlatformViewGLFW::OnMouseButtonChanged(int button, int action, int mods) {
A
Adam Barth 已提交
115
  blink::PointerData::Change change = blink::PointerData::Change::kCancel;
116 117
  if (action == GLFW_PRESS) {
    if (!buttons_) {
A
Adam Barth 已提交
118
      change = blink::PointerData::Change::kDown;
119 120 121 122 123
      glfwSetCursorPosCallback(
          glfw_window_, [](GLFWwindow* window, double x, double y) {
            ToPlatformView(window)->OnCursorPosChanged(x, y);
          });
    } else {
A
Adam Barth 已提交
124
      change = blink::PointerData::Change::kMove;
125 126 127 128 129 130 131 132
    }
    // GLFW's button order matches what we want:
    // https://github.com/flutter/engine/blob/master/sky/specs/pointer.md
    // http://www.glfw.org/docs/3.2/group__buttons.html
    buttons_ |= 1 << button;
  } else if (action == GLFW_RELEASE) {
    buttons_ &= ~(1 << button);
    if (!buttons_) {
A
Adam Barth 已提交
133
      change = blink::PointerData::Change::kUp;
134 135
      glfwSetCursorPosCallback(glfw_window_, nullptr);
    } else {
A
Adam Barth 已提交
136
      change = blink::PointerData::Change::kMove;
137 138 139 140 141 142
    }
  } else {
    DLOG(INFO) << "Unknown mouse action: " << action;
    return;
  }

A
Adam Barth 已提交
143 144
  double x = 0.0;
  double y = 0.0;
145 146 147 148
  glfwGetCursorPos(glfw_window_, &x, &y);

  base::TimeDelta time_stamp = base::TimeTicks::Now() - base::TimeTicks();

A
Adam Barth 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  blink::PointerData pointer_data;
  pointer_data.Clear();
  pointer_data.time_stamp = time_stamp.InMicroseconds();
  pointer_data.change = change;
  pointer_data.kind = blink::PointerData::DeviceKind::kMouse;
  pointer_data.physical_x = x;
  pointer_data.physical_y = y;
  pointer_data.buttons = buttons_;
  pointer_data.pressure = 1.0;
  pointer_data.pressure_max = 1.0;

  blink::Threads::UI()->PostTask(
      [ engine = engine().GetWeakPtr(), pointer_data ] {
        if (engine.get()) {
          blink::PointerDataPacket packet(1);
          packet.SetPointerData(0, pointer_data);
          engine->DispatchPointerDataPacket(packet);
        }
      });
168 169 170 171 172
}

void PlatformViewGLFW::OnCursorPosChanged(double x, double y) {
  base::TimeDelta time_stamp = base::TimeTicks::Now() - base::TimeTicks();

A
Adam Barth 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  blink::PointerData pointer_data;
  pointer_data.Clear();
  pointer_data.time_stamp = time_stamp.InMicroseconds();
  pointer_data.change = blink::PointerData::Change::kMove;
  pointer_data.kind = blink::PointerData::DeviceKind::kMouse;
  pointer_data.physical_x = x;
  pointer_data.physical_y = y;
  pointer_data.buttons = buttons_;
  pointer_data.pressure = 1.0;
  pointer_data.pressure_max = 1.0;

  blink::Threads::UI()->PostTask(
      [ engine = engine().GetWeakPtr(), pointer_data ] {
        if (engine.get()) {
          blink::PointerDataPacket packet(1);
          packet.SetPointerData(0, pointer_data);
          engine->DispatchPointerDataPacket(packet);
        }
      });
192 193 194 195 196 197
}

void PlatformViewGLFW::OnKeyEvent(int key, int scancode, int action, int mods) {
}

}  // namespace shell