diff --git a/CMakeLists.txt b/CMakeLists.txt index 12f01f6d2..9d282b4cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,6 @@ enable_testing() # CMakeCache.txt) option(WITH_WEBP_SUPPORT "Enable support to load/save .webp files" on) -option(WITH_GTK_FILE_DIALOG_SUPPORT "Enable support for the experimental native GTK File Dialog" off) option(WITH_DESKTOP_INTEGRATION "Enable desktop integration modules" off) option(WITH_QT_THUMBNAILER "Enable kde5/qt5 thumnailer" off) @@ -92,7 +91,7 @@ else() endif() # Check valid gtk + libpng combination -if(WITH_GTK_FILE_DIALOG_SUPPORT) +if(LAF_OS_WITH_GTK) if(NOT USE_SHARED_LIBPNG) message(FATAL_ERROR "Cannot compile with gtk and static libpng, set USE_SHARED_LIBPNG=ON") endif() diff --git a/cmake/FindTests.cmake b/cmake/FindTests.cmake index 866370f8b..eeb354d44 100644 --- a/cmake/FindTests.cmake +++ b/cmake/FindTests.cmake @@ -8,8 +8,8 @@ function(find_tests dir dependencies) # Add gtest include directory so we can #include in tests source code include_directories(${CMAKE_SOURCE_DIR}/third_party/gtest/include) - # See if the test is linked with "os-lib" library. - list(FIND dependencies os-lib link_with_os) + # See if the test is linked with "laf-os" library. + list(FIND dependencies laf-os link_with_os) if(link_with_os) set(extra_definitions -DLINKED_WITH_OS_LIBRARY) endif() diff --git a/laf b/laf index 2068f6532..f2a95de10 160000 --- a/laf +++ b/laf @@ -1 +1 @@ -Subproject commit 2068f653224edfbfafc00a40a1d72a8e022d00d8 +Subproject commit f2a95de10e51b0dffdc3a14199fa489baf086c22 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2531c1e4..5eb5aac89 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,12 +102,9 @@ add_subdirectory(filters) add_subdirectory(fixmath) add_subdirectory(flic) add_subdirectory(gen) -add_subdirectory(gfx) add_subdirectory(net) add_subdirectory(render) add_subdirectory(dio) -add_subdirectory(ft) -add_subdirectory(os) add_subdirectory(ui) if(ENABLE_SCRIPTING) @@ -207,7 +204,6 @@ install(DIRECTORY ../data if(ENABLE_TESTS) include(FindTests) - find_tests(gfx gfx-lib) find_tests(doc doc-lib) find_tests(render render-lib) find_tests(ui ui-lib) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index d9e3895b1..8f6108433 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -575,10 +575,11 @@ target_link_libraries(app-lib filters-lib fixmath-lib flic-lib - gfx-lib + laf-gfx net-lib render-lib - os-lib + laf-ft + laf-os ui-lib undo ${CMARK_LIBRARIES} diff --git a/src/app/color.cpp b/src/app/color.cpp index 9922dd7b9..f06a1a200 100644 --- a/src/app/color.cpp +++ b/src/app/color.cpp @@ -12,6 +12,7 @@ #include "app/color_utils.h" #include "app/modules/palettes.h" +#include "base/debug.h" #include "doc/image.h" #include "doc/palette.h" #include "doc/primitives.h" @@ -80,7 +81,7 @@ Color Color::fromGray(int g, int a) // static Color Color::fromIndex(int index) { - assert(index >= 0); + ASSERT(index >= 0); Color color(Color::IndexType); color.m_value.index = index; diff --git a/src/doc/CMakeLists.txt b/src/doc/CMakeLists.txt index cb33240a7..d69ee1890 100644 --- a/src/doc/CMakeLists.txt +++ b/src/doc/CMakeLists.txt @@ -70,7 +70,7 @@ add_library(doc-lib # TODO Remove 'os' as dependency and move conversion_to_surface.cpp/h files # to other library/layer (render-lib? new conversion-lib?) target_link_libraries(doc-lib - os-lib - gfx-lib + laf-os + laf-gfx fixmath-lib laf-base) diff --git a/src/ft/CMakeLists.txt b/src/ft/CMakeLists.txt deleted file mode 100644 index 43799ebeb..000000000 --- a/src/ft/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Aseprite FreeType Wrapper -# Copyright (C) 2017 David Capello - -add_library(ft-lib - lib.cpp - stream.cpp) - -target_link_libraries(ft-lib - laf-base - ${FREETYPE_LIBRARIES} - ${HARFBUZZ_LIBRARIES}) diff --git a/src/ft/LICENSE.txt b/src/ft/LICENSE.txt deleted file mode 100644 index 7854a820d..000000000 --- a/src/ft/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2016-2017 David Capello - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/ft/README.md b/src/ft/README.md deleted file mode 100644 index 0ae4d6d4f..000000000 --- a/src/ft/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Aseprite FreeType Wrapper -*Copyright (C) 2016-2017 David Capello* - -> Distributed under [MIT license](LICENSE.txt) diff --git a/src/ft/algorithm.h b/src/ft/algorithm.h deleted file mode 100644 index 206581e35..000000000 --- a/src/ft/algorithm.h +++ /dev/null @@ -1,175 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_ALGORITHM_H_INCLUDED -#define FT_ALGORITHM_H_INCLUDED -#pragma once - -#include "base/string.h" -#include "ft/freetype_headers.h" -#include "ft/hb_shaper.h" -#include "gfx/rect.h" - -namespace ft { - - template - class DefaultShaper { - public: - typedef typename FaceFT::Glyph Glyph; - - DefaultShaper(FaceFT& face) : m_face(face) { - } - - bool initialize(const base::utf8_const_iterator& it, - const base::utf8_const_iterator& end) { - m_begin = m_it = it; - m_end = end; - return (m_it != end); - } - - bool nextChar() { - ++m_it; - return (m_it != m_end); - } - - int unicodeChar() const { - return *m_it; - } - - int charIndex() { - return m_it - m_begin; - } - - unsigned int glyphIndex() { - return m_face.cache().getGlyphIndex(m_face, unicodeChar()); - } - - void glyphOffsetXY(Glyph* glyph) { - // Do nothing - } - - void glyphAdvanceXY(const Glyph* glyph, double& x, double& y) { - x += glyph->ft_glyph->advance.x / double(1 << 16); - y += glyph->ft_glyph->advance.y / double(1 << 16); - } - - private: - FaceFT& m_face; - base::utf8_const_iterator m_begin, m_end, m_it; - }; - - template > - class ForEachGlyph { - public: - typedef typename FaceFT::Glyph Glyph; - - ForEachGlyph(FaceFT& face) - : m_face(face) - , m_shaper(face) - , m_glyph(nullptr) - , m_useKerning(FT_HAS_KERNING((FT_Face)face) ? true: false) - , m_prevGlyph(0) - , m_x(0.0), m_y(0.0) { - } - - ~ForEachGlyph() { - unloadGlyph(); - } - - int unicodeChar() { return m_shaper.unicodeChar(); } - int charIndex() { return m_shaper.charIndex(); } - - const Glyph* glyph() const { return m_glyph; } - - bool initialize(const base::utf8_const_iterator& it, - const base::utf8_const_iterator& end) { - bool res = m_shaper.initialize(it, end); - if (res) - prepareGlyph(); - return res; - } - - bool nextChar() { - m_prevGlyph = m_shaper.glyphIndex(); - - if (m_shaper.nextChar()) { - prepareGlyph(); - return true; - } - else - return false; - } - - private: - void prepareGlyph() { - FT_UInt glyphIndex = m_shaper.glyphIndex(); - double initialX = m_x; - - if (m_useKerning && m_prevGlyph && glyphIndex) { - FT_Vector kerning; - FT_Get_Kerning(m_face, m_prevGlyph, glyphIndex, - FT_KERNING_DEFAULT, &kerning); - m_x += kerning.x / 64.0; - } - - unloadGlyph(); - - // Load new glyph - m_glyph = m_face.cache().loadGlyph(m_face, glyphIndex, m_face.antialias()); - if (m_glyph) { - m_glyph->bitmap = &FT_BitmapGlyph(m_glyph->ft_glyph)->bitmap; - m_glyph->x = m_x - + m_glyph->bearingX; - m_glyph->y = m_y - + m_face.height() - + m_face.descender() // descender is negative - - m_glyph->bearingY; - - m_shaper.glyphOffsetXY(m_glyph); - m_shaper.glyphAdvanceXY(m_glyph, m_x, m_y); - - m_glyph->startX = initialX; - m_glyph->endX = m_x; - } - } - - void unloadGlyph() { - if (m_glyph) { - m_face.cache().doneGlyph(m_glyph); - m_glyph = nullptr; - } - } - - private: - FaceFT& m_face; - Shaper m_shaper; - Glyph* m_glyph; - bool m_useKerning; - FT_UInt m_prevGlyph; - double m_x, m_y; - }; - - template - gfx::Rect calc_text_bounds(FaceFT& face, const std::string& str) { - gfx::Rect bounds(0, 0, 0, 0); - ForEachGlyph feg(face); - if (feg.initialize(base::utf8_const_iterator(str.begin()), - base::utf8_const_iterator(str.end()))) { - do { - if (auto glyph = feg.glyph()) - bounds |= gfx::Rect(int(glyph->x), - int(glyph->y), - glyph->bitmap->width, - glyph->bitmap->rows); - } while (feg.nextChar()); - } - return bounds; - } - -} // namespace ft - -#endif diff --git a/src/ft/face.h b/src/ft/face.h deleted file mode 100644 index 631ca12c8..000000000 --- a/src/ft/face.h +++ /dev/null @@ -1,202 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_FACE_H_INCLUDED -#define FT_FACE_H_INCLUDED -#pragma once - -#include "base/debug.h" -#include "base/disable_copying.h" -#include "ft/freetype_headers.h" - -#include - -namespace ft { - - struct Glyph { - FT_UInt glyph_index; - FT_Glyph ft_glyph; - FT_Bitmap* bitmap; - double startX; - double endX; - double bearingX; - double bearingY; - double x; - double y; - }; - - template - class FaceFT { - public: - typedef ft::Glyph Glyph; - - FaceFT(FT_Face face) : m_face(face) { - } - - ~FaceFT() { - if (m_face) - FT_Done_Face(m_face); - } - - operator FT_Face() { return m_face; } - FT_Face operator->() { return m_face; } - - bool isValid() const { - return (m_face != nullptr); - } - - bool antialias() const { - return m_antialias; - } - - void setAntialias(bool antialias) { - m_antialias = antialias; - m_cache.invalidate(); - } - - void setSize(int size) { - FT_Set_Pixel_Sizes(m_face, size, size); - m_cache.invalidate(); - } - - double height() const { - FT_Size_Metrics* metrics = &m_face->size->metrics; - double em_size = 1.0 * m_face->units_per_EM; - double y_scale = metrics->y_ppem / em_size; - return int(m_face->height * y_scale) - 1; - } - - double ascender() const { - FT_Size_Metrics* metrics = &m_face->size->metrics; - double em_size = 1.0 * m_face->units_per_EM; - double y_scale = metrics->y_ppem / em_size; - return int(m_face->ascender * y_scale); - } - - double descender() const { - FT_Size_Metrics* metrics = &m_face->size->metrics; - double em_size = 1.0 * m_face->units_per_EM; - double y_scale = metrics->y_ppem / em_size; - return int(m_face->descender * y_scale); - } - - bool hasCodePoint(int codepoint) const { - if (m_face) { - codepoint = FT_Get_Char_Index(m_face, codepoint); - return (codepoint != 0); - } - else - return false; - } - - Cache& cache() { return m_cache; } - - protected: - FT_Face m_face; - bool m_antialias; - Cache m_cache; - - private: - DISABLE_COPYING(FaceFT); - }; - - class NoCache { - public: - void invalidate() { - // Do nothing - } - - FT_UInt getGlyphIndex(FT_Face face, int charCode) { - return FT_Get_Char_Index(face, charCode); - } - - Glyph* loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) { - FT_Error err = FT_Load_Glyph( - face, glyphIndex, - FT_LOAD_RENDER | - (antialias ? FT_LOAD_TARGET_NORMAL: - FT_LOAD_TARGET_MONO)); - if (err) - return nullptr; - - FT_Glyph ft_glyph; - err = FT_Get_Glyph(face->glyph, &ft_glyph); - if (err) - return nullptr; - - if (ft_glyph->format != FT_GLYPH_FORMAT_BITMAP) { - err = FT_Glyph_To_Bitmap(&ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1); - if (!err) { - FT_Done_Glyph(ft_glyph); - return nullptr; - } - } - - m_glyph.ft_glyph = ft_glyph; - m_glyph.bearingX = face->glyph->metrics.horiBearingX / 64.0; - m_glyph.bearingY = face->glyph->metrics.horiBearingY / 64.0; - - return &m_glyph; - } - - void doneGlyph(Glyph* glyph) { - ASSERT(glyph); - FT_Done_Glyph(glyph->ft_glyph); - } - - private: - Glyph m_glyph; - }; - - class SimpleCache : public NoCache { - public: - ~SimpleCache() { - invalidate(); - } - - void invalidate() { - for (auto& it : m_glyphMap) { - FT_Done_Glyph(it.second->ft_glyph); - delete it.second; - } - - m_glyphMap.clear(); - } - - Glyph* loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) { - auto it = m_glyphMap.find(glyphIndex); - if (it != m_glyphMap.end()) - return it->second; - - Glyph* glyph = NoCache::loadGlyph(face, glyphIndex, antialias); - if (!glyph) - return nullptr; - - FT_Glyph new_ft_glyph = nullptr; - FT_Glyph_Copy(glyph->ft_glyph, &new_ft_glyph); - if (!new_ft_glyph) - return nullptr; - - Glyph* newGlyph = new Glyph(*glyph); - newGlyph->ft_glyph = new_ft_glyph; - - m_glyphMap[glyphIndex] = newGlyph; - FT_Done_Glyph(glyph->ft_glyph); - - return newGlyph; - } - - void doneGlyph(Glyph* glyph) { - // Do nothing - } - - private: - std::map m_glyphMap; - }; - -} // namespace ft - -#endif diff --git a/src/ft/freetype_headers.h b/src/ft/freetype_headers.h deleted file mode 100644 index 2a69526c3..000000000 --- a/src/ft/freetype_headers.h +++ /dev/null @@ -1,15 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_FREETYPE_HEADERS_H_INCLUDED -#define FT_FREETYPE_HEADERS_H_INCLUDED -#pragma once - -#include -#include FT_GLYPH_H -#include FT_FREETYPE_H - -#endif diff --git a/src/ft/hb_face.h b/src/ft/hb_face.h deleted file mode 100644 index dc8c9ad07..000000000 --- a/src/ft/hb_face.h +++ /dev/null @@ -1,44 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_HB_FACE_H_INCLUDED -#define FT_HB_FACE_H_INCLUDED -#pragma once - -#include "base/string.h" -#include "ft/face.h" - -#include -#include - -namespace ft { - - template - class HBFace : public FaceFT { - public: - HBFace(FT_Face face) : FaceFT(face) { - m_font = (face ? hb_ft_font_create((FT_Face)face, nullptr): nullptr); - m_buffer = (face ? hb_buffer_create(): nullptr); - } - - ~HBFace() { - if (m_buffer) hb_buffer_destroy(m_buffer); - if (m_font) hb_font_destroy(m_font); - } - - hb_font_t* font() const { return m_font; } - hb_buffer_t* buffer() const { return m_buffer; } - - private: - hb_buffer_t* m_buffer; - hb_font_t* m_font; - }; - - typedef HBFace > Face; - -} // namespace ft - -#endif diff --git a/src/ft/hb_shaper.h b/src/ft/hb_shaper.h deleted file mode 100644 index 9d0705684..000000000 --- a/src/ft/hb_shaper.h +++ /dev/null @@ -1,90 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_HB_SHAPER_H_INCLUDED -#define FT_HB_SHAPER_H_INCLUDED -#pragma once - -#include "ft/hb_face.h" - -#include - -namespace ft { - - template - class HBShaper { - public: - HBShaper(HBFace& face) - : m_face(face) - , m_unicodeFuncs(hb_buffer_get_unicode_funcs(face.buffer())) { - } - - bool initialize(const base::utf8_const_iterator& begin, - const base::utf8_const_iterator& end) { - m_index = 0; - if (begin == end) - return false; - - hb_buffer_t* buf = m_face.buffer(); - - hb_buffer_reset(buf); - for (auto it=begin; it!=end; ++it) - hb_buffer_add(buf, *it, it - begin); - - // Just in case we're compiling with an old harfbuzz version -#ifdef HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS - hb_buffer_set_cluster_level(buf, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS); -#endif - hb_buffer_set_content_type(buf, HB_BUFFER_CONTENT_TYPE_UNICODE); - hb_buffer_set_direction(buf, HB_DIRECTION_LTR); - hb_buffer_guess_segment_properties(buf); - - hb_shape(m_face.font(), buf, nullptr, 0); - - m_glyphInfo = hb_buffer_get_glyph_infos(buf, &m_glyphCount); - m_glyphPos = hb_buffer_get_glyph_positions(buf, &m_glyphCount); - return (m_glyphCount > 0); - } - - bool nextChar() { - ++m_index; - return (m_index < m_glyphCount); - } - - int unicodeChar() const { - return m_glyphInfo[m_index].codepoint; - } - - int charIndex() { - return m_glyphInfo[m_index].cluster; - } - - unsigned int glyphIndex() const { - return m_glyphInfo[m_index].codepoint; - } - - void glyphOffsetXY(Glyph* glyph) { - glyph->x += m_glyphPos[m_index].x_offset / 64.0; - glyph->y += m_glyphPos[m_index].y_offset / 64.0; - } - - void glyphAdvanceXY(const Glyph* glyph, double& x, double& y) { - x += m_glyphPos[m_index].x_advance / 64.0; - y += m_glyphPos[m_index].y_advance / 64.0; - } - - private: - HBFace& m_face; - hb_glyph_info_t* m_glyphInfo; - hb_glyph_position_t* m_glyphPos; - unsigned int m_glyphCount; - unsigned int m_index; - hb_unicode_funcs_t* m_unicodeFuncs; - }; - -} // namespace ft - -#endif diff --git a/src/ft/lib.cpp b/src/ft/lib.cpp deleted file mode 100644 index fc1978dfe..000000000 --- a/src/ft/lib.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "ft/lib.h" - -#include "base/log.h" -#include "ft/stream.h" - -#include - -namespace ft { - -Lib::Lib() - : m_ft(nullptr) -{ - FT_Init_FreeType(&m_ft); -} - -Lib::~Lib() -{ - if (m_ft) - FT_Done_FreeType(m_ft); -} - -FT_Face Lib::open(const std::string& filename) -{ - FT_Stream stream = ft::open_stream(filename); - FT_Open_Args args; - memset(&args, 0, sizeof(args)); - args.flags = FT_OPEN_STREAM; - args.stream = stream; - - LOG(VERBOSE) << "FT: Loading font '" << filename << "'\n"; - - FT_Face face = nullptr; - FT_Error err = FT_Open_Face(m_ft, &args, 0, &face); - if (!err) - FT_Select_Charmap(face, FT_ENCODING_UNICODE); - return face; -} - -} // namespace ft diff --git a/src/ft/lib.h b/src/ft/lib.h deleted file mode 100644 index 792493bc1..000000000 --- a/src/ft/lib.h +++ /dev/null @@ -1,35 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_LIB_H_INCLUDED -#define FT_LIB_H_INCLUDED -#pragma once - -#include "base/disable_copying.h" -#include "ft/freetype_headers.h" - -#include - -namespace ft { - - class Lib { - public: - Lib(); - ~Lib(); - - operator FT_Library() { return m_ft; } - - FT_Face open(const std::string& filename); - - private: - FT_Library m_ft; - - DISABLE_COPYING(Lib); - }; - -} // namespace ft - -#endif diff --git a/src/ft/stream.cpp b/src/ft/stream.cpp deleted file mode 100644 index df115eebb..000000000 --- a/src/ft/stream.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "ft/stream.h" - -#include "base/file_handle.h" - -#include - -#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) - -namespace ft { - -static void ft_stream_close(FT_Stream stream) -{ - fclose(STREAM_FILE(stream)); - free(stream); -} - -static unsigned long ft_stream_io(FT_Stream stream, - unsigned long offset, - unsigned char* buffer, - unsigned long count) -{ - if (!count && offset > stream->size) - return 1; - - FILE* file = STREAM_FILE(stream); - if (stream->pos != offset) - fseek(file, (long)offset, SEEK_SET); - - return (unsigned long)fread(buffer, 1, count, file); -} - -FT_Stream open_stream(const std::string& utf8Filename) -{ - FT_Stream stream = nullptr; - stream = (FT_Stream)malloc(sizeof(*stream)); - if(!stream) - return nullptr; - memset(stream, 0, sizeof(*stream)); - - TRACE("FT: Loading font %s... ", utf8Filename.c_str()); - - FILE* file = base::open_file_raw(utf8Filename, "rb"); - if (!file) { - free(stream); - TRACE("FAIL\n"); - return nullptr; - } - - fseek(file, 0, SEEK_END); - stream->size = (unsigned long)ftell(file); - if (!stream->size) { - fclose(file); - free(stream); - TRACE("FAIL\n"); - return nullptr; - } - fseek(file, 0, SEEK_SET); - - stream->descriptor.pointer = file; - stream->base = nullptr; - stream->pos = 0; - stream->read = ft_stream_io; - stream->close = ft_stream_close; - - TRACE("OK\n"); - return stream; -} - -} // namespace ft diff --git a/src/ft/stream.h b/src/ft/stream.h deleted file mode 100644 index 8803f88bc..000000000 --- a/src/ft/stream.h +++ /dev/null @@ -1,21 +0,0 @@ -// Aseprite FreeType Wrapper -// Copyright (c) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef FT_STREAM_H_INCLUDED -#define FT_STREAM_H_INCLUDED -#pragma once - -#include "ft/freetype_headers.h" - -#include - -namespace ft { - -FT_Stream open_stream(const std::string& utf8Filename); - -} // namespace ft - -#endif diff --git a/src/gfx/CMakeLists.txt b/src/gfx/CMakeLists.txt deleted file mode 100644 index d902cfdca..000000000 --- a/src/gfx/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Aseprite -# Copyright (C) 2001-2017 David Capello - -add_library(gfx-lib - hsl.cpp - hsv.cpp - packing_rects.cpp - region.cpp - rgb.cpp) - -target_link_libraries(gfx-lib - laf-base - ${PIXMAN_LIBRARY}) diff --git a/src/gfx/LICENSE.txt b/src/gfx/LICENSE.txt deleted file mode 100644 index 0d2d81fd4..000000000 --- a/src/gfx/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2001-2016 David Capello - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/gfx/README.md b/src/gfx/README.md deleted file mode 100644 index 40179d6ec..000000000 --- a/src/gfx/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Aseprite Gfx Library -*Copyright (C) 2001-2016 David Capello* - -> Distributed under [MIT license](LICENSE.txt) - -The `gfx::Region` class depends on pixman library. diff --git a/src/gfx/border.h b/src/gfx/border.h deleted file mode 100644 index d2929ffcd..000000000 --- a/src/gfx/border.h +++ /dev/null @@ -1,205 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2013, 2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_BORDER_H_INCLUDED -#define GFX_BORDER_H_INCLUDED -#pragma once - -namespace gfx { - -template -class SizeT; - -template -class BorderT -{ -public: - BorderT() : - m_left(0), - m_top(0), - m_right(0), - m_bottom(0) { - } - - BorderT(const T& left, const T& top, const T& right, const T& bottom) : - m_left(left), - m_top(top), - m_right(right), - m_bottom(bottom) { - } - - explicit BorderT(const T& allSides) : - m_left(allSides), - m_top(allSides), - m_right(allSides), - m_bottom(allSides) { - } - - T left() const { return m_left; }; - T top() const { return m_top; }; - T right() const { return m_right; }; - T bottom() const { return m_bottom; }; - - T width() const { return m_left + m_right; }; - T height() const { return m_top + m_bottom; }; - - void left(const T& left) { m_left = left; } - void top(const T& top) { m_top = top; } - void right(const T& right) { m_right = right; } - void bottom(const T& bottom) { m_bottom = bottom; } - - SizeT size() const { - return SizeT(m_left + m_right, m_top + m_bottom); - } - - const BorderT& operator+=(const BorderT& br) { - m_left += br.m_left; - m_top += br.m_top; - m_right += br.m_right; - m_bottom += br.m_bottom; - return *this; - } - - const BorderT& operator-=(const BorderT& br) { - m_left -= br.m_left; - m_top -= br.m_top; - m_right -= br.m_right; - m_bottom -= br.m_bottom; - return *this; - } - - const BorderT& operator*=(const BorderT& br) { - m_left *= br.m_left; - m_top *= br.m_top; - m_right *= br.m_right; - m_bottom *= br.m_bottom; - return *this; - } - - const BorderT& operator/=(const BorderT& br) { - m_left /= br.m_left; - m_top /= br.m_top; - m_right /= br.m_right; - m_bottom /= br.m_bottom; - return *this; - } - - const BorderT& operator+=(const T& value) { - m_left += value; - m_top += value; - m_right += value; - m_bottom += value; - return *this; - } - - const BorderT& operator-=(const T& value) { - m_left -= value; - m_top -= value; - m_right -= value; - m_bottom -= value; - return *this; - } - - const BorderT& operator*=(const T& value) { - m_left *= value; - m_top *= value; - m_right *= value; - m_bottom *= value; - return *this; - } - - const BorderT& operator/=(const T& value) { - m_left /= value; - m_top /= value; - m_right /= value; - m_bottom /= value; - return *this; - } - - BorderT operator+(const BorderT& br) const { - return BorderT(m_left + br.left(), - m_top + br.top(), - m_right + br.right(), - m_bottom + br.bottom()); - } - - BorderT operator-(const BorderT& br) const { - return BorderT(m_left - br.left(), - m_top - br.top(), - m_right - br.right(), - m_bottom - br.bottom()); - } - - BorderT operator*(const BorderT& br) const { - return BorderT(m_left * br.left(), - m_top * br.top(), - m_right * br.right(), - m_bottom * br.bottom()); - } - - BorderT operator/(const BorderT& br) const { - return BorderT(m_left / br.left(), - m_top / br.top(), - m_right / br.right(), - m_bottom / br.bottom()); - } - - BorderT operator+(const T& value) const { - return BorderT(m_left + value, - m_top + value, - m_right + value, - m_bottom + value); - } - - BorderT operator-(const T& value) const { - return BorderT(m_left - value, - m_top - value, - m_right - value, - m_bottom - value); - } - - BorderT operator*(const T& value) const { - return BorderT(m_left * value, - m_top * value, - m_right * value, - m_bottom * value); - } - - BorderT operator/(const T& value) const { - return BorderT(m_left / value, - m_top / value, - m_right / value, - m_bottom / value); - } - - BorderT operator-() const { - return BorderT(-m_left, -m_top, -m_right, -m_bottom); - } - - bool operator==(const BorderT& br) const { - return - m_left == br.m_left && m_top == br.m_top && - m_right == br.m_right && m_bottom == br.m_bottom; - } - - bool operator!=(const BorderT& br) const { - return - m_left != br.m_left || m_top != br.m_top || - m_right != br.m_right || m_bottom != br.m_bottom; - } - -private: - T m_left; - T m_top; - T m_right; - T m_bottom; -}; - -typedef BorderT Border; - -} // namespace gfx - -#endif diff --git a/src/gfx/clip.h b/src/gfx/clip.h deleted file mode 100644 index 8364e2e06..000000000 --- a/src/gfx/clip.h +++ /dev/null @@ -1,138 +0,0 @@ -// Aseprite Gfx Library -// Copyright (c) 2001-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_CLIP_H_INCLUDED -#define GFX_CLIP_H_INCLUDED -#pragma once - -#include "gfx/point.h" -#include "gfx/rect.h" -#include "gfx/size.h" - -namespace gfx { - - template - class ClipT { - public: - PointT dst; - PointT src; - SizeT size; - - ClipT() - : dst(0, 0) - , src(0, 0) - , size(0, 0) { - } - - ClipT(T w, T h) - : dst(0, 0) - , src(0, 0) - , size(w, h) { - } - - ClipT(T dst_x, T dst_y, T src_x, T src_y, T w, T h) - : dst(dst_x, dst_y) - , src(src_x, src_y) - , size(w, h) { - } - - ClipT(T dst_x, T dst_y, const RectT& srcBounds) - : dst(dst_x, dst_y) - , src(srcBounds.x, srcBounds.y) - , size(srcBounds.w, srcBounds.h) { - } - - ClipT(const PointT& dst, const PointT& src, const SizeT& size) - : dst(dst) - , src(src) - , size(size) { - } - - ClipT(const PointT& dst, const RectT& srcBounds) - : dst(dst) - , src(srcBounds.x, srcBounds.y) - , size(srcBounds.w, srcBounds.h) { - } - - ClipT(const RectT& bounds) - : dst(bounds.x, bounds.y) - , src(bounds.x, bounds.y) - , size(bounds.w, bounds.h) { - } - - template - ClipT(const ClipT& other) - : dst(other.dst) - , src(other.src) - , size(other.size) { - } - - RectT dstBounds() const { return RectT(dst, size); } - RectT srcBounds() const { return RectT(src, size); } - - bool operator==(const ClipT& other) const { - return (dst == other.dst && - src == other.src && - size == other.size); - } - - bool clip( - // Available area - T avail_dst_w, - T avail_dst_h, - T avail_src_w, - T avail_src_h) { - // Clip srcBounds - - if (src.x < T(0)) { - size.w += src.x; - dst.x -= src.x; - src.x = T(0); - } - - if (src.y < T(0)) { - size.h += src.y; - dst.y -= src.y; - src.y = T(0); - } - - if (src.x + size.w > avail_src_w) - size.w -= src.x + size.w - avail_src_w; - - if (src.y + size.h > avail_src_h) - size.h -= src.y + size.h - avail_src_h; - - // Clip dstBounds - - if (dst.x < T(0)) { - size.w += dst.x; - src.x -= dst.x; - dst.x = T(0); - } - - if (dst.y < T(0)) { - size.h += dst.y; - src.y -= dst.y; - dst.y = T(0); - } - - if (dst.x + size.w > avail_dst_w) - size.w -= dst.x + size.w - avail_dst_w; - - if (dst.y + size.h > avail_dst_h) - size.h -= dst.y + size.h - avail_dst_h; - - return (size.w > T(0) && size.h > T(0)); - } - - }; - - typedef ClipT Clip; - typedef ClipT ClipF; - -} // namespace gfx - -#endif diff --git a/src/gfx/clip_tests.cpp b/src/gfx/clip_tests.cpp deleted file mode 100644 index d79000f71..000000000 --- a/src/gfx/clip_tests.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Aseprite Document Library -// Copyright (c) 2001-2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gfx/clip.h" - -using namespace gfx; - -namespace gfx { - -inline std::ostream& operator<<(std::ostream& os, const Clip& area) -{ - return os << "(" - << area.dst.x << ", " - << area.dst.y << ", " - << area.src.x << ", " - << area.src.y << ", " - << area.size.w << ", " - << area.size.h << ")"; -} - -} - -TEST(ScaledClip, WithoutClip) -{ - Clip area; - - area = Clip(0, 0, 0, 0, 16, 16); - EXPECT_TRUE(area.clip(16, 16, 16, 16)); - EXPECT_EQ(Clip(0, 0, 0, 0, 16, 16), area); - - area = Clip(2, 2, 0, 0, 16, 16); - EXPECT_TRUE(area.clip(32, 32, 16, 16)); - EXPECT_EQ(Clip(2, 2, 0, 0, 16, 16), area); -} - -TEST(ScaledClip, FullyClipped) -{ - Clip area; - - area = Clip(32, 32, 0, 0, 16, 16); - EXPECT_FALSE(area.clip(32, 32, 16, 16)); - - area = Clip(-16, -16, 0, 0, 16, 16); - EXPECT_FALSE(area.clip(32, 32, 16, 16)); - - area = Clip(0, 0, 16, 16, 16, 16); - EXPECT_FALSE(area.clip(32, 32, 16, 16)); -} - -TEST(ScaledClip, WithoutZoomWithClip) -{ - Clip area; - - area = Clip(2, 3, 1, -1, 4, 3); - EXPECT_TRUE(area.clip(30, 29, 16, 16)); - EXPECT_EQ(Clip(2, 4, 1, 0, 4, 2), area); - - area = Clip(0, 0, -1, -4, 8, 5); - EXPECT_TRUE(area.clip(3, 32, 8, 8)); - EXPECT_EQ(Clip(1, 4, 0, 0, 2, 1), area); -} - -TEST(ScaledClip, Zoom) -{ - Clip area; - - area = Clip(0, 0, 0, 0, 32, 32); - EXPECT_TRUE(area.clip(32, 32, 16, 16)); - EXPECT_EQ(Clip(0, 0, 0, 0, 16, 16), area); - - area = Clip(0, 0, 1, 2, 32, 32); - EXPECT_TRUE(area.clip(32, 32, 32, 32)); - EXPECT_EQ(Clip(0, 0, 1, 2, 31, 30), area); - - // X: - // -1 0 1 2 3 4 5 - // [ ] - // a[a a b] b c c c DST - // a a[a b b]b c c c SRC - // - // Y: - // -1 0 1 2 3 - // [ ] - // a[a a]b b b DST - // [a a]a b b b c c SRC - area = Clip(-1, 1, 1, -1, 4, 4); - EXPECT_TRUE(area.clip(6, 4, 9, 9)); - EXPECT_EQ(Clip(0, 2, 2, 0, 3, 2), area); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/gfx/color.h b/src/gfx/color.h deleted file mode 100644 index f58f70b7e..000000000 --- a/src/gfx/color.h +++ /dev/null @@ -1,41 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_COLOR_H_INCLUDED -#define GFX_COLOR_H_INCLUDED -#pragma once - -#include "base/ints.h" - -namespace gfx { - - typedef uint32_t Color; - typedef uint8_t ColorComponent; - - static const int ColorRShift = 0; - static const int ColorGShift = 8; - static const int ColorBShift = 16; - static const int ColorAShift = 24; - - static const Color ColorNone = Color(0); - - inline Color rgba(ColorComponent r, ColorComponent g, ColorComponent b, ColorComponent a = 255) { - return Color((r << ColorRShift) | - (g << ColorGShift) | - (b << ColorBShift) | - (a << ColorAShift)); - } - - inline ColorComponent getr(Color c) { return (c >> ColorRShift) & 0xff; } - inline ColorComponent getg(Color c) { return (c >> ColorGShift) & 0xff; } - inline ColorComponent getb(Color c) { return (c >> ColorBShift) & 0xff; } - inline ColorComponent geta(Color c) { return (c >> ColorAShift) & 0xff; } - - inline bool is_transparent(Color c) { return geta(c) == 0; } - -} // namespace gfx - -#endif // GFX_COLOR_H_INCLUDED diff --git a/src/gfx/fwd.h b/src/gfx/fwd.h deleted file mode 100644 index 2b1ba5a7f..000000000 --- a/src/gfx/fwd.h +++ /dev/null @@ -1,29 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_FWD_H_INCLUDED -#define GFX_FWD_H_INCLUDED -#pragma once - -namespace gfx { - -template class BorderT; -template class ClipT; -template class PointT; -template class RectT; -template class SizeT; - -typedef BorderT Border; -typedef ClipT Clip; -typedef PointT Point; -typedef RectT Rect; -typedef SizeT Size; - -class Region; - -} // namespace gfx - -#endif diff --git a/src/gfx/hsl.cpp b/src/gfx/hsl.cpp deleted file mode 100644 index 0125a4963..000000000 --- a/src/gfx/hsl.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gfx/hsl.h" -#include "gfx/rgb.h" -#include - -namespace gfx { - -using namespace std; - -Hsl::Hsl(double hue, double saturation, double lightness) - : m_hue(hue) - , m_saturation(MID(0.0, saturation, 1.0)) - , m_lightness(MID(0.0, lightness, 1.0)) -{ - while (m_hue < 0.0) - m_hue += 360.0; - m_hue = std::fmod(m_hue, 360.0); -} - -Hsl::Hsl(const Rgb& rgb) -{ - int M = rgb.maxComponent(); - int m = rgb.minComponent(); - int c = M - m; - double chroma = double(c) / 255.0; - double hue_prime = 0.0; - double h, s, l; - double r, g, b; - - l = double((M + m) / 255.0) / 2.0; - - if (c == 0) { - h = 0.0; // Undefined Hue because max == min - s = 0.0; - } - else { - r = double(rgb.red()) / 255.0; - g = double(rgb.green()) / 255.0; - b = double(rgb.blue()) / 255.0; - s = chroma / (1-std::fabs(2.0*l-1.0)); - - if (M == rgb.red()) { - hue_prime = (g - b) / chroma; - - while (hue_prime < 0.0) - hue_prime += 6.0; - hue_prime = std::fmod(hue_prime, 6.0); - } - else if (M == rgb.green()) { - hue_prime = ((b - r) / chroma) + 2.0; - } - else if (M == rgb.blue()) { - hue_prime = ((r - g) / chroma) + 4.0; - } - - h = hue_prime * 60.0; - } - - m_hue = h; - m_saturation = s; - m_lightness = l; -} - -int Hsl::hueInt() const -{ - return int(std::floor(m_hue + 0.5)); -} - -int Hsl::saturationInt() const -{ - return int(std::floor(m_saturation*100.0 + 0.5)); -} - -int Hsl::lightnessInt() const -{ - return int(std::floor(m_lightness*100.0 + 0.5)); -} - -} // namespace gfx diff --git a/src/gfx/hsl.h b/src/gfx/hsl.h deleted file mode 100644 index 2c1674c37..000000000 --- a/src/gfx/hsl.h +++ /dev/null @@ -1,81 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_HSL_H_INCLUDED -#define GFX_HSL_H_INCLUDED -#pragma once - -#include "base/base.h" // MID - -namespace gfx { - -class Rgb; - -class Hsl { -public: - Hsl() - : m_hue(0.0) - , m_saturation(0.0) - , m_lightness(0.0) - { } - - Hsl(double hue, double saturation, double lightness); - - Hsl(const Hsl& hsl) - : m_hue(hsl.hue()) - , m_saturation(hsl.saturation()) - , m_lightness(hsl.lightness()) - { } - - // RGB to HSL conversion - explicit Hsl(const Rgb& rgb); - - // Returns color's hue, a value from 0 to 360 - double hue() const { return m_hue; } - - // Returns color's saturation, a value from 0 to 100 - double saturation() const { return m_saturation; } - - // Returns color's lightness, a value from 0 to 100 - double lightness() const { return m_lightness; } - - // Integer getters, hue=[0,360), saturation=[0,100], value=[0,100] - int hueInt() const; - int saturationInt() const; - int lightnessInt() const; - - void hue(double hue) { - m_hue = MID(0.0, hue, 360.0); - } - - void saturation(double saturation) { - m_saturation = MID(0.0, saturation, 1.0); - } - - void lightness(double lightness) { - m_lightness = MID(0.0, lightness, 1.0); - } - - // The comparison is done through the integer value of each component. - bool operator==(const Hsl& other) const { - return (hueInt() == other.hueInt() && - saturationInt() == other.saturationInt() && - lightnessInt() == other.lightnessInt()); - } - - bool operator!=(const Hsl& other) const { - return !operator==(other); - } - -private: - double m_hue; - double m_saturation; - double m_lightness; -}; - -} // namespace gfx - -#endif diff --git a/src/gfx/hsv.cpp b/src/gfx/hsv.cpp deleted file mode 100644 index 40e5d5dec..000000000 --- a/src/gfx/hsv.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gfx/hsv.h" -#include "gfx/rgb.h" -#include - -namespace gfx { - -using namespace std; - -Hsv::Hsv(double hue, double saturation, double value) - : m_hue(hue) - , m_saturation(MID(0.0, saturation, 1.0)) - , m_value(MID(0.0, value, 1.0)) -{ - while (m_hue < 0.0) - m_hue += 360.0; - m_hue = std::fmod(m_hue, 360.0); -} - -// Reference: http://en.wikipedia.org/wiki/HSL_and_HSV -Hsv::Hsv(const Rgb& rgb) -{ - int M = rgb.maxComponent(); - int m = rgb.minComponent(); - int c = M - m; - double chroma = double(c) / 255.0; - double hue_prime = 0.0; - double h, s, v; - double r, g, b; - - v = double(M) / 255.0; - - if (c == 0) { - h = 0.0; // Undefined Hue because max == min - s = 0.0; - } - else { - r = double(rgb.red()) / 255.0; - g = double(rgb.green()) / 255.0; - b = double(rgb.blue()) / 255.0; - s = chroma / v; - - if (M == rgb.red()) { - hue_prime = (g - b) / chroma; - - while (hue_prime < 0.0) - hue_prime += 6.0; - hue_prime = std::fmod(hue_prime, 6.0); - } - else if (M == rgb.green()) { - hue_prime = ((b - r) / chroma) + 2.0; - } - else if (M == rgb.blue()) { - hue_prime = ((r - g) / chroma) + 4.0; - } - - h = hue_prime * 60.0; - } - - m_hue = h; - m_saturation = s; - m_value = v; -} - -int Hsv::hueInt() const -{ - return int(std::floor(m_hue + 0.5)); -} - -int Hsv::saturationInt() const -{ - return int(std::floor(m_saturation*100.0 + 0.5)); -} - -int Hsv::valueInt() const -{ - return int(std::floor(m_value*100.0 + 0.5)); -} - -} // namespace gfx diff --git a/src/gfx/hsv.h b/src/gfx/hsv.h deleted file mode 100644 index ecac069cf..000000000 --- a/src/gfx/hsv.h +++ /dev/null @@ -1,81 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_HSV_H_INCLUDED -#define GFX_HSV_H_INCLUDED -#pragma once - -#include "base/base.h" // MID - -namespace gfx { - -class Rgb; - -class Hsv { -public: - Hsv() - : m_hue(0.0) - , m_saturation(0.0) - , m_value(0.0) - { } - - Hsv(double hue, double saturation, double value); - - Hsv(const Hsv& hsv) - : m_hue(hsv.hue()) - , m_saturation(hsv.saturation()) - , m_value(hsv.value()) - { } - - // RGB to HSV conversion - explicit Hsv(const Rgb& rgb); - - // Returns color's hue, a value from 0 to 360 - double hue() const { return m_hue; } - - // Returns color's saturation, a value from 0 to 100 - double saturation() const { return m_saturation; } - - // Returns color's brightness, a value from 0 to 100 - double value() const { return m_value; } - - // Integer getters, hue=[0,360), saturation=[0,100], value=[0,100] - int hueInt() const; - int saturationInt() const; - int valueInt() const; - - void hue(double hue) { - m_hue = MID(0.0, hue, 360.0); - } - - void saturation(double saturation) { - m_saturation = MID(0.0, saturation, 1.0); - } - - void value(double value) { - m_value = MID(0.0, value, 1.0); - } - - // The comparison is done through the integer value of each component. - bool operator==(const Hsv& other) const { - return (hueInt() == other.hueInt() && - saturationInt() == other.saturationInt() && - valueInt() == other.valueInt()); - } - - bool operator!=(const Hsv& other) const { - return !operator==(other); - } - -private: - double m_hue; - double m_saturation; - double m_value; -}; - -} // namespace gfx - -#endif diff --git a/src/gfx/hsv_tests.cpp b/src/gfx/hsv_tests.cpp deleted file mode 100644 index 46fbdc163..000000000 --- a/src/gfx/hsv_tests.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2013 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gfx/hsv.h" -#include "gfx/rgb.h" - -using namespace gfx; -using namespace std; - -namespace gfx { - - ostream& operator<<(ostream& os, const Hsv& hsv) - { - return os << "(" - << hsv.hueInt() << ", " - << hsv.saturationInt() << ", " - << hsv.valueInt() << "); real: (" - << hsv.hue() << ", " - << hsv.saturation() << ", " - << hsv.value() << ")"; - } - -} - -TEST(Hsv, Ctor) -{ - EXPECT_EQ(35.0, Hsv(35.0, 0.50, 0.75).hue()); - EXPECT_EQ(0.50, Hsv(35.0, 0.50, 0.75).saturation()); - EXPECT_EQ(0.75, Hsv(35.0, 0.50, 0.75).value()); - EXPECT_EQ(35, Hsv(35.0, 0.50, 0.75).hueInt()); - EXPECT_EQ(50, Hsv(35.0, 0.50, 0.75).saturationInt()); - EXPECT_EQ(75, Hsv(35.0, 0.50, 0.75).valueInt()); - EXPECT_EQ(Hsv(0, 0, 0), Hsv()); -} - -TEST(Hsv, FromRgb) -{ - EXPECT_EQ(Hsv( 0.0, 0.00, 0.00), Hsv(Rgb( 0, 0, 0))); - EXPECT_EQ(Hsv( 0.0, 1.00, 0.01), Hsv(Rgb( 3, 0, 0))); - EXPECT_EQ(Hsv( 0.0, 1.00, 0.99), Hsv(Rgb(252, 0, 0))); - EXPECT_EQ(Hsv( 0.0, 1.00, 1.00), Hsv(Rgb(255, 0, 0))); - EXPECT_EQ(Hsv( 60.0, 1.00, 0.75), Hsv(Rgb(191, 191, 0))); - EXPECT_EQ(Hsv(120.0, 1.00, 0.50), Hsv(Rgb( 0, 128, 0))); - EXPECT_EQ(Hsv(120.0, 1.00, 1.00), Hsv(Rgb( 0, 255, 0))); - EXPECT_EQ(Hsv(180.0, 0.50, 1.00), Hsv(Rgb(128, 255, 255))); - EXPECT_EQ(Hsv(240.0, 0.50, 1.00), Hsv(Rgb(128, 128, 255))); - EXPECT_EQ(Hsv(240.0, 1.00, 1.00), Hsv(Rgb( 0, 0, 255))); - EXPECT_EQ(Hsv(300.0, 0.66, 0.75), Hsv(Rgb(191, 64, 191))); - EXPECT_EQ(Hsv(360.0, 1.00, 0.99), Hsv(Rgb(252, 0, 0))); - EXPECT_EQ(Hsv(360.0, 1.00, 1.00), Hsv(Rgb(255, 0, 0))); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/gfx/packing_rects.cpp b/src/gfx/packing_rects.cpp deleted file mode 100644 index e1e15bebb..000000000 --- a/src/gfx/packing_rects.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2014 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gfx/packing_rects.h" - -#include "gfx/region.h" -#include "gfx/size.h" - -namespace gfx { - -void PackingRects::add(const Size& sz) -{ - m_rects.push_back(Rect(sz)); -} - -void PackingRects::add(const Rect& rc) -{ - m_rects.push_back(rc); -} - -Size PackingRects::bestFit() -{ - Size size(0, 0); - - // Calculate the amount of pixels that we need, the texture cannot - // be smaller than that. - int neededArea = 0; - for (const auto& rc : m_rects) { - neededArea += rc.w * rc.h; - } - - int w = 1; - int h = 1; - int z = 0; - bool fit = false; - while (true) { - if (w*h >= neededArea) { - fit = pack(Size(w, h)); - if (fit) { - size = Size(w, h); - break; - } - } - - if ((++z) & 1) - w *= 2; - else - h *= 2; - } - - return size; -} - -static bool by_area(const Rect* a, const Rect* b) { - return a->w*a->h > b->w*b->h; -} - -bool PackingRects::pack(const Size& size) -{ - m_bounds = Rect(size); - - // We cannot sort m_rects because we want to - std::vector rectPtrs(m_rects.size()); - int i = 0; - for (auto& rc : m_rects) - rectPtrs[i++] = &rc; - std::sort(rectPtrs.begin(), rectPtrs.end(), by_area); - - gfx::Region rgn(m_bounds); - for (auto rcPtr : rectPtrs) { - gfx::Rect& rc = *rcPtr; - - for (int v=0; v<=m_bounds.h-rc.h; ++v) { - for (int u=0; u<=m_bounds.w-rc.w; ++u) { - gfx::Rect possible(u, v, rc.w, rc.h); - Region::Overlap overlap = rgn.contains(possible); - if (overlap == Region::In) { - rc = possible; - rgn.createSubtraction(rgn, gfx::Region(rc)); - goto next_rc; - } - } - } - return false; // There is not enough room for "rc" - next_rc:; - } - - return true; -} - -} // namespace gfx diff --git a/src/gfx/packing_rects.h b/src/gfx/packing_rects.h deleted file mode 100644 index 137de50d7..000000000 --- a/src/gfx/packing_rects.h +++ /dev/null @@ -1,53 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_TEXTURE_SIZE_H_INCLUDED -#define GFX_TEXTURE_SIZE_H_INCLUDED -#pragma once - -#include "gfx/fwd.h" -#include "gfx/rect.h" -#include - -namespace gfx { - - // TODO add support for rotations - class PackingRects { - public: - typedef std::vector Rects; - typedef Rects::const_iterator const_iterator; - - // Iterate over all given rectangles (in the same order they where - // given in addSize() calls). - const_iterator begin() const { return m_rects.begin(); } - const_iterator end() const { return m_rects.end(); } - - std::size_t size() const { return m_rects.size(); } - const Rect& operator[](int i) const { return m_rects[i]; } - - // Adds a new rectangle. - void add(const Size& sz); - void add(const Rect& rc); - - // Returns the best size for the texture. - Size bestFit(); - - // Rearrange all given rectangles to best fit a texture size. - // Returns true if all rectangles were correctly arranged or false - // if there is not enough space. - bool pack(const Size& size); - - // Returns the bounds of the packed area. - const Rect& bounds() const { return m_bounds; } - - private: - Rect m_bounds; - Rects m_rects; - }; - -} // namespace gfx - -#endif diff --git a/src/gfx/packing_rects_tests.cpp b/src/gfx/packing_rects_tests.cpp deleted file mode 100644 index a18088a1e..000000000 --- a/src/gfx/packing_rects_tests.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2014 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gfx/packing_rects.h" -#include "gfx/rect_io.h" -#include "gfx/size.h" - -using namespace gfx; - -TEST(PackingRects, Simple) -{ - PackingRects pr; - pr.add(Size(256, 128)); - EXPECT_FALSE(pr.pack(Size(256, 120))); - EXPECT_TRUE(pr.pack(Size(256, 128))); - - EXPECT_EQ(Rect(0, 0, 256, 128), pr[0]); - EXPECT_EQ(Rect(0, 0, 256, 128), pr.bounds()); -} - -TEST(PackingRects, SimpleTwoRects) -{ - PackingRects pr; - pr.add(Size(256, 128)); - pr.add(Size(256, 120)); - EXPECT_TRUE(pr.pack(Size(256, 256))); - - EXPECT_EQ(Rect(0, 0, 256, 256), pr.bounds()); - EXPECT_EQ(Rect(0, 0, 256, 128), pr[0]); - EXPECT_EQ(Rect(0, 128, 256, 120), pr[1]); -} - -TEST(PackingRects, BestFit) -{ - PackingRects pr; - pr.add(Size(10, 12)); - pr.bestFit(); - EXPECT_EQ(Rect(0, 0, 16, 16), pr.bounds()); -} - -TEST(PackingRects, BestFitTwoRects) -{ - PackingRects pr; - pr.add(Size(256, 128)); - pr.add(Size(256, 127)); - pr.bestFit(); - - EXPECT_EQ(Rect(0, 0, 256, 256), pr.bounds()); - EXPECT_EQ(Rect(0, 0, 256, 128), pr[0]); - EXPECT_EQ(Rect(0, 128, 256, 127), pr[1]); -} - -TEST(PackingRects, BestFit6Frames100x100) -{ - PackingRects pr; - pr.add(Size(100, 100)); - pr.add(Size(100, 100)); - pr.add(Size(100, 100)); - pr.add(Size(100, 100)); - pr.add(Size(100, 100)); - pr.add(Size(100, 100)); - pr.bestFit(); - - EXPECT_EQ(Rect(0, 0, 512, 256), pr.bounds()); - EXPECT_EQ(Rect(0, 0, 100, 100), pr[0]); - EXPECT_EQ(Rect(100, 0, 100, 100), pr[1]); - EXPECT_EQ(Rect(200, 0, 100, 100), pr[2]); - EXPECT_EQ(Rect(300, 0, 100, 100), pr[3]); - EXPECT_EQ(Rect(400, 0, 100, 100), pr[4]); - EXPECT_EQ(Rect(0, 100, 100, 100), pr[5]); -} - -TEST(PackingRects, KeepSameRectsOrder) -{ - PackingRects pr; - pr.add(Size(10, 10)); - pr.add(Size(20, 20)); - pr.add(Size(30, 30)); - pr.bestFit(); - - EXPECT_EQ(Rect(0, 0, 64, 32), pr.bounds()); - EXPECT_EQ(Rect(50, 0, 10, 10), pr[0]); - EXPECT_EQ(Rect(30, 0, 20, 20), pr[1]); - EXPECT_EQ(Rect(0, 0, 30, 30), pr[2]); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/gfx/point.h b/src/gfx/point.h deleted file mode 100644 index 438b58315..000000000 --- a/src/gfx/point.h +++ /dev/null @@ -1,125 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_POINT_H_INCLUDED -#define GFX_POINT_H_INCLUDED -#pragma once - -namespace gfx { - -template -class SizeT; - -// A 2D coordinate in the screen. -template -class PointT -{ -public: - T x, y; - - PointT() : x(0), y(0) { - } - - PointT(const T& x, const T& y) : x(x), y(y) { - } - - PointT(const PointT& point) : x(point.x), y(point.y) { - } - - template - explicit PointT(const PointT& point) : x(static_cast(point.x)), - y(static_cast(point.y)) { - } - - explicit PointT(const SizeT& size) : x(size.w), y(size.h) { - } - - const PointT& operator=(const PointT& pt) { - x = pt.x; - y = pt.y; - return *this; - } - - const PointT& operator+=(const PointT& pt) { - x += pt.x; - y += pt.y; - return *this; - } - - const PointT& operator-=(const PointT& pt) { - x -= pt.x; - y -= pt.y; - return *this; - } - - const PointT& operator+=(const T& value) { - x += value; - y += value; - return *this; - } - - const PointT& operator-=(const T& value) { - x -= value; - y -= value; - return *this; - } - - const PointT& operator*=(const T& value) { - x *= value; - y *= value; - return *this; - } - - const PointT& operator/=(const T& value) { - x /= value; - y /= value; - return *this; - } - - PointT operator+(const PointT& pt) const { - return PointT(x+pt.x, y+pt.y); - } - - PointT operator-(const PointT& pt) const { - return PointT(x-pt.x, y-pt.y); - } - - PointT operator+(const T& value) const { - return PointT(x+value, y+value); - } - - PointT operator-(const T& value) const { - return PointT(x-value, y-value); - } - - PointT operator*(const T& value) const { - return PointT(x*value, y*value); - } - - PointT operator/(const T& value) const { - return PointT(x/value, y/value); - } - - PointT operator-() const { - return PointT(-x, -y); - } - - bool operator==(const PointT& pt) const { - return x == pt.x && y == pt.y; - } - - bool operator!=(const PointT& pt) const { - return x != pt.x || y != pt.y; - } - -}; - -typedef PointT Point; -typedef PointT PointF; - -} // namespace gfx - -#endif diff --git a/src/gfx/rect.h b/src/gfx/rect.h deleted file mode 100644 index e3fef0480..000000000 --- a/src/gfx/rect.h +++ /dev/null @@ -1,365 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_RECT_H_INCLUDED -#define GFX_RECT_H_INCLUDED -#pragma once - -namespace gfx { - -template class PointT; -template class SizeT; -template class BorderT; - -// A rectangle. -template -class RectT -{ -public: - T x, y, w, h; - - T x2() const { return x+w; } - T y2() const { return y+h; } - - // Creates a new empty rectangle with the origin in 0,0. - RectT() : x(0), y(0), w(0), h(0) { - } - - // Creates a new rectangle with the specified size with the origin in 0,0. - RectT(const T& w, const T& h) : - x(0), y(0), - w(w), h(h) { - } - - // Creates a new rectangle with the specified size with the origin in 0,0. - explicit RectT(const SizeT& size) : - x(0), y(0), - w(size.w), h(size.h) { - } - - RectT(const RectT& rect) : - x(rect.x), y(rect.y), - w(rect.w), h(rect.h) { - } - - template - RectT(const RectT& rect) : - x(static_cast(rect.x)), y(static_cast(rect.y)), - w(static_cast(rect.w)), h(static_cast(rect.h)) { - } - - RectT(const PointT& point, const SizeT& size) : - x(point.x), y(point.y), - w(size.w), h(size.h) { - } - - // Creates a new rectangle with the origin in point1 and size - // equal to point2-point1. - // - // If a coordinate of point1 is greater than point2, the coordinates - // are swapped. The resulting rectangle will be: - // - // x = min(point1.x, point2.x) - // y = min(point1.y, point2.y) - // w = max(point1.x, point2.x) - x - // h = max(point1.x, point2.x) - y - // - // See that point2 isn't included in the rectangle, it's like the - // point returned by point2() member function. - RectT(const PointT& point1, const PointT& point2) { - PointT leftTop = point1; - PointT rightBottom = point2; - T t; - - if (leftTop.x > rightBottom.x) { - t = leftTop.x; - leftTop.x = rightBottom.x; - rightBottom.x = t; - } - - if (leftTop.y > rightBottom.y) { - t = leftTop.y; - leftTop.y = rightBottom.y; - rightBottom.y = t; - } - - this->x = leftTop.x; - this->y = leftTop.y; - this->w = rightBottom.x - leftTop.x; - this->h = rightBottom.y - leftTop.y; - } - - RectT(const T& x, const T& y, const T& w, const T& h) : x(x), y(y), w(w), h(h) { - } - - // Verifies if the width and/or height of the rectangle are less or - // equal than zero. - bool isEmpty() const { - return (w <= 0 || h <= 0); - } - - // Returns the middle point of the rectangle (x+w/2, y+h/2). - PointT center() const { - return PointT(x+w/2, y+h/2); - } - - // Returns the point in the upper-left corner (that is inside the - // rectangle). - PointT origin() const { - return PointT(x, y); - } - - // Returns point in the lower-right corner that is outside the - // rectangle (x+w, y+h). - PointT point2() const { - return PointT(x+w, y+h); - } - - SizeT size() const { - return SizeT(w, h); - } - - RectT& setOrigin(const PointT& pt) { - x = pt.x; - y = pt.y; - return *this; - } - - RectT& setSize(const SizeT& sz) { - w = sz.w; - h = sz.h; - return *this; - } - - // Moves the rectangle origin in the specified delta. - RectT& offset(const T& dx, const T& dy) { - x += dx; - y += dy; - return *this; - } - - RectT& offset(const PointT& delta) { - x += delta.x; - y += delta.y; - return *this; - } - - RectT& inflate(const T& delta) { - w += delta; - h += delta; - return *this; - } - - RectT& inflate(const T& dw, const T& dh) { - w += dw; - h += dh; - return *this; - } - - RectT& inflate(const SizeT& delta) { - w += delta.w; - h += delta.h; - return *this; - } - - RectT& enlarge(const T& unit) { - x -= unit; - y -= unit; - w += unit<<1; - h += unit<<1; - return *this; - } - - RectT& enlarge(const BorderT& br) { - x -= br.left(); - y -= br.top(); - w += br.left() + br.right(); - h += br.top() + br.bottom(); - return *this; - } - - RectT& enlargeXW(const T& unit) { - x -= unit; - w += unit<<1; - return *this; - } - - RectT& enlargeYH(const T& unit) { - y -= unit; - h += unit<<1; - return *this; - } - - RectT& shrink(const T& unit) { - x += unit; - y += unit; - w -= unit<<1; - h -= unit<<1; - return *this; - } - - RectT& shrink(const BorderT& br) { - x += br.left(); - y += br.top(); - w -= br.left() + br.right(); - h -= br.top() + br.bottom(); - return *this; - } - - // Returns true if this rectangle encloses the pt point. - bool contains(const PointT& pt) const { - return - pt.x >= x && pt.x < x+w && - pt.y >= y && pt.y < y+h; - } - - bool contains(const T& u, const T& v) const { - return - u >= x && u < x+w && - v >= y && v < y+h; - } - - // Returns true if this rectangle entirely contains the rc rectangle. - bool contains(const RectT& rc) const { - if (isEmpty() || rc.isEmpty()) - return false; - - return - rc.x >= x && rc.x+rc.w <= x+w && - rc.y >= y && rc.y+rc.h <= y+h; - } - - // Returns true if the intersection between this rectangle with rc - // rectangle is not empty. - bool intersects(const RectT& rc) const { - if (isEmpty() || rc.isEmpty()) - return false; - - return - rc.x < x+w && rc.x+rc.w > x && - rc.y < y+h && rc.y+rc.h > y; - } - - // Returns the union rectangle between this and rc rectangle. - RectT createUnion(const RectT& rc) const { - if (isEmpty()) - return rc; - else if (rc.isEmpty()) - return *this; - else - return RectT(PointT(x < rc.x ? x: rc.x, - y < rc.y ? y: rc.y), - PointT(x+w > rc.x+rc.w ? x+w: rc.x+rc.w, - y+h > rc.y+rc.h ? y+h: rc.y+rc.h)); - } - - // Returns the intersection rectangle between this and rc rectangles. - RectT createIntersection(const RectT& rc) const { - if (intersects(rc)) - return RectT(PointT(x > rc.x ? x: rc.x, - y > rc.y ? y: rc.y), - PointT(x+w < rc.x+rc.w ? x+w: rc.x+rc.w, - y+h < rc.y+rc.h ? y+h: rc.y+rc.h)); - else - return RectT(); - } - - const RectT& operator+=(const BorderT& br) { - enlarge(br); - return *this; - } - - const RectT& operator-=(const BorderT& br) { - shrink(br); - return *this; - } - - RectT& operator*=(const int factor) { - x *= factor; - y *= factor; - w *= factor; - h *= factor; - return *this; - } - - RectT& operator/=(const int factor) { - x /= factor; - y /= factor; - w /= factor; - h /= factor; - return *this; - } - - RectT& operator*=(const SizeT& size) { - x *= size.w; - y *= size.h; - w *= size.w; - h *= size.h; - return *this; - } - - RectT& operator/=(const SizeT& size) { - x /= size.w; - y /= size.h; - w /= size.w; - h /= size.h; - return *this; - } - - const RectT& operator|=(const RectT& rc) { - return *this = createUnion(rc); - } - - const RectT& operator&=(const RectT& rc) { - return *this = createIntersection(rc); - } - - RectT operator+(const BorderT& br) const { - return RectT(*this).enlarge(br); - } - - RectT operator-(const BorderT& br) const { - return RectT(*this).shrink(br); - } - - RectT operator|(const RectT& other) const { - return createUnion(other); - } - - RectT operator&(const RectT& other) const { - return createIntersection(other); - } - - RectT operator*(const SizeT& size) const { - return RectT(x*size.w, y*size.h, - w*size.w, h*size.h); - } - - RectT operator/(const SizeT& size) const { - return RectT(x/size.w, y/size.h, - w/size.w, h/size.h); - } - - bool operator==(const RectT& rc) const { - return - x == rc.x && w == rc.w && - y == rc.y && h == rc.h; - } - - bool operator!=(const RectT& rc) const { - return - x != rc.x || w != rc.w || - y != rc.y || h != rc.h; - } - -}; - -typedef RectT Rect; -typedef RectT RectF; - -} // namespace gfx - -#endif diff --git a/src/gfx/rect_io.h b/src/gfx/rect_io.h deleted file mode 100644 index 69be02bf7..000000000 --- a/src/gfx/rect_io.h +++ /dev/null @@ -1,42 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_RECT_IO_H_INCLUDED -#define GFX_RECT_IO_H_INCLUDED -#pragma once - -#include "gfx/rect.h" -#include - -namespace gfx { - - inline std::ostream& operator<<(std::ostream& os, const Rect& rect) { - return os << "(" - << rect.x << ", " - << rect.y << ", " - << rect.w << ", " - << rect.h << ")"; - } - - inline std::istream& operator>>(std::istream& in, Rect& rect) { - while (in && in.get() != '(') - ; - - if (!in) - return in; - - char chr; - in >> rect.x >> chr - >> rect.y >> chr - >> rect.w >> chr - >> rect.h >> chr; - - return in; - } - -} - -#endif diff --git a/src/gfx/rect_tests.cpp b/src/gfx/rect_tests.cpp deleted file mode 100644 index c890cfd5d..000000000 --- a/src/gfx/rect_tests.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2013 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gfx/border.h" -#include "gfx/rect.h" -#include "gfx/rect_io.h" -#include "gfx/size.h" - -using namespace std; -using namespace gfx; - -TEST(Rect, Ctor) -{ - EXPECT_EQ(Rect(0, 0, 0, 0), Rect()); - EXPECT_EQ(10, Rect(10, 20, 30, 40).x); - EXPECT_EQ(20, Rect(10, 20, 30, 40).y); - EXPECT_EQ(30, Rect(10, 20, 30, 40).w); - EXPECT_EQ(40, Rect(10, 20, 30, 40).h); -} - -TEST(Rect, Inflate) -{ - EXPECT_EQ(Rect(10, 20, 31, 42), Rect(10, 20, 30, 40).inflate(1, 2)); - EXPECT_EQ(Rect(10, 20, 31, 42), Rect(10, 20, 30, 40).inflate(Size(1, 2))); -} - -TEST(Rect, Enlarge) -{ - EXPECT_EQ(Rect(9, 19, 32, 42), Rect(10, 20, 30, 40).enlarge(1)); - EXPECT_EQ(Rect(9, 18, 34, 46), Rect(10, 20, 30, 40).enlarge(Border(1, 2, 3, 4))); - EXPECT_EQ(Rect(9, 18, 34, 46), Rect(10, 20, 30, 40) + Border(1, 2, 3, 4)); -} - -TEST(Rect, Shrink) -{ - EXPECT_EQ(Rect(11, 21, 28, 38), Rect(10, 20, 30, 40).shrink(1)); - EXPECT_EQ(Rect(11, 22, 26, 34), Rect(10, 20, 30, 40).shrink(Border(1, 2, 3, 4))); - EXPECT_EQ(Rect(11, 22, 26, 34), Rect(10, 20, 30, 40) - Border(1, 2, 3, 4)); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/gfx/region.cpp b/src/gfx/region.cpp deleted file mode 100644 index f141a1e72..000000000 --- a/src/gfx/region.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2013, 2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "pixman.h" - -#include "gfx/point.h" -#include "gfx/region.h" - -#include -#include -#include -#include - -namespace gfx { - -inline Rect to_rect(const pixman_box32& extends) -{ - return Rect( - extends.x1, extends.y1, - extends.x2 - extends.x1, - extends.y2 - extends.y1); -} - -Region::Region() -{ - pixman_region32_init(&m_region); -} - -Region::Region(const Region& copy) -{ - pixman_region32_init(&m_region); - pixman_region32_copy(&m_region, ©.m_region); -} - -Region::Region(const Rect& rect) -{ - if (!rect.isEmpty()) - pixman_region32_init_rect(&m_region, rect.x, rect.y, rect.w, rect.h); - else - pixman_region32_init(&m_region); -} - -Region::~Region() -{ - pixman_region32_fini(&m_region); -} - -Region& Region::operator=(const Rect& rect) -{ - if (!rect.isEmpty()) { - pixman_box32 box = { rect.x, rect.y, rect.x2(), rect.y2() }; - pixman_region32_reset(&m_region, &box); - } - else - pixman_region32_clear(&m_region); - return *this; -} - -Region& Region::operator=(const Region& copy) -{ - pixman_region32_copy(&m_region, ©.m_region); - return *this; -} - -Region::iterator Region::begin() -{ - iterator it; - it.m_ptr = pixman_region32_rectangles(&m_region, NULL); - return it; -} - -Region::iterator Region::end() -{ - iterator it; - it.m_ptr = pixman_region32_rectangles(&m_region, NULL) + size(); - return it; -} - -Region::const_iterator Region::begin() const -{ - const_iterator it; - it.m_ptr = pixman_region32_rectangles(&m_region, NULL); - return it; -} - -Region::const_iterator Region::end() const -{ - const_iterator it; - it.m_ptr = pixman_region32_rectangles(&m_region, NULL) + size(); - return it; -} - -bool Region::isEmpty() const -{ - return pixman_region32_not_empty(&m_region) ? false: true; -} - -Rect Region::bounds() const -{ - return to_rect(*pixman_region32_extents(&m_region)); -} - -std::size_t Region::size() const -{ - return pixman_region32_n_rects(&m_region); -} - -void Region::clear() -{ - pixman_region32_clear(&m_region); -} - -void Region::offset(int dx, int dy) -{ - pixman_region32_translate(&m_region, dx, dy); -} - -void Region::offset(const PointT& delta) -{ - pixman_region32_translate(&m_region, delta.x, delta.y); -} - -Region& Region::createIntersection(const Region& a, const Region& b) -{ - pixman_region32_intersect(&m_region, &a.m_region, &b.m_region); - return *this; -} - -Region& Region::createUnion(const Region& a, const Region& b) -{ - pixman_region32_union(&m_region, &a.m_region, &b.m_region); - return *this; -} - -Region& Region::createSubtraction(const Region& a, const Region& b) -{ - pixman_region32_subtract(&m_region, &a.m_region, &b.m_region); - return *this; -} - -bool Region::contains(const PointT& pt) const -{ - return pixman_region32_contains_point(&m_region, pt.x, pt.y, NULL) ? true: false; -} - -Region::Overlap Region::contains(const Rect& rect) const -{ - static_assert( - int(Out) == int(PIXMAN_REGION_OUT) && - int(In) == int(PIXMAN_REGION_IN) && - int(Part) == int(PIXMAN_REGION_PART), "Pixman constants have changed"); - - pixman_box32 box = { rect.x, rect.y, rect.x2(), rect.y2() }; - return (Region::Overlap)pixman_region32_contains_rectangle(&m_region, &box); -} - -Rect Region::operator[](int i) -{ - assert(i >= 0 && i < (int)size()); - return to_rect(pixman_region32_rectangles(&m_region, NULL)[i]); -} - -const Rect Region::operator[](int i) const -{ - assert(i >= 0 && i < (int)size()); - return to_rect(pixman_region32_rectangles(&m_region, NULL)[i]); -} - -} // namespace gfx diff --git a/src/gfx/region.h b/src/gfx/region.h deleted file mode 100644 index 568168c7b..000000000 --- a/src/gfx/region.h +++ /dev/null @@ -1,115 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_REGION_H_INCLUDED -#define GFX_REGION_H_INCLUDED -#pragma once - -#include "gfx/rect.h" -#include -#include - -namespace gfx { - - template class PointT; - - class Region; - - namespace details { - -#ifdef PIXMAN_VERSION_MAJOR - typedef struct pixman_box32 Box; - typedef struct pixman_region32 Region; -#else - struct Box { - int32_t x1, y1, x2, y2; - }; - struct Region { - Box extents; - void* data; - }; -#endif - - template - class RegionIterator : public std::iterator { - public: - typedef typename std::iterator::reference reference; - - RegionIterator() : m_ptr(NULL) { } - RegionIterator(const RegionIterator& o) : m_ptr(o.m_ptr) { } - template - RegionIterator(const RegionIterator& o) : m_ptr(o.m_ptr) { } - RegionIterator& operator=(const RegionIterator& o) { m_ptr = o.m_ptr; return *this; } - RegionIterator& operator++() { ++m_ptr; return *this; } - RegionIterator operator++(int) { RegionIterator o(*this); ++m_ptr; return o; } - bool operator==(const RegionIterator& o) const { return m_ptr == o.m_ptr; } - bool operator!=(const RegionIterator& o) const { return m_ptr != o.m_ptr; } - reference operator*() { - m_rect.x = m_ptr->x1; - m_rect.y = m_ptr->y1; - m_rect.w = m_ptr->x2 - m_ptr->x1; - m_rect.h = m_ptr->y2 - m_ptr->y1; - return m_rect; - } - private: - Box* m_ptr; - mutable Rect m_rect; - template friend class RegionIterator; - friend class ::gfx::Region; - }; - - } // namespace details - - class Region { - public: - enum Overlap { Out, In, Part }; - - typedef details::RegionIterator iterator; - typedef details::RegionIterator const_iterator; - - Region(); - Region(const Region& copy); - explicit Region(const Rect& rect); - Region& operator=(const Rect& rect); - Region& operator=(const Region& copy); - ~Region(); - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - bool isEmpty() const; - Rect bounds() const; - std::size_t size() const; - - void clear(); - - void offset(int dx, int dy); - void offset(const PointT& delta); - - Region& createIntersection(const Region& a, const Region& b); - Region& createUnion(const Region& a, const Region& b); - Region& createSubtraction(const Region& a, const Region& b); - - bool contains(const PointT& pt) const; - Overlap contains(const Rect& rect) const; - - Rect operator[](int i); - const Rect operator[](int i) const; - - Region& operator+=(const Region& b) { return createUnion(*this, b); } - Region& operator|=(const Region& b) { return createUnion(*this, b); } - Region& operator&=(const Region& b) { return createIntersection(*this, b); } - Region& operator-=(const Region& b) { return createSubtraction(*this, b); } - - private: - mutable details::Region m_region; - }; - -} // namespace gfx - -#endif diff --git a/src/gfx/region_tests.cpp b/src/gfx/region_tests.cpp deleted file mode 100644 index 99d4ea4a4..000000000 --- a/src/gfx/region_tests.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gfx/point.h" -#include "gfx/rect_io.h" -#include "gfx/region.h" - -using namespace std; -using namespace gfx; - -ostream& operator<<(ostream& os, const Region& rgn) -{ - os << "{"; - for (Region::const_iterator it=rgn.begin(), end=rgn.end(); - it != end; ) { - os << *it; - ++it; - if (it != end) - os << ", "; - } - os << "}"; - return os; -} - -TEST(Region, Ctor) -{ - EXPECT_EQ(0, Region().size()); - EXPECT_TRUE(Region(Rect(0, 0, 0, 0)).isEmpty()); - EXPECT_TRUE(Region().isEmpty()); - ASSERT_EQ(0, Region(Rect(0, 0, 0, 0)).size()); - ASSERT_EQ(1, Region(Rect(0, 0, 1, 1)).size()); - EXPECT_EQ(Rect(2, 3, 4, 5), Region(Rect(2, 3, 4, 5))[0]); -} - -TEST(Region, Equal) -{ - Region a; - a = Rect(2, 3, 4, 5); - EXPECT_EQ(Rect(2, 3, 4, 5), a.bounds()); - EXPECT_EQ(Rect(2, 3, 4, 5), a[0]); - EXPECT_FALSE(a.isEmpty()); - - a = Rect(6, 7, 8, 9); - EXPECT_EQ(Rect(6, 7, 8, 9), a.bounds()); - EXPECT_EQ(Rect(6, 7, 8, 9), a[0]); - - Region b; - b = a; - EXPECT_EQ(Rect(6, 7, 8, 9), b[0]); - - b = Rect(0, 0, 0, 0); - EXPECT_TRUE(b.isEmpty()); -} - -TEST(Region, Clear) -{ - Region a(Rect(2, 3, 4, 5)); - EXPECT_FALSE(a.isEmpty()); - a.clear(); - EXPECT_TRUE(a.isEmpty()); -} - -TEST(Region, Union) -{ - Region a(Rect(2, 3, 4, 5)); - Region b(Rect(6, 3, 4, 5)); - EXPECT_EQ(Rect(2, 3, 8, 5), Region().createUnion(a, b).bounds()); - EXPECT_EQ(Rect(2, 3, 8, 5), Region().createUnion(b, a).bounds()); - ASSERT_EQ(1, Region().createUnion(a, b).size()); - ASSERT_EQ(1, Region().createUnion(b, a).size()); - EXPECT_EQ(Rect(2, 3, 8, 5), Region().createUnion(a, b)[0]); - EXPECT_EQ(Rect(2, 3, 8, 5), Region().createUnion(b, a)[0]); -} - -TEST(Region, ContainsPoint) -{ - Region a(Rect(2, 3, 4, 5)); - EXPECT_TRUE(a.contains(Point(2, 3))); - EXPECT_FALSE(a.contains(Point(2-1, 3-1))); - EXPECT_FALSE(a.contains(Point(2+4, 3))); - EXPECT_FALSE(a.contains(Point(2, 3+5))); - EXPECT_FALSE(a.contains(Point(2+4, 3+5))); - EXPECT_TRUE(a.contains(Point(2+4-1, 3))); - EXPECT_TRUE(a.contains(Point(2, 3+5-1))); - EXPECT_TRUE(a.contains(Point(2+4-1, 3+5-1))); -} - -TEST(Region, Iterators) -{ - Region a; - a.createUnion(a, Region(Rect(0, 0, 32, 64))); - a.createUnion(a, Region(Rect(0, 0, 64, 32))); - int c = 0; - for (Region::iterator it=a.begin(), end=a.end(); it!=end; ++it) { - ++c; - } - EXPECT_EQ(2, c); - - c = 0; - for (Region::const_iterator it=a.begin(), end=a.end(); it!=end; ++it) { - ++c; - } - EXPECT_EQ(2, c); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/gfx/rgb.cpp b/src/gfx/rgb.cpp deleted file mode 100644 index 422cfa7b9..000000000 --- a/src/gfx/rgb.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "gfx/rgb.h" - -#include "gfx/hsl.h" -#include "gfx/hsv.h" -#include - -namespace gfx { - -using namespace std; - -// Reference: http://en.wikipedia.org/wiki/HSL_and_HSV -Rgb::Rgb(const Hsv& hsv) -{ - double chroma = hsv.value() * hsv.saturation(); - double hue_prime = hsv.hue() / 60.0; - double x = chroma * (1.0 - std::fabs(std::fmod(hue_prime, 2.0) - 1.0)); - double r, g, b; - - r = g = b = 0.0; - - switch (int(hue_prime)) { - - case 6: - case 0: - r = chroma; - g = x; - break; - case 1: - r = x; - g = chroma; - break; - - case 2: - g = chroma; - b = x; - break; - case 3: - g = x; - b = chroma; - break; - - case 4: - b = chroma; - r = x; - break; - case 5: - b = x; - r = chroma; - break; - } - - double m = hsv.value() - chroma; - r += m; - g += m; - b += m; - - m_red = int(r*255.0+0.5); - m_green = int(g*255.0+0.5); - m_blue = int(b*255.0+0.5); -} - -Rgb::Rgb(const Hsl& hsl) -{ - double chroma = (1.0 - std::fabs(2.0*hsl.lightness() - 1.0)) * hsl.saturation(); - double hue_prime = hsl.hue() / 60.0; - double x = chroma * (1.0 - std::fabs(std::fmod(hue_prime, 2.0) - 1.0)); - double r, g, b; - - r = g = b = 0.0; - - switch (int(hue_prime)) { - - case 6: - case 0: - r = chroma; - g = x; - break; - case 1: - r = x; - g = chroma; - break; - - case 2: - g = chroma; - b = x; - break; - case 3: - g = x; - b = chroma; - break; - - case 4: - b = chroma; - r = x; - break; - case 5: - b = x; - r = chroma; - break; - } - - double m = hsl.lightness() - chroma/2.0; - r += m; - g += m; - b += m; - - m_red = int(r*255.0+0.5); - m_green = int(g*255.0+0.5); - m_blue = int(b*255.0+0.5); -} - -int Rgb::maxComponent() const -{ - if (m_red > m_green) - return (m_red > m_blue) ? m_red: m_blue; - else - return (m_green > m_blue) ? m_green: m_blue; -} - -int Rgb::minComponent() const -{ - if (m_red < m_green) - return (m_red < m_blue) ? m_red: m_blue; - else - return (m_green < m_blue) ? m_green: m_blue; -} - -} // namespace gfx diff --git a/src/gfx/rgb.h b/src/gfx/rgb.h deleted file mode 100644 index 7ecb340e2..000000000 --- a/src/gfx/rgb.h +++ /dev/null @@ -1,94 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_RGB_H_INCLUDED -#define GFX_RGB_H_INCLUDED -#pragma once - -#include - -namespace gfx { - -class Hsv; -class Hsl; - -class Rgb { -public: - Rgb() - : m_red(0) - , m_green(0) - , m_blue(0) - { } - - Rgb(int red, int green, int blue) - : m_red(red) - , m_green(green) - , m_blue(blue) - { - assert(red >= 0 && red <= 255); - assert(green >= 0 && green <= 255); - assert(blue >= 0 && blue <= 255); - } - - Rgb(const Rgb& rgb) - : m_red(rgb.red()) - , m_green(rgb.green()) - , m_blue(rgb.blue()) - { } - - // Conversions - explicit Rgb(const Hsv& hsv); - explicit Rgb(const Hsl& hsl); - - int red() const { - return m_red; - } - - int green() const { - return m_green; - } - - int blue() const { - return m_blue; - } - - int maxComponent() const; - int minComponent() const; - - void red(int red) { - assert(red >= 0 && red <= 255); - m_red = red; - } - - void green(int green) { - assert(green >= 0 && green <= 255); - m_green = green; - } - - void blue(int blue) { - assert(blue >= 0 && blue <= 255); - m_blue = blue; - } - - bool operator==(const Rgb& other) const { - return (m_red == other.m_red && - m_green == other.m_green && - m_blue == other.m_blue); - } - - bool operator!=(const Rgb& other) const { - return !operator==(other); - } - -private: - int m_red; - int m_green; - int m_blue; -}; - -} // namespace gfx - -#endif diff --git a/src/gfx/rgb_tests.cpp b/src/gfx/rgb_tests.cpp deleted file mode 100644 index acfc621df..000000000 --- a/src/gfx/rgb_tests.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2013 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gfx/rgb.h" -#include "gfx/hsv.h" - -using namespace gfx; -using namespace std; - -namespace gfx { - - ostream& operator<<(ostream& os, const Rgb& rgb) { - return os << "(" - << rgb.red() << ", " - << rgb.green() << ", " - << rgb.blue() << ")"; - } - -} - -TEST(Rgb, Ctor) -{ - EXPECT_EQ(1, Rgb(1, 2, 3).red()); - EXPECT_EQ(2, Rgb(1, 2, 3).green()); - EXPECT_EQ(3, Rgb(1, 2, 3).blue()); - EXPECT_EQ(Rgb(0, 0, 0), Rgb()); -} - -TEST(Rgb, Equal) -{ - EXPECT_TRUE(Rgb(1, 2, 3) == Rgb(1, 2, 3)); - EXPECT_FALSE(Rgb(1, 2, 3) != Rgb(1, 2, 3)); - EXPECT_FALSE(Rgb(1, 2, 3) == Rgb(1, 3, 2)); - EXPECT_FALSE(Rgb(0, 0, 0) == Rgb(0, 0, 1)); - EXPECT_FALSE(Rgb(0, 0, 0) == Rgb(0, 1, 0)); - EXPECT_FALSE(Rgb(0, 0, 0) == Rgb(1, 0, 0)); -} - -TEST(Rgb, MaxComponent) -{ - EXPECT_EQ(3, Rgb(1, 2, 3).maxComponent()); - EXPECT_EQ(3, Rgb(1, 3, 2).maxComponent()); - EXPECT_EQ(3, Rgb(2, 1, 3).maxComponent()); - EXPECT_EQ(3, Rgb(2, 3, 1).maxComponent()); - EXPECT_EQ(3, Rgb(3, 1, 2).maxComponent()); - EXPECT_EQ(3, Rgb(3, 2, 1).maxComponent()); -} - -TEST(Rgb, MinComponent) -{ - EXPECT_EQ(1, Rgb(1, 2, 3).minComponent()); - EXPECT_EQ(1, Rgb(1, 3, 2).minComponent()); - EXPECT_EQ(1, Rgb(2, 1, 3).minComponent()); - EXPECT_EQ(1, Rgb(2, 3, 1).minComponent()); - EXPECT_EQ(1, Rgb(3, 1, 2).minComponent()); - EXPECT_EQ(1, Rgb(3, 2, 1).minComponent()); -} - -TEST(Rgb, FromHsv) -{ - for (double hue = 0.0; hue <= 360.0; hue += 10.0) { - EXPECT_EQ(Rgb(255, 255, 255), Rgb(Hsv(hue, 0.000, 1.000))); - EXPECT_EQ(Rgb(128, 128, 128), Rgb(Hsv(hue, 0.000, 0.500))); - EXPECT_EQ(Rgb( 0, 0, 0), Rgb(Hsv(hue, 0.000, 0.000))); - } - - EXPECT_EQ(Rgb( 3, 0, 0), Rgb(Hsv( 0.0, 1.000, 0.010))); - EXPECT_EQ(Rgb(252, 0, 0), Rgb(Hsv( 0.0, 1.000, 0.990))); - EXPECT_EQ(Rgb(255, 0, 0), Rgb(Hsv( 0.0, 1.000, 1.000))); - EXPECT_EQ(Rgb(191, 191, 0), Rgb(Hsv( 60.0, 1.000, 0.750))); - EXPECT_EQ(Rgb( 0, 128, 0), Rgb(Hsv(120.0, 1.000, 0.500))); - EXPECT_EQ(Rgb( 0, 255, 0), Rgb(Hsv(120.0, 1.000, 1.000))); - EXPECT_EQ(Rgb(128, 255, 255), Rgb(Hsv(180.0, 0.500, 1.000))); - EXPECT_EQ(Rgb(128, 128, 255), Rgb(Hsv(240.0, 0.500, 1.000))); - EXPECT_EQ(Rgb( 0, 0, 255), Rgb(Hsv(240.0, 1.000, 1.000))); - EXPECT_EQ(Rgb(191, 64, 191), Rgb(Hsv(300.0, 0.667, 0.750))); - EXPECT_EQ(Rgb(252, 0, 0), Rgb(Hsv(360.0, 1.000, 0.990))); - EXPECT_EQ(Rgb(255, 0, 0), Rgb(Hsv(360.0, 1.000, 1.000))); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/gfx/size.h b/src/gfx/size.h deleted file mode 100644 index ed6c4738e..000000000 --- a/src/gfx/size.h +++ /dev/null @@ -1,145 +0,0 @@ -// Aseprite Gfx Library -// Copyright (C) 2001-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef GFX_SIZE_H_INCLUDED -#define GFX_SIZE_H_INCLUDED -#pragma once - -#include - -namespace gfx { - -template -class PointT; - -// A 2D size. -template -class SizeT -{ -public: - T w, h; - - SizeT() : w(0), h(0) { - } - - SizeT(const T& w, const T& h) : w(w), h(h) { - } - - SizeT(const SizeT& size) : w(size.w), h(size.h) { - } - - template - explicit SizeT(const SizeT& size) : w(static_cast(size.w)), - h(static_cast(size.h)) { - } - - explicit SizeT(const PointT& point) : w(point.x), h(point.y) { - } - - SizeT createUnion(const SizeT& sz) const { - return SizeT(std::max(w, sz.w), - std::max(h, sz.h)); - } - - SizeT createIntersection(const SizeT& sz) const { - return SizeT(std::min(w, sz.w), - std::min(h, sz.h)); - } - - const SizeT& operator=(const SizeT& sz) { - w = sz.w; - h = sz.h; - return *this; - } - - const SizeT& operator+=(const SizeT& sz) { - w += sz.w; - h += sz.h; - return *this; - } - - const SizeT& operator-=(const SizeT& sz) { - w -= sz.w; - h -= sz.h; - return *this; - } - - const SizeT& operator+=(const T& value) { - w += value; - h += value; - return *this; - } - - const SizeT& operator-=(const T& value) { - w -= value; - h -= value; - return *this; - } - - const SizeT& operator*=(const T& value) { - w *= value; - h *= value; - return *this; - } - - const SizeT& operator/=(const T& value) { - w /= value; - h /= value; - return *this; - } - - const SizeT& operator|=(const SizeT& sz) { - return *this = createUnion(sz); - } - - const SizeT& operator&=(const SizeT& sz) { - return *this = createIntersection(sz); - } - - SizeT operator+(const SizeT& sz) const { - return SizeT(w+sz.w, h+sz.h); - } - - SizeT operator-(const SizeT& sz) const { - return SizeT(w-sz.w, h-sz.h); - } - - SizeT operator+(const T& value) const { - return SizeT(w+value, h+value); - } - - SizeT operator-(const T& value) const { - return SizeT(w-value, h-value); - } - - SizeT operator*(const T& value) const { - return SizeT(w*value, h*value); - } - - SizeT operator/(const T& value) const { - return SizeT(w/value, h/value); - } - - SizeT operator-() const { - return SizeT(-w, -h); - } - - bool operator==(const SizeT& sz) const { - return w == sz.w && h == sz.h; - } - - bool operator!=(const SizeT& sz) const { - return w != sz.w || h != sz.h; - } - -}; - -typedef SizeT Size; -typedef SizeT SizeF; - -} // namespace gfx - -#endif diff --git a/src/os/CMakeLists.txt b/src/os/CMakeLists.txt deleted file mode 100644 index a408958d6..000000000 --- a/src/os/CMakeLists.txt +++ /dev/null @@ -1,175 +0,0 @@ -# LAF OS -# Copyright (C) 2012-2018 David Capello - -# TODO the following variables should be available through options -# in this file instead of the main Aseprite CMakeLists.txt: -# - USE_NONE_BACKEND -# - USE_SKIA_BACKEND -# - WITH_GTK_FILE_DIALOG_SUPPORT - -set(OS_SOURCES - common/freetype_font.cpp - draw_text.cpp - system.cpp) - -###################################################################### -# Skia backend - -if(USE_SKIA_BACKEND) - set(SKIA_DIR "" CACHE PATH "Skia source code directory") - - add_definitions( - -DSK_INTERNAL - -DSK_GAMMA_SRGB - -DSK_GAMMA_APPLY_TO_A8 - -DSK_SCALAR_TO_FLOAT_EXCLUDED - -DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1 - -DSK_SUPPORT_OPENCL=0 - -DSK_FORCE_DISTANCE_FIELD_TEXT=0 - -DGR_GL_FUNCTION_TYPE=__stdcall - # TODO change this to 1 - -DSK_SUPPORT_GPU=0) - - if(WIN32) - add_definitions(-DSK_BUILD_FOR_WIN32) - elseif(APPLE) - add_definitions(-DSK_BUILD_FOR_MAC) - add_definitions(-Wno-ignored-attributes -Wno-unused-result) - - # Use Automatic Reference Counting - add_definitions(-fobjc-arc) - else() - add_definitions(-DSK_SAMPLES_FOR_X) - endif() - - if(NOT SKIA_DIR) - set(SKIA_OUT_DIR "" CACHE PATH "Skia output directory") - else() - if(CMAKE_BUILD_TYPE STREQUAL Debug) - set(SKIA_OUT_DIR "${SKIA_DIR}/out/Debug" CACHE PATH "Skia output directory") - else() - set(SKIA_OUT_DIR "${SKIA_DIR}/out/Release" CACHE PATH "Skia output directory") - endif() - endif() - - find_library(SKIA_LIBRARY skia PATH "${SKIA_OUT_DIR}") - if(WIN32) - find_library(SKIA_OPENGL_LIBRARY opengl32) - else() - find_library(SKIA_OPENGL_LIBRARY opengl NAMES GL) - endif() - - find_path(SKIA_CONFIG_INCLUDE_DIR SkUserConfig.h HINTS "${SKIA_DIR}/include/config") - find_path(SKIA_CORE_INCLUDE_DIR SkCanvas.h HINTS "${SKIA_DIR}/include/core") - find_path(SKIA_UTILS_INCLUDE_DIR SkRandom.h HINTS "${SKIA_DIR}/include/utils") - find_path(SKIA_CODEC_INCLUDE_DIR SkCodec.h HINTS "${SKIA_DIR}/include/codec") - find_path(SKIA_EFFECTS_INCLUDE_DIR SkImageSource.h HINTS "${SKIA_DIR}/include/effects") - find_path(SKIA_GPU_INCLUDE_DIR GrContext.h HINTS "${SKIA_DIR}/include/gpu") - find_path(SKIA_GPU2_INCLUDE_DIR gl/GrGLDefines.h HINTS "${SKIA_DIR}/src/gpu") - find_path(SKIA_ANGLE_INCLUDE_DIR angle_gl.h HINTS "${SKIA_DIR}/third_party/externals/angle2/include") - - include_directories( - ${SKIA_CONFIG_INCLUDE_DIR} - ${SKIA_CORE_INCLUDE_DIR} - ${SKIA_PORTS_INCLUDE_DIR} - ${SKIA_UTILS_INCLUDE_DIR} - ${SKIA_CODEC_INCLUDE_DIR} - ${SKIA_GPU_INCLUDE_DIR} - ${SKIA_GPU2_INCLUDE_DIR}) - if(WIN32) - include_directories(${SKIA_ANGLE_INCLUDE_DIR}) - endif() - - set(SKIA_LIBRARIES - ${SKIA_LIBRARY} - ${SKIA_OPENGL_LIBRARY} - CACHE INTERNAL "Skia libraries") - - list(APPEND OS_SOURCES - skia/skia_display.cpp - skia/skia_surface.cpp - skia/os.cpp) - - if(WIN32) - list(APPEND OS_SOURCES - skia/skia_window_win.cpp - win/keys.cpp - win/pen.cpp - win/winapi.cpp - win/window.cpp - win/window_dde.cpp) - elseif(APPLE) - list(APPEND OS_SOURCES - osx/app.mm - osx/app_delegate.mm - osx/event_queue.mm - osx/keys.mm - osx/view.mm - osx/window.mm - skia/skia_window_osx.mm) - else() - list(APPEND OS_SOURCES - skia/skia_window_x11.cpp - x11/event_queue.cpp - x11/keys.cpp - x11/window.cpp - x11/x11.cpp) - endif() -endif() - -###################################################################### -# None backend - -if(USE_NONE_BACKEND) - list(APPEND OS_SOURCES - none/os.cpp) -endif() - -###################################################################### - -if(WIN32) - list(APPEND OS_SOURCES - win/native_dialogs.cpp) -endif() - -if(APPLE) - list(APPEND OS_SOURCES - osx/logger.mm - osx/menus.mm - osx/native_dialogs.mm) -endif() - -if(WITH_GTK_FILE_DIALOG_SUPPORT AND UNIX AND NOT APPLE AND NOT BEOS) - # Find gtkmm library - find_package(PkgConfig REQUIRED) - pkg_check_modules(GTK gtk+-3.0) - include_directories(${GTK_INCLUDE_DIRS}) - link_directories(${GTK_LIBRARY_DIRS}) - - add_definitions(-DASEPRITE_WITH_GTK_FILE_DIALOG_SUPPORT) - list(APPEND OS_SOURCES - gtk/native_dialogs.cpp) -endif() - -add_library(os-lib ${OS_SOURCES}) - -target_link_libraries(os-lib - ft-lib - gfx-lib - laf-base - ${FREETYPE_LIBRARIES}) - -if(USE_SKIA_BACKEND) - target_link_libraries(os-lib - ${SKIA_LIBRARIES} - ${X11_LIBRARIES}) - - if(UNIX AND NOT APPLE) - target_link_libraries(os-lib fontconfig Xcursor) - endif() -endif() - -if(WITH_GTK_FILE_DIALOG_SUPPORT) - target_link_libraries(os-lib - ${GTKMM_LIBRARIES}) -endif() diff --git a/src/os/LICENSE.txt b/src/os/LICENSE.txt deleted file mode 100644 index b023b6f24..000000000 --- a/src/os/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2012-2018 David Capello - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/os/README.md b/src/os/README.md deleted file mode 100644 index 8915a3480..000000000 --- a/src/os/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# LAF OS Library - -`os` is an abstraction layer to access in different way the Operating -System graphics interface. We have our own implementation to create -windows and handle mouse/keyboard input. The graphics are rendered -using the [Skia](https://skia.org/) library. - -* Minimum Windows platform: Windows Vista diff --git a/src/os/capabilities.h b/src/os/capabilities.h deleted file mode 100644 index 8463919c0..000000000 --- a/src/os/capabilities.h +++ /dev/null @@ -1,23 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_CAPABILITIES_H_INCLUDED -#define OS_CAPABILITIES_H_INCLUDED -#pragma once - -namespace os { - - enum class Capabilities { - MultipleDisplays = 1, - CanResizeDisplay = 2, - DisplayScale = 4, - CustomNativeMouseCursor = 8, - GpuAccelerationSwitch = 16 - }; - -} // namespace os - -#endif diff --git a/src/os/common/file_dialog.h b/src/os/common/file_dialog.h deleted file mode 100644 index 6c267ccf5..000000000 --- a/src/os/common/file_dialog.h +++ /dev/null @@ -1,53 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_COMMON_FILE_DIALOG_H -#define OS_COMMON_FILE_DIALOG_H -#pragma once - -#include "os/native_dialogs.h" - -namespace os { - -class CommonFileDialog : public FileDialog { -public: - CommonFileDialog() - : m_type(Type::OpenFile) { - } - - void dispose() override { - delete this; - } - - void setType(const Type type) override { - m_type = type; - } - - void setTitle(const std::string& title) override { - m_title = title; - } - - void setDefaultExtension(const std::string& extension) override { - m_defExtension = extension; - } - - void addFilter(const std::string& extension, const std::string& description) override { - if (m_defExtension.empty()) - m_defExtension = extension; - - m_filters.push_back(std::make_pair(extension, description)); - } - -protected: - Type m_type; - std::string m_title; - std::string m_defExtension; - std::vector> m_filters; -}; - -} // namespace os - -#endif diff --git a/src/os/common/freetype_font.cpp b/src/os/common/freetype_font.cpp deleted file mode 100644 index 061178d37..000000000 --- a/src/os/common/freetype_font.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/common/freetype_font.h" - -#include "base/string.h" -#include "ft/algorithm.h" -#include "gfx/point.h" -#include "gfx/size.h" - -namespace os { - -FreeTypeFont::FreeTypeFont(ft::Lib& lib, - const char* filename, - const int height) - : m_face(lib.open(filename)) -{ - if (m_face.isValid()) - m_face.setSize(height); -} - -FreeTypeFont::~FreeTypeFont() -{ -} - -bool FreeTypeFont::isValid() const -{ - return m_face.isValid(); -} - -void FreeTypeFont::dispose() -{ - delete this; -} - -FontType FreeTypeFont::type() -{ - return FontType::kTrueType; -} - -int FreeTypeFont::height() const -{ - return int(m_face.height()); -} - -int FreeTypeFont::textLength(const std::string& str) const -{ - return ft::calc_text_bounds(m_face, str).w; -} - -bool FreeTypeFont::isScalable() const -{ - return true; -} - -void FreeTypeFont::setSize(int size) -{ - m_face.setSize(size); -} - -void FreeTypeFont::setAntialias(bool antialias) -{ - m_face.setAntialias(antialias); -} - -bool FreeTypeFont::hasCodePoint(int codepoint) const -{ - return m_face.hasCodePoint(codepoint); -} - -FreeTypeFont* load_free_type_font(ft::Lib& lib, - const char* filename, - const int height) -{ - FreeTypeFont* font = new FreeTypeFont(lib, filename, height); - if (!font->isValid()) { - delete font; - font = nullptr; - } - return font; -} - -} // namespace os diff --git a/src/os/common/freetype_font.h b/src/os/common/freetype_font.h deleted file mode 100644 index 3d09f423c..000000000 --- a/src/os/common/freetype_font.h +++ /dev/null @@ -1,49 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_COMMON_FREETYPE_FONT_H_INCLUDED -#define OS_COMMON_FREETYPE_FONT_H_INCLUDED -#pragma once - -#include "ft/hb_face.h" -#include "ft/lib.h" -#include "os/font.h" - -namespace os { - class Font; - - class FreeTypeFont : public Font { - public: - typedef ft::Face Face; - - FreeTypeFont(ft::Lib& lib, - const char* filename, - const int height); - ~FreeTypeFont(); - - bool isValid() const; - void dispose() override; - FontType type() override; - int height() const override; - int textLength(const std::string& str) const override; - bool isScalable() const override; - void setSize(int size) override; - void setAntialias(bool antialias) override; - bool hasCodePoint(int codepoint) const override; - - Face& face() { return m_face; } - - private: - mutable Face m_face; - }; - - FreeTypeFont* load_free_type_font(ft::Lib& lib, - const char* filename, - const int height); - -} // namespace os - -#endif diff --git a/src/os/common/generic_surface.h b/src/os/common/generic_surface.h deleted file mode 100644 index 15e022910..000000000 --- a/src/os/common/generic_surface.h +++ /dev/null @@ -1,97 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_COMMON_GENERIC_SURFACE_H -#define OS_COMMON_GENERIC_SURFACE_H -#pragma once - -#include "gfx/clip.h" -#include "gfx/color.h" -#include "os/surface.h" - -namespace os { - -namespace { - -#define MUL_UN8(a, b, t) \ - ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8)) - -inline gfx::Color blend(const gfx::Color backdrop, gfx::Color src) -{ - if (gfx::geta(backdrop) == 0) - return src; - else if (gfx::geta(src) == 0) - return backdrop; - - int Br, Bg, Bb, Ba; - int Sr, Sg, Sb, Sa; - int Rr, Rg, Rb, Ra; - - Br = gfx::getr(backdrop); - Bg = gfx::getg(backdrop); - Bb = gfx::getb(backdrop); - Ba = gfx::geta(backdrop); - - Sr = gfx::getr(src); - Sg = gfx::getg(src); - Sb = gfx::getb(src); - Sa = gfx::geta(src); - - int t; - Ra = Ba + Sa - MUL_UN8(Ba, Sa, t); - Rr = Br + (Sr-Br) * Sa / Ra; - Rg = Bg + (Sg-Bg) * Sa / Ra; - Rb = Bb + (Sb-Bb) * Sa / Ra; - - return gfx::rgba(Rr, Rg, Rb, Ra); -} - -} // anoynmous namespace - -template -class GenericDrawColoredRgbaSurface : public Base { -public: - - void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override { - gfx::Clip clip(clipbase); - if (!clip.clip(this->width(), - this->height(), - src->width(), src->height())) - return; - - SurfaceFormatData format; - src->getFormat(&format); - - ASSERT(format.format == kRgbaSurfaceFormat); - ASSERT(format.bitsPerPixel == 32); - - for (int v=0; vgetData( - clip.src.x, clip.src.y+v); - - for (int u=0; ugetPixel(clip.dst.x+u, clip.dst.y+v); - if (gfx::geta(bg) > 0) - dstColor = blend(dstColor, bg); - - uint32_t src = (((*ptr) & format.alphaMask) >> format.alphaShift); - if (src > 0) { - src = gfx::rgba(gfx::getr(fg), - gfx::getg(fg), - gfx::getb(fg), src); - dstColor = blend(dstColor, src); - } - - this->putPixel(dstColor, clip.dst.x+u, clip.dst.y+v); - ++ptr; - } - } - } -}; - -} // namespace os - -#endif diff --git a/src/os/common/sprite_sheet_font.h b/src/os/common/sprite_sheet_font.h deleted file mode 100644 index abfc70059..000000000 --- a/src/os/common/sprite_sheet_font.h +++ /dev/null @@ -1,138 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SPRITE_SHEET_FONT_H -#define OS_SPRITE_SHEET_FONT_H -#pragma once - -#include "base/debug.h" -#include "base/string.h" -#include "gfx/rect.h" -#include "os/font.h" -#include "os/surface.h" - -#include - -namespace os { - -class SpriteSheetFont : public Font { -public: - - SpriteSheetFont() : m_sheet(nullptr) { - } - - ~SpriteSheetFont() { - ASSERT(m_sheet); - m_sheet->dispose(); - } - - void dispose() override { - delete this; - } - - FontType type() override { - return FontType::kSpriteSheet; - } - - int height() const override { - return getCharBounds(' ').h; - } - - int textLength(const std::string& str) const override { - base::utf8_const_iterator it(str.begin()), end(str.end()); - int x = 0; - while (it != end) { - x += getCharBounds(*it).w; - ++it; - } - return x; - } - - bool isScalable() const override { - return false; - } - - void setSize(int size) override { - // Do nothing - } - - void setAntialias(bool antialias) override { - // Do nothing - } - - bool hasCodePoint(int codepoint) const override { - codepoint -= (int)' '; - return (codepoint >= 0 && codepoint < (int)m_chars.size()); - } - - Surface* getSurfaceSheet() const { - return m_sheet; - } - - gfx::Rect getCharBounds(int chr) const { - chr -= (int)' '; - if (chr >= 0 && chr < (int)m_chars.size()) - return m_chars[chr]; - else if (chr != 128) - return getCharBounds(128); - else - return gfx::Rect(); - } - - static Font* fromSurface(Surface* sur) { - SpriteSheetFont* font = new SpriteSheetFont; - font->m_sheet = sur; - - SurfaceLock lock(sur); - gfx::Rect bounds(0, 0, 1, 1); - - while (font->findChar(sur, sur->width(), sur->height(), bounds)) { - font->m_chars.push_back(bounds); - bounds.x += bounds.w; - } - - return font; - } - -private: - - bool findChar(const Surface* sur, int width, int height, gfx::Rect& bounds) { - gfx::Color keyColor = sur->getPixel(0, 0); - - while (sur->getPixel(bounds.x, bounds.y) == keyColor) { - bounds.x++; - if (bounds.x >= width) { - bounds.x = 0; - bounds.y += bounds.h; - bounds.h = 1; - if (bounds.y >= height) - return false; - } - } - - bounds.w = 0; - while ((bounds.x+bounds.w < width) && - (sur->getPixel(bounds.x+bounds.w, bounds.y) != keyColor)) { - bounds.w++; - } - - bounds.h = 0; - while ((bounds.y+bounds.h < height) && - (sur->getPixel(bounds.x, bounds.y+bounds.h) != keyColor)) { - bounds.h++; - } - - return !bounds.isEmpty(); - } - -private: - Surface* m_sheet; - std::vector m_chars; -}; - -} // namespace os - -#endif diff --git a/src/os/common/system.h b/src/os/common/system.h deleted file mode 100644 index 584d0839a..000000000 --- a/src/os/common/system.h +++ /dev/null @@ -1,139 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_COMMON_SYSTEM_H -#define OS_COMMON_SYSTEM_H -#pragma once - -#ifdef _WIN32 - #include "os/win/native_dialogs.h" -#elif defined(__APPLE__) - #include "os/osx/menus.h" - #include "os/osx/native_dialogs.h" -#elif defined(ASEPRITE_WITH_GTK_FILE_DIALOG_SUPPORT) && defined(__linux__) - #include "os/gtk/native_dialogs.h" -#else - #include "os/native_dialogs.h" -#endif - -#include "ft/lib.h" -#include "os/common/freetype_font.h" -#include "os/common/sprite_sheet_font.h" -#include "os/menus.h" -#include "os/system.h" - -#include - -namespace os { - -#ifdef __APPLE__ -Logger* getOsxLogger(); -#endif - -class CommonSystem : public System { -public: - CommonSystem() - : m_nativeDialogs(nullptr) - , m_menus(nullptr) { -#ifdef _WIN32 - m_useWintabAPI = true; -#endif - } - - ~CommonSystem() { - delete m_nativeDialogs; - delete m_menus; - } - - void dispose() override { - delete this; - } - - void useWintabAPI(bool state) override { -#ifdef _WIN32 - m_useWintabAPI = state; -#endif - } - -#ifdef _WIN32 - bool useWintabAPI() const { - return m_useWintabAPI; - } -#endif - - Logger* logger() override { -#ifdef __APPLE__ - return getOsxLogger(); -#else - return nullptr; -#endif - } - - Menus* menus() override { -#ifdef __APPLE__ - if (!m_menus) - m_menus = new MenusOSX(); -#endif - return m_menus; - } - - NativeDialogs* nativeDialogs() override { -#ifdef _WIN32 - if (!m_nativeDialogs) - m_nativeDialogs = new NativeDialogsWin32(); -#elif defined(__APPLE__) - if (!m_nativeDialogs) - m_nativeDialogs = new NativeDialogsOSX(); -#elif defined(ASEPRITE_WITH_GTK_FILE_DIALOG_SUPPORT) && defined(__linux__) - if (!m_nativeDialogs) - m_nativeDialogs = new NativeDialogsGTK(); -#endif - return m_nativeDialogs; - } - - Font* loadSpriteSheetFont(const char* filename, int scale) override { - Surface* sheet = loadRgbaSurface(filename); - Font* font = nullptr; - if (sheet) { - sheet->applyScale(scale); - font = SpriteSheetFont::fromSurface(sheet); - } - return font; - } - - Font* loadTrueTypeFont(const char* filename, int height) override { - if (!m_ft) - m_ft.reset(new ft::Lib()); - return load_free_type_font(*m_ft.get(), filename, height); - } - - KeyModifiers keyModifiers() override { - return - (KeyModifiers) - ((isKeyPressed(kKeyLShift) || - isKeyPressed(kKeyRShift) ? kKeyShiftModifier: 0) | - (isKeyPressed(kKeyLControl) || - isKeyPressed(kKeyRControl) ? kKeyCtrlModifier: 0) | - (isKeyPressed(kKeyAlt) ? kKeyAltModifier: 0) | - (isKeyPressed(kKeyAltGr) ? (kKeyCtrlModifier | kKeyAltModifier): 0) | - (isKeyPressed(kKeyCommand) ? kKeyCmdModifier: 0) | - (isKeyPressed(kKeySpace) ? kKeySpaceModifier: 0) | - (isKeyPressed(kKeyLWin) || - isKeyPressed(kKeyRWin) ? kKeyWinModifier: 0)); - } - -private: -#ifdef _WIN32 - bool m_useWintabAPI; -#endif - NativeDialogs* m_nativeDialogs; - Menus* m_menus; - std::unique_ptr m_ft; -}; - -} // namespace os - -#endif diff --git a/src/os/display.h b/src/os/display.h deleted file mode 100644 index 726ebaceb..000000000 --- a/src/os/display.h +++ /dev/null @@ -1,86 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_DISPLAY_H_INCLUDED -#define OS_DISPLAY_H_INCLUDED -#pragma once - -#include "gfx/point.h" -#include "os/display_handle.h" -#include "os/native_cursor.h" -#include "os/surface_list.h" - -#include - -namespace os { - - class Surface; - - // A display or window to show graphics. - class Display { - public: - virtual ~Display() { } - virtual void dispose() = 0; - - // Returns the real and current display's size (without scale applied). - virtual int width() const = 0; - virtual int height() const = 0; - - // Returns the display when it was not maximized. - virtual int originalWidth() const = 0; - virtual int originalHeight() const = 0; - - // Returns the current display scale. Each pixel in the internal - // display surface, is represented by SCALExSCALE pixels on the - // screen. - virtual int scale() const = 0; - - // Changes the scale. - // The available surface size will be (Display::width() / scale, - // Display::height() / scale) - virtual void setScale(int scale) = 0; - - // Returns the main surface to draw into this display. - // You must not dispose this surface. - virtual Surface* getSurface() = 0; - - // Flips all graphics in the surface to the real display. - virtual void flip(const gfx::Rect& bounds) = 0; - - virtual void maximize() = 0; - virtual bool isMaximized() const = 0; - virtual bool isMinimized() const = 0; - - virtual void setTitleBar(const std::string& title) = 0; - virtual void setIcons(const SurfaceList& icons) = 0; - - virtual NativeCursor nativeMouseCursor() = 0; - virtual bool setNativeMouseCursor(NativeCursor cursor) = 0; - virtual bool setNativeMouseCursor(const os::Surface* cursor, - const gfx::Point& focus, - const int scale) = 0; - virtual void setMousePosition(const gfx::Point& position) = 0; - virtual void captureMouse() = 0; - virtual void releaseMouse() = 0; - - // Set/get the specific information to restore the exact same - // window position (e.g. in the same monitor). - virtual std::string getLayout() = 0; - virtual void setLayout(const std::string& layout) = 0; - - // For Windows 8/10 only in tablet devices: Set to true if you - // want to interpret one finger as the mouse movement and two - // fingers as pan/scroll (true by default). If you want to pan - // with one finger, call this function with false. - virtual void setInterpretOneFingerGestureAsMouseMovement(bool state) = 0; - - // Returns the HWND on Windows. - virtual DisplayHandle nativeHandle() = 0; - }; - -} // namespace os - -#endif diff --git a/src/os/display_handle.h b/src/os/display_handle.h deleted file mode 100644 index 869aa321a..000000000 --- a/src/os/display_handle.h +++ /dev/null @@ -1,17 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_DISPLAY_HANDLE_H_INCLUDED -#define OS_DISPLAY_HANDLE_H_INCLUDED -#pragma once - -namespace os { - - typedef void* DisplayHandle; - -} // namespace os - -#endif diff --git a/src/os/draw_text.cpp b/src/os/draw_text.cpp deleted file mode 100644 index 404a2ea16..000000000 --- a/src/os/draw_text.cpp +++ /dev/null @@ -1,228 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/draw_text.h" - -#include "ft/algorithm.h" -#include "ft/hb_shaper.h" -#include "gfx/clip.h" -#include "os/common/freetype_font.h" -#include "os/common/generic_surface.h" -#include "os/common/sprite_sheet_font.h" - -namespace os { - -gfx::Rect draw_text(Surface* surface, Font* font, - const base::utf8_const_iterator& begin, - const base::utf8_const_iterator& end, - gfx::Color fg, gfx::Color bg, - int x, int y, - DrawTextDelegate* delegate) -{ - base::utf8_const_iterator it = begin; - gfx::Rect textBounds; - -retry:; - // Check if this font is enough to draw the given string or we will - // need the fallback for some special Unicode chars - if (font->fallback()) { - // TODO compose unicode characters and check those codepoints, the - // same in the drawing code of sprite sheet font - for (auto it=begin; it!=end; ++it) { - uint32_t code = *it; - if (code && !font->hasCodePoint(code)) { - Font* newFont = font->fallback(); - - // Search a valid fallback - while (newFont && !newFont->hasCodePoint(code)) - newFont = newFont->fallback(); - if (!newFont) - break; - - y += font->height()/2 - newFont->height()/2; - - font = newFont; - goto retry; - } - } - } - - switch (font->type()) { - - case FontType::kSpriteSheet: { - SpriteSheetFont* ssFont = static_cast(font); - Surface* sheet = ssFont->getSurfaceSheet(); - - if (surface) { - sheet->lock(); - surface->lock(); - } - - while (it != end) { - int chr = *it; - if (delegate) { - int i = it-begin; - delegate->preProcessChar(i, chr, fg, bg); - } - - gfx::Rect charBounds = ssFont->getCharBounds(chr); - gfx::Rect outCharBounds(x, y, charBounds.w, charBounds.h); - if (delegate && !delegate->preDrawChar(outCharBounds)) - break; - - if (!charBounds.isEmpty()) { - if (surface) - surface->drawColoredRgbaSurface(sheet, fg, bg, gfx::Clip(x, y, charBounds)); - } - - textBounds |= outCharBounds; - if (delegate) - delegate->postDrawChar(outCharBounds); - - x += charBounds.w; - ++it; - } - - if (surface) { - surface->unlock(); - sheet->unlock(); - } - break; - } - - case FontType::kTrueType: { - FreeTypeFont* ttFont = static_cast(font); - bool antialias = ttFont->face().antialias(); - int fg_alpha = gfx::geta(fg); - - gfx::Rect clipBounds; - os::SurfaceFormatData fd; - if (surface) { - clipBounds = surface->getClipBounds(); - surface->getFormat(&fd); - surface->lock(); - } - - ft::ForEachGlyph feg(ttFont->face()); - if (feg.initialize(it, end)) { - do { - if (delegate) { - delegate->preProcessChar(feg.charIndex(), - feg.unicodeChar(), fg, bg); - } - - auto glyph = feg.glyph(); - if (!glyph) - continue; - - gfx::Rect origDstBounds( - x + int(glyph->startX), - y + int(glyph->y), - int(glyph->endX) - int(glyph->startX), - int(glyph->bitmap->rows) ? int(glyph->bitmap->rows): 1); - - if (delegate && !delegate->preDrawChar(origDstBounds)) - break; - - origDstBounds.x = x + int(glyph->x); - origDstBounds.w = int(glyph->bitmap->width); - origDstBounds.h = int(glyph->bitmap->rows); - - gfx::Rect dstBounds = origDstBounds; - if (surface) - dstBounds &= clipBounds; - - if (surface && !dstBounds.isEmpty()) { - int clippedRows = dstBounds.y - origDstBounds.y; - int dst_y = dstBounds.y; - int t; - for (int v=0; vbitmap->buffer - + (v+clippedRows)*glyph->bitmap->pitch; - int dst_x = dstBounds.x; - uint32_t* dst_address = - (uint32_t*)surface->getData(dst_x, dst_y); - - // Skip first clipped pixels - for (int u=0; u> fd.redShift), - ((backdrop & fd.greenMask) >> fd.greenShift), - ((backdrop & fd.blueMask) >> fd.blueShift), - ((backdrop & fd.alphaMask) >> fd.alphaShift)); - - gfx::Color output = gfx::rgba(gfx::getr(fg), - gfx::getg(fg), - gfx::getb(fg), - MUL_UN8(fg_alpha, alpha, t)); - if (gfx::geta(bg) > 0) - output = blend(blend(backdropColor, bg), output); - else - output = blend(backdropColor, output); - - *dst_address = - ((gfx::getr(output) << fd.redShift ) & fd.redMask ) | - ((gfx::getg(output) << fd.greenShift) & fd.greenMask) | - ((gfx::getb(output) << fd.blueShift ) & fd.blueMask ) | - ((gfx::geta(output) << fd.alphaShift) & fd.alphaMask); - - ++dst_address; - } - } - } - - if (!origDstBounds.w) origDstBounds.w = 1; - if (!origDstBounds.h) origDstBounds.h = 1; - textBounds |= origDstBounds; - if (delegate) - delegate->postDrawChar(origDstBounds); - } while (feg.nextChar()); - } - - if (surface) - surface->unlock(); - break; - } - - } - - return textBounds; -} - -} // namespace os diff --git a/src/os/draw_text.h b/src/os/draw_text.h deleted file mode 100644 index 51915f791..000000000 --- a/src/os/draw_text.h +++ /dev/null @@ -1,54 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_DRAW_TEXT_H_INCLUDED -#define OS_DRAW_TEXT_H_INCLUDED -#pragma once - -#include "base/string.h" -#include "gfx/color.h" -#include "gfx/fwd.h" - -namespace os { - - class Font; - class Surface; - class SurfaceLock; - - class DrawTextDelegate { - public: - virtual ~DrawTextDelegate() { } - - // This is called before drawing the character. - virtual void preProcessChar(const int index, - const int codepoint, - gfx::Color& fg, gfx::Color& bg) { - // Do nothing - } - - virtual bool preDrawChar(const gfx::Rect& charBounds) { - // Returns false if the process should stop here. - return true; - } - - virtual void postDrawChar(const gfx::Rect& charBounds) { - // Do nothing - } - }; - - // The surface can be nullptr just to process the string - // (e.g. measure how much space will use the text without drawing - // it). - gfx::Rect draw_text(Surface* surface, Font* font, - const base::utf8_const_iterator& begin, - const base::utf8_const_iterator& end, - gfx::Color fg, gfx::Color bg, - int x, int y, - DrawTextDelegate* delegate); - -} // namespace os - -#endif diff --git a/src/os/error.h b/src/os/error.h deleted file mode 100644 index a01288707..000000000 --- a/src/os/error.h +++ /dev/null @@ -1,17 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2014 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_ERROR_H_INCLUDED -#define OS_ERROR_H_INCLUDED -#pragma once - -namespace os { - - void error_message(const char* msg); - -} // namespace os - -#endif diff --git a/src/os/event.h b/src/os/event.h deleted file mode 100644 index 380cd21bf..000000000 --- a/src/os/event.h +++ /dev/null @@ -1,135 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_EVENT_H_INCLUDED -#define OS_EVENT_H_INCLUDED -#pragma once - -#include "base/paths.h" -#include "gfx/point.h" -#include "gfx/size.h" -#include "os/keys.h" -#include "os/pointer_type.h" - -#pragma push_macro("None") -#undef None // Undefine the X11 None macro - -namespace os { - - class Display; - - class Event { - public: - enum Type { - None, - CloseDisplay, - ResizeDisplay, - DropFiles, - MouseEnter, - MouseLeave, - MouseMove, - MouseDown, - MouseUp, - MouseWheel, - MouseDoubleClick, - KeyDown, - KeyUp, - TouchMagnify, - }; - - enum MouseButton { - NoneButton, - LeftButton, - RightButton, - MiddleButton, - X1Button, - X2Button, - }; - - Event() : m_type(None), - m_display(nullptr), - m_scancode(kKeyNil), - m_modifiers(kKeyUninitializedModifier), - m_unicodeChar(0), - m_isDead(false), - m_repeat(0), - m_preciseWheel(false), - m_pointerType(PointerType::Unknown), - m_button(NoneButton), - m_magnification(0.0), - m_pressure(0.0) { - } - - Type type() const { return m_type; } - Display* display() const { return m_display; } - const base::paths& files() const { return m_files; } - // TODO Rename this to virtualKey(), which is the real - // meaning. Then we need another kind of "scan code" with the - // position in the keyboard, which might be useful to identify - // keys by its position (e.g. WASD keys in other keyboard - // layouts). - KeyScancode scancode() const { return m_scancode; } - KeyModifiers modifiers() const { return m_modifiers; } - int unicodeChar() const { return m_unicodeChar; } - bool isDeadKey() const { return m_isDead; } - int repeat() const { return m_repeat; } - gfx::Point position() const { return m_position; } - gfx::Point wheelDelta() const { return m_wheelDelta; } - - // We suppose that if we are receiving precise scrolling deltas, - // it means that the user is using a touch-like surface (trackpad, - // magic mouse scrolling, touch wacom tablet, etc.) - bool preciseWheel() const { return m_preciseWheel; } - - PointerType pointerType() const { return m_pointerType; } - MouseButton button() const { return m_button; } - double magnification() const { return m_magnification; } - double pressure() const { return m_pressure; } - - void setType(Type type) { m_type = type; } - void setDisplay(Display* display) { m_display = display; } - void setFiles(const base::paths& files) { m_files = files; } - - void setScancode(KeyScancode scancode) { m_scancode = scancode; } - void setModifiers(KeyModifiers modifiers) { m_modifiers = modifiers; } - void setUnicodeChar(int unicodeChar) { m_unicodeChar = unicodeChar; } - void setDeadKey(bool state) { m_isDead = state; } - void setRepeat(int repeat) { m_repeat = repeat; } - void setPosition(const gfx::Point& pos) { m_position = pos; } - void setWheelDelta(const gfx::Point& delta) { m_wheelDelta = delta; } - void setPreciseWheel(bool precise) { m_preciseWheel = precise; } - void setPointerType(PointerType pointerType) { m_pointerType = pointerType; } - void setButton(MouseButton button) { m_button = button; } - void setMagnification(double magnification) { m_magnification = magnification; } - void setPressure(double pressure) { m_pressure = pressure; } - - private: - Type m_type; - Display* m_display; - base::paths m_files; - KeyScancode m_scancode; - KeyModifiers m_modifiers; - int m_unicodeChar; - bool m_isDead; - int m_repeat; // repeat=0 means the first time the key is pressed - gfx::Point m_position; - gfx::Point m_wheelDelta; - bool m_preciseWheel; - PointerType m_pointerType; - MouseButton m_button; - - // For TouchMagnify event - double m_magnification; - - // Pressure of stylus used in mouse-like events - double m_pressure; - }; - -} // namespace os - -#pragma pop_macro("None") - -#endif diff --git a/src/os/event_queue.h b/src/os/event_queue.h deleted file mode 100644 index 7692f190f..000000000 --- a/src/os/event_queue.h +++ /dev/null @@ -1,34 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_EVENT_QUEUE_H_INCLUDED -#define OS_EVENT_QUEUE_H_INCLUDED -#pragma once - -namespace os { - - class Event; - - class EventQueue { - public: - virtual ~EventQueue() { } - virtual void getEvent(Event& ev, bool canWait) = 0; - virtual void queueEvent(const Event& ev) = 0; - - // On MacOS X we need the EventQueue before the creation of the - // System. E.g. when we double-click a file an Event to open that - // file is queued in application:openFile:, code which is executed - // before the user's main() code. - static EventQueue* instance(); - }; - - inline void queue_event(const Event& ev) { - EventQueue::instance()->queueEvent(ev); - } - -} // namespace os - -#endif diff --git a/src/os/font.h b/src/os/font.h deleted file mode 100644 index 3ca0489e5..000000000 --- a/src/os/font.h +++ /dev/null @@ -1,47 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_FONT_H_INCLUDED -#define OS_FONT_H_INCLUDED -#pragma once - -#include - -namespace os { - - enum class FontType { - kUnknown, - kSpriteSheet, - kTrueType, - }; - - class Font { - public: - Font() : m_fallback(nullptr) { } - virtual ~Font() { } - virtual void dispose() = 0; - virtual FontType type() = 0; - virtual int height() const = 0; - virtual int textLength(const std::string& str) const = 0; - virtual bool isScalable() const = 0; - virtual void setSize(int size) = 0; - virtual void setAntialias(bool antialias) = 0; - virtual bool hasCodePoint(int codepoint) const = 0; - - os::Font* fallback() const { - return m_fallback; - } - void setFallback(os::Font* font) { - m_fallback = font; - } - - private: - os::Font* m_fallback; - }; - -} // namespace os - -#endif diff --git a/src/os/gl/gl_context.h b/src/os/gl/gl_context.h deleted file mode 100644 index aececbd89..000000000 --- a/src/os/gl/gl_context.h +++ /dev/null @@ -1,25 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_GL_CONTEXT_INCLUDED -#define OS_GL_CONTEXT_INCLUDED -#pragma once - -namespace os { - -class GLContext { -public: - virtual ~GLContext() { } - virtual bool createGLContext() = 0; - virtual void destroyGLContext() = 0; - virtual int getStencilBits() = 0; - virtual int getSampleCount() = 0; - virtual void swapBuffers() { } -}; - -} // namespace os - -#endif diff --git a/src/os/gl/gl_context_cgl.h b/src/os/gl/gl_context_cgl.h deleted file mode 100644 index e07ccd60f..000000000 --- a/src/os/gl/gl_context_cgl.h +++ /dev/null @@ -1,83 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_GL_CONTEXT_CGL_INCLUDED -#define OS_GL_CONTEXT_CGL_INCLUDED -#pragma once - -#include "os/gl/gl_context.h" - -#include -#include - -namespace os { - -class GLContextCGL : public GLContext { -public: - GLContextCGL() - : m_glctx(nullptr) - , m_stencilBits(0) - , m_sampleCount(0) { - } - - ~GLContextCGL() { - destroyGLContext(); - } - - bool createGLContext() override { - CGLPixelFormatAttribute attributes[] = { - kCGLPFAOpenGLProfile, - (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, - kCGLPFAAccelerated, - kCGLPFADoubleBuffer, - (CGLPixelFormatAttribute)0 - }; - CGLPixelFormatObj format; - GLint npix; - CGLChoosePixelFormat(attributes, &format, &npix); - if (!format) - return false; - - CGLDescribePixelFormat(format, 0, kCGLPFASamples, &m_sampleCount); - CGLDescribePixelFormat(format, 0, kCGLPFAStencilSize, &m_stencilBits); - - CGLCreateContext(format, nullptr, &m_glctx); - CGLReleasePixelFormat(format); - if (!m_glctx) - return false; - - CGLSetCurrentContext(m_glctx); - return true; - } - - void destroyGLContext() override { - if (m_glctx) { - CGLReleaseContext(m_glctx); - m_glctx = nullptr; - } - } - - int getStencilBits() override { - return m_stencilBits; - } - - int getSampleCount() override { - return m_sampleCount; - } - - CGLContextObj cglContext() { - return m_glctx; - } - -private: - CGLContextObj m_glctx; - int m_stencilBits; - int m_sampleCount; -}; - -} // namespace os - -#endif diff --git a/src/os/gl/gl_context_egl.h b/src/os/gl/gl_context_egl.h deleted file mode 100644 index 9f449d6bf..000000000 --- a/src/os/gl/gl_context_egl.h +++ /dev/null @@ -1,165 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_GL_CONTEXT_EGL_INCLUDED -#define OS_GL_CONTEXT_EGL_INCLUDED -#pragma once - -#include "os/gl/gl_context.h" - -#include -#include - -namespace os { - -class GLContextEGL : public GLContext { -public: - GLContextEGL(void* nativeDisplay) - : m_nativeDisplay(nativeDisplay) - , m_context(EGL_NO_CONTEXT) - , m_display(EGL_NO_DISPLAY) - , m_surface(EGL_NO_SURFACE) - { - } - - ~GLContextEGL() { - destroyGLContext(); - } - - bool createGLContext() override { - m_display = getD3DEGLDisplay((HDC)GetDC((HWND)m_nativeDisplay)); - if (m_display == EGL_NO_DISPLAY) { - LOG("OS: Cannot create EGL display"); - return false; - } - - EGLint majorVersion; - EGLint minorVersion; - if (!eglInitialize(m_display, &majorVersion, &minorVersion)) - return false; - - static const EGLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_NONE - }; - EGLConfig surfaceConfig; - EGLint numConfigs; - if (!eglChooseConfig(m_display, configAttribs, &surfaceConfig, 1, &numConfigs)) - return false; - - static const EGLint surfaceAttribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }; - m_surface = eglCreateWindowSurface( - m_display, - surfaceConfig, - (EGLNativeWindowType)m_nativeDisplay, - surfaceAttribs); - if (m_surface == EGL_NO_SURFACE) - return false; - - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - m_context = eglCreateContext(m_display, surfaceConfig, - EGL_NO_CONTEXT, - contextAttribs); - if (m_context == EGL_NO_CONTEXT) - return false; - - if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context)) - return false; - - eglGetConfigAttrib(m_display, surfaceConfig, EGL_STENCIL_SIZE, &m_stencilBits); - eglGetConfigAttrib(m_display, surfaceConfig, EGL_SAMPLES, &m_sampleCount); - - return true; - } - - void destroyGLContext() override { - if (m_display != EGL_NO_DISPLAY) { - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - if (m_surface != EGL_NO_SURFACE) { - eglDestroySurface(m_display, m_surface); - m_surface = EGL_NO_SURFACE; - } - - if (m_context != EGL_NO_CONTEXT) { - eglDestroyContext(m_display, m_context); - m_context = EGL_NO_CONTEXT; - } - - eglTerminate(m_display); - m_display = EGL_NO_DISPLAY; - } - } - - int getStencilBits() override { - return m_stencilBits; - } - - int getSampleCount() override { - return m_sampleCount; - } - - void swapBuffers() override { - eglSwapBuffers(m_display, m_surface); - } - -private: - static void* getD3DEGLDisplay(void* nativeDisplay) { - PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; - eglGetPlatformDisplayEXT = - (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); - if (!eglGetPlatformDisplayEXT) - return eglGetDisplay(static_cast(nativeDisplay)); - - EGLint attribs[3][3] = { - { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_NONE - }, - { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, - EGL_NONE - }, - { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, - EGL_NONE - } - }; - - EGLDisplay display = EGL_NO_DISPLAY; - for (int i=0; i<3 && display == EGL_NO_DISPLAY; ++i) { - display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, - nativeDisplay, attribs[i]); - } - return display; - } - - void* m_nativeDisplay; - void* m_context; - void* m_display; - void* m_surface; - EGLint m_stencilBits; - EGLint m_sampleCount; -}; - -} // namespace os - -#endif diff --git a/src/os/gl/gl_context_wgl.h b/src/os/gl/gl_context_wgl.h deleted file mode 100644 index 195271d3d..000000000 --- a/src/os/gl/gl_context_wgl.h +++ /dev/null @@ -1,92 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_GL_CONTEXT_WGL_INCLUDED -#define OS_GL_CONTEXT_WGL_INCLUDED -#pragma once - -#include "os/gl/gl_context.h" - -#include - -namespace os { - -class GLContextWGL : public GLContext { -public: - GLContextWGL(HWND hwnd) - : m_hwnd(hwnd) - , m_glrc(nullptr) { - } - - ~GLContextWGL() { - destroyGLContext(); - } - - bool createGLContext() override { - HDC hdc = GetDC(m_hwnd); - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), - 1, // version number - PFD_DRAW_TO_WINDOW | // support window - PFD_SUPPORT_OPENGL, // support OpenGL - PFD_TYPE_RGBA, // RGBA type - 24, // 24-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 8, // 8-bit alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 0, // no z-buffer - 0, // no stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - int pixelFormat = ChoosePixelFormat(hdc, &pfd); - SetPixelFormat(hdc, pixelFormat, &pfd); - - m_glrc = wglCreateContext(hdc); - if (!m_glrc) { - ReleaseDC(m_hwnd, hdc); - return false; - } - - wglMakeCurrent(hdc, m_glrc); - ReleaseDC(m_hwnd, hdc); - return true; - } - - void destroyGLContext() override { - if (m_glrc) { - wglMakeCurrent(nullptr, nullptr); - wglDeleteContext(m_glrc); - m_glrc = nullptr; - } - } - - int getStencilBits() override { - HDC hdc = GetDC(m_hwnd); - int pixelFormat = GetPixelFormat(hdc); - PIXELFORMATDESCRIPTOR pfd; - DescribePixelFormat(hdc, pixelFormat, sizeof(pfd), &pfd); - ReleaseDC(m_hwnd, hdc); - return pfd.cStencilBits; - } - - int getSampleCount() override { - return 0; - } - -private: - HWND m_hwnd; - HGLRC m_glrc; -}; - -} // namespace os - -#endif diff --git a/src/os/gtk/native_dialogs.cpp b/src/os/gtk/native_dialogs.cpp deleted file mode 100644 index 2edcada81..000000000 --- a/src/os/gtk/native_dialogs.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017-2018 David Capello -// Copyright (C) 2016 Gabriel Rauter -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/gtk/native_dialogs.h" - -#include "base/fs.h" -#include "base/string.h" -#include "os/common/file_dialog.h" -#include "os/display.h" -#include "os/error.h" - -#include -#include -#include - -namespace os { - -class FileDialogGTK : public CommonFileDialog { -public: - FileDialogGTK() { - } - - std::string fileName() override { - return m_filename; - } - - void getMultipleFileNames(base::paths& output) override { - output = m_filenames; - } - - void setFileName(const std::string& filename) override { - m_filename = base::get_file_name(filename); - m_initialDir = base::get_file_path(filename); - } - - bool show(Display* parent) override { - static std::string s_lastUsedDir; - if (s_lastUsedDir.empty()) - s_lastUsedDir = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP); - - const char* okLabel; - GtkFileChooserAction action; - - switch (m_type) { - case Type::OpenFile: - case Type::OpenFiles: - action = GTK_FILE_CHOOSER_ACTION_OPEN; - okLabel = "_Open"; - break; - case Type::OpenFolder: - action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - okLabel = "_Open Folder"; - break; - case Type::SaveFile: - action = GTK_FILE_CHOOSER_ACTION_SAVE; - okLabel = "_Save"; - break; - } - - // GtkWindow* gtkParent = nullptr; - GtkWidget* dialog = gtk_file_chooser_dialog_new( - m_title.c_str(), - nullptr, - action, - "_Cancel", GTK_RESPONSE_CANCEL, - okLabel, GTK_RESPONSE_ACCEPT, - nullptr); - - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - - GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog); - m_chooser = chooser; - - if (m_type == Type::SaveFile) - gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); - else if (m_type == Type::OpenFiles) - gtk_file_chooser_set_select_multiple(chooser, true); - - if (m_type != Type::OpenFolder) { - setupFilters(base::get_file_extension(m_filename)); - setupPreview(); - } - - if (m_initialDir.empty()) - gtk_file_chooser_set_current_folder(chooser, s_lastUsedDir.c_str()); - else - gtk_file_chooser_set_current_folder(chooser, m_initialDir.c_str()); - - if (!m_filename.empty()) { - std::string fn = m_filename; - // Add default extension - if (m_type == Type::SaveFile && base::get_file_extension(fn).empty()) { - fn.push_back('.'); - fn += m_defExtension; - } - gtk_file_chooser_set_current_name(chooser, fn.c_str()); - } - - // Setup the "parent" display as the parent of the dialog (we've - // to convert a X11 Window into a GdkWindow to do this). - GdkWindow* gdkParentWindow = nullptr; - if (parent) { - GdkWindow* gdkWindow = gtk_widget_get_root_window(dialog); - - gdkParentWindow = - gdk_x11_window_foreign_new_for_display( - gdk_window_get_display(gdkWindow), - (::Window)parent->nativeHandle()); - - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT); - gdk_window_set_transient_for(gdkWindow, gdkParentWindow); - } - else { - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); - } - - // Show the dialog - gint res = gtk_dialog_run(GTK_DIALOG(dialog)); - if (res == GTK_RESPONSE_ACCEPT) { - s_lastUsedDir = gtk_file_chooser_get_current_folder(chooser); - m_filename = gtk_file_chooser_get_filename(chooser); - - if (m_type == Type::OpenFiles) { - GSList* list = gtk_file_chooser_get_filenames(chooser); - g_slist_foreach( - list, - [](void* fn, void* userdata){ - auto self = (FileDialogGTK*)userdata; - self->m_filenames.push_back((char*)fn); - g_free(fn); - }, this); - g_slist_free(list); - } - } - - gtk_widget_destroy(dialog); - if (gdkParentWindow) - g_object_unref(gdkParentWindow); - - // Pump gtk+ events to finally hide the dialog from the screen - while (gtk_events_pending()) - gtk_main_iteration(); - - return (res == GTK_RESPONSE_ACCEPT); - } - -private: - void setupFilters(const std::string& fnExtension) { - // Filter for all known formats - GtkFileFilter* gtkFilter = gtk_file_filter_new(); - gtk_file_filter_set_name(gtkFilter, "All formats"); - for (const auto& filter : m_filters) { - const std::string& ext = filter.first; - std::string pat = "*." + ext; - gtk_file_filter_add_pattern(gtkFilter, pat.c_str()); - } - gtk_file_chooser_add_filter(m_chooser, gtkFilter); - - // One filter for each format - for (const auto& filter : m_filters) { - const std::string& ext = filter.first; - const std::string& desc = filter.second; - std::string pat = "*." + ext; - - gtkFilter = gtk_file_filter_new(); - gtk_file_filter_set_name(gtkFilter, desc.c_str()); - gtk_file_filter_add_pattern(gtkFilter, pat.c_str()); - gtk_file_chooser_add_filter(m_chooser, gtkFilter); - - if (base::utf8_icmp(ext, fnExtension) == 0) - gtk_file_chooser_set_filter(m_chooser, gtkFilter); - } - - // One filter for all files - gtkFilter = gtk_file_filter_new(); - gtk_file_filter_set_name(gtkFilter, "All files"); - gtk_file_filter_add_pattern(gtkFilter, "*"); - gtk_file_chooser_add_filter(m_chooser, gtkFilter); - } - - void setupPreview() { - m_preview = gtk_image_new(); - - gtk_file_chooser_set_use_preview_label(m_chooser, false); - gtk_file_chooser_set_preview_widget(m_chooser, m_preview); - - g_signal_connect( - m_chooser, "update-preview", - G_CALLBACK(&FileDialogGTK::s_onUpdatePreview), this); - } - - static void s_onUpdatePreview(GtkFileChooser* chooser, gpointer userData) { - ((FileDialogGTK*)userData)->onUpdatePreview(); - } - void onUpdatePreview() { - // Disable preview because we don't know if we will be able to - // load/generate the preview successfully. - gtk_file_chooser_set_preview_widget_active(m_chooser, false); - - const char* fn = gtk_file_chooser_get_filename(m_chooser); - if (fn && base::is_file(fn)) { - GError* err = nullptr; - GdkPixbuf* previewPixbuf = - gdk_pixbuf_new_from_file_at_scale(fn, 256, 256, true, &err); - if (previewPixbuf) { - gtk_image_set_from_pixbuf(GTK_IMAGE(m_preview), previewPixbuf); - g_object_unref(previewPixbuf); - - // Now we can enable the preview panel as the preview was - // generated. - gtk_file_chooser_set_preview_widget_active(m_chooser, true); - } - if (err) - g_error_free(err); - } - } - - std::string m_filename; - std::string m_initialDir; - base::paths m_filenames; - GtkFileChooser* m_chooser; - GtkWidget* m_preview; -}; - -NativeDialogsGTK::NativeDialogsGTK() - : m_gtkApp(nullptr) -{ -} - -NativeDialogsGTK::~NativeDialogsGTK() -{ - if (m_gtkApp) { - g_object_unref(m_gtkApp); - m_gtkApp = nullptr; - } -} - -FileDialog* NativeDialogsGTK::createFileDialog() -{ - if (!m_gtkApp) { - int argc = 0; - char** argv = nullptr; - gtk_init(&argc, &argv); - - m_gtkApp = gtk_application_new(nullptr, G_APPLICATION_FLAGS_NONE); - } - return new FileDialogGTK; -} - -} // namespace os diff --git a/src/os/gtk/native_dialogs.h b/src/os/gtk/native_dialogs.h deleted file mode 100644 index 5a174260e..000000000 --- a/src/os/gtk/native_dialogs.h +++ /dev/null @@ -1,29 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// Copyright (C) 2016 Gabriel Rauter -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_GTK_NATIVE_DIALOGS_H_INCLUDED -#define OS_GTK_NATIVE_DIALOGS_H_INCLUDED -#pragma once - -#include "os/native_dialogs.h" - -extern "C" struct _GtkApplication; - -namespace os { - - class NativeDialogsGTK : public NativeDialogs { - public: - NativeDialogsGTK(); - ~NativeDialogsGTK(); - FileDialog* createFileDialog() override; - private: - _GtkApplication* m_gtkApp; - }; - -} // namespace os - -#endif diff --git a/src/os/keys.h b/src/os/keys.h deleted file mode 100644 index 715d251aa..000000000 --- a/src/os/keys.h +++ /dev/null @@ -1,165 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_KEYS_H_INCLUDED -#define OS_KEYS_H_INCLUDED -#pragma once - -namespace os { - - enum KeyModifiers { - kKeyNoneModifier = 0, - kKeyShiftModifier = 1, - kKeyCtrlModifier = 2, - kKeyAltModifier = 4, - kKeyCmdModifier = 8, - kKeySpaceModifier = 16, - kKeyWinModifier = 32, - kKeyUninitializedModifier = 64, - }; - - // TODO These are virtual key code (not scancodes), we should rename - // it to KeyCodes or use Unicode directly as on macOS (some - // special keys like F1, arrow keys, etc. have a special - // unicode value). - enum KeyScancode { - kKeyNil = 0, - kKeyA = 1, - kKeyB = 2, - kKeyC = 3, - kKeyD = 4, - kKeyE = 5, - kKeyF = 6, - kKeyG = 7, - kKeyH = 8, - kKeyI = 9, - kKeyJ = 10, - kKeyK = 11, - kKeyL = 12, - kKeyM = 13, - kKeyN = 14, - kKeyO = 15, - kKeyP = 16, - kKeyQ = 17, - kKeyR = 18, - kKeyS = 19, - kKeyT = 20, - kKeyU = 21, - kKeyV = 22, - kKeyW = 23, - kKeyX = 24, - kKeyY = 25, - kKeyZ = 26, - kKey0 = 27, - kKey1 = 28, - kKey2 = 29, - kKey3 = 30, - kKey4 = 31, - kKey5 = 32, - kKey6 = 33, - kKey7 = 34, - kKey8 = 35, - kKey9 = 36, - kKey0Pad = 37, - kKey1Pad = 38, - kKey2Pad = 39, - kKey3Pad = 40, - kKey4Pad = 41, - kKey5Pad = 42, - kKey6Pad = 43, - kKey7Pad = 44, - kKey8Pad = 45, - kKey9Pad = 46, - kKeyF1 = 47, - kKeyF2 = 48, - kKeyF3 = 49, - kKeyF4 = 50, - kKeyF5 = 51, - kKeyF6 = 52, - kKeyF7 = 53, - kKeyF8 = 54, - kKeyF9 = 55, - kKeyF10 = 56, - kKeyF11 = 57, - kKeyF12 = 58, - kKeyEsc = 59, - kKeyTilde = 60, - kKeyMinus = 61, - kKeyEquals = 62, - kKeyBackspace = 63, - kKeyTab = 64, - kKeyOpenbrace = 65, - kKeyClosebrace = 66, - kKeyEnter = 67, - kKeyColon = 68, - kKeyQuote = 69, - kKeyBackslash = 70, - kKeyBackslash2 = 71, - kKeyComma = 72, - kKeyStop = 73, - kKeySlash = 74, - kKeySpace = 75, - kKeyInsert = 76, - kKeyDel = 77, - kKeyHome = 78, - kKeyEnd = 79, - kKeyPageUp = 80, - kKeyPageDown = 81, - kKeyLeft = 82, - kKeyRight = 83, - kKeyUp = 84, - kKeyDown = 85, - kKeySlashPad = 86, - kKeyAsterisk = 87, - kKeyMinusPad = 88, - kKeyPlusPad = 89, - kKeyDelPad = 90, - kKeyEnterPad = 91, - kKeyPrtscr = 92, - kKeyPause = 93, - kKeyAbntC1 = 94, - kKeyYen = 95, - kKeyKana = 96, - kKeyConvert = 97, - kKeyNoconvert = 98, - kKeyAt = 99, - kKeyCircumflex = 100, - kKeyColon2 = 101, - kKeyKanji = 102, - kKeyEqualsPad = 103, // macOS - kKeyBackquote = 104, // macOS - kKeySemicolon = 105, // macOS - kKeyUnknown1 = 106, - kKeyUnknown2 = 107, - kKeyUnknown3 = 108, - kKeyUnknown4 = 109, - kKeyUnknown5 = 110, - kKeyUnknown6 = 111, - kKeyUnknown7 = 112, - kKeyUnknown8 = 113, - - kKeyFirstModifierScancode = 114, - - kKeyLShift = 114, - kKeyRShift = 115, - kKeyLControl = 116, - kKeyRControl = 117, - kKeyAlt = 118, - kKeyAltGr = 119, - kKeyLWin = 120, - kKeyRWin = 121, - kKeyMenu = 122, - kKeyCommand = 123, - kKeyScrLock = 124, - kKeyNumLock = 125, - kKeyCapsLock = 126, - - kKeyScancodes = 127 - }; - -} // namespace os - -#endif diff --git a/src/os/logger.h b/src/os/logger.h deleted file mode 100644 index f040bc64e..000000000 --- a/src/os/logger.h +++ /dev/null @@ -1,21 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2014 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_LOGGER_H_INCLUDED -#define OS_LOGGER_H_INCLUDED -#pragma once - -namespace os { - - class Logger { - public: - virtual ~Logger() { } - virtual void logError(const char* error) = 0; - }; - -} // namespace os - -#endif diff --git a/src/os/menus.h b/src/os/menus.h deleted file mode 100644 index df73a521c..000000000 --- a/src/os/menus.h +++ /dev/null @@ -1,92 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_MENUS_H_INCLUDED -#define OS_MENUS_H_INCLUDED -#pragma once - -#include "os/keys.h" -#include "os/shortcut.h" - -#include -#include - -namespace os { - class MenuItem; - - struct MenuItemInfo { - enum Type { - Normal, - Separator - }; - - enum Action { - UserDefined, - - // macOS standard commands - Hide, - HideOthers, - ShowAll, - Quit, - Minimize, - Zoom, - }; - - Type type; - Action action; - std::string text; - Shortcut shortcut; - std::function execute; - std::function validate; - - explicit MenuItemInfo(const Type type = Normal, - const Action action = UserDefined) - : type(type) - , action(action) { - } - - explicit MenuItemInfo(const char* text, - const Action action = UserDefined) - : type(Normal) - , action(action) - , text(text) { - } - }; - - class Menu; - class MenuItem; - class Menus; - - class MenuItem { - public: - virtual ~MenuItem() { } - virtual void dispose() = 0; - virtual void setText(const std::string& text) = 0; - virtual void setSubmenu(Menu* submenu) = 0; - virtual void setEnabled(bool state) = 0; - virtual void setChecked(bool state) = 0; - virtual void setShortcut(const Shortcut& shortcut) = 0; - }; - - class Menu { - public: - virtual ~Menu() { } - virtual void dispose() = 0; - virtual void addItem(MenuItem* item) = 0; - virtual void insertItem(const int index, MenuItem* item) = 0; - }; - - class Menus { - public: - virtual ~Menus() { } - virtual Menu* createMenu() = 0; - virtual MenuItem* createMenuItem(const MenuItemInfo& info) = 0; - virtual void setAppMenu(Menu* menu) = 0; - }; - -} // namespace os - -#endif diff --git a/src/os/native_cursor.h b/src/os/native_cursor.h deleted file mode 100644 index 44a1cbb81..000000000 --- a/src/os/native_cursor.h +++ /dev/null @@ -1,39 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2014 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_NATIVE_CURSOR_H_INCLUDED -#define OS_NATIVE_CURSOR_H_INCLUDED -#pragma once - -#include "gfx/fwd.h" - -namespace os { - - enum NativeCursor { - kNoCursor, - kArrowCursor, - kCrosshairCursor, - kIBeamCursor, - kWaitCursor, - kLinkCursor, - kHelpCursor, - kForbiddenCursor, - kMoveCursor, - kSizeNSCursor, - kSizeWECursor, - kSizeNCursor, - kSizeNECursor, - kSizeECursor, - kSizeSECursor, - kSizeSCursor, - kSizeSWCursor, - kSizeWCursor, - kSizeNWCursor, - }; - -} // namespace os - -#endif diff --git a/src/os/native_dialogs.h b/src/os/native_dialogs.h deleted file mode 100644 index f12c501bf..000000000 --- a/src/os/native_dialogs.h +++ /dev/null @@ -1,47 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_NATIVE_DIALOGS_H_INCLUDED -#define OS_NATIVE_DIALOGS_H_INCLUDED -#pragma once - -#include "base/paths.h" - -#include - -namespace os { - class Display; - - class FileDialog { - public: - enum class Type { - OpenFile, - OpenFiles, - OpenFolder, - SaveFile, - }; - - virtual ~FileDialog() { } - virtual void dispose() = 0; - virtual void setType(const Type type) = 0; - virtual void setTitle(const std::string& title) = 0; - virtual void setDefaultExtension(const std::string& extension) = 0; - virtual void addFilter(const std::string& extension, const std::string& description) = 0; - virtual std::string fileName() = 0; - virtual void getMultipleFileNames(base::paths& output) = 0; - virtual void setFileName(const std::string& filename) = 0; - virtual bool show(Display* parent) = 0; - }; - - class NativeDialogs { - public: - virtual ~NativeDialogs() { } - virtual FileDialog* createFileDialog() = 0; - }; - -} // namespace os - -#endif diff --git a/src/os/none/os.cpp b/src/os/none/os.cpp deleted file mode 100644 index 7ddf629fa..000000000 --- a/src/os/none/os.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// LAF OS Library -// Copyright (C) 2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "base/memory.h" -#include "os/system.h" - -namespace os { - -class NoneSystem : public System { -public: - void dispose() override { delete this; } - void activateApp() override { } - void finishLaunching() override { } - Capabilities capabilities() const override { return (Capabilities)0; } - void useWintabAPI(bool enable) override { } - Logger* logger() override { return nullptr; } - Menus* menus() override { return nullptr; } - NativeDialogs* nativeDialogs() override { return nullptr; } - EventQueue* eventQueue() override { return nullptr; } - bool gpuAcceleration() const override { return false; } - void setGpuAcceleration(bool state) override { } - gfx::Size defaultNewDisplaySize() override { return gfx::Size(0, 0); } - Display* defaultDisplay() override { return nullptr; } - Display* createDisplay(int width, int height, int scale) override { return nullptr; } - Surface* createSurface(int width, int height) override { return nullptr; } - Surface* createRgbaSurface(int width, int height) override { return nullptr; } - Surface* loadSurface(const char* filename) override { return nullptr; } - Surface* loadRgbaSurface(const char* filename) override { return nullptr; } - Font* loadSpriteSheetFont(const char* filename, int scale) override { return nullptr; } - Font* loadTrueTypeFont(const char* filename, int height) override { return nullptr; } - bool isKeyPressed(KeyScancode scancode) override { return false; } - KeyModifiers keyModifiers() override { return kKeyNoneModifier; } - int getUnicodeFromScancode(KeyScancode scancode) override { return 0; } - void setTranslateDeadKeys(bool state) override { } -}; - -System* create_system_impl() { - return new NoneSystem; -} - -void error_message(const char* msg) -{ - fputs(msg, stderr); - // TODO -} - -} // namespace os - -extern int app_main(int argc, char* argv[]); - -#if _WIN32 -int wmain(int argc, wchar_t* wargv[], wchar_t* envp[]) { - char** argv; - if (wargv && argc > 0) { - argv = new char*[argc]; - for (int i=0; i - -#include "os/osx/app.h" - -#include "base/debug.h" -#include "base/thread.h" -#include "os/osx/app_delegate.h" - -extern int app_main(int argc, char* argv[]); - -namespace os { - -class OSXApp::Impl { -public: - bool init() { - m_app = [NSApplication sharedApplication]; - m_appDelegate = [OSXAppDelegate new]; - - [m_app setActivationPolicy:NSApplicationActivationPolicyRegular]; - [m_app setDelegate:m_appDelegate]; - - // Don't activate the application ignoring other apps. This is - // called by OS X when the application is launched by the user - // from the application bundle. In this way, we can execute - // aseprite from the command line/bash scripts and the app will - // not be activated. - //[m_app activateIgnoringOtherApps:YES]; - - return true; - } - - // We might need to call this function when the app is launched from - // Steam. It appears that there is a bug on OS X Steam client where - // the app is launched, activated, and then the Steam client is - // activated again. - void activateApp() { - [m_app activateIgnoringOtherApps:YES]; - } - - void finishLaunching() { - [m_app finishLaunching]; - } - -private: - NSApplication* m_app; - OSXAppDelegate* m_appDelegate; -}; - -static OSXApp* g_instance = nullptr; - -// static -OSXApp* OSXApp::instance() -{ - return g_instance; -} - -OSXApp::OSXApp() - : m_impl(new Impl) -{ - ASSERT(!g_instance); - g_instance = this; -} - -OSXApp::~OSXApp() -{ - ASSERT(g_instance == this); - g_instance = nullptr; -} - -bool OSXApp::init() -{ - return m_impl->init(); -} - -void OSXApp::activateApp() -{ - m_impl->activateApp(); -} - -void OSXApp::finishLaunching() -{ - m_impl->finishLaunching(); -} - -} // namespace os diff --git a/src/os/osx/app_delegate.h b/src/os/osx/app_delegate.h deleted file mode 100644 index 123f61f1f..000000000 --- a/src/os/osx/app_delegate.h +++ /dev/null @@ -1,24 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_APP_DELEGATE_H_INCLUDED -#define OS_OSX_APP_DELEGATE_H_INCLUDED -#pragma once - -#include - -@interface OSXAppDelegate : NSObject -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)app; -- (void)applicationWillTerminate:(NSNotification*)notification; -- (void)applicationWillResignActive:(NSNotification*)notification; -- (void)applicationDidBecomeActive:(NSNotification*)notification; -- (BOOL)application:(NSApplication*)app openFiles:(NSArray*)filenames; -- (void)executeMenuItem:(id)sender; -- (BOOL)validateMenuItem:(NSMenuItem*)menuItem; -@end - -#endif diff --git a/src/os/osx/app_delegate.mm b/src/os/osx/app_delegate.mm deleted file mode 100644 index 766e0442a..000000000 --- a/src/os/osx/app_delegate.mm +++ /dev/null @@ -1,83 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "os/osx/app_delegate.h" - -#include "base/fs.h" -#include "os/event.h" -#include "os/event_queue.h" -#include "os/osx/app.h" -#include "os/osx/generate_drop_files.h" -#include "os/osx/view.h" -#include "os/system.h" - -@protocol OSXValidateMenuItemProtocol -- (void)validateMenuItem; -@end - -@implementation OSXAppDelegate - -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender -{ - os::Event ev; - ev.setType(os::Event::CloseDisplay); - os::queue_event(ev); - return NSTerminateCancel; -} - -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)app -{ - return YES; -} - -- (void)applicationWillTerminate:(NSNotification*)notification -{ -} - -- (void)applicationWillResignActive:(NSNotification*)notification -{ - NSEvent* event = [NSApp currentEvent]; - if (event != nil) - [OSXView updateKeyFlags:event]; -} - -- (void)applicationDidBecomeActive:(NSNotification*)notification -{ - NSEvent* event = [NSApp currentEvent]; - if (event != nil) - [OSXView updateKeyFlags:event]; -} - -- (BOOL)application:(NSApplication*)app openFiles:(NSArray*)filenames -{ - generate_drop_files_from_nsarray(filenames); - - [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; - return YES; -} - -- (void)executeMenuItem:(id)sender -{ - [sender executeMenuItem:sender]; -} - -- (BOOL)validateMenuItem:(NSMenuItem*)menuItem -{ - if ([menuItem respondsToSelector:@selector(validateMenuItem)]) { - [((id)menuItem) validateMenuItem]; - return menuItem.enabled; - } - else - return [super validateMenuItem:menuItem]; -} - -@end diff --git a/src/os/osx/event_queue.h b/src/os/osx/event_queue.h deleted file mode 100644 index 903481fa0..000000000 --- a/src/os/osx/event_queue.h +++ /dev/null @@ -1,30 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_EVENT_QUEUE_INCLUDED -#define OS_OSX_EVENT_QUEUE_INCLUDED -#pragma once - -#include "base/concurrent_queue.h" -#include "os/event.h" -#include "os/event_queue.h" - -namespace os { - -class OSXEventQueue : public EventQueue { -public: - void getEvent(Event& ev, bool canWait) override; - void queueEvent(const Event& ev) override; - -private: - base::concurrent_queue m_events; -}; - -typedef OSXEventQueue EventQueueImpl; - -} // namespace os - -#endif diff --git a/src/os/osx/event_queue.mm b/src/os/osx/event_queue.mm deleted file mode 100644 index 62ff40841..000000000 --- a/src/os/osx/event_queue.mm +++ /dev/null @@ -1,67 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "os/osx/event_queue.h" - -namespace os { - -void OSXEventQueue::getEvent(Event& ev, bool canWait) -{ - ev.setType(Event::None); - - @autoreleasepool { - retry:; - NSApplication* app = [NSApplication sharedApplication]; - if (!app) - return; - - // Pump the whole queue of Cocoa events - NSEvent* event; - do { - event = [app nextEventMatchingMask:NSEventMaskAny - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (event) { - // Intercept , , and other keyboard - // combinations, and send them directly to the main - // NSView. Without this, the NSApplication intercepts the key - // combination and use it to go to the next key view. - if (event.type == NSEventTypeKeyDown) { - [app.mainWindow.contentView keyDown:event]; - } - else { - [app sendEvent:event]; - } - } - } while (event); - - if (!m_events.try_pop(ev)) { - if (canWait) { - // Wait until there is a Cocoa event in queue - [NSApp nextEventMatchingMask:NSEventMaskAny - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:NO]; - goto retry; - } - } - } -} - -void OSXEventQueue::queueEvent(const Event& ev) -{ - m_events.push(ev); -} - -} // namespace os diff --git a/src/os/osx/generate_drop_files.h b/src/os/osx/generate_drop_files.h deleted file mode 100644 index 93458e356..000000000 --- a/src/os/osx/generate_drop_files.h +++ /dev/null @@ -1,27 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_APP_GENERATE_DROP_FILES_H_INCLUDED -#define OS_OSX_APP_GENERATE_DROP_FILES_H_INCLUDED -#pragma once - -#include "base/fs.h" - -inline void generate_drop_files_from_nsarray(NSArray* filenames) -{ - base::paths files; - for (int i=0; i<[filenames count]; ++i) { - NSString* fn = [filenames objectAtIndex: i]; - files.push_back(base::normalize_path([fn UTF8String])); - } - - os::Event ev; - ev.setType(os::Event::DropFiles); - ev.setFiles(files); - os::queue_event(ev); -} - -#endif diff --git a/src/os/osx/keys.h b/src/os/osx/keys.h deleted file mode 100644 index ec7f35ea0..000000000 --- a/src/os/osx/keys.h +++ /dev/null @@ -1,25 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_KEYS_H_INCLUDED -#define OS_OSX_KEYS_H_INCLUDED -#pragma once - -#include "os/keys.h" - -#include - -namespace os { - - KeyScancode scancode_from_nsevent(NSEvent* event); - - CFStringRef get_unicode_from_key_code(const UInt16 keyCode, - const NSEventModifierFlags modifierFlags, - UInt32* deadKeyState = nullptr); - -} - -#endif diff --git a/src/os/osx/keys.mm b/src/os/osx/keys.mm deleted file mode 100644 index 01260c8e4..000000000 --- a/src/os/osx/keys.mm +++ /dev/null @@ -1,433 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -// Uncomment this to log how scancodes are generated -#define KEY_TRACE(...) - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/osx/keys.h" - -#include -#include // TIS functions - -namespace os { - -static KeyScancode from_char_to_scancode(int chr) -{ - static KeyScancode map[] = { - kKeyNil, // 0 = 00 = NUL - kKeyNil, // 1 = 01 = STX - kKeyNil, // 2 = 02 = SOT - kKeyNil, // 3 = 03 = ETX - kKeyNil, // 4 = 04 = EOT - kKeyNil, // 5 = 05 = ENQ - kKeyNil, // 6 = 06 = ACK - kKeyNil, // 7 = 07 = BEL - kKeyBackspace, // 8 = 08 = BS - kKeyNil, // 9 = 09 = HT - kKeyNil, // 10 =0A = LF - kKeyNil, // 11 =0B = VT - kKeyNil, // 12 =0C = FF - kKeyNil, // 13 =0D = CR - kKeyNil, // 14 =0E = SO - kKeyNil, // 15 =0F = SI - kKeyNil, // 16 =10 = DLE - kKeyNil, // 17 =11 = DC1 - kKeyNil, // 18 =12 = DC2 - kKeyNil, // 19 =13 = DC3 - kKeyNil, // 20 =14 = DC4 - kKeyNil, // 21 =15 = NAK - kKeyNil, // 22 =16 = SYN - kKeyNil, // 23 =17 = ETB - kKeyNil, // 24 =18 = CAN - kKeyNil, // 25 =19 = EM - kKeyNil, // 26 =1A = SUB - kKeyNil, // 27 =1B = ESC - kKeyNil, // 28 =1C = FS - kKeyNil, // 29 =1D = GS - kKeyNil, // 30 =1E = RS - kKeyNil, // 31 =1F = US - kKeySpace, // 32 =20 = Space - kKeyNil, // 33 =21 = ! - kKeyNil, // 34 =22 = " - kKeyNil, // 35 =23 = # - kKeyNil, // 36 =24 = $ - kKeyNil, // 37 =25 = % - kKeyNil, // 38 =26 = & - kKeyQuote, // 39 =27 = ' - kKeyNil, // 40 = 28 = ( - kKeyNil, // 41 = 29 = ) - kKeyNil, // 42 = 2A = * - kKeyNil, // 43 = 2B = + - kKeyComma, // 44 = 2C = , - kKeyMinus, // 45 = 2D = - - kKeyStop, // 46 = 2E = . - kKeySlash, // 47 = 2F = / - kKey0, // 48 = 30 = 0 - kKey1, // 49 = 31 = 1 - kKey2, // 50 = 32 = 2 - kKey3, // 51 = 33 = 3 - kKey4, // 52 = 34 = 4 - kKey5, // 53 = 35 = 5 - kKey6, // 54 = 36 = 6 - kKey7, // 55 = 37 = 7 - kKey8, // 56 = 38 = 8 - kKey9, // 57 = 39 = 9 - kKeyColon, // 58 = 3A = : - kKeySemicolon, // 59 = 3B = ; - kKeyNil, // 60 = 3C = < - kKeyEquals, // 61 = 3D = = - kKeyNil, // 62 = 3E = > - kKeyNil, // 63 = 3F = ? - kKeyNil, // 64 = 40 = @ - kKeyA, // 65 = 41 = A - kKeyB, // 66 = 42 = B - kKeyC, // 67 = 43 = C - kKeyD, // 68 = 44 = D - kKeyE, // 69 = 45 = E - kKeyF, // 70 = 46 = F - kKeyG, // 71 = 47 = G - kKeyH, // 72 = 48 = H - kKeyI, // 73 = 49 = I - kKeyJ, // 74 = 4A = J - kKeyK, // 75 = 4B = K - kKeyL, // 76 = 4C = L - kKeyM, // 77 = 4D = M - kKeyN, // 78 = 4E = N - kKeyO, // 79 = 4F = O - kKeyP, // 80 = 50 = P - kKeyQ, // 81 = 51 = Q - kKeyR, // 82 = 52 = R - kKeyS, // 83 = 53 = S - kKeyT, // 84 = 54 = T - kKeyU, // 85 = 55 = U - kKeyV, // 86 = 56 = V - kKeyW, // 87 = 57 = W - kKeyX, // 88 = 58 = X - kKeyY, // 89 = 59 = Y - kKeyZ, // 90 = 5A = Z - kKeyOpenbrace, // 91 = 5B = [ - kKeyBackslash, // 92 = 5C = backslash - kKeyClosebrace, // 93 = 5D = ] - kKeyCircumflex, // 94 = 5E = ^ - kKeyNil, // 95 = 5F = _ - kKeyBackquote, // 96 = 60 = ` - kKeyA, // 97 = 61 = a - kKeyB, // 98 = 62 = b - kKeyC, // 99 = 63 = c - kKeyD, // 100 = 64 = d - kKeyE, // 101 = 65 = e - kKeyF, // 102 = 66 = f - kKeyG, // 103 = 67 = g - kKeyH, // 104 = 68 = h - kKeyI, // 105 = 69 = i - kKeyJ, // 106 = 6A = j - kKeyK, // 107 = 6B = k - kKeyL, // 108 = 6C = l - kKeyM, // 109 = 6D = m - kKeyN, // 110 = 6E = n - kKeyO, // 111 = 6F = o - kKeyP, // 112 = 70 = p - kKeyQ, // 113 = 71 = q - kKeyR, // 114 = 72 = r - kKeyS, // 115 = 73 = s - kKeyT, // 116 = 74 = t - kKeyU, // 117 = 75 = u - kKeyV, // 118 = 76 = v - kKeyW, // 119 = 77 = w - kKeyX, // 120 = 78 = x - kKeyY, // 121 = 79 = y - kKeyZ, // 122 = 7A = z - kKeyOpenbrace, // 123 = 7B = { - kKeyBackslash, // 124 = 7C = | - kKeyClosebrace, // 125 = 7D = } - kKeyTilde, // 126 = 7E = ~ - kKeyNil, // 127 = 7F = DEL - }; - - if (chr >= 0 && chr < sizeof(map) / sizeof(map[0])) { - // Converts an ASCII character into a os::KeyScancode - return map[chr]; - } - else - return kKeyNil; -} - -static KeyScancode from_keycode_to_scancode(UInt16 keyCode) -{ - // Converts macOS virtual key code into a os::KeyScancode - static KeyScancode map[256] = { - // 0x00 - kKeyA, // 0x00 - kVK_ANSI_A - kKeyS, // 0x01 - kVK_ANSI_S - kKeyD, // 0x02 - kVK_ANSI_D - kKeyF, // 0x03 - kVK_ANSI_F - kKeyH, // 0x04 - kVK_ANSI_H - kKeyG, // 0x05 - kVK_ANSI_G - kKeyZ, // 0x06 - kVK_ANSI_Z - kKeyX, // 0x07 - kVK_ANSI_X - kKeyC, // 0x08 - kVK_ANSI_C - kKeyV, // 0x09 - kVK_ANSI_V - kKeyNil, // 0x0A - kVK_ISO_Section - kKeyB, // 0x0B - kVK_ANSI_B - kKeyQ, // 0x0C - kVK_ANSI_Q - kKeyW, // 0x0D - kVK_ANSI_W - kKeyE, // 0x0E - kVK_ANSI_E - kKeyR, // 0x0F - kVK_ANSI_R - // 0x10 - kKeyY, // 0x10 - kVK_ANSI_Y - kKeyT, // 0x11 - kVK_ANSI_T - kKey1, // 0x12 - kVK_ANSI_1 - kKey2, // 0x13 - kVK_ANSI_2 - kKey3, // 0x14 - kVK_ANSI_3 - kKey4, // 0x15 - kVK_ANSI_4 - kKey6, // 0x16 - kVK_ANSI_6 - kKey5, // 0x17 - kVK_ANSI_5 - kKeyEquals, // 0x18 - kVK_ANSI_Equal - kKey9, // 0x19 - kVK_ANSI_9 - kKey7, // 0x1A - kVK_ANSI_7 - kKeyMinus, // 0x1B - kVK_ANSI_Minus - kKey8, // 0x1C - kVK_ANSI_8 - kKey0, // 0x1D - kVK_ANSI_0 - kKeyClosebrace, // 0x1E - kVK_ANSI_RightBracket - kKeyO, // 0x1F - kVK_ANSI_O - // 0x20 - kKeyU, // 0x20 - kVK_ANSI_U - kKeyOpenbrace, // 0x21 - kVK_ANSI_LeftBracket - kKeyI, // 0x22 - kVK_ANSI_I - kKeyP, // 0x23 - kVK_ANSI_P - kKeyEnter, // 0x24 - kVK_Return - kKeyL, // 0x25 - kVK_ANSI_L - kKeyJ, // 0x26 - kVK_ANSI_J - kKeyQuote, // 0x27 - kVK_ANSI_Quote - kKeyK, // 0x28 - kVK_ANSI_K - kKeySemicolon, // 0x29 - kVK_ANSI_Semicolon - kKeyBackslash, // 0x2A - kVK_ANSI_Backslash - kKeyComma, // 0x2B - kVK_ANSI_Comma - kKeySlash, // 0x2C - kVK_ANSI_Slash - kKeyN, // 0x2D - kVK_ANSI_N - kKeyM, // 0x2E - kVK_ANSI_M - kKeyStop, // 0x2F - kVK_ANSI_Period - // 0x30 - kKeyTab, // 0x30 - kVK_Tab - kKeySpace, // 0x31 - kVK_Space - kKeyNil, // 0x32 - kVK_ANSI_Grave - kKeyBackspace, // 0x33 - kVK_Delete - kKeyNil, // 0x34 - ? - kKeyEsc, // 0x35 - kVK_Escape - kKeyNil, // 0x36 - ? - kKeyCommand, // 0x37 - kVK_Command - kKeyLShift, // 0x38 - kVK_Shift - kKeyCapsLock, // 0x39 - kVK_CapsLock - kKeyAlt, // 0x3A - kVK_Option - kKeyLControl, // 0x3B - kVK_Control - kKeyRShift, // 0x3C - kVK_RightShift - kKeyAltGr, // 0x3D - kVK_RightOption - kKeyRControl, // 0x3E - kVK_RightControl - kKeyNil, // 0x3F - kVK_Function - // 0x40 - kKeyNil, // 0x40 - kVK_F17 - kKeyNil, // 0x41 - kVK_ANSI_KeypadDecimal - kKeyNil, // 0x42 - ? - kKeyAsterisk, // 0x43 - kVK_ANSI_KeypadMultiply - kKeyNil, // 0x44 - ? - kKeyPlusPad, // 0x45 - kVK_ANSI_KeypadPlus - kKeyNil, // 0x46 - ? - kKeyDelPad, // 0x47 - kVK_ANSI_KeypadClear - kKeyNil, // 0x48 - kVK_VolumeUp - kKeyNil, // 0x49 - kVK_VolumeDown - kKeyNil, // 0x4A - kVK_Mute - kKeySlashPad, // 0x4B - kVK_ANSI_KeypadDivide - kKeyEnterPad, // 0x4C - kVK_ANSI_KeypadEnter - kKeyNil, // 0x4D - ? - kKeyMinusPad, // 0x4E - kVK_ANSI_KeypadMinus - kKeyNil, // 0x4F - kVK_F18 - // 0x50 - kKeyNil, // 0x50 - kVK_F19 - kKeyEqualsPad, // 0x51 - kVK_ANSI_KeypadEquals - kKey0Pad, // 0x52 - kVK_ANSI_Keypad0 - kKey1Pad, // 0x53 - kVK_ANSI_Keypad1 - kKey2Pad, // 0x54 - kVK_ANSI_Keypad2 - kKey3Pad, // 0x55 - kVK_ANSI_Keypad3 - kKey4Pad, // 0x56 - kVK_ANSI_Keypad4 - kKey5Pad, // 0x57 - kVK_ANSI_Keypad5 - kKey6Pad, // 0x58 - kVK_ANSI_Keypad6 - kKey7Pad, // 0x59 - kVK_ANSI_Keypad7 - kKeyNil, // 0x5A - kVK_F20 - kKey8Pad, // 0x5B - kVK_ANSI_Keypad8 - kKey9Pad, // 0x5C - kVK_ANSI_Keypad9 - kKeyYen, // 0x5D - kVK_JIS_Yen - kKeyNil, // 0x5E - kVK_JIS_Underscore - kKeyNil, // 0x5F - kVK_JIS_KeypadComma - // 0x60 - kKeyF5, // 0x60 - kVK_F5 - kKeyF6, // 0x61 - kVK_F6 - kKeyF7, // 0x62 - kVK_F7 - kKeyF3, // 0x63 - kVK_F3 - kKeyF8, // 0x64 - kVK_F8 - kKeyF9, // 0x65 - kVK_F9 - kKeyNil, // 0x66 - kVK_JIS_Eisu - kKeyF11, // 0x67 - kVK_F11 - kKeyKana, // 0x68 - kVK_JIS_Kana - kKeyNil, // 0x69 - kVK_F13 - kKeyNil, // 0x6A - kVK_F16 - kKeyNil, // 0x6B - kVK_F14 - kKeyNil, // 0x6C - ? - kKeyF10, // 0x6D - kVK_F10 - kKeyNil, // 0x6E - ? - kKeyF12, // 0x6F - kVK_F12 - // 0x70 - kKeyNil, // 0x70 - ? - kKeyNil, // 0x71 - kVK_F15 - kKeyNil, // 0x72 - kVK_Help - kKeyHome, // 0x73 - kVK_Home - kKeyPageUp, // 0x74 - kVK_PageUp - kKeyDel, // 0x75 - kVK_ForwardDelete - kKeyF4, // 0x76 - kVK_F4 - kKeyEnd, // 0x77 - kVK_End - kKeyF2, // 0x78 - kVK_F2 - kKeyPageDown, // 0x79 - kVK_PageDown - kKeyF1, // 0x7A - kVK_F1 - kKeyLeft, // 0x7B - kVK_LeftArrow - kKeyRight, // 0x7C - kVK_RightArrow - kKeyDown, // 0x7D - kVK_DownArrow - kKeyUp, // 0x7E - kVK_UpArrow - kKeyNil // 0x7F - ? - }; - - if (keyCode >= 0 && keyCode < sizeof(map) / sizeof(map[0])) { - // Converts macOS virtual key into a os::KeyScancode - return map[keyCode]; - } - else - return kKeyNil; -} - -KeyScancode scancode_from_nsevent(NSEvent* event) -{ -#if 1 - // For keys that are not in the numpad we try to get the scancode - // converting the first char in NSEvent.characters to a - // scancode. - if ((event.modifierFlags & NSEventModifierFlagNumericPad) == 0) { - KeyScancode code; - - // It looks like getting the first "event.characters" char is the - // only way to get the correct Cmd+letter combination on "Dvorak - - // QWERTY Cmd" keyboard layout. - NSString* chars = event.characters; - if (chars.length > 0) { - int chr = [chars characterAtIndex:chars.length-1]; - - // Avoid activating space bar modifier. E.g. pressing - // Ctrl+Alt+Shift+S on "Spanish ISO" layout generates a - // whitespace ' ', and we prefer the S scancode instead of the - // space bar scancode. - if (chr != 32) { - code = from_char_to_scancode(chr); - if (code != kKeyNil) { - KEY_TRACE("scancode_from_nsevent %d -> %d (characters)\n", - (int)chr, (int)code); - return code; - } - } - } - - chars = event.charactersIgnoringModifiers; - if (chars.length > 0) { - int chr = [chars characterAtIndex:chars.length-1]; - code = from_char_to_scancode(chr); - if (code != kKeyNil) { - KEY_TRACE("scancode_from_nsevent %d -> %d (charactersIgnoringModifiers)\n", - (int)chr, (int)code); - return code; - } - } - } -#else // Don't use this code, it reports scancodes always as QWERTY - // and doesn't work for Dvorak or AZERTY layouts. - { - CFStringRef strRef = get_unicode_from_key_code( - event.keyCode, - event.modifierFlags & NSCommandKeyMask); - - if (strRef) { - KeyScancode code = kKeyNil; - - int length = CFStringGetLength(strRef); - if (length > 0) { - // Converts the first unicode char into a macOS virtual key - UInt16 chr = CFStringGetCharacterAtIndex(strRef, length-1); - code = from_char_to_scancode(chr); - if (code != kKeyNil) { - KEY_TRACE("scancode_from_nsevent %d -> %d (get_unicode_from_key_code)\n", - (int)chr, (int)code); - } - } - - CFRelease(strRef); - if (code != kKeyNil) { - return code; - } - } - } -#endif - - KeyScancode code = from_keycode_to_scancode(event.keyCode); - KEY_TRACE("scancode_from_nsevent %d -> %d (keyCode)\n", - (int)event.keyCode, (int)code); - return code; -} - -// Based on code from: -// http://stackoverflow.com/questions/22566665/how-to-capture-unicode-from-key-events-without-an-nstextview -// http://stackoverflow.com/questions/12547007/convert-key-code-into-key-equivalent-string -// http://stackoverflow.com/questions/8263618/convert-virtual-key-code-to-unicode-string -// -// If "deadKeyState" is = nullptr, it doesn't process dead keys. -CFStringRef get_unicode_from_key_code(const UInt16 keyCode, - const NSEventModifierFlags modifierFlags, - UInt32* deadKeyState) -{ - // The "TISCopyCurrentKeyboardInputSource()" doesn't contain - // kTISPropertyUnicodeKeyLayoutData (returns nullptr) when the input - // source is Japanese (Romaji/Hiragana/Katakana). - - //TISInputSourceRef inputSource = TISCopyCurrentKeyboardInputSource(); - TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource(); - CFDataRef keyLayoutData = (CFDataRef)TISGetInputSourceProperty(inputSource, kTISPropertyUnicodeKeyLayoutData); - const UCKeyboardLayout* keyLayout = - (keyLayoutData ? (const UCKeyboardLayout*)CFDataGetBytePtr(keyLayoutData): nullptr); - - UInt32 deadKeyStateWrap = (deadKeyState ? *deadKeyState: 0); - UniChar output[4]; - UniCharCount length; - - // Reference here: - // https://developer.apple.com/reference/coreservices/1390584-uckeytranslate?language=objc - UCKeyTranslate( - keyLayout, - keyCode, - kUCKeyActionDown, - ((modifierFlags >> 16) & 0xFF), - LMGetKbdType(), - (deadKeyState ? 0: kUCKeyTranslateNoDeadKeysMask), - &deadKeyStateWrap, - sizeof(output) / sizeof(output[0]), - &length, - output); - - if (deadKeyState) - *deadKeyState = deadKeyStateWrap; - - CFRelease(inputSource); - return CFStringCreateWithCharacters(kCFAllocatorDefault, output, length); -} - -} // namespace os diff --git a/src/os/osx/logger.mm b/src/os/osx/logger.mm deleted file mode 100644 index 32b131418..000000000 --- a/src/os/osx/logger.mm +++ /dev/null @@ -1,25 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2014 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include -#include - -#include "os/logger.h" - -namespace os { - - class OSXLogger : public Logger { - public: - void logError(const char* error) override { - NSLog([NSString stringWithUTF8String:error]); - } - }; - - Logger* getOsxLogger() { - return new OSXLogger; - } - -} // namespace os diff --git a/src/os/osx/menus.h b/src/os/osx/menus.h deleted file mode 100644 index 129bfa253..000000000 --- a/src/os/osx/menus.h +++ /dev/null @@ -1,25 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_MENUS_H_INCLUDED -#define OS_OSX_MENUS_H_INCLUDED -#pragma once - -#include "os/menus.h" - -namespace os { - - class MenusOSX : public Menus { - public: - MenusOSX(); - Menu* createMenu() override; - MenuItem* createMenuItem(const MenuItemInfo& info) override; - void setAppMenu(Menu* menu) override; - }; - -} // namespace os - -#endif diff --git a/src/os/osx/menus.mm b/src/os/osx/menus.mm deleted file mode 100644 index b216ee154..000000000 --- a/src/os/osx/menus.mm +++ /dev/null @@ -1,288 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include - -#include "base/debug.h" -#include "base/string.h" -#include "os/osx/menus.h" -#include "os/shortcut.h" - -namespace os { - class MenuItemOSX; -} - -@interface OSXNSMenu : NSMenu -- (BOOL)performKeyEquivalent:(NSEvent*)event; -@end - -@interface OSXNSMenuItem : NSMenuItem { - os::MenuItemOSX* original; -} -+ (OSXNSMenuItem*)alloc:(os::MenuItemOSX*)original; -- (void)executeMenuItem:(id)sender; -- (void)validateMenuItem; -@end - -namespace os { - -extern bool g_keyEquivalentUsed; - -class MenuItemOSX : public MenuItem { -public: - MenuItemOSX(const MenuItemInfo& info); - void dispose() override; - void setText(const std::string& text) override; - void setSubmenu(Menu* submenu) override; - void setEnabled(bool state) override; - void setChecked(bool state) override; - void setShortcut(const Shortcut& shortcut) override; - NSMenuItem* handle() { return m_handle; } - - // Called by OSXNSMenuItem.executeMenuItem - void execute(); - void validate(); - -private: - void syncTitle(); - NSMenuItem* m_handle; - Menu* m_submenu; - std::function m_execute; - std::function m_validate; -}; - -class MenuOSX : public Menu { -public: - MenuOSX(); - void dispose() override; - void addItem(MenuItem* item) override; - void insertItem(const int index, MenuItem* item) override; - NSMenu* handle() { return m_handle; } -private: - NSMenu* m_handle; -}; - -} // namespace os - -@implementation OSXNSMenu -- (BOOL)performKeyEquivalent:(NSEvent*)event -{ - BOOL result = [super performKeyEquivalent:event]; - if (result) - os::g_keyEquivalentUsed = true; - return result; -} -@end - -@implementation OSXNSMenuItem -+ (OSXNSMenuItem*)alloc:(os::MenuItemOSX*)original -{ - OSXNSMenuItem* item = [super alloc]; - item->original = original; - return item; -} -- (void)executeMenuItem:(id)sender -{ - original->execute(); -} -- (void)validateMenuItem -{ - original->validate(); -} -@end - -namespace os { - -MenuItemOSX::MenuItemOSX(const MenuItemInfo& info) - : m_handle(nullptr) - , m_submenu(nullptr) -{ - switch (info.type) { - - case MenuItemInfo::Normal: { - SEL sel = nil; - id target = nil; - switch (info.action) { - - case MenuItemInfo::UserDefined: - sel = @selector(executeMenuItem:); - - // TODO this is strange, it doesn't work, we receive the - // message in OSXAppDelegate anyway. So - // OSXAppDelegate.executeMenuItem: will redirect the message - // to OSXNSMenuItem.executeMenuItem: - target = m_handle; - break; - - case MenuItemInfo::Hide: - sel = @selector(hide:); - break; - - case MenuItemInfo::HideOthers: - sel = @selector(hideOtherApplications:); - break; - - case MenuItemInfo::ShowAll: - sel = @selector(unhideAllApplications:); - break; - - case MenuItemInfo::Quit: - sel = @selector(terminate:); - break; - - case MenuItemInfo::Minimize: - sel = @selector(performMiniaturize:); - break; - - case MenuItemInfo::Zoom: - sel = @selector(performZoom:); - break; - } - - m_handle = - [[OSXNSMenuItem alloc:this] - initWithTitle:[NSString stringWithUTF8String:info.text.c_str()] - action:sel - keyEquivalent:@""]; - - m_handle.target = target; - m_execute = info.execute; - m_validate = info.validate; - - if (!info.shortcut.isEmpty()) - setShortcut(info.shortcut); - break; - } - - case MenuItemInfo::Separator: - m_handle = [NSMenuItem separatorItem]; - break; - } -} - -void MenuItemOSX::dispose() -{ - delete this; -} - -void MenuItemOSX::setText(const std::string& text) -{ - [m_handle setTitle:[NSString stringWithUTF8String:text.c_str()]]; - syncTitle(); -} - -void MenuItemOSX::setSubmenu(Menu* submenu) -{ - m_submenu = submenu; - if (submenu) { - [m_handle setSubmenu:((MenuOSX*)submenu)->handle()]; - syncTitle(); - } - else - [m_handle setSubmenu:nil]; -} - -void MenuItemOSX::setEnabled(bool state) -{ - m_handle.enabled = state; -} - -void MenuItemOSX::setChecked(bool state) -{ - if (state) - m_handle.state = NSOnState; - else - m_handle.state = NSOffState; -} - -void MenuItemOSX::setShortcut(const Shortcut& shortcut) -{ - KeyModifiers mods = shortcut.modifiers(); - NSEventModifierFlags nsFlags = 0; - if (mods & kKeyShiftModifier) nsFlags |= NSEventModifierFlagShift; - if (mods & kKeyCtrlModifier) nsFlags |= NSEventModifierFlagControl; - if (mods & kKeyAltModifier) nsFlags |= NSEventModifierFlagOption; - if (mods & kKeyCmdModifier) nsFlags |= NSEventModifierFlagCommand; - - NSString* keyStr; - if (shortcut.unicode()) { - unichar chr = shortcut.unicode(); - keyStr = [NSString stringWithCharacters:&chr length:1]; - } - else - keyStr = @""; - - m_handle.keyEquivalent = keyStr; - m_handle.keyEquivalentModifierMask = nsFlags; -} - -void MenuItemOSX::execute() -{ - if (m_execute) - m_execute(); -} - -void MenuItemOSX::validate() -{ - if (m_validate) - m_validate(this); -} - -void MenuItemOSX::syncTitle() -{ - // On macOS the submenu title is the one that is displayed in the - // UI instead of the MenuItem title (so here we copy the menu item - // title to the submenu title) - if (m_submenu) - [((MenuOSX*)m_submenu)->handle() setTitle:m_handle.title]; -} - -MenuOSX::MenuOSX() -{ - m_handle = [[OSXNSMenu alloc] init]; -} - -void MenuOSX::dispose() -{ - delete this; -} - -void MenuOSX::addItem(MenuItem* item) -{ - ASSERT(item); - [m_handle addItem:((MenuItemOSX*)item)->handle()]; -} - -void MenuOSX::insertItem(const int index, MenuItem* item) -{ - ASSERT(item); - [m_handle insertItem:((MenuItemOSX*)item)->handle() - atIndex:index]; -} - -MenusOSX::MenusOSX() -{ -} - -Menu* MenusOSX::createMenu() -{ - return new MenuOSX; -} - -MenuItem* MenusOSX::createMenuItem(const MenuItemInfo& info) -{ - return new MenuItemOSX(info); -} - -void MenusOSX::setAppMenu(Menu* menu) -{ - if (menu) - [NSApp setMainMenu:((MenuOSX*)menu)->handle()]; - else - [NSApp setMainMenu:nil]; -} - -} // namespace os diff --git a/src/os/osx/native_dialogs.h b/src/os/osx/native_dialogs.h deleted file mode 100644 index 0c740a3ea..000000000 --- a/src/os/osx/native_dialogs.h +++ /dev/null @@ -1,23 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_NATIVE_DIALOGS_H_INCLUDED -#define OS_OSX_NATIVE_DIALOGS_H_INCLUDED -#pragma once - -#include "os/native_dialogs.h" - -namespace os { - - class NativeDialogsOSX : public NativeDialogs { - public: - NativeDialogsOSX(); - FileDialog* createFileDialog() override; - }; - -} // namespace os - -#endif diff --git a/src/os/osx/native_dialogs.mm b/src/os/osx/native_dialogs.mm deleted file mode 100644 index fc084ccd4..000000000 --- a/src/os/osx/native_dialogs.mm +++ /dev/null @@ -1,174 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include -#include - -#include "base/fs.h" -#include "os/common/file_dialog.h" -#include "os/display.h" -#include "os/keys.h" -#include "os/native_cursor.h" -#include "os/osx/native_dialogs.h" - -@interface OpenSaveHelper : NSObject { -@private - NSSavePanel* panel; - os::Display* display; - int result; -} -- (id)init; -- (void)setPanel:(NSSavePanel*)panel; -- (void)setDisplay:(os::Display*)display; -- (void)runModal; -- (int)result; -@end - -@implementation OpenSaveHelper - -- (id)init -{ - if (self = [super init]) { - result = NSFileHandlingPanelCancelButton; - } - return self; -} - -- (void)setPanel:(NSSavePanel*)newPanel -{ - panel = newPanel; -} - -- (void)setDisplay:(os::Display*)newDisplay -{ - display = newDisplay; -} - -// This is executed in the main thread. -- (void)runModal -{ - os::NativeCursor oldCursor = display->nativeMouseCursor(); - display->setNativeMouseCursor(os::kArrowCursor); - -#ifndef __MAC_10_6 // runModalForTypes is deprecated in 10.6 - if ([panel isKindOfClass:[NSOpenPanel class]]) { - // As we're using OS X 10.4 framework, it looks like runModal - // doesn't recognize the allowedFileTypes property. So we force it - // using runModalForTypes: selector. - - result = [(NSOpenPanel*)panel runModalForTypes:[panel allowedFileTypes]]; - } - else -#endif - { - result = [panel runModal]; - } - - display->setNativeMouseCursor(oldCursor); -} - -- (int)result -{ - return result; -} - -@end - -namespace os { - -class FileDialogOSX : public CommonFileDialog { -public: - FileDialogOSX() { - } - - std::string fileName() override { - return m_filename; - } - - void getMultipleFileNames(base::paths& output) override { - output = m_filenames; - } - - void setFileName(const std::string& filename) override { - m_filename = filename; - } - - bool show(Display* display) override { - bool retValue = false; - @autoreleasepool { - NSSavePanel* panel = nil; - - if (m_type == Type::SaveFile) { - panel = [NSSavePanel new]; - } - else { - panel = [NSOpenPanel new]; - [(NSOpenPanel*)panel setAllowsMultipleSelection:(m_type == Type::OpenFiles ? YES: NO)]; - [(NSOpenPanel*)panel setCanChooseFiles:(m_type != Type::OpenFolder ? YES: NO)]; - [(NSOpenPanel*)panel setCanChooseDirectories:(m_type == Type::OpenFolder ? YES: NO)]; - } - - [panel setTitle:[NSString stringWithUTF8String:m_title.c_str()]]; - [panel setCanCreateDirectories:YES]; - - std::string defPath = base::get_file_path(m_filename); - std::string defName = base::get_file_name(m_filename); - if (!defPath.empty()) - [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:defPath.c_str()]]]; - if (!defName.empty()) - [panel setNameFieldStringValue:[NSString stringWithUTF8String:defName.c_str()]]; - - if (m_type != Type::OpenFolder && !m_filters.empty()) { - NSMutableArray* types = [[NSMutableArray alloc] init]; - // The first extension in the array is used as the default one. - if (!m_defExtension.empty()) - [types addObject:[NSString stringWithUTF8String:m_defExtension.c_str()]]; - for (const auto& filter : m_filters) - [types addObject:[NSString stringWithUTF8String:filter.first.c_str()]]; - [panel setAllowedFileTypes:types]; - if (m_type == Type::SaveFile) - [panel setAllowsOtherFileTypes:NO]; - } - - OpenSaveHelper* helper = [OpenSaveHelper new]; - [helper setPanel:panel]; - [helper setDisplay:display]; - [helper performSelectorOnMainThread:@selector(runModal) withObject:nil waitUntilDone:YES]; - - if ([helper result] == NSFileHandlingPanelOKButton) { - if (m_type == Type::OpenFiles) { - for (NSURL* url in [(NSOpenPanel*)panel URLs]) { - m_filename = [[url path] UTF8String]; - m_filenames.push_back(m_filename); - } - } - else { - NSURL* url = [panel URL]; - m_filename = [[url path] UTF8String]; - m_filenames.push_back(m_filename); - } - retValue = true; - } - } - return retValue; - } - -private: - - std::string m_filename; - base::paths m_filenames; -}; - -NativeDialogsOSX::NativeDialogsOSX() -{ -} - -FileDialog* NativeDialogsOSX::createFileDialog() -{ - return new FileDialogOSX(); -} - -} // namespace os diff --git a/src/os/osx/system.h b/src/os/osx/system.h deleted file mode 100644 index ffc0e48ac..000000000 --- a/src/os/osx/system.h +++ /dev/null @@ -1,31 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_SYSTEM_H -#define OS_OSX_SYSTEM_H -#pragma once - -#include "os/common/system.h" - -namespace os { - -bool osx_is_key_pressed(KeyScancode scancode); -int osx_get_unicode_from_scancode(KeyScancode scancode); - -class OSXSystem : public CommonSystem { -public: - bool isKeyPressed(KeyScancode scancode) override { - return osx_is_key_pressed(scancode); - } - - int getUnicodeFromScancode(KeyScancode scancode) override { - return osx_get_unicode_from_scancode(scancode); - } -}; - -} // namespace os - -#endif diff --git a/src/os/osx/view.h b/src/os/osx/view.h deleted file mode 100644 index cd97e5391..000000000 --- a/src/os/osx/view.h +++ /dev/null @@ -1,60 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_VIEW_H_INCLUDED -#define OS_OSX_VIEW_H_INCLUDED -#pragma once - -#include "os/pointer_type.h" - -#include - -@interface OSXView : NSView { -@private - NSTrackingArea* m_trackingArea; - NSCursor* m_nsCursor; - bool m_visibleMouse; - os::PointerType m_pointerType; -} -- (id)initWithFrame:(NSRect)frameRect; -- (BOOL)acceptsFirstResponder; -- (void)viewDidHide; -- (void)viewDidUnhide; -- (void)viewDidMoveToWindow; -- (void)drawRect:(NSRect)dirtyRect; -- (void)keyDown:(NSEvent*)event; -- (void)keyUp:(NSEvent*)event; -- (void)flagsChanged:(NSEvent*)event; -+ (void)updateKeyFlags:(NSEvent*)event; -- (void)mouseEntered:(NSEvent*)event; -- (void)mouseMoved:(NSEvent*)event; -- (void)mouseExited:(NSEvent*)event; -- (void)mouseDown:(NSEvent*)event; -- (void)mouseUp:(NSEvent*)event; -- (void)mouseDragged:(NSEvent*)event; -- (void)rightMouseDown:(NSEvent*)event; -- (void)rightMouseUp:(NSEvent*)event; -- (void)rightMouseDragged:(NSEvent*)event; -- (void)otherMouseDown:(NSEvent*)event; -- (void)otherMouseUp:(NSEvent*)event; -- (void)otherMouseDragged:(NSEvent*)event; -- (void)handleMouseDown:(NSEvent*)event; -- (void)handleMouseUp:(NSEvent*)event; -- (void)handleMouseDragged:(NSEvent*)event; -- (void)scrollWheel:(NSEvent*)event; -- (void)cursorUpdate:(NSEvent*)event; -- (void)setCursor:(NSCursor*)cursor; -- (void)setFrameSize:(NSSize)newSize; -- (void)createMouseTrackingArea; -- (void)destroyMouseTrackingArea; -- (void)updateCurrentCursor; -- (NSDragOperation)draggingEntered:(id)sender; -- (BOOL)performDragOperation:(id)sender; -- (void)doCommandBySelector:(SEL)selector; -- (void)setTranslateDeadKeys:(BOOL)state; -@end - -#endif diff --git a/src/os/osx/view.mm b/src/os/osx/view.mm deleted file mode 100644 index ce90104de..000000000 --- a/src/os/osx/view.mm +++ /dev/null @@ -1,585 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#define KEY_TRACE(...) - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/osx/view.h" - -#include "gfx/point.h" -#include "os/event.h" -#include "os/event_queue.h" -#include "os/osx/generate_drop_files.h" -#include "os/osx/keys.h" -#include "os/osx/window.h" -#include "os/system.h" - -namespace os { - -// Global variable used between View and OSXNSMenu to check if the -// keyDown: event was used by a key equivalent in the menu. -// -// TODO I'm not proud of this, but it does the job -bool g_keyEquivalentUsed = false; - -bool osx_is_key_pressed(KeyScancode scancode); - -namespace { - -// Internal array of pressed keys used in isKeyPressed() -int g_pressedKeys[kKeyScancodes]; -bool g_translateDeadKeys = false; -UInt32 g_lastDeadKeyState = 0; - -gfx::Point get_local_mouse_pos(NSView* view, NSEvent* event) -{ - NSPoint point = [view convertPoint:[event locationInWindow] - fromView:nil]; - int scale = 1; - if ([view window]) - scale = [(OSXWindow*)[view window] scale]; - - // "os" layer coordinates expect (X,Y) origin at the top-left corner. - return gfx::Point(point.x / scale, - (view.bounds.size.height - point.y) / scale); -} - -Event::MouseButton get_mouse_buttons(NSEvent* event) -{ - // Some Wacom drivers on OS X report right-clicks with - // buttonNumber=0, so we've to check the type event anyway. - switch (event.type) { - case NSEventTypeLeftMouseDown: - case NSEventTypeLeftMouseUp: - case NSEventTypeLeftMouseDragged: - return Event::LeftButton; - case NSEventTypeRightMouseDown: - case NSEventTypeRightMouseUp: - case NSEventTypeRightMouseDragged: - return Event::RightButton; - } - - switch (event.buttonNumber) { - case 0: return Event::LeftButton; break; - case 1: return Event::RightButton; break; - case 2: return Event::MiddleButton; break; - // NSOtherMouseDown/Up/Dragged - case 3: return Event::X1Button; break; - case 4: return Event::X2Button; break; - } - - return Event::MouseButton::NoneButton; -} - -KeyModifiers get_modifiers_from_nsevent(NSEvent* event) -{ - int modifiers = kKeyNoneModifier; - NSEventModifierFlags nsFlags = event.modifierFlags; - if (nsFlags & NSEventModifierFlagShift) modifiers |= kKeyShiftModifier; - if (nsFlags & NSEventModifierFlagControl) modifiers |= kKeyCtrlModifier; - if (nsFlags & NSEventModifierFlagOption) modifiers |= kKeyAltModifier; - if (nsFlags & NSEventModifierFlagCommand) modifiers |= kKeyCmdModifier; - if (osx_is_key_pressed(kKeySpace)) modifiers |= kKeySpaceModifier; - return (KeyModifiers)modifiers; -} - -} // anonymous namespace - -bool osx_is_key_pressed(KeyScancode scancode) -{ - if (scancode >= 0 && scancode < kKeyScancodes) - return (g_pressedKeys[scancode] != 0); - else - return false; -} - -int osx_get_unicode_from_scancode(KeyScancode scancode) -{ - if (scancode >= 0 && scancode < kKeyScancodes) - return g_pressedKeys[scancode]; - else - return 0; -} - -} // namespace os - -using namespace os; - -@implementation OSXView - -- (id)initWithFrame:(NSRect)frameRect -{ - // We start without the system mouse cursor - m_nsCursor = nil; - m_visibleMouse = true; - m_pointerType = os::PointerType::Unknown; - - self = [super initWithFrame:frameRect]; - if (self != nil) { - [self createMouseTrackingArea]; - [self registerForDraggedTypes: - [NSArray arrayWithObjects: - NSFilenamesPboardType, - nil]]; - } - return self; -} - -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -- (void)viewDidHide -{ - [super viewDidHide]; - [self destroyMouseTrackingArea]; -} - -- (void)viewDidUnhide -{ - [super viewDidUnhide]; - [self createMouseTrackingArea]; -} - -- (void)viewDidMoveToWindow -{ - [super viewDidMoveToWindow]; - - if ([self window]) { - OSXWindowImpl* impl = [((OSXWindow*)[self window]) impl]; - if (impl) - impl->onWindowChanged(); - } -} - -- (void)drawRect:(NSRect)dirtyRect -{ - [super drawRect:dirtyRect]; - - if ([self window]) { - OSXWindowImpl* impl = [((OSXWindow*)[self window]) impl]; - if (impl) - impl->onDrawRect(gfx::Rect(dirtyRect.origin.x, - dirtyRect.origin.y, - dirtyRect.size.width, - dirtyRect.size.height)); - } -} - -- (void)keyDown:(NSEvent*)event -{ - g_keyEquivalentUsed = false; - [super keyDown:event]; - - // If a key equivalent used the keyDown event, we don't generate - // this os::KeyDown event. - if (g_keyEquivalentUsed) - return; - - KeyScancode scancode = scancode_from_nsevent(event); - Event ev; - ev.setType(Event::KeyDown); - ev.setScancode(scancode); - ev.setModifiers(get_modifiers_from_nsevent(event)); - ev.setRepeat(event.ARepeat ? 1: 0); - ev.setUnicodeChar(0); - - bool sendMsg = true; - - CFStringRef strRef = get_unicode_from_key_code(event.keyCode, - event.modifierFlags); - if (strRef) { - int length = CFStringGetLength(strRef); - if (length == 1) - ev.setUnicodeChar(CFStringGetCharacterAtIndex(strRef, 0)); - CFRelease(strRef); - } - - if (scancode >= 0 && scancode < kKeyScancodes) - g_pressedKeys[scancode] = (ev.unicodeChar() ? ev.unicodeChar(): 1); - - if (g_translateDeadKeys) { - strRef = get_unicode_from_key_code(event.keyCode, - event.modifierFlags, - &g_lastDeadKeyState); - if (strRef) { - int length = CFStringGetLength(strRef); - if (length > 0) { - sendMsg = false; - for (int i=0; i= 0 && scancode < kKeyScancodes) - g_pressedKeys[scancode] = 0; - - Event ev; - ev.setType(Event::KeyUp); - ev.setScancode(scancode); - ev.setModifiers(get_modifiers_from_nsevent(event)); - ev.setRepeat(event.ARepeat ? 1: 0); - ev.setUnicodeChar(0); - - queue_event(ev); -} - -- (void)flagsChanged:(NSEvent*)event -{ - [super flagsChanged:event]; - [OSXView updateKeyFlags:event]; -} - -+ (void)updateKeyFlags:(NSEvent*)event -{ - static int lastFlags = 0; - static int flags[] = { - NSEventModifierFlagShift, - NSEventModifierFlagControl, - NSEventModifierFlagOption, - NSEventModifierFlagCommand - }; - static KeyScancode scancodes[] = { - kKeyLShift, - kKeyLControl, - kKeyAlt, - kKeyCommand - }; - - KeyModifiers modifiers = get_modifiers_from_nsevent(event); - int newFlags = event.modifierFlags; - - for (int i=0; ionResize(gfx::Size(newSize.width, - newSize.height)); - } -} - -- (void)scrollWheel:(NSEvent*)event -{ - Event ev; - ev.setType(Event::MouseWheel); - ev.setPosition(get_local_mouse_pos(self, event)); - ev.setButton(get_mouse_buttons(event)); - ev.setModifiers(get_modifiers_from_nsevent(event)); - - int scale = 1; - if (self.window) - scale = [(OSXWindow*)self.window scale]; - - if (event.hasPreciseScrollingDeltas) { - ev.setPointerType(os::PointerType::Touchpad); - ev.setWheelDelta(gfx::Point(-event.scrollingDeltaX / scale, - -event.scrollingDeltaY / scale)); - ev.setPreciseWheel(true); - } - else { - // Ignore the acceleration factor, just use the wheel sign. - gfx::Point pt(0, 0); - if (event.scrollingDeltaX >= 0.1) - pt.x = -1; - else if (event.scrollingDeltaX <= -0.1) - pt.x = 1; - if (event.scrollingDeltaY >= 0.1) - pt.y = -1; - else if (event.scrollingDeltaY <= -0.1) - pt.y = 1; - - ev.setPointerType(os::PointerType::Mouse); - ev.setWheelDelta(pt); - } - - queue_event(ev); -} - -- (void)magnifyWithEvent:(NSEvent*)event -{ - Event ev; - ev.setType(Event::TouchMagnify); - ev.setMagnification(event.magnification); - ev.setPosition(get_local_mouse_pos(self, event)); - ev.setModifiers(get_modifiers_from_nsevent(event)); - ev.setPointerType(os::PointerType::Touchpad); - queue_event(ev); -} - -- (void)tabletProximity:(NSEvent*)event -{ - if (event.isEnteringProximity == YES) { - switch (event.pointingDeviceType) { - case NSPointingDeviceTypePen: m_pointerType = os::PointerType::Pen; break; - case NSPointingDeviceTypeCursor: m_pointerType = os::PointerType::Cursor; break; - case NSPointingDeviceTypeEraser: m_pointerType = os::PointerType::Eraser; break; - default: - m_pointerType = os::PointerType::Unknown; - break; - } - } - else { - m_pointerType = os::PointerType::Unknown; - } -} - -- (void)cursorUpdate:(NSEvent*)event -{ - [self updateCurrentCursor]; -} - -- (void)setCursor:(NSCursor*)cursor -{ - m_nsCursor = cursor; - [self updateCurrentCursor]; -} - -- (void)createMouseTrackingArea -{ - // Create a tracking area to receive mouseMoved events - m_trackingArea = - [[NSTrackingArea alloc] - initWithRect:self.bounds - options:(NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveAlways | - NSTrackingEnabledDuringMouseDrag) - owner:self - userInfo:nil]; - [self addTrackingArea:m_trackingArea]; -} - -- (void)destroyMouseTrackingArea -{ - [self removeTrackingArea:m_trackingArea]; - m_trackingArea = nil; -} - -- (void)updateCurrentCursor -{ - if (m_nsCursor) { - if (!m_visibleMouse) { - m_visibleMouse = true; - [NSCursor unhide]; - } - [m_nsCursor set]; - } - else if (m_visibleMouse) { - m_visibleMouse = false; - [NSCursor hide]; - } -} - -- (NSDragOperation)draggingEntered:(id)sender -{ - return NSDragOperationCopy; -} - -- (BOOL)performDragOperation:(id )sender -{ - NSPasteboard* pasteboard = [sender draggingPasteboard]; - - if ([pasteboard.types containsObject:NSFilenamesPboardType]) { - NSArray* filenames = [pasteboard propertyListForType:NSFilenamesPboardType]; - generate_drop_files_from_nsarray(filenames); - return YES; - } - else - return NO; -} - -- (void)doCommandBySelector:(SEL)selector -{ - // Do nothing (avoid beep pressing Escape key) -} - -- (void)setTranslateDeadKeys:(BOOL)state -{ - g_translateDeadKeys = (state ? true: false); - g_lastDeadKeyState = 0; -} - -@end diff --git a/src/os/osx/window.h b/src/os/osx/window.h deleted file mode 100644 index 5e559a12a..000000000 --- a/src/os/osx/window.h +++ /dev/null @@ -1,56 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_OSX_WINDOW_H_INCLUDED -#define OS_OSX_WINDOW_H_INCLUDED -#pragma once - -#include - -#include "gfx/point.h" -#include "gfx/rect.h" -#include "gfx/size.h" -#include "os/keys.h" -#include "os/native_cursor.h" - -namespace os { - class Surface; -} - -class OSXWindowImpl { -public: - virtual ~OSXWindowImpl() { } - virtual void onClose() = 0; - virtual void onResize(const gfx::Size& size) = 0; - virtual void onDrawRect(const gfx::Rect& rect) = 0; - virtual void onWindowChanged() = 0; -}; - -@class OSXWindowDelegate; - -@interface OSXWindow : NSWindow { -@private - OSXWindowImpl* m_impl; - OSXWindowDelegate* m_delegate; - int m_scale; -} -- (OSXWindow*)initWithImpl:(OSXWindowImpl*)impl - width:(int)width - height:(int)height - scale:(int)scale; -- (OSXWindowImpl*)impl; -- (int)scale; -- (void)setScale:(int)scale; -- (gfx::Size)clientSize; -- (gfx::Size)restoredSize; -- (void)setMousePosition:(const gfx::Point&)position; -- (BOOL)setNativeMouseCursor:(os::NativeCursor)cursor; -- (BOOL)setNativeMouseCursor:(const os::Surface*)surface - focus:(const gfx::Point&)focus - scale:(const int)scale; -@end - -#endif diff --git a/src/os/osx/window.mm b/src/os/osx/window.mm deleted file mode 100644 index 2596fab6c..000000000 --- a/src/os/osx/window.mm +++ /dev/null @@ -1,242 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/osx/window.h" - -#include "base/debug.h" -#include "os/event.h" -#include "os/osx/event_queue.h" -#include "os/osx/view.h" -#include "os/osx/window_delegate.h" -#include "os/surface.h" - -using namespace os; - -@implementation OSXWindow - -- (OSXWindow*)initWithImpl:(OSXWindowImpl*)impl - width:(int)width - height:(int)height - scale:(int)scale -{ - m_impl = impl; - m_scale = scale; - - NSRect rect = NSMakeRect(0, 0, width, height); - self = [self initWithContentRect:rect - styleMask:(NSWindowStyleMaskTitled | - NSWindowStyleMaskClosable | - NSWindowStyleMaskMiniaturizable | - NSWindowStyleMaskResizable) - backing:NSBackingStoreBuffered - defer:NO]; - if (!self) - return nil; - - m_delegate = [[OSXWindowDelegate alloc] initWithWindowImpl:impl]; - - // The NSView width and height will be a multiple of 4. In this way - // all scaled pixels should be exactly the same - // for Screen Scaling > 1 and <= 4) - self.contentResizeIncrements = NSMakeSize(4, 4); - - OSXView* view = [[OSXView alloc] initWithFrame:rect]; - [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - [self setDelegate:m_delegate]; - [self setContentView:view]; - [self center]; - [self makeKeyAndOrderFront:self]; - - // Hide the "View > Show Tab Bar" menu item - if ([self respondsToSelector:@selector(setTabbingMode:)]) - [self setTabbingMode:NSWindowTabbingModeDisallowed]; - - return self; -} - -- (OSXWindowImpl*)impl -{ - return m_impl; -} - -- (int)scale -{ - return m_scale; -} - -- (void)setScale:(int)scale -{ - m_scale = scale; - - if (m_impl) { - NSRect bounds = [[self contentView] bounds]; - m_impl->onResize(gfx::Size(bounds.size.width, - bounds.size.height)); - } -} - -- (gfx::Size)clientSize -{ - return gfx::Size([[self contentView] frame].size.width, - [[self contentView] frame].size.height); -} - -- (gfx::Size)restoredSize -{ - return [self clientSize]; -} - -- (void)setMousePosition:(const gfx::Point&)position -{ - NSView* view = self.contentView; - NSPoint pt = NSMakePoint( - position.x*m_scale, - view.frame.size.height - position.y*m_scale); - - pt = [view convertPoint:pt toView:view]; - pt = [view convertPoint:pt toView:nil]; - pt = [self convertBaseToScreen:pt]; - pt.y = [[self screen] frame].size.height - pt.y; - - CGPoint pos = CGPointMake(pt.x, pt.y); - CGEventRef event = CGEventCreateMouseEvent( - NULL, kCGEventMouseMoved, pos, kCGMouseButtonLeft); - CGEventPost(kCGHIDEventTap, event); - CFRelease(event); -} - -- (BOOL)setNativeMouseCursor:(NativeCursor)cursor -{ - NSCursor* nsCursor = nullptr; - - switch (cursor) { - case kArrowCursor: - case kWaitCursor: - case kHelpCursor: - case kSizeNECursor: - case kSizeNWCursor: - case kSizeSECursor: - case kSizeSWCursor: - nsCursor = [NSCursor arrowCursor]; - break; - case kCrosshairCursor: - nsCursor = [NSCursor crosshairCursor]; - break; - case kIBeamCursor: - nsCursor = [NSCursor IBeamCursor]; - break; - case kLinkCursor: - nsCursor = [NSCursor pointingHandCursor]; - break; - case kForbiddenCursor: - nsCursor = [NSCursor operationNotAllowedCursor]; - break; - case kMoveCursor: - nsCursor = [NSCursor openHandCursor]; - break; - case kSizeNSCursor: - nsCursor = [NSCursor resizeUpDownCursor]; - break; - case kSizeWECursor: - nsCursor = [NSCursor resizeLeftRightCursor]; - break; - case kSizeNCursor: - nsCursor = [NSCursor resizeUpCursor]; - break; - case kSizeECursor: - nsCursor = [NSCursor resizeRightCursor]; - break; - case kSizeSCursor: - nsCursor = [NSCursor resizeDownCursor]; - break; - case kSizeWCursor: - nsCursor = [NSCursor resizeLeftCursor]; - break; - } - - [self.contentView setCursor:nsCursor]; - return (nsCursor ? YES: NO); -} - -- (BOOL)setNativeMouseCursor:(const os::Surface*)surface - focus:(const gfx::Point&)focus - scale:(const int)scale -{ - ASSERT(surface); - SurfaceFormatData format; - surface->getFormat(&format); - if (format.bitsPerPixel != 32) - return NO; - - const int w = scale*surface->width(); - const int h = scale*surface->height(); - - if (4*w*h == 0) - return NO; - - @autoreleasepool { - NSBitmapImageRep* bmp = - [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:nil - pixelsWide:w - pixelsHigh:h - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:NSAlphaNonpremultipliedBitmapFormat - bytesPerRow:w*4 - bitsPerPixel:32]; - if (!bmp) - return NO; - - uint32_t* dst = (uint32_t*)[bmp bitmapData]; - for (int y=0; ygetData(0, y/scale); - for (int x=0, u=0; xonClose(); -} - -- (void)windowDidResize:(NSNotification*)notification -{ -} - -- (void)windowDidMiniaturize:(NSNotification*)notification -{ -} - -@end diff --git a/src/os/pointer_type.h b/src/os/pointer_type.h deleted file mode 100644 index db5cd9d66..000000000 --- a/src/os/pointer_type.h +++ /dev/null @@ -1,26 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_POINTER_TYPE_H_INCLUDED -#define OS_POINTER_TYPE_H_INCLUDED -#pragma once - -namespace os { - - // Source of a mouse like event - enum class PointerType { - Unknown, - Mouse, // A regular mouse - Touchpad, // Touchpad/trackpad - Touch, // Touch screen - Pen, // Stylus pen - Cursor, // Puck like device - Eraser // Eraser end of a stylus pen - }; - -} // namespace os - -#endif diff --git a/src/os/scoped_handle.h b/src/os/scoped_handle.h deleted file mode 100644 index f84bc1eb9..000000000 --- a/src/os/scoped_handle.h +++ /dev/null @@ -1,34 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2013 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SCOPED_HANDLE_H_INCLUDED -#define OS_SCOPED_HANDLE_H_INCLUDED -#pragma once - -namespace os { - - template - class ScopedHandle { - public: - ScopedHandle(T* handle) : m_handle(handle) { } - ~ScopedHandle() { - if (m_handle) - m_handle->dispose(); - } - - T* operator->() { return m_handle; } - operator T*() { return m_handle; } - private: - T* m_handle; - - // Cannot copy - ScopedHandle(const ScopedHandle&); - ScopedHandle& operator=(const ScopedHandle&); - }; - -} // namespace os - -#endif diff --git a/src/os/shortcut.h b/src/os/shortcut.h deleted file mode 100644 index 70836e93e..000000000 --- a/src/os/shortcut.h +++ /dev/null @@ -1,35 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SHORTCUT_H_INCLUDED -#define OS_SHORTCUT_H_INCLUDED -#pragma once - -#include "os/keys.h" - -namespace os { - - class Shortcut { - public: - Shortcut(int unicode = 0, - KeyModifiers modifiers = kKeyNoneModifier) - : m_unicode(unicode) - , m_modifiers(modifiers) { - } - - int unicode() const { return m_unicode; } - KeyModifiers modifiers() const { return m_modifiers; } - - bool isEmpty() const { return m_unicode == 0; } - - private: - int m_unicode; - KeyModifiers m_modifiers; - }; - -} // namespace os - -#endif diff --git a/src/os/skia/os.cpp b/src/os/skia/os.cpp deleted file mode 100644 index e59a466ea..000000000 --- a/src/os/skia/os.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "base/memory.h" -#include "gfx/rect.h" -#include "gfx/size.h" - -#include "os/skia/skia_system.h" - -#if __APPLE__ - #include "os/osx/app.h" - #include -#elif !defined(_WIN32) - #include "os/x11/x11.h" -#endif - -namespace os { - -System* create_system_impl() { - return new SkiaSystem; -} - -void error_message(const char* msg) -{ - fputs(msg, stderr); - // TODO -} - -} // namespace os - -extern int app_main(int argc, char* argv[]); - -#if _WIN32 -int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, - PWSTR lpCmdLine, int nCmdShow) { - int argc = __argc; - char** argv; - if (__wargv && argc > 0) { - argv = new char*[argc]; - for (int i=0; ieventQueue(), this, width, height, scale) - , m_surface(new SkiaSurface) - , m_customSurface(false) - , m_nativeCursor(kArrowCursor) -{ - m_window.setScale(scale); - m_window.setVisible(true); - - resetSkiaSurface(); - - m_initialized = true; -} - -void SkiaDisplay::setSkiaSurface(SkiaSurface* surface) -{ - m_surface->dispose(); - m_surface = surface; - m_customSurface = true; -} - -void SkiaDisplay::resetSkiaSurface() -{ - if (m_surface) { - m_surface->dispose(); - m_surface = nullptr; - } - - gfx::Size size = m_window.clientSize() / m_window.scale(); - m_surface = new SkiaSurface; - m_surface->create(size.w, size.h); - m_customSurface = false; -} - -void SkiaDisplay::resize(const gfx::Size& size) -{ - Event ev; - ev.setType(Event::ResizeDisplay); - ev.setDisplay(this); - os::queue_event(ev); - - if (!m_initialized || m_customSurface) - return; - - m_surface->dispose(); - m_surface = new SkiaSurface; - m_surface->create(size.w / m_window.scale(), - size.h / m_window.scale()); -} - -void SkiaDisplay::dispose() -{ - delete this; -} - -int SkiaDisplay::width() const -{ - return m_window.clientSize().w; -} - -int SkiaDisplay::height() const -{ - return m_window.clientSize().h; -} - -int SkiaDisplay::originalWidth() const -{ - return m_window.restoredSize().w; -} - -int SkiaDisplay::originalHeight() const -{ - return m_window.restoredSize().h; -} - -int SkiaDisplay::scale() const -{ - return m_window.scale(); -} - -void SkiaDisplay::setScale(int scale) -{ - ASSERT(scale > 0); - m_window.setScale(scale); -} - -Surface* SkiaDisplay::getSurface() -{ - return m_surface; -} - -// Flips all graphics in the surface to the real display. Returns -// false if the flip couldn't be done because the display was -// resized. -void SkiaDisplay::flip(const gfx::Rect& bounds) -{ - m_window.updateWindow(bounds); -} - -void SkiaDisplay::maximize() -{ - m_window.maximize(); -} - -bool SkiaDisplay::isMaximized() const -{ - return m_window.isMaximized(); -} - -bool SkiaDisplay::isMinimized() const -{ - return m_window.isMinimized(); -} - -void SkiaDisplay::setTitleBar(const std::string& title) -{ - m_window.setTitle(title); -} - -void SkiaDisplay::setIcons(const SurfaceList& icons) -{ -#if !defined(_WIN32) && !defined(__APPLE__) - m_window.setIcons(icons); -#endif -} - -NativeCursor SkiaDisplay::nativeMouseCursor() -{ - return m_nativeCursor; -} - -bool SkiaDisplay::setNativeMouseCursor(NativeCursor cursor) -{ - m_nativeCursor = cursor; - return m_window.setNativeMouseCursor(cursor); -} - -bool SkiaDisplay::setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale) -{ - return m_window.setNativeMouseCursor(surface, focus, scale); -} - -void SkiaDisplay::setMousePosition(const gfx::Point& position) -{ - m_window.setMousePosition(position); -} - -void SkiaDisplay::captureMouse() -{ - m_window.captureMouse(); -} - -void SkiaDisplay::releaseMouse() -{ - m_window.releaseMouse(); -} - -std::string SkiaDisplay::getLayout() -{ - return m_window.getLayout(); -} - -void SkiaDisplay::setLayout(const std::string& layout) -{ - m_window.setLayout(layout); -} - -void SkiaDisplay::setInterpretOneFingerGestureAsMouseMovement(bool state) -{ -#ifdef _WIN32 - m_window.setInterpretOneFingerGestureAsMouseMovement(state); -#endif -} - -void SkiaDisplay::setTranslateDeadKeys(bool state) -{ - m_window.setTranslateDeadKeys(state); -} - -DisplayHandle SkiaDisplay::nativeHandle() -{ - return (DisplayHandle)m_window.handle(); -} - -} // namespace os diff --git a/src/os/skia/skia_display.h b/src/os/skia/skia_display.h deleted file mode 100644 index c6ded9263..000000000 --- a/src/os/skia/skia_display.h +++ /dev/null @@ -1,84 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_DISPLAY_INCLUDED -#define OS_SKIA_SKIA_DISPLAY_INCLUDED -#pragma once - -#include "os/display.h" -#include "os/native_cursor.h" -#include "os/skia/skia_window.h" - -namespace os { - -class SkiaSurface; - -class SkiaDisplay : public Display { -public: - SkiaDisplay(int width, int height, int scale); - - bool isInitialized() const { return m_initialized; } - void setSkiaSurface(SkiaSurface* surface); - void resetSkiaSurface(); - - void resize(const gfx::Size& size); - void dispose() override; - - // Returns the real and current display's size (without scale applied). - int width() const override; - int height() const override; - - // Returns the display when it was not maximized. - int originalWidth() const override; - int originalHeight() const override; - - int scale() const override; - void setScale(int scale) override; - - // Returns the main surface to draw into this display. - // You must not dispose this surface. - Surface* getSurface() override; - - // Flips all graphics in the surface to the real display. - void flip(const gfx::Rect& bounds) override; - void maximize() override; - bool isMaximized() const override; - bool isMinimized() const override; - void setTitleBar(const std::string& title) override; - void setIcons(const SurfaceList& icons) override; - NativeCursor nativeMouseCursor() override; - bool setNativeMouseCursor(NativeCursor cursor) override; - bool setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale) override; - void setMousePosition(const gfx::Point& position) override; - void captureMouse() override; - void releaseMouse() override; - - std::string getLayout() override; - void setLayout(const std::string& layout) override; - - void setInterpretOneFingerGestureAsMouseMovement(bool state) override; - - void setTranslateDeadKeys(bool state); - - // Returns the HWND on Windows. - DisplayHandle nativeHandle() override; - -private: - // Flag used to avoid accessing to an invalid m_surface in the first - // SkiaDisplay::resize() call when the SkiaWindow is created (as the - // window is created, it send a first resize event.) - bool m_initialized; - SkiaWindow m_window; - SkiaSurface* m_surface; - bool m_customSurface; - NativeCursor m_nativeCursor; -}; - -} // namespace os - -#endif diff --git a/src/os/skia/skia_surface.cpp b/src/os/skia/skia_surface.cpp deleted file mode 100644 index a2ad8d2bd..000000000 --- a/src/os/skia/skia_surface.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/skia/skia_surface.h" - -#include "base/file_handle.h" - -#include "SkCodec.h" -#include "SkPixelRef.h" -#include "SkStream.h" - -#include - -namespace os { - -sk_sp SkiaSurface::m_colorSpace; - -// static -Surface* SkiaSurface::loadSurface(const char* filename) -{ - FILE* f = base::open_file_raw(filename, "rb"); - if (!f) - return nullptr; - - std::unique_ptr codec( - SkCodec::MakeFromStream( - std::unique_ptr(new SkFILEStream(f)))); - if (!codec) - return nullptr; - - SkImageInfo info = codec->getInfo() - .makeColorType(kN32_SkColorType) - .makeAlphaType(kPremul_SkAlphaType) - .makeColorSpace(colorSpace()); - SkBitmap bm; - if (!bm.tryAllocPixels(info)) - return nullptr; - - const SkCodec::Result r = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); - if (r != SkCodec::kSuccess) - return nullptr; - - SkiaSurface* sur = new SkiaSurface(); - sur->swapBitmap(bm); - return sur; -} - -// static -sk_sp SkiaSurface::colorSpace() -{ -#if 0 // TODO Add support to different color spaces - if (!m_colorSpace) - m_colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); -#endif - return m_colorSpace; -} - -} // namespace os diff --git a/src/os/skia/skia_surface.h b/src/os/skia/skia_surface.h deleted file mode 100644 index 4df8a75fb..000000000 --- a/src/os/skia/skia_surface.h +++ /dev/null @@ -1,549 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_SURFACE_INCLUDED -#define OS_SKIA_SKIA_SURFACE_INCLUDED -#pragma once - -#include "base/exception.h" -#include "gfx/clip.h" -#include "os/common/generic_surface.h" -#include "os/common/sprite_sheet_font.h" - -#include "SkBitmap.h" -#include "SkCanvas.h" -#include "SkColorFilter.h" -#include "SkColorPriv.h" -#include "SkImageInfo.h" -#include "SkRegion.h" -#include "SkSurface.h" - -#ifndef SK_BGRA_B32_SHIFT - #ifdef SK_CPU_BENDIAN - #define SK_BGRA_B32_SHIFT 24 - #define SK_BGRA_G32_SHIFT 16 - #define SK_BGRA_R32_SHIFT 8 - #define SK_BGRA_A32_SHIFT 0 - #else - #define SK_BGRA_B32_SHIFT 0 - #define SK_BGRA_G32_SHIFT 8 - #define SK_BGRA_R32_SHIFT 16 - #define SK_BGRA_A32_SHIFT 24 - #endif -#endif - -#ifndef SK_A4444_SHIFT - #define SK_R4444_SHIFT 12 - #define SK_G4444_SHIFT 8 - #define SK_B4444_SHIFT 4 - #define SK_A4444_SHIFT 0 -#endif - -namespace os { - -inline SkColor to_skia(gfx::Color c) { - return SkColorSetARGBInline(gfx::geta(c), gfx::getr(c), gfx::getg(c), gfx::getb(c)); -} - -inline SkIRect to_skia(const gfx::Rect& rc) { - return SkIRect::MakeXYWH(rc.x, rc.y, rc.w, rc.h); -} - -class SkiaSurface : public Surface { -public: - SkiaSurface() : m_surface(nullptr) - , m_canvas(nullptr) - , m_lock(0) { - } - - SkiaSurface(const sk_sp& surface) - : m_surface(surface) - , m_canvas(nullptr) - , m_lock(0) - { - ASSERT(m_surface); - if (m_surface) - m_canvas = m_surface->getCanvas(); - } - - ~SkiaSurface() { - ASSERT(m_lock == 0); - if (!m_surface) - delete m_canvas; - } - - void create(int width, int height) { - ASSERT(!m_surface); - - if (!m_bitmap.tryAllocPixels( - SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType, - colorSpace()))) - throw base::Exception("Cannot create Skia surface"); - - m_bitmap.eraseColor(SK_ColorTRANSPARENT); - rebuild(); - } - - void createRgba(int width, int height) { - ASSERT(!m_surface); - - if (!m_bitmap.tryAllocPixels( - SkImageInfo::MakeN32Premul(width, height, colorSpace()))) - throw base::Exception("Cannot create Skia surface"); - - m_bitmap.eraseColor(SK_ColorTRANSPARENT); - rebuild(); - } - - void flush() { - if (m_canvas) - m_canvas->flush(); - } - - // Surface impl - - void dispose() override { - delete this; - } - - int width() const override { - if (m_surface) - return m_surface->width(); - else - return m_bitmap.width(); - } - - int height() const override { - if (m_surface) - return m_surface->height(); - else - return m_bitmap.height(); - } - - bool isDirectToScreen() const override { - return false; - } - - int getSaveCount() const override { - return m_canvas->getSaveCount(); - } - - gfx::Rect getClipBounds() const override { - SkIRect rc; - if (m_canvas->getDeviceClipBounds(&rc)) - return gfx::Rect(rc.x(), rc.y(), rc.width(), rc.height()); - else - return gfx::Rect(); - } - - void saveClip() override { - m_canvas->save(); - } - - void restoreClip() override { - m_canvas->restore(); - } - - bool clipRect(const gfx::Rect& rc) override { - m_canvas->clipRect(SkRect::Make(to_skia(rc))); - return !m_canvas->isClipEmpty(); - } - - void setDrawMode(DrawMode mode, int param, - const gfx::Color a, - const gfx::Color b) override { - switch (mode) { - case DrawMode::Solid: - m_paint.setBlendMode(SkBlendMode::kSrcOver); - m_paint.setShader(nullptr); - break; - case DrawMode::Xor: - m_paint.setBlendMode(SkBlendMode::kXor); - m_paint.setShader(nullptr); - break; - case DrawMode::Checked: { - m_paint.setBlendMode(SkBlendMode::kSrcOver); - { - SkBitmap bitmap; - if (!bitmap.tryAllocPixels( - SkImageInfo::MakeN32(8, 8, kOpaque_SkAlphaType, colorSpace()))) { - throw base::Exception("Cannot create temporary Skia surface"); - } - - { - SkPMColor A = SkPreMultiplyARGB(gfx::geta(a), gfx::getr(a), gfx::getg(a), gfx::getb(a)); - SkPMColor B = SkPreMultiplyARGB(gfx::geta(b), gfx::getr(b), gfx::getg(b), gfx::getb(b)); - int offset = 7 - (param & 7); - for (int y=0; y<8; y++) - for (int x=0; x<8; x++) - *bitmap.getAddr32(x, y) = (((x+y+offset)&7) < 4 ? B: A); - } - - sk_sp shader( - SkShader::MakeBitmapShader( - bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode)); - m_paint.setShader(shader); - } - break; - } - } - } - - void lock() override { - ASSERT(m_lock >= 0); - if (m_lock++ == 0) { - // m_bitmap is always locked - } - } - - void unlock() override { - ASSERT(m_lock > 0); - if (--m_lock == 0) { - // m_bitmap is always locked - } - } - - void applyScale(int scaleFactor) override { - ASSERT(!m_surface); - - SkBitmap result; - if (!result.tryAllocPixels( - m_bitmap.info().makeWH( - width()*scaleFactor, - height()*scaleFactor))) - throw base::Exception("Cannot create temporary Skia surface to change scale"); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - - SkCanvas canvas(result); - SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, width(), height())); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, result.width(), result.height())); - canvas.drawBitmapRect(m_bitmap, srcRect, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - - swapBitmap(result); - } - - void* nativeHandle() override { - return (void*)this; - } - - void clear() override { - m_canvas->clear(0); - } - - uint8_t* getData(int x, int y) const override { - if (m_bitmap.isNull()) - return nullptr; - else - return (uint8_t*)m_bitmap.getAddr32(x, y); - } - - void getFormat(SurfaceFormatData* formatData) const override { - formatData->format = kRgbaSurfaceFormat; - formatData->bitsPerPixel = 8*m_bitmap.bytesPerPixel(); - - switch (m_bitmap.colorType()) { - case kRGB_565_SkColorType: - formatData->redShift = SK_R16_SHIFT; - formatData->greenShift = SK_G16_SHIFT; - formatData->blueShift = SK_B16_SHIFT; - formatData->alphaShift = 0; - formatData->redMask = SK_R16_MASK; - formatData->greenMask = SK_G16_MASK; - formatData->blueMask = SK_B16_MASK; - formatData->alphaMask = 0; - break; - case kARGB_4444_SkColorType: - formatData->redShift = SK_R4444_SHIFT; - formatData->greenShift = SK_G4444_SHIFT; - formatData->blueShift = SK_B4444_SHIFT; - formatData->alphaShift = SK_A4444_SHIFT; - formatData->redMask = (15 << SK_R4444_SHIFT); - formatData->greenMask = (15 << SK_G4444_SHIFT); - formatData->blueMask = (15 << SK_B4444_SHIFT); - formatData->alphaMask = (15 << SK_A4444_SHIFT); - break; - case kRGBA_8888_SkColorType: - formatData->redShift = SK_RGBA_R32_SHIFT; - formatData->greenShift = SK_RGBA_G32_SHIFT; - formatData->blueShift = SK_RGBA_B32_SHIFT; - formatData->alphaShift = SK_RGBA_A32_SHIFT; - formatData->redMask = (255 << SK_RGBA_R32_SHIFT); - formatData->greenMask = (255 << SK_RGBA_G32_SHIFT); - formatData->blueMask = (255 << SK_RGBA_B32_SHIFT); - formatData->alphaMask = (255 << SK_RGBA_A32_SHIFT); - break; - case kBGRA_8888_SkColorType: - formatData->redShift = SK_BGRA_R32_SHIFT; - formatData->greenShift = SK_BGRA_G32_SHIFT; - formatData->blueShift = SK_BGRA_B32_SHIFT; - formatData->alphaShift = SK_BGRA_A32_SHIFT; - formatData->redMask = (255 << SK_BGRA_R32_SHIFT); - formatData->greenMask = (255 << SK_BGRA_G32_SHIFT); - formatData->blueMask = (255 << SK_BGRA_B32_SHIFT); - formatData->alphaMask = (255 << SK_BGRA_A32_SHIFT); - break; - default: - formatData->redShift = 0; - formatData->greenShift = 0; - formatData->blueShift = 0; - formatData->alphaShift = 0; - formatData->redMask = 0; - formatData->greenMask = 0; - formatData->blueMask = 0; - formatData->alphaMask = 0; - break; - } - } - - gfx::Color getPixel(int x, int y) const override { - SkColor c = 0; - - if (m_surface) { - SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(1, 1, colorSpace()); - uint32_t dstPixels; - if (m_canvas->readPixels(dstInfo, &dstPixels, 4, x, y)) - c = dstPixels; - } - else - c = m_bitmap.getColor(x, y); - - return gfx::rgba( - SkColorGetR(c), - SkColorGetG(c), - SkColorGetB(c), - SkColorGetA(c)); - } - - void putPixel(gfx::Color color, int x, int y) override { - m_paint.setColor(to_skia(color)); - m_canvas->drawPoint(SkIntToScalar(x), SkIntToScalar(y), m_paint); - } - - void drawHLine(gfx::Color color, int x, int y, int w) override { - m_paint.setColor(to_skia(color)); - m_canvas->drawLine( - SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x+w), SkIntToScalar(y), m_paint); - } - - void drawVLine(gfx::Color color, int x, int y, int h) override { - m_paint.setColor(to_skia(color)); - m_canvas->drawLine( - SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x), SkIntToScalar(y+h), m_paint); - } - - void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) override { - m_paint.setColor(to_skia(color)); - m_canvas->drawLine( - SkIntToScalar(a.x), SkIntToScalar(a.y), - SkIntToScalar(b.x), SkIntToScalar(b.y), m_paint); - } - - void drawRect(gfx::Color color, const gfx::Rect& rc) override { - m_paint.setColor(to_skia(color)); - m_paint.setStyle(SkPaint::kStroke_Style); - m_canvas->drawIRect(to_skia(gfx::Rect(rc.x, rc.y, rc.w-1, rc.h-1)), m_paint); - } - - void fillRect(gfx::Color color, const gfx::Rect& rc) override { - m_paint.setColor(to_skia(color)); - m_paint.setStyle(SkPaint::kFill_Style); - m_canvas->drawIRect(to_skia(rc), m_paint); - } - - void blitTo(Surface* _dst, int srcx, int srcy, int dstx, int dsty, int width, int height) const override { - ASSERT(!m_bitmap.empty()); - - auto dst = static_cast(_dst); - - SkIRect srcRect = SkIRect::MakeXYWH(srcx, srcy, width, height); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(dstx, dsty, width, height)); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - - dst->m_canvas->drawBitmapRect(m_bitmap, srcRect, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - } - - void scrollTo(const gfx::Rect& rc, int dx, int dy) override { - int w = width(); - int h = height(); - gfx::Clip clip(rc.x+dx, rc.y+dy, rc); - if (!clip.clip(w, h, w, h)) - return; - - if (m_surface) { - SurfaceLock lock(this); - blitTo(this, clip.src.x, clip.src.y, clip.dst.x, clip.dst.y, clip.size.w, clip.size.h); - return; - } - - int bytesPerPixel = m_bitmap.bytesPerPixel(); - int rowBytes = (int)m_bitmap.rowBytes(); - int rowDelta; - - if (dy > 0) { - clip.src.y += clip.size.h-1; - clip.dst.y += clip.size.h-1; - rowDelta = -rowBytes; - } - else - rowDelta = rowBytes; - - char* dst = (char*)m_bitmap.getPixels(); - const char* src = dst; - dst += rowBytes*clip.dst.y + bytesPerPixel*clip.dst.x; - src += rowBytes*clip.src.y + bytesPerPixel*clip.src.x; - w = bytesPerPixel*clip.size.w; - h = clip.size.h; - - while (--h >= 0) { - memmove(dst, src, w); - dst += rowDelta; - src += rowDelta; - } - - m_bitmap.notifyPixelsChanged(); - } - - void drawSurface(const Surface* src, int dstx, int dsty) override { - gfx::Clip clip(dstx, dsty, 0, 0, - ((SkiaSurface*)src)->width(), - ((SkiaSurface*)src)->height()); - - if (!clip.clip(width(), height(), clip.size.w, clip.size.h)) - return; - - SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h)); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(clip.dst.x, clip.dst.y, clip.size.w, clip.size.h)); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - - m_canvas->drawBitmapRect( - ((SkiaSurface*)src)->m_bitmap, srcRect, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - } - - void drawRgbaSurface(const Surface* src, int dstx, int dsty) override { - gfx::Clip clip(dstx, dsty, 0, 0, - ((SkiaSurface*)src)->width(), - ((SkiaSurface*)src)->height()); - - if (!clip.clip(width(), height(), clip.size.w, clip.size.h)) - return; - - SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h)); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(clip.dst.x, clip.dst.y, clip.size.w, clip.size.h)); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrcOver); - - m_canvas->drawBitmapRect( - ((SkiaSurface*)src)->m_bitmap, srcRect, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - } - - void drawRgbaSurface(const Surface* src, int srcx, int srcy, int dstx, int dsty, int w, int h) override { - gfx::Clip clip(dstx, dsty, srcx, srcy, w, h); - if (!clip.clip(width(), height(), src->width(), src->height())) - return; - - SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h)); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(clip.dst.x, clip.dst.y, clip.size.w, clip.size.h)); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrcOver); - - m_canvas->drawBitmapRect( - ((SkiaSurface*)src)->m_bitmap, srcRect, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - } - - void drawRgbaSurface(const Surface* src, const gfx::Rect& srcRect, const gfx::Rect& dstRect) override { - SkRect srcRect2 = SkRect::Make(SkIRect::MakeXYWH(srcRect.x, srcRect.y, srcRect.w, srcRect.h)); - SkRect dstRect2 = SkRect::Make(SkIRect::MakeXYWH(dstRect.x, dstRect.y, dstRect.w, dstRect.h)); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrcOver); - paint.setFilterQuality(srcRect.w < dstRect.w || - srcRect.h < dstRect.h ? kNone_SkFilterQuality: - kHigh_SkFilterQuality); - - m_canvas->drawBitmapRect( - ((SkiaSurface*)src)->m_bitmap, srcRect2, dstRect2, &paint, - SkCanvas::kStrict_SrcRectConstraint); - } - - void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override { - gfx::Clip clip(clipbase); - if (!clip.clip(width(), height(), src->width(), src->height())) - return; - - SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(clip.src.x, clip.src.y, clip.size.w, clip.size.h)); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(clip.dst.x, clip.dst.y, clip.size.w, clip.size.h)); - - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrcOver); - - if (gfx::geta(bg) > 0) { - SkPaint paint; - paint.setColor(to_skia(bg)); - paint.setStyle(SkPaint::kFill_Style); - m_canvas->drawRect(dstRect, paint); - } - - sk_sp colorFilter( - SkColorFilter::MakeModeFilter(to_skia(fg), SkBlendMode::kSrcIn)); - paint.setColorFilter(colorFilter); - - m_canvas->drawBitmapRect( - ((SkiaSurface*)src)->m_bitmap, - srcRect, dstRect, &paint); - } - - SkBitmap& bitmap() { - return m_bitmap; - } - - void swapBitmap(SkBitmap& other) { - ASSERT(!m_surface); - - m_bitmap.swap(other); - rebuild(); - } - - static Surface* loadSurface(const char* filename); - -private: - void rebuild() { - ASSERT(!m_surface); - - delete m_canvas; - m_canvas = new SkCanvas(m_bitmap); - } - - static sk_sp colorSpace(); - - SkBitmap m_bitmap; - sk_sp m_surface; - SkCanvas* m_canvas; - SkPaint m_paint; - int m_lock; - static sk_sp m_colorSpace; - -}; - -} // namespace os - -#endif diff --git a/src/os/skia/skia_system.h b/src/os/skia/skia_system.h deleted file mode 100644 index b6c4da896..000000000 --- a/src/os/skia/skia_system.h +++ /dev/null @@ -1,158 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_SYSTEM_INCLUDED -#define OS_SKIA_SKIA_SYSTEM_INCLUDED -#pragma once - -#include "base/base.h" - -#include "os/common/system.h" -#include "os/skia/skia_display.h" -#include "os/skia/skia_surface.h" - -#ifdef _WIN32 - #include "os/win/event_queue.h" - #include "os/win/system.h" - #define SkiaSystemBase WindowSystem -#elif __APPLE__ - #include "os/osx/app.h" - #include "os/osx/event_queue.h" - #include "os/osx/system.h" - #define SkiaSystemBase OSXSystem -#else - #include "os/x11/event_queue.h" - #include "os/x11/system.h" - #define SkiaSystemBase X11System -#endif - -#include "SkGraphics.h" - -namespace os { - -EventQueueImpl g_queue; - -class SkiaSystem : public SkiaSystemBase { -public: - SkiaSystem() - : m_defaultDisplay(nullptr) - , m_gpuAcceleration(false) { - SkGraphics::Init(); - } - - ~SkiaSystem() { - SkGraphics::Term(); - } - - void dispose() override { - delete this; - } - - void activateApp() override { -#if __APPLE__ - OSXApp::instance()->activateApp(); -#endif - } - - void finishLaunching() override { -#if __APPLE__ - // Start processing NSApplicationDelegate events. (E.g. after - // calling this we'll receive application:openFiles: and we'll - // generate DropFiles events.) events - OSXApp::instance()->finishLaunching(); -#endif - } - - Capabilities capabilities() const override { - return Capabilities( - int(Capabilities::MultipleDisplays) | - int(Capabilities::CanResizeDisplay) | - int(Capabilities::DisplayScale) | - int(Capabilities::CustomNativeMouseCursor) - // TODO enable this when the GPU support is ready -#if 0 // SK_SUPPORT_GPU - | int(Capabilities::GpuAccelerationSwitch) -#endif - ); - } - - EventQueue* eventQueue() override { - return &g_queue; - } - - bool gpuAcceleration() const override { - return m_gpuAcceleration; - } - - void setGpuAcceleration(bool state) override { - m_gpuAcceleration = state; - } - - gfx::Size defaultNewDisplaySize() override { - gfx::Size sz; -#ifdef _WIN32 - sz.w = GetSystemMetrics(SM_CXMAXIMIZED); - sz.h = GetSystemMetrics(SM_CYMAXIMIZED); - sz.w -= GetSystemMetrics(SM_CXSIZEFRAME)*4; - sz.h -= GetSystemMetrics(SM_CYSIZEFRAME)*4; - sz.w = MAX(0, sz.w); - sz.h = MAX(0, sz.h); -#endif - return sz; - } - - Display* defaultDisplay() override { - return m_defaultDisplay; - } - - Display* createDisplay(int width, int height, int scale) override { - SkiaDisplay* display = new SkiaDisplay(width, height, scale); - if (!m_defaultDisplay) - m_defaultDisplay = display; - return display; - } - - Surface* createSurface(int width, int height) override { - SkiaSurface* sur = new SkiaSurface; - sur->create(width, height); - return sur; - } - - Surface* createRgbaSurface(int width, int height) override { - SkiaSurface* sur = new SkiaSurface; - sur->createRgba(width, height); - return sur; - } - - Surface* loadSurface(const char* filename) override { - return SkiaSurface::loadSurface(filename); - } - - Surface* loadRgbaSurface(const char* filename) override { - return loadSurface(filename); - } - - void setTranslateDeadKeys(bool state) override { - if (m_defaultDisplay) - m_defaultDisplay->setTranslateDeadKeys(state); - -#ifdef _WIN32 - g_queue.setTranslateDeadKeys(state); -#endif - } - -private: - SkiaDisplay* m_defaultDisplay; - bool m_gpuAcceleration; -}; - -EventQueue* EventQueue::instance() { - return &g_queue; -} - -} // namespace os - -#endif diff --git a/src/os/skia/skia_window.h b/src/os/skia/skia_window.h deleted file mode 100644 index 17270a8c9..000000000 --- a/src/os/skia/skia_window.h +++ /dev/null @@ -1,19 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_WINDOW_INCLUDED -#define OS_SKIA_SKIA_WINDOW_INCLUDED -#pragma once - -#ifdef _WIN32 - #include "os/skia/skia_window_win.h" -#elif __APPLE__ - #include "os/skia/skia_window_osx.h" -#else - #include "os/skia/skia_window_x11.h" -#endif - -#endif diff --git a/src/os/skia/skia_window_osx.h b/src/os/skia/skia_window_osx.h deleted file mode 100644 index 995684ca1..000000000 --- a/src/os/skia/skia_window_osx.h +++ /dev/null @@ -1,63 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_WINDOW_OSX_INCLUDED -#define OS_SKIA_SKIA_WINDOW_OSX_INCLUDED -#pragma once - -#include "base/disable_copying.h" -#include "os/native_cursor.h" - -#include - -namespace os { - -class EventQueue; -class SkiaDisplay; -class Surface; - -class SkiaWindow { -public: - enum class Backend { NONE, GL }; - - SkiaWindow(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale); - ~SkiaWindow(); - - int scale() const; - void setScale(int scale); - void setVisible(bool visible); - void maximize(); - bool isMaximized() const; - bool isMinimized() const; - gfx::Size clientSize() const; - gfx::Size restoredSize() const; - void setTitle(const std::string& title); - void captureMouse(); - void releaseMouse(); - void setMousePosition(const gfx::Point& position); - bool setNativeMouseCursor(NativeCursor cursor); - bool setNativeMouseCursor(const Surface* surface, - const gfx::Point& focus, - const int scale); - void updateWindow(const gfx::Rect& bounds); - std::string getLayout() { return ""; } - void setLayout(const std::string& layout) { } - void setTranslateDeadKeys(bool state); - void* handle(); - -private: - void destroyImpl(); - - class Impl; - Impl* m_impl; - - DISABLE_COPYING(SkiaWindow); -}; - -} // namespace os - -#endif diff --git a/src/os/skia/skia_window_osx.mm b/src/os/skia/skia_window_osx.mm deleted file mode 100644 index 94fab4ae6..000000000 --- a/src/os/skia/skia_window_osx.mm +++ /dev/null @@ -1,512 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -//#define DEBUG_UPDATE_RECTS - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/skia/skia_window_osx.h" - -#include "base/log.h" -#include "gfx/size.h" -#include "os/event.h" -#include "os/event_queue.h" -#include "os/osx/view.h" -#include "os/osx/window.h" -#include "os/skia/skia_display.h" -#include "os/skia/skia_surface.h" -#include "os/system.h" - -#include "mac/SkCGUtils.h" - -#if SK_SUPPORT_GPU - - #include "GrBackendSurface.h" - #include "GrContext.h" - #include "gl/GrGLDefines.h" - #include "gl/GrGLInterface.h" - #include "os/gl/gl_context_cgl.h" - #include "os/skia/skia_surface.h" - -#endif - -#include - -namespace os { - -class SkiaWindow::Impl : public OSXWindowImpl { -public: - Impl(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale) - : m_display(display) - , m_backend(Backend::NONE) -#if SK_SUPPORT_GPU - , m_nsGL(nil) - , m_skSurface(nullptr) -#endif - { - m_closing = false; - m_window = [[OSXWindow alloc] initWithImpl:this - width:width - height:height - scale:scale]; - } - - ~Impl() { -#if SK_SUPPORT_GPU - if (m_backend == Backend::GL) - detachGL(); -#endif - } - - gfx::Size clientSize() const { - return [m_window clientSize]; - } - - gfx::Size restoredSize() const { - return [m_window restoredSize]; - } - - int scale() const { - return [m_window scale]; - } - - void setScale(int scale) { - [m_window setScale:scale]; - } - - void setVisible(bool visible) { - if (visible) { - // Make the first OSXWindow as the main one. - [m_window makeKeyAndOrderFront:nil]; - - // The main window can be changed only when the NSWindow - // is visible (i.e. when NSWindow::canBecomeMainWindow - // returns YES). - [m_window makeMainWindow]; - } - else { - [m_window close]; - } - } - - void setTitle(const std::string& title) { - [m_window setTitle:[NSString stringWithUTF8String:title.c_str()]]; - } - - void setMousePosition(const gfx::Point& position) { - [m_window setMousePosition:position]; - } - - bool setNativeMouseCursor(NativeCursor cursor) { - return ([m_window setNativeMouseCursor:cursor] ? true: false); - } - - bool setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale) { - return ([m_window setNativeMouseCursor:surface - focus:focus - scale:scale] ? true: false); - } - - void updateWindow(const gfx::Rect& bounds) { - @autoreleasepool { - int scale = this->scale(); - NSView* view = m_window.contentView; - [view setNeedsDisplayInRect: - NSMakeRect(bounds.x*scale, - view.frame.size.height - (bounds.y+bounds.h)*scale, - bounds.w*scale, - bounds.h*scale)]; - [view displayIfNeeded]; - } - } - - void setTranslateDeadKeys(bool state) { - OSXView* view = (OSXView*)m_window.contentView; - [view setTranslateDeadKeys:(state ? YES: NO)]; - } - - void* handle() { - return (__bridge void*)m_window; - } - - // OSXWindowImpl impl - - void onClose() override { - m_closing = true; - } - - void onResize(const gfx::Size& size) override { - bool gpu = os::instance()->gpuAcceleration(); - (void)gpu; - -#if SK_SUPPORT_GPU - if (gpu && attachGL()) { - m_backend = Backend::GL; - } - else -#endif - { -#if SK_SUPPORT_GPU - detachGL(); -#endif - m_backend = Backend::NONE; - } - -#if SK_SUPPORT_GPU - if (m_glCtx && m_display->isInitialized()) - createRenderTarget(size); -#endif - - m_display->resize(size); - } - - void onDrawRect(const gfx::Rect& rect) override { - switch (m_backend) { - - case Backend::NONE: - paintGC(rect); - break; - -#if SK_SUPPORT_GPU - case Backend::GL: - // TODO - if (m_nsGL) - [m_nsGL flushBuffer]; - break; -#endif - } - } - - void onWindowChanged() override { -#if SK_SUPPORT_GPU - if (m_nsGL) - [m_nsGL setView:[m_window contentView]]; -#endif - } - -private: -#if SK_SUPPORT_GPU - bool attachGL() { - if (!m_glCtx) { - try { - std::unique_ptr ctx(new GLContextCGL); - if (!ctx->createGLContext()) - throw std::runtime_error("Cannot create CGL context"); - - m_glInterfaces.reset(GrGLCreateNativeInterface()); - if (!m_glInterfaces || !m_glInterfaces->validate()) { - LOG(ERROR) << "OS: Cannot create GL interfaces\n"; - detachGL(); - return false; - } - - m_glCtx.reset(ctx.get()); - ctx.release(); - - m_grCtx.reset(GrContext::Create(kOpenGL_GrBackend, - (GrBackendContext)m_glInterfaces.get())); - - m_nsGL = [[NSOpenGLContext alloc] - initWithCGLContextObj:static_cast(m_glCtx.get())->cglContext()]; - - [m_nsGL setView:m_window.contentView]; - LOG("OS: Using CGL backend\n"); - } - catch (const std::exception& ex) { - LOG(ERROR) << "OS: Cannot create GL context: " << ex.what() << "\n"; - detachGL(); - return false; - } - } - return true; - } - - void detachGL() { - if (m_nsGL) - m_nsGL = nil; - - m_skSurface.reset(nullptr); - m_skSurfaceDirect.reset(nullptr); - m_grCtx.reset(nullptr); - m_glCtx.reset(nullptr); - } - - void createRenderTarget(const gfx::Size& size) { - const int scale = this->scale(); - m_lastSize = size; - - GrGLint buffer; - m_glInterfaces->fFunctions.fGetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer); - GrGLFramebufferInfo info; - info.fFBOID = (GrGLuint)buffer; - - GrBackendRenderTarget - target(size.w, size.h, - m_glCtx->getSampleCount(), - m_glCtx->getStencilBits(), - kSkia8888_GrPixelConfig, - info); - - SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); - - m_skSurface.reset(nullptr); // set m_skSurface comparing with the old m_skSurfaceDirect - m_skSurfaceDirect = SkSurface::MakeFromBackendRenderTarget( - m_grCtx.get(), target, - kBottomLeft_GrSurfaceOrigin, - nullptr, &props); - - if (scale == 1 && m_skSurfaceDirect) { - LOG("OS: Using GL direct surface\n"); - m_skSurface = m_skSurfaceDirect; - } - else { - LOG("OS: Using double buffering\n"); - m_skSurface = - SkSurface::MakeRenderTarget( - m_grCtx.get(), - SkBudgeted::kYes, - SkImageInfo::Make(MAX(1, size.w / scale), - MAX(1, size.h / scale), - kN32_SkColorType, kOpaque_SkAlphaType); - m_glCtx->getSampleCount(), - nullptr); - } - - if (!m_skSurface) - throw std::runtime_error("Error creating surface for main display"); - - m_display->setSkiaSurface(new SkiaSurface(m_skSurface)); - - if (m_nsGL) - [m_nsGL update]; - } - -#endif - - void paintGC(const gfx::Rect& rect) { - if (!m_display->isInitialized()) - return; - - if (rect.isEmpty()) - return; - - NSRect viewBounds = m_window.contentView.bounds; - int scale = this->scale(); - - SkiaSurface* surface = static_cast(m_display->getSurface()); - const SkBitmap& origBitmap = surface->bitmap(); - - SkBitmap bitmap; - if (scale == 1) { - // Create a subset to draw on the view - if (!origBitmap.extractSubset( - &bitmap, SkIRect::MakeXYWH(rect.x, - (viewBounds.size.height-(rect.y+rect.h)), - rect.w, - rect.h))) - return; - } - else { - // Create a bitmap to draw the original one scaled. This is - // faster than doing the scaling directly in - // CGContextDrawImage(). This avoid a slow path where the - // internal macOS argb32_image_mark_RGB32() function is called - // (which is a performance hit). - if (!bitmap.tryAllocN32Pixels(rect.w, rect.h, true)) - return; - - SkCanvas canvas(bitmap); - canvas.drawBitmapRect(origBitmap, - SkIRect::MakeXYWH(rect.x/scale, - (viewBounds.size.height-(rect.y+rect.h))/scale, - rect.w/scale, - rect.h/scale), - SkRect::MakeXYWH(0, 0, rect.w, rect.h), - nullptr); - } - - @autoreleasepool { - NSGraphicsContext* gc = [NSGraphicsContext currentContext]; - CGContextRef cg = (CGContextRef)[gc graphicsPort]; - CGColorSpaceRef colorSpace = CGDisplayCopyColorSpace(CGMainDisplayID()); - CGImageRef img = SkCreateCGImageRefWithColorspace(bitmap, colorSpace); - if (img) { - CGRect r = CGRectMake(viewBounds.origin.x+rect.x, - viewBounds.origin.y+rect.y, - rect.w, rect.h); - - CGContextSaveGState(cg); - CGContextSetInterpolationQuality(cg, kCGInterpolationNone); - CGContextDrawImage(cg, r, img); -#ifdef DEBUG_UPDATE_RECTS - { - static int i = 0; - i = (i+1) % 8; - CGContextSetRGBStrokeColor(cg, - (i & 1 ? 1.0f: 0.0f), - (i & 2 ? 1.0f: 0.0f), - (i & 4 ? 1.0f: 0.0f), 1.0f); - CGContextStrokeRectWithWidth(cg, r, 2.0f); - } -#endif - CGContextRestoreGState(cg); - CGImageRelease(img); - } - CGColorSpaceRelease(colorSpace); - } - } - - SkiaDisplay* m_display; - Backend m_backend; - bool m_closing; - OSXWindow* m_window; -#if SK_SUPPORT_GPU - std::unique_ptr m_glCtx; - sk_sp m_glInterfaces; - NSOpenGLContext* m_nsGL; - sk_sp m_grCtx; - sk_sp m_skSurfaceDirect; - sk_sp m_skSurface; - gfx::Size m_lastSize; -#endif -}; - -SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale) - : m_impl(new Impl(queue, display, - width, height, scale)) -{ -} - -SkiaWindow::~SkiaWindow() -{ - destroyImpl(); -} - -void SkiaWindow::destroyImpl() -{ - delete m_impl; - m_impl = nullptr; -} - -int SkiaWindow::scale() const -{ - if (m_impl) - return m_impl->scale(); - else - return 1; -} - -void SkiaWindow::setScale(int scale) -{ - if (m_impl) - m_impl->setScale(scale); -} - -void SkiaWindow::setVisible(bool visible) -{ - if (!m_impl) - return; - - m_impl->setVisible(visible); -} - -void SkiaWindow::maximize() -{ -} - -bool SkiaWindow::isMaximized() const -{ - return false; -} - -bool SkiaWindow::isMinimized() const -{ - return false; -} - -gfx::Size SkiaWindow::clientSize() const -{ - if (!m_impl) - return gfx::Size(0, 0); - - return m_impl->clientSize(); -} - -gfx::Size SkiaWindow::restoredSize() const -{ - if (!m_impl) - return gfx::Size(0, 0); - - return m_impl->restoredSize(); -} - -void SkiaWindow::setTitle(const std::string& title) -{ - if (!m_impl) - return; - - m_impl->setTitle(title); -} - -void SkiaWindow::captureMouse() -{ -} - -void SkiaWindow::releaseMouse() -{ -} - -void SkiaWindow::setMousePosition(const gfx::Point& position) -{ - if (m_impl) - m_impl->setMousePosition(position); -} - -bool SkiaWindow::setNativeMouseCursor(NativeCursor cursor) -{ - if (m_impl) - return m_impl->setNativeMouseCursor(cursor); - else - return false; -} - -bool SkiaWindow::setNativeMouseCursor(const Surface* surface, - const gfx::Point& focus, - const int scale) -{ - if (m_impl) - return m_impl->setNativeMouseCursor(surface, focus, scale); - else - return false; -} - -void SkiaWindow::updateWindow(const gfx::Rect& bounds) -{ - if (m_impl) - m_impl->updateWindow(bounds); -} - -void SkiaWindow::setTranslateDeadKeys(bool state) -{ - if (m_impl) - m_impl->setTranslateDeadKeys(state); -} - -void* SkiaWindow::handle() -{ - if (m_impl) - return (void*)m_impl->handle(); - else - return nullptr; -} - -} // namespace os diff --git a/src/os/skia/skia_window_win.cpp b/src/os/skia/skia_window_win.cpp deleted file mode 100644 index 10e3e1b9e..000000000 --- a/src/os/skia/skia_window_win.cpp +++ /dev/null @@ -1,358 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/skia/skia_window_win.h" - -#include "base/log.h" -#include "os/event.h" -#include "os/event_queue.h" -#include "os/skia/skia_display.h" -#include "os/system.h" - -#undef max // To avoid include/private/SkPathRef.h(451): error C2589: '(': illegal token on right side of '::' - -#if SK_SUPPORT_GPU - - #include "GrBackendSurface.h" - #include "GrContext.h" - #include "gl/GrGLDefines.h" - #include "os/gl/gl_context_wgl.h" - #if SK_ANGLE - #include "os/gl/gl_context_egl.h" - #include "gl/GrGLAssembleInterface.h" - #endif - -#endif - -#include -#include "os/win/window_dde.h" - -#include - -namespace os { - -SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale) - : WinWindow(width, height, scale) - , m_queue(queue) - , m_display(display) - , m_backend(Backend::NONE) -#if SK_SUPPORT_GPU - , m_skSurface(nullptr) - , m_sampleCount(0) - , m_stencilBits(0) -#endif -{ -} - -SkiaWindow::~SkiaWindow() -{ - switch (m_backend) { - - case Backend::NONE: - // Do nothing - break; - -#if SK_SUPPORT_GPU - - case Backend::GL: - case Backend::ANGLE: - detachGL(); - break; - -#endif // SK_SUPPORT_GPU - } -} - -void SkiaWindow::onQueueEvent(Event& ev) -{ - ev.setDisplay(m_display); - m_queue->queueEvent(ev); -} - -void SkiaWindow::onPaint(HDC hdc) -{ - switch (m_backend) { - - case Backend::NONE: - paintHDC(hdc); - break; - -#if SK_SUPPORT_GPU - - case Backend::GL: - case Backend::ANGLE: - // Flush operations to the SkCanvas - { - SkiaSurface* surface = static_cast(m_display->getSurface()); - surface->flush(); - } - - // If we are drawing inside an off-screen texture, here we have - // to blit that texture into the main framebuffer. - if (m_skSurfaceDirect != m_skSurface) { -#if 0 // TODO - GrBackendObject texID = m_skSurface->getTextureHandle( - SkSurface::kFlushRead_BackendHandleAccess); - - GrBackendTextureDesc texDesc; - texDesc.fFlags = kNone_GrBackendTextureFlag; - texDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; - texDesc.fWidth = m_lastSize.w / scale(); - texDesc.fHeight = m_lastSize.h / scale(); - texDesc.fConfig = kSkia8888_GrPixelConfig; - texDesc.fSampleCnt = m_sampleCount; - texDesc.fTextureHandle = texID; - sk_sp image(SkImage::MakeFromTexture(m_grCtx.get(), texDesc)); - - SkRect dstRect(SkRect::MakeWH(SkIntToScalar(m_lastSize.w), - SkIntToScalar(m_lastSize.h))); - - SkPaint paint; - m_skSurfaceDirect->getCanvas()->drawImageRect( - image, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - - m_skSurfaceDirect->getCanvas()->flush(); -#endif - } - - // Flush GL context - m_glInterfaces->fFunctions.fFlush(); - m_glCtx->swapBuffers(); - break; - -#endif // SK_SUPPORT_GPU - } -} - -void SkiaWindow::paintHDC(HDC hdc) -{ - SkiaSurface* surface = static_cast(m_display->getSurface()); - const SkBitmap& bitmap = surface->bitmap(); - - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = bitmap.width(); - bmi.bmiHeader.biHeight = -bitmap.height(); - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = 0; - - ASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes()); - - int ret = StretchDIBits(hdc, - 0, 0, bitmap.width()*scale(), bitmap.height()*scale(), - 0, 0, bitmap.width(), bitmap.height(), - bitmap.getPixels(), - &bmi, DIB_RGB_COLORS, SRCCOPY); - (void)ret; -} - -#if SK_SUPPORT_GPU - -#if SK_ANGLE - -struct ANGLEAssembleContext { - ANGLEAssembleContext() { - fEGL = GetModuleHandle(L"libEGL.dll"); - fGL = GetModuleHandle(L"libGLESv2.dll"); - } - - bool isValid() const { return SkToBool(fEGL) && SkToBool(fGL); } - - HMODULE fEGL; - HMODULE fGL; -}; - -static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) { - const ANGLEAssembleContext& context = *reinterpret_cast(ctx); - GrGLFuncPtr proc = (GrGLFuncPtr) GetProcAddress(context.fGL, name); - if (proc) { - return proc; - } - proc = (GrGLFuncPtr) GetProcAddress(context.fEGL, name); - if (proc) { - return proc; - } - return eglGetProcAddress(name); -} - -static const GrGLInterface* get_angle_gl_interface() { - ANGLEAssembleContext context; - if (!context.isValid()) { - return nullptr; - } - return GrGLAssembleGLESInterface(&context, angle_get_gl_proc); -} - -bool SkiaWindow::attachANGLE() -{ - if (!m_glCtx) { - try { - std::unique_ptr ctx(new GLContextEGL(handle())); - if (!ctx->createGLContext()) - throw std::runtime_error("Cannot create EGL context"); - - m_glInterfaces.reset(get_angle_gl_interface()); - if (!m_glInterfaces || !m_glInterfaces->validate()) - throw std::runtime_error("Cannot create EGL interfaces\n"); - - m_stencilBits = ctx->getStencilBits(); - m_sampleCount = ctx->getSampleCount(); - - m_glCtx.reset(ctx.release()); - m_grCtx.reset( - GrContext::Create(kOpenGL_GrBackend, - (GrBackendContext)m_glInterfaces.get())); - - LOG("OS: Using EGL backend\n"); - } - catch (const std::exception& ex) { - LOG(ERROR) << "OS: Error initializing EGL backend: " << ex.what() << "\n"; - detachGL(); - } - } - - if (m_glCtx) - return true; - else - return false; -} - -#endif // SK_ANGLE - -bool SkiaWindow::attachGL() -{ - if (!m_glCtx) { - try { - std::unique_ptr ctx(new GLContextWGL(handle())); - if (!ctx->createGLContext()) - throw std::runtime_error("Cannot create WGL context\n"); - - m_glInterfaces.reset(GrGLCreateNativeInterface()); - if (!m_glInterfaces || !m_glInterfaces->validate()) - throw std::runtime_error("Cannot create WGL interfaces\n"); - - m_stencilBits = ctx->getStencilBits(); - m_sampleCount = ctx->getSampleCount(); - - m_glCtx.reset(ctx.release()); - m_grCtx.reset( - GrContext::Create(kOpenGL_GrBackend, - (GrBackendContext)m_glInterfaces.get())); - - LOG("OS: Using WGL backend\n"); - } - catch (const std::exception& ex) { - LOG(ERROR) << "OS: Error initializing WGL backend: " << ex.what() << "\n"; - detachGL(); - } - } - - if (m_glCtx) - return true; - else - return false; -} - -void SkiaWindow::detachGL() -{ - if (m_glCtx && m_display) - m_display->resetSkiaSurface(); - - m_skSurface.reset(nullptr); - m_skSurfaceDirect.reset(nullptr); - m_grCtx.reset(nullptr); - m_glCtx.reset(nullptr); -} - -void SkiaWindow::createRenderTarget(const gfx::Size& size) -{ - int scale = m_display->scale(); - m_lastSize = size; - - GrGLint buffer; - m_glInterfaces->fFunctions.fGetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer); - GrGLFramebufferInfo info; - info.fFBOID = (GrGLuint) buffer; - - GrBackendRenderTarget - target(size.w, size.h, - m_sampleCount, - m_stencilBits, - kSkia8888_GrPixelConfig, - info); - - SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); - - m_skSurface.reset(nullptr); // set m_skSurface comparing with the old m_skSurfaceDirect - m_skSurfaceDirect = SkSurface::MakeFromBackendRenderTarget( - m_grCtx.get(), target, - kBottomLeft_GrSurfaceOrigin, - nullptr, &props); - - if (scale == 1) { - m_skSurface = m_skSurfaceDirect; - } - else { - m_skSurface = - SkSurface::MakeRenderTarget( - m_grCtx.get(), - SkBudgeted::kYes, - SkImageInfo::MakeN32Premul(MAX(1, size.w / scale), - MAX(1, size.h / scale)), - m_sampleCount, - nullptr); - } - - if (!m_skSurface) - throw std::runtime_error("Error creating surface for main display"); - - m_display->setSkiaSurface(new SkiaSurface(m_skSurface)); -} - -#endif // SK_SUPPORT_GPU - -void SkiaWindow::onResize(const gfx::Size& size) -{ - bool gpu = instance()->gpuAcceleration(); - (void)gpu; - -#if SK_SUPPORT_GPU -#if SK_ANGLE - if (gpu && attachANGLE()) { - m_backend = Backend::ANGLE; - } - else -#endif // SK_ANGLE - if (gpu && attachGL()) { - m_backend = Backend::GL; - } - else -#endif // SK_SUPPORT_GPU - { -#if SK_SUPPORT_GPU - detachGL(); -#endif - m_backend = Backend::NONE; - } - -#if SK_SUPPORT_GPU - if (m_glCtx) - createRenderTarget(size); -#endif - - m_display->resize(size); -} - -} // namespace os diff --git a/src/os/skia/skia_window_win.h b/src/os/skia/skia_window_win.h deleted file mode 100644 index 90e348426..000000000 --- a/src/os/skia/skia_window_win.h +++ /dev/null @@ -1,67 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_WINDOW_WIN_INCLUDED -#define OS_SKIA_SKIA_WINDOW_WIN_INCLUDED -#pragma once - -#include "base/disable_copying.h" -#include "os/skia/skia_surface.h" -#include "os/win/window.h" - -#if SK_SUPPORT_GPU - #include "gl/GrGLInterface.h" - #include "os/gl/gl_context.h" -#endif - -namespace os { - -class EventQueue; -class SkiaDisplay; - -class SkiaWindow : public WinWindow { -public: - enum class Backend { NONE, GL, ANGLE }; - - SkiaWindow(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale); - ~SkiaWindow(); - -private: - void onQueueEvent(Event& ev) override; - void onPaint(HDC hdc) override; - void onResize(const gfx::Size& sz) override; - void paintHDC(HDC dc); - -#if SK_SUPPORT_GPU -#if SK_ANGLE - bool attachANGLE(); -#endif // SK_ANGLE - bool attachGL(); - void detachGL(); - void createRenderTarget(const gfx::Size& size); -#endif // SK_SUPPORT_GPU - - EventQueue* m_queue; - SkiaDisplay* m_display; - Backend m_backend; -#if SK_SUPPORT_GPU - std::unique_ptr m_glCtx; - sk_sp m_glInterfaces; - sk_sp m_grCtx; - sk_sp m_skSurfaceDirect; - sk_sp m_skSurface; - int m_sampleCount; - int m_stencilBits; - gfx::Size m_lastSize; -#endif // SK_SUPPORT_GPU - - DISABLE_COPYING(SkiaWindow); -}; - -} // namespace os - -#endif diff --git a/src/os/skia/skia_window_x11.cpp b/src/os/skia/skia_window_x11.cpp deleted file mode 100644 index a424fc5da..000000000 --- a/src/os/skia/skia_window_x11.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/skia/skia_window_x11.h" - -#include "gfx/size.h" -#include "os/event.h" -#include "os/event_queue.h" -#include "os/skia/skia_display.h" -#include "os/skia/skia_surface.h" -#include "os/x11/x11.h" - -#include "SkBitmap.h" - -namespace os { - -namespace { - -bool convert_skia_bitmap_to_ximage(const SkBitmap& bitmap, XImage& image) -{ - memset(&image, 0, sizeof(image)); - int bpp = 8*bitmap.bytesPerPixel(); - image.width = bitmap.width(); - image.height = bitmap.height(); - image.format = ZPixmap; - image.data = (char*)bitmap.getPixels(); - image.byte_order = LSBFirst; - image.bitmap_unit = bpp; - image.bitmap_bit_order = LSBFirst; - image.bitmap_pad = bpp; - image.depth = 24; - image.bytes_per_line = bitmap.rowBytes() - 4*bitmap.width(); - image.bits_per_pixel = bpp; - - bool result = XInitImage(&image); - - return result; -} - -} // anonymous namespace - -SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale) - : X11Window(X11::instance()->display(), width, height, scale) - , m_queue(queue) - , m_display(display) -{ -} - -SkiaWindow::~SkiaWindow() -{ -} - -void SkiaWindow::setVisible(bool visible) -{ - // TODO -} - -void SkiaWindow::maximize() -{ - // TODO -} - -bool SkiaWindow::isMaximized() const -{ - return false; -} - -bool SkiaWindow::isMinimized() const -{ - return false; -} - -void SkiaWindow::queueEvent(Event& ev) -{ - ev.setDisplay(m_display); - m_queue->queueEvent(ev); -} - -void SkiaWindow::paintGC(const gfx::Rect& rc) -{ - SkiaSurface* surface = static_cast(m_display->getSurface()); - const SkBitmap& bitmap = surface->bitmap(); - - int scale = this->scale(); - if (scale == 1) { - XImage image; - if (convert_skia_bitmap_to_ximage(bitmap, image)) { - XPutImage( - x11display(), handle(), gc(), &image, - rc.x, rc.y, - rc.x, rc.y, - rc.w, rc.h); - } - } - else { - SkBitmap scaled; - if (scaled.tryAllocPixels( - SkImageInfo::Make(rc.w, rc.h, - bitmap.info().colorType(), - bitmap.info().alphaType()))) { - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - - SkCanvas canvas(scaled); - SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(rc.x/scale, rc.y/scale, rc.w/scale, rc.h/scale)); - SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, rc.w, rc.h)); - canvas.drawBitmapRect(bitmap, srcRect, dstRect, &paint, - SkCanvas::kStrict_SrcRectConstraint); - - XImage image; - if (convert_skia_bitmap_to_ximage(scaled, image)) { - XPutImage( - x11display(), handle(), gc(), &image, - 0, 0, - rc.x, rc.y, - rc.w, rc.h); - } - } - } -} - -void SkiaWindow::resizeDisplay(const gfx::Size& sz) -{ - m_display->resize(sz); - updateWindow(gfx::Rect(sz / scale())); -} - -} // namespace os diff --git a/src/os/skia/skia_window_x11.h b/src/os/skia/skia_window_x11.h deleted file mode 100644 index d404a337b..000000000 --- a/src/os/skia/skia_window_x11.h +++ /dev/null @@ -1,52 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SKIA_SKIA_WINDOW_X11_INCLUDED -#define OS_SKIA_SKIA_WINDOW_X11_INCLUDED -#pragma once - -#include "base/disable_copying.h" -#include "gfx/size.h" -#include "os/native_cursor.h" -#include "os/x11/window.h" - -#include - -namespace os { - -class EventQueue; -class SkiaDisplay; - -class SkiaWindow : public X11Window { -public: - enum class Backend { NONE, GL }; - - SkiaWindow(EventQueue* queue, SkiaDisplay* display, - int width, int height, int scale); - ~SkiaWindow(); - - void setVisible(bool visible); - void maximize(); - bool isMaximized() const; - bool isMinimized() const; - - std::string getLayout() { return ""; } - void setLayout(const std::string& layout) { } - -private: - void queueEvent(Event& ev) override; - void paintGC(const gfx::Rect& rc) override; - void resizeDisplay(const gfx::Size& sz) override; - - EventQueue* m_queue; - SkiaDisplay* m_display; - - DISABLE_COPYING(SkiaWindow); -}; - -} // namespace os - -#endif diff --git a/src/os/surface.h b/src/os/surface.h deleted file mode 100644 index 3a60c2ce8..000000000 --- a/src/os/surface.h +++ /dev/null @@ -1,86 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SURFACE_H_INCLUDED -#define OS_SURFACE_H_INCLUDED -#pragma once - -#include "base/string.h" -#include "gfx/color.h" -#include "gfx/fwd.h" -#include "os/surface_format.h" - -#include - -namespace os { - - class SurfaceLock; - - enum class DrawMode { - Solid, - Checked, - Xor - }; - - class Surface { - public: - virtual ~Surface() { } - virtual void dispose() = 0; - virtual int width() const = 0; - virtual int height() const = 0; - virtual bool isDirectToScreen() const = 0; - - virtual int getSaveCount() const = 0; - virtual gfx::Rect getClipBounds() const = 0; - virtual void saveClip() = 0; - virtual void restoreClip() = 0; - virtual bool clipRect(const gfx::Rect& rc) = 0; - - virtual void setDrawMode(DrawMode mode, int param = 0, - const gfx::Color a = gfx::ColorNone, - const gfx::Color b = gfx::ColorNone) = 0; - - virtual void lock() = 0; - virtual void unlock() = 0; - - virtual void clear() = 0; - - virtual uint8_t* getData(int x, int y) const = 0; - virtual void getFormat(SurfaceFormatData* formatData) const = 0; - - virtual gfx::Color getPixel(int x, int y) const = 0; - virtual void putPixel(gfx::Color color, int x, int y) = 0; - - virtual void drawHLine(gfx::Color color, int x, int y, int w) = 0; - virtual void drawVLine(gfx::Color color, int x, int y, int h) = 0; - virtual void drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b) = 0; - - virtual void drawRect(gfx::Color color, const gfx::Rect& rc) = 0; - virtual void fillRect(gfx::Color color, const gfx::Rect& rc) = 0; - - virtual void blitTo(Surface* dest, int srcx, int srcy, int dstx, int dsty, int width, int height) const = 0; - virtual void scrollTo(const gfx::Rect& rc, int dx, int dy) = 0; - virtual void drawSurface(const Surface* src, int dstx, int dsty) = 0; - virtual void drawRgbaSurface(const Surface* src, int dstx, int dsty) = 0; - virtual void drawRgbaSurface(const Surface* src, int srcx, int srcy, int dstx, int dsty, int width, int height) = 0; - virtual void drawRgbaSurface(const Surface* surface, const gfx::Rect& srcRect, const gfx::Rect& dstRect) = 0; - virtual void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clip) = 0; - - virtual void applyScale(int scaleFactor) = 0; - virtual void* nativeHandle() = 0; - }; - - class SurfaceLock { - public: - SurfaceLock(Surface* surface) : m_surface(surface) { m_surface->lock(); } - ~SurfaceLock() { m_surface->unlock(); } - private: - Surface* m_surface; - }; - -} // namespace os - -#endif diff --git a/src/os/surface_format.h b/src/os/surface_format.h deleted file mode 100644 index 0d9654ad1..000000000 --- a/src/os/surface_format.h +++ /dev/null @@ -1,32 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2013 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SURFACE_FORMAT_H_INCLUDED -#define OS_SURFACE_FORMAT_H_INCLUDED -#pragma once - -namespace os { - - enum SurfaceFormat { - kRgbaSurfaceFormat, - }; - - struct SurfaceFormatData { - SurfaceFormat format; - uint32_t bitsPerPixel; - uint32_t redShift; - uint32_t greenShift; - uint32_t blueShift; - uint32_t alphaShift; - uint32_t redMask; - uint32_t greenMask; - uint32_t blueMask; - uint32_t alphaMask; - }; - -} // namespace os - -#endif diff --git a/src/os/surface_list.h b/src/os/surface_list.h deleted file mode 100644 index f826c491b..000000000 --- a/src/os/surface_list.h +++ /dev/null @@ -1,21 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SURFACE_LIST_H_INCLUDED -#define OS_SURFACE_LIST_H_INCLUDED -#pragma once - -#include - -namespace os { - - class Surface; - - typedef std::vector SurfaceList; - -} // namespace os - -#endif diff --git a/src/os/system.cpp b/src/os/system.cpp deleted file mode 100644 index a4184bc21..000000000 --- a/src/os/system.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "base/debug.h" -#include "os/system.h" - -namespace os { - -static System* g_system = nullptr; - -System* create_system_impl(); // Defined on each back-end - -System* create_system() -{ - ASSERT(!g_system); - return g_system = create_system_impl(); -} - -System* instance() -{ - return g_system; -} - -} // namespace os diff --git a/src/os/system.h b/src/os/system.h deleted file mode 100644 index e5e952e41..000000000 --- a/src/os/system.h +++ /dev/null @@ -1,84 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_SYSTEM_H_INCLUDED -#define OS_SYSTEM_H_INCLUDED -#pragma once - -#include "gfx/fwd.h" -#include "os/capabilities.h" -#include "os/keys.h" - -#include - -namespace os { - - class Display; - class EventQueue; - class Font; - class Logger; - class Menus; - class NativeDialogs; - class Surface; - - class DisplayCreationException : public std::runtime_error { - public: - DisplayCreationException(const char* msg) throw() - : std::runtime_error(msg) { } - }; - - class System { - public: - virtual ~System() { } - virtual void dispose() = 0; - virtual void activateApp() = 0; - virtual void finishLaunching() = 0; - virtual Capabilities capabilities() const = 0; - - // Disables loading wintab32.dll (sometimes a program can be - // locked when we load the wintab32.dll, so we need a way to - // opt-out loading this library.) - virtual void useWintabAPI(bool enable) = 0; - - virtual Logger* logger() = 0; - virtual Menus* menus() = 0; - virtual NativeDialogs* nativeDialogs() = 0; - virtual EventQueue* eventQueue() = 0; - virtual bool gpuAcceleration() const = 0; - virtual void setGpuAcceleration(bool state) = 0; - virtual gfx::Size defaultNewDisplaySize() = 0; - virtual Display* defaultDisplay() = 0; - virtual Display* createDisplay(int width, int height, int scale) = 0; - virtual Surface* createSurface(int width, int height) = 0; - virtual Surface* createRgbaSurface(int width, int height) = 0; - virtual Surface* loadSurface(const char* filename) = 0; - virtual Surface* loadRgbaSurface(const char* filename) = 0; - virtual Font* loadSpriteSheetFont(const char* filename, int scale = 1) = 0; - virtual Font* loadTrueTypeFont(const char* filename, int height) = 0; - - // Returns true if the the given scancode key is pressed/actived. - virtual bool isKeyPressed(KeyScancode scancode) = 0; - - // Returns the active pressed modifiers. - virtual KeyModifiers keyModifiers() = 0; - - // Returns the latest unicode character that activated the given - // scancode. - virtual int getUnicodeFromScancode(KeyScancode scancode) = 0; - - // Indicates if you want to use dead keys or not. By default it's - // false, which behaves as regular shortcuts. You should set this - // to true when you're inside a text field in your app. - virtual void setTranslateDeadKeys(bool state) = 0; - - }; - - System* create_system(); - System* instance(); - -} // namespace os - -#endif diff --git a/src/os/win/event_queue.h b/src/os/win/event_queue.h deleted file mode 100644 index b92f9ba95..000000000 --- a/src/os/win/event_queue.h +++ /dev/null @@ -1,84 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_EVENT_QUEUE_INCLUDED -#define OS_WIN_EVENT_QUEUE_INCLUDED -#pragma once - -#include - -#include - -#include "os/event.h" -#include "os/event_queue.h" - -namespace os { - -class WinEventQueue : public EventQueue { -public: - WinEventQueue() : m_translateDeadKeys(false) { - } - - void getEvent(Event& ev, bool canWait) override { - MSG msg; - - while (m_events.empty()) { - BOOL res; - - if (canWait) { - ASSERT(false); // Not yet supported - res = GetMessage(&msg, nullptr, 0, 0); - } - else { - res = PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE); - } - - if (res) { - // Avoid transforming WM_KEYDOWN/UP into WM_DEADCHAR/WM_CHAR - // messages. Dead keys are converted manually in the - // WM_KEYDOWN processing on our WinWindow class. - // - // From MSDN TranslateMessage() documentation: - // "WM_KEYDOWN and WM_KEYUP combinations produce a WM_CHAR - // or WM_DEADCHAR message." - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644955.aspx - if (msg.message != WM_KEYDOWN && - msg.message != WM_KEYUP) { - TranslateMessage(&msg); - } - DispatchMessage(&msg); - } - else if (!canWait) - break; - } - - if (m_events.empty()) { - ev.setType(Event::None); - } - else { - ev = m_events.front(); - m_events.pop(); - } - } - - void queueEvent(const Event& ev) override { - m_events.push(ev); - } - - void setTranslateDeadKeys(bool state) { - m_translateDeadKeys = state; - } - -private: - std::queue m_events; - bool m_translateDeadKeys; -}; - -typedef WinEventQueue EventQueueImpl; - -} // namespace os - -#endif diff --git a/src/os/win/keys.cpp b/src/os/win/keys.cpp deleted file mode 100644 index 5dd793017..000000000 --- a/src/os/win/keys.cpp +++ /dev/null @@ -1,361 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/win/keys.h" - -namespace os { - -KeyScancode win32vk_to_scancode(int vk) -{ - static KeyScancode keymap[256] = { - // 0x00 - kKeyNil, // 0x00 - kKeyNil, // 0x01 - VK_LBUTTON - kKeyNil, // 0x02 - VK_RBUTTON - kKeyNil, // 0x03 - VK_CANCEL - kKeyNil, // 0x04 - VK_MBUTTON - kKeyNil, // 0x05 - VK_XBUTTON1 - kKeyNil, // 0x06 - VK_XBUTTON2 - kKeyNil, // 0x07 - Unassigned - kKeyBackspace, // 0x08 - VK_BACK - kKeyTab, // 0x09 - VK_TAB - kKeyNil, // 0x0A - Reserved - kKeyNil, // 0x0B - Reserved - kKeyNil, // 0x0C - VK_CLEAR - kKeyEnter, // 0x0D - VK_RETURN - kKeyNil, // 0x0E - Undefined - kKeyNil, // 0x0F - Undefined - // 0x10 - kKeyLShift, // 0x10 - VK_SHIFT - kKeyLControl, // 0x11 - VK_CONTROL - kKeyAlt, // 0x12 - VK_MENU - kKeyPause, // 0x13 - VK_PAUSE - kKeyCapsLock, // 0x14 - VK_CAPITAL - kKeyKana, // 0x15 - VK_KANA - kKeyNil, // 0x16 - Undefined - kKeyNil, // 0x17 - VK_JUNJA - kKeyNil, // 0x18 - VK_FINAL - kKeyKanji, // 0x19 - VK_KANJI - kKeyNil, // 0x1A - Unknown - kKeyEsc, // 0x1B - VK_ESCAPE - kKeyConvert, // 0x1C - VK_CONVERT - kKeyNoconvert, // 0x1D - VK_NONCONVERT - kKeyNil, // 0x1E - VK_ACCEPT - kKeyNil, // 0x1F - VK_MODECHANGE - // 0x20 - kKeySpace, // 0x20 - VK_SPACE - kKeyPageUp, // 0x21 - VK_PRIOR - kKeyPageDown, // 0x22 - VK_NEXT - kKeyEnd, // 0x23 - VK_END - kKeyHome, // 0x24 - VK_HOME - kKeyLeft, // 0x25 - VK_LEFT - kKeyUp, // 0x26 - VK_UP - kKeyRight, // 0x27 - VK_RIGHT - kKeyDown, // 0x28 - VK_DOWN - kKeyNil, // 0x29 - VK_SELECT - kKeyNil, // 0x2A - VK_PRINT - kKeyNil, // 0x2B - VK_EXECUTE - kKeyPrtscr, // 0x2C - VK_SNAPSHOT - kKeyInsert, // 0x2D - VK_INSERT - kKeyDel, // 0x2E - VK_DELETE - kKeyNil, // 0x2F - VK_HELP - // 0x30 - kKey0, // 0x30 - VK_0 - kKey1, // 0x31 - VK_1 - kKey2, // 0x32 - VK_2 - kKey3, // 0x33 - VK_3 - kKey4, // 0x34 - VK_4 - kKey5, // 0x35 - VK_5 - kKey6, // 0x36 - VK_6 - kKey7, // 0x37 - VK_7 - kKey8, // 0x38 - VK_8 - kKey9, // 0x39 - VK_9 - kKeyNil, // 0x3A - Unassigned - kKeyNil, // 0x3B - Unassigned - kKeyNil, // 0x3C - Unassigned - kKeyNil, // 0x3D - Unassigned - kKeyNil, // 0x3E - Unassigned - kKeyNil, // 0x3F - Unassigned - // 0x40 - kKeyNil, // 0x40 - Unassigned - kKeyA, // 0x41 - VK_A - kKeyB, // 0x42 - VK_B - kKeyC, // 0x43 - VK_C - kKeyD, // 0x44 - VK_D - kKeyE, // 0x45 - VK_E - kKeyF, // 0x46 - VK_F - kKeyG, // 0x47 - VK_G - kKeyH, // 0x48 - VK_H - kKeyI, // 0x49 - VK_I - kKeyJ, // 0x4A - VK_J - kKeyK, // 0x4B - VK_K - kKeyL, // 0x4C - VK_L - kKeyM, // 0x4D - VK_M - kKeyN, // 0x4E - VK_N - kKeyO, // 0x4F - VK_O - // 0x50 - kKeyP, // 0x50 - VK_P - kKeyQ, // 0x51 - VK_Q - kKeyR, // 0x52 - VK_R - kKeyS, // 0x53 - VK_S - kKeyT, // 0x54 - VK_T - kKeyU, // 0x55 - VK_U - kKeyV, // 0x56 - VK_V - kKeyW, // 0x57 - VK_W - kKeyX, // 0x58 - VK_X - kKeyY, // 0x59 - VK_Y - kKeyZ, // 0x5A - VK_Z - kKeyLWin, // 0x5B - VK_LWIN - kKeyRWin, // 0x5C - VK_RWIN - kKeyMenu, // 0x5D - VK_APPS - kKeyNil, // 0x5E - Reserved - kKeyNil, // 0x5F - VK_SLEEP - // 0x60 - kKey0Pad, // 0x60 - VK_NUMPAD0 - kKey1Pad, // 0x61 - VK_NUMPAD1 - kKey2Pad, // 0x62 - VK_NUMPAD2 - kKey3Pad, // 0x63 - VK_NUMPAD3 - kKey4Pad, // 0x64 - VK_NUMPAD4 - kKey5Pad, // 0x65 - VK_NUMPAD5 - kKey6Pad, // 0x66 - VK_NUMPAD6 - kKey7Pad, // 0x67 - VK_NUMPAD7 - kKey8Pad, // 0x68 - VK_NUMPAD8 - kKey9Pad, // 0x69 - VK_NUMPAD9 - kKeyAsterisk, // 0x6A - VK_MULTIPLY - kKeyPlusPad, // 0x6B - VK_ADD - kKeyNil, // 0x6C - VK_SEPARATOR - kKeyMinusPad, // 0x6D - VK_SUBTRACT - kKeyNil, // 0x6E - VK_DECIMAL - kKeySlashPad, // 0x6F - VK_DIVIDE - // 0x70 - kKeyF1, // 0x70 - VK_F1 - kKeyF2, // 0x71 - VK_F2 - kKeyF3, // 0x72 - VK_F3 - kKeyF4, // 0x73 - VK_F4 - kKeyF5, // 0x74 - VK_F5 - kKeyF6, // 0x75 - VK_F6 - kKeyF7, // 0x76 - VK_F7 - kKeyF8, // 0x77 - VK_F8 - kKeyF9, // 0x78 - VK_F9 - kKeyF10, // 0x79 - VK_F10 - kKeyF11, // 0x7A - VK_F11 - kKeyF12, // 0x7B - VK_F12 - kKeyNil, // 0x7C - VK_F13 - kKeyNil, // 0x7D - VK_F14 - kKeyNil, // 0x7E - VK_F15 - kKeyNil, // 0x7F - VK_F16 - // 0x80 - kKeyNil, // 0x80 - VK_F17 - kKeyNil, // 0x81 - VK_F18 - kKeyNil, // 0x82 - VK_F19 - kKeyNil, // 0x83 - VK_F20 - kKeyNil, // 0x84 - VK_F21 - kKeyNil, // 0x85 - VK_F22 - kKeyNil, // 0x86 - VK_F23 - kKeyNil, // 0x87 - VK_F24 - kKeyNil, // 0x88 - Unassigned - kKeyNil, // 0x89 - Unassigned - kKeyNil, // 0x8A - Unassigned - kKeyNil, // 0x8B - Unassigned - kKeyNil, // 0x8C - Unassigned - kKeyNil, // 0x8D - Unassigned - kKeyNil, // 0x8E - Unassigned - kKeyNil, // 0x8F - Unassigned - // 0x90 - kKeyNumLock, // 0x90 - VK_NUMLOCK - kKeyScrLock, // 0x91 - VK_SCROLL - kKeyNil, // 0x92 - VK_OEM_NEC_EQUAL / VK_OEM_FJ_JISHO - kKeyNil, // 0x93 - VK_OEM_FJ_MASSHOU - kKeyNil, // 0x94 - VK_OEM_FJ_TOUROKU - kKeyNil, // 0x95 - VK_OEM_FJ_LOYA - kKeyNil, // 0x96 - VK_OEM_FJ_ROYA - kKeyNil, // 0x97 - Unassigned - kKeyNil, // 0x98 - Unassigned - kKeyNil, // 0x99 - Unassigned - kKeyNil, // 0x9A - Unassigned - kKeyNil, // 0x9B - Unassigned - kKeyNil, // 0x9C - Unassigned - kKeyNil, // 0x9D - Unassigned - kKeyNil, // 0x9E - Unassigned - kKeyNil, // 0x9F - Unassigned - // 0xA0 - kKeyLShift, // 0xA0 - VK_LSHIFT - kKeyRShift, // 0xA1 - VK_RSHIFT - kKeyLControl, // 0xA2 - VK_LCONTROL - kKeyRControl, // 0xA3 - VK_RCONTROL - kKeyAlt, // 0xA4 - VK_LMENU - kKeyAltGr, // 0xA5 - VK_RMENU - kKeyNil, // 0xA6 - VK_BROWSER_BACK - kKeyNil, // 0xA7 - VK_BROWSER_FORWARD - kKeyNil, // 0xA8 - VK_BROWSER_REFRESH - kKeyNil, // 0xA9 - VK_BROWSER_STOP - kKeyNil, // 0xAA - VK_BROWSER_SEARCH - kKeyNil, // 0xAB - VK_BROWSER_FAVORITES - kKeyNil, // 0xAC - VK_BROWSER_HOME - kKeyNil, // 0xAD - VK_VOLUME_MUTE - kKeyNil, // 0xAE - VK_VOLUME_DOWN - kKeyNil, // 0xAF - VK_VOLUME_UP - // 0xB0 - kKeyNil, // 0xB0 - VK_MEDIA_NEXT_TRACK - kKeyNil, // 0xB1 - VK_MEDIA_PREV_TRACK - kKeyNil, // 0xB2 - VK_MEDIA_STOP - kKeyNil, // 0xB3 - VK_MEDIA_PLAY_PAUSE - kKeyNil, // 0xB4 - VK_LAUNCH_MAIL - kKeyNil, // 0xB5 - VK_LAUNCH_MEDIA_SELECT - kKeyNil, // 0xB6 - VK_LAUNCH_APP1 - kKeyNil, // 0xB7 - VK_LAUNCH_APP2 - kKeyNil, // 0xB8 - Reserved - kKeyNil, // 0xB9 - Reserved - kKeySemicolon, // 0xBA - VK_OEM_1 - kKeyEquals, // 0xBB - VK_OEM_PLUS - kKeyComma, // 0xBC - VK_OEM_COMMA - kKeyMinus, // 0xBD - VK_OEM_MINUS - kKeyStop, // 0xBE - VK_OEM_PERIOD - kKeySlash, // 0xBF - VK_OEM_2 - // 0xC0 - kKeyTilde, // 0xC0 - VK_OEM_3 - kKeyNil, // 0xC1 - Reserved - kKeyNil, // 0xC2 - Reserved - kKeyNil, // 0xC3 - Reserved - kKeyNil, // 0xC4 - Reserved - kKeyNil, // 0xC5 - Reserved - kKeyNil, // 0xC6 - Reserved - kKeyNil, // 0xC7 - Reserved - kKeyNil, // 0xC8 - Reserved - kKeyNil, // 0xC9 - Reserved - kKeyNil, // 0xCA - Reserved - kKeyNil, // 0xCB - Reserved - kKeyNil, // 0xCC - Reserved - kKeyNil, // 0xCD - Reserved - kKeyNil, // 0xCE - Reserved - kKeyNil, // 0xCF - Reserved - // 0xD0 - kKeyNil, // 0xD0 - Reserved - kKeyNil, // 0xD1 - Reserved - kKeyNil, // 0xD2 - Reserved - kKeyNil, // 0xD3 - Reserved - kKeyNil, // 0xD4 - Reserved - kKeyNil, // 0xD5 - Reserved - kKeyNil, // 0xD6 - Reserved - kKeyNil, // 0xD7 - Reserved - kKeyNil, // 0xD8 - Unassigned - kKeyNil, // 0xD9 - Unassigned - kKeyNil, // 0xDA - Unassigned - kKeyOpenbrace, // 0xDB - VK_OEM_4 - kKeyBackslash, // 0xDC - VK_OEM_5 - kKeyClosebrace, // 0xDD - VK_OEM_6 - kKeyQuote, // 0xDE - VK_OEM_7 - kKeyNil, // 0xDF - VK_OEM_8 - // 0xE0 - kKeyNil, // 0xE0 - Reserved - kKeyNil, // 0xE1 - VK_OEM_AX - kKeyBackslash2, // 0xE2 - VK_OEM_102 - kKeyNil, // 0xE3 - VK_ICO_HELP - kKeyNil, // 0xE4 - VK_ICO_00 - kKeyNil, // 0xE5 - VK_PROCESSKEY - kKeyNil, // 0xE6 - VK_ICO_CLEAR - kKeyNil, // 0xE7 - VK_PACKET - kKeyNil, // 0xE8 - Unassigned - kKeyNil, // 0xE9 - VK_OEM_RESET - kKeyNil, // 0xEA - VK_OEM_JUMP - kKeyNil, // 0xEB - VK_OEM_PA1 - kKeyNil, // 0xEC - VK_OEM_PA2 - kKeyNil, // 0xED - VK_OEM_PA3 - kKeyNil, // 0xEE - VK_OEM_WSCTRL - kKeyNil, // 0xEF - VK_OEM_CUSEL - // 0xF0 - kKeyNil, // 0xF0 - VK_OEM_ATTN - kKeyNil, // 0xF1 - VK_OEM_FINISH - kKeyNil, // 0xF2 - VK_OEM_COPY - kKeyNil, // 0xF3 - VK_OEM_AUTO - kKeyNil, // 0xF4 - VK_OEM_ENLW - kKeyNil, // 0xF5 - VK_OEM_BACKTAB - kKeyNil, // 0xF6 - VK_ATTN - kKeyNil, // 0xF7 - VK_CRSEL - kKeyNil, // 0xF8 - VK_EXSEL - kKeyNil, // 0xF9 - VK_EREOF - kKeyNil, // 0xFA - VK_PLAY - kKeyNil, // 0xFB - VK_ZOOM - kKeyNil, // 0xFC - VK_NONAME - kKeyNil, // 0xFD - VK_PA1 - kKeyNil, // 0xFE - VK_OEM_CLEAR - kKeyNil, // 0xFF - Reserved - }; - if (vk < 0 || vk > 255) - vk = 0; - return keymap[vk]; -} - -KeyModifiers get_modifiers_from_last_win32_message() -{ - int modifiers = kKeyNoneModifier; - if ((GetKeyState(VK_LSHIFT) & 0x8000) || - (GetKeyState(VK_RSHIFT) & 0x8000)) - modifiers |= kKeyShiftModifier; - if ((GetKeyState(VK_LCONTROL) & 0x8000) || - (GetKeyState(VK_RCONTROL) & 0x8000)) - modifiers |= kKeyCtrlModifier; - if ((GetKeyState(VK_LMENU) & 0x8000) || - (GetKeyState(VK_RMENU) & 0x8000)) - modifiers |= kKeyAltModifier; - if (GetKeyState(VK_SPACE) & 0x8000) - modifiers |= kKeySpaceModifier; - if ((GetKeyState(VK_LWIN) & 0x8000) || - (GetKeyState(VK_RWIN) & 0x8000)) - modifiers |= kKeyWinModifier; - return (KeyModifiers)modifiers; -} - -static int scancode_to_win32vk(KeyScancode scancode) -{ - static int initialized = false; - static int keymap[kKeyScancodes]; - - if (!initialized) { - initialized = true; - for (int i=0; i kKeyScancodes) - scancode = kKeyNil; - - return keymap[scancode]; -} - -bool win_is_key_pressed(KeyScancode scancode) -{ - int vk = scancode_to_win32vk(scancode); - if (vk) - return (GetAsyncKeyState(vk) & 0x8000 ? true: false); - else - return false; -} - -int win_get_unicode_from_scancode(KeyScancode scancode) -{ - int vk = scancode_to_win32vk(scancode); - if (vk && (GetAsyncKeyState(vk) & 0x8000 ? true: false)) { - VkToUnicode tu; - if (tu) { - tu.toUnicode(vk, 0); - if (tu.size() > 0) - return tu[0]; - } - } - return 0; -} - -} // namespace os diff --git a/src/os/win/keys.h b/src/os/win/keys.h deleted file mode 100644 index 3a220e54d..000000000 --- a/src/os/win/keys.h +++ /dev/null @@ -1,71 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_VK_H_INCLUDED -#define OS_WIN_VK_H_INCLUDED -#pragma once - -#include - -#include "os/keys.h" - -namespace os { - - KeyScancode win32vk_to_scancode(int vk); - KeyModifiers get_modifiers_from_last_win32_message(); - - class VkToUnicode { - public: - VkToUnicode() : m_size(0) { - m_ok = (GetKeyboardState(&m_keystate[0]) ? true: false); - } - - void toUnicode(int vk, int scancode) { - // ToUnicode returns several characters inside the buffer in - // case that a dead-key wasn't combined with the next pressed - // character. - m_size = - ToUnicode(vk, scancode, m_keystate, m_buffer, - sizeof(m_buffer)/sizeof(m_buffer[0]), 0); - - // If there is a control key pressed, we'll try to get the - // unicode character turning control/shift off. - if (m_size == 0 || - (m_size == 1 && m_buffer[0] == 0 && - m_keystate[VK_CONTROL] | m_keystate[VK_LCONTROL] | m_keystate[VK_RCONTROL])) { - m_keystate[VK_SHIFT] = m_keystate[VK_LSHIFT] = m_keystate[VK_RSHIFT] = 0; - m_keystate[VK_CONTROL] = m_keystate[VK_LCONTROL] = m_keystate[VK_RCONTROL] = 0; - m_size = - ToUnicode(vk, scancode, m_keystate, m_buffer, - sizeof(m_buffer)/sizeof(m_buffer[0]), 0); - } - } - - operator bool() { return m_ok; } - int size() const { return ABS(m_size); } - LPCWSTR begin() const { return m_buffer; } - LPCWSTR end() const { return m_buffer+size(); } - - int operator[](const int i) { - ASSERT(i >= 0 && i < size()); - return m_buffer[i]; - } - - // ToUnicode() returns -1 if there is dead key waiting - bool isDeadKey() const { - return (m_size == -1); - } - - private: - bool m_ok; - BYTE m_keystate[256]; - WCHAR m_buffer[8]; - int m_size; - }; - -} // namespace os - -#endif diff --git a/src/os/win/native_dialogs.cpp b/src/os/win/native_dialogs.cpp deleted file mode 100644 index e46e0641f..000000000 --- a/src/os/win/native_dialogs.cpp +++ /dev/null @@ -1,370 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/win/native_dialogs.h" - -#include "base/fs.h" -#include "base/string.h" -#include "base/win/comptr.h" -#include "os/common/file_dialog.h" -#include "os/display.h" -#include "os/error.h" - -#include -#include - -#include -#include - -namespace os { - -// 32k is the limit for Win95/98/Me/NT4/2000/XP with ANSI version -#define FILENAME_BUFSIZE (1024*32) - -class FileDialogWin32 : public CommonFileDialog { -public: - FileDialogWin32() - : m_filename(FILENAME_BUFSIZE) - , m_defFilter(0) { - } - - std::string fileName() override { - return base::to_utf8(&m_filename[0]); - } - - void getMultipleFileNames(base::paths& output) override { - output = m_filenames; - } - - void setFileName(const std::string& filename) override { - wcscpy(&m_filename[0], base::from_utf8(base::get_file_name(filename)).c_str()); - m_initialDir = base::from_utf8(base::get_file_path(filename)); - } - - bool show(Display* parent) override { - bool result = false; - bool shown = false; - - HRESULT hr = showWithNewAPI(parent, result, shown); - if (FAILED(hr) && !shown) - hr = showWithOldAPI(parent, result); - - if (SUCCEEDED(hr)) - return result; - - return false; - } - -private: - - HRESULT showWithNewAPI(Display* parent, bool& result, bool& shown) { - base::ComPtr dlg; - HRESULT hr = CoCreateInstance( - (m_type == Type::SaveFile ? CLSID_FileSaveDialog: - CLSID_FileOpenDialog), - nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dlg)); - if (FAILED(hr)) - return hr; - - FILEOPENDIALOGOPTIONS options = - FOS_NOCHANGEDIR | - FOS_PATHMUSTEXIST | - FOS_FORCEFILESYSTEM; - - switch (m_type) { - case Type::OpenFile: - options |= FOS_FILEMUSTEXIST; - break; - case Type::OpenFiles: - options |= FOS_FILEMUSTEXIST - | FOS_ALLOWMULTISELECT; - break; - case Type::OpenFolder: - options |= FOS_PICKFOLDERS; - break; - case Type::SaveFile: - options |= FOS_OVERWRITEPROMPT; - break; - } - - hr = dlg->SetOptions(options); - if (FAILED(hr)) - return hr; - - if (!m_title.empty()) { - std::wstring title = base::from_utf8(m_title); - hr = dlg->SetTitle(title.c_str()); - if (FAILED(hr)) - return hr; - } - - if (std::wcslen(&m_filename[0]) > 0) { - hr = dlg->SetFileName(&m_filename[0]); - if (FAILED(hr)) - return hr; - } - - if (std::wcslen(&m_initialDir[0]) > 0) { - base::ComPtr item; - - // The SHCreateItemFromParsingName() function is available since - // Windows Vista in shell32.dll - hr = ::SHCreateItemFromParsingName(&m_initialDir[0], nullptr, - IID_PPV_ARGS(&item)); - if (FAILED(hr)) - return hr; - - if (item.get()) { - hr = dlg->SetFolder(item.get()); - if (FAILED(hr)) - return hr; - } - } - - if (!m_defExtension.empty()) { - std::wstring defExt = base::from_utf8(m_defExtension); - hr = dlg->SetDefaultExtension(defExt.c_str()); - if (FAILED(hr)) - return hr; - } - - if (m_type != Type::OpenFolder && !m_filters.empty()) { - std::vector specs; - getFiltersForIFileDialog(specs); - hr = dlg->SetFileTypes(specs.size(), &specs[0]); - freeFiltersForIFileDialog(specs); - - if (SUCCEEDED(hr)) - hr = dlg->SetFileTypeIndex(m_defFilter+1); // One-based index - if (FAILED(hr)) - return hr; - } - - hr = dlg->Show(parent ? (HWND)parent->nativeHandle(): nullptr); - if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { - shown = true; - result = false; - return S_OK; - } - if (FAILED(hr)) - return hr; - shown = true; - - if (m_type == Type::OpenFiles) { - base::ComPtr odlg; - hr = dlg->QueryInterface(IID_IFileOpenDialog, (void**)&odlg); - base::ComPtr items; - hr = odlg->GetResults(&items); - if (FAILED(hr)) - return hr; - - DWORD nitems = 0; - hr = items->GetCount(&nitems); - if (FAILED(hr)) - return hr; - - for (DWORD i=0; i item; - hr = items->GetItemAt(i, &item); - if (FAILED(hr)) - return hr; - - LPWSTR fn; - hr = item->GetDisplayName(SIGDN_FILESYSPATH, &fn); - if (SUCCEEDED(hr)) { - m_filenames.push_back(base::to_utf8(fn)); - CoTaskMemFree(fn); - } - } - } - else { - base::ComPtr item; - hr = dlg->GetResult(&item); - if (FAILED(hr)) - return hr; - - LPWSTR fn; - hr = item->GetDisplayName(SIGDN_FILESYSPATH, &fn); - if (FAILED(hr)) - return hr; - - wcscpy(&m_filename[0], fn); - m_filenames.push_back(base::to_utf8(&m_filename[0])); - CoTaskMemFree(fn); - } - - result = (hr == S_OK); - return S_OK; - } - - HRESULT showWithOldAPI(Display* parent, bool& result) { - std::wstring title = base::from_utf8(m_title); - std::wstring defExt = base::from_utf8(m_defExtension); - std::wstring filtersWStr = getFiltersForGetOpenFileName(); - - OPENFILENAME ofn; - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = (HWND)parent->nativeHandle(); - ofn.hInstance = GetModuleHandle(NULL); - ofn.lpstrFilter = filtersWStr.c_str(); - ofn.nFilterIndex = m_defFilter; - ofn.lpstrFile = &m_filename[0]; - ofn.nMaxFile = FILENAME_BUFSIZE; - if (!m_initialDir.empty()) - ofn.lpstrInitialDir = m_initialDir.c_str(); - ofn.lpstrTitle = title.c_str(); - ofn.lpstrDefExt = defExt.c_str(); - ofn.Flags = - OFN_ENABLESIZING | - OFN_EXPLORER | - OFN_LONGNAMES | - OFN_NOCHANGEDIR | - OFN_PATHMUSTEXIST; - - if (m_type == Type::SaveFile) { - ofn.Flags |= OFN_OVERWRITEPROMPT; - } - else { - ofn.Flags |= OFN_FILEMUSTEXIST; - if (m_type == Type::OpenFiles) - ofn.Flags |= OFN_ALLOWMULTISELECT; - } - - BOOL res; - if (m_type == Type::SaveFile) - res = GetSaveFileName(&ofn); - else { - res = GetOpenFileName(&ofn); - if (res && m_type == Type::OpenFiles) { - WCHAR* p = &m_filename[0]; - std::string path = base::to_utf8(p); - - for (p+=std::wcslen(p)+1; ; ++p) { - if (*p) { - WCHAR* q = p; - for (++p; *p; ++p) - ; - - m_filenames.push_back( - base::join_path(path, base::to_utf8(q))); - } - else // Two null chars in a row - break; - } - - // Just one filename was selected - if (m_filenames.empty()) - m_filenames.push_back(path); - } - } - - if (!res) { - DWORD err = CommDlgExtendedError(); - if (err) { - std::vector buf(1024); - sprintf(&buf[0], "Error using GetOpen/SaveFileName Win32 API. Code: %d", err); - os::error_message(&buf[0]); - } - } - - result = (res != FALSE); - return S_OK; - } - - void getFiltersForIFileDialog(std::vector& specs) const { - specs.resize(m_filters.size()+2); - - int i = 0, j = 0; - specs[i].pszName = _wcsdup(L"All formats"); - std::wstring exts; - bool first = true; - for (const auto& filter : m_filters) { - if (first) - first = false; - else - exts.push_back(';'); - exts.append(L"*."); - exts.append(base::from_utf8(filter.first)); - } - specs[i].pszSpec = _wcsdup(exts.c_str()); - ++i; - - for (const auto& filter : m_filters) { - specs[i].pszName = _wcsdup(base::from_utf8(filter.second).c_str()); - specs[i].pszSpec = _wcsdup(base::from_utf8("*." + filter.first).c_str()); - ++i; - } - - specs[i].pszName = _wcsdup(L"All files"); - specs[i].pszSpec = _wcsdup(L"*.*"); - ++i; - } - - void freeFiltersForIFileDialog(std::vector& specs) const { - for (auto& spec : specs) { - free((void*)spec.pszName); - free((void*)spec.pszSpec); - } - } - - std::wstring getFiltersForGetOpenFileName() const { - std::wstring filters; - - // A filter for all known types - filters.append(L"All formats"); - filters.push_back('\0'); - bool first = true; - for (const auto& filter : m_filters) { - if (first) - first = false; - else - filters.push_back(';'); - filters.append(L"*."); - filters.append(base::from_utf8(filter.first)); - } - filters.push_back('\0'); - - // A specific filter for each type - for (const auto& filter : m_filters) { - filters.append(base::from_utf8(filter.second)); - filters.push_back('\0'); - filters.append(L"*."); - filters.append(base::from_utf8(filter.first)); - filters.push_back('\0'); - } - - // A filter for all files - filters.append(L"All files"); - filters.push_back('\0'); - filters.append(L"*.*"); - filters.push_back('\0'); - - // End of filter string (two zeros at the end) - filters.push_back('\0'); - return filters; - } - - int m_defFilter; - std::vector m_filename; - base::paths m_filenames; - std::wstring m_initialDir; -}; - -NativeDialogsWin32::NativeDialogsWin32() -{ -} - -FileDialog* NativeDialogsWin32::createFileDialog() -{ - return new FileDialogWin32(); -} - -} // namespace os diff --git a/src/os/win/native_dialogs.h b/src/os/win/native_dialogs.h deleted file mode 100644 index 47ac7f55a..000000000 --- a/src/os/win/native_dialogs.h +++ /dev/null @@ -1,23 +0,0 @@ -// LAF OS Library -// Copyright (C) 2015 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_NATIVE_DIALOGS_H_INCLUDED -#define OS_WIN_NATIVE_DIALOGS_H_INCLUDED -#pragma once - -#include "os/native_dialogs.h" - -namespace os { - - class NativeDialogsWin32 : public NativeDialogs { - public: - NativeDialogsWin32(); - FileDialog* createFileDialog() override; - }; - -} // namespace os - -#endif diff --git a/src/os/win/pen.cpp b/src/os/win/pen.cpp deleted file mode 100644 index 1c4bbfa87..000000000 --- a/src/os/win/pen.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/win/pen.h" - -#include "base/convert_to.h" -#include "base/debug.h" -#include "base/fs.h" -#include "base/log.h" -#include "base/sha1.h" -#include "base/string.h" - -#include - -namespace os { - -namespace { - -typedef UINT (API* WTInfoW_Func)(UINT, UINT, LPVOID); -typedef HCTX (API* WTOpenW_Func)(HWND, LPLOGCONTEXTW, BOOL); -typedef BOOL (API* WTClose_Func)(HCTX); -typedef BOOL (API* WTPacket_Func)(HCTX, UINT, LPVOID); - -WTInfoW_Func WTInfo; -WTOpenW_Func WTOpen; -WTClose_Func WTClose; -WTPacket_Func WTPacket; - -} // anonymous namespace - -PenAPI::PenAPI() - : m_wintabLib(nullptr) -{ -} - -PenAPI::~PenAPI() -{ - if (!m_wintabLib) - return; - - base::unload_dll(m_wintabLib); - m_wintabLib = nullptr; -} - -HCTX PenAPI::open(HWND hwnd) -{ - if (!m_wintabLib && !loadWintab()) - return nullptr; - - // Log Wintab ID - { - UINT nchars = WTInfo(WTI_INTERFACE, IFC_WINTABID, nullptr); - if (nchars > 0 && nchars < 1024) { - std::vector buf(nchars+1, 0); - WTInfo(WTI_INTERFACE, IFC_WINTABID, &buf[0]); - LOG("PEN: Wintab ID \"%s\"\n", base::to_utf8(&buf[0]).c_str()); - } - } - - // Log Wintab version for debugging purposes - { - WORD specVer = 0; - WORD implVer = 0; - UINT options = 0; - WTInfo(WTI_INTERFACE, IFC_SPECVERSION, &specVer); - WTInfo(WTI_INTERFACE, IFC_IMPLVERSION, &implVer); - WTInfo(WTI_INTERFACE, IFC_CTXOPTIONS, &options); - LOG("PEN: Wintab spec v%d.%d impl v%d.%d options 0x%x\n", - (specVer & 0xff00) >> 8, (specVer & 0xff), - (implVer & 0xff00) >> 8, (implVer & 0xff), options); - } - - LOGCONTEXTW logctx; - memset(&logctx, 0, sizeof(LOGCONTEXTW)); - UINT infoRes = WTInfo(WTI_DEFSYSCTX, 0, &logctx); - - // TODO Sometimes we receive infoRes=88 from WTInfo and logctx.lcOptions=0 - // while sizeof(LOGCONTEXTW) is 212 - ASSERT(infoRes == sizeof(LOGCONTEXTW)); - ASSERT(logctx.lcOptions & CXO_SYSTEM); - -#if 0 // We shouldn't bypass WTOpen() if the return value from - // WTInfo() isn't the expected one, WTOpen() should just fail - // anyway. - if (infoRes != sizeof(LOGCONTEXTW)) { - LOG(ERROR) - << "PEN: Not supported WTInfo:\n" - << " Expected context size: " << sizeof(LOGCONTEXTW) << "\n" - << " Actual context size: " << infoRes << "\n" - << " Options: " << logctx.lcOptions << ")\n"; - return nullptr; - } -#endif - - logctx.lcOptions |= - CXO_MESSAGES | - CXO_CSRMESSAGES; - logctx.lcPktData = PACKETDATA; - logctx.lcPktMode = PACKETMODE; - logctx.lcMoveMask = PACKETDATA; - - LOG("PEN: Opening context, options 0x%x\n", logctx.lcOptions); - HCTX ctx = WTOpen(hwnd, &logctx, TRUE); - if (!ctx) { - LOG("PEN: Error attaching pen to display\n"); - return nullptr; - } - - LOG("PEN: Pen attached to display, new context %p\n", ctx); - return ctx; -} - -void PenAPI::close(HCTX ctx) -{ - LOG("PEN: Closing context %p\n", ctx); - if (ctx) { - ASSERT(m_wintabLib); - LOG("PEN: Pen detached from window\n"); - WTClose(ctx); - } -} - -bool PenAPI::packet(HCTX ctx, UINT serial, LPVOID packet) -{ - return (WTPacket(ctx, serial, packet) ? true: false); -} - -bool PenAPI::loadWintab() -{ - ASSERT(!m_wintabLib); - - m_wintabLib = base::load_dll("wintab32.dll"); - if (!m_wintabLib) { - LOG(ERROR) << "PEN: wintab32.dll is not present\n"; - return false; - } - - if (isBuggyDll()) { - base::unload_dll(m_wintabLib); - m_wintabLib = nullptr; - return false; - } - - WTInfo = base::get_dll_proc(m_wintabLib, "WTInfoW"); - WTOpen = base::get_dll_proc(m_wintabLib, "WTOpenW"); - WTClose = base::get_dll_proc(m_wintabLib, "WTClose"); - WTPacket = base::get_dll_proc(m_wintabLib, "WTPacket"); - if (!WTInfo || !WTOpen || !WTClose || !WTPacket) { - LOG(ERROR) << "PEN: wintab32.dll does not contain all required functions\n"; - return false; - } - - LOG("PEN: Wintab library loaded\n"); - return true; -} - -bool PenAPI::isBuggyDll() -{ - ASSERT(m_wintabLib); - - WCHAR wpath[MAX_PATH]; - memset(wpath, 0, sizeof(wpath)); - GetModuleFileNameW((HMODULE)m_wintabLib, wpath, sizeof(wpath) / sizeof(WCHAR)); - - // Ugly hack to bypass the buggy WALTOP International Corp .dll that - // hangs Aseprite completely when we call its WTInfo function. - std::string path = base::to_utf8(wpath); - if (base::is_file(path)) { - std::string checksum = - base::convert_to(base::Sha1::calculateFromFile(path)); - LOG("PEN: SHA1 <%s> of <%s>\n", checksum.c_str(), path.c_str()); - if (checksum == "a3ba0d9c0f5d8b9f4070981b243a80579f8be105") - return true; - } - return false; -} - -} // namespace os diff --git a/src/os/win/pen.h b/src/os/win/pen.h deleted file mode 100644 index 665356ecb..000000000 --- a/src/os/win/pen.h +++ /dev/null @@ -1,42 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_PEN_H_INCLUDED -#define OS_WIN_PEN_H_INCLUDED -#pragma once - -#include "base/dll.h" - -#include -#include "wacom/wintab.h" - -#define PACKETDATA (PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE) -#define PACKETMODE (PK_BUTTONS) -#include "wacom/pktdef.h" - -namespace os { - - // Wintab API wrapper - // Read http://www.wacomeng.com/windows/docs/Wintab_v140.htm for more information. - class PenAPI { - public: - PenAPI(); - ~PenAPI(); - - HCTX open(HWND hwnd); - void close(HCTX ctx); - bool packet(HCTX ctx, UINT serial, LPVOID packet); - - private: - bool loadWintab(); - bool isBuggyDll(); - - base::dll m_wintabLib; - }; - -} // namespace os - -#endif diff --git a/src/os/win/system.h b/src/os/win/system.h deleted file mode 100644 index ab88481c3..000000000 --- a/src/os/win/system.h +++ /dev/null @@ -1,43 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_SYSTEM_H -#define OS_WIN_SYSTEM_H -#pragma once - -#include "os/common/system.h" -#include "os/win/pen.h" -#include "os/win/winapi.h" - -namespace os { - -bool win_is_key_pressed(KeyScancode scancode); -int win_get_unicode_from_scancode(KeyScancode scancode); - -class WindowSystem : public CommonSystem { -public: - WindowSystem() { } - ~WindowSystem() { } - - WinAPI& winApi() { return m_winApi; } - PenAPI& penApi() { return m_penApi; } - - bool isKeyPressed(KeyScancode scancode) override { - return win_is_key_pressed(scancode); - } - - int getUnicodeFromScancode(KeyScancode scancode) override { - return win_get_unicode_from_scancode(scancode); - } - -private: - WinAPI m_winApi; - PenAPI m_penApi; -}; - -} // namespace os - -#endif diff --git a/src/os/win/winapi.cpp b/src/os/win/winapi.cpp deleted file mode 100644 index 069480cc0..000000000 --- a/src/os/win/winapi.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/win/winapi.h" - -namespace os { - -#define GET_PROC(dll, name) \ - name = base::get_dll_proc(dll, #name) - -WinAPI::WinAPI() - : EnableMouseInPointer(nullptr) - , IsMouseInPointerEnabled(nullptr) - , GetPointerInfo(nullptr) - , GetPointerPenInfo(nullptr) - , CreateInteractionContext(nullptr) - , DestroyInteractionContext(nullptr) - , StopInteractionContext(nullptr) - , RegisterOutputCallbackInteractionContext(nullptr) - , AddPointerInteractionContext(nullptr) - , RemovePointerInteractionContext(nullptr) - , SetInteractionConfigurationInteractionContext(nullptr) - , ProcessPointerFramesInteractionContext(nullptr) - , m_user32(nullptr) - , m_ninput(nullptr) -{ - m_user32 = base::load_dll("user32.dll"); - m_ninput = base::load_dll("ninput.dll"); - if (m_user32) { - GET_PROC(m_user32, EnableMouseInPointer); - GET_PROC(m_user32, IsMouseInPointerEnabled); - GET_PROC(m_user32, GetPointerInfo); - GET_PROC(m_user32, GetPointerPenInfo); - } - if (m_ninput) { - GET_PROC(m_ninput, CreateInteractionContext); - GET_PROC(m_ninput, DestroyInteractionContext); - GET_PROC(m_ninput, StopInteractionContext); - GET_PROC(m_ninput, RegisterOutputCallbackInteractionContext); - GET_PROC(m_ninput, AddPointerInteractionContext); - GET_PROC(m_ninput, RemovePointerInteractionContext); - GET_PROC(m_ninput, SetInteractionConfigurationInteractionContext); - GET_PROC(m_ninput, SetPropertyInteractionContext); - GET_PROC(m_ninput, ProcessPointerFramesInteractionContext); - } -} - -WinAPI::~WinAPI() -{ - if (m_user32) { - base::unload_dll(m_user32); - m_user32 = nullptr; - } - if (m_ninput) { - base::unload_dll(m_ninput); - m_ninput = nullptr; - } -} - -} // namespace os diff --git a/src/os/win/winapi.h b/src/os/win/winapi.h deleted file mode 100644 index 6d7222b99..000000000 --- a/src/os/win/winapi.h +++ /dev/null @@ -1,79 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_WINAPI_H_INCLUDED -#define OS_WIN_WINAPI_H_INCLUDED -#pragma once - -#include "base/dll.h" - -#include -#include - -namespace os { - - typedef BOOL (WINAPI* EnableMouseInPointer_Func)(BOOL fEnable); - typedef BOOL (WINAPI* IsMouseInPointerEnabled_Func)(void); - typedef BOOL (WINAPI* GetPointerInfo_Func)(UINT32 pointerId, POINTER_INFO* pointerInfo); - typedef BOOL (WINAPI* GetPointerPenInfo_Func)(UINT32 pointerId, POINTER_PEN_INFO* penInfo); - - typedef HRESULT (WINAPI* CreateInteractionContext_Func)(HINTERACTIONCONTEXT* interactionContext); - typedef HRESULT (WINAPI* DestroyInteractionContext_Func)(HINTERACTIONCONTEXT interactionContext); - typedef HRESULT (WINAPI* StopInteractionContext_Func)(HINTERACTIONCONTEXT interactionContext); - typedef HRESULT (WINAPI* RegisterOutputCallbackInteractionContext_Func)( - HINTERACTIONCONTEXT interactionContext, - INTERACTION_CONTEXT_OUTPUT_CALLBACK outputCallback, - void* clientData); - typedef HRESULT (WINAPI* AddPointerInteractionContext_Func)( - HINTERACTIONCONTEXT interactionContext, - UINT32 pointerId); - typedef HRESULT (WINAPI* RemovePointerInteractionContext_Func)( - HINTERACTIONCONTEXT interactionContext, - UINT32 pointerId); - typedef HRESULT (WINAPI* SetInteractionConfigurationInteractionContext_Func)( - HINTERACTIONCONTEXT interactionContext, - UINT32 configurationCount, - const INTERACTION_CONTEXT_CONFIGURATION* configuration); - typedef HRESULT (WINAPI* SetPropertyInteractionContext_Func)( - HINTERACTIONCONTEXT interactionContext, - INTERACTION_CONTEXT_PROPERTY contextProperty, - UINT32 value); - typedef HRESULT (WINAPI* ProcessPointerFramesInteractionContext_Func)( - HINTERACTIONCONTEXT interactionContext, - UINT32 entriesCount, - UINT32 pointerCount, - const POINTER_INFO* pointerInfo); - - class WinAPI { - public: - WinAPI(); - ~WinAPI(); - - // These functions are availble only since Windows 8 - EnableMouseInPointer_Func EnableMouseInPointer; - IsMouseInPointerEnabled_Func IsMouseInPointerEnabled; - GetPointerInfo_Func GetPointerInfo; - GetPointerPenInfo_Func GetPointerPenInfo; - - // InteractionContext introduced on Windows 8 - CreateInteractionContext_Func CreateInteractionContext; - DestroyInteractionContext_Func DestroyInteractionContext; - StopInteractionContext_Func StopInteractionContext; - RegisterOutputCallbackInteractionContext_Func RegisterOutputCallbackInteractionContext; - AddPointerInteractionContext_Func AddPointerInteractionContext; - RemovePointerInteractionContext_Func RemovePointerInteractionContext; - SetInteractionConfigurationInteractionContext_Func SetInteractionConfigurationInteractionContext; - SetPropertyInteractionContext_Func SetPropertyInteractionContext; - ProcessPointerFramesInteractionContext_Func ProcessPointerFramesInteractionContext; - - private: - base::dll m_user32; - base::dll m_ninput; - }; - -} // namespace os - -#endif diff --git a/src/os/win/window.cpp b/src/os/win/window.cpp deleted file mode 100644 index 7c49e89c2..000000000 --- a/src/os/win/window.cpp +++ /dev/null @@ -1,1652 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/win/window.h" - -#include -#include -#include -#include - -#include "base/base.h" -#include "base/debug.h" -#include "base/log.h" -#include "gfx/size.h" -#include "os/event.h" -#include "os/native_cursor.h" -#include "os/win/keys.h" -#include "os/win/system.h" -#include "os/win/window_dde.h" - -#define OS_WND_CLASS_NAME L"Aseprite.Window" - -#define KEY_TRACE(...) -#define MOUSE_TRACE(...) -#define TOUCH_TRACE(...) - -#define kFingerAsMouseTimeout 50 - -// Gets the window client are in absolute/screen coordinates -#define ABS_CLIENT_RC(rc) \ - RECT rc; \ - GetClientRect(m_hwnd, &rc); \ - MapWindowPoints(m_hwnd, NULL, (POINT*)&rc, 2) - -#ifndef INTERACTION_CONTEXT_PROPERTY_MEASUREMENT_UNITS_SCREEN -#define INTERACTION_CONTEXT_PROPERTY_MEASUREMENT_UNITS_SCREEN 1 -#endif - -namespace os { - -static PointerType wt_packet_pkcursor_to_pointer_type(int pkCursor) -{ - switch (pkCursor) { - case 0: - case 3: - return PointerType::Cursor; - case 1: - case 4: - return PointerType::Pen; - case 2: - case 5: - case 6: // Undocumented: Inverted stylus when EnableMouseInPointer() is on - return PointerType::Eraser; - } - return PointerType::Unknown; -} - -WinWindow::Touch::Touch() - : fingers(0) - , canBeMouse(false) - , asMouse(false) - , timerID(0) -{ -} - -WinWindow::WinWindow(int width, int height, int scale) - : m_hwnd(nullptr) - , m_hcursor(nullptr) - , m_clientSize(1, 1) - , m_restoredSize(0, 0) - , m_scale(scale) - , m_isCreated(false) - , m_translateDeadKeys(false) - , m_hasMouse(false) - , m_captureMouse(false) - , m_customHcursor(false) - , m_usePointerApi(false) - , m_lastPointerId(0) - , m_ictx(nullptr) - , m_ignoreRandomMouseEvents(0) - // True by default, we prefer to interpret one finger as mouse movement - , m_touch(new Touch) -#if OS_USE_POINTER_API_FOR_MOUSE - , m_emulateDoubleClick(false) - , m_doubleClickMsecs(GetDoubleClickTime()) - , m_lastPointerDownTime(0) - , m_lastPointerDownButton(Event::NoneButton) - , m_pointerDownCount(0) -#endif - , m_hpenctx(nullptr) - , m_pointerType(PointerType::Unknown) - , m_pressure(0.0) -{ - auto& winApi = system()->winApi(); - if (winApi.EnableMouseInPointer && - winApi.IsMouseInPointerEnabled && - winApi.GetPointerInfo && - winApi.GetPointerPenInfo) { - // Do not enable pointer API for mouse events because: - // - Wacom driver doesn't inform their messages in a correct - // pointer API format (events from pen are reported as mouse - // events and without eraser tip information). - // - We have to emulate the double-click for the regular mouse - // (search for m_emulateDoubleClick). - // - Double click with Wacom stylus doesn't work. -#if OS_USE_POINTER_API_FOR_MOUSE - if (!winApi.IsMouseInPointerEnabled()) { - // Prefer pointer messages (WM_POINTER*) since Windows 8 instead - // of mouse messages (WM_MOUSE*) - winApi.EnableMouseInPointer(TRUE); - m_emulateDoubleClick = - (winApi.IsMouseInPointerEnabled() ? true: false); - } -#endif - - // Initialize a Interaction Context to convert WM_POINTER messages - // into gestures processed by handleInteractionContextOutput(). - if (winApi.CreateInteractionContext && - winApi.RegisterOutputCallbackInteractionContext && - winApi.SetInteractionConfigurationInteractionContext) { - HRESULT hr = winApi.CreateInteractionContext(&m_ictx); - if (SUCCEEDED(hr)) { - hr = winApi.RegisterOutputCallbackInteractionContext( - m_ictx, &WinWindow::staticInteractionContextCallback, this); - } - if (SUCCEEDED(hr)) { - INTERACTION_CONTEXT_CONFIGURATION cfg[] = { - { INTERACTION_ID_MANIPULATION, - INTERACTION_CONFIGURATION_FLAG_MANIPULATION | - INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_X | - INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_Y | - INTERACTION_CONFIGURATION_FLAG_MANIPULATION_SCALING | - INTERACTION_CONFIGURATION_FLAG_MANIPULATION_TRANSLATION_INERTIA | - INTERACTION_CONFIGURATION_FLAG_MANIPULATION_SCALING_INERTIA }, - { INTERACTION_ID_TAP, - INTERACTION_CONFIGURATION_FLAG_TAP | - INTERACTION_CONFIGURATION_FLAG_TAP_DOUBLE }, - { INTERACTION_ID_SECONDARY_TAP, - INTERACTION_CONFIGURATION_FLAG_SECONDARY_TAP }, - { INTERACTION_ID_HOLD, - INTERACTION_CONFIGURATION_FLAG_NONE }, - { INTERACTION_ID_DRAG, - INTERACTION_CONFIGURATION_FLAG_NONE }, - { INTERACTION_ID_CROSS_SLIDE, - INTERACTION_CONFIGURATION_FLAG_NONE } - }; - hr = winApi.SetInteractionConfigurationInteractionContext( - m_ictx, sizeof(cfg) / sizeof(INTERACTION_CONTEXT_CONFIGURATION), cfg); - } - if (SUCCEEDED(hr)) { - hr = winApi.SetPropertyInteractionContext( - m_ictx, - INTERACTION_CONTEXT_PROPERTY_MEASUREMENT_UNITS, - INTERACTION_CONTEXT_PROPERTY_MEASUREMENT_UNITS_SCREEN); - } - } - - m_usePointerApi = true; - } - - registerClass(); - - // The HWND returned by CreateWindowEx() is different than the - // HWND used in WM_CREATE message. - m_hwnd = createHwnd(this, width, height); - if (!m_hwnd) - throw std::runtime_error("Error creating window"); - - SetWindowLongPtr(m_hwnd, GWLP_USERDATA, - reinterpret_cast(this)); - - // This flag is used to avoid calling T::resizeImpl() when we - // add the scrollbars to the window. (As the T type could not be - // fully initialized yet.) - m_isCreated = true; -} - -WinWindow::~WinWindow() -{ - auto& winApi = system()->winApi(); - if (m_ictx && winApi.DestroyInteractionContext) - winApi.DestroyInteractionContext(m_ictx); - - if (m_hwnd) - DestroyWindow(m_hwnd); -} - -void WinWindow::queueEvent(Event& ev) -{ - onQueueEvent(ev); -} - -void WinWindow::setScale(int scale) -{ - m_scale = scale; - onResize(m_clientSize); -} - -void WinWindow::setVisible(bool visible) -{ - if (visible) { - ShowWindow(m_hwnd, SW_SHOWNORMAL); - UpdateWindow(m_hwnd); - DrawMenuBar(m_hwnd); - } - else - ShowWindow(m_hwnd, SW_HIDE); -} - -void WinWindow::maximize() -{ - ShowWindow(m_hwnd, SW_MAXIMIZE); -} - -bool WinWindow::isMaximized() const -{ - return (IsZoomed(m_hwnd) ? true: false); -} - -bool WinWindow::isMinimized() const -{ - return (GetWindowLong(m_hwnd, GWL_STYLE) & WS_MINIMIZE ? true: false); -} - -gfx::Size WinWindow::clientSize() const -{ - return m_clientSize; -} - -gfx::Size WinWindow::restoredSize() const -{ - return m_restoredSize; -} - -void WinWindow::setTitle(const std::string& title) -{ - SetWindowText(m_hwnd, base::from_utf8(title).c_str()); -} - -void WinWindow::captureMouse() -{ - m_captureMouse = true; - - if (GetCapture() != m_hwnd) { - MOUSE_TRACE("SetCapture\n"); - SetCapture(m_hwnd); - } -} - -void WinWindow::releaseMouse() -{ - m_captureMouse = false; - - if (GetCapture() == m_hwnd) { - MOUSE_TRACE("ReleaseCapture\n"); - ReleaseCapture(); - } -} - -void WinWindow::setMousePosition(const gfx::Point& position) -{ - POINT pos = { position.x * m_scale, - position.y * m_scale }; - ClientToScreen(m_hwnd, &pos); - SetCursorPos(pos.x, pos.y); -} - -bool WinWindow::setNativeMouseCursor(NativeCursor cursor) -{ - HCURSOR hcursor = NULL; - - switch (cursor) { - case kNoCursor: - // Do nothing, just set to null - break; - case kArrowCursor: - hcursor = LoadCursor(NULL, IDC_ARROW); - break; - case kCrosshairCursor: - hcursor = LoadCursor(NULL, IDC_CROSS); - break; - case kIBeamCursor: - hcursor = LoadCursor(NULL, IDC_IBEAM); - break; - case kWaitCursor: - hcursor = LoadCursor(NULL, IDC_WAIT); - break; - case kLinkCursor: - hcursor = LoadCursor(NULL, IDC_HAND); - break; - case kHelpCursor: - hcursor = LoadCursor(NULL, IDC_HELP); - break; - case kForbiddenCursor: - hcursor = LoadCursor(NULL, IDC_NO); - break; - case kMoveCursor: - hcursor = LoadCursor(NULL, IDC_SIZEALL); - break; - case kSizeNCursor: - case kSizeNSCursor: - case kSizeSCursor: - hcursor = LoadCursor(NULL, IDC_SIZENS); - break; - case kSizeECursor: - case kSizeWCursor: - case kSizeWECursor: - hcursor = LoadCursor(NULL, IDC_SIZEWE); - break; - case kSizeNWCursor: - case kSizeSECursor: - hcursor = LoadCursor(NULL, IDC_SIZENWSE); - break; - case kSizeNECursor: - case kSizeSWCursor: - hcursor = LoadCursor(NULL, IDC_SIZENESW); - break; - } - - return setCursor(hcursor, false); -} - -bool WinWindow::setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale) -{ - ASSERT(surface); - - SurfaceFormatData format; - surface->getFormat(&format); - - // Only for 32bpp surfaces - if (format.bitsPerPixel != 32) - return false; - - // Based on the following article "How To Create an Alpha - // Blended Cursor or Icon in Windows XP": - // https://support.microsoft.com/en-us/kb/318876 - - int w = scale*surface->width(); - int h = scale*surface->height(); - - BITMAPV5HEADER bi; - ZeroMemory(&bi, sizeof(BITMAPV5HEADER)); - bi.bV5Size = sizeof(BITMAPV5HEADER); - bi.bV5Width = w; - bi.bV5Height = h; - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5RedMask = 0x00ff0000; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5BlueMask = 0x000000ff; - bi.bV5AlphaMask = 0xff000000; - - uint32_t* bits; - HDC hdc = GetDC(nullptr); - HBITMAP hbmp = CreateDIBSection( - hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, - (void**)&bits, NULL, (DWORD)0); - ReleaseDC(nullptr, hdc); - if (!hbmp) - return false; - - for (int y=0; ygetData(0, (h-1-y)/scale); - for (int x=0, u=0; x> format.alphaShift) << 24) | - (((c & format.redMask ) >> format.redShift ) << 16) | - (((c & format.greenMask) >> format.greenShift) << 8) | - (((c & format.blueMask ) >> format.blueShift )); - if (++u == scale) { - u = 0; - ++ptr; - } - } - } - - // Create an empty mask bitmap. - HBITMAP hmonobmp = CreateBitmap(w, h, 1, 1, nullptr); - if (!hmonobmp) { - DeleteObject(hbmp); - return false; - } - - ICONINFO ii; - ii.fIcon = FALSE; - ii.xHotspot = scale*focus.x + scale/2; - ii.yHotspot = scale*focus.y + scale/2; - ii.hbmMask = hmonobmp; - ii.hbmColor = hbmp; - - HCURSOR hcursor = CreateIconIndirect(&ii); - - DeleteObject(hbmp); - DeleteObject(hmonobmp); - - return setCursor(hcursor, true); -} - -void WinWindow::updateWindow(const gfx::Rect& bounds) -{ - RECT rc = { bounds.x*m_scale, - bounds.y*m_scale, - bounds.x*m_scale+bounds.w*m_scale, - bounds.y*m_scale+bounds.h*m_scale }; - InvalidateRect(m_hwnd, &rc, FALSE); - UpdateWindow(m_hwnd); -} - -std::string WinWindow::getLayout() -{ - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - if (GetWindowPlacement(m_hwnd, &wp)) { - std::ostringstream s; - s << 1 << ' ' - << wp.flags << ' ' - << wp.showCmd << ' ' - << wp.ptMinPosition.x << ' ' - << wp.ptMinPosition.y << ' ' - << wp.ptMaxPosition.x << ' ' - << wp.ptMaxPosition.y << ' ' - << wp.rcNormalPosition.left << ' ' - << wp.rcNormalPosition.top << ' ' - << wp.rcNormalPosition.right << ' ' - << wp.rcNormalPosition.bottom; - return s.str(); - } - return ""; -} - -void WinWindow::setLayout(const std::string& layout) -{ - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - - std::istringstream s(layout); - int ver; - s >> ver; - if (ver == 1) { - s >> wp.flags - >> wp.showCmd - >> wp.ptMinPosition.x - >> wp.ptMinPosition.y - >> wp.ptMaxPosition.x - >> wp.ptMaxPosition.y - >> wp.rcNormalPosition.left - >> wp.rcNormalPosition.top - >> wp.rcNormalPosition.right - >> wp.rcNormalPosition.bottom; - } - else - return; - - if (SetWindowPlacement(m_hwnd, &wp)) { - // TODO use the return value - } -} - -void WinWindow::setTranslateDeadKeys(bool state) -{ - m_translateDeadKeys = state; - - // Here we clear dead keys so we don't get those keys in the new - // "translate dead keys" state. E.g. If we focus a text entry - // field and the translation of dead keys is enabled, we don't - // want to get previous dead keys. The same in case we leave the - // text field with a pending dead key, that dead key must be - // discarded. - VkToUnicode tu; - if (tu) { - tu.toUnicode(VK_SPACE, 0); - if (tu.size() != 0) - tu.toUnicode(VK_SPACE, 0); - } -} - -void WinWindow::setInterpretOneFingerGestureAsMouseMovement(bool state) -{ - if (state) { - if (!m_touch) - m_touch = new Touch; - } - else if (m_touch) { - killTouchTimer(); - delete m_touch; - m_touch = nullptr; - } -} - -bool WinWindow::setCursor(HCURSOR hcursor, bool custom) -{ - SetCursor(hcursor); - if (m_hcursor && m_customHcursor) - DestroyIcon(m_hcursor); - m_hcursor = hcursor; - m_customHcursor = custom; - return (hcursor ? true: false); -} - -LRESULT WinWindow::wndProc(UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) { - - case WM_CREATE: - LOG("WIN: Creating window %p\n", m_hwnd); - - if (system()->useWintabAPI()) { - // Attach Wacom context - m_hpenctx = system()->penApi().open(m_hwnd); - } - break; - - case WM_DESTROY: - LOG("WIN: Destroying window %p (pen context %p)\n", - m_hwnd, m_hpenctx); - - if (m_hpenctx) { - system()->penApi().close(m_hpenctx); - m_hpenctx = nullptr; - } - break; - - case WM_SETCURSOR: - if (LOWORD(lparam) == HTCLIENT) { - SetCursor(m_hcursor); - return TRUE; - } - break; - - case WM_CLOSE: { - Event ev; - ev.setType(Event::CloseDisplay); - queueEvent(ev); - - // Don't close the window, it must be closed manually after - // the CloseDisplay event is processed. - return 0; - } - - case WM_PAINT: - if (m_isCreated) { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(m_hwnd, &ps); - onPaint(hdc); - EndPaint(m_hwnd, &ps); - return true; - } - break; - - case WM_SIZE: - if (m_isCreated) { - int w = GET_X_LPARAM(lparam); - int h = GET_Y_LPARAM(lparam); - - if (w > 0 && h > 0) { - m_clientSize.w = w; - m_clientSize.h = h; - onResize(m_clientSize); - } - - WINDOWPLACEMENT pl; - pl.length = sizeof(pl); - if (GetWindowPlacement(m_hwnd, &pl)) { - m_restoredSize = gfx::Size( - pl.rcNormalPosition.right - pl.rcNormalPosition.left, - pl.rcNormalPosition.bottom - pl.rcNormalPosition.top); - } - } - break; - - // Mouse and Trackpad Messages - - case WM_MOUSEMOVE: { - Event ev; - mouseEvent(lparam, ev); - - MOUSE_TRACE("MOUSEMOVE xy=%d,%d\n", - ev.position().x, ev.position().y); - - if (m_ignoreRandomMouseEvents > 0) { - MOUSE_TRACE(" - IGNORED\n"); - --m_ignoreRandomMouseEvents; - break; - } - - if (!m_hasMouse) { - m_hasMouse = true; - - ev.setType(Event::MouseEnter); - queueEvent(ev); - - MOUSE_TRACE("-> Event::MouseEnter\n"); - - // Track mouse to receive WM_MOUSELEAVE message. - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = m_hwnd; - _TrackMouseEvent(&tme); - } - - if (m_pointerType != PointerType::Unknown) { - ev.setPointerType(m_pointerType); - ev.setPressure(m_pressure); - } - - ev.setType(Event::MouseMove); - queueEvent(ev); - break; - } - - case WM_NCMOUSEMOVE: - case WM_MOUSELEAVE: - if (m_hasMouse) { - m_hasMouse = false; - - Event ev; - ev.setType(Event::MouseLeave); - ev.setModifiers(get_modifiers_from_last_win32_message()); - queueEvent(ev); - - MOUSE_TRACE("-> Event::MouseLeave\n"); - } - break; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_XBUTTONDOWN: { - Event ev; - mouseEvent(lparam, ev); - ev.setType(Event::MouseDown); - ev.setButton( - msg == WM_LBUTTONDOWN ? Event::LeftButton: - msg == WM_RBUTTONDOWN ? Event::RightButton: - msg == WM_MBUTTONDOWN ? Event::MiddleButton: - msg == WM_XBUTTONDOWN && GET_XBUTTON_WPARAM(wparam) == 1 ? Event::X1Button: - msg == WM_XBUTTONDOWN && GET_XBUTTON_WPARAM(wparam) == 2 ? Event::X2Button: - Event::NoneButton); - - if (m_pointerType != PointerType::Unknown) { - ev.setPointerType(m_pointerType); - ev.setPressure(m_pressure); - } - queueEvent(ev); - - MOUSE_TRACE("BUTTONDOWN xy=%d,%d button=%d\n", - ev.position().x, ev.position().y, - ev.button()); - break; - } - - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - case WM_XBUTTONUP: { - Event ev; - mouseEvent(lparam, ev); - ev.setType(Event::MouseUp); - ev.setButton( - msg == WM_LBUTTONUP ? Event::LeftButton: - msg == WM_RBUTTONUP ? Event::RightButton: - msg == WM_MBUTTONUP ? Event::MiddleButton: - msg == WM_XBUTTONUP && GET_XBUTTON_WPARAM(wparam) == 1 ? Event::X1Button: - msg == WM_XBUTTONUP && GET_XBUTTON_WPARAM(wparam) == 2 ? Event::X2Button: - Event::NoneButton); - - if (m_pointerType != PointerType::Unknown) { - ev.setPointerType(m_pointerType); - ev.setPressure(m_pressure); - } - queueEvent(ev); - - MOUSE_TRACE("BUTTONUP xy=%d,%d button=%d\n", - ev.position().x, ev.position().y, - ev.button()); - - // Avoid popup menu for scrollbars - if (msg == WM_RBUTTONUP) - return 0; - - break; - } - - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: { - Event ev; - mouseEvent(lparam, ev); - ev.setType(Event::MouseDoubleClick); - ev.setButton( - msg == WM_LBUTTONDBLCLK ? Event::LeftButton: - msg == WM_RBUTTONDBLCLK ? Event::RightButton: - msg == WM_MBUTTONDBLCLK ? Event::MiddleButton: - msg == WM_XBUTTONDBLCLK && GET_XBUTTON_WPARAM(wparam) == 1 ? Event::X1Button: - msg == WM_XBUTTONDBLCLK && GET_XBUTTON_WPARAM(wparam) == 2 ? Event::X2Button: - Event::NoneButton); - - if (m_pointerType != PointerType::Unknown) { - ev.setPointerType(m_pointerType); - ev.setPressure(m_pressure); - } - queueEvent(ev); - - MOUSE_TRACE("BUTTONDBLCLK xy=%d,%d button=%d\n", - ev.position().x, ev.position().y, - ev.button()); - break; - } - - case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: { - POINT pos = { GET_X_LPARAM(lparam), - GET_Y_LPARAM(lparam) }; - ScreenToClient(m_hwnd, &pos); - - Event ev; - ev.setType(Event::MouseWheel); - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setPosition(gfx::Point(pos.x, pos.y) / m_scale); - - int z = GET_WHEEL_DELTA_WPARAM(wparam); - if (ABS(z) >= WHEEL_DELTA) - z /= WHEEL_DELTA; - else { - // TODO use floating point numbers or something similar - // (so we could use: z /= double(WHEEL_DELTA)) - z = SGN(z); - } - - gfx::Point delta( - (msg == WM_MOUSEHWHEEL ? z: 0), - (msg == WM_MOUSEWHEEL ? -z: 0)); - ev.setWheelDelta(delta); - queueEvent(ev); - - MOUSE_TRACE("MOUSEWHEEL xy=%d,%d delta=%d,%d\n", - ev.position().x, ev.position().y, - ev.wheelDelta().x, ev.wheelDelta().y); - break; - } - - case WM_HSCROLL: - case WM_VSCROLL: { - POINT pos; - GetCursorPos(&pos); - ScreenToClient(m_hwnd, &pos); - - Event ev; - ev.setType(Event::MouseWheel); - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setPosition(gfx::Point(pos.x, pos.y) / m_scale); - - int bar = (msg == WM_HSCROLL ? SB_HORZ: SB_VERT); - int z = GetScrollPos(m_hwnd, bar); - - switch (LOWORD(wparam)) { - case SB_LEFT: - case SB_LINELEFT: - --z; - break; - case SB_PAGELEFT: - z -= 2; - break; - case SB_RIGHT: - case SB_LINERIGHT: - ++z; - break; - case SB_PAGERIGHT: - z += 2; - break; - case SB_THUMBPOSITION: - case SB_THUMBTRACK: - case SB_ENDSCROLL: - // Do nothing - break; - } - - gfx::Point delta( - (msg == WM_HSCROLL ? (z-50): 0), - (msg == WM_VSCROLL ? (z-50): 0)); - ev.setWheelDelta(delta); - - SetScrollPos(m_hwnd, bar, 50, FALSE); - queueEvent(ev); - - MOUSE_TRACE("HVSCROLL xy=%d,%d delta=%d,%d\n", - ev.position().x, ev.position().y, - ev.wheelDelta().x, ev.wheelDelta().y); - break; - } - - // Pointer API (since Windows 8.0) - - case WM_POINTERCAPTURECHANGED: { - MOUSE_TRACE("POINTERCAPTURECHANGED\n"); - releaseMouse(); - break; - } - - case WM_POINTERENTER: { - POINTER_INFO pi; - Event ev; - if (!pointerEvent(wparam, ev, pi)) - break; - - MOUSE_TRACE("POINTERENTER id=%d xy=%d,%d\n", - pi.pointerId, ev.position().x, ev.position().y); - - if (pi.pointerType == PT_TOUCH || pi.pointerType == PT_PEN) { - auto& winApi = system()->winApi(); - if (m_ictx && winApi.AddPointerInteractionContext) { - winApi.AddPointerInteractionContext(m_ictx, pi.pointerId); - - if (m_touch && pi.pointerType == PT_TOUCH && - !m_touch->asMouse) { - ++m_touch->fingers; - TOUCH_TRACE("POINTERENTER fingers=%d\n", m_touch->fingers); - if (m_touch->fingers == 1) { - waitTimerToConvertFingerAsMouseMovement(); - } - else if (m_touch->canBeMouse && m_touch->fingers >= 2) { - delegateFingerToInteractionContext(); - } - } - } - } - - if (!m_hasMouse) { - m_hasMouse = true; - - ev.setType(Event::MouseEnter); - queueEvent(ev); - - MOUSE_TRACE("-> Event::MouseEnter\n"); - } - return 0; - } - - case WM_POINTERLEAVE: { - POINTER_INFO pi; - Event ev; - if (!pointerEvent(wparam, ev, pi)) - break; - - MOUSE_TRACE("POINTERLEAVE id=%d\n", pi.pointerId); - - // After releasing a finger a WM_MOUSEMOVE event in the trackpad - // position is generated, we'll ignore that message. - if (m_touch) - m_ignoreRandomMouseEvents = 1; - else - m_ignoreRandomMouseEvents = 0; - - if (pi.pointerType == PT_TOUCH || pi.pointerType == PT_PEN) { - auto& winApi = system()->winApi(); - if (m_ictx && winApi.RemovePointerInteractionContext) { - winApi.RemovePointerInteractionContext(m_ictx, pi.pointerId); - - if (m_touch && pi.pointerType == PT_TOUCH) { - if (m_touch->fingers > 0) - --m_touch->fingers; - TOUCH_TRACE("POINTERLEAVE fingers=%d\n", m_touch->fingers); - if (m_touch->fingers == 0) { - if (m_touch->canBeMouse) - sendDelayedTouchEvents(); - else - clearDelayedTouchEvents(); - killTouchTimer(); - m_touch->asMouse = false; - } - } - } - } - -#if 0 // Don't generate MouseLeave from pen/touch messages - // TODO we should generate this message, but after this touch - // messages don't work anymore, so we have to fix that problem. - if (m_hasMouse) { - m_hasMouse = false; - - ev.setType(Event::MouseLeave); - queueEvent(ev); - - MOUSE_TRACE("-> Event::MouseLeave\n"); - return 0; - } -#endif - break; - } - - case WM_POINTERDOWN: { - POINTER_INFO pi; - Event ev; - if (!pointerEvent(wparam, ev, pi)) - break; - - if (pi.pointerType == PT_TOUCH || pi.pointerType == PT_PEN) { - auto& winApi = system()->winApi(); - if (m_ictx && winApi.ProcessPointerFramesInteractionContext) { - winApi.ProcessPointerFramesInteractionContext(m_ictx, 1, 1, &pi); - if (!m_touch && pi.pointerType == PT_TOUCH) - return 0; - } - } - - handlePointerButtonChange(ev, pi); - - MOUSE_TRACE("POINTERDOWN id=%d xy=%d,%d button=%d\n", - pi.pointerId, ev.position().x, ev.position().y, - ev.button()); - return 0; - } - - case WM_POINTERUP: { - POINTER_INFO pi; - Event ev; - if (!pointerEvent(wparam, ev, pi)) - break; - - if (pi.pointerType == PT_TOUCH || pi.pointerType == PT_PEN) { - auto& winApi = system()->winApi(); - if (m_ictx && winApi.ProcessPointerFramesInteractionContext) { - winApi.ProcessPointerFramesInteractionContext(m_ictx, 1, 1, &pi); - if (!m_touch && pi.pointerType == PT_TOUCH) - return 0; - } - } - - handlePointerButtonChange(ev, pi); - - MOUSE_TRACE("POINTERUP id=%d xy=%d,%d button=%d\n", - pi.pointerId, ev.position().x, ev.position().y, - ev.button()); - return 0; - } - - case WM_POINTERUPDATE: { - POINTER_INFO pi; - Event ev; - if (!pointerEvent(wparam, ev, pi)) - break; - - // See the comment for m_ignoreRandomMouseEvents variable, and - // why here is = 2. - m_ignoreRandomMouseEvents = 2; - - if (pi.pointerType == PT_TOUCH || pi.pointerType == PT_PEN) { - auto& winApi = system()->winApi(); - if (m_ictx && winApi.ProcessPointerFramesInteractionContext) { - winApi.ProcessPointerFramesInteractionContext(m_ictx, 1, 1, &pi); - if (!m_touch && pi.pointerType == PT_TOUCH) - return 0; - } - } - - if (!m_hasMouse) { - m_hasMouse = true; - - ev.setType(Event::MouseEnter); - queueEvent(ev); - - MOUSE_TRACE("-> Event::MouseEnter\n"); - } - - ev.setType(Event::MouseMove); - - if (m_touch && pi.pointerType == PT_TOUCH) { - TOUCH_TRACE("POINTERUPDATE canBeMouse=%d asMouse=%d\n", - m_touch->canBeMouse, - m_touch->asMouse); - if (!m_touch->asMouse) { - if (m_touch->canBeMouse) - m_touch->delayedEvents.push_back(ev); - else - return 0; - } - else - queueEvent(ev); - } - else - queueEvent(ev); - - handlePointerButtonChange(ev, pi); - - MOUSE_TRACE("POINTERUPDATE id=%d xy=%d,%d\n", - pi.pointerId, ev.position().x, ev.position().y); - return 0; - } - - case WM_POINTERWHEEL: - case WM_POINTERHWHEEL: { - POINTER_INFO pi; - Event ev; - if (!pointerEvent(wparam, ev, pi)) - break; - - ev.setType(Event::MouseWheel); - - int z = GET_WHEEL_DELTA_WPARAM(wparam); - if (ABS(z) >= WHEEL_DELTA) - z /= WHEEL_DELTA; - else { - // TODO use floating point numbers or something similar - // (so we could use: z /= double(WHEEL_DELTA)) - z = SGN(z); - } - - gfx::Point delta( - (msg == WM_POINTERHWHEEL ? z: 0), - (msg == WM_POINTERWHEEL ? -z: 0)); - ev.setWheelDelta(delta); - queueEvent(ev); - - MOUSE_TRACE("POINTERWHEEL xy=%d,%d delta=%d,%d\n", - ev.position().x, ev.position().y, - ev.wheelDelta().x, ev.wheelDelta().y); - - return 0; - } - - case WM_TIMER: - TOUCH_TRACE("TIMER %d\n", wparam); - if (m_touch && m_touch->timerID == wparam) { - killTouchTimer(); - - if (!m_touch->asMouse && - m_touch->canBeMouse && - m_touch->fingers == 1) { - TOUCH_TRACE("-> finger as mouse, sent %d events\n", - m_touch->delayedEvents.size()); - - convertFingerAsMouseMovement(); - } - else { - delegateFingerToInteractionContext(); - } - } - break; - - // Keyboard Messages - - case WM_SYSKEYDOWN: - case WM_KEYDOWN: { - int vk = wparam; - int scancode = (lparam >> 16) & 0xff; - bool sendMsg = true; - const KeyScancode ourScancode = win32vk_to_scancode(vk); - - // We only create one KeyDown event for modifiers. Bit 30 - // indicates the previous state of the key, if the modifier was - // already pressed don't generate the event. - if ((ourScancode >= kKeyFirstModifierScancode) && - (lparam & (1 << 30))) - return 0; - - Event ev; - ev.setType(Event::KeyDown); - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setScancode(ourScancode); - ev.setUnicodeChar(0); - ev.setRepeat(MAX(0, (lparam & 0xffff)-1)); - - KEY_TRACE("KEYDOWN vk=%d scancode=%d->%d modifiers=%d\n", - vk, scancode, ev.scancode(), ev.modifiers()); - - { - VkToUnicode tu; - if (tu) { - tu.toUnicode(vk, scancode); - if (tu.isDeadKey()) { - ev.setDeadKey(true); - ev.setUnicodeChar(tu[0]); - if (!m_translateDeadKeys) - tu.toUnicode(vk, scancode); // Call again to remove dead-key - } - else if (tu.size() > 0) { - sendMsg = false; - for (int chr : tu) { - ev.setUnicodeChar(chr); - queueEvent(ev); - - KEY_TRACE(" -> queued unicode char=%d <%c>\n", - ev.unicodeChar(), - ev.unicodeChar() ? ev.unicodeChar(): ' '); - } - } - } - } - - if (sendMsg) { - queueEvent(ev); - KEY_TRACE(" -> queued unicode char=%d <%c>\n", - ev.unicodeChar(), - ev.unicodeChar() ? ev.unicodeChar(): ' '); - } - - return 0; - } - - case WM_SYSKEYUP: - case WM_KEYUP: { - Event ev; - ev.setType(Event::KeyUp); - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setScancode(win32vk_to_scancode(wparam)); - ev.setUnicodeChar(0); - ev.setRepeat(MAX(0, (lparam & 0xffff)-1)); - queueEvent(ev); - - // TODO If we use native menus, this message should be given - // to the DefWindowProc() in some cases (e.g. F10 or Alt keys) - return 0; - } - - case WM_MENUCHAR: - // Avoid playing a sound when Alt+key is pressed and it's not in a native menu - return MAKELONG(0, MNC_CLOSE); - - case WM_DROPFILES: { - HDROP hdrop = (HDROP)(wparam); - base::paths files; - - int count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0); - for (int index=0; index 0) { - std::vector str(length+1); - DragQueryFile(hdrop, index, &str[0], str.size()); - files.push_back(base::to_utf8(&str[0])); - } - } - - DragFinish(hdrop); - - Event ev; - ev.setType(Event::DropFiles); - ev.setFiles(files); - queueEvent(ev); - break; - } - - case WM_NCCALCSIZE: { - if (wparam) { - // Scrollbars must be enabled and visible to get trackpad - // events of old drivers. So we cannot use ShowScrollBar() to - // hide them. This is a simple (maybe not so elegant) - // solution: Expand the client area to we overlap the - // scrollbars. In this way they are not visible, but we still - // get their messages. - NCCALCSIZE_PARAMS* cs = reinterpret_cast(lparam); - cs->rgrc[0].right += GetSystemMetrics(SM_CYVSCROLL); - cs->rgrc[0].bottom += GetSystemMetrics(SM_CYHSCROLL); - } - break; - } - - case WM_NCHITTEST: { - LRESULT result = CallWindowProc(DefWindowProc, m_hwnd, msg, wparam, lparam); - gfx::Point pt(GET_X_LPARAM(lparam), - GET_Y_LPARAM(lparam)); - - ABS_CLIENT_RC(rc); - gfx::Rect area(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); - - //LOG("NCHITTEST: %d %d - %d %d %d %d - %s\n", pt.x, pt.y, area.x, area.y, area.w, area.h, area.contains(pt) ? "true": "false"); - - // We ignore scrollbars so if the mouse is above them, we return - // as it's in the window client or resize area. (Remember that - // we have scroll bars are enabled and visible to receive - // trackpad messages only.) - if (result == HTHSCROLL) { - result = (area.contains(pt) ? HTCLIENT: HTBOTTOM); - } - else if (result == HTVSCROLL) { - result = (area.contains(pt) ? HTCLIENT: HTRIGHT); - } - - return result; - } - - // Wintab API Messages - - case WT_PROXIMITY: { - MOUSE_TRACE("WT_PROXIMITY\n"); - - bool entering_ctx = (LOWORD(lparam) ? true: false); - if (!entering_ctx) - m_pointerType = PointerType::Unknown; - break; - } - - case WT_CSRCHANGE: { // From Wintab 1.1 - auto& api = system()->penApi(); - UINT serial = wparam; - HCTX ctx = (HCTX)lparam; - PACKET packet; - - if (api.packet(ctx, serial, &packet)) - m_pointerType = wt_packet_pkcursor_to_pointer_type(packet.pkCursor); - else - m_pointerType = PointerType::Unknown; - - MOUSE_TRACE("WT_CSRCHANGE pointer=%d\n", m_pointerType); - break; - } - - case WT_PACKET: { - auto& api = system()->penApi(); - UINT serial = wparam; - HCTX ctx = (HCTX)lparam; - PACKET packet; - - if (api.packet(ctx, serial, &packet)) { - m_pressure = packet.pkNormalPressure / 1000.0; // TODO get the maximum value - m_pointerType = wt_packet_pkcursor_to_pointer_type(packet.pkCursor); - } - else - m_pointerType = PointerType::Unknown; - - MOUSE_TRACE("WT_PACKET pointer=%d m_pressure=%.16g\n", - m_pointerType, m_pressure); - break; - } - - } - - LRESULT result = FALSE; - if (handle_dde_messages(m_hwnd, msg, wparam, lparam, result)) - return result; - - return DefWindowProc(m_hwnd, msg, wparam, lparam); -} - -void WinWindow::mouseEvent(LPARAM lparam, Event& ev) -{ - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setPosition(gfx::Point( - GET_X_LPARAM(lparam) / m_scale, - GET_Y_LPARAM(lparam) / m_scale)); -} - -bool WinWindow::pointerEvent(WPARAM wparam, Event& ev, POINTER_INFO& pi) -{ - if (!m_usePointerApi) - return false; - - auto& winApi = system()->winApi(); - if (!winApi.GetPointerInfo(GET_POINTERID_WPARAM(wparam), &pi)) - return false; - - ABS_CLIENT_RC(rc); - - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setPosition(gfx::Point((pi.ptPixelLocation.x - rc.left) / m_scale, - (pi.ptPixelLocation.y - rc.top) / m_scale)); - - switch (pi.pointerType) { - case PT_MOUSE: { - MOUSE_TRACE("pi.pointerType PT_MOUSE\n"); - ev.setPointerType(PointerType::Mouse); - - // If we use EnableMouseInPointer(true), events from Wacom - // stylus came as PT_MOUSE instead of PT_PEN with eraser - // flag. This is just insane, EnableMouseInPointer(true) is not - // an option at the moment if we want proper support for Wacom - // events. - break; - } - case PT_TOUCH: { - MOUSE_TRACE("pi.pointerType PT_TOUCH\n"); - ev.setPointerType(PointerType::Touch); - break; - } - case PT_TOUCHPAD: { - MOUSE_TRACE("pi.pointerType PT_TOUCHPAD\n"); - ev.setPointerType(PointerType::Touchpad); - break; - } - case PT_PEN: { - MOUSE_TRACE("pi.pointerType PT_PEN\n"); - ev.setPointerType(PointerType::Pen); - - POINTER_PEN_INFO ppi; - if (winApi.GetPointerPenInfo(pi.pointerId, &ppi)) { - MOUSE_TRACE(" - ppi.penFlags = %d\n", ppi.penFlags); - if (ppi.penFlags & PEN_FLAG_ERASER) - ev.setPointerType(PointerType::Eraser); - } - break; - } - } - - m_lastPointerId = pi.pointerId; - return true; -} - -void WinWindow::handlePointerButtonChange(Event& ev, POINTER_INFO& pi) -{ - if (pi.ButtonChangeType == POINTER_CHANGE_NONE) { -#if OS_USE_POINTER_API_FOR_MOUSE - // Reset the counter of pointer down for the emulated double-click - if (m_emulateDoubleClick) - m_pointerDownCount = 0; -#endif - return; - } - - Event::MouseButton button = Event::NoneButton; - bool down = false; - - switch (pi.ButtonChangeType) { - case POINTER_CHANGE_FIRSTBUTTON_DOWN: - down = true; - case POINTER_CHANGE_FIRSTBUTTON_UP: - button = Event::LeftButton; - break; - case POINTER_CHANGE_SECONDBUTTON_DOWN: - down = true; - case POINTER_CHANGE_SECONDBUTTON_UP: - button = Event::RightButton; - break; - case POINTER_CHANGE_THIRDBUTTON_DOWN: - down = true; - case POINTER_CHANGE_THIRDBUTTON_UP: - button = Event::MiddleButton; - break; - case POINTER_CHANGE_FOURTHBUTTON_DOWN: - down = true; - case POINTER_CHANGE_FOURTHBUTTON_UP: - button = Event::X1Button; - break; - case POINTER_CHANGE_FIFTHBUTTON_DOWN: - down = true; - case POINTER_CHANGE_FIFTHBUTTON_UP: - button = Event::X2Button; - break; - } - - if (button == Event::NoneButton) - return; - - ev.setType(down ? Event::MouseDown: Event::MouseUp); - ev.setButton(button); - -#if OS_USE_POINTER_API_FOR_MOUSE - if (down && m_emulateDoubleClick) { - if (button != m_lastPointerDownButton) - m_pointerDownCount = 0; - - ++m_pointerDownCount; - - base::tick_t curTime = base::current_tick(); - if ((m_pointerDownCount == 2) && - (curTime - m_lastPointerDownTime) <= m_doubleClickMsecs) { - ev.setType(Event::MouseDoubleClick); - m_pointerDownCount = 0; - } - - m_lastPointerDownTime = curTime; - m_lastPointerDownButton = button; - } -#endif - - if (m_touch && pi.pointerType == PT_TOUCH) { - if (!m_touch->asMouse) { - if (m_touch->canBeMouse) { - // TODO Review why the ui layer needs a Event::MouseMove event - // before ButtonDown/Up events. - Event evMouseMove = ev; - evMouseMove.setType(Event::MouseMove); - m_touch->delayedEvents.push_back(evMouseMove); - m_touch->delayedEvents.push_back(ev); - } - return; - } - } - - queueEvent(ev); -} - -void WinWindow::handleInteractionContextOutput( - const INTERACTION_CONTEXT_OUTPUT* output) -{ - MOUSE_TRACE("%s (%d) xy=%.16g %.16g flags=%d type=%d\n", - output->interactionId == INTERACTION_ID_MANIPULATION ? "INTERACTION_ID_MANIPULATION": - output->interactionId == INTERACTION_ID_TAP ? "INTERACTION_ID_TAP": - output->interactionId == INTERACTION_ID_SECONDARY_TAP ? "INTERACTION_ID_SECONDARY_TAP": - output->interactionId == INTERACTION_ID_HOLD ? "INTERACTION_ID_HOLD": "INTERACTION_ID_???", - output->interactionId, - output->x, output->y, - output->interactionFlags, - output->inputType); - - // We use the InteractionContext to interpret touch gestures only - // and double tap with pen. - if ((output->inputType == PT_TOUCH - && (!m_touch - || (!m_touch->asMouse && !m_touch->canBeMouse) - || (output->arguments.tap.count == 2))) - || (output->inputType == PT_PEN && - output->interactionId == INTERACTION_ID_TAP && - output->arguments.tap.count == 2)) { - ABS_CLIENT_RC(rc); - - gfx::Point pos(int((output->x - rc.left) / m_scale), - int((output->y - rc.top) / m_scale)); - - Event ev; - ev.setModifiers(get_modifiers_from_last_win32_message()); - ev.setPosition(pos); - - bool hadMouse = m_hasMouse; - if (!m_hasMouse) { - m_hasMouse = true; - ev.setType(Event::MouseEnter); - queueEvent(ev); - } - - switch (output->interactionId) { - case INTERACTION_ID_MANIPULATION: { - MOUSE_TRACE(" - delta xy=%.16g %.16g scale=%.16g expansion=%.16g rotation=%.16g\n", - output->arguments.manipulation.delta.translationX, - output->arguments.manipulation.delta.translationY, - output->arguments.manipulation.delta.scale, - output->arguments.manipulation.delta.expansion, - output->arguments.manipulation.delta.rotation); - - gfx::Point delta(-int(output->arguments.manipulation.delta.translationX) / m_scale, - -int(output->arguments.manipulation.delta.translationY) / m_scale); - - if (output->interactionFlags & INTERACTION_FLAG_BEGIN) { - ev.setType(Event::MouseMove); - queueEvent(ev); - } - - ev.setType(Event::MouseWheel); - ev.setWheelDelta(delta); - ev.setPreciseWheel(true); - queueEvent(ev); - - ev.setType(Event::TouchMagnify); - ev.setMagnification(output->arguments.manipulation.delta.scale - 1.0); - queueEvent(ev); - break; - } - - case INTERACTION_ID_TAP: - MOUSE_TRACE(" - count=%d\n", output->arguments.tap.count); - - ev.setButton(Event::LeftButton); - ev.setType(Event::MouseMove); queueEvent(ev); - if (output->arguments.tap.count == 2) { - ev.setType(Event::MouseDoubleClick); queueEvent(ev); - } - else { - ev.setType(Event::MouseDown); queueEvent(ev); - ev.setType(Event::MouseUp); queueEvent(ev); - } - break; - - case INTERACTION_ID_SECONDARY_TAP: - case INTERACTION_ID_HOLD: - ev.setButton(Event::RightButton); - ev.setType(Event::MouseMove); queueEvent(ev); - ev.setType(Event::MouseDown); queueEvent(ev); - ev.setType(Event::MouseUp); queueEvent(ev); - break; - } - } -} - -void WinWindow::waitTimerToConvertFingerAsMouseMovement() -{ - ASSERT(m_touch); - m_touch->canBeMouse = true; - clearDelayedTouchEvents(); - SetTimer(m_hwnd, m_touch->timerID = 1, - kFingerAsMouseTimeout, nullptr); - TOUCH_TRACE(" - Set timer\n"); -} - -void WinWindow::convertFingerAsMouseMovement() -{ - ASSERT(m_touch); - m_touch->asMouse = true; - sendDelayedTouchEvents(); -} - -void WinWindow::delegateFingerToInteractionContext() -{ - ASSERT(m_touch); - m_touch->canBeMouse = false; - m_touch->asMouse = false; - clearDelayedTouchEvents(); - if (m_touch->timerID > 0) - killTouchTimer(); -} - -void WinWindow::sendDelayedTouchEvents() -{ - ASSERT(m_touch); - for (auto& ev : m_touch->delayedEvents) - queueEvent(ev); - clearDelayedTouchEvents(); -} - -void WinWindow::clearDelayedTouchEvents() -{ - ASSERT(m_touch); - m_touch->delayedEvents.clear(); -} - -void WinWindow::killTouchTimer() -{ - ASSERT(m_touch); - if (m_touch->timerID > 0) { - KillTimer(m_hwnd, m_touch->timerID); - m_touch->timerID = 0; - TOUCH_TRACE(" - Kill timer\n"); - } -} - -//static -void WinWindow::registerClass() -{ - HMODULE instance = GetModuleHandle(nullptr); - - WNDCLASSEX wcex; - if (GetClassInfoEx(instance, OS_WND_CLASS_NAME, &wcex)) - return; // Already registered - - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_DBLCLKS; - wcex.lpfnWndProc = &WinWindow::staticWndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = instance; - wcex.hIcon = LoadIcon(instance, L"0"); - wcex.hCursor = NULL; - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = nullptr; - wcex.lpszClassName = OS_WND_CLASS_NAME; - wcex.hIconSm = nullptr; - - if (RegisterClassEx(&wcex) == 0) - throw std::runtime_error("Error registering window class"); -} - -//static -HWND WinWindow::createHwnd(WinWindow* self, int width, int height) -{ - HWND hwnd = CreateWindowEx( - WS_EX_APPWINDOW | WS_EX_ACCEPTFILES, - OS_WND_CLASS_NAME, - L"", - WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, - CW_USEDEFAULT, CW_USEDEFAULT, - width, height, - nullptr, - nullptr, - GetModuleHandle(nullptr), - reinterpret_cast(self)); - if (!hwnd) - return nullptr; - - // Center the window - RECT workarea; - if (SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&workarea, 0)) { - SetWindowPos(hwnd, nullptr, - (workarea.right-workarea.left)/2-width/2, - (workarea.bottom-workarea.top)/2-height/2, 0, 0, - SWP_NOSIZE | - SWP_NOSENDCHANGING | - SWP_NOOWNERZORDER | - SWP_NOZORDER | - SWP_NOREDRAW); - } - - // Set scroll info to receive WM_HSCROLL/VSCROLL events (events - // generated by some trackpad drivers). - SCROLLINFO si; - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; - si.nMin = 0; - si.nPos = 50; - si.nMax = 100; - si.nPage = 10; - SetScrollInfo(hwnd, SB_HORZ, &si, FALSE); - SetScrollInfo(hwnd, SB_VERT, &si, FALSE); - - return hwnd; -} - -//static -LRESULT CALLBACK WinWindow::staticWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - WinWindow* wnd = nullptr; - - if (msg == WM_CREATE) { - wnd = - reinterpret_cast( - reinterpret_cast(lparam)->lpCreateParams); - - if (wnd && wnd->m_hwnd == nullptr) - wnd->m_hwnd = hwnd; - } - else { - wnd = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - - // Check that the user data makes sense - if (wnd && wnd->m_hwnd != hwnd) - wnd = nullptr; - } - - if (wnd) { - ASSERT(wnd->m_hwnd == hwnd); - return wnd->wndProc(msg, wparam, lparam); - } - else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - -//static -void CALLBACK WinWindow::staticInteractionContextCallback( - void* clientData, - const INTERACTION_CONTEXT_OUTPUT* output) -{ - WinWindow* self = reinterpret_cast(clientData); - self->handleInteractionContextOutput(output); -} - -// static -WindowSystem* WinWindow::system() -{ - return static_cast(os::instance()); -} - -} // namespace os diff --git a/src/os/win/window.h b/src/os/win/window.h deleted file mode 100644 index 56ea37c63..000000000 --- a/src/os/win/window.h +++ /dev/null @@ -1,190 +0,0 @@ -// LAF OS Library -// Copyright (C) 2012-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_WIN_WINDOW_H_INCLUDED -#define OS_WIN_WINDOW_H_INCLUDED -#pragma once - -#include "base/time.h" -#include "gfx/size.h" -#include "os/event.h" -#include "os/native_cursor.h" -#include "os/pointer_type.h" -#include "os/win/pen.h" - -#include -#include -#include - -#define OS_USE_POINTER_API_FOR_MOUSE 0 - -namespace os { - class Surface; - class WindowSystem; - - class WinWindow { - public: - WinWindow(int width, int height, int scale); - ~WinWindow(); - - void queueEvent(Event& ev); - int scale() const { return m_scale; } - void setScale(int scale); - void setVisible(bool visible); - void maximize(); - bool isMaximized() const; - bool isMinimized() const; - gfx::Size clientSize() const; - gfx::Size restoredSize() const; - void setTitle(const std::string& title); - void captureMouse(); - void releaseMouse(); - void setMousePosition(const gfx::Point& position); - bool setNativeMouseCursor(NativeCursor cursor); - bool setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale); - void updateWindow(const gfx::Rect& bounds); - std::string getLayout(); - - void setLayout(const std::string& layout); - void setTranslateDeadKeys(bool state); - void setInterpretOneFingerGestureAsMouseMovement(bool state); - - HWND handle() { return m_hwnd; } - - private: - bool setCursor(HCURSOR hcursor, bool custom); - LRESULT wndProc(UINT msg, WPARAM wparam, LPARAM lparam); - void mouseEvent(LPARAM lparam, Event& ev); - bool pointerEvent(WPARAM wparam, Event& ev, POINTER_INFO& pi); - void handlePointerButtonChange(Event& ev, POINTER_INFO& pi); - void handleInteractionContextOutput( - const INTERACTION_CONTEXT_OUTPUT* output); - - void waitTimerToConvertFingerAsMouseMovement(); - void convertFingerAsMouseMovement(); - void delegateFingerToInteractionContext(); - void sendDelayedTouchEvents(); - void clearDelayedTouchEvents(); - void killTouchTimer(); - - virtual void onQueueEvent(Event& ev) { } - virtual void onResize(const gfx::Size& sz) { } - virtual void onPaint(HDC hdc) { } - - static void registerClass(); - static HWND createHwnd(WinWindow* self, int width, int height); - static LRESULT CALLBACK staticWndProc( - HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - static void CALLBACK staticInteractionContextCallback( - void* clientData, - const INTERACTION_CONTEXT_OUTPUT* output); - - static WindowSystem* system(); - - mutable HWND m_hwnd; - HCURSOR m_hcursor; - gfx::Size m_clientSize; - gfx::Size m_restoredSize; - int m_scale; - bool m_isCreated; - bool m_translateDeadKeys; - bool m_hasMouse; - bool m_captureMouse; - bool m_customHcursor; - - // Windows 8 pointer API - bool m_usePointerApi; - UINT32 m_lastPointerId; - UINT32 m_capturePointerId; - HINTERACTIONCONTEXT m_ictx; - - // This might be the most ugliest hack I've done to fix a Windows - // bug. Here's the thing: - // 1) When we use the pen on a Surface device, it send us - // WM_POINTERUPDATE messages, but after a WM_POINTERUPDATE - // we'll receive a WM_MOUSEMOVE with the position of the mouse - // (which is different to the position of the pen). This - // happens constantly if we press a modifier key like Alt, - // Ctrl, or Shift, and randomly if we don't use a modifier. - // 2) First I tried to fix this issue disabling the WM_MOUSEMOVE - // processing when a pointer device is inside the window (with - // WM_POINTERENTER/LEAVE events), but that generated some buggy - // behavior (sometimes we stopped processing WM_MOUSEMOVE - // messages completely, it looks like a WM_POINTERLEAVE could - // be lost in time). - // 3) Then I tried to fix this using the Windows pointer API for - // mouse messages (EnableMouseInPointer(TRUE)) but that API - // doesn't work well with Wacom drivers. And I guess it might - // depend on the specific driver version. - // 4) Now I've reverted the pointer API change (we keep using the - // WM_MOUSE* messages) and fixed the original issue with this - // "m_ignoreRandomMouseEvents" variable. This is a counter that - // indicates the number of WM_MOUSEMOVE messages that we must - // ignore after a WM_POINTERUPDATE. - // 5) Each time we receive a WM_POINTERUPDATE this counter is set - // to 2. A value that I calculated practically just testing the - // pen in a Surface Pro using the Alt modifier and seeing how - // many random WM_MOUSEMOVE messages were received. - // 6) When a WM_MOUSEMOVE is received this counter is decreased, - // so when it backs to 0 we start processing WM_MOUSEMOVE - // messages again. - int m_ignoreRandomMouseEvents; - - // Variables used to convert one finger in mouse-like movement, - // and two/more fingers in scroll movement/pan/zoom. The idea - // is as follows: - // 1) When a PT_TOUCH is received, we count this event in - // m_fingers and setup a timer (m_fingerTimerID) to wait for - // another touch event. - // 2) If another touch event is received, we process the messages - // with the interaction context (m_ictx) to handle special - // gestures (pan, magnify, etc.). - // 3) If the timeout is reached, and we've received only one - // finger on the windows, we can send all awaiting events - // (m_fingerEvents) like mouse movement messages/button - // presses/releases. - struct Touch { - int fingers; // Number of fingers in the window - // True when the timeout wasn't reached yet and the finger can be - // converted to mouse events yet. - bool canBeMouse; - // True if we're already processing finger/touch events as mouse - // movement events. - bool asMouse; - // Timeout (WM_TIMER) when the finger is converted to mouse events. - UINT_PTR timerID; - // Queued events to be sent when the finger is converted to mouse - // events (these events are discarded if another finger is - // introduced in the gesture e.g. to pan) - std::vector delayedEvents; - Touch(); - } *m_touch; - -#if OS_USE_POINTER_API_FOR_MOUSE - // Emulate double-click with pointer API. I guess that this should - // be done by the Interaction Context API but it looks like - // messages with pointerType != PT_TOUCH or PT_PEN are just - // ignored by the ProcessPointerFramesInteractionContext() - // function even when we call AddPointerInteractionContext() with - // the given PT_MOUSE pointer. - bool m_emulateDoubleClick; - base::tick_t m_doubleClickMsecs; - base::tick_t m_lastPointerDownTime; - Event::MouseButton m_lastPointerDownButton; - int m_pointerDownCount; -#endif - - // Wintab API data - HCTX m_hpenctx; - PointerType m_pointerType; - double m_pressure; - }; - -} // namespace os - -#endif diff --git a/src/os/win/window_dde.cpp b/src/os/win/window_dde.cpp deleted file mode 100644 index a3316da91..000000000 --- a/src/os/win/window_dde.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/win/window_dde.h" - -#include "base/paths.h" -#include "base/string.h" -#include "os/event.h" -#include "os/event_queue.h" - -#include -#include - -namespace os { - -namespace { - -std::string get_atom_string(ATOM atom, bool isUnicode) -{ - std::string result; - if (!atom) - return result; - - if (isUnicode) { - std::vector buf(256, 0); - GlobalGetAtomNameW(atom, &buf[0], buf.size()); - result = base::to_utf8(std::wstring(&buf[0])); - } - else { - std::vector buf(256, 0); - UINT chars = GlobalGetAtomNameA(atom, &buf[0], buf.size()); - result = &buf[0]; - } - - return result; -} - -// Converts a DDE command string (e.g. "[open(filename)]") into 'os' library events. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms648995.aspx -bool parse_dde_command(const std::string& cmd) -{ - bool result = false; - - for (size_t i=0; i - -namespace os { - -bool handle_dde_messages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT& result); - -} // namespace os - -#endif diff --git a/src/os/x11/event_queue.cpp b/src/os/x11/event_queue.cpp deleted file mode 100644 index a02e0d9b2..000000000 --- a/src/os/x11/event_queue.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/x11/event_queue.h" - -#include "os/x11/window.h" - -#include - -#define EV_TRACE(...) - -namespace os { - -#if !defined(NDEBUG) -namespace { - -const char* get_event_name(XEvent& event) -{ - switch (event.type) { - case KeyPress: return "KeyPress"; - case KeyRelease: return "KeyRelease"; - case ButtonPress: return "ButtonPress"; - case ButtonRelease: return "ButtonRelease"; - case MotionNotify: return "MotionNotify"; - case EnterNotify: return "EnterNotify"; - case LeaveNotify: return "LeaveNotify"; - case FocusIn: return "FocusIn"; - case FocusOut: return "FocusOut"; - case KeymapNotify: return "KeymapNotify"; - case Expose: return "Expose"; - case GraphicsExpose: return "GraphicsExpose"; - case NoExpose: return "NoExpose"; - case VisibilityNotify: return "VisibilityNotify"; - case CreateNotify: return "CreateNotify"; - case DestroyNotify: return "DestroyNotify"; - case UnmapNotify: return "UnmapNotify"; - case MapNotify: return "MapNotify"; - case MapRequest: return "MapRequest"; - case ReparentNotify: return "ReparentNotify"; - case ConfigureNotify: return "ConfigureNotify"; - case ConfigureRequest: return "ConfigureRequest"; - case GravityNotify: return "GravityNotify"; - case ResizeRequest: return "ResizeRequest"; - case CirculateNotify: return "CirculateNotify"; - case CirculateRequest: return "CirculateRequest"; - case PropertyNotify: return "PropertyNotify"; - case SelectionClear: return "SelectionClear"; - case SelectionRequest: return "SelectionRequest"; - case SelectionNotify: return "SelectionNotify"; - case ColormapNotify: return "ColormapNotify"; - case ClientMessage: return "ClientMessage"; - case MappingNotify: return "MappingNotify"; - case GenericEvent: return "GenericEvent"; - } - return "Unknown"; -} - -} // anonymous namespace -#endif - -void X11EventQueue::getEvent(Event& ev, bool canWait) -{ - ::Display* display = X11::instance()->display(); - XSync(display, False); - - XEvent event; - int events = XEventsQueued(display, QueuedAlready); - for (int i=0; iprocessX11Event(event); -} - -} // namespace os diff --git a/src/os/x11/event_queue.h b/src/os/x11/event_queue.h deleted file mode 100644 index 3e3085679..000000000 --- a/src/os/x11/event_queue.h +++ /dev/null @@ -1,36 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2017 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_X11_EVENT_QUEUE_INCLUDED -#define OS_X11_EVENT_QUEUE_INCLUDED -#pragma once - -#include "os/event.h" -#include "os/event_queue.h" -#include "os/x11/x11.h" - -#include - -namespace os { - -class X11EventQueue : public EventQueue { -public: - void getEvent(Event& ev, bool canWait) override; - void queueEvent(const Event& ev) override { - m_events.push(ev); - } - -private: - void processX11Event(XEvent& event); - - std::queue m_events; -}; - -typedef X11EventQueue EventQueueImpl; - -} // namespace os - -#endif diff --git a/src/os/x11/keys.cpp b/src/os/x11/keys.cpp deleted file mode 100644 index ca4cd78ad..000000000 --- a/src/os/x11/keys.cpp +++ /dev/null @@ -1,362 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "base/ints.h" -#include "os/x11/keys.h" -#include "os/x11/x11.h" - -#include -#include - -namespace os { - -KeyScancode x11_keysym_to_scancode(const KeySym keysym) -{ - switch (keysym) { - case XK_BackSpace: return kKeyBackspace; - case XK_Tab: return kKeyTab; - case XK_Linefeed: return kKeyEnter; - case XK_Clear: return kKeyDel; - case XK_Return: return kKeyEnter; - case XK_Pause: - case XK_Break: return kKeyPause; - case XK_Scroll_Lock: return kKeyScrLock; - case XK_Escape: return kKeyEsc; - case XK_Delete: return kKeyDel; - case XK_Home: return kKeyHome; - case XK_Left: return kKeyLeft; - case XK_Up: return kKeyUp; - case XK_Right: return kKeyRight; - case XK_Down: return kKeyDown; - case XK_Page_Up: return kKeyPageUp; - case XK_Page_Down: return kKeyPageDown; - case XK_End: return kKeyEnd; - case XK_Sys_Req: - case XK_Print: return kKeyPrtscr; - case XK_Insert: return kKeyInsert; - case XK_Menu: return kKeyMenu; - case XK_Num_Lock: return kKeyNumLock; - case XK_KP_Space: return kKeySpace; - case XK_KP_Tab: return kKeyTab; - case XK_KP_Enter: return kKeyEnterPad; - case XK_KP_0: case XK_KP_Insert: return kKey0Pad; - case XK_KP_1: case XK_KP_End: return kKey1Pad; - case XK_KP_2: case XK_KP_Down: return kKey2Pad; - case XK_KP_3: case XK_KP_Page_Down: return kKey3Pad; - case XK_KP_4: case XK_KP_Left: return kKey4Pad; - case XK_KP_5: case XK_KP_Begin: return kKey5Pad; - case XK_KP_6: case XK_KP_Right: return kKey6Pad; - case XK_KP_7: case XK_KP_Home: return kKey7Pad; - case XK_KP_8: case XK_KP_Up: return kKey8Pad; - case XK_KP_9: case XK_KP_Page_Up: return kKey9Pad; - case XK_KP_Decimal: - case XK_KP_Delete: return kKeyDelPad; - case XK_KP_Equal: return kKeyEqualsPad; - case XK_KP_Multiply: return kKeyAsterisk; - case XK_KP_Add: return kKeyPlusPad; - case XK_KP_Subtract: return kKeyMinusPad; - case XK_KP_Divide: return kKeySlashPad; - case XK_F1: return kKeyF1; - case XK_F2: return kKeyF2; - case XK_F3: return kKeyF3; - case XK_F4: return kKeyF4; - case XK_F5: return kKeyF5; - case XK_F6: return kKeyF6; - case XK_F7: return kKeyF7; - case XK_F8: return kKeyF8; - case XK_F9: return kKeyF9; - case XK_F10: return kKeyF10; - case XK_F11: return kKeyF11; - case XK_F12: return kKeyF12; - case XK_Shift_L: return kKeyLShift; - case XK_Shift_R: return kKeyRShift; - case XK_Control_L: return kKeyLControl; - case XK_Control_R: return kKeyRControl; - case XK_Caps_Lock: return kKeyCapsLock; - case XK_Alt_L: return kKeyAlt; - case XK_Alt_R: return kKeyAltGr; - case XK_Meta_L: - case XK_Super_L: return kKeyLWin; - case XK_Meta_R: - case XK_Super_R: return kKeyRWin; - case XK_space: return kKeySpace; - case XK_apostrophe: return kKeyQuote; - case XK_comma: return kKeyComma; - case XK_minus: return kKeyMinus; - case XK_period: return kKeyStop; - case XK_slash: return kKeySlash; - case XK_0: return kKey0; - case XK_1: return kKey1; - case XK_2: return kKey2; - case XK_3: return kKey3; - case XK_4: return kKey4; - case XK_5: return kKey5; - case XK_6: return kKey6; - case XK_7: return kKey7; - case XK_8: return kKey8; - case XK_9: return kKey9; - case XK_semicolon: return kKeyColon; - case XK_less: return kKeyBackslash2; - case XK_A: return kKeyA; - case XK_B: return kKeyB; - case XK_C: return kKeyC; - case XK_D: return kKeyD; - case XK_E: return kKeyE; - case XK_F: return kKeyF; - case XK_G: return kKeyG; - case XK_H: return kKeyH; - case XK_I: return kKeyI; - case XK_J: return kKeyJ; - case XK_K: return kKeyK; - case XK_L: return kKeyL; - case XK_M: return kKeyM; - case XK_N: return kKeyN; - case XK_O: return kKeyO; - case XK_P: return kKeyP; - case XK_Q: return kKeyQ; - case XK_R: return kKeyR; - case XK_S: return kKeyS; - case XK_T: return kKeyT; - case XK_U: return kKeyU; - case XK_V: return kKeyV; - case XK_W: return kKeyW; - case XK_X: return kKeyX; - case XK_Y: return kKeyY; - case XK_Z: return kKeyZ; - case XK_bracketleft: return kKeyOpenbrace; - case XK_backslash: return kKeyBackslash; - case XK_bracketright: return kKeyClosebrace; - case XK_grave: return kKeyTilde; - case XK_a: return kKeyA; - case XK_b: return kKeyB; - case XK_c: return kKeyC; - case XK_d: return kKeyD; - case XK_e: return kKeyE; - case XK_f: return kKeyF; - case XK_g: return kKeyG; - case XK_h: return kKeyH; - case XK_i: return kKeyI; - case XK_j: return kKeyJ; - case XK_k: return kKeyK; - case XK_l: return kKeyL; - case XK_m: return kKeyM; - case XK_n: return kKeyN; - case XK_o: return kKeyO; - case XK_p: return kKeyP; - case XK_q: return kKeyQ; - case XK_r: return kKeyR; - case XK_s: return kKeyS; - case XK_t: return kKeyT; - case XK_u: return kKeyU; - case XK_v: return kKeyV; - case XK_w: return kKeyW; - case XK_x: return kKeyX; - case XK_y: return kKeyY; - case XK_z: return kKeyZ; - } - return kKeyNil; -} - -KeySym x11_keysym_to_scancode(const KeyScancode scancode) -{ - switch (scancode) { - case kKeyBackspace: return XK_BackSpace; - case kKeyTab: return XK_Tab; - case kKeyEnter: return XK_Return; - case kKeyPause: return XK_Pause; - case kKeyScrLock: return XK_Scroll_Lock; - case kKeyEsc: return XK_Escape; - case kKeyDel: return XK_Delete; - case kKeyHome: return XK_Home; - case kKeyLeft: return XK_Left; - case kKeyUp: return XK_Up; - case kKeyRight: return XK_Right; - case kKeyDown: return XK_Down; - case kKeyPageUp: return XK_Page_Up; - case kKeyPageDown: return XK_Page_Down; - case kKeyEnd: return XK_End; - case kKeyPrtscr: return XK_Print; - case kKeyInsert: return XK_Insert; - case kKeyMenu: return XK_Menu; - case kKeyNumLock: return XK_Num_Lock; - case kKeyEnterPad: return XK_KP_Enter; - case kKey0Pad: return XK_KP_0; - case kKey1Pad: return XK_KP_1; - case kKey2Pad: return XK_KP_2; - case kKey3Pad: return XK_KP_3; - case kKey4Pad: return XK_KP_4; - case kKey5Pad: return XK_KP_5; - case kKey6Pad: return XK_KP_6; - case kKey7Pad: return XK_KP_7; - case kKey8Pad: return XK_KP_8; - case kKey9Pad: return XK_KP_9; - case kKeyDelPad: return XK_KP_Delete; - case kKeyEqualsPad: return XK_KP_Equal; - case kKeyAsterisk: return XK_KP_Multiply; - case kKeyPlusPad: return XK_KP_Add; - case kKeyMinusPad: return XK_KP_Subtract; - case kKeySlashPad: return XK_KP_Divide; - case kKeyF1: return XK_F1; - case kKeyF2: return XK_F2; - case kKeyF3: return XK_F3; - case kKeyF4: return XK_F4; - case kKeyF5: return XK_F5; - case kKeyF6: return XK_F6; - case kKeyF7: return XK_F7; - case kKeyF8: return XK_F8; - case kKeyF9: return XK_F9; - case kKeyF10: return XK_F10; - case kKeyF11: return XK_F11; - case kKeyF12: return XK_F12; - case kKeyLShift: return XK_Shift_L; - case kKeyRShift: return XK_Shift_R; - case kKeyLControl: return XK_Control_L; - case kKeyRControl: return XK_Control_R; - case kKeyCapsLock: return XK_Caps_Lock; - case kKeyAlt: return XK_Alt_L; - case kKeyAltGr: return XK_Alt_R; - case kKeyLWin: return XK_Super_L; - case kKeyRWin: return XK_Super_R; - case kKeySpace: return XK_space; - case kKeyQuote: return XK_apostrophe; - case kKeyComma: return XK_comma; - case kKeyMinus: return XK_minus; - case kKeyStop: return XK_period; - case kKeySlash: return XK_slash; - case kKey0: return XK_0; - case kKey1: return XK_1; - case kKey2: return XK_2; - case kKey3: return XK_3; - case kKey4: return XK_4; - case kKey5: return XK_5; - case kKey6: return XK_6; - case kKey7: return XK_7; - case kKey8: return XK_8; - case kKey9: return XK_9; - case kKeyColon: return XK_semicolon; - case kKeyBackslash2: return XK_less; - case kKeyOpenbrace: return XK_bracketleft; - case kKeyBackslash: return XK_backslash; - case kKeyClosebrace: return XK_bracketright; - case kKeyTilde: return XK_grave; - case kKeyA: return XK_a; - case kKeyB: return XK_b; - case kKeyC: return XK_c; - case kKeyD: return XK_d; - case kKeyE: return XK_e; - case kKeyF: return XK_f; - case kKeyG: return XK_g; - case kKeyH: return XK_h; - case kKeyI: return XK_i; - case kKeyJ: return XK_j; - case kKeyK: return XK_k; - case kKeyL: return XK_l; - case kKeyM: return XK_m; - case kKeyN: return XK_n; - case kKeyO: return XK_o; - case kKeyP: return XK_p; - case kKeyQ: return XK_q; - case kKeyR: return XK_r; - case kKeyS: return XK_s; - case kKeyT: return XK_t; - case kKeyU: return XK_u; - case kKeyV: return XK_v; - case kKeyW: return XK_w; - case kKeyX: return XK_x; - case kKeyY: return XK_y; - case kKeyZ: return XK_z; - } - return 0; -} - -bool x11_is_key_pressed(const KeyScancode scancode) -{ - ::Display* display = X11::instance()->display(); - const KeySym keysym = x11_keysym_to_scancode(scancode); - const KeyCode keycode = XKeysymToKeycode(display, keysym); - if (!keycode) - return false; - - // TODO several platforms have this kind of API to get the whole - // keyboard state, it would be a lot better if we expose this - // API to the user (so we don't have to call XQueryKeymap for - // each key). - char keys[32]; - XQueryKeymap(display, keys); - - return (keys[keycode/8] & (1 << (keycode%8)) ? true: false); -} - -// TODO I guess that this code should be common to all platforms, but -// osx/win_get_unicode_from_scancode() work in a different way: -// the Unicode is returned only if the scancode key is pressed -// (and that's the case anyway in the only part we are using -// System::getUnicodeFromScancode(), a System::isKeyPressed() is -// tested before). -int x11_get_unicode_from_scancode(const KeyScancode scancode) -{ - switch (scancode) { - case kKeyEqualsPad: return '='; - case kKeyAsterisk: return '*'; - case kKeyPlusPad: return '+'; - case kKeyMinusPad: return '-'; - case kKeySlashPad: return '/'; - case kKeySpace: return ' '; - case kKeyQuote: return '\''; - case kKeyComma: return ','; - case kKeyMinus: return '-'; - case kKeyStop: return '.'; - case kKeySlash: return '/'; - case kKey0: case kKey0Pad: return '0'; - case kKey1: case kKey1Pad: return '1'; - case kKey2: case kKey2Pad: return '2'; - case kKey3: case kKey3Pad: return '3'; - case kKey4: case kKey4Pad: return '4'; - case kKey5: case kKey5Pad: return '5'; - case kKey6: case kKey6Pad: return '6'; - case kKey7: case kKey7Pad: return '7'; - case kKey8: case kKey8Pad: return '8'; - case kKey9: case kKey9Pad: return '9'; - case kKeyColon: return ':'; - case kKeyBackslash: case kKeyBackslash2: return '\\'; - case kKeyOpenbrace: return '['; - case kKeyClosebrace: return ']'; - case kKeyTilde: return '~'; - case kKeyA: return 'a'; - case kKeyB: return 'b'; - case kKeyC: return 'c'; - case kKeyD: return 'd'; - case kKeyE: return 'e'; - case kKeyF: return 'f'; - case kKeyG: return 'g'; - case kKeyH: return 'h'; - case kKeyI: return 'i'; - case kKeyJ: return 'j'; - case kKeyK: return 'k'; - case kKeyL: return 'l'; - case kKeyM: return 'm'; - case kKeyN: return 'n'; - case kKeyO: return 'o'; - case kKeyP: return 'p'; - case kKeyQ: return 'q'; - case kKeyR: return 'r'; - case kKeyS: return 's'; - case kKeyT: return 't'; - case kKeyU: return 'u'; - case kKeyV: return 'v'; - case kKeyW: return 'w'; - case kKeyX: return 'x'; - case kKeyY: return 'y'; - case kKeyZ: return 'z'; - } - return 0; -} - -} // namespace os diff --git a/src/os/x11/keys.h b/src/os/x11/keys.h deleted file mode 100644 index 45b8729d5..000000000 --- a/src/os/x11/keys.h +++ /dev/null @@ -1,23 +0,0 @@ -// LAF OS Library -// Copyright (C) 2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_X11_KEYS_INCLUDED -#define OS_X11_KEYS_INCLUDED -#pragma once - -#include "os/keys.h" -#include - -namespace os { - - KeyScancode x11_keysym_to_scancode(const KeySym keysym); - KeySym x11_keysym_to_scancode(const KeyScancode scancode); - bool x11_is_key_pressed(const KeyScancode scancode); - int x11_get_unicode_from_scancode(const KeyScancode scancode); - -} // namespace os - -#endif diff --git a/src/os/x11/system.h b/src/os/x11/system.h deleted file mode 100644 index 83c916ee5..000000000 --- a/src/os/x11/system.h +++ /dev/null @@ -1,29 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_X11_SYSTEM_H -#define OS_X11_SYSTEM_H -#pragma once - -#include "os/common/system.h" -#include "os/x11/keys.h" - -namespace os { - -class X11System : public CommonSystem { -public: - bool isKeyPressed(KeyScancode scancode) override { - return x11_is_key_pressed(scancode); - } - - int getUnicodeFromScancode(KeyScancode scancode) override { - return x11_get_unicode_from_scancode(scancode); - } -}; - -} // namespace os - -#endif diff --git a/src/os/x11/window.cpp b/src/os/x11/window.cpp deleted file mode 100644 index f35169a1a..000000000 --- a/src/os/x11/window.cpp +++ /dev/null @@ -1,628 +0,0 @@ -// LAF OS Library -// Copyright (C) 2017-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/x11/window.h" - -#include "base/string.h" -#include "gfx/rect.h" -#include "os/event.h" -#include "os/surface.h" -#include "os/x11/keys.h" -#include "os/x11/x11.h" - -#include -#include - -#define KEY_TRACE(...) -#define MOUSE_TRACE(...) -#define EVENT_TRACE(...) - -namespace os { - -namespace { - -// Event generated by the window manager when the close button on the -// window is pressed by the userh. -Atom wmDeleteMessage = 0; - -// Cursor Without pixels to simulate a hidden X11 cursor -Cursor empty_xcursor = None; - -// See https://bugs.freedesktop.org/show_bug.cgi?id=12871 for more -// information, it looks like the official way to convert a X Window -// into our own user data pointer (X11Window instance) is using a map. -std::map<::Window, X11Window*> g_activeWindows; - -bool g_spaceBarIsPressed = false; - -KeyModifiers get_modifiers_from_x(int state) -{ - int modifiers = kKeyNoneModifier; - if (state & ShiftMask) { - modifiers |= kKeyShiftModifier; - KEY_TRACE("+SHIFT\n"); - } - if (state & ControlMask) { - modifiers |= kKeyCtrlModifier; - KEY_TRACE("+CTRL\n"); - } - // Mod1Mask is Alt, and Mod5Mask is AltGr - if (state & (Mod1Mask | Mod5Mask)) { - modifiers |= kKeyAltModifier; - KEY_TRACE("+ALT\n"); - } - // Mod4Mask is Windows key - if (state & Mod4Mask) { - modifiers |= kKeyWinModifier; - KEY_TRACE("+WIN\n"); - } - if (g_spaceBarIsPressed) { - modifiers |= kKeySpaceModifier; - KEY_TRACE("+SPACE\n"); - } - return (KeyModifiers)modifiers; -} - -bool is_mouse_wheel_button(int button) -{ - return (button == Button4 || button == Button5 || - button == 6 || button == 7); -} - -gfx::Point get_mouse_wheel_delta(int button) -{ - gfx::Point delta(0, 0); - switch (button) { - // Vertical wheel - case Button4: delta.y = -1; break; - case Button5: delta.y = +1; break; - // Horizontal wheel - case 6: delta.x = -1; break; - case 7: delta.x = +1; break; - } - return delta; -} - -Event::MouseButton get_mouse_button_from_x(int button) -{ - switch (button) { - case Button1: MOUSE_TRACE("LeftButton\n"); return Event::LeftButton; - case Button2: MOUSE_TRACE("MiddleButton\n"); return Event::MiddleButton; - case Button3: MOUSE_TRACE("RightButton\n"); return Event::RightButton; - case 8: MOUSE_TRACE("X1Button\n"); return Event::X1Button; - case 9: MOUSE_TRACE("X2Button\n"); return Event::X2Button; - } - MOUSE_TRACE("Unknown Button %d\n", button); - return Event::NoneButton; -} - -} // anonymous namespace - -// static -X11Window* X11Window::getPointerFromHandle(Window handle) -{ - auto it = g_activeWindows.find(handle); - if (it != g_activeWindows.end()) - return it->second; - else - return nullptr; -} - -// static -void X11Window::addWindow(X11Window* window) -{ - ASSERT(g_activeWindows.find(window->handle()) == g_activeWindows.end()); - g_activeWindows[window->handle()] = window; -} - -// static -void X11Window::removeWindow(X11Window* window) -{ - auto it = g_activeWindows.find(window->handle()); - ASSERT(it != g_activeWindows.end()); - if (it != g_activeWindows.end()) { - ASSERT(it->second == window); - g_activeWindows.erase(it); - } -} - -X11Window::X11Window(::Display* display, int width, int height, int scale) - : m_display(display) - , m_gc(nullptr) - , m_cursor(None) - , m_xcursorImage(nullptr) - , m_xic(nullptr) - , m_scale(scale) -{ - // Initialize special messages (just the first time a X11Window is - // created) - if (!wmDeleteMessage) - wmDeleteMessage = XInternAtom(m_display, "WM_DELETE_WINDOW", False); - - ::Window root = XDefaultRootWindow(m_display); - - XSetWindowAttributes swa; - swa.event_mask = (StructureNotifyMask | ExposureMask | PropertyChangeMask | - EnterWindowMask | LeaveWindowMask | FocusChangeMask | - ButtonPressMask | ButtonReleaseMask | PointerMotionMask | - KeyPressMask | KeyReleaseMask); - - m_window = XCreateWindow( - m_display, root, - 0, 0, width, height, 0, - CopyFromParent, - InputOutput, - CopyFromParent, - CWEventMask, - &swa); - - XMapWindow(m_display, m_window); - XSetWMProtocols(m_display, m_window, &wmDeleteMessage, 1); - - m_gc = XCreateGC(m_display, m_window, 0, nullptr); - - XIM xim = X11::instance()->xim(); - if (xim) { - m_xic = XCreateIC(xim, - XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, m_window, - XNFocusWindow, m_window, - nullptr); - } - X11Window::addWindow(this); -} - -X11Window::~X11Window() -{ - if (m_xcursorImage != None) - XcursorImageDestroy(m_xcursorImage); - if (m_xic) - XDestroyIC(m_xic); - XFreeGC(m_display, m_gc); - XDestroyWindow(m_display, m_window); - - X11Window::removeWindow(this); -} - -void X11Window::setScale(const int scale) -{ - m_scale = scale; - resizeDisplay(clientSize()); -} - -void X11Window::setTitle(const std::string& title) -{ - XTextProperty prop; - prop.value = (unsigned char*)title.c_str(); - prop.encoding = XA_STRING; - prop.format = 8; - prop.nitems = std::strlen((char*)title.c_str()); - XSetWMName(m_display, m_window, &prop); -} - -void X11Window::setIcons(const SurfaceList& icons) -{ - if (!m_display || !m_window) - return; - - bool first = true; - for (Surface* icon : icons) { - const int w = icon->width(); - const int h = icon->height(); - - SurfaceFormatData format; - icon->getFormat(&format); - - std::vector data(w*h+2); - int i = 0; - data[i++] = w; - data[i++] = h; - for (int y=0; ygetData(0, y); - for (int x=0; x> format.blueShift ) ) | - (((c & format.greenMask) >> format.greenShift) << 8) | - (((c & format.redMask ) >> format.redShift ) << 16) | - (((c & format.alphaMask) >> format.alphaShift) << 24); - } - } - - Atom _NET_WM_ICON = XInternAtom(m_display, "_NET_WM_ICON", False); - XChangeProperty( - m_display, m_window, _NET_WM_ICON, XA_CARDINAL, 32, - first ? PropModeReplace: - PropModeAppend, - (const unsigned char*)&data[0], data.size()); - - first = false; - } -} - -gfx::Size X11Window::clientSize() const -{ - Window root; - int x, y; - unsigned int width, height, border, depth; - XGetGeometry(m_display, m_window, &root, - &x, &y, &width, &height, &border, &depth); - return gfx::Size(int(width), int(height)); -} - -gfx::Size X11Window::restoredSize() const -{ - Window root; - int x, y; - unsigned int width, height, border, depth; - XGetGeometry(m_display, m_window, &root, - &x, &y, &width, &height, &border, &depth); - return gfx::Size(int(width), int(height)); -} - -void X11Window::captureMouse() -{ - XGrabPointer(m_display, m_window, False, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, - None, None, CurrentTime); -} - -void X11Window::releaseMouse() -{ - XUngrabPointer(m_display, CurrentTime); -} - -void X11Window::setMousePosition(const gfx::Point& position) -{ - Window root; - int x, y; - unsigned int w, h, border, depth; - XGetGeometry(m_display, m_window, &root, - &x, &y, &w, &h, &border, &depth); - XWarpPointer(m_display, m_window, m_window, 0, 0, w, h, - position.x*m_scale, position.y*m_scale); -} - -void X11Window::updateWindow(const gfx::Rect& unscaledBounds) -{ - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xexpose.type = Expose; - ev.xexpose.display = x11display(); - ev.xexpose.window = handle(); - ev.xexpose.x = unscaledBounds.x*m_scale; - ev.xexpose.y = unscaledBounds.y*m_scale; - ev.xexpose.width = unscaledBounds.w*m_scale; - ev.xexpose.height = unscaledBounds.h*m_scale; - XSendEvent(m_display, m_window, False, - ExposureMask, (XEvent*)&ev); -} - -bool X11Window::setNativeMouseCursor(NativeCursor cursor) -{ - Cursor xcursor = None; - - switch (cursor) { - case kNoCursor: { - if (empty_xcursor == None) { - char data = 0; - Pixmap image = XCreateBitmapFromData( - m_display, m_window, (char*)&data, 1, 1); - - XColor color; - empty_xcursor = XCreatePixmapCursor( - m_display, image, image, &color, &color, 0, 0); - - XFreePixmap(m_display, image); - } - xcursor = empty_xcursor; - break; - } - case kArrowCursor: - xcursor = XCreateFontCursor(m_display, XC_arrow); - break; - case kCrosshairCursor: - xcursor = XCreateFontCursor(m_display, XC_crosshair); - break; - case kIBeamCursor: - xcursor = XCreateFontCursor(m_display, XC_xterm); - break; - case kWaitCursor: - xcursor = XCreateFontCursor(m_display, XC_watch); - break; - case kLinkCursor: - xcursor = XCreateFontCursor(m_display, XC_hand1); - break; - case kHelpCursor: - xcursor = XCreateFontCursor(m_display, XC_question_arrow); - break; - case kForbiddenCursor: - xcursor = XCreateFontCursor(m_display, XC_X_cursor); - break; - case kMoveCursor: - xcursor = XCreateFontCursor(m_display, XC_fleur); - break; - case kSizeNCursor: - xcursor = XCreateFontCursor(m_display, XC_top_side); - break; - case kSizeNSCursor: - xcursor = XCreateFontCursor(m_display, XC_sb_v_double_arrow); - break; - case kSizeSCursor: - xcursor = XCreateFontCursor(m_display, XC_bottom_side); - break; - case kSizeWCursor: - xcursor = XCreateFontCursor(m_display, XC_left_side); - break; - case kSizeECursor: - xcursor = XCreateFontCursor(m_display, XC_right_side); - break; - case kSizeWECursor: - xcursor = XCreateFontCursor(m_display, XC_sb_h_double_arrow); - break; - case kSizeNWCursor: - xcursor = XCreateFontCursor(m_display, XC_top_left_corner); - break; - case kSizeNECursor: - xcursor = XCreateFontCursor(m_display, XC_top_right_corner); - break; - case kSizeSWCursor: - xcursor = XCreateFontCursor(m_display, XC_bottom_left_corner); - break; - case kSizeSECursor: - xcursor = XCreateFontCursor(m_display, XC_bottom_right_corner); - break; - } - - return setX11Cursor(xcursor); -} - -bool X11Window::setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale) -{ - ASSERT(surface); - - // This X11 server doesn't support ARGB cursors. - if (!XcursorSupportsARGB(m_display)) - return false; - - SurfaceFormatData format; - surface->getFormat(&format); - - // Only for 32bpp surfaces - if (format.bitsPerPixel != 32) - return false; - - const int w = scale*surface->width(); - const int h = scale*surface->height(); - - Cursor xcursor = None; - if (m_xcursorImage == None || - m_xcursorImage->width != XcursorDim(w) || - m_xcursorImage->height != XcursorDim(h)) { - if (m_xcursorImage != None) - XcursorImageDestroy(m_xcursorImage); - m_xcursorImage = XcursorImageCreate(w, h); - } - if (m_xcursorImage != None) { - XcursorPixel* dst = m_xcursorImage->pixels; - for (int y=0; ygetData(0, y/scale); - for (int x=0, u=0; x> format.alphaShift) << 24) | - (((c & format.redMask ) >> format.redShift ) << 16) | - (((c & format.greenMask) >> format.greenShift) << 8) | - (((c & format.blueMask ) >> format.blueShift )); - if (++u == scale) { - u = 0; - ++src; - } - } - } - - m_xcursorImage->xhot = scale*focus.x + scale/2; - m_xcursorImage->yhot = scale*focus.y + scale/2; - xcursor = XcursorImageLoadCursor(m_display, - m_xcursorImage); - } - - return setX11Cursor(xcursor); -} - -bool X11Window::setX11Cursor(::Cursor xcursor) -{ - if (m_cursor != None) { - if (m_cursor != empty_xcursor) // Don't delete empty_xcursor - XFreeCursor(m_display, m_cursor); - m_cursor = None; - } - if (xcursor != None) { - m_cursor = xcursor; - XDefineCursor(m_display, m_window, xcursor); - return true; - } - else - return false; -} - -void X11Window::processX11Event(XEvent& event) -{ - switch (event.type) { - - case ConfigureNotify: { - gfx::Size newSize(event.xconfigure.width, - event.xconfigure.height); - - if (newSize.w > 0 && - newSize.h > 0 && - newSize != clientSize()) { - resizeDisplay(newSize); - } - break; - } - - case Expose: { - gfx::Rect rc(event.xexpose.x, event.xexpose.y, - event.xexpose.width, event.xexpose.height); - paintGC(rc); - break; - } - - case KeyPress: - case KeyRelease: { - Event ev; - - ev.setType(event.type == KeyPress ? Event::KeyDown: Event::KeyUp); - - KeySym keysym = XLookupKeysym(&event.xkey, 0); - ev.setScancode(x11_keysym_to_scancode(keysym)); - - if (m_xic) { - std::vector buf(16); - size_t len = Xutf8LookupString(m_xic, &event.xkey, - &buf[0], buf.size(), - nullptr, nullptr); - if (len < buf.size()) - buf[len] = 0; - std::wstring wideChars = base::from_utf8(std::string(&buf[0])); - if (!wideChars.empty()) - ev.setUnicodeChar(wideChars[0]); - KEY_TRACE("Xutf8LookupString %s\n", &buf[0]); - } - - // Key event used by the input method (e.g. when the user - // presses a dead key). - if (XFilterEvent(&event, m_window)) - break; - - int modifiers = (int)get_modifiers_from_x(event.xkey.state); - switch (keysym) { - case XK_space: { - switch (event.type) { - case KeyPress: - g_spaceBarIsPressed = true; - break; - case KeyRelease: - g_spaceBarIsPressed = false; - - // If the next event after a KeyRelease is a KeyPress of - // the same keycode (the space bar in this case), it - // means that this KeyRelease is just a repetition of a - // the same keycode. - if (XEventsQueued(m_display, QueuedAfterReading)) { - XEvent nextEvent; - XPeekEvent(m_display, &nextEvent); - if (nextEvent.type == KeyPress && - nextEvent.xkey.time == event.xkey.time && - nextEvent.xkey.keycode == event.xkey.keycode) { - g_spaceBarIsPressed = true; - } - } - break; - } - break; - } - case XK_Shift_L: - case XK_Shift_R: - modifiers |= kKeyShiftModifier; - break; - case XK_Control_L: - case XK_Control_R: - modifiers |= kKeyCtrlModifier; - break; - case XK_Alt_L: - case XK_Alt_R: - modifiers |= kKeyAltModifier; - break; - case XK_Meta_L: - case XK_Super_L: - case XK_Meta_R: - case XK_Super_R: - modifiers |= kKeyWinModifier; - break; - } - ev.setModifiers((KeyModifiers)modifiers); - KEY_TRACE("%s state=%04x keycode=%04x\n", - (event.type == KeyPress ? "KeyPress": "KeyRelease"), - event.xkey.state, - event.xkey.keycode); - KEY_TRACE(" > %s\n", XKeysymToString(keysym)); - - queueEvent(ev); - break; - } - - case ButtonPress: - case ButtonRelease: { - Event ev; - - if (is_mouse_wheel_button(event.xbutton.button)) { - ev.setType(Event::MouseWheel); - ev.setWheelDelta(get_mouse_wheel_delta(event.xbutton.button)); - } - else { - ev.setType(event.type == ButtonPress? Event::MouseDown: - Event::MouseUp); - ev.setButton(get_mouse_button_from_x(event.xbutton.button)); - } - ev.setModifiers(get_modifiers_from_x(event.xbutton.state)); - ev.setPosition(gfx::Point(event.xbutton.x / m_scale, - event.xbutton.y / m_scale)); - - queueEvent(ev); - break; - } - - case MotionNotify: { - Event ev; - ev.setType(Event::MouseMove); - ev.setModifiers(get_modifiers_from_x(event.xmotion.state)); - ev.setPosition(gfx::Point(event.xmotion.x / m_scale, - event.xmotion.y / m_scale)); - queueEvent(ev); - break; - } - - case EnterNotify: - case LeaveNotify: - g_spaceBarIsPressed = false; - - // "mode" can be NotifyGrab or NotifyUngrab when middle mouse - // button is pressed/released. We must not generated - // MouseEnter/Leave events on those cases, only on NotifyNormal - // (when mouse leaves/enter the X11 window). - if (event.xcrossing.mode == NotifyNormal) { - Event ev; - ev.setType(event.type == EnterNotify ? Event::MouseEnter: - Event::MouseLeave); - ev.setModifiers(get_modifiers_from_x(event.xcrossing.state)); - ev.setPosition(gfx::Point(event.xcrossing.x / m_scale, - event.xcrossing.y / m_scale)); - queueEvent(ev); - } - break; - - case ClientMessage: - // When the close button is pressed - if (Atom(event.xclient.data.l[0]) == wmDeleteMessage) { - Event ev; - ev.setType(Event::CloseDisplay); - queueEvent(ev); - } - break; - - } -} - -} // namespace os diff --git a/src/os/x11/window.h b/src/os/x11/window.h deleted file mode 100644 index 4fa8ee1f8..000000000 --- a/src/os/x11/window.h +++ /dev/null @@ -1,83 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_X11_WINDOW_INCLUDED -#define OS_X11_WINDOW_INCLUDED -#pragma once - -#include "gfx/fwd.h" -#include "gfx/size.h" -#include "os/native_cursor.h" -#include "os/surface_list.h" - -#include -#include -#include -#include - -#include -#include - -namespace os { - -class Event; -class Surface; - -class X11Window { -public: - X11Window(::Display* display, int width, int height, int scale); - ~X11Window(); - - int scale() const { return m_scale; } - void setScale(const int scale); - - void setTitle(const std::string& title); - void setIcons(const SurfaceList& icons); - - gfx::Size clientSize() const; - gfx::Size restoredSize() const; - void captureMouse(); - void releaseMouse(); - void setMousePosition(const gfx::Point& position); - void updateWindow(const gfx::Rect& bounds); - bool setNativeMouseCursor(NativeCursor cursor); - bool setNativeMouseCursor(const os::Surface* surface, - const gfx::Point& focus, - const int scale); - - ::Display* x11display() const { return m_display; } - ::Window handle() const { return m_window; } - ::GC gc() const { return m_gc; } - - void setTranslateDeadKeys(bool state) { - // TODO - } - - void processX11Event(XEvent& event); - static X11Window* getPointerFromHandle(Window handle); - -protected: - virtual void queueEvent(Event& event) = 0; - virtual void paintGC(const gfx::Rect& rc) = 0; - virtual void resizeDisplay(const gfx::Size& sz) = 0; - -private: - bool setX11Cursor(::Cursor xcursor); - static void addWindow(X11Window* window); - static void removeWindow(X11Window* window); - - ::Display* m_display; - ::Window m_window; - ::GC m_gc; - ::Cursor m_cursor; - ::XcursorImage* m_xcursorImage; - ::XIC m_xic; - int m_scale; -}; - -} // namespace os - -#endif diff --git a/src/os/x11/x11.cpp b/src/os/x11/x11.cpp deleted file mode 100644 index dd214cdfc..000000000 --- a/src/os/x11/x11.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "os/x11/x11.h" - -namespace os { - -X11* X11::m_instance = nullptr; - -// static -X11* X11::instance() -{ - ASSERT(m_instance); - return m_instance; -} - -} // namespace os diff --git a/src/os/x11/x11.h b/src/os/x11/x11.h deleted file mode 100644 index f68ef7724..000000000 --- a/src/os/x11/x11.h +++ /dev/null @@ -1,44 +0,0 @@ -// LAF OS Library -// Copyright (C) 2016-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef OS_X11_X11_INCLUDED -#define OS_X11_X11_INCLUDED -#pragma once - -#include - -namespace os { - -class X11 { - static X11* m_instance; -public: - static X11* instance(); - - X11() { - ASSERT(m_instance == nullptr); - m_instance = this; - m_display = XOpenDisplay(nullptr); - m_xim = XOpenIM(m_display, nullptr, nullptr, nullptr); - } - - ~X11() { - ASSERT(m_instance == this); - if (m_xim) XCloseIM(m_xim); - XCloseDisplay(m_display); - m_instance = nullptr; - } - - ::Display* display() const { return m_display; } - ::XIM xim() const { return m_xim; } - -private: - ::Display* m_display; - ::XIM m_xim; -}; - -} // namespace os - -#endif diff --git a/src/render/CMakeLists.txt b/src/render/CMakeLists.txt index 811b0c9a3..9467f90d0 100644 --- a/src/render/CMakeLists.txt +++ b/src/render/CMakeLists.txt @@ -11,5 +11,5 @@ add_library(render-lib target_link_libraries(render-lib doc-lib - gfx-lib + laf-gfx laf-base) diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index c57565007..3ef348261 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -56,8 +56,8 @@ add_library(ui-lib window.cpp) target_link_libraries(ui-lib - os-lib - gfx-lib + laf-os + laf-gfx laf-base obs ${PIXMAN_LIBRARY})