X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fplatform%2Fsdl%2Fwindow.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fplatform%2Fsdl%2Fwindow.cpp;h=936eba1f2b19f09c0417c87959077dd9bd90b893;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/platform/sdl/window.cpp b/src/type3_AndroidCloud/anbox-master/src/anbox/platform/sdl/window.cpp new file mode 100644 index 0000000..936eba1 --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/src/anbox/platform/sdl/window.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#include "anbox/platform/sdl/window.h" +#include "anbox/wm/window_state.h" +#include "anbox/graphics/density.h" +#include "anbox/logger.h" + +#include + +#if defined(MIR_SUPPORT) +#include +#endif + +namespace { +constexpr const int window_resize_border{10}; +constexpr const int top_drag_area{42}; +constexpr const int button_size{32}; +constexpr const int button_margin{5}; +constexpr const int button_padding{0}; +} + +namespace anbox { +namespace platform { +namespace sdl { +Window::Id Window::Invalid{-1}; + +Window::Observer::~Observer() {} + +Window::Window(const std::shared_ptr &renderer, + const Id &id, const wm::Task::Id &task, + const std::shared_ptr &observer, + const graphics::Rect &frame, + const std::string &title, + bool resizable, + bool borderless) + : wm::Window(renderer, task, frame, title), + id_(id), + observer_(observer), + native_display_(0), + native_window_(0) { + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + + // NOTE: We don't furce GL initialization of the window as this will + // be take care of by the Renderer when we attach to it. On EGL + // initializing GL here will cause a surface to be created and the + // renderer will attempt to create one too which will not work as + // only a single surface per EGLNativeWindowType is supported. + std::uint32_t flags = 0; + if (borderless) + flags |= SDL_WINDOW_BORDERLESS; + if (resizable) + flags |= SDL_WINDOW_RESIZABLE; + + window_ = SDL_CreateWindow(title.c_str(), + frame.left(), frame.top(), + frame.width(), frame.height(), + flags); + if (!window_) { + const auto message = utils::string_format("Failed to create window: %s", SDL_GetError()); + BOOST_THROW_EXCEPTION(std::runtime_error(message)); + } + + // If we create a window with border (server-side decoration), We + // should not set hit test handler beacuse we don't need to simulate + // the behavior of the title bar and resize area. + if (borderless && utils::get_env_value("ANBOX_NO_SDL_WINDOW_HIT_TEST", "false") == "false") + if (SDL_SetWindowHitTest(window_, &Window::on_window_hit, this) < 0) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to register for window hit test")); + + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + SDL_GetWindowWMInfo(window_, &info); + switch (info.subsystem) { +#if defined(X11_SUPPORT) + case SDL_SYSWM_X11: + native_display_ = static_cast(info.info.x11.display); + native_window_ = static_cast(info.info.x11.window); + break; +#endif +#if defined(WAYLAND_SUPPORT) + case SDL_SYSWM_WAYLAND: + native_display_ = reinterpret_cast(info.info.wl.display); + native_window_ = reinterpret_cast(info.info.wl.surface); + break; +#endif +#if defined(MIR_SUPPORT) + case SDL_SYSWM_MIR: { + native_display_ = static_cast(mir_connection_get_egl_native_display(info.info.mir.connection)); + auto buffer_stream = mir_surface_get_buffer_stream(info.info.mir.surface); + native_window_ = reinterpret_cast(mir_buffer_stream_get_egl_native_window(buffer_stream)); + break; + } +#endif + default: + ERROR("Unknown subsystem (%d)", info.subsystem); + BOOST_THROW_EXCEPTION(std::runtime_error("SDL subsystem not supported")); + } + + SDL_ShowWindow(window_); +} + +Window::~Window() { + if (window_) SDL_DestroyWindow(window_); +} + +SDL_HitTestResult Window::on_window_hit(SDL_Window *window, const SDL_Point *pt, void *data) { + auto platform_window = reinterpret_cast(data); + + int w = 0, h = 0; + SDL_GetWindowSize(window, &w, &h); + + const auto border_size = graphics::dp_to_pixel(window_resize_border); + const auto top_drag_area_height = graphics::dp_to_pixel(top_drag_area); + const auto button_area_width = graphics::dp_to_pixel(button_size + button_padding * 2 + button_margin * 2); + const auto flags = SDL_GetWindowFlags(window); + + if (flags & SDL_WINDOW_FULLSCREEN) + return SDL_HITTEST_NORMAL; + + if (!(flags & SDL_WINDOW_RESIZABLE)) { + if (pt->y < border_size) + return SDL_HITTEST_DRAGGABLE; + else + return SDL_HITTEST_NORMAL; + } + + if (pt->y < top_drag_area_height) { + if (pt->x > w - button_area_width && pt->x < w) { + platform_window->close(); + return SDL_HITTEST_NORMAL; + } else if (pt->x > w - button_area_width * 2 && pt->x < w - button_area_width) { + platform_window->switch_window_state(); + return SDL_HITTEST_NORMAL; + } + return SDL_HITTEST_DRAGGABLE; + } + + if (flags & SDL_WINDOW_MAXIMIZED) + return SDL_HITTEST_NORMAL; + + if (pt->x < border_size && pt->y < border_size) + return SDL_HITTEST_RESIZE_TOPLEFT; + else if (pt->x > border_size && pt->x < w - border_size && pt->y < border_size) + return SDL_HITTEST_RESIZE_TOP; + else if (pt->x > w - border_size && pt->y < border_size) + return SDL_HITTEST_RESIZE_TOPRIGHT; + else if (pt->x > w - border_size && pt->y > border_size && pt->y < h - border_size) + return SDL_HITTEST_RESIZE_RIGHT; + else if (pt->x > w - border_size && pt->y > h - border_size) + return SDL_HITTEST_RESIZE_BOTTOMRIGHT; + else if (pt->x < w - border_size && pt->x > border_size && pt->y > h - border_size) + return SDL_HITTEST_RESIZE_BOTTOM; + else if (pt->x < border_size && pt->y > h - border_size) + return SDL_HITTEST_RESIZE_BOTTOMLEFT; + else if (pt->x < border_size && pt->y < h - border_size && pt->y > border_size) + return SDL_HITTEST_RESIZE_LEFT; + + return SDL_HITTEST_NORMAL; +} + +void Window::close() { + if (observer_) + observer_->window_deleted(id_); +} + +void Window::switch_window_state() { + const auto flags = SDL_GetWindowFlags(window_); + if (flags & SDL_WINDOW_MAXIMIZED) + SDL_RestoreWindow(window_); + else + SDL_MaximizeWindow(window_); +} + +void Window::process_event(const SDL_Event &event) { + switch (event.window.event) { + case SDL_WINDOWEVENT_FOCUS_GAINED: + if (observer_) observer_->window_wants_focus(id_); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + break; + // Not need to listen for SDL_WINDOWEVENT_RESIZED here as the + // SDL_WINDOWEVENT_SIZE_CHANGED is always sent. + case SDL_WINDOWEVENT_SIZE_CHANGED: + if (observer_) + observer_->window_resized(id_, event.window.data1, event.window.data2); + break; + case SDL_WINDOWEVENT_MOVED: + if (observer_) + observer_->window_moved(id_, event.window.data1, event.window.data2); + break; + case SDL_WINDOWEVENT_SHOWN: + break; + case SDL_WINDOWEVENT_HIDDEN: + break; + case SDL_WINDOWEVENT_CLOSE: + close(); + break; + default: + break; + } +} + +EGLNativeWindowType Window::native_handle() const { return native_window_; } + +Window::Id Window::id() const { return id_; } + +std::uint32_t Window::window_id() const { return SDL_GetWindowID(window_); } +} // namespace sdl +} // namespace platform +} // namespace anbox