Ecore_Win32: add API to retrieve the geometry and dpi of plugged displays

@feature

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Vincent Torri 2017-05-05 07:52:12 +02:00 committed by Cedric BAIL
parent 122c34b2ce
commit 449b2a4bf3
5 changed files with 282 additions and 3 deletions

View File

@ -18,6 +18,7 @@ lib/ecore_win32/ecore_win32_dnd_data_object.cpp \
lib/ecore_win32/ecore_win32_dnd_drop_source.cpp \
lib/ecore_win32/ecore_win32_dnd_drop_target.cpp \
lib/ecore_win32/ecore_win32_event.c \
lib/ecore_win32/ecore_win32_monitor.c \
lib/ecore_win32/ecore_win32_window.c \
lib/ecore_win32/ecore_win32_private.h \
lib/ecore_win32/ecore_win32_cursor_x11.h \

View File

@ -740,6 +740,35 @@ EAPI Eina_Bool ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
*/
EAPI Eina_Bool ecore_win32_clipboard_clear(const Ecore_Win32_Window *window);
/**
* @typedef Ecore_Win32_Monitor
* Desktop geometry and dpi of a monitor.
*
* @since 1.20
*/
typedef struct
{
Eina_Rectangle desktop; /**< Coordinates and size of the desktop */
struct
{
unsigned int x; /**< DPI along the X axis */
unsigned int y; /**< DPI along the Y axis */
} dpi;
} Ecore_Win32_Monitor;
/**
* @brief Return the coordinates, sizes DPI's of the monitors.
*
* @return An iterator of an Eina list, with #Ecore_Win32_Monitor
* as data.
*
* This function returns the coordinates, sizes and DPI's of the
* monitors as an iterator of a list of #Ecore_Win32_Monitor.
*
* @since 1.20
*/
EAPI Eina_Iterator *ecore_win32_monitors_get(void);
/**
* @}
*/

View File

@ -8,6 +8,7 @@
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <windowsx.h>
#include <dbt.h>
#include <Eina.h>
#include <Ecore.h>
@ -209,6 +210,7 @@ _ecore_win32_window_procedure(HWND window,
efl_AddClipboardFormatListener acfl;
INF("create window message");
acfl = (efl_AddClipboardFormatListener)GetProcAddress(GetModuleHandle("user32.dll"),
"AddClipboardFormatListener");
if (acfl)
@ -386,6 +388,20 @@ _ecore_win32_window_procedure(HWND window,
case WM_SYNCPAINT:
INF("sync paint message");
return 0;
/* Desktop notifications */
case WM_DEVICECHANGE:
if (window == ecore_win32_monitor_window)
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)data_param;
if ((window_param == DBT_DEVICEARRIVAL) &&
(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
ecore_win32_monitor_update(1);
if ((window_param == DBT_DEVICEREMOVECOMPLETE) &&
(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
ecore_win32_monitor_update(2);
}
default:
return DefWindowProc(window, message, window_param, data_param);
}
@ -578,6 +594,8 @@ ecore_win32_init()
for (i = 0; i < 77; i++)
_ecore_win32_cursor_x[i] = _ecore_win32_cursor_x11_shaped_new(i);
ecore_win32_monitor_init();
return _ecore_win32_init_count;
unregister_class:
@ -612,6 +630,8 @@ ecore_win32_shutdown()
if (--_ecore_win32_init_count != 0)
return _ecore_win32_init_count;
ecore_win32_monitor_shutdown();
for (i = 0; i < 77; i++)
ecore_win32_cursor_free(_ecore_win32_cursor_x[i]);

View File

@ -0,0 +1,224 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <dbt.h>
#include <Eina.h>
#include "Ecore_Win32.h"
#include "ecore_win32_private.h"
/*============================================================================*
* Local *
*============================================================================*/
/**
* @cond LOCAL
*/
typedef struct
{
Ecore_Win32_Monitor monitor;
char *name;
Eina_Bool delete_me : 1;
} Ecore_Win32_Monitor_Priv;
typedef HRESULT (WINAPI *GetDpiForMonitor_t)(HMONITOR, int, UINT *, UINT *);
static HMODULE _ecore_win32_mod = NULL;
static GetDpiForMonitor_t GetDpiForMonitor_ = NULL;
static Eina_List *ecore_win32_monitors = NULL;
#ifndef GUID_DEVINTERFACE_MONITOR
static GUID GUID_DEVINTERFACE_MONITOR = {0xe6f07b5f, 0xee97, 0x4a90, { 0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7} };
#endif
static void
_ecore_win32_monitor_free(void *p)
{
Ecore_Win32_Monitor_Priv *ewm = p;
if (ewm)
{
free(ewm->name);
free(ewm);
}
}
static BOOL CALLBACK
_ecore_win32_monitor_update_cb(HMONITOR m, HDC monitor EINA_UNUSED, LPRECT r EINA_UNUSED, LPARAM data)
{
MONITORINFOEX mi;
Ecore_Win32_Monitor_Priv *ewm;
Eina_Bool is_added;
mi.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(m, (MONITORINFO *)&mi);
if (data == 1)
{
Eina_List *l;
is_added = EINA_FALSE;
EINA_LIST_FOREACH(ecore_win32_monitors, l, ewm)
{
if (strcmp(mi.szDevice, ewm->name) != 0)
{
is_added = EINA_TRUE;
break;
}
}
}
else if (data == 2)
{
Eina_List *l;
EINA_LIST_FOREACH(ecore_win32_monitors, l, ewm)
{
if (strcmp(mi.szDevice, ewm->name) == 0)
{
ewm->delete_me = EINA_FALSE;
return FALSE;
}
}
}
else
is_added = EINA_TRUE;
if (!is_added)
return TRUE;
ewm = (Ecore_Win32_Monitor_Priv *)malloc(sizeof(Ecore_Win32_Monitor_Priv));
if (ewm)
{
ewm->monitor.desktop.x = mi.rcMonitor.left;
ewm->monitor.desktop.y = mi.rcMonitor.top;
ewm->monitor.desktop.w = mi.rcMonitor.right - mi.rcMonitor.left;
ewm->monitor.desktop.h = mi.rcMonitor.bottom - mi.rcMonitor.top;
if (!GetDpiForMonitor_ ||
(GetDpiForMonitor_(m, 0,
&ewm->monitor.dpi.x,
&ewm->monitor.dpi.y) != S_OK))
{
HDC dc;
dc = GetDC(NULL);
ewm->monitor.dpi.x = GetDeviceCaps(dc, LOGPIXELSX);
ewm->monitor.dpi.y = GetDeviceCaps(dc, LOGPIXELSY);
ReleaseDC(NULL, dc);
}
ewm->name = strdup(mi.szDevice);
if (ewm->name)
ecore_win32_monitors = eina_list_append(ecore_win32_monitors, ewm);
else
free(ewm);
}
return TRUE;
}
/**
* @endcond
*/
/*============================================================================*
* Global *
*============================================================================*/
HWND ecore_win32_monitor_window = NULL;
void
ecore_win32_monitor_init(void)
{
DEV_BROADCAST_DEVICEINTERFACE notification;
DWORD style;
style = WS_POPUP & ~(WS_CAPTION | WS_THICKFRAME);
ecore_win32_monitor_window = CreateWindow(ECORE_WIN32_WINDOW_CLASS, "",
style,
10, 10,
100, 100,
NULL, NULL,
_ecore_win32_instance, NULL);
if (ecore_win32_monitor_window)
{
ZeroMemory(&notification, sizeof(notification));
notification.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
notification.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notification.dbcc_classguid = GUID_DEVINTERFACE_MONITOR;
RegisterDeviceNotification(ecore_win32_monitor_window,
&notification,
DEVICE_NOTIFY_WINDOW_HANDLE);
}
/*
* Even if RegisterDeviceNotification() fails, the next call will
* fill one item of the monitor lists, except if there is no more
* memory
*/
ecore_win32_monitor_update(0);
_ecore_win32_mod = LoadLibrary("shcore.dll");
if (_ecore_win32_mod)
GetDpiForMonitor_ = (GetDpiForMonitor_t)GetProcAddress(_ecore_win32_mod,
"GetDpiForMonitor");
}
void
ecore_win32_monitor_shutdown(void)
{
Ecore_Win32_Monitor_Priv *ewm;
if (_ecore_win32_mod)
FreeLibrary(_ecore_win32_mod);
EINA_LIST_FREE(ecore_win32_monitors, ewm)
_ecore_win32_monitor_free(ewm);
if (ecore_win32_monitor_window)
DestroyWindow(ecore_win32_monitor_window);
}
void
ecore_win32_monitor_update(int d)
{
Ecore_Win32_Monitor_Priv *ewm;
Eina_List *l;
if (d == 2)
{
EINA_LIST_FOREACH(ecore_win32_monitors, l, ewm)
ewm->delete_me = EINA_TRUE;
}
EnumDisplayMonitors(NULL, NULL, _ecore_win32_monitor_update_cb, d);
if (d == 2)
{
EINA_LIST_FOREACH(ecore_win32_monitors, l, ewm)
{
if (ewm->delete_me == EINA_TRUE)
{
ecore_win32_monitors = eina_list_remove(ecore_win32_monitors, ewm);
_ecore_win32_monitor_free(ewm);
break;
}
}
}
}
/*============================================================================*
* API *
*============================================================================*/
EAPI Eina_Iterator *
ecore_win32_monitors_get(void)
{
return eina_list_iterator_new(ecore_win32_monitors);
}

View File

@ -6,9 +6,6 @@
extern "C" {
#endif
/* logging messages macros */
extern int _ecore_win32_log_dom_global;
#ifdef ECORE_WIN32_DEFAULT_LOG_COLOR
# undef ECORE_WIN32_DEFAULT_LOG_COLOR
#endif
@ -134,12 +131,16 @@ struct _Ecore_Win32_Window
};
/* logging messages macros */
extern int _ecore_win32_log_dom_global;
extern HINSTANCE _ecore_win32_instance;
extern double _ecore_win32_double_click_time;
extern unsigned long _ecore_win32_event_last_time;
extern Ecore_Win32_Window *_ecore_win32_event_last_window;
extern Ecore_Win32_Cursor *_ecore_win32_cursor_x[77];
extern HWND ecore_win32_monitor_window;
void _ecore_win32_event_handle_key_press(Ecore_Win32_Callback_Data *msg);
void _ecore_win32_event_handle_key_release(Ecore_Win32_Callback_Data *msg);
@ -173,6 +174,10 @@ Eina_Bool ecore_win32_window_drag(Ecore_Win32_Window *w, int ptx, int pty);
Ecore_Win32_Cursor *_ecore_win32_cursor_x11_shaped_new(Ecore_Win32_Cursor_X11_Shape shape);
void ecore_win32_monitor_init(void);
void ecore_win32_monitor_shutdown(void);
void ecore_win32_monitor_update(int d);
#ifdef __cplusplus
}