From de6f7bae6756e5eda7b93d5e892919de99f9c546 Mon Sep 17 00:00:00 2001 From: OmniaX Date: Thu, 30 Nov 2023 10:36:15 +0100 Subject: [PATCH] Added Windows support --- .vscode/c_cpp_properties.json | 23 +- CMakeLists.txt | 47 +- README.md | 22 + compile | 23 +- src/ostd/File.cpp | 8 +- src/ostd/Utils.cpp | 6 +- src/ostd/Utils.hpp | 5 +- src/vendor/clip/clip.cpp | 174 ----- src/vendor/clip/clip.h | 180 ----- src/vendor/clip/clip_common.h | 76 --- src/vendor/clip/clip_lock_impl.h | 33 - src/vendor/clip/clip_win.cpp | 646 ------------------ src/vendor/clip/clip_win_wic.h | 246 ------- src/vendor/clip/clip_x11.cpp | 1094 ------------------------------ src/vendor/clip/clip_x11_png.h | 230 ------- src/vendor/clip/image.cpp | 99 --- tools/build.nr | 2 +- tools/create_includes.py | 80 --- tools/inc_bnr | Bin 25280 -> 16880 bytes tools/inc_bnr.exe | Bin 140989 -> 136717 bytes 20 files changed, 68 insertions(+), 2926 deletions(-) create mode 100644 README.md delete mode 100755 src/vendor/clip/clip.cpp delete mode 100755 src/vendor/clip/clip.h delete mode 100755 src/vendor/clip/clip_common.h delete mode 100755 src/vendor/clip/clip_lock_impl.h delete mode 100755 src/vendor/clip/clip_win.cpp delete mode 100755 src/vendor/clip/clip_win_wic.h delete mode 100755 src/vendor/clip/clip_x11.cpp delete mode 100755 src/vendor/clip/clip_x11_png.h delete mode 100755 src/vendor/clip/image.cpp delete mode 100755 tools/create_includes.py diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 8b8f6f2..fbe812b 100755 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -13,9 +13,26 @@ "compilerPath": "/usr/bin/clang++", "cStandard": "c17", "cppStandard": "c++20", - "intelliSenseMode": "linux-clang-x64", - "compileCommands": "${workspaceFolder}/Debug/compile_commands.json" + "intelliSenseMode": "linux-clang-x64" + //"compileCommands": "${workspaceFolder}/compile_commands.json" + }, + { + "name": "Windows", + "includePath": [ + "${default}", + "${workspaceRoot}/src/vendor/GLAD", + "${workspaceRoot}/src/vendor", + "${workspaceRoot}/src/ostd", + "${workspaceRoot}/src" + ], + "defines": [], + "compilerPath": "C:\\msys64\\ucrt64\\bin\\clang++", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "linux-clang-x64" + //"compileCommands": "${workspaceFolder}/compile_commands.json" } ], "version": 4 -} \ No newline at end of file +} + diff --git a/CMakeLists.txt b/CMakeLists.txt index 75d1a83..9584b99 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ #Setup #----------------------------------------------------------------------------------------- set(CMAKE_CXX_COMPILER "clang++") +set(CMAKE_C_COMPILER "clang") cmake_minimum_required(VERSION 3.18) project(${PROJ_NAME} LANGUAGES C CXX) set(CMAKE_BUILD_TYPE Debug) @@ -27,33 +28,18 @@ message("** Building ${PROJ_NAME} ${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}") #Sources #----------------------------------------------------------------------------------------- -list(APPEND OSTD_VENDOR_SOURCES - ${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/clip.cpp - ${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/image.cpp -) -list(APPEND OGFX_VENDOR_SOURCES - ${CMAKE_CURRENT_LIST_DIR}/src/vendor/GLAD/glad.c -) - list(APPEND INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/src ${CMAKE_CURRENT_LIST_DIR}/src/ostd ${CMAKE_CURRENT_LIST_DIR}/src/vendor ${CMAKE_CURRENT_LIST_DIR}/src/vendor/GLAD ) - list(APPEND TEST_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/test/main.cpp ${CMAKE_CURRENT_LIST_DIR}/src/test/TestApp2D.cpp ${CMAKE_CURRENT_LIST_DIR}/src/test/TestApp3D.cpp ${CMAKE_CURRENT_LIST_DIR}/src/test/TetrisApp.cpp ) -list(APPEND OSH_SOURCE_FILES - ${CMAKE_CURRENT_LIST_DIR}/src/osh/commandShell.cpp -) -list(APPEND OXGE_SOURCE_FILES - ${CMAKE_CURRENT_LIST_DIR}/src/oxge/iso/Engine.cpp -) list(APPEND OGFX_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/BitmapFont.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/BlendRenderer.cpp @@ -73,8 +59,8 @@ list(APPEND OGFX_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Texture.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Window.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Widgets.cpp - ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/DebugTools.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/vendor/GLAD/glad.c ) list(APPEND OSTD_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ostd/BaseObject.cpp @@ -99,24 +85,8 @@ list(APPEND OSTD_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ostd/StringEditor.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ostd/Utils.cpp ) - -if (WIN32) - list(APPEND OSTD_VENDOR_SOURCES - ${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/clip_win.cpp - ) -endif (WIN32) -if (UNIX) - list(APPEND OSTD_VENDOR_SOURCES - ${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/clip_x11.cpp - ) -endif (UNIX) - -list(APPEND OSTD_SOURCE_FILES ${OSTD_VENDOR_SOURCES}) -list(APPEND OGFX_SOURCE_FILES ${OGFX_VENDOR_SOURCES}) #----------------------------------------------------------------------------------------- - - #Targets #----------------------------------------------------------------------------------------- add_library(${OMNIA_STD_LIB} SHARED ${OSTD_SOURCE_FILES}) @@ -140,8 +110,6 @@ endif (UNIX) target_link_libraries(${OMNIA_GFX_LIB} PUBLIC sfml-system sfml-window sfml-graphics) #----------------------------------------------------------------------------------------- - - #Linking Targets #----------------------------------------------------------------------------------------- target_link_libraries(${OMNIA_GFX_LIB} PUBLIC ${OMNIA_STD_LIB}) @@ -150,8 +118,6 @@ target_link_libraries(${TEST_TARGET} PUBLIC ${OMNIA_STD_LIB}) target_link_libraries(${TEST_TARGET} PUBLIC ${OMNIA_GFX_LIB}) #----------------------------------------------------------------------------------------- - - #BuildNumber Target #----------------------------------------------------------------------------------------- if (WIN32) @@ -174,8 +140,7 @@ add_custom_target( #----------------------------------------------------------------------------------------- - -#Install +#Finalize #----------------------------------------------------------------------------------------- #TODO: Change TEST_TARGET to last lib built, for release config add_custom_command(TARGET ${TEST_TARGET} POST_BUILD @@ -183,12 +148,6 @@ add_custom_command(TARGET ${TEST_TARGET} POST_BUILD ${CMAKE_SOURCE_DIR}/extra/ $ VERBATIM ) - -set(CMAKE_INSTALL_MESSAGE NEVER) -install(TARGETS ${OMNIA_STD_LIB} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Build/bin) -install(TARGETS ${OMNIA_GFX_LIB} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Build/bin) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/licences DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Build) - add_custom_target(FinalMessage ALL ${CMAKE_COMMAND} -E cmake_echo_color --cyan "[100%] Built ${PROJ_NAME} ${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}") add_dependencies(FinalMessage ${TEST_TARGET}) #----------------------------------------------------------------------------------------- diff --git a/README.md b/README.md new file mode 100644 index 0000000..8ed4f9a --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# OmniaFramework + +Compile instructions on Windows + +**Step 1:** +download MSYS2 from https://www.msys2.org/ and install it + +**Step 2:** +run MSYS2, and in the terminal run: +``` +pacman -Syuu +pacman -S --needed base-devel mingw-w64-ucrt-x86_64-clang mingw-w64-ucrt-x86_64-gdb mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-sfml mingw-w64-ucrt-x86_64-make +``` + +**Step 3:** +open a UCRT64/MSYS2 command prompt inside the root directory of the project + +**Step 4:** +execute this command: +``` +./compile +``` diff --git a/compile b/compile index 1892174..b7df819 100755 --- a/compile +++ b/compile @@ -1,14 +1,15 @@ #/bin/bash -rm -r Build rm -r bin -#export CXX=/usr/bin/clang++ -cmake -B bin -S ./ -cd bin -make install -cd .. -if [ $? -eq 0 ]; then - printf "Installing includes...\n" - python ./tools/create_includes.py - printf "Done!\n" -fi + +if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + cmake -B bin -S ./ + cd bin + make + cd .. +elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then + cmake -B bin -S ./ -G "MinGW Makefiles" + cd bin + mingw32-make.exe + cd .. +fi \ No newline at end of file diff --git a/src/ostd/File.cpp b/src/ostd/File.cpp index a7047cf..06817ab 100755 --- a/src/ostd/File.cpp +++ b/src/ostd/File.cpp @@ -24,10 +24,10 @@ namespace ostd if (!file.is_open()) return *this; m_buffer = { std::istreambuf_iterator(file), std::istreambuf_iterator() }; - m_extension = filePath.extension(); - m_fullPath = filePath; - m_fullName = filePath.filename(); - m_name = filePath.stem(); + m_extension = filePath.extension().string(); + m_fullPath = filePath.string(); + m_fullName = filePath.filename().string(); + m_name = filePath.stem().string(); StringEditor pathEditor(m_fullPath); if (pathEditor.contains('/')) m_directoryPath = pathEditor.substr(0, pathEditor.lastIndexOf('/')); diff --git a/src/ostd/Utils.cpp b/src/ostd/Utils.cpp index 91a83c0..856496e 100755 --- a/src/ostd/Utils.cpp +++ b/src/ostd/Utils.cpp @@ -1,7 +1,7 @@ #include "Utils.hpp" #include "Defines.hpp" #include -#include +//#include #include #include #include @@ -682,7 +682,7 @@ namespace ostd return std::chrono::duration_cast (std::chrono::system_clock::now().time_since_epoch()).count() - Utils::s_startTime_ms; } - bool Utils::setClipboardText(String text) + /*bool Utils::setClipboardText(String text) { return clip::set_text(text); } @@ -692,7 +692,7 @@ namespace ostd String text = ""; if (!clip::get_text(text)) return ""; return text; - } + }*/ float Utils::map_value(float input, float input_start, float input_end, float output_start, float output_end) { diff --git a/src/ostd/Utils.hpp b/src/ostd/Utils.hpp index 0c96091..ef79e7b 100755 --- a/src/ostd/Utils.hpp +++ b/src/ostd/Utils.hpp @@ -150,8 +150,9 @@ namespace ostd static String duplicateChar(unsigned char c, uint16_t count); static void sleep(uint32_t __time, eTimeUnits __unit = eTimeUnits::Milliseconds); static uint64_t getRunningTime_ms(void); - static bool setClipboardText(String text); - static String getClipboardText(void); + //TODO: Doesn't work on Windows + //static bool setClipboardText(String text); + //static String getClipboardText(void); static float map_value(float input, float input_start, float input_end, float output_start, float output_end); static bool loadFileFromHppResource(String output_file_path, const char* resource_buffer, unsigned int size); static void printByteStream(const ByteStream& data, StreamIndex start, uint8_t line_len, uint16_t n_rows, IOutputHandler& out, int32_t addrHighlight = -1, uint32_t highlightRange = 1, const String& title = ""); diff --git a/src/vendor/clip/clip.cpp b/src/vendor/clip/clip.cpp deleted file mode 100755 index bd221fc..0000000 --- a/src/vendor/clip/clip.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// Clip Library -// Copyright (c) 2015-2018 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "clip.h" -#include "clip_lock_impl.h" - -#include -#include - -namespace clip { - -namespace { - -void default_error_handler(ErrorCode code) { - static const char* err[] = { - "Cannot lock clipboard", - "Image format is not supported" - }; - throw std::runtime_error(err[static_cast(code)]); -} - -} // anonymous namespace - -error_handler g_error_handler = default_error_handler; - -lock::lock(void* native_window_handle) - : p(new impl(native_window_handle)) { -} - -lock::~lock() = default; - -bool lock::locked() const { - return p->locked(); -} - -bool lock::clear() { - return p->clear(); -} - -bool lock::is_convertible(format f) const { - return p->is_convertible(f); -} - -bool lock::set_data(format f, const char* buf, size_t length) { - return p->set_data(f, buf, length); -} - -bool lock::get_data(format f, char* buf, size_t len) const { - return p->get_data(f, buf, len); -} - -size_t lock::get_data_length(format f) const { - return p->get_data_length(f); -} - -bool lock::set_image(const image& img) { - return p->set_image(img); -} - -bool lock::get_image(image& img) const { - return p->get_image(img); -} - -bool lock::get_image_spec(image_spec& spec) const { - return p->get_image_spec(spec); -} - -format empty_format() { return 0; } -format text_format() { return 1; } -format image_format() { return 2; } - -bool has(format f) { - lock l; - if (l.locked()) - return l.is_convertible(f); - else - return false; -} - -bool clear() { - lock l; - if (l.locked()) - return l.clear(); - else - return false; -} - -bool set_text(const std::string& value) { - lock l; - if (l.locked()) { - l.clear(); - return l.set_data(text_format(), value.c_str(), value.size()); - } - else - return false; -} - -bool get_text(std::string& value) { - lock l; - if (!l.locked()) - return false; - - format f = text_format(); - if (!l.is_convertible(f)) - return false; - - size_t len = l.get_data_length(f); - if (len > 0) { - std::vector buf(len); - l.get_data(f, &buf[0], len); - value = &buf[0]; - return true; - } - else { - value.clear(); - return true; - } -} - -bool set_image(const image& img) { - lock l; - if (l.locked()) { - l.clear(); - return l.set_image(img); - } - else - return false; -} - -bool get_image(image& img) { - lock l; - if (!l.locked()) - return false; - - format f = image_format(); - if (!l.is_convertible(f)) - return false; - - return l.get_image(img); -} - -bool get_image_spec(image_spec& spec) { - lock l; - if (!l.locked()) - return false; - - format f = image_format(); - if (!l.is_convertible(f)) - return false; - - return l.get_image_spec(spec); -} - -void set_error_handler(error_handler handler) { - g_error_handler = handler; -} - -error_handler get_error_handler() { - return g_error_handler; -} - -#ifdef HAVE_XCB_XLIB_H -static int g_x11_timeout = 1000; -void set_x11_wait_timeout(int msecs) { g_x11_timeout = msecs; } -int get_x11_wait_timeout() { return g_x11_timeout; } -#else -void set_x11_wait_timeout(int) { } -int get_x11_wait_timeout() { return 1000; } -#endif - -} // namespace clip diff --git a/src/vendor/clip/clip.h b/src/vendor/clip/clip.h deleted file mode 100755 index bf3c9fd..0000000 --- a/src/vendor/clip/clip.h +++ /dev/null @@ -1,180 +0,0 @@ -// Clip Library -// Copyright (c) 2015-2022 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef CLIP_H_INCLUDED -#define CLIP_H_INCLUDED -#pragma once - -#include -#include -#include - -namespace clip { - - // ====================================================================== - // Low-level API to lock the clipboard/pasteboard and modify it - // ====================================================================== - - // Clipboard format identifier. - typedef size_t format; - - class image; - struct image_spec; - - class lock { - public: - // You can give your current HWND as the "native_window_handle." - // Windows clipboard functions use this handle to open/close - // (lock/unlock) the clipboard. From the MSDN documentation we - // need this handler so SetClipboardData() doesn't fail after a - // EmptyClipboard() call. Anyway it looks to work just fine if we - // call OpenClipboard() with a null HWND. - lock(void* native_window_handle = nullptr); - ~lock(); - - // Returns true if we've locked the clipboard successfully in - // lock() constructor. - bool locked() const; - - // Clears the clipboard content. If you don't clear the content, - // previous clipboard content (in unknown formats) could persist - // after the unlock. - bool clear(); - - // Returns true if the clipboard can be converted to the given - // format. - bool is_convertible(format f) const; - bool set_data(format f, const char* buf, size_t len); - bool get_data(format f, char* buf, size_t len) const; - size_t get_data_length(format f) const; - - // For images - bool set_image(const image& image); - bool get_image(image& image) const; - bool get_image_spec(image_spec& spec) const; - - private: - class impl; - std::unique_ptr p; - }; - - format register_format(const std::string& name); - - // This format is when the clipboard has no content. - format empty_format(); - - // When the clipboard has UTF8 text. - format text_format(); - - // When the clipboard has an image. - format image_format(); - - // Returns true if the clipboard has content of the given type. - bool has(format f); - - // Clears the clipboard content. - bool clear(); - - // ====================================================================== - // Error handling - // ====================================================================== - - enum class ErrorCode { - CannotLock, - ImageNotSupported, - }; - - typedef void (*error_handler)(ErrorCode code); - - void set_error_handler(error_handler f); - error_handler get_error_handler(); - - // ====================================================================== - // Text - // ====================================================================== - - // High-level API to put/get UTF8 text in/from the clipboard. These - // functions returns false in case of error. - bool set_text(const std::string& value); - bool get_text(std::string& value); - - // ====================================================================== - // Image - // ====================================================================== - - struct image_spec { - unsigned long width = 0; - unsigned long height = 0; - unsigned long bits_per_pixel = 0; - unsigned long bytes_per_row = 0; - unsigned long red_mask = 0; - unsigned long green_mask = 0; - unsigned long blue_mask = 0; - unsigned long alpha_mask = 0; - unsigned long red_shift = 0; - unsigned long green_shift = 0; - unsigned long blue_shift = 0; - unsigned long alpha_shift = 0; - - unsigned long required_data_size() const; - }; - - // The image data must contain straight RGB values - // (non-premultiplied by alpha). The image retrieved from the - // clipboard will be non-premultiplied too. Basically you will be - // always dealing with straight alpha images. - // - // Details: Windows expects premultiplied images on its clipboard - // content, so the library code make the proper conversion - // automatically. macOS handles straight alpha directly, so there is - // no conversion at all. Linux/X11 images are transferred in - // image/png format which are specified in straight alpha. - class image { - public: - image(); - image(const image_spec& spec); - image(const void* data, const image_spec& spec); - image(const image& image); - image(image&& image); - ~image(); - - image& operator=(const image& image); - image& operator=(image&& image); - - char* data() const { return m_data; } - const image_spec& spec() const { return m_spec; } - - bool is_valid() const { return m_data != nullptr; } - void reset(); - - private: - void copy_image(const image& image); - void move_image(image&& image); - - bool m_own_data; - char* m_data; - image_spec m_spec; - }; - - // High-level API to set/get an image in/from the clipboard. These - // functions returns false in case of error. - bool set_image(const image& img); - bool get_image(image& img); - bool get_image_spec(image_spec& spec); - - // ====================================================================== - // Platform-specific - // ====================================================================== - - // Only for X11: Sets the time (in milliseconds) that we must wait - // for the selection/clipboard owner to receive the content. This - // value is 1000 (one second) by default. - void set_x11_wait_timeout(int msecs); - int get_x11_wait_timeout(); - -} // namespace clip - -#endif // CLIP_H_INCLUDED diff --git a/src/vendor/clip/clip_common.h b/src/vendor/clip/clip_common.h deleted file mode 100755 index ebe0d72..0000000 --- a/src/vendor/clip/clip_common.h +++ /dev/null @@ -1,76 +0,0 @@ -// Clip Library -// Copyright (C) 2020 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#ifndef CLIP_COMMON_H_INCLUDED -#define CLIP_COMMON_H_INCLUDED -#pragma once - -namespace clip { -namespace details { - -inline void divide_rgb_by_alpha(image& img, - bool hasAlphaGreaterThanZero = false) { - const image_spec& spec = img.spec(); - - bool hasValidPremultipliedAlpha = true; - - for (unsigned long y=0; y> spec.red_shift ); - const int g = ((c & spec.green_mask) >> spec.green_shift); - const int b = ((c & spec.blue_mask ) >> spec.blue_shift ); - const int a = ((c & spec.alpha_mask) >> spec.alpha_shift); - - if (a > 0) - hasAlphaGreaterThanZero = true; - if (r > a || g > a || b > a) - hasValidPremultipliedAlpha = false; - } - } - - for (unsigned long y=0; y> spec.red_shift ); - int g = ((c & spec.green_mask) >> spec.green_shift); - int b = ((c & spec.blue_mask ) >> spec.blue_shift ); - int a = ((c & spec.alpha_mask) >> spec.alpha_shift); - - // If all alpha values = 0, we make the image opaque. - if (!hasAlphaGreaterThanZero) { - a = 255; - - // We cannot change the image spec (e.g. spec.alpha_mask=0) to - // make the image opaque, because the "spec" of the image is - // read-only. The image spec used by the client is the one - // returned by get_image_spec(). - } - // If there is alpha information and it's pre-multiplied alpha - else if (hasValidPremultipliedAlpha) { - if (a > 0) { - // Convert it to straight alpha - r = r * 255 / a; - g = g * 255 / a; - b = b * 255 / a; - } - } - - *dst = - (r << spec.red_shift ) | - (g << spec.green_shift) | - (b << spec.blue_shift ) | - (a << spec.alpha_shift); - } - } -} - -} // namespace details -} // namespace clip - -#endif // CLIP_H_INCLUDED diff --git a/src/vendor/clip/clip_lock_impl.h b/src/vendor/clip/clip_lock_impl.h deleted file mode 100755 index 3f08af7..0000000 --- a/src/vendor/clip/clip_lock_impl.h +++ /dev/null @@ -1,33 +0,0 @@ -// Clip 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 CLIP_LOCK_IMPL_H_INCLUDED -#define CLIP_LOCK_IMPL_H_INCLUDED - -namespace clip { - -class lock::impl { -public: - impl(void* native_window_handle); - ~impl(); - - bool locked() const { return m_locked; } - bool clear(); - bool is_convertible(format f) const; - bool set_data(format f, const char* buf, size_t len); - bool get_data(format f, char* buf, size_t len) const; - size_t get_data_length(format f) const; - bool set_image(const image& image); - bool get_image(image& image) const; - bool get_image_spec(image_spec& spec) const; - -private: - bool m_locked; -}; - -} // namespace clip - -#endif diff --git a/src/vendor/clip/clip_win.cpp b/src/vendor/clip/clip_win.cpp deleted file mode 100755 index 4fabb7e..0000000 --- a/src/vendor/clip/clip_win.cpp +++ /dev/null @@ -1,646 +0,0 @@ -// Clip Library -// Copyright (C) 2015-2020 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "clip.h" -#include "clip_common.h" -#include "clip_lock_impl.h" - -#include -#include -#include -#include -#include - -#include - -#include "clip_win_wic.h" - -#ifndef LCS_WINDOWS_COLOR_SPACE -#define LCS_WINDOWS_COLOR_SPACE 'Win ' -#endif - -#ifndef CF_DIBV5 -#define CF_DIBV5 17 -#endif - -namespace clip { - -namespace { - -// Data type used as header for custom formats to indicate the exact -// size of the user custom data. This is necessary because it looks -// like GlobalSize() might not return the exact size, but a greater -// value. -typedef uint64_t CustomSizeT; - -unsigned long get_shift_from_mask(unsigned long mask) { - unsigned long shift = 0; - for (shift=0; shiftbV5BitCount == 32 && - ((b5->bV5Compression == BI_RGB) || - (b5->bV5Compression == BI_BITFIELDS && - b5->bV5RedMask && b5->bV5GreenMask && - b5->bV5BlueMask && b5->bV5AlphaMask))) { - width = b5->bV5Width; - height = b5->bV5Height; - bit_count = b5->bV5BitCount; - compression = b5->bV5Compression; - if (compression == BI_BITFIELDS) { - red_mask = b5->bV5RedMask; - green_mask = b5->bV5GreenMask; - blue_mask = b5->bV5BlueMask; - alpha_mask = b5->bV5AlphaMask; - } - else { - red_mask = 0xff0000; - green_mask = 0xff00; - blue_mask = 0xff; - alpha_mask = 0xff000000; - } - return; - } - } - - if (IsClipboardFormatAvailable(CF_DIB)) - bi = (BITMAPINFO*)GetClipboardData(CF_DIB); - if (!bi) - return; - - width = bi->bmiHeader.biWidth; - height = bi->bmiHeader.biHeight; - bit_count = bi->bmiHeader.biBitCount; - compression = bi->bmiHeader.biCompression; - - if (compression == BI_BITFIELDS) { - red_mask = *((uint32_t*)&bi->bmiColors[0]); - green_mask = *((uint32_t*)&bi->bmiColors[1]); - blue_mask = *((uint32_t*)&bi->bmiColors[2]); - if (bit_count == 32) - alpha_mask = 0xff000000; - } - else if (compression == BI_RGB) { - switch (bit_count) { - case 32: - red_mask = 0xff0000; - green_mask = 0xff00; - blue_mask = 0xff; - alpha_mask = 0xff000000; - break; - case 24: - red_mask = 0xff0000; - green_mask = 0xff00; - blue_mask = 0xff; - break; - case 16: - red_mask = 0x7c00; - green_mask = 0x03e0; - blue_mask = 0x001f; - break; - } - } - } - - bool is_valid() const { - return (b5 || bi); - } - - void fill_spec(image_spec& spec) { - spec.width = width; - spec.height = (height >= 0 ? height: -height); - // We convert indexed to 24bpp RGB images to match the OS X behavior - spec.bits_per_pixel = bit_count; - if (spec.bits_per_pixel <= 8) - spec.bits_per_pixel = 24; - spec.bytes_per_row = width*((spec.bits_per_pixel+7)/8); - spec.red_mask = red_mask; - spec.green_mask = green_mask; - spec.blue_mask = blue_mask; - spec.alpha_mask = alpha_mask; - - switch (spec.bits_per_pixel) { - - case 24: { - // We need one extra byte to avoid a crash updating the last - // pixel on last row using: - // - // *((uint32_t*)ptr) = pixel24bpp; - // - ++spec.bytes_per_row; - - // Align each row to 32bpp - int padding = (4-(spec.bytes_per_row&3))&3; - spec.bytes_per_row += padding; - break; - } - - case 16: { - int padding = (4-(spec.bytes_per_row&3))&3; - spec.bytes_per_row += padding; - break; - } - } - - unsigned long* masks = &spec.red_mask; - unsigned long* shifts = &spec.red_shift; - for (unsigned long* shift=shifts, *mask=masks; shift 0) { - int reqsize = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0); - if (reqsize > 0) { - ++reqsize; - - Hglobal hglobal(sizeof(WCHAR)*reqsize); - LPWSTR lpstr = static_cast(GlobalLock(hglobal)); - MultiByteToWideChar(CP_UTF8, 0, buf, len, lpstr, reqsize); - GlobalUnlock(hglobal); - - result = (SetClipboardData(CF_UNICODETEXT, hglobal)) ? true: false; - if (result) - hglobal.release(); - } - } - } - else { - Hglobal hglobal(len+sizeof(CustomSizeT)); - if (hglobal) { - auto dst = (uint8_t*)GlobalLock(hglobal); - if (dst) { - *((CustomSizeT*)dst) = len; - memcpy(dst+sizeof(CustomSizeT), buf, len); - GlobalUnlock(hglobal); - result = (SetClipboardData(f, hglobal) ? true: false); - if (result) - hglobal.release(); - } - } - } - - return result; -} - -bool lock::impl::get_data(format f, char* buf, size_t len) const { - assert(buf); - - if (!buf || !is_convertible(f)) - return false; - - bool result = false; - - if (f == text_format()) { - if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { - HGLOBAL hglobal = GetClipboardData(CF_UNICODETEXT); - if (hglobal) { - LPWSTR lpstr = static_cast(GlobalLock(hglobal)); - if (lpstr) { - size_t reqsize = - WideCharToMultiByte(CP_UTF8, 0, lpstr, -1, - nullptr, 0, nullptr, nullptr); - - assert(reqsize <= len); - if (reqsize <= len) { - WideCharToMultiByte(CP_UTF8, 0, lpstr, -1, - buf, reqsize, nullptr, nullptr); - result = true; - } - GlobalUnlock(hglobal); - } - } - } - else if (IsClipboardFormatAvailable(CF_TEXT)) { - HGLOBAL hglobal = GetClipboardData(CF_TEXT); - if (hglobal) { - LPSTR lpstr = static_cast(GlobalLock(hglobal)); - if (lpstr) { - // TODO check length - memcpy(buf, lpstr, len); - result = true; - GlobalUnlock(hglobal); - } - } - } - } - else { - if (IsClipboardFormatAvailable(f)) { - HGLOBAL hglobal = GetClipboardData(f); - if (hglobal) { - const SIZE_T total_size = GlobalSize(hglobal); - auto ptr = (const uint8_t*)GlobalLock(hglobal); - if (ptr) { - CustomSizeT reqsize = *((CustomSizeT*)ptr); - - // If the registered length of data in the first CustomSizeT - // number of bytes of the hglobal data is greater than the - // GlobalSize(hglobal), something is wrong, it should not - // happen. - assert(reqsize <= total_size); - if (reqsize > total_size) - reqsize = total_size - sizeof(CustomSizeT); - - if (reqsize <= len) { - memcpy(buf, ptr+sizeof(CustomSizeT), reqsize); - result = true; - } - GlobalUnlock(hglobal); - } - } - } - } - - return result; -} - -size_t lock::impl::get_data_length(format f) const { - size_t len = 0; - - if (f == text_format()) { - if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { - HGLOBAL hglobal = GetClipboardData(CF_UNICODETEXT); - if (hglobal) { - LPWSTR lpstr = static_cast(GlobalLock(hglobal)); - if (lpstr) { - len = - WideCharToMultiByte(CP_UTF8, 0, lpstr, -1, - nullptr, 0, nullptr, nullptr); - GlobalUnlock(hglobal); - } - } - } - else if (IsClipboardFormatAvailable(CF_TEXT)) { - HGLOBAL hglobal = GetClipboardData(CF_TEXT); - if (hglobal) { - LPSTR lpstr = (LPSTR)GlobalLock(hglobal); - if (lpstr) { - len = strlen(lpstr) + 1; - GlobalUnlock(hglobal); - } - } - } - } - else if (f != empty_format()) { - if (IsClipboardFormatAvailable(f)) { - HGLOBAL hglobal = GetClipboardData(f); - if (hglobal) { - const SIZE_T total_size = GlobalSize(hglobal); - auto ptr = (const uint8_t*)GlobalLock(hglobal); - if (ptr) { - len = *((CustomSizeT*)ptr); - - assert(len <= total_size); - if (len > total_size) - len = total_size - sizeof(CustomSizeT); - - GlobalUnlock(hglobal); - } - } - } - } - - return len; -} - -bool lock::impl::set_image(const image& image) { - const image_spec& spec = image.spec(); - - // Add the PNG clipboard format for images with alpha channel - // (useful to communicate with some Windows programs that only use - // alpha data from PNG clipboard format) - if (spec.bits_per_pixel == 32 && - spec.alpha_mask) { - UINT png_format = RegisterClipboardFormatA("PNG"); - if (png_format) { - Hglobal png_handle(win::write_png(image)); - if (png_handle) - SetClipboardData(png_format, png_handle); - } - } - - image_spec out_spec = spec; - - int palette_colors = 0; - int padding = 0; - switch (spec.bits_per_pixel) { - case 24: padding = (4-((spec.width*3)&3))&3; break; - case 16: padding = ((4-((spec.width*2)&3))&3)/2; break; - case 8: padding = (4-(spec.width&3))&3; break; - } - out_spec.bytes_per_row += padding; - - // Create the BITMAPV5HEADER structure - Hglobal hmem( - GlobalAlloc( - GHND, - sizeof(BITMAPV5HEADER) - + palette_colors*sizeof(RGBQUAD) - + out_spec.bytes_per_row*out_spec.height)); - if (!hmem) - return false; - - out_spec.red_mask = 0x00ff0000; - out_spec.green_mask = 0xff00; - out_spec.blue_mask = 0xff; - out_spec.alpha_mask = 0xff000000; - out_spec.red_shift = 16; - out_spec.green_shift = 8; - out_spec.blue_shift = 0; - out_spec.alpha_shift = 24; - - BITMAPV5HEADER* bi = (BITMAPV5HEADER*)GlobalLock(hmem); - bi->bV5Size = sizeof(BITMAPV5HEADER); - bi->bV5Width = out_spec.width; - bi->bV5Height = out_spec.height; - bi->bV5Planes = 1; - bi->bV5BitCount = (WORD)out_spec.bits_per_pixel; - bi->bV5Compression = BI_RGB; - bi->bV5SizeImage = out_spec.bytes_per_row*spec.height; - bi->bV5RedMask = out_spec.red_mask; - bi->bV5GreenMask = out_spec.green_mask; - bi->bV5BlueMask = out_spec.blue_mask; - bi->bV5AlphaMask = out_spec.alpha_mask; - bi->bV5CSType = LCS_WINDOWS_COLOR_SPACE; - bi->bV5Intent = LCS_GM_GRAPHICS; - bi->bV5ClrUsed = 0; - - switch (spec.bits_per_pixel) { - case 32: { - const char* src = image.data(); - char* dst = (((char*)bi)+bi->bV5Size) + (out_spec.height-1)*out_spec.bytes_per_row; - for (long y=spec.height-1; y>=0; --y) { - const uint32_t* src_x = (const uint32_t*)src; - uint32_t* dst_x = (uint32_t*)dst; - - for (unsigned long x=0; x> spec.red_shift ); - int g = ((c & spec.green_mask) >> spec.green_shift); - int b = ((c & spec.blue_mask ) >> spec.blue_shift ); - int a = ((c & spec.alpha_mask) >> spec.alpha_shift); - - // Windows requires premultiplied RGBA values - r = r * a / 255; - g = g * a / 255; - b = b * a / 255; - - *dst_x = - (r << out_spec.red_shift ) | - (g << out_spec.green_shift) | - (b << out_spec.blue_shift ) | - (a << out_spec.alpha_shift); - } - - src += spec.bytes_per_row; - dst -= out_spec.bytes_per_row; - } - break; - } - default: - error_handler e = get_error_handler(); - if (e) - e(ErrorCode::ImageNotSupported); - return false; - } - - GlobalUnlock(hmem); - SetClipboardData(CF_DIBV5, hmem); - return true; -} - -bool lock::impl::get_image(image& output_img) const { - // Get the "PNG" clipboard format (this is useful only for 32bpp - // images with alpha channel, in other case we can use the regular - // DIB format) - UINT png_format = RegisterClipboardFormatA("PNG"); - if (png_format && IsClipboardFormatAvailable(png_format)) { - HANDLE png_handle = GetClipboardData(png_format); - if (png_handle) { - size_t png_size = GlobalSize(png_handle); - uint8_t* png_data = (uint8_t*)GlobalLock(png_handle); - bool result = win::read_png(png_data, png_size, &output_img, nullptr); - GlobalUnlock(png_handle); - if (result) - return true; - } - } - - BitmapInfo bi; - if (!bi.is_valid()) { - // There is no image at all in the clipboard, no need to report - // this as an error, just return false. - return false; - } - - image_spec spec; - bi.fill_spec(spec); - image img(spec); - - switch (bi.bit_count) { - - case 32: - case 24: - case 16: { - const uint8_t* src = nullptr; - - if (bi.compression == BI_RGB || - bi.compression == BI_BITFIELDS) { - if (bi.b5) - src = ((uint8_t*)bi.b5) + bi.b5->bV5Size; - else - src = ((uint8_t*)bi.bi) + bi.bi->bmiHeader.biSize; - if (bi.compression == BI_BITFIELDS) - src += sizeof(RGBQUAD)*3; - } - - if (src) { - const int src_bytes_per_row = spec.width*((bi.bit_count+7)/8); - const int padding = (4-(src_bytes_per_row&3))&3; - - for (long y=spec.height-1; y>=0; --y, src+=src_bytes_per_row+padding) { - char* dst = img.data()+y*spec.bytes_per_row; - std::copy(src, src+src_bytes_per_row, dst); - } - } - - // Windows uses premultiplied RGB values, and we use straight - // alpha. So we have to divide all RGB values by its alpha. - if (bi.bit_count == 32 && spec.alpha_mask) { - details::divide_rgb_by_alpha(img); - } - break; - } - - case 8: { - assert(bi.bi); - - const int colors = (bi.bi->bmiHeader.biClrUsed > 0 ? bi.bi->bmiHeader.biClrUsed: 256); - std::vector palette(colors); - for (int c=0; cbmiColors[c].rgbRed << spec.red_shift) | - (bi.bi->bmiColors[c].rgbGreen << spec.green_shift) | - (bi.bi->bmiColors[c].rgbBlue << spec.blue_shift); - } - - const uint8_t* src = (((uint8_t*)bi.bi) + bi.bi->bmiHeader.biSize + sizeof(RGBQUAD)*colors); - const int padding = (4-(spec.width&3))&3; - - for (long y=spec.height-1; y>=0; --y, src+=padding) { - char* dst = img.data()+y*spec.bytes_per_row; - - for (unsigned long x=0; x= colors) - idx = colors-1; - - *((uint32_t*)dst) = palette[idx]; - } - } - break; - } - } - - std::swap(output_img, img); - return true; -} - -bool lock::impl::get_image_spec(image_spec& spec) const { - UINT png_format = RegisterClipboardFormatA("PNG"); - if (png_format && IsClipboardFormatAvailable(png_format)) { - HANDLE png_handle = GetClipboardData(png_format); - if (png_handle) { - size_t png_size = GlobalSize(png_handle); - uint8_t* png_data = (uint8_t*)GlobalLock(png_handle); - bool result = win::read_png(png_data, png_size, nullptr, &spec); - GlobalUnlock(png_handle); - if (result) - return true; - } - } - - BitmapInfo bi; - if (!bi.is_valid()) - return false; - bi.fill_spec(spec); - return true; -} - -format register_format(const std::string& name) { - int reqsize = 1+MultiByteToWideChar(CP_UTF8, 0, - name.c_str(), name.size(), NULL, 0); - std::vector buf(reqsize); - MultiByteToWideChar(CP_UTF8, 0, name.c_str(), name.size(), - &buf[0], reqsize); - - // From MSDN, registered clipboard formats are identified by values - // in the range 0xC000 through 0xFFFF. - return (format)RegisterClipboardFormatW(&buf[0]); -} - -} // namespace clip diff --git a/src/vendor/clip/clip_win_wic.h b/src/vendor/clip/clip_win_wic.h deleted file mode 100755 index c0dbc9b..0000000 --- a/src/vendor/clip/clip_win_wic.h +++ /dev/null @@ -1,246 +0,0 @@ -// Clip Library -// Copyright (c) 2020 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "clip.h" - -#include -#include - -#include -#include - -namespace clip { -namespace win { - -// Successful calls to CoInitialize() (S_OK or S_FALSE) must match -// the calls to CoUninitialize(). -// From: https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-couninitialize#remarks -struct coinit { - HRESULT hr; - coinit() { - hr = CoInitialize(nullptr); - } - ~coinit() { - if (hr == S_OK || hr == S_FALSE) - CoUninitialize(); - } -}; - -template -class comptr { -public: - comptr() : m_ptr(nullptr) { } - explicit comptr(T* ptr) : m_ptr(ptr) { } - comptr(const comptr&) = delete; - comptr& operator=(const comptr&) = delete; - ~comptr() { reset(); } - - T** operator&() { return &m_ptr; } - T* operator->() { return m_ptr; } - bool operator!() const { return !m_ptr; } - - T* get() { return m_ptr; } - void reset() { - if (m_ptr) { - m_ptr->Release(); - m_ptr = nullptr; - } - } -private: - T* m_ptr; -}; - -////////////////////////////////////////////////////////////////////// -// Encode the image as PNG format - -bool write_png_on_stream(const image& image, - IStream* stream) { - const image_spec& spec = image.spec(); - - comptr encoder; - HRESULT hr = CoCreateInstance(CLSID_WICPngEncoder, - nullptr, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&encoder)); - if (FAILED(hr)) - return false; - - hr = encoder->Initialize(stream, WICBitmapEncoderNoCache); - if (FAILED(hr)) - return false; - - comptr frame; - comptr options; - hr = encoder->CreateNewFrame(&frame, &options); - if (FAILED(hr)) - return false; - - hr = frame->Initialize(options.get()); - if (FAILED(hr)) - return false; - - // PNG encoder (and decoder) only supports GUID_WICPixelFormat32bppBGRA for 32bpp. - // See: https://docs.microsoft.com/en-us/windows/win32/wic/-wic-codec-native-pixel-formats#png-native-codec - WICPixelFormatGUID pixelFormat = GUID_WICPixelFormat32bppBGRA; - hr = frame->SetPixelFormat(&pixelFormat); - if (FAILED(hr)) - return false; - - hr = frame->SetSize(spec.width, spec.height); - if (FAILED(hr)) - return false; - - std::vector buf; - uint8_t* ptr = (uint8_t*)image.data(); - int bytes_per_row = spec.bytes_per_row; - - // Convert to GUID_WICPixelFormat32bppBGRA if needed - if (spec.red_mask != 0xff0000 || - spec.green_mask != 0xff00 || - spec.blue_mask != 0xff || - spec.alpha_mask != 0xff000000) { - buf.resize(spec.width * spec.height); - uint32_t* dst = (uint32_t*)&buf[0]; - uint32_t* src = (uint32_t*)image.data(); - for (int y=0; y> spec.red_shift ) << 16) | - (((c & spec.green_mask) >> spec.green_shift) << 8) | - (((c & spec.blue_mask ) >> spec.blue_shift ) ) | - (((c & spec.alpha_mask) >> spec.alpha_shift) << 24)); - ++dst; - ++src; - } - src = (uint32_t*)(((uint8_t*)src_line_start) + spec.bytes_per_row); - } - ptr = (uint8_t*)&buf[0]; - bytes_per_row = 4 * spec.width; - } - - hr = frame->WritePixels(spec.height, - bytes_per_row, - bytes_per_row * spec.height, - (BYTE*)ptr); - if (FAILED(hr)) - return false; - - hr = frame->Commit(); - if (FAILED(hr)) - return false; - - hr = encoder->Commit(); - if (FAILED(hr)) - return false; - - return true; -} - -HGLOBAL write_png(const image& image) { - coinit com; - - comptr stream; - HRESULT hr = CreateStreamOnHGlobal(nullptr, false, &stream); - if (FAILED(hr)) - return nullptr; - - bool result = write_png_on_stream(image, stream.get()); - - HGLOBAL handle; - hr = GetHGlobalFromStream(stream.get(), &handle); - if (result) - return handle; - - GlobalFree(handle); - return nullptr; -} - -////////////////////////////////////////////////////////////////////// -// Decode the clipboard data from PNG format - -bool read_png(const uint8_t* buf, - const UINT len, - image* output_image, - image_spec* output_spec) { - coinit com; - - comptr stream(SHCreateMemStream(buf, len)); - if (!stream) - return false; - - comptr decoder; - HRESULT hr = CoCreateInstance(CLSID_WICPngDecoder2, - nullptr, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&decoder)); - if (FAILED(hr)) { - hr = CoCreateInstance(CLSID_WICPngDecoder1, - nullptr, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&decoder)); - if (FAILED(hr)) - return false; - } - - hr = decoder->Initialize(stream.get(), WICDecodeMetadataCacheOnDemand); - if (FAILED(hr)) - return false; - - comptr frame; - hr = decoder->GetFrame(0, &frame); - if (FAILED(hr)) - return false; - - WICPixelFormatGUID pixelFormat; - hr = frame->GetPixelFormat(&pixelFormat); - if (FAILED(hr)) - return false; - - // Only support this pixel format - // TODO add support for more pixel formats - if (pixelFormat != GUID_WICPixelFormat32bppBGRA) - return false; - - UINT width = 0, height = 0; - hr = frame->GetSize(&width, &height); - if (FAILED(hr)) - return false; - - image_spec spec; - spec.width = width; - spec.height = height; - spec.bits_per_pixel = 32; - spec.bytes_per_row = 4 * width; - spec.red_mask = 0xff0000; - spec.green_mask = 0xff00; - spec.blue_mask = 0xff; - spec.alpha_mask = 0xff000000; - spec.red_shift = 16; - spec.green_shift = 8; - spec.blue_shift = 0; - spec.alpha_shift = 24; - - if (output_spec) - *output_spec = spec; - - if (output_image) { - image img(spec); - - hr = frame->CopyPixels( - nullptr, // Entire bitmap - spec.bytes_per_row, - spec.bytes_per_row * spec.height, - (BYTE*)img.data()); - if (FAILED(hr)) { - return false; - } - - std::swap(*output_image, img); - } - - return true; -} - -} // namespace win -} // namespace clip diff --git a/src/vendor/clip/clip_x11.cpp b/src/vendor/clip/clip_x11.cpp deleted file mode 100755 index 842105b..0000000 --- a/src/vendor/clip/clip_x11.cpp +++ /dev/null @@ -1,1094 +0,0 @@ -// Clip Library -// Copyright (c) 2018-2022 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "clip.h" -#include "clip_lock_impl.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_PNG_H - #include "clip_x11_png.h" -#endif - -#define CLIP_SUPPORT_SAVE_TARGETS 1 - -namespace clip { - -namespace { - -enum CommonAtom { - ATOM, - INCR, - TARGETS, - CLIPBOARD, -#ifdef HAVE_PNG_H - MIME_IMAGE_PNG, -#endif -#ifdef CLIP_SUPPORT_SAVE_TARGETS - ATOM_PAIR, - SAVE_TARGETS, - MULTIPLE, - CLIPBOARD_MANAGER, -#endif -}; - -const char* kCommonAtomNames[] = { - "ATOM", - "INCR", - "TARGETS", - "CLIPBOARD", -#ifdef HAVE_PNG_H - "image/png", -#endif -#ifdef CLIP_SUPPORT_SAVE_TARGETS - "ATOM_PAIR", - "SAVE_TARGETS", - "MULTIPLE", - "CLIPBOARD_MANAGER", -#endif -}; - -const int kBaseForCustomFormats = 100; - -class Manager { -public: - typedef std::shared_ptr> buffer_ptr; - typedef std::vector atoms; - typedef std::function notify_callback; - - Manager() - : m_lock(m_mutex, std::defer_lock) - , m_connection(xcb_connect(nullptr, nullptr)) - , m_window(0) - , m_incr_process(false) { - if (!m_connection) - return; - - const xcb_setup_t* setup = xcb_get_setup(m_connection); - if (!setup) - return; - - xcb_screen_t* screen = xcb_setup_roots_iterator(setup).data; - if (!screen) - return; - - uint32_t event_mask = - // Just in case that some program reports SelectionNotify events - // with XCB_EVENT_MASK_PROPERTY_CHANGE mask. - XCB_EVENT_MASK_PROPERTY_CHANGE | - // To receive DestroyNotify event and stop the message loop. - XCB_EVENT_MASK_STRUCTURE_NOTIFY; - - m_window = xcb_generate_id(m_connection); - xcb_create_window(m_connection, 0, - m_window, - screen->root, - 0, 0, 1, 1, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - screen->root_visual, - XCB_CW_EVENT_MASK, - &event_mask); - - m_thread = std::thread( - [this]{ - process_x11_events(); - }); - } - - ~Manager() { -#ifdef CLIP_SUPPORT_SAVE_TARGETS - if (!m_data.empty() && - m_window && - m_window == get_x11_selection_owner()) { - // If the CLIPBOARD_MANAGER atom is not 0, we assume that there - // is a clipboard manager available were we can leave our data. - xcb_atom_t x11_clipboard_manager = get_atom(CLIPBOARD_MANAGER); - if (x11_clipboard_manager) { - // We have to lock the m_lock mutex that will be used to wait - // the m_cv condition in get_data_from_selection_owner(). - if (try_lock()) { - // Start the SAVE_TARGETS mechanism so the X11 - // CLIPBOARD_MANAGER will save our clipboard data - // from now on. - get_data_from_selection_owner( - { get_atom(SAVE_TARGETS) }, - []() -> bool { return true; }, - x11_clipboard_manager); - } - } - } -#endif - - if (m_window) { - xcb_destroy_window(m_connection, m_window); - xcb_flush(m_connection); - } - - if (m_thread.joinable()) - m_thread.join(); - - if (m_connection) - xcb_disconnect(m_connection); - } - - bool try_lock() { - bool res = m_lock.try_lock(); - if (!res) { - // TODO make this configurable (the same for Windows retries) - for (int i=0; i<5 && !res; ++i) { - res = m_lock.try_lock(); - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } - } - return res; - } - - void unlock() { - m_lock.unlock(); - } - - // Clear our data - void clear_data() { - m_data.clear(); - m_image.reset(); - } - - void clear() { - clear_data(); - - // As we want to clear the clipboard content, we set us as the new - // clipboard owner (with an empty clipboard). If this fails, we'll - // try to send a XCB_SELECTION_CLEAR request to the real owner - // (but that can fail anyway because it's a request that the owner - // could ignore). - if (set_x11_selection_owner()) - return; - - // Clear the clipboard data from the selection owner - const xcb_window_t owner = get_x11_selection_owner(); - if (m_window != owner) { - xcb_selection_clear_event_t event; - event.response_type = XCB_SELECTION_CLEAR; - event.pad0 = 0; - event.sequence = 0; - event.time = XCB_CURRENT_TIME; - event.owner = owner; - event.selection = get_atom(CLIPBOARD); - - xcb_send_event(m_connection, false, - owner, - XCB_EVENT_MASK_NO_EVENT, - (const char*)&event); - - xcb_flush(m_connection); - } - } - - bool is_convertible(format f) const { - const atoms atoms = get_format_atoms(f); - const xcb_window_t owner = get_x11_selection_owner(); - - // If we are the owner, we just can check the m_data map - if (owner == m_window) { - for (xcb_atom_t atom : atoms) { - auto it = m_data.find(atom); - if (it != m_data.end()) - return true; - } - } - // Ask to the selection owner the available formats/atoms/targets. - else if (owner) { - return - get_data_from_selection_owner( - { get_atom(TARGETS) }, - [this, &atoms]() -> bool { - assert(m_reply_data); - if (!m_reply_data) - return false; - - const xcb_atom_t* sel_atoms = (const xcb_atom_t*)&(*m_reply_data)[0]; - int sel_natoms = m_reply_data->size() / sizeof(xcb_atom_t); - auto atoms_begin = atoms.begin(); - auto atoms_end = atoms.end(); - for (int i=0; i>(len); - std::copy(buf, - buf+len, - shared_data_buf->begin()); - for (xcb_atom_t atom : atoms) - m_data[atom] = shared_data_buf; - - return true; - } - - bool get_data(format f, char* buf, size_t len) const { - const atoms atoms = get_format_atoms(f); - const xcb_window_t owner = get_x11_selection_owner(); - if (owner == m_window) { - for (xcb_atom_t atom : atoms) { - auto it = m_data.find(atom); - if (it != m_data.end()) { - size_t n = std::min(len, it->second->size()); - std::copy(it->second->begin(), - it->second->begin()+n, - buf); - - if (f == text_format()) { - // Add an extra null char - if (n < len) - buf[n] = 0; - } - - return true; - } - } - } - else if (owner) { - if (get_data_from_selection_owner( - atoms, - [this, buf, len, f]() -> bool { - size_t n = std::min(len, m_reply_data->size()); - std::copy(m_reply_data->begin(), - m_reply_data->begin()+n, - buf); - - if (f == text_format()) { - if (n < len) - buf[n] = 0; // Include a null character - } - - return true; - })) { - return true; - } - } - return false; - } - - size_t get_data_length(format f) const { - size_t len = 0; - const atoms atoms = get_format_atoms(f); - const xcb_window_t owner = get_x11_selection_owner(); - if (owner == m_window) { - for (xcb_atom_t atom : atoms) { - auto it = m_data.find(atom); - if (it != m_data.end()) { - len = it->second->size(); - break; - } - } - } - else if (owner) { - if (!get_data_from_selection_owner( - atoms, - [this, &len]() -> bool { - len = m_reply_data->size(); - return true; - })) { - // Error getting data length - return 0; - } - } - if (f == text_format() && len > 0) { - ++len; // Add an extra byte for the null char - } - return len; - } - - bool set_image(const image& image) { - if (!set_x11_selection_owner()) - return false; - - m_image = image; - -#ifdef HAVE_PNG_H - // Put a nullptr in the m_data for image/png format and then we'll - // encode the png data when the image is requested in this format. - m_data[get_atom(MIME_IMAGE_PNG)] = buffer_ptr(); -#endif - - return true; - } - - bool get_image(image& output_img) const { - const xcb_window_t owner = get_x11_selection_owner(); - if (owner == m_window) { - if (m_image.is_valid()) { - output_img = m_image; - return true; - } - } -#ifdef HAVE_PNG_H - else if (owner && - get_data_from_selection_owner( - { get_atom(MIME_IMAGE_PNG) }, - [this, &output_img]() -> bool { - return x11::read_png(&(*m_reply_data)[0], - m_reply_data->size(), - &output_img, nullptr); - })) { - return true; - } -#endif - return false; - } - - bool get_image_spec(image_spec& spec) const { - const xcb_window_t owner = get_x11_selection_owner(); - if (owner == m_window) { - if (m_image.is_valid()) { - spec = m_image.spec(); - return true; - } - } -#ifdef HAVE_PNG_H - else if (owner && - get_data_from_selection_owner( - { get_atom(MIME_IMAGE_PNG) }, - [this, &spec]() -> bool { - return x11::read_png(&(*m_reply_data)[0], - m_reply_data->size(), - nullptr, &spec); - })) { - return true; - } -#endif - return false; - } - - format register_format(const std::string& name) { - xcb_atom_t atom = get_atom(name.c_str()); - m_custom_formats.push_back(atom); - return (format)(m_custom_formats.size()-1) + kBaseForCustomFormats; - } - -private: - - void process_x11_events() { - bool stop = false; - xcb_generic_event_t* event; - while (!stop && (event = xcb_wait_for_event(m_connection))) { - int type = (event->response_type & ~0x80); - - switch (type) { - - case XCB_DESTROY_NOTIFY: - // To stop the message loop we can just destroy the window - stop = true; - break; - - // Someone else has new content in the clipboard, so is - // notifying us that we should delete our data now. - case XCB_SELECTION_CLEAR: - handle_selection_clear_event( - (xcb_selection_clear_event_t*)event); - break; - - // Someone is requesting the clipboard content from us. - case XCB_SELECTION_REQUEST: - handle_selection_request_event( - (xcb_selection_request_event_t*)event); - break; - - // We've requested the clipboard content and this is the - // answer. - case XCB_SELECTION_NOTIFY: - handle_selection_notify_event( - (xcb_selection_notify_event_t*)event); - break; - - case XCB_PROPERTY_NOTIFY: - handle_property_notify_event( - (xcb_property_notify_event_t*)event); - break; - - } - - free(event); - } - } - - void handle_selection_clear_event(xcb_selection_clear_event_t* event) { - if (event->selection == get_atom(CLIPBOARD)) { - std::lock_guard lock(m_mutex); - clear_data(); // Clear our clipboard data - } - } - - void handle_selection_request_event(xcb_selection_request_event_t* event) { - std::lock_guard lock(m_mutex); - - if (event->target == get_atom(TARGETS)) { - atoms targets; - targets.push_back(get_atom(TARGETS)); -#ifdef CLIP_SUPPORT_SAVE_TARGETS - targets.push_back(get_atom(SAVE_TARGETS)); - targets.push_back(get_atom(MULTIPLE)); -#endif - for (const auto& it : m_data) - targets.push_back(it.first); - - // Set the "property" of "requestor" with the clipboard - // formats ("targets", atoms) that we provide. - xcb_change_property( - m_connection, - XCB_PROP_MODE_REPLACE, - event->requestor, - event->property, - get_atom(ATOM), - 8*sizeof(xcb_atom_t), - targets.size(), - &targets[0]); - } -#ifdef CLIP_SUPPORT_SAVE_TARGETS - else if (event->target == get_atom(SAVE_TARGETS)) { - // Do nothing - } - else if (event->target == get_atom(MULTIPLE)) { - xcb_get_property_reply_t* reply = - get_and_delete_property(event->requestor, - event->property, - get_atom(ATOM_PAIR), - false); - if (reply) { - for (xcb_atom_t - *ptr=(xcb_atom_t*)xcb_get_property_value(reply), - *end=ptr + (xcb_get_property_value_length(reply)/sizeof(xcb_atom_t)); - ptrrequestor, - property, - target)) { - xcb_change_property( - m_connection, - XCB_PROP_MODE_REPLACE, - event->requestor, - event->property, - XCB_ATOM_NONE, 0, 0, nullptr); - } - } - - free(reply); - } - } -#endif // CLIP_SUPPORT_SAVE_TARGETS - else { - if (!set_requestor_property_with_clipboard_content( - event->requestor, - event->property, - event->target)) { - return; - } - } - - // Notify the "requestor" that we've already updated the property. - xcb_selection_notify_event_t notify; - notify.response_type = XCB_SELECTION_NOTIFY; - notify.pad0 = 0; - notify.sequence = 0; - notify.time = event->time; - notify.requestor = event->requestor; - notify.selection = event->selection; - notify.target = event->target; - notify.property = event->property; - - xcb_send_event(m_connection, false, - event->requestor, - XCB_EVENT_MASK_NO_EVENT, // SelectionNotify events go without mask - (const char*)¬ify); - - xcb_flush(m_connection); - } - - bool set_requestor_property_with_clipboard_content(const xcb_atom_t requestor, - const xcb_atom_t property, - const xcb_atom_t target) { - auto it = m_data.find(target); - if (it == m_data.end()) { - // Nothing to do (unsupported target) - return false; - } - - // This can be null of the data was set from an image but we - // didn't encode the image yet (e.g. to image/png format). - if (!it->second) { - encode_data_on_demand(*it); - - // Return nothing, the given "target" cannot be constructed - // (maybe by some encoding error). - if (!it->second) - return false; - } - - // Set the "property" of "requestor" with the - // clipboard content in the requested format ("target"). - xcb_change_property( - m_connection, - XCB_PROP_MODE_REPLACE, - requestor, - property, - target, - 8, - it->second->size(), - &(*it->second)[0]); - return true; - } - - void handle_selection_notify_event(xcb_selection_notify_event_t* event) { - assert(event->requestor == m_window); - - if (event->target == get_atom(TARGETS)) - m_target_atom = get_atom(ATOM); - else - m_target_atom = event->target; - - xcb_get_property_reply_t* reply = - get_and_delete_property(event->requestor, - event->property, - m_target_atom); - if (reply) { - // In this case, We're going to receive the clipboard content in - // chunks of data with several PropertyNotify events. - if (reply->type == get_atom(INCR)) { - free(reply); - - reply = get_and_delete_property(event->requestor, - event->property, - get_atom(INCR)); - if (reply) { - if (xcb_get_property_value_length(reply) == 4) { - uint32_t n = *(uint32_t*)xcb_get_property_value(reply); - m_reply_data = std::make_shared>(n); - m_reply_offset = 0; - m_incr_process = true; - m_incr_received = true; - } - free(reply); - } - } - else { - // Simple case, the whole clipboard content in just one reply - // (without the INCR method). - m_reply_data.reset(); - m_reply_offset = 0; - copy_reply_data(reply); - - call_callback(reply); - - free(reply); - } - } - } - - void handle_property_notify_event(xcb_property_notify_event_t* event) { - if (m_incr_process && - event->state == XCB_PROPERTY_NEW_VALUE && - event->atom == get_atom(CLIPBOARD)) { - xcb_get_property_reply_t* reply = - get_and_delete_property(event->window, - event->atom, - m_target_atom); - if (reply) { - m_incr_received = true; - - // When the length is 0 it means that the content was - // completely sent by the selection owner. - if (xcb_get_property_value_length(reply) > 0) { - copy_reply_data(reply); - } - else { - // Now that m_reply_data has the complete clipboard content, - // we can call the m_callback. - call_callback(reply); - m_incr_process = false; - } - free(reply); - } - } - } - - xcb_get_property_reply_t* get_and_delete_property(xcb_window_t window, - xcb_atom_t property, - xcb_atom_t atom, - bool delete_prop = true) { - xcb_get_property_cookie_t cookie = - xcb_get_property(m_connection, - delete_prop, - window, - property, - atom, - 0, 0x1fffffff); // 0x1fffffff = INT32_MAX / 4 - - xcb_generic_error_t* err = nullptr; - xcb_get_property_reply_t* reply = - xcb_get_property_reply(m_connection, cookie, &err); - if (err) { - // TODO report error - free(err); - } - return reply; - } - - // Concatenates the new data received in "reply" into "m_reply_data" - // buffer. - void copy_reply_data(xcb_get_property_reply_t* reply) { - const uint8_t* src = (const uint8_t*)xcb_get_property_value(reply); - // n = length of "src" in bytes - size_t n = xcb_get_property_value_length(reply); - - size_t req = m_reply_offset+n; - if (!m_reply_data) { - m_reply_data = std::make_shared>(req); - } - // The "m_reply_data" size can be smaller because the size - // specified in INCR property is just a lower bound. - else if (req > m_reply_data->size()) { - m_reply_data->resize(req); - } - - std::copy(src, src+n, m_reply_data->begin()+m_reply_offset); - m_reply_offset += n; - } - - // Calls the current m_callback() to handle the clipboard content - // received from the owner. - void call_callback(xcb_get_property_reply_t* reply) { - m_callback_result = false; - if (m_callback) - m_callback_result = m_callback(); - - m_cv.notify_one(); - - m_reply_data.reset(); - } - - bool get_data_from_selection_owner(const atoms& atoms, - const notify_callback&& callback, - xcb_atom_t selection = 0) const { - if (!selection) - selection = get_atom(CLIPBOARD); - - // Put the callback on "m_callback" so we can call it on - // SelectionNotify event. - m_callback = std::move(callback); - - // Clear data if we are not the selection owner. - if (m_window != get_x11_selection_owner()) - m_data.clear(); - - // Ask to the selection owner for its content on each known - // text format/atom. - for (xcb_atom_t atom : atoms) { - xcb_convert_selection(m_connection, - m_window, // Send us the result - selection, // Clipboard selection - atom, // The clipboard format that we're requesting - get_atom(CLIPBOARD), // Leave result in this window's property - XCB_CURRENT_TIME); - - xcb_flush(m_connection); - - // We use the "m_incr_received" to wait several timeouts in case - // that we've received the INCR SelectionNotify or - // PropertyNotify events. - do { - m_incr_received = false; - - // Wait a response for 100 milliseconds - std::cv_status status = - m_cv.wait_for(m_lock, - std::chrono::milliseconds(get_x11_wait_timeout())); - if (status == std::cv_status::no_timeout) { - // If the condition variable was notified, it means that the - // callback was called correctly. - return m_callback_result; - } - } while (m_incr_received); - } - - // Reset callback - m_callback = notify_callback(); - return false; - } - - atoms get_atoms(const char** names, - const int n) const { - atoms result(n, 0); - std::vector cookies(n); - - for (int i=0; isecond; - else - cookies[i] = xcb_intern_atom( - m_connection, 0, - std::strlen(names[i]), names[i]); - } - - for (int i=0; iatom; - free(reply); - } - } - } - - return result; - } - - xcb_atom_t get_atom(const char* name) const { - auto it = m_atoms.find(name); - if (it != m_atoms.end()) - return it->second; - - xcb_atom_t result = 0; - xcb_intern_atom_cookie_t cookie = - xcb_intern_atom(m_connection, 0, - std::strlen(name), name); - - xcb_intern_atom_reply_t* reply = - xcb_intern_atom_reply(m_connection, - cookie, - nullptr); - if (reply) { - result = m_atoms[name] = reply->atom; - free(reply); - } - return result; - } - - xcb_atom_t get_atom(CommonAtom i) const { - if (m_common_atoms.empty()) { - m_common_atoms = - get_atoms(kCommonAtomNames, - sizeof(kCommonAtomNames) / sizeof(kCommonAtomNames[0])); - } - return m_common_atoms[i]; - } - - const atoms& get_text_format_atoms() const { - if (m_text_atoms.empty()) { - const char* names[] = { - // Prefer utf-8 formats first - "UTF8_STRING", - "text/plain;charset=utf-8", - "text/plain;charset=UTF-8", - "GTK_TEXT_BUFFER_CONTENTS", // Required for gedit (and maybe gtk+ apps) - // ANSI C strings? - "STRING", - "TEXT", - "text/plain", - }; - m_text_atoms = get_atoms(names, sizeof(names) / sizeof(names[0])); - } - return m_text_atoms; - } - - const atoms& get_image_format_atoms() const { - if (m_image_atoms.empty()) { -#ifdef HAVE_PNG_H - m_image_atoms.push_back(get_atom(MIME_IMAGE_PNG)); -#endif - } - return m_image_atoms; - } - - atoms get_format_atoms(const format f) const { - atoms atoms; - if (f == text_format()) { - atoms = get_text_format_atoms(); - } - else if (f == image_format()) { - atoms = get_image_format_atoms(); - } - else { - xcb_atom_t atom = get_format_atom(f); - if (atom) - atoms.push_back(atom); - } - return atoms; - } - -#if !defined(NDEBUG) - // This can be used to print debugging messages. - std::string get_atom_name(xcb_atom_t atom) const { - std::string result; - xcb_get_atom_name_cookie_t cookie = - xcb_get_atom_name(m_connection, atom); - xcb_generic_error_t* err = nullptr; - xcb_get_atom_name_reply_t* reply = - xcb_get_atom_name_reply(m_connection, cookie, &err); - if (err) { - free(err); - } - if (reply) { - int len = xcb_get_atom_name_name_length(reply); - if (len > 0) { - result.resize(len); - char* name = xcb_get_atom_name_name(reply); - if (name) - std::copy(name, name+len, result.begin()); - } - free(reply); - } - return result; - } -#endif - - bool set_x11_selection_owner() const { - xcb_void_cookie_t cookie = - xcb_set_selection_owner_checked(m_connection, - m_window, - get_atom(CLIPBOARD), - XCB_CURRENT_TIME); - xcb_generic_error_t* err = - xcb_request_check(m_connection, - cookie); - if (err) { - free(err); - return false; - } - return true; - } - - xcb_window_t get_x11_selection_owner() const { - xcb_window_t result = 0; - xcb_get_selection_owner_cookie_t cookie = - xcb_get_selection_owner(m_connection, - get_atom(CLIPBOARD)); - - xcb_get_selection_owner_reply_t* reply = - xcb_get_selection_owner_reply(m_connection, cookie, nullptr); - if (reply) { - result = reply->owner; - free(reply); - } - return result; - } - - xcb_atom_t get_format_atom(const format f) const { - int i = f - kBaseForCustomFormats; - if (i >= 0 && i < int(m_custom_formats.size())) - return m_custom_formats[i]; - else - return 0; - } - - void encode_data_on_demand(std::pair& e) { -#ifdef HAVE_PNG_H - if (e.first == get_atom(MIME_IMAGE_PNG)) { - assert(m_image.is_valid()); - if (!m_image.is_valid()) - return; - - std::vector output; - if (x11::write_png(m_image, output)) { - e.second = - std::make_shared>( - std::move(output)); - } - // else { TODO report png conversion errors } - } -#endif - } - - // Access to the whole Manager - std::mutex m_mutex; - - // Lock used in the main thread using the Manager (i.e. by lock::impl) - mutable std::unique_lock m_lock; - - // Connection to X11 server - xcb_connection_t* m_connection; - - // Temporal background window used to own the clipboard and process - // all events related about the clipboard in a background thread - xcb_window_t m_window; - - // Used to wait/notify the arrival of the SelectionNotify event when - // we requested the clipboard content from other selection owner. - mutable std::condition_variable m_cv; - - // Thread used to run a background message loop to wait X11 events - // about clipboard. The X11 selection owner will be a hidden window - // created by us just for the clipboard purpose/communication. - std::thread m_thread; - - // Internal callback used when a SelectionNotify is received (or the - // whole data content is received by the INCR method). So this - // callback can use the notification by different purposes (e.g. get - // the data length only, or get/process the data content, etc.). - mutable notify_callback m_callback; - - // Result returned by the m_callback. Used as return value in the - // get_data_from_selection_owner() function. For example, if the - // callback must read a "image/png" file from the clipboard data and - // fails, the callback can return false and finally the get_image() - // will return false (i.e. there is data, but it's not a valid image - // format). - std::atomic m_callback_result; - - // Cache of known atoms - mutable std::map m_atoms; - - // Cache of common used atoms by us - mutable atoms m_common_atoms; - - // Cache of atoms related to text or image content - mutable atoms m_text_atoms; - mutable atoms m_image_atoms; - - // Actual clipboard data generated by us (when we "copy" content in - // the clipboard, it means that we own the X11 "CLIPBOARD" - // selection, and in case of SelectionRequest events, we've to - // return the data stored in this "m_data" field) - mutable std::map m_data; - - // Copied image in the clipboard. As we have to transfer the image - // in some specific format (e.g. image/png) we want to keep a copy - // of the image and make the conversion when the clipboard data is - // requested by other process. - mutable image m_image; - - // True if we have received an INCR notification so we're going to - // process several PropertyNotify to concatenate all data chunks. - bool m_incr_process; - - // Variable used to wait more time if we've received an INCR - // notification, which means that we're going to receive large - // amounts of data from the selection owner. - mutable bool m_incr_received; - - // Target/selection format used in the SelectionNotify. Used in the - // INCR method to get data from the same property in the same format - // (target) on each PropertyNotify. - xcb_atom_t m_target_atom; - - // Each time we receive data from the selection owner, we put that - // data in this buffer. If we get the data with the INCR method, - // we'll concatenate chunks of data in this buffer to complete the - // whole clipboard content. - buffer_ptr m_reply_data; - - // Used to concatenate chunks of data in "m_reply_data" from several - // PropertyNotify when we are getting the selection owner data with - // the INCR method. - size_t m_reply_offset; - - // List of user-defined formats/atoms. - std::vector m_custom_formats; -}; - -Manager* manager = nullptr; - -void delete_manager_atexit() { - if (manager) { - delete manager; - manager = nullptr; - } -} - -Manager* get_manager() { - if (!manager) { - manager = new Manager; - std::atexit(delete_manager_atexit); - } - return manager; -} - -} // anonymous namespace - -lock::impl::impl(void*) : m_locked(false) { - m_locked = get_manager()->try_lock(); -} - -lock::impl::~impl() { - if (m_locked) - manager->unlock(); -} - -bool lock::impl::clear() { - manager->clear(); - return true; -} - -bool lock::impl::is_convertible(format f) const { - return manager->is_convertible(f); -} - -bool lock::impl::set_data(format f, const char* buf, size_t len) { - return manager->set_data(f, buf, len); -} - -bool lock::impl::get_data(format f, char* buf, size_t len) const { - return manager->get_data(f, buf, len); -} - -size_t lock::impl::get_data_length(format f) const { - return manager->get_data_length(f); -} - -bool lock::impl::set_image(const image& image) { - return manager->set_image(image); -} - -bool lock::impl::get_image(image& output_img) const { - return manager->get_image(output_img); -} - -bool lock::impl::get_image_spec(image_spec& spec) const { - return manager->get_image_spec(spec); -} - -format register_format(const std::string& name) { - return get_manager()->register_format(name); -} - -} // namespace clip diff --git a/src/vendor/clip/clip_x11_png.h b/src/vendor/clip/clip_x11_png.h deleted file mode 100755 index cf3b514..0000000 --- a/src/vendor/clip/clip_x11_png.h +++ /dev/null @@ -1,230 +0,0 @@ -// Clip Library -// Copyright (c) 2018-2021 David Capello -// -// This file is released under the terms of the MIT license. -// Read LICENSE.txt for more information. - -#include "clip.h" - -#include -#include - -#include "png.h" - -namespace clip { -namespace x11 { - -////////////////////////////////////////////////////////////////////// -// Functions to convert clip::image into png data to store it in the -// clipboard. - -void write_data_fn(png_structp png, png_bytep buf, png_size_t len) { - std::vector& output = *(std::vector*)png_get_io_ptr(png); - const size_t i = output.size(); - output.resize(i+len); - std::copy(buf, buf+len, output.begin()+i); -} - -bool write_png(const image& image, - std::vector& output) { - png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, - nullptr, nullptr, nullptr); - if (!png) - return false; - - png_infop info = png_create_info_struct(png); - if (!info) { - png_destroy_write_struct(&png, nullptr); - return false; - } - - if (setjmp(png_jmpbuf(png))) { - png_destroy_write_struct(&png, &info); - return false; - } - - png_set_write_fn(png, - (png_voidp)&output, - write_data_fn, - nullptr); // No need for a flush function - - const image_spec& spec = image.spec(); - int color_type = (spec.alpha_mask ? - PNG_COLOR_TYPE_RGB_ALPHA: - PNG_COLOR_TYPE_RGB); - - png_set_IHDR(png, info, - spec.width, spec.height, 8, color_type, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - png_write_info(png, info); - png_set_packing(png); - - png_bytep row = - (png_bytep)png_malloc(png, png_get_rowbytes(png, info)); - - for (png_uint_32 y=0; y> spec.red_shift; - *(dst++) = (c & spec.green_mask) >> spec.green_shift; - *(dst++) = (c & spec.blue_mask ) >> spec.blue_shift; - if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) - *(dst++) = (c & spec.alpha_mask) >> spec.alpha_shift; - } - - png_write_rows(png, &row, 1); - } - - png_free(png, row); - png_write_end(png, info); - png_destroy_write_struct(&png, &info); - return true; -} - -////////////////////////////////////////////////////////////////////// -// Functions to convert png data stored in the clipboard to a -// clip::image. - -struct read_png_io { - const uint8_t* buf; - size_t len; - size_t pos; -}; - -void read_data_fn(png_structp png, png_bytep buf, png_size_t len) { - read_png_io& io = *(read_png_io*)png_get_io_ptr(png); - if (io.pos < io.len) { - size_t n = std::min(len, io.len-io.pos); - if (n > 0) { - std::copy(io.buf+io.pos, - io.buf+io.pos+n, - buf); - io.pos += n; - } - } -} - -bool read_png(const uint8_t* buf, - const size_t len, - image* output_image, - image_spec* output_spec) { - png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, - nullptr, nullptr, nullptr); - if (!png) - return false; - - png_infop info = png_create_info_struct(png); - if (!info) { - png_destroy_read_struct(&png, nullptr, nullptr); - return false; - } - - if (setjmp(png_jmpbuf(png))) { - png_destroy_read_struct(&png, &info, nullptr); - return false; - } - - read_png_io io = { buf, len, 0 }; - png_set_read_fn(png, (png_voidp)&io, read_data_fn); - - png_read_info(png, info); - - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; - png_get_IHDR(png, info, &width, &height, - &bit_depth, &color_type, - &interlace_type, - nullptr, nullptr); - - image_spec spec; - spec.width = width; - spec.height = height; - spec.bits_per_pixel = 32; - - // Don't use png_get_rowbytes(png, info) here because this is the - // bytes_per_row of the output clip::image (the png file could - // contain 24bpp but we want to return a 32bpp anyway with alpha=255 - // in that case). - spec.bytes_per_row = 4*width; - - spec.red_mask = 0x000000ff; - spec.green_mask = 0x0000ff00; - spec.blue_mask = 0x00ff0000; - spec.red_shift = 0; - spec.green_shift = 8; - spec.blue_shift = 16; - - if ((color_type & PNG_COLOR_MASK_ALPHA) == PNG_COLOR_MASK_ALPHA) { - spec.alpha_mask = 0xff000000; - spec.alpha_shift = 24; - } - else { - spec.alpha_mask = 0; - spec.alpha_shift = 0; - } - - if (output_spec) - *output_spec = spec; - - if (output_image && - width > 0 && - height > 0) { - image img(spec); - - // We want RGB 24-bit or RGBA 32-bit as a result - png_set_strip_16(png); // Down to 8-bit (TODO we might support 16-bit values) - png_set_packing(png); // Use one byte if color depth < 8-bit - png_set_expand_gray_1_2_4_to_8(png); - png_set_palette_to_rgb(png); - png_set_gray_to_rgb(png); - png_set_tRNS_to_alpha(png); - - int number_passes = png_set_interlace_handling(png); - png_read_update_info(png, info); - - const int src_bytes_per_row = png_get_rowbytes(png, info); - png_bytepp rows = (png_bytepp)png_malloc(png, sizeof(png_bytep)*height); - png_uint_32 y; - for (y=0; y 0) - n += 4 - (n % 4); - else - ++n; - } - - return n; -} - -image::image() - : m_own_data(false), - m_data(nullptr) -{ -} - -image::image(const image_spec& spec) - : m_own_data(true), - m_data(new char[spec.required_data_size()]), - m_spec(spec) { -} - -image::image(const void* data, const image_spec& spec) - : m_own_data(false), - m_data((char*)data), - m_spec(spec) { -} - -image::image(const image& image) - : m_own_data(false), - m_data(nullptr), - m_spec(image.m_spec) { - copy_image(image); -} - -image::image(image&& image) - : m_own_data(false), - m_data(nullptr) { - move_image(std::move(image)); -} - -image::~image() { - reset(); -} - -image& image::operator=(const image& image) { - copy_image(image); - return *this; -} - -image& image::operator=(image&& image) { - move_image(std::move(image)); - return *this; -} - -void image::reset() { - if (m_own_data) { - delete[] m_data; - m_own_data = false; - m_data = nullptr; - } -} - -void image::copy_image(const image& image) { - reset(); - - m_spec = image.spec(); - std::size_t n = m_spec.required_data_size(); - - m_own_data = true; - m_data = new char[n]; - std::copy(image.data(), - image.data()+n, - m_data); -} - -void image::move_image(image&& image) { - std::swap(m_own_data, image.m_own_data); - std::swap(m_data, image.m_data); - std::swap(m_spec, image.m_spec); -} - -} // namespace clip diff --git a/tools/build.nr b/tools/build.nr index f754216..d75c403 100755 --- a/tools/build.nr +++ b/tools/build.nr @@ -1 +1 @@ -1716 \ No newline at end of file +1718 diff --git a/tools/create_includes.py b/tools/create_includes.py deleted file mode 100755 index 38ed9a3..0000000 --- a/tools/create_includes.py +++ /dev/null @@ -1,80 +0,0 @@ -# Note: This file is meant to be ran by CMake -# and it should not be ran manually. -# -# It uses hardcoded paths, relative to -# the root of the project (the OmniaX directory) -# therefore it is only meant to run directly -# from that directory and not form the -# OmniaX/tools directory (in which it is located). - -import os -import shutil -import os.path -import sys -from os import path - -verbose = False - -def run_fast_scandir(dir, ext): - subfolders, files = [], [] - - for f in os.scandir(dir): - if f.is_dir(): - subfolders.append(f.path) - if f.is_file(): - if os.path.splitext(f.name)[1].lower() in ext: - files.append(f.path) - - - for dir in list(subfolders): - sf, f = run_fast_scandir(dir, ext) - subfolders.extend(sf) - files.extend(f) - return subfolders, files - -def install_includes(source_dir, include_dir, exception_dirs): - _list = run_fast_scandir(source_dir, [".hpp", ".h", ".inl", ".cpp", ".c"]) - if path.exists(include_dir): - if verbose: - print("Removing old include directory...") - shutil.rmtree(include_dir) - os.mkdir(include_dir) - - for elem in _list[0]: - elem = elem[len(source_dir) + 1:] - elem = os.path.join(include_dir, elem) - #elem = include_dir + "/" + elem - os.mkdir(elem) - if verbose: - print("Creating Directory: " + elem) - - if verbose: - print("\n") - - for elem in _list[1]: - #new_elem = include_dir + "/" + elem[len(source_dir):] - new_elem = os.path.join(include_dir, elem[len(source_dir) + 1:]) - found = True - if elem.endswith(".c") or elem.endswith(".cpp"): - found = False - for exep in exception_dirs: - if new_elem.startswith(exep): - found = True - break - if found: - shutil.copy(elem, new_elem) - if verbose: - print("Creating File: " + new_elem) - - -if __name__ == "__main__": - if len(sys.argv) > 1 and sys.argv[1] == "--verbose": - verbose = True - #src_dir = "./src/omniax/" - #inc_dir = "./Build/include" - #excep_dirs = [inc_dir + "/vendor/GLAD", inc_dir + "/vendor/glm"] - src_dir = os.path.join(".", "src") - inc_dir = os.path.join(".", "Build", "include") - excep_dirs = [os.path.join(inc_dir, "vendor", "GLAD"), os.path.join(inc_dir, "vendor", "glm"), os.path.join(inc_dir, "vendor", "clip"), os.path.join(inc_dir, "vendor", "MiniAudio")] - install_includes(src_dir, inc_dir, excep_dirs) - diff --git a/tools/inc_bnr b/tools/inc_bnr index 0bd20cfe0644b1df75c9e123fa6bffab613ddc8d..4a0e37bfd303aa1d806667a1e1f15b0e6baf8fef 100755 GIT binary patch literal 16880 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 diff --git a/tools/inc_bnr.exe b/tools/inc_bnr.exe index 2449335d646cd4a9f777ab171baa0a1307c478a0..ba3b943ec5bddfc32f77a1adec8d9b71501714a0 100755 GIT binary patch literal 136717 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