summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Torri <vincent dot torri at gmail dot com>2015-10-15 23:11:28 +0200
committerNicolas Aguirre <aguirre.nicolas@gmail.com>2015-11-10 08:32:49 +0100
commit5f056dc2b3f348634dd1eb6854067841dabedc6f (patch)
treeb0dc322bed74627db97328991b101d906658fa50
parent65b71bcea72322f42c12d5688320c3b385c0605e (diff)
downloadefl-5f056dc2b3f348634dd1eb6854067841dabedc6f.tar.gz
Ecore_Win32: add clipboard management
@feature
-rw-r--r--src/Makefile_Ecore_Win32.am1
-rw-r--r--src/lib/ecore_win32/Ecore_Win32.h114
-rw-r--r--src/lib/ecore_win32/ecore_win32.c53
-rw-r--r--src/lib/ecore_win32/ecore_win32_clipboard.c188
-rw-r--r--src/lib/ecore_win32/ecore_win32_event.c70
-rw-r--r--src/lib/ecore_win32/ecore_win32_private.h1
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);