diff --git a/clip.cpp b/clip.cpp index bd221fc..06e0902 100644 --- a/clip.cpp +++ b/clip.cpp @@ -27,7 +27,14 @@ void default_error_handler(ErrorCode code) { error_handler g_error_handler = default_error_handler; lock::lock(void* native_window_handle) - : p(new impl(native_window_handle)) { + : lock(get_error_handler(), 5, 20, native_window_handle) { +} + +lock::lock(error_handler e, int tries, int sleepms, void* native_window_handle) + : p(new impl(native_window_handle, tries, sleepms)) { + if (!p->locked() && e) { + e(ErrorCode::CannotLock); + } } lock::~lock() = default; @@ -80,6 +87,14 @@ bool has(format f) { return false; } +bool has(format f, error_handler e, int tries, int sleepms) { + lock l(e, tries, sleepms); + if (l.locked()) + return l.is_convertible(f); + else + return false; +} + bool clear() { lock l; if (l.locked()) diff --git a/clip.h b/clip.h index bf3c9fd..7d448b0 100644 --- a/clip.h +++ b/clip.h @@ -24,6 +24,22 @@ namespace clip { class image; struct image_spec; + // ====================================================================== + // 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(); + + #define OMIT_LOCKING_ERROR nullptr + class lock { public: // You can give your current HWND as the "native_window_handle." @@ -33,6 +49,12 @@ namespace clip { // EmptyClipboard() call. Anyway it looks to work just fine if we // call OpenClipboard() with a null HWND. lock(void* native_window_handle = nullptr); + // Creates a lock where you can specify an error handler to use + // when the clipboad implementation requires locking it first and + // we couldn't get the lock. Also, we can specify the number of + // times we want to try to get the clipboard lock and how many + // milliseconds we want to wait between tries. + lock(error_handler e, int tries, int sleepms, void* native_window_handle = nullptr); ~lock(); // Returns true if we've locked the clipboard successfully in @@ -75,22 +97,14 @@ namespace clip { // Returns true if the clipboard has content of the given type. bool has(format f); - // Clears the clipboard content. - bool clear(); + // The same as has(format f) but you can specify an error handler when the + // clipboard cannot be locked, along with the number of locking tries and + // waiting period between tries. + bool has(format f, error_handler e, int tries, int sleepms); - // ====================================================================== - // 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(); + // Clears the clipboard content. + bool clear(); // ====================================================================== // Text diff --git a/clip_lock_impl.h b/clip_lock_impl.h index 3f08af7..c2d5fa5 100644 --- a/clip_lock_impl.h +++ b/clip_lock_impl.h @@ -1,33 +1,34 @@ -// 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 +// 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(void* native_window_handle, int tries, int sleepms); + ~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/clip_none.cpp b/clip_none.cpp index f4cc40c..74732e9 100644 --- a/clip_none.cpp +++ b/clip_none.cpp @@ -19,7 +19,10 @@ typedef std::map Map; static format g_last_format = 100; // TODO create an enum with common formats static Map g_data; -lock::impl::impl(void* native_handle) : m_locked(true) { +lock::impl::impl(void*, int tries, int sleepms) : m_locked(true) { +} + +lock::impl::impl(void* native_handle) : impl(native_handle, 0, 0) { } lock::impl::~impl() { diff --git a/clip_osx.mm b/clip_osx.mm index 52683b8..742000b 100644 --- a/clip_osx.mm +++ b/clip_osx.mm @@ -132,7 +132,10 @@ bool get_image_from_clipboard(image* output_img, } -lock::impl::impl(void*) : m_locked(true) { +lock::impl::impl(void*, int tries, int sleepms) : m_locked(true) { +} + +lock::impl::impl(void*) : impl(nullptr, 0, 0) { } lock::impl::~impl() { diff --git a/clip_win.cpp b/clip_win.cpp index d03a798..1145cfd 100644 --- a/clip_win.cpp +++ b/clip_win.cpp @@ -207,20 +207,17 @@ struct BitmapInfo { } -lock::impl::impl(void* hwnd) : m_locked(false) { - for (int i=0; i<5; ++i) { +lock::impl::impl(void* hwnd, int tries, int sleepms) : m_locked(false) { + for (int i = 0; i < tries; ++i) { if (OpenClipboard((HWND)hwnd)) { m_locked = true; break; } - Sleep(20); + Sleep(sleepms); } +} - if (!m_locked) { - error_handler e = get_error_handler(); - if (e) - e(ErrorCode::CannotLock); - } +lock::impl::impl(void* hwnd) : impl(hwnd, 5, 20) { } lock::impl::~impl() { diff --git a/clip_x11.cpp b/clip_x11.cpp index 842105b..ad4bc3a 100644 --- a/clip_x11.cpp +++ b/clip_x11.cpp @@ -123,7 +123,7 @@ class 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()) { + if (try_lock(5, 20)) { // Start the SAVE_TARGETS mechanism so the X11 // CLIPBOARD_MANAGER will save our clipboard data // from now on. @@ -148,13 +148,13 @@ class Manager { xcb_disconnect(m_connection); } - bool try_lock() { + bool try_lock(int tries, int sleepms) { 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) { + for (int i=0; itry_lock(tries, sleepms); +} + lock::impl::impl(void*) : m_locked(false) { - m_locked = get_manager()->try_lock(); + m_locked = get_manager()->try_lock(5, 20); } lock::impl::~impl() {