diff options
author | Vincent Torri <vincent dot torri at gmail dot com> | 2015-10-15 23:11:28 +0200 |
---|---|---|
committer | Nicolas Aguirre <aguirre.nicolas@gmail.com> | 2015-11-10 08:32:49 +0100 |
commit | 5f056dc2b3f348634dd1eb6854067841dabedc6f (patch) | |
tree | b0dc322bed74627db97328991b101d906658fa50 | |
parent | 65b71bcea72322f42c12d5688320c3b385c0605e (diff) | |
download | efl-5f056dc2b3f348634dd1eb6854067841dabedc6f.tar.gz |
Ecore_Win32: add clipboard management
@feature
-rw-r--r-- | src/Makefile_Ecore_Win32.am | 1 | ||||
-rw-r--r-- | src/lib/ecore_win32/Ecore_Win32.h | 114 | ||||
-rw-r--r-- | src/lib/ecore_win32/ecore_win32.c | 53 | ||||
-rw-r--r-- | src/lib/ecore_win32/ecore_win32_clipboard.c | 188 | ||||
-rw-r--r-- | src/lib/ecore_win32/ecore_win32_event.c | 70 | ||||
-rw-r--r-- | src/lib/ecore_win32/ecore_win32_private.h | 1 |
6 files changed, 420 insertions, 7 deletions
diff --git a/src/Makefile_Ecore_Win32.am b/src/Makefile_Ecore_Win32.am index dbdaec549d..0f564f6a97 100644 --- a/src/Makefile_Ecore_Win32.am +++ b/src/Makefile_Ecore_Win32.am @@ -10,6 +10,7 @@ lib/ecore_win32/Ecore_Win32.h lib_ecore_win32_libecore_win32_la_SOURCES = \ lib/ecore_win32/ecore_win32.c \ +lib/ecore_win32/ecore_win32_clipboard.c \ lib/ecore_win32/ecore_win32_cursor.c \ lib/ecore_win32/ecore_win32_dnd.c \ lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp \ diff --git a/src/lib/ecore_win32/Ecore_Win32.h b/src/lib/ecore_win32/Ecore_Win32.h index 154ede87b6..0e0582ba96 100644 --- a/src/lib/ecore_win32/Ecore_Win32.h +++ b/src/lib/ecore_win32/Ecore_Win32.h @@ -129,6 +129,21 @@ typedef enum } Ecore_Win32_DnD_State; /** + * @typedef Ecore_Win32_Selection + * Type of the selection. + * + * @since 1.16 + */ +typedef enum +{ + ECORE_WIN32_SELECTION_PRIMARY, + ECORE_WIN32_SELECTION_SECONDARY, + ECORE_WIN32_SELECTION_DND, + ECORE_WIN32_SELECTION_CLIPBOARD, + ECORE_WIN32_SELECTION_OTHER +} Ecore_Win32_Selection; + +/** * @typedef Ecore_Win32_Window * Abstract type for a window. */ @@ -214,6 +229,22 @@ typedef struct _Ecore_Win32_Event_Window_Resize Ecore_Win32_Event_Window typedef struct _Ecore_Win32_Event_Window_Delete_Request Ecore_Win32_Event_Window_Delete_Request; /** + * @typedef Ecore_Win32_Event_Selection_Clear + * Event sent when the content of the clipboard has been removed. + * + * @since 1.16 + */ +typedef struct _Ecore_Win32_Event_Selection_Clear Ecore_Win32_Event_Selection_Clear; + +/** + * @typedef Ecore_Win32_Event_Selection_Notify + * Event sent when the content of the clipboard has been added. + * + * @since 1.16 + */ +typedef struct _Ecore_Win32_Event_Selection_Notify Ecore_Win32_Event_Selection_Notify; + +/** * @struct _Ecore_Win32_Event_Mouse_In * Event sent when the mouse enters the window. */ @@ -351,6 +382,33 @@ struct _Ecore_Win32_Event_Window_Delete_Request }; /** + * @struct _Ecore_Win32_Event_Selection_Clear + * Event sent when the content of the clipboard has been removed. + * + * @since 1.16 + */ +struct _Ecore_Win32_Event_Selection_Clear +{ + Ecore_Win32_Window *window; /**< The window that received the event */ + unsigned long timestamp; /**< The time the event occurred */ + Ecore_Win32_Selection selection; /**< The type of the selection */ +}; + +/** + * @struct _Ecore_Win32_Event_Selection_Notify + * Event sent when the content of the clipboard has been added. + * + * @since 1.16 + */ +struct _Ecore_Win32_Event_Selection_Notify +{ + Ecore_Win32_Window *window; /**< The window that received the event */ + unsigned long timestamp; /**< The time the event occurred */ + Ecore_Win32_Selection selection; /**< The type of the selection */ + void *data; /**< The data of the selection */ +}; + +/** * @typedef Ecore_Win32_Dnd_DropTarget_Callback * Callback type for Drop operations. See ecore_win32_dnd_register_drop_target(). */ @@ -368,6 +426,8 @@ EAPI extern int ECORE_WIN32_EVENT_WINDOW_SHOW; /**< Ecore_Event for the Ecore_Wi EAPI extern int ECORE_WIN32_EVENT_WINDOW_CONFIGURE; /**< Ecore_Event for the Ecore_Win32_Event_Configure event */ EAPI extern int ECORE_WIN32_EVENT_WINDOW_RESIZE; /**< Ecore_Event for the Ecore_Win32_Event_Resize event */ EAPI extern int ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST; /**< Ecore_Event for the #Ecore_Win32_Event_Window_Delete_Request event */ +EAPI extern int ECORE_WIN32_EVENT_SELECTION_CLEAR; /**< Ecore_Event for the #Ecore_Win32_Event_Selection_Clear event @since 1.16 */ +EAPI extern int ECORE_WIN32_EVENT_SELECTION_NOTIFY; /**< Ecore_Event for the #Ecore_Win32_Event_Selection_Notify event @since 1.16 */ /* Core */ @@ -516,6 +576,60 @@ EAPI Eina_Bool ecore_win32_dnd_register_drop_target(Ecore_Win32_Window Ecore_Win32_Dnd_DropTarget_Callback callback); EAPI void ecore_win32_dnd_unregister_drop_target(Ecore_Win32_Window *window); +/* Clipboard */ + +/** + * @brief Set data to the clipboard. + * + * @param[in] window The window that owns the clipboard. + * @param[in] data The data to set. + * @param[in] size The size of the data. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * This function sets @p data of size @p size in the clipboard owned by + * @p window. This function returns #EINA_TRUE on success, and + * #EINA_FALSE otherwise. If @p window or @p data are @c NULL, or @p size + * is less than or equal to 0, this function returns #EINA_FALSE. + * + * @since 1.16 + */ +EAPI Eina_Bool ecore_win32_clipboard_set(const Ecore_Win32_Window *window, + const void *data, + int size); + +/** + * @brief Get data from the clipboard. + * + * @param[in] window The window that owns the clipboard. + * @param[out] data The retrieved data. + * @param[out] size The size of the data. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * This function gets @p data of size @p size from the clipboard owned by + * @p window. This function returns #EINA_TRUE on success, and + * #EINA_FALSE otherwise. If @p window is @c NULL, this function returns + * #EINA_FALSE. @p data and @p size must be valid buffers. + * + * @since 1.16 + */ +EAPI Eina_Bool ecore_win32_clipboard_get(const Ecore_Win32_Window *window, + void **data, + int *size); + +/** + * @brief Cleat the clipboard. + * + * @param[in] window The window that owns the clipboard. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * This function clears the clipboard owned by @p window. This + * function returns #EINA_TRUE on success, and #EINA_FALSE otherwise. + * If @p window is @c NULL, this function returns #EINA_FALSE. + * + * @since 1.16 + */ +EAPI Eina_Bool ecore_win32_clipboard_clear(const Ecore_Win32_Window *window); + /** * @} */ diff --git a/src/lib/ecore_win32/ecore_win32.c b/src/lib/ecore_win32/ecore_win32.c index 37b79565b4..cdee3916ee 100644 --- a/src/lib/ecore_win32/ecore_win32.c +++ b/src/lib/ecore_win32/ecore_win32.c @@ -24,10 +24,18 @@ * @cond LOCAL */ +/* FIXME: uncomment when mingw-w64 will be updated in win-builds */ + +/* #if _WIN32_WINNT >= 0x0600 */ +/* # ifndef WM_CLIPBOARDUPDATE */ +# define WM_CLIPBOARDUPDATE 0x031D +/* # endif */ +/* #endif */ + /* OLE IID for Drag'n Drop */ -# define INITGUID -# include <basetyps.h> +#define INITGUID +#include <basetyps.h> DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103L, 0, 0); DEFINE_OLEGUID(IID_IDataObject, 0x0000010EL, 0, 0); DEFINE_OLEGUID(IID_IDropSource, 0x00000121L, 0, 0); @@ -36,7 +44,10 @@ DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0); #define IDI_ICON 101 -static int _ecore_win32_init_count = 0; +typedef BOOL WINAPI (*efl_AddClipboardFormatListener)(_In_ HWND hwnd); +typedef BOOL WINAPI (*efl_RemoveClipboardFormatListener)(_In_ HWND hwnd); + +static int _ecore_win32_init_count = 0; LRESULT CALLBACK _ecore_win32_window_procedure(HWND window, @@ -194,13 +205,33 @@ _ecore_win32_window_procedure(HWND window, return 0; /* Window notifications */ case WM_CREATE: - INF("create window message"); + { + efl_AddClipboardFormatListener acfl; + + INF("create window message"); + acfl = (efl_AddClipboardFormatListener)GetProcAddress(GetModuleHandle("user32.dll"), + "AddClipboardFormatListener"); + if (acfl) + { + if (!acfl(window)) + INF("can not create clipboard format listener; no clipboard notification will be sent"); + } _ecore_win32_event_handle_create_notify(data); return 0; + } case WM_DESTROY: - INF("destroy window message"); - _ecore_win32_event_handle_destroy_notify(data); - return 0; + { + efl_RemoveClipboardFormatListener rcfl; + + INF("destroy window message"); + _ecore_win32_event_handle_destroy_notify(data); + + rcfl = (efl_RemoveClipboardFormatListener)GetProcAddress(GetModuleHandle("user32.dll"), + "RemoveClipboardFormatListener"); + if (rcfl) + rcfl(window); + return 0; + } case WM_SHOWWINDOW: INF("show window message"); if ((data->data_param == SW_OTHERUNZOOM) || @@ -299,6 +330,10 @@ _ecore_win32_window_procedure(HWND window, return 0; } return DefWindowProc(window, message, window_param, data_param); + case WM_CLIPBOARDUPDATE: + INF("clipboard data updated"); + _ecore_win32_event_handle_selection_notify(data); + return 0; /* GDI notifications */ case WM_PAINT: { @@ -358,6 +393,8 @@ int ECORE_WIN32_EVENT_WINDOW_HIDE = 0; int ECORE_WIN32_EVENT_WINDOW_CONFIGURE = 0; int ECORE_WIN32_EVENT_WINDOW_RESIZE = 0; int ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = 0; +int ECORE_WIN32_EVENT_SELECTION_CLEAR = 0; +int ECORE_WIN32_EVENT_SELECTION_NOTIFY = 0; /*============================================================================* * API * @@ -504,6 +541,8 @@ ecore_win32_init() ECORE_WIN32_EVENT_WINDOW_CONFIGURE = ecore_event_type_new(); ECORE_WIN32_EVENT_WINDOW_RESIZE = ecore_event_type_new(); ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new(); + ECORE_WIN32_EVENT_SELECTION_CLEAR = ecore_event_type_new(); + ECORE_WIN32_EVENT_SELECTION_NOTIFY = ecore_event_type_new(); } return _ecore_win32_init_count; diff --git a/src/lib/ecore_win32/ecore_win32_clipboard.c b/src/lib/ecore_win32/ecore_win32_clipboard.c new file mode 100644 index 0000000000..ec9934ea32 --- /dev/null +++ b/src/lib/ecore_win32/ecore_win32_clipboard.c @@ -0,0 +1,188 @@ +#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <Eina.h>
+
+#include "Ecore_Win32.h"
+#include "ecore_win32_private.h"
+
+/*============================================================================*
+ * Local *
+ *============================================================================*/
+
+/**
+ * @cond LOCAL
+ */
+
+
+
+/**
+ * @endcond
+ */
+
+
+/*============================================================================*
+ * Global *
+ *============================================================================*/
+
+
+/*============================================================================*
+ * API *
+ *============================================================================*/
+
+
+EAPI Eina_Bool
+ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
+ const void *data,
+ int size)
+{
+ HGLOBAL global;
+ char *d;
+
+ /*
+ * See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx#_win32_Copying_Information_to_the_Clipboard
+ * 1. Open the clipboard
+ * 2. Empty the clipboard
+ * 3. Set the data
+ * 4. Close the clipboard
+ */
+
+ INF("setting data to the clipboard");
+
+ if (!window || !data || (size <= 0))
+ return EINA_FALSE;
+
+ if (!OpenClipboard(window->window))
+ return EINA_FALSE;
+
+ if (!EmptyClipboard())
+ goto close_clipboard;
+
+ global = GlobalAlloc(GMEM_MOVEABLE, size + 1);
+ if (!global)
+ goto close_clipboard;
+
+ d = (char *)GlobalLock(global);
+ if (!d)
+ goto unlock_global;
+
+ memcpy(d, data, size);
+ d[size] = '\0';
+ GlobalUnlock(global);
+ SetClipboardData(CF_TEXT, global);
+ CloseClipboard();
+
+ return EINA_TRUE;
+
+ unlock_global:
+ GlobalUnlock(global);
+ close_clipboard:
+ CloseClipboard();
+
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
+ void **data,
+ int *size)
+{
+ HGLOBAL global;
+ void *d;
+ void *p;
+
+ /*
+ * See https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx#_win32_Pasting_Information_from_the_Clipboard
+ * 1. Open Clipboard
+ * 2. Determine format
+ * 3. Retrieve data
+ * 4. Manage data
+ * 5. Close clipboard
+ */
+
+ INF("getting data from the clipboard");
+
+ if (!window)
+ return EINA_FALSE;
+
+ if (!IsClipboardFormatAvailable(CF_TEXT))
+ return EINA_FALSE;
+
+ if (!OpenClipboard(window->window))
+ goto set_val;
+
+ /* { */
+ /* UINT fmt = 0; */
+
+ /* while (1) */
+ /* { */
+ /* fmt = EnumClipboardFormats(fmt); */
+ /* printf(" $ Format : %x\n", fmt); */
+ /* if (!fmt) */
+ /* break; */
+ /* } */
+ /* } */
+
+ global = GetClipboardData(CF_TEXT);
+ if (!global)
+ goto close_clipboard;
+
+ d = GlobalLock(global);
+ if (!d)
+ goto unlock_global;
+
+ *size = strlen(d);
+ p = malloc(*size);
+ if (!p)
+ goto unlock_global;
+
+ memcpy(p, d, *size);
+ *data = p;
+ GlobalUnlock(global);
+ CloseClipboard();
+
+ return EINA_TRUE;
+
+ unlock_global:
+ GlobalUnlock(global);
+ close_clipboard:
+ CloseClipboard();
+ set_val:
+ *data = NULL;
+ *size = 0;
+
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+ecore_win32_clipboard_clear(const Ecore_Win32_Window *window)
+{
+ INF("clearing the clipboard");
+
+ if (!window)
+ return EINA_FALSE;
+
+ if (!OpenClipboard(window->window))
+ return EINA_FALSE;
+
+ if (!EmptyClipboard())
+ goto close_clipboard;
+
+ CloseClipboard();
+
+ return EINA_TRUE;
+
+ close_clipboard:
+ CloseClipboard();
+
+ return EINA_FALSE;
+}
+
+/**
+ * @}
+ */
diff --git a/src/lib/ecore_win32/ecore_win32_event.c b/src/lib/ecore_win32/ecore_win32_event.c index 99ad2d49bf..b5f0d604ed 100644 --- a/src/lib/ecore_win32/ecore_win32_event.c +++ b/src/lib/ecore_win32/ecore_win32_event.c @@ -40,6 +40,7 @@ static int _ecore_win32_mouse_down_did_triple = 0; static int _ecore_win32_mouse_up_count = 0; static Ecore_Win32_Key_Mask _ecore_win32_key_mask = 0; static Eina_Bool _ecore_win32_ctrl_fake = EINA_FALSE; +static Eina_Bool _ecore_win32_clipboard_has_data = EINA_FALSE; static unsigned int _ecore_win32_modifiers_get(void) @@ -1895,3 +1896,72 @@ _ecore_win32_event_handle_delete_request(Ecore_Win32_Callback_Data *msg) ecore_event_add(ECORE_WIN32_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL); } + +void +_ecore_win32_event_handle_selection_notify(Ecore_Win32_Callback_Data *msg) +{ + Ecore_Win32_Event_Selection_Notify *e; + HGLOBAL global; + char *str; + + INF("selection_notify"); + + /* + * we have text data in clipboard but no data before, + * so text data has just been added + */ + if (IsClipboardFormatAvailable(CF_TEXT) && !_ecore_win32_clipboard_has_data) + { + e = calloc(1, sizeof(Ecore_Win32_Event_Selection_Notify)); + if (!e) return; + + e->window = (void *)GetWindowLongPtr(msg->window, GWLP_USERDATA); + e->timestamp = _ecore_win32_event_last_time; + e->selection = ECORE_WIN32_SELECTION_CLIPBOARD; + + if (!OpenClipboard(msg->window)) + goto free_e; + + global = GetClipboardData(CF_TEXT); + if (!global) + goto close_clipboard; + + str = GlobalLock(global); + if (str) + { + e->data = strdup(str); + GlobalUnlock(global); + } + + CloseClipboard(); + + ecore_event_add(ECORE_WIN32_EVENT_SELECTION_NOTIFY, e, NULL, NULL); + + _ecore_win32_clipboard_has_data = EINA_TRUE; + } + + /* + * we have no more text data in clipboard and data before, + * so text data has just been removed + */ + if (!IsClipboardFormatAvailable(CF_TEXT) && _ecore_win32_clipboard_has_data) + { + e = calloc(1, sizeof(Ecore_Win32_Event_Selection_Clear)); + if (!e) return; + + e->window = (void *)GetWindowLongPtr(msg->window, GWLP_USERDATA); + e->timestamp = _ecore_win32_event_last_time; + e->selection = ECORE_WIN32_SELECTION_CLIPBOARD; + + ecore_event_add(ECORE_WIN32_EVENT_SELECTION_CLEAR, e, NULL, NULL); + + _ecore_win32_clipboard_has_data = EINA_FALSE; + } + + return; + + close_clipboard: + CloseClipboard(); + free_e: + free(e); +} diff --git a/src/lib/ecore_win32/ecore_win32_private.h b/src/lib/ecore_win32/ecore_win32_private.h index 1e2bb1bd19..23af65ad98 100644 --- a/src/lib/ecore_win32/ecore_win32_private.h +++ b/src/lib/ecore_win32/ecore_win32_private.h @@ -164,6 +164,7 @@ void _ecore_win32_event_handle_unmap_notify(Ecore_Win32_Callback_Data *msg); void _ecore_win32_event_handle_configure_notify(Ecore_Win32_Callback_Data *msg); void _ecore_win32_event_handle_resize(Ecore_Win32_Callback_Data *msg); void _ecore_win32_event_handle_delete_request(Ecore_Win32_Callback_Data *msg); +void _ecore_win32_event_handle_selection_notify(Ecore_Win32_Callback_Data *msg); void *_ecore_win32_dnd_data_object_new(void *fmtetc, void *stgmeds, int count); void _ecore_win32_dnd_data_object_free(void *data_object); |