diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3e2817b..82b130c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -126,6 +126,7 @@ set(SOURCES anbox/graphics/buffer_queue.cpp anbox/graphics/buffered_io_stream.cpp anbox/graphics/gl_renderer_server.cpp + anbox/graphics/density.cpp anbox/graphics/density.h anbox/graphics/rect.cpp anbox/graphics/layer_composer.cpp diff --git a/src/anbox/graphics/density.cpp b/src/anbox/graphics/density.cpp new file mode 100644 index 0000000..3ce2bf7 --- /dev/null +++ b/src/anbox/graphics/density.cpp @@ -0,0 +1,30 @@ +/* + * 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/graphics/density.h" + +namespace anbox { +namespace graphics { +DensityType current_density() { + return DensityType::medium; +} + +int dp_to_pixel(unsigned int dp) { + return dp * static_cast(current_density()) / static_cast(DensityType::medium); +} +} // namespace graphics +} // namespace anbox diff --git a/src/anbox/graphics/density.h b/src/anbox/graphics/density.h index 4338dc4..f662caa 100644 --- a/src/anbox/graphics/density.h +++ b/src/anbox/graphics/density.h @@ -35,6 +35,9 @@ enum class DensityType { xhigh = 360, xxhigh = 480, }; + +DensityType current_density(); +int dp_to_pixel(unsigned int dp); } // namespace graphics } // namespace anbox diff --git a/src/anbox/platform/sdl/window.cpp b/src/anbox/platform/sdl/window.cpp index 1343d5b..8bb5c26 100644 --- a/src/anbox/platform/sdl/window.cpp +++ b/src/anbox/platform/sdl/window.cpp @@ -16,8 +16,9 @@ */ #include "anbox/platform/sdl/window.h" -#include "anbox/logger.h" #include "anbox/wm/window_state.h" +#include "anbox/graphics/density.h" +#include "anbox/logger.h" #include @@ -25,6 +26,14 @@ #include #endif +namespace { +constexpr const int window_resize_border{30}; +constexpr const int top_drag_area{50}; +constexpr const int button_size{32}; +constexpr const int button_margin{5}; +constexpr const int button_padding{4}; +} + namespace anbox { namespace platform { namespace sdl { @@ -43,15 +52,14 @@ Window::Window(const std::shared_ptr &renderer, observer_(observer), native_display_(0), native_window_(0) { - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + 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; + std::uint32_t flags = SDL_WINDOW_BORDERLESS; if (resizable) flags |= SDL_WINDOW_RESIZABLE; @@ -64,6 +72,9 @@ Window::Window(const std::shared_ptr &renderer, BOOST_THROW_EXCEPTION(std::runtime_error(message)); } + 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); @@ -92,6 +103,58 @@ 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); + + 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; + } else if (pt->x < border_size && pt->y < border_size) + return SDL_HITTEST_RESIZE_TOPLEFT; + else if (pt->x > window_resize_border && 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: @@ -114,7 +177,10 @@ void Window::process_event(const SDL_Event &event) { case SDL_WINDOWEVENT_HIDDEN: break; case SDL_WINDOWEVENT_CLOSE: - if (observer_) observer_->window_deleted(id_); + if (observer_) + observer_->window_deleted(id_); + + close(); break; default: break; diff --git a/src/anbox/platform/sdl/window.h b/src/anbox/platform/sdl/window.h index b44a7cb..6849425 100644 --- a/src/anbox/platform/sdl/window.h +++ b/src/anbox/platform/sdl/window.h @@ -62,6 +62,11 @@ class Window : public std::enable_shared_from_this, public wm::Window { std::uint32_t window_id() const; private: + static SDL_HitTestResult on_window_hit(SDL_Window *window, const SDL_Point *pt, void *data); + + void close(); + void switch_window_state(); + Id id_; std::shared_ptr observer_; EGLNativeDisplayType native_display_; diff --git a/src/anbox/qemu/boot_properties_message_processor.cpp b/src/anbox/qemu/boot_properties_message_processor.cpp index 783b568..897bc00 100644 --- a/src/anbox/qemu/boot_properties_message_processor.cpp +++ b/src/anbox/qemu/boot_properties_message_processor.cpp @@ -35,10 +35,8 @@ void BootPropertiesMessageProcessor::handle_command( void BootPropertiesMessageProcessor::list_properties() { std::vector properties = { // TODO(morphis): Using HDPI here for now but should be adjusted to the - // device - // we're running on. - utils::string_format("ro.sf.lcd_density=%d", - static_cast(graphics::DensityType::medium)), + // device we're running on + utils::string_format("ro.sf.lcd_density=%d", static_cast(graphics::current_density())), }; for (const auto &prop : properties) {