forked from enlightenment/efl
ecore_win32: add clipboard management
@feature Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
parent
9e5852fcfb
commit
abf4364b30
|
@ -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 \
|
||||
|
|
|
@ -128,6 +128,21 @@ typedef enum
|
|||
ECORE_WIN32_DND_EVENT_DROP = 4 /**< Drop */
|
||||
} 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.
|
||||
|
@ -213,6 +228,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.
|
||||
|
@ -350,6 +381,33 @@ struct _Ecore_Win32_Event_Window_Delete_Request
|
|||
unsigned long timestamp; /**< The time the event occurred */
|
||||
};
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue