cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=449b2a4bf3b072d039bcebfb7f811b75cb9644bc

commit 449b2a4bf3b072d039bcebfb7f811b75cb9644bc
Author: Vincent Torri <vincent.to...@gmail.com>
Date:   Fri May 5 07:52:12 2017 +0200

    Ecore_Win32: add API to retrieve the geometry and dpi of plugged displays
    
    @feature
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 src/Makefile_Ecore_Win32.am               |   1 +
 src/lib/ecore_win32/Ecore_Win32.h         |  29 ++++
 src/lib/ecore_win32/ecore_win32.c         |  20 +++
 src/lib/ecore_win32/ecore_win32_monitor.c | 224 ++++++++++++++++++++++++++++++
 src/lib/ecore_win32/ecore_win32_private.h |  11 +-
 5 files changed, 282 insertions(+), 3 deletions(-)

diff --git a/src/Makefile_Ecore_Win32.am b/src/Makefile_Ecore_Win32.am
index 8a407e9..c230a8b 100644
--- a/src/Makefile_Ecore_Win32.am
+++ b/src/Makefile_Ecore_Win32.am
@@ -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 \
diff --git a/src/lib/ecore_win32/Ecore_Win32.h 
b/src/lib/ecore_win32/Ecore_Win32.h
index 19a8b2c..34e8596 100644
--- a/src/lib/ecore_win32/Ecore_Win32.h
+++ b/src/lib/ecore_win32/Ecore_Win32.h
@@ -741,6 +741,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);
+
+/**
  * @}
  */
 
diff --git a/src/lib/ecore_win32/ecore_win32.c 
b/src/lib/ecore_win32/ecore_win32.c
index cd75bee..7b170c9 100644
--- a/src/lib/ecore_win32/ecore_win32.c
+++ b/src/lib/ecore_win32/ecore_win32.c
@@ -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]);
 
diff --git a/src/lib/ecore_win32/ecore_win32_monitor.c 
b/src/lib/ecore_win32/ecore_win32_monitor.c
new file mode 100644
index 0000000..36d1369
--- /dev/null
+++ b/src/lib/ecore_win32/ecore_win32_monitor.c
@@ -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);
+}
diff --git a/src/lib/ecore_win32/ecore_win32_private.h 
b/src/lib/ecore_win32/ecore_win32_private.h
index bb22b46..1956f8b 100644
--- a/src/lib/ecore_win32/ecore_win32_private.h
+++ b/src/lib/ecore_win32/ecore_win32_private.h
@@ -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
 }

-- 


Reply via email to