<html><body><div style="font-family: times new roman, new york, times, serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Javier Celaya" <javier.celaya@flexvdi.com><br><b>To: </b>"Frediano Ziglio" <fziglio@redhat.com><br><b>Cc: </b>spice-devel@lists.freedesktop.org, devel@flexvdi.com<br><b>Sent: </b>Thursday, February 11, 2016 3:50:00 PM<br><b>Subject: </b>Re: [Spice-devel] [vd-agent-win32 2/2] Use CCD API to update the WDDM display modes.<br><div><br></div><br><br><div class="moz-cite-prefix">El 11/02/16 a las 15:44, Javier Celaya
      escribió:<br></div><blockquote cite="mid:56BC9E38.6010301@flexvdi.com"><br><br><div class="moz-cite-prefix">El 11/02/16 a las 12:04, Frediano
        Ziglio escribió:<br></div><blockquote cite="mid:569393689.22271021.1455188649820.JavaMail.zimbra@redhat.com"><div style="font-family: times new roman, new york, times,
          serif; font-size: 12pt; color: #000000"><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div><br></div>
            Hi, I answer inline<br><br><div class="moz-cite-prefix">El 10/02/16 a las 16:33,
              Frediano Ziglio escribió:<br></div><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>When a new custom display mode is added, the current WDDM driver notifies
a disconnection and reconnection of the virtual monitor to force Windows
to update the display modes. This produces an ugly effect, keeping the
screen black for up to some seconds and usually not repainting it
afterwards.

This patch uses the CCD API to update the display modes, and produces
just a quick flash followed by a whole screen repaint. For best results,
it should be used with a driver that does not update the display modes
by itself, but it is still compatible with the current implementation.
---
 common/vdcommon.h          | 40 +++++++++++++++++++++++++++
 vdagent/desktop_layout.cpp | 68
 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/common/vdcommon.h b/common/vdcommon.h
index f40e68e..29437c3 100644
--- a/common/vdcommon.h
+++ b/common/vdcommon.h
@@ -102,6 +102,46 @@ private:
     PFND3DKMT_OPENADAPTERFROMHDC _pD3DKMTOpenAdapterFromHdc;
 };
 
+// CCD API
+#define SDC_APPLY 0x00000080
+#define SDC_USE_SUPPLIED_DISPLAY_CONFIG 0x00000020
+#define SDC_FORCE_MODE_ENUMERATION 0x00001000
+#define QDC_ALL_PATHS 1
+struct DISPLAYCONFIG_PATH_INFO;
+struct DISPLAYCONFIG_MODE_INFO;
+struct DISPLAYCONFIG_TOPOLOGY_ID;
+typedef LONG (*PFNGETDISPLAYCONFIGBUFFERSIZES)(UINT32, UINT32*, UINT32*);
+typedef LONG (*PFNQUERYDISPLAYCONFIG)(UINT32, UINT32*,
DISPLAYCONFIG_PATH_INFO*, UINT32*,
+                                      DISPLAYCONFIG_MODE_INFO*,
DISPLAYCONFIG_TOPOLOGY_ID*);
+typedef LONG (*PFNSETDISPLAYCONFIG)(UINT32, DISPLAYCONFIG_PATH_INFO*,
UINT32,
+                                    DISPLAYCONFIG_MODE_INFO*, UINT32);</pre></blockquote></blockquote></blockquote><div><br></div><div>So your system headers does not have definitions for
            these!<br></div><div>My MingW have these definition in wingdi.h but you have
            to define WINVER >= 0x0601 before including the file.<br></div><div>If your environment does not have such defines I would
            suggest to put these into a compat_ccd.h (for instance) file
            so<br></div><div>is easy to remove in a future.<br></div></div></blockquote>
      I don't know how I missed that... Even the CCD API functions are
      there! So there is no need for the CCDLibrary class either, unless
      we want compatibility with quite old MinGW versions, but I don't
      see the point.<br></blockquote>
    Well, not so old, actually. The type definitions and function
    declarations were added to the headers on December 2013, but the
    functions are undefined in libuser32.a until April 2015. My MinGW
    build (from Fedora 22) issues undefined reference errors for all
    three functions, so I'm going to consider your suggestion of a
    ccd_compat.{h,c} file.</blockquote><div><br></div><div>Beside that you should also consider what does it mean version 6.1.<br></div><div>I mean, if we need to support OSes < 6.1 your approach of dynamic finding the APIs was right.<br></div><div>If you static link and the OS does not have these function the program/dll does not load<br></div><div><br></div><div>Frediano<br></div><div><br></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><br><blockquote cite="mid:56BC9E38.6010301@flexvdi.com"><blockquote cite="mid:569393689.22271021.1455188649820.JavaMail.zimbra@redhat.com"><div style="font-family: times new roman, new york, times,
          serif; font-size: 12pt; color: #000000"><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>+class CCDLibrary {
+public:
+    ~CCDLibrary();
+    static CCDLibrary& singleton() {
+        static CCDLibrary instance;
+        return instance;
+    }
+    bool found() {
+        return _hUser32 && _pGetDisplayConfigBufferSizes &&
+               _pQuieryDisplayConfig && _pSetDisplayConfig;
+    }</pre></blockquote></blockquote></blockquote><div>Why don't you return a CCDLibrary* from singleton
            returning NULL if you couldn't find the required APIs?<br></div><div>This would avoid to expose a not initialized object and
            would remove the need for a found method.<br></div><div><br></div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>+    LONG get_display_config_buffer_sizes(UINT32* num_paths, UINT32*
num_modes);
+    LONG query_display_config(UINT32* num_paths, DISPLAYCONFIG_PATH_INFO*
paths,
+                              UINT32* num_modes, DISPLAYCONFIG_MODE_INFO*
modes);
+    LONG set_display_config(UINT32 num_paths, DISPLAYCONFIG_PATH_INFO*
paths,
+                            UINT32 num_modes, DISPLAYCONFIG_MODE_INFO*
modes,
+                            UINT32 flags);
+
+private:
+    CCDLibrary();</pre></blockquote></blockquote></blockquote><div>probably here you want also the copy constructor and
            assignment operator.<br></div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>+
+    HINSTANCE _hUser32;
+    PFNGETDISPLAYCONFIGBUFFERSIZES _pGetDisplayConfigBufferSizes;
+    PFNQUERYDISPLAYCONFIG _pQuieryDisplayConfig;
+    PFNSETDISPLAYCONFIG _pSetDisplayConfig;
+};
+
 #if defined __GNUC__
 #define ALIGN_GCC __attribute__ ((packed))
 #define ALIGN_VC
diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp
index b5e8cfa..92493f3 100644
--- a/vdagent/desktop_layout.cpp
+++ b/vdagent/desktop_layout.cpp
@@ -312,6 +312,70 @@ NTSTATUS D3DKMTLibrary::close_adapter(D3DKMT_HANDLE
adapter)
     return _pD3DKMTCloseAdapter(&func_params);
 }
 
+CCDLibrary::CCDLibrary()
+    : _pGetDisplayConfigBufferSizes(NULL)
+    , _pQuieryDisplayConfig(NULL)
+    , _pSetDisplayConfig(NULL)
+{
+    _hUser32 = LoadLibrary(L"User32.dll");
</pre></blockquote><pre>probably you want a GetModuleHandle, user32 have to be already available.</pre></blockquote>
            Ok, I'll send another patch<br><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>+    if (_hUser32) {
+        _pGetDisplayConfigBufferSizes =
(PFNGETDISPLAYCONFIGBUFFERSIZES)GetProcAddress(_hUser32,
"GetDisplayConfigBufferSizes");
+        _pQuieryDisplayConfig =
(PFNQUERYDISPLAYCONFIG)GetProcAddress(_hUser32, "QueryDisplayConfig");
+        _pSetDisplayConfig = (PFNSETDISPLAYCONFIG)GetProcAddress(_hUser32,
"SetDisplayConfig");
+    }
+}
+
+
+CCDLibrary::~CCDLibrary()
+{
+    if (_hUser32)
+        FreeLibrary(_hUser32);
</pre></blockquote><pre>If you use GetModuleHandle this is not necessary

</pre><blockquote><pre>+}
+
+LONG CCDLibrary::get_display_config_buffer_sizes(UINT32* num_paths, UINT32*
num_modes)
+{
+    return _pGetDisplayConfigBufferSizes(QDC_ALL_PATHS, num_paths,
num_modes);
+}
+
+LONG CCDLibrary::query_display_config(UINT32* num_paths,
DISPLAYCONFIG_PATH_INFO* paths,
+                                      UINT32* num_modes,
DISPLAYCONFIG_MODE_INFO* modes)
+{
+    return _pQuieryDisplayConfig(QDC_ALL_PATHS, num_paths, paths, num_modes,
modes, NULL);
+}
+
+LONG CCDLibrary::set_display_config(UINT32 num_paths,
DISPLAYCONFIG_PATH_INFO* paths,
+                                    UINT32 num_modes,
DISPLAYCONFIG_MODE_INFO* modes,
+                                    UINT32 flags)
+{
+    return _pSetDisplayConfig(num_paths, paths, num_modes, modes, flags);
+}
+
+static void update_display_modes()
+{
+    // The trick here is to call SetDisplayConfig with the current config
and
+    // the SDC_FORCE_MODE_ENUMERATION flag
+    CCDLibrary& ccd = CCDLibrary::singleton();
+    if (!ccd.found()) return;
+    UINT32 num_paths = 0, num_modes = 0;
+    DISPLAYCONFIG_PATH_INFO * paths;
+    DISPLAYCONFIG_MODE_INFO * modes;
+    LONG status = ccd.get_display_config_buffer_sizes(&num_paths,
&num_modes);
+    if (NT_SUCCESS(status)) {
+        // Being conservative, struct sizes are under 100 bytes
+        paths = reinterpret_cast<DISPLAYCONFIG_PATH_INFO *>(new
char[num_paths * 100]);
+        modes = reinterpret_cast<DISPLAYCONFIG_MODE_INFO *>(new
char[num_modes * 100]);
</pre></blockquote><pre>why not

paths = new DISPLAYCONFIG_PATH_INFO[num_paths];
modes = new DISPLAYCONFIG_MODE_INFO[num_modes];</pre></blockquote></blockquote><div><br></div><div>once defined the types you could also use<br></div><div><br></div><div>std::vector<DISPLAYCONFIG_PATH_INFO>
            paths(num_paths);<br></div><div>std::vector<DISPLAYCONFIG_MODE_INFO>
            modes(num_modes);</div><div><br></div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
            This is to avoid having to fully define both
            DISPLAYCONFIG_PATH_INFO and DISPLAYCONFIG_MODE_INFO structs.
            The definition is quite long, and I am not using any of
            their members. Just filling two buffers with
            query_display_config and passing them to set_display_config.
            But if you think it is cleaner to include the full
            definition, I can do so in the next version of the patch.<br><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>+        status = ccd.query_display_config(&num_paths, paths, &num_modes,
modes);</pre></blockquote></blockquote></blockquote><div><br></div><div>Here you would use paths.front()<br></div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><blockquote><pre>+        if (NT_SUCCESS(status)) {
+            ccd.set_display_config(num_paths, paths, num_modes, modes,
+                                   SDC_APPLY |
+                                   SDC_USE_SUPPLIED_DISPLAY_CONFIG |
+                                   SDC_FORCE_MODE_ENUMERATION);
+        }
+        delete[] reinterpret_cast<char *>(paths);
+        delete[] reinterpret_cast<char *>(modes);
</pre></blockquote><pre>and here

delete[] paths;
delete[] modes;</pre></blockquote></blockquote><div><br></div><div>And here nothing!<br></div><div><br></div><div>Frediano<br></div><blockquote style="border-left:2px solid
#1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
            Same here<br><blockquote cite="mid:177889165.22023362.1455118399478.JavaMail.zimbra@redhat.com"><pre>Frediano

</pre><blockquote><pre>+    }
+}
+
 bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode,
 DisplayMode* mode,
                                   LONG normal_x, LONG normal_y, bool
                                   set_pos)
 {
@@ -384,7 +448,9 @@ bool DesktopLayout::init_dev_mode(LPCTSTR dev_name,
DEVMODE* dev_mode, DisplayMo
             vd_printf("escape xres = %d, yres = %d, bpp = %d", custom.xres,
             custom.yres, custom.bpp);
             NTSTATUS status = d3dkmt.escape_driver_private(adapter, &custom,
                                                            sizeof(QXLEscapeSetCustomDisplay));
-            if (!NT_SUCCESS(status)) {
+            if (NT_SUCCESS(status)) {
+                update_display_modes();
+            } else {
                 vd_printf("escape failed with error 0x%08X", status);
             }
         }
</pre></blockquote></blockquote><br><div class="moz-signature">-- <br><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><br><br></p><table class="mceItemTable" style=" margin-top:0px;
                margin-bottom:0px; margin-left:0px; margin-right:0px;" width="480" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td style=" vertical-align:top; padding-right:10;"><p style=" margin-top:0px; margin-bottom:0px;
                        margin-left:0px; margin-right:0px;
                        -qt-block-indent:0; text-indent:0px;
                        -qt-user-state:0;"><a href="http://flexvdi.com" target="_blank"><img src="cid:part1.01080800.09090603@flexvdi.com" style="vertical-align:
                            top;" height="45" width="151"></a><a href="http://flexvdi.com" target="_blank"><span style=" font-family:'Lato,Arial';
                            text-decoration: underline; color:#0057ae;">
                          </span></a><br></p><p style=" margin-top:0px; margin-bottom:0px;
                        margin-left:0px; margin-right:0px;
                        -qt-block-indent:0; text-indent:0px;
                        -qt-user-state:0;"><span style="
                          font-family:'Lato,Arial'; font-size:15px;
                          font-weight:600; color:#3e5d6b;">Javier Celaya
                        </span></p><p style=" margin-top:0px; margin-bottom:0px;
                        margin-left:0px; margin-right:0px;
                        -qt-block-indent:0; text-indent:0px;
                        -qt-user-state:0;"><span style="
                          font-family:'Lato,Arial'; font-size:13px;
                          font-style:italic; color:#00a1c1;">Software
                          Engineer </span></p></td><td style=" padding-left:18; padding-right:18;
                      padding-top:7; padding-bottom:7;"><p style=" margin-top:0px; margin-bottom:0px;
                        margin-left:0px; margin-right:0px;
                        -qt-block-indent:0; text-indent:0px;
                        -qt-user-state:0;"><img src="cid:part4.03070400.03050502@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><a href="mailto:javier.celaya@flexvdi.com" target="_blank"><span style="
                            font-family:'Lato,Arial'; font-size:14px;
                            text-decoration: underline; color:#727272;">j</span></a><span style=" font-family:'Lato,Arial';
                          font-size:14px; text-decoration: underline;
                          color:#727272;"><a class="moz-txt-link-abbreviated" href="mailto:avier.celaya@flexvdi.com" target="_blank">avier.celaya@flexvdi.com</a></span><span style=" font-family:'Lato,Arial';"> </span></p><p style=" margin-top:0px; margin-bottom:0px;
                        margin-left:0px; margin-right:0px;
                        -qt-block-indent:0; text-indent:0px;
                        -qt-user-state:0;"><img src="cid:part7.08090700.07030808@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><span style=" font-family:'Lato,Arial';
                          font-size:14px; color:#727272;">+</span><span style=" font-family:'Lato,Arial';
                          font-size:14px; color:#727272;">34 876 60 00
                          73</span></p><p style=" margin-top:0px; margin-bottom:0px;
                        margin-left:0px; margin-right:0px;
                        -qt-block-indent:0; text-indent:0px;
                        -qt-user-state:0;"><img src="cid:part8.07090407.00060207@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><span style=" font-family:'Lato,Arial';
                          font-size:14px; color:#727272;">@</span><span style=" font-family:'Lato,Arial';
                          font-size:14px; color:#727272;">j_celaya</span><span style=" font-family:'Lato,Arial';"> </span></p></td></tr></tbody></table></div></blockquote><div><br></div></div></blockquote><br><div class="moz-signature">-- <br><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px;
          margin-right:0px; -qt-block-indent:0; text-indent:0px;
          -qt-user-state:0;"><br><br></p><table class="mceItemTable" style=" margin-top:0px; margin-bottom:0px;
          margin-left:0px; margin-right:0px;" width="480" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td style=" vertical-align:top; padding-right:10;"><p style=" margin-top:0px; margin-bottom:0px;
                  margin-left:0px; margin-right:0px; -qt-block-indent:0;
                  text-indent:0px; -qt-user-state:0;"><a href="http://flexvdi.com" target="_blank"><img src="cid:part9.08020005.04000902@flexvdi.com" style="vertical-align: top;" height="45" width="151"></a><a href="http://flexvdi.com" target="_blank"><span style="
                      font-family:'Lato,Arial'; text-decoration:
                      underline; color:#0057ae;"> </span></a><br data-mce-bogus="1"></p><p style=" margin-top:0px; margin-bottom:0px;
                  margin-left:0px; margin-right:0px; -qt-block-indent:0;
                  text-indent:0px; -qt-user-state:0;"><span style="
                    font-family:'Lato,Arial'; font-size:15px;
                    font-weight:600; color:#3e5d6b;">Javier Celaya </span></p><p style=" margin-top:0px; margin-bottom:0px;
                  margin-left:0px; margin-right:0px; -qt-block-indent:0;
                  text-indent:0px; -qt-user-state:0;"><span style="
                    font-family:'Lato,Arial'; font-size:13px;
                    font-style:italic; color:#00a1c1;">Software Engineer
                  </span></p></td><td style=" padding-left:18; padding-right:18;
                padding-top:7; padding-bottom:7;"><p style=" margin-top:0px; margin-bottom:0px;
                  margin-left:0px; margin-right:0px; -qt-block-indent:0;
                  text-indent:0px; -qt-user-state:0;"><img src="cid:part12.02020300.05090605@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><a href="mailto:javier.celaya@flexvdi.com" target="_blank"><span style=" font-family:'Lato,Arial'; font-size:14px;
                      text-decoration: underline; color:#727272;">j</span></a><span style=" font-family:'Lato,Arial'; font-size:14px;
                    text-decoration: underline; color:#727272;"><a class="moz-txt-link-abbreviated" href="mailto:avier.celaya@flexvdi.com" target="_blank">avier.celaya@flexvdi.com</a></span><span style=" font-family:'Lato,Arial';"> </span></p><p style=" margin-top:0px; margin-bottom:0px;
                  margin-left:0px; margin-right:0px; -qt-block-indent:0;
                  text-indent:0px; -qt-user-state:0;"><img src="cid:part16.04040800.09030903@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><span style="
                    font-family:'Lato,Arial'; font-size:14px;
                    color:#727272;">+</span><span style="
                    font-family:'Lato,Arial'; font-size:14px;
                    color:#727272;">34 876 60 00 73</span></p><p style=" margin-top:0px; margin-bottom:0px;
                  margin-left:0px; margin-right:0px; -qt-block-indent:0;
                  text-indent:0px; -qt-user-state:0;"><img src="cid:part18.02040604.00080100@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><span style="
                    font-family:'Lato,Arial'; font-size:14px;
                    color:#727272;">@</span><span style="
                    font-family:'Lato,Arial'; font-size:14px;
                    color:#727272;">j_celaya</span><span style="
                    font-family:'Lato,Arial';"> </span></p></td></tr></tbody></table></div></blockquote><br><div class="moz-signature">-- <br><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px;
        margin-right:0px; -qt-block-indent:0; text-indent:0px;
        -qt-user-state:0;"><br><br></p><table class="mceItemTable" style=" margin-top:0px; margin-bottom:0px; margin-left:0px;
        margin-right:0px;" width="480" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td style=" vertical-align:top; padding-right:10;"><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><a href="http://flexvdi.com" target="_blank"><img src="cid:part20.05040301.08080406@flexvdi.com" style="vertical-align: top;" height="45" width="151"></a><a href="http://flexvdi.com" target="_blank"><span style="
                    font-family:'Lato,Arial'; text-decoration:
                    underline; color:#0057ae;"> </span></a><br data-mce-bogus="1"></p><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><span style="
                  font-family:'Lato,Arial'; font-size:15px;
                  font-weight:600; color:#3e5d6b;">Javier Celaya </span></p><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><span style="
                  font-family:'Lato,Arial'; font-size:13px;
                  font-style:italic; color:#00a1c1;">Software Engineer </span></p></td><td style=" padding-left:18; padding-right:18;
              padding-top:7; padding-bottom:7;"><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><img src="cid:part23.03030702.00030801@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><a href="mailto:javier.celaya@flexvdi.com" target="_blank"><span style="
                    font-family:'Lato,Arial'; font-size:14px;
                    text-decoration: underline; color:#727272;">j</span></a><span style=" font-family:'Lato,Arial'; font-size:14px;
                  text-decoration: underline; color:#727272;"><a class="moz-txt-link-abbreviated" href="mailto:avier.celaya@flexvdi.com" target="_blank">avier.celaya@flexvdi.com</a></span><span style=" font-family:'Lato,Arial';"> </span></p><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><img src="cid:part26.00050306.04070707@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><span style="
                  font-family:'Lato,Arial'; font-size:14px;
                  color:#727272;">+</span><span style="
                  font-family:'Lato,Arial'; font-size:14px;
                  color:#727272;">34 876 60 00 73</span></p><p style=" margin-top:0px; margin-bottom:0px;
                margin-left:0px; margin-right:0px; -qt-block-indent:0;
                text-indent:0px; -qt-user-state:0;"><img src="cid:part28.00040305.00050304@flexvdi.com" style="float: left;" height="17" width="17"><span style=" font-family:'Lato,Arial';"> </span><span style="
                  font-family:'Lato,Arial'; font-size:14px;
                  color:#727272;">@</span><span style="
                  font-family:'Lato,Arial'; font-size:14px;
                  color:#727272;">j_celaya</span><span style="
                  font-family:'Lato,Arial';"> </span></p></td></tr></tbody></table></div></blockquote><div><br></div></div></body></html>