From 3f2309a760073c9fc28e298f217f23424be78978 Mon Sep 17 00:00:00 2001
From: KO Myung-Hun <komh@chollian.net>
Date: Sun, 12 May 2013 17:33:29 +0900
Subject: [PATCH] skins2: add OS/2 support

---
 configure.ac                              |    3 +
 extras/package/os2/configure.sh           |    2 +-
 modules/gui/skins2/Modules.am             |   21 ++
 modules/gui/skins2/os2/os2_dragdrop.cpp   |   40 +++
 modules/gui/skins2/os2/os2_dragdrop.hpp   |   50 ++++
 modules/gui/skins2/os2/os2_factory.cpp    |  457 +++++++++++++++++++++++++++++
 modules/gui/skins2/os2/os2_factory.hpp    |  158 ++++++++++
 modules/gui/skins2/os2/os2_graphics.cpp   |  453 ++++++++++++++++++++++++++++
 modules/gui/skins2/os2/os2_graphics.hpp   |  140 +++++++++
 modules/gui/skins2/os2/os2_loop.cpp       |  299 +++++++++++++++++++
 modules/gui/skins2/os2/os2_loop.hpp       |   68 +++++
 modules/gui/skins2/os2/os2_popup.cpp      |  129 ++++++++
 modules/gui/skins2/os2/os2_popup.hpp      |   69 +++++
 modules/gui/skins2/os2/os2_timer.cpp      |  102 +++++++
 modules/gui/skins2/os2/os2_timer.hpp      |   68 +++++
 modules/gui/skins2/os2/os2_tooltip.cpp    |   92 ++++++
 modules/gui/skins2/os2/os2_tooltip.hpp    |   54 ++++
 modules/gui/skins2/os2/os2_window.cpp     |  237 +++++++++++++++
 modules/gui/skins2/os2/os2_window.hpp     |   90 ++++++
 modules/gui/skins2/parser/builder.cpp     |    2 +-
 modules/gui/skins2/src/os_factory.cpp     |    4 +
 modules/gui/skins2/src/skin_main.cpp      |    2 +-
 modules/gui/skins2/src/vout_manager.hpp   |    2 +-
 modules/gui/skins2/src/window_manager.cpp |    6 +-
 24 files changed, 2541 insertions(+), 7 deletions(-)
 create mode 100644 modules/gui/skins2/os2/os2_dragdrop.cpp
 create mode 100644 modules/gui/skins2/os2/os2_dragdrop.hpp
 create mode 100644 modules/gui/skins2/os2/os2_factory.cpp
 create mode 100644 modules/gui/skins2/os2/os2_factory.hpp
 create mode 100644 modules/gui/skins2/os2/os2_graphics.cpp
 create mode 100644 modules/gui/skins2/os2/os2_graphics.hpp
 create mode 100644 modules/gui/skins2/os2/os2_loop.cpp
 create mode 100644 modules/gui/skins2/os2/os2_loop.hpp
 create mode 100644 modules/gui/skins2/os2/os2_popup.cpp
 create mode 100644 modules/gui/skins2/os2/os2_popup.hpp
 create mode 100644 modules/gui/skins2/os2/os2_timer.cpp
 create mode 100644 modules/gui/skins2/os2/os2_timer.hpp
 create mode 100644 modules/gui/skins2/os2/os2_tooltip.cpp
 create mode 100644 modules/gui/skins2/os2/os2_tooltip.hpp
 create mode 100644 modules/gui/skins2/os2/os2_window.cpp
 create mode 100644 modules/gui/skins2/os2/os2_window.hpp

diff --git a/configure.ac b/configure.ac
index 567b01a..90720fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3755,6 +3755,9 @@ AS_IF([test "${enable_skins2}" != "no"], [
   ], [test "${SYS}" = "darwin"], [
     VLC_ADD_CPPFLAGS([skins2],[ -DMACOSX_SKINS])
     VLC_ADD_LIBS([skins2],[-Wl,-framework,Carbon])
+  dnl OS/2
+  ], [test "${SYS}" = "os2"], [
+    VLC_ADD_CPPFLAGS([skins2],[ -DOS2_SKINS])
   dnl Linux/Unix
   ], [
     PKG_CHECK_MODULES([XPM], [xpm],, [have_skins_deps="no"])
diff --git a/extras/package/os2/configure.sh b/extras/package/os2/configure.sh
index c7c742f..7b17cfa 100644
--- a/extras/package/os2/configure.sh
+++ b/extras/package/os2/configure.sh
@@ -36,7 +36,7 @@ OPTIONS="
       --enable-kva
       --enable-kai
       --enable-qt
-      --disable-skins2
+      --enable-skins2
       --enable-libxml2
       --enable-libgcrypt
       --enable-vlc
diff --git a/modules/gui/skins2/Modules.am b/modules/gui/skins2/Modules.am
index eb1b61d..a962ab2 100644
--- a/modules/gui/skins2/Modules.am
+++ b/modules/gui/skins2/Modules.am
@@ -235,6 +235,26 @@ SOURCES_skins2 += \
 	macosx/macosx_tooltip.hpp \
     $(NULL)
 else
+if HAVE_OS2
+SOURCES_skins2 += \
+	os2/os2_dragdrop.cpp \
+	os2/os2_dragdrop.hpp \
+	os2/os2_factory.cpp \
+	os2/os2_factory.hpp \
+	os2/os2_graphics.cpp \
+	os2/os2_graphics.hpp \
+	os2/os2_loop.cpp \
+	os2/os2_loop.hpp \
+	os2/os2_popup.cpp \
+	os2/os2_popup.hpp \
+	os2/os2_timer.cpp \
+	os2/os2_timer.hpp \
+	os2/os2_tooltip.cpp \
+	os2/os2_tooltip.hpp \
+	os2/os2_window.cpp \
+	os2/os2_window.hpp \
+    $(NULL)
+else
 SOURCES_skins2 += \
 	x11/x11_display.cpp \
 	x11/x11_display.hpp \
@@ -257,3 +277,4 @@ SOURCES_skins2 += \
     $(NULL)
 endif
 endif
+endif
diff --git a/modules/gui/skins2/os2/os2_dragdrop.cpp b/modules/gui/skins2/os2/os2_dragdrop.cpp
new file mode 100644
index 0000000..8232242
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_dragdrop.cpp
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * os2_dragdrop.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "os2/os2_dragdrop.hpp"
+#include "../commands/cmd_add_item.hpp"
+#include "../events/evt_dragndrop.hpp"
+#include <list>
+
+
+OS2DragDrop::OS2DragDrop( intf_thread_t *pIntf,
+                              bool playOnDrop, GenericWindow* pWin )
+    : SkinObject( pIntf ), m_playOnDrop( playOnDrop ), m_pWin( pWin)
+{
+}
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_dragdrop.hpp b/modules/gui/skins2/os2/os2_dragdrop.hpp
new file mode 100644
index 0000000..3e70d03
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_dragdrop.hpp
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ * os2_dragdrop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_DRAGDROP_HPP
+#define OS2_DRAGDROP_HPP
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "../src/skin_common.hpp"
+#include "../src/generic_window.hpp"
+
+
+class OS2DragDrop: public SkinObject
+{
+public:
+   OS2DragDrop( intf_thread_t *pIntf, bool playOnDrop, GenericWindow* pWin );
+   virtual ~OS2DragDrop() { }
+
+private:
+    /// Indicates whether the file(s) must be played immediately
+    bool m_playOnDrop;
+    ///
+    GenericWindow* m_pWin;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_factory.cpp b/modules/gui/skins2/os2/os2_factory.cpp
new file mode 100644
index 0000000..61170eb
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_factory.cpp
@@ -0,0 +1,457 @@
+/*****************************************************************************
+ * os2_factory.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "os2_factory.hpp"
+#include "os2_graphics.hpp"
+#include "os2_timer.hpp"
+#include "os2_window.hpp"
+#include "os2_tooltip.hpp"
+#include "os2_popup.hpp"
+#include "os2_loop.hpp"
+#include "../src/theme.hpp"
+#include "../src/window_manager.hpp"
+#include "../src/generic_window.hpp"
+#include "../commands/cmd_dialogs.hpp"
+#include "../commands/cmd_minimize.hpp"
+
+
+static void MorphToPM( void )
+{
+    PPIB pib;
+    PTIB tib;
+
+    DosGetInfoBlocks(&tib, &pib);
+
+    // Change flag from VIO to PM
+    if (pib->pib_ultype==2) pib->pib_ultype = 3;
+}
+
+
+MRESULT EXPENTRY OS2Factory::OS2FrameProc( HWND hwnd, ULONG msg,
+                                           MPARAM mp1, MPARAM mp2 )
+{
+    // Get pointer to thread info: should only work with the parent window
+    intf_thread_t *p_intf = (intf_thread_t *)WinQueryWindowPtr( hwnd, 0 );
+
+    OS2Factory *pFactory = (OS2Factory*)OS2Factory::instance( p_intf );
+
+    if( msg == WM_ADJUSTWINDOWPOS )
+    {
+        PSWP pswp = ( PSWP )PVOIDFROMMP( mp1 );
+        if( pswp->fl & ( SWP_MINIMIZE | SWP_RESTORE ))
+        {
+            // propagate to all the owned windows
+            HENUM henum = WinBeginEnumWindows( HWND_DESKTOP );
+            HWND  hwndNext;
+            while(( hwndNext = WinGetNextWindow( henum )) != NULLHANDLE )
+            {
+                if( WinQueryWindow( hwndNext, QW_OWNER ) ==
+                        pFactory->m_hParentClientWindow )
+                    WinSetWindowPos( hwndNext, 0, 0, 0, 0, 0,
+                                     pswp->fl &
+                                         ( SWP_MINIMIZE | SWP_RESTORE ));
+            }
+        }
+    }
+    else if( msg == WM_SYSCOMMAND )
+    {
+        // If closing parent window
+        if( SHORT1FROMMP(mp1) == SC_CLOSE )
+        {
+            libvlc_Quit( p_intf->p_libvlc );
+
+            return 0;
+        }
+        else if( SHORT1FROMMP(mp1) == SC_MINIMIZE )
+        {
+            pFactory->minimize();
+
+            return 0;
+        }
+        else if( SHORT1FROMMP(mp1) == SC_RESTORE )
+        {
+            pFactory->restore();
+
+            return 0;
+        }
+        else
+        {
+            msg_Dbg( p_intf, "WM_SYSCOMMAND %i", (SHORT1FROMMP(mp1)));
+        }
+    }
+
+    return pFactory->m_pfnwpOldFrameProc( hwnd, msg, mp1, mp2 );
+}
+
+MRESULT EXPENTRY OS2Factory::OS2Proc( HWND hwnd, ULONG msg,
+                                      MPARAM mp1, MPARAM mp2 )
+{
+    // Get pointer to thread info: should only work with the parent window
+    intf_thread_t *p_intf = (intf_thread_t *)WinQueryWindowPtr( hwnd, 0 );
+
+    // If doesn't exist, treat windows message normally
+    if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
+    {
+        return WinDefWindowProc( hwnd, msg, mp1, mp2 );
+    }
+
+    OS2Factory *pFactory = (OS2Factory*)OS2Factory::instance( p_intf );
+    GenericWindow *pWin = pFactory->m_windowMap[hwnd];
+
+    // Subclass a frame window
+    if( !pFactory->m_pfnwpOldFrameProc )
+    {
+        // Store with it a pointer to the interface thread
+        WinSetWindowPtr( pFactory->m_hParentWindow, 0, p_intf );
+
+        pFactory->m_pfnwpOldFrameProc =
+            WinSubclassWindow( pFactory->m_hParentWindow, OS2FrameProc );
+    }
+
+    if( hwnd != pFactory->getParentWindow() && pWin )
+    {
+        OS2Loop* pLoop =
+            (OS2Loop*) OSFactory::instance( p_intf )->getOSLoop();
+        if( pLoop )
+            return pLoop->processEvent( hwnd, msg, mp1, mp2 );
+    }
+
+    // If hwnd does not match any window or message not processed
+    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
+}
+
+
+OS2Factory::OS2Factory( intf_thread_t *pIntf ):
+    OSFactory( pIntf ), m_hParentWindow( 0 ),
+    m_pfnwpOldFrameProc( 0 ), m_dirSep( "\\" )
+{
+    // see init()
+}
+
+
+bool OS2Factory::init()
+{
+    PCSZ vlc_name = "VLC Media Player";
+    PCSZ vlc_icon = "VLC_ICON";
+    PCSZ vlc_class = "SkinWindowClass";
+
+    MorphToPM();
+
+    m_hab = WinInitialize( 0 );
+    m_hmq = WinCreateMsgQueue( m_hab, 0 );
+
+    if( !WinRegisterClass( m_hab, vlc_class, OS2Factory::OS2Proc,
+                           CS_SIZEREDRAW, sizeof( PVOID )))
+    {
+        msg_Err( getIntf(), "cannot register window class" );
+        return false;
+    }
+
+    ULONG flFrame = FCF_SYSMENU | FCF_MINBUTTON | FCF_TASKLIST
+                    /* | FCF_ICON */;
+
+    m_hParentWindow = WinCreateStdWindow( HWND_DESKTOP,
+                                          0,
+                                          &flFrame,
+                                          vlc_class,
+                                          vlc_name,
+                                          0,
+                                          NULLHANDLE,
+                                          0/* ID_VLC_ICON */,
+                                          &m_hParentClientWindow );
+
+    if( !m_hParentWindow )
+    {
+        msg_Err( getIntf(), "cannot create parent window" );
+        return false;
+    }
+
+    // Store with it a pointer to the interface thread
+    WinSetWindowPtr( m_hParentClientWindow, 0, getIntf());
+
+    WinSetWindowPos( m_hParentWindow, HWND_TOP, 0, 0, 0, 0,
+                     SWP_ACTIVATE | SWP_ZORDER | SWP_MOVE | SWP_SIZE |
+                     SWP_SHOW );
+
+    // Set the mouse pointer to a default arrow
+    changeCursor( kDefaultArrow );
+
+    // Initialize the resource path
+    char *datadir = config_GetUserDir( VLC_DATA_DIR );
+    m_resourcePath.push_back( (string)datadir + "\\skins" );
+    free( datadir );
+    datadir = config_GetDataDir();
+    m_resourcePath.push_back( (string)datadir + "\\skins" );
+    m_resourcePath.push_back( (string)datadir + "\\skins2" );
+    m_resourcePath.push_back( (string)datadir + "\\share\\skins" );
+    m_resourcePath.push_back( (string)datadir + "\\share\\skins2" );
+    m_resourcePath.push_back( (string)datadir + "\\vlc\\skins" );
+    m_resourcePath.push_back( (string)datadir + "\\vlc\\skins2" );
+    free( datadir );
+
+    // All went well
+    return true;
+}
+
+
+OS2Factory::~OS2Factory()
+{
+    if( m_hParentWindow ) WinDestroyWindow( m_hParentWindow );
+
+    WinDestroyMsgQueue( m_hmq );
+    WinTerminate( m_hab );
+}
+
+
+OSGraphics *OS2Factory::createOSGraphics( int width, int height )
+{
+    return new OS2Graphics( getIntf(), width, height );
+}
+
+
+OSLoop *OS2Factory::getOSLoop()
+{
+    return OS2Loop::instance( getIntf() );
+}
+
+
+void OS2Factory::destroyOSLoop()
+{
+    OS2Loop::destroy( getIntf() );
+}
+
+void OS2Factory::minimize()
+{
+    /* Make sure no tooltip is visible first */
+    getIntf()->p_sys->p_theme->getWindowManager().hideTooltip();
+
+    WinSetWindowPos( m_hParentWindow, NULLHANDLE, 0, 0, 0, 0, SWP_MINIMIZE );
+}
+
+void OS2Factory::restore()
+{
+    WinSetWindowPos( m_hParentWindow, NULLHANDLE, 0, 0, 0, 0, SWP_RESTORE );
+}
+
+void OS2Factory::addInTray()
+{
+    // TODO
+}
+
+void OS2Factory::removeFromTray()
+{
+    // TODO
+}
+
+void OS2Factory::addInTaskBar()
+{
+    WinSetWindowPos( m_hParentWindow, NULLHANDLE, 0, 0, 0, 0, SWP_HIDE );
+
+    HSWITCH hswitch = WinQuerySwitchHandle( m_hParentWindow, 0 );
+
+    SWCNTRL swctl;
+    WinQuerySwitchEntry( hswitch, &swctl );
+    swctl.uchVisibility = SWL_VISIBLE;
+    WinChangeSwitchEntry( hswitch, &swctl );
+
+    WinSetWindowPos( m_hParentWindow, NULLHANDLE, 0, 0, 0, 0,
+                     SWP_ACTIVATE | SWP_SHOW );
+}
+
+void OS2Factory::removeFromTaskBar()
+{
+    WinSetWindowPos( m_hParentWindow, NULLHANDLE, 0, 0, 0, 0, SWP_HIDE );
+
+    HSWITCH hswitch = WinQuerySwitchHandle( m_hParentWindow, 0 );
+
+    SWCNTRL swctl;
+    WinQuerySwitchEntry( hswitch, &swctl );
+    swctl.uchVisibility = SWL_INVISIBLE;
+    WinChangeSwitchEntry( hswitch, &swctl );
+
+    WinSetWindowPos( m_hParentWindow, NULLHANDLE, 0, 0, 0, 0,
+                     SWP_ACTIVATE | SWP_SHOW );
+}
+
+OSTimer *OS2Factory::createOSTimer( CmdGeneric &rCmd )
+{
+    return new OS2Timer( getIntf(), rCmd, m_hParentClientWindow );
+}
+
+
+OSWindow *OS2Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
+                                      bool playOnDrop, OSWindow *pParent,
+                                      GenericWindow::WindowType_t type )
+{
+    return new OS2Window( getIntf(), rWindow, m_hInst, m_hParentClientWindow,
+                          dragDrop, playOnDrop, (OS2Window*)pParent, type );
+}
+
+
+OSTooltip *OS2Factory::createOSTooltip()
+{
+    return new OS2Tooltip( getIntf(), m_hInst, m_hParentClientWindow );
+}
+
+
+OSPopup *OS2Factory::createOSPopup()
+{
+    // XXX FIXME: this way of getting the handle really sucks!
+    // In fact, the clean way would be to have in Builder::addPopup() a call
+    // to pPopup->associateToWindow() (to be written)... but the problem is
+    // that there is no way to access the OS-dependent window handle from a
+    // GenericWindow (we cannot even access the OSWindow).
+    if( m_windowMap.begin() == m_windowMap.end() )
+    {
+        msg_Err( getIntf(), "no window has been created before the popup!" );
+        return NULL;
+    }
+
+    return new OS2Popup( getIntf(), m_windowMap.begin()->first );
+}
+
+
+int OS2Factory::getScreenWidth() const
+{
+    return WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
+}
+
+
+int OS2Factory::getScreenHeight() const
+{
+    return WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
+}
+
+
+void OS2Factory::getMonitorInfo( const GenericWindow &rWindow,
+                                 int* p_x, int* p_y,
+                                 int* p_width, int* p_height ) const
+{
+    *p_x = 0;
+    *p_y = 0;
+    *p_width = getScreenWidth();
+    *p_height = getScreenHeight();
+}
+
+
+void OS2Factory::getMonitorInfo( int numScreen, int* p_x, int* p_y,
+                                   int* p_width, int* p_height ) const
+{
+    *p_x = 0;
+    *p_y = 0;
+    *p_width = getScreenWidth();
+    *p_height = getScreenHeight();
+}
+
+
+SkinsRect OS2Factory::getWorkArea() const
+{
+    // TODO : calculate Desktop Workarea excluding WarpCenter
+
+    // Fill a Rect object
+    return  SkinsRect( 0, 0, getScreenWidth(), getScreenHeight());
+}
+
+
+void OS2Factory::getMousePos( int &rXPos, int &rYPos ) const
+{
+    POINTL ptl;
+
+    WinQueryPointerPos( HWND_DESKTOP, &ptl );
+
+    rXPos = ptl.x;
+    rYPos = ( getScreenHeight() - 1 ) - ptl.y;   // Invert Y
+}
+
+
+void OS2Factory::changeCursor( CursorType_t type ) const
+{
+    LONG id;
+    switch( type )
+    {
+    default:
+    case kDefaultArrow: id = SPTR_ARROW;    break;
+    case kResizeNWSE:   id = SPTR_SIZENWSE; break;
+    case kResizeNS:     id = SPTR_SIZENS;   break;
+    case kResizeWE:     id = SPTR_SIZEWE;   break;
+    case kResizeNESW:   id = SPTR_SIZENESW; break;
+    }
+
+    HPOINTER hptr = WinQuerySysPointer( HWND_DESKTOP, id, FALSE );
+    WinSetPointer( HWND_DESKTOP, hptr );
+
+    m_cursorType = type;
+}
+
+
+void OS2Factory::rmDir( const string &rPath )
+{
+    struct dirent *file;
+    DIR *dir;
+
+    dir = opendir( rPath.c_str() );
+    if( !dir ) return;
+
+    // Parse the directory and remove everything it contains
+    while( (file = readdir( dir )) )
+    {
+        struct stat statbuf;
+        string filename = file->d_name;
+
+        // Skip "." and ".."
+        if( filename == "." || filename == ".." )
+        {
+            continue;
+        }
+
+        filename = rPath + "\\" + filename;
+
+        if( !stat( filename.c_str(), &statbuf ) && statbuf.st_mode & S_IFDIR )
+        {
+            rmDir( filename );
+        }
+        else
+        {
+            unlink( filename.c_str() );
+        }
+    }
+
+    // Close the directory
+    closedir( dir );
+
+    // And delete it
+    rmdir( rPath.c_str() );
+}
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_factory.hpp b/modules/gui/skins2/os2/os2_factory.hpp
new file mode 100644
index 0000000..e125504
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_factory.hpp
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ * os2_factory.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_FACTORY_HPP
+#define OS2_FACTORY_HPP
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "../src/os_factory.hpp"
+#include "../src/generic_window.hpp"
+
+#include <map>
+
+
+/// Class used to instanciate OS2 specific objects
+class OS2Factory: public OSFactory
+{
+public:
+    OS2Factory( intf_thread_t *pIntf );
+    virtual ~OS2Factory();
+
+    /// Initialization method
+    virtual bool init();
+
+    /// Instantiate an object OSGraphics
+    virtual OSGraphics *createOSGraphics( int width, int height );
+
+    /// Get the instance of the singleton OSLoop
+    virtual OSLoop *getOSLoop();
+
+    /// Destroy the instance of OSLoop
+    virtual void destroyOSLoop();
+
+    /// Minimize all the windows
+    virtual void minimize();
+
+    /// Restore the minimized windows
+    virtual void restore();
+
+    /// Add an icon in the system tray
+    virtual void addInTray();
+
+    /// Remove the icon from the system tray
+    virtual void removeFromTray();
+
+    /// Show the task in the task bar
+    virtual void addInTaskBar();
+
+    /// Remove the task from the task bar
+    virtual void removeFromTaskBar();
+
+    /// Instantiate an OSTimer with the given command
+    virtual OSTimer *createOSTimer( CmdGeneric &rCmd );
+
+    /// Instantiate an OSWindow object
+    virtual OSWindow *createOSWindow( GenericWindow &rWindow,
+                                      bool dragDrop, bool playOnDrop,
+                                      OSWindow *pParent,
+                                      GenericWindow::WindowType_t type );
+
+    /// Instantiate an object OSTooltip
+    virtual OSTooltip *createOSTooltip();
+
+    /// Instantiate an object OSPopup
+    virtual OSPopup *createOSPopup();
+
+    /// Get the directory separator
+    virtual const string &getDirSeparator() const { return m_dirSep; }
+
+    /// Get the resource path
+    virtual const list<string> &getResourcePath() const
+        { return m_resourcePath; }
+
+    /// Get the screen size
+    virtual int getScreenWidth() const;
+    virtual int getScreenHeight() const;
+
+    /// Get Monitor Information
+    virtual void getMonitorInfo( const GenericWindow &rWindow,
+                                 int* x, int* y,
+                                 int* width, int* height ) const;
+    virtual void getMonitorInfo( int numScreen,
+                                 int* x, int* y,
+                                 int* width, int* height ) const;
+
+    /// Get the work area (screen area without taskbars)
+    virtual SkinsRect getWorkArea() const;
+
+    /// Get the position of the mouse
+    virtual void getMousePos( int &rXPos, int &rYPos ) const;
+
+    /// Change the cursor
+    virtual void changeCursor( CursorType_t type ) const;
+
+    /// Delete a directory recursively
+    virtual void rmDir( const string &rPath );
+
+    /// Map to find the GenericWindow associated with a OS2Window
+    map<HWND, GenericWindow*> m_windowMap;
+
+    /// Get the parent window handle
+    HWND getParentWindow() { return m_hParentClientWindow; }
+
+    /// Get the m_cursorType
+    CursorType_t getCursorType() const { return m_cursorType; }
+
+    /// Callback function (Windows Procedure)
+    static MRESULT EXPENTRY OS2FrameProc( HWND hwnd, ULONG msg,
+                                          MPARAM mp1, MPARAM Mp2 );
+    static MRESULT EXPENTRY OS2Proc( HWND hwnd, ULONG msg,
+                                     MPARAM mp1, MPARAM Mp2 );
+
+private:
+    /// Handle of the instance
+    HMODULE m_hInst;
+    /// Handle of anchor-block
+    HAB m_hab;
+    /// Handle of message queue
+    HMQ m_hmq;
+    /// Handle of the parent window
+    HWND m_hParentWindow;
+    /// Handle of the client window of the parent window
+    HWND m_hParentClientWindow;
+    /// Window procedure of the old frame window
+    PFNWP m_pfnwpOldFrameProc;
+    /// Cursor type
+    mutable CursorType_t m_cursorType;
+    /// Directory separator
+    const string m_dirSep;
+    /// Resource path
+    list<string> m_resourcePath;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_graphics.cpp b/modules/gui/skins2/os2/os2_graphics.cpp
new file mode 100644
index 0000000..ece5521
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_graphics.cpp
@@ -0,0 +1,453 @@
+/*****************************************************************************
+ * os2_graphics.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "os2_factory.hpp"
+#include "os2_graphics.hpp"
+#include "os2_window.hpp"
+#include "../src/generic_bitmap.hpp"
+
+// kLIBC does not declare this function
+extern "C" BOOL APIENTRY WinSetClipRegion( HWND, HRGN );
+
+OS2Graphics::OS2Graphics( intf_thread_t *pIntf, int width, int height ):
+    OSGraphics( pIntf ), m_width( width ), m_height( height )
+{
+    m_hdc = DevOpenDC( 0, OD_MEMORY, "*", 0L, NULL, NULLHANDLE );
+
+    SIZEL sizl = { 0, 0 };
+    m_hps = GpiCreatePS( 0, m_hdc, &sizl,
+                         PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
+
+    // Set the color table into RGB mode
+    GpiCreateLogColorTable( m_hps, 0, LCOLF_RGB, 0, 0, NULL );
+
+    BITMAPINFOHEADER bmp;
+    bmp.cbFix     = sizeof( bmp );
+    bmp.cx        = width;
+    bmp.cy        = height;
+    bmp.cPlanes   = 1;
+    bmp.cBitCount = 24;
+
+    m_hbm = GpiCreateBitmap( m_hps, ( PBITMAPINFOHEADER2 )&bmp, 0L,
+                             NULL, NULL);
+
+    GpiSetBitmap( m_hps, m_hbm );
+
+    // Create the mask
+    RECTL rcl = { 0, 0, 0, 0 };
+    m_mask = GpiCreateRegion( m_hps, 1, &rcl );
+}
+
+
+OS2Graphics::~OS2Graphics()
+{
+    GpiDestroyRegion( m_hps, m_mask );
+
+    GpiSetBitmap( m_hps, NULLHANDLE );
+    GpiDeleteBitmap( m_hbm );
+
+    GpiDestroyPS( m_hps );
+
+    DevCloseDC( m_hdc );
+}
+
+
+void OS2Graphics::clear( int xDest, int yDest, int width, int height )
+{
+    if( width <= 0 || height <= 0 )
+    {
+        // Clear the transparency mask
+        GpiDestroyRegion( m_hps, m_mask );
+        RECTL rcl = { 0, 0, 0, 0 };
+        m_mask = GpiCreateRegion( m_hps, 1, &rcl );
+    }
+    else
+    {
+        RECTL rcl = { xDest, invertRectY( yDest + height ),
+                      xDest + width, invertRectY( yDest )};
+        HRGN mask = GpiCreateRegion( m_hps, 1, &rcl );
+        GpiCombineRegion( m_hps, m_mask, m_mask, mask, CRGN_DIFF );
+        GpiDestroyRegion( m_hps, mask );
+    }
+}
+
+
+void OS2Graphics::drawBitmap( const GenericBitmap &rBitmap,
+                              int xSrc, int ySrc, int xDest, int yDest,
+                              int width, int height, bool blend )
+{
+    (void)blend;
+
+    // check and adapt to source if needed
+    if( !checkBoundaries( 0, 0, rBitmap.getWidth(), rBitmap.getHeight(),
+                          xSrc, ySrc, width, height ) )
+    {
+        msg_Err( getIntf(), "empty source! pls, debug your skin" );
+        return;
+    }
+
+    // check destination
+    if( !checkBoundaries( 0, 0, m_width, m_height,
+                          xDest, yDest, width, height ) )
+    {
+        msg_Err( getIntf(), "out of reach destination! pls, debug your skin" );
+        return;
+    }
+
+    // Get a buffer on the image data
+    uint8_t *pBmpData = rBitmap.getData();
+    if( pBmpData == NULL )
+    {
+        // Nothing to draw
+        return;
+    }
+
+    BITMAPINFOHEADER bmp;
+    bmp.cbFix     = sizeof( bmp );
+    bmp.cx        = width;
+    bmp.cy        = height;
+    bmp.cPlanes   = 1;
+    bmp.cBitCount = 24;
+
+    // pointer to bitmap bits
+    uint8_t *pBits = ( uint8_t * )malloc((( bmp.cBitCount * bmp.cx + 31 ) /
+                                         32 ) * bmp.cPlanes * 4 );
+
+    HDC hdc = DevOpenDC( 0, OD_MEMORY, "*", 0L, NULL, NULLHANDLE );
+
+    SIZEL sizl = { 0, 0 };
+    HPS hps = GpiCreatePS( 0, hdc, &sizl,
+                           PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
+
+    HBITMAP hbm = GpiCreateBitmap( hps, ( PBITMAPINFOHEADER2 )&bmp, 0L,
+                                   NULL, NULL);
+
+    GpiSetBitmap( hps, hbm );
+
+    // Mask for transparency
+    RECTL rcl = { 0, 0, 0, 0 };
+    HRGN  mask = GpiCreateRegion( m_hps, 1, &rcl );
+
+    // Skip the first lines of the image
+    pBmpData += 4 * ySrc * rBitmap.getWidth();
+
+    // Copy the bitmap on the image and compute the mask
+    for( int y = 0; y < height; y++ )
+    {
+        // Skip uninteresting bytes at the beginning of the line
+        pBmpData += 4 * xSrc;
+        // Flag to say whether the previous pixel on the line was visible
+        bool wasVisible = false;
+        // Beginning of the current visible segment on the line
+        int visibleSegmentStart = 0;
+        for( int x = 0; x < width; x++ )
+        {
+            uint8_t b = *( pBmpData++ );
+            uint8_t g = *( pBmpData++ );
+            uint8_t r = *( pBmpData++ );
+            uint8_t a = *( pBmpData++ );
+
+            // Draw the pixel
+            pBits[ x * 3     ] = b;
+            pBits[ x * 3 + 1 ] = g;
+            pBits[ x * 3 + 2 ] = r;
+
+            if( a > 0 )
+            {
+                // Pixel is visible
+                if( ! wasVisible )
+                {
+                    // Beginning of a visible segment
+                    visibleSegmentStart = x;
+                }
+                wasVisible = true;
+            }
+            else
+            {
+                // Pixel is transparent
+                if( wasVisible )
+                {
+                    // End of a visible segment: add it to the mask
+                    addSegmentInRegion( mask, visibleSegmentStart, x, y,
+                                        height );
+                }
+                wasVisible = false;
+            }
+        }
+
+        // Transfer bitmap bits to hps
+        GpiSetBitmapBits( hps, invertPointY( y, height ), 1, ( PBYTE )pBits,
+                          ( PBITMAPINFO2 )&bmp );
+
+        if( wasVisible )
+        {
+            // End of a visible segment: add it to the mask
+            addSegmentInRegion( mask, visibleSegmentStart, width, y, height );
+        }
+        // Skip uninteresting bytes at the end of the line
+        pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
+    }
+
+    // Apply the mask to the internal DC
+    POINTL ptl = { xDest, invertRectY( yDest + height )};
+    GpiOffsetRegion( m_hps, mask, &ptl );
+
+    GpiSetClipRegion( m_hps, mask, NULL );
+
+    POINTL aptl[] = {{ xDest, invertRectY( yDest + height )},
+                     { xDest + width, invertRectY( yDest )},
+                     { 0, 0 }};
+    GpiBitBlt( m_hps, hps, 3, aptl, ROP_SRCCOPY, BBO_IGNORE );
+
+    // Release a clip region handle
+    GpiSetClipRegion( m_hps, NULLHANDLE, NULL );
+
+    // Add the bitmap mask to the global graphics mask
+    GpiCombineRegion( m_hps, m_mask, m_mask, mask, CRGN_OR );
+
+    // Do cleanup
+    GpiDestroyRegion( m_hps, mask );
+    GpiSetBitmap( hps, NULLHANDLE );
+    GpiDeleteBitmap( hbm );
+    GpiDestroyPS( hps );
+    DevCloseDC( hdc );
+    free( pBits );
+}
+
+
+void OS2Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
+                                int ySrc, int xDest, int yDest, int width,
+                                int height )
+{
+    // check and adapt to source if needed
+    if( !checkBoundaries( 0, 0, rGraphics.getWidth(), rGraphics.getHeight(),
+                          xSrc, ySrc, width, height ) )
+    {
+        msg_Err( getIntf(), "nothing to draw from graphics source" );
+        return;
+    }
+
+    // check destination
+    if( !checkBoundaries( 0, 0, m_width, m_height,
+                          xDest, yDest, width, height ) )
+    {
+        msg_Err( getIntf(), "out of reach destination! pls, debug your skin" );
+        return;
+    }
+
+    // To invert Y
+    int h = rGraphics.getHeight();
+
+    // Create the mask for transparency
+    RECTL rcl = { xSrc, invertRectY( ySrc + height, h ),
+                  xSrc + width, invertRectY( ySrc, h )};
+    HRGN  mask = GpiCreateRegion( m_hps, 1, &rcl );
+    GpiCombineRegion( m_hps, mask, ((OS2Graphics&)rGraphics).getMask(), mask,
+                      CRGN_AND );
+
+    POINTL ptl = { xDest - xSrc,
+                   invertRectY( yDest + height ) -
+                   invertRectY( ySrc + height, h )};
+    GpiOffsetRegion( m_hps, mask, &ptl );
+
+    // Copy the image
+    HPS hpsSrc = ((OS2Graphics&)rGraphics).getPS();
+
+    GpiSetClipRegion( m_hps, mask, NULL );
+
+    POINTL aptl[] = {{ xDest, invertRectY( yDest + height )},
+                     { xDest + width, invertRectY( yDest )},
+                     { xSrc, invertRectY( ySrc + height, h )}};
+    GpiBitBlt( m_hps, hpsSrc, 3, aptl, ROP_SRCCOPY, BBO_IGNORE );
+
+    // Release a clip region handle
+    GpiSetClipRegion( m_hps, NULLHANDLE, NULL );
+
+    // Add the source mask to the mask of the graphics
+    GpiCombineRegion( m_hps, m_mask, mask, m_mask, CRGN_OR );
+    GpiDestroyRegion( m_hps, mask );
+}
+
+
+void OS2Graphics::fillRect( int left, int top, int width, int height,
+                            uint32_t color )
+{
+    // Update the mask with the rectangle area
+    int bottom = invertRectY( top + height );
+    RECTL rcl = { left, bottom, left + width, bottom + height };
+    HRGN  newMask = GpiCreateRegion( m_hps, 1, &rcl );
+    GpiCombineRegion( m_hps, m_mask, m_mask, newMask, CRGN_OR );
+
+    GpiSetClipRegion( m_hps, m_mask, NULL );
+    GpiDestroyRegion( m_hps, newMask );
+
+    // Draw the rectangle
+    WinSetRect( 0, &rcl, left, bottom, left + width, bottom + height );
+    WinFillRect( m_hps, &rcl, color );
+
+    // Release a clip region handle
+    GpiSetClipRegion( m_hps, NULLHANDLE, NULL );
+}
+
+
+void OS2Graphics::drawRect( int left, int top, int width, int height,
+                            uint32_t color )
+{
+    // Update the mask with the rectangle
+    int bottom = invertRectY( top + height );
+    RECTL rcl = { left, bottom, left + width, bottom + 1 };
+    HRGN  l1 = GpiCreateRegion( m_hps, 1, &rcl );
+
+    WinSetRect( 0, &rcl, left + width - 1, bottom, left + width,
+                bottom + height );
+    HRGN l2 = GpiCreateRegion( m_hps, 1, &rcl );
+
+    WinSetRect( 0, &rcl, left, bottom + height - 1, left + width,
+                bottom + height );
+    HRGN l3 = GpiCreateRegion( m_hps, 1, &rcl );
+
+    WinSetRect( 0, &rcl, left, bottom, left + 1, bottom + height );
+    HRGN l4 = GpiCreateRegion( m_hps, 1, &rcl );
+
+    GpiCombineRegion( m_hps, m_mask, m_mask, l1, CRGN_OR );
+    GpiCombineRegion( m_hps, m_mask, m_mask, l2, CRGN_OR );
+    GpiCombineRegion( m_hps, m_mask, m_mask, l3, CRGN_OR );
+    GpiCombineRegion( m_hps, m_mask, m_mask, l4, CRGN_OR );
+
+    GpiDestroyRegion( m_hps, l1 );
+    GpiDestroyRegion( m_hps, l2 );
+    GpiDestroyRegion( m_hps, l3 );
+    GpiDestroyRegion( m_hps, l4 );
+
+    GpiSetClipRegion( m_hps, m_mask, NULL );
+
+    // Set color
+    GpiSetColor( m_hps, color );
+
+    // Draw the rectangle
+    POINTL ptl = { left, bottom };
+    GpiMove( m_hps, &ptl );
+
+    ptl.x = left + width - 1;
+    ptl.y = bottom;
+    GpiLine( m_hps, &ptl );
+
+    ptl.x = left + width - 1;
+    ptl.y = bottom + height - 1;
+    GpiLine( m_hps, &ptl );
+
+    ptl.x = left;
+    ptl.y = bottom + height - 1;
+    GpiLine( m_hps, &ptl );
+
+    ptl.x = left;
+    ptl.y = bottom;
+    GpiLine( m_hps, &ptl );
+
+    // Release a clip region handle
+    GpiSetClipRegion( m_hps, NULLHANDLE, NULL );
+}
+
+
+void OS2Graphics::applyMaskToWindow( OSWindow &rWindow )
+{
+    // Get window handle
+    HWND hWnd = ((OS2Window&)rWindow).getHandle();
+
+    // Apply the mask
+    RECTL rcl = { 0, 0, 0, 0 };
+    HRGN mask = GpiCreateRegion( m_hps, 1, &rcl );
+    GpiCombineRegion( m_hps, mask, m_mask, NULLHANDLE, CRGN_COPY );
+    //WinSetClipRegion( hWnd, mask );
+    GpiDestroyRegion( m_hps, mask );
+}
+
+
+void OS2Graphics::copyToWindow( OSWindow &rWindow, int xSrc, int ySrc,
+                                int width, int height, int xDest, int yDest )
+{
+    // Initialize painting
+    HWND hWnd = ((OS2Window&)rWindow).getHandle();
+    HPS hpsWnd = WinGetPS( hWnd );
+    HPS hpsSrc = m_hps;
+
+    RECTL rcl;
+    WinQueryWindowRect( hWnd, &rcl );
+
+    // Draw image on window
+    POINTL aptl[] = {{ xDest, invertRectY( yDest + height, rcl.yTop )},
+                     { xDest + width, invertRectY( yDest, rcl.yTop )},
+                     { xSrc, invertRectY( ySrc + height )}};
+    GpiBitBlt( hpsWnd, hpsSrc, 3, aptl, ROP_SRCCOPY, BBO_IGNORE );
+
+    // Release window device context
+    WinReleasePS( hpsWnd );
+}
+
+
+bool OS2Graphics::hit( int x, int y ) const
+{
+    POINTL ptl = { x, invertPointY( y )};
+    return GpiPtInRegion( m_hps, m_mask, &ptl ) == PRGN_INSIDE;
+}
+
+
+void OS2Graphics::addSegmentInRegion( HRGN &rMask, int start,
+                                      int end, int line, int height )
+{
+    RECTL rcl = { start, invertRectY( line + 1, height ),
+                  end, invertRectY( line, height )};
+    HRGN buffer = GpiCreateRegion( m_hps, 1, &rcl );
+    GpiCombineRegion( m_hps, rMask, buffer, rMask, CRGN_OR );
+    GpiDestroyRegion( m_hps, buffer );
+}
+
+
+bool OS2Graphics::checkBoundaries( int x_src, int y_src,
+                                   int w_src, int h_src,
+                                   int& x_target, int& y_target,
+                                   int& w_target, int& h_target )
+{
+    // set valid width and height
+    w_target = (w_target > 0) ? w_target : w_src;
+    h_target = (h_target > 0) ? h_target : h_src;
+
+    // clip source if needed
+    rect srcRegion( x_src, y_src, w_src, h_src );
+    rect targetRegion( x_target, y_target, w_target, h_target );
+    rect inter;
+    if( rect::intersect( srcRegion, targetRegion, &inter ) )
+    {
+        x_target = inter.x;
+        y_target = inter.y;
+        w_target = inter.width;
+        h_target = inter.height;
+        return true;
+    }
+    return false;
+}
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_graphics.hpp b/modules/gui/skins2/os2/os2_graphics.hpp
new file mode 100644
index 0000000..dfe775f
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_graphics.hpp
@@ -0,0 +1,140 @@
+/*****************************************************************************
+ * os2_graphics.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_GRAPHICS_HPP
+#define OS2_GRAPHICS_HPP
+
+#include "../src/os_graphics.hpp"
+
+
+class GenericBitmap;
+
+/// OS2 implementation of OSGraphics
+class OS2Graphics: public OSGraphics
+{
+public:
+    OS2Graphics( intf_thread_t *pIntf, int width, int height );
+    virtual ~OS2Graphics();
+
+    /// Clear the graphics
+    virtual void clear( int xDest = 0, int yDest = 0,
+                        int width = -1, int height = -1 );
+
+    /// Render a bitmap on this graphics
+    virtual void drawBitmap( const GenericBitmap &rBitmap, int xSrc = 0,
+                             int ySrc = 0, int xDest = 0, int yDest = 0,
+                             int width = -1, int height = -1,
+                             bool blend = false );
+
+    /// Draw another graphics on this one
+    virtual void drawGraphics( const OSGraphics &rGraphics, int xSrc = 0,
+                               int ySrc = 0, int xDest = 0, int yDest = 0,
+                               int width = -1, int height = -1 );
+
+    /// Draw an empty rectangle on the grahics (color is #RRGGBB)
+    virtual void drawRect( int left, int top, int width, int height,
+                           uint32_t color );
+
+
+    /// Draw a filled rectangle on the grahics (color is #RRGGBB)
+    virtual void fillRect( int left, int top, int width, int height,
+                           uint32_t color );
+
+    /// Set the shape of a window with the mask of this graphics.
+    virtual void applyMaskToWindow( OSWindow &rWindow );
+
+    /// Copy the graphics on a window
+    virtual void copyToWindow( OSWindow &rWindow, int xSrc,
+                               int ySrc, int width, int height,
+                               int xDest, int yDest );
+
+    /// Tell whether the pixel at the given position is visible
+    virtual bool hit( int x, int y ) const;
+
+    /// Getters for the size
+    virtual int getWidth() const { return m_width; }
+    virtual int getHeight() const { return m_height; }
+
+    /// Get the device context handler
+    virtual HDC getPS() const { return m_hps; }
+
+    /// Get the mask
+    virtual HRGN getMask() const { return m_mask; }
+
+private:
+    /// Size of the image
+    int m_width, m_height;
+
+    /// Device context
+    HDC m_hdc;
+
+    /// Presentaiton space
+    HPS m_hps;
+
+    /// Bitmap handle
+    HBITMAP m_hbm;
+
+    /// Transparency mask
+    HRGN m_mask;
+
+    /// Add a segment in a region
+    void addSegmentInRegion( HRGN &rMask, int start, int end, int line,
+                             int height );
+
+    /// check boundaries for graphics and bitmaps
+    bool checkBoundaries( int x_src, int y_src, int w_src, int h_src,
+                          int& x_target, int& y_target,
+                          int& w_target, int& h_target );
+
+    /// invert Y of a point against the given height
+    int invertPointY( int y, int height ) const
+    {
+        return ( height - 1 ) - y;
+    }
+
+    /// invert Y of a point against the m_height
+    int invertPointY( int y ) const
+    {
+        return ( m_height - 1 ) - y;
+    }
+
+    /// invert Y of a rectangular against the given height
+    int invertRectY( int y, int height ) const
+    {
+        // bottom is inclusive, top is exclusive
+        // the following is the short of ( height - 1 ) - ( y - 1 )
+        return height - y;
+    }
+
+    /// invert Y of a rectangular against the m_height
+    int invertRectY( int y ) const
+    {
+        // bottom is inclusive, top is exclusive
+        // the following is the short of ( m_height - 1 ) - ( y - 1 )
+        return m_height - y;
+    }
+};
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_loop.cpp b/modules/gui/skins2/os2/os2_loop.cpp
new file mode 100644
index 0000000..e1d7462
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_loop.cpp
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ * os2_loop.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "os2_factory.hpp"
+#include "os2_loop.hpp"
+#include "../src/generic_window.hpp"
+#include "../events/evt_key.hpp"
+#include "../events/evt_leave.hpp"
+#include "../events/evt_menu.hpp"
+#include "../events/evt_motion.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_refresh.hpp"
+#include "../events/evt_scroll.hpp"
+#include <vlc_keys.h>
+
+
+#define GET_X_MP( mp ) ( SHORT1FROMMP( mp ))
+#define GET_Y_MP( mp ) (( rcl.yTop - 1 ) - SHORT2FROMMP( mp )) /* Invert Y */
+
+#ifndef WM_MOUSELEAVE
+#define WM_MOUSELEAVE   0x41F
+#endif
+
+OS2Loop::OS2Loop( intf_thread_t *pIntf ): OSLoop( pIntf )
+{
+    // Initialize the map
+    virtKeyToVlcKey[VK_F1] = KEY_F1;
+    virtKeyToVlcKey[VK_F2] = KEY_F2;
+    virtKeyToVlcKey[VK_F3] = KEY_F3;
+    virtKeyToVlcKey[VK_F4] = KEY_F4;
+    virtKeyToVlcKey[VK_F5] = KEY_F5;
+    virtKeyToVlcKey[VK_F6] = KEY_F6;
+    virtKeyToVlcKey[VK_F7] = KEY_F7;
+    virtKeyToVlcKey[VK_F8] = KEY_F8;
+    virtKeyToVlcKey[VK_F9] = KEY_F9;
+    virtKeyToVlcKey[VK_F10] = KEY_F10;
+    virtKeyToVlcKey[VK_F11] = KEY_F11;
+    virtKeyToVlcKey[VK_F12] = KEY_F12;
+    virtKeyToVlcKey[VK_ENTER] = KEY_ENTER;
+    virtKeyToVlcKey[VK_NEWLINE] = KEY_ENTER;
+    virtKeyToVlcKey[VK_SPACE] = ' ';
+    virtKeyToVlcKey[VK_ESC] = KEY_ESC;
+    virtKeyToVlcKey[VK_LEFT] = KEY_LEFT;
+    virtKeyToVlcKey[VK_RIGHT] = KEY_RIGHT;
+    virtKeyToVlcKey[VK_UP] = KEY_UP;
+    virtKeyToVlcKey[VK_DOWN] = KEY_DOWN;
+    virtKeyToVlcKey[VK_INSERT] = KEY_INSERT;
+    virtKeyToVlcKey[VK_DELETE] = KEY_DELETE;
+    virtKeyToVlcKey[VK_HOME] = KEY_HOME;
+    virtKeyToVlcKey[VK_END] = KEY_END;
+    virtKeyToVlcKey[VK_PAGEUP] = KEY_PAGEUP;
+    virtKeyToVlcKey[VK_PAGEDOWN] = KEY_PAGEDOWN;
+}
+
+
+OS2Loop::~OS2Loop()
+{
+}
+
+
+OSLoop *OS2Loop::instance( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_osLoop == NULL )
+    {
+        OSLoop *pOsLoop = new OS2Loop( pIntf );
+        pIntf->p_sys->p_osLoop = pOsLoop;
+    }
+    return pIntf->p_sys->p_osLoop;
+}
+
+
+void OS2Loop::destroy( intf_thread_t *pIntf )
+{
+    delete pIntf->p_sys->p_osLoop;
+    pIntf->p_sys->p_osLoop = NULL;
+}
+
+
+void OS2Loop::run()
+{
+    QMSG qm;
+
+    // Compute windows message list
+    while( WinGetMsg( 0, &qm, NULLHANDLE, 0, 0 ))
+        WinDispatchMsg( 0, &qm );
+}
+
+
+MRESULT EXPENTRY OS2Loop::processEvent( HWND hwnd, ULONG msg,
+                                        MPARAM mp1, MPARAM mp2 )
+{
+    OS2Factory *pFactory =
+        (OS2Factory*)OS2Factory::instance( getIntf() );
+    GenericWindow *pWin = pFactory->m_windowMap[hwnd];
+
+    // To invert Y
+    RECTL rcl;
+    WinQueryWindowRect( hwnd, &rcl );
+
+    GenericWindow &win = *pWin;
+    switch( msg )
+    {
+        case WM_PAINT:
+        {
+            HPS   hps;
+            RECTL rclPaint;
+
+            hps = WinBeginPaint( hwnd, NULLHANDLE, &rclPaint );
+            EvtRefresh evt( getIntf(),
+                            rclPaint.xLeft,
+                            // Find top and invert it
+                            ( rcl.yTop - 1 ) - ( rclPaint.yTop - 1 ),
+                            rclPaint.xRight - rclPaint.xLeft + 1,
+                            rclPaint.yTop - rclPaint.yBottom + 1 );
+            win.processEvent( evt );
+            WinEndPaint( hps );
+            return 0;
+        }
+        case WM_COMMAND:
+        {
+            EvtMenu evt( getIntf(), SHORT1FROMMP( mp1 ));
+            win.processEvent( evt );
+            return 0;
+        }
+        case WM_MOUSEMOVE:
+        {
+            pFactory->changeCursor( pFactory->getCursorType());
+
+            // Compute the absolute position of the mouse
+            POINTL ptl;
+            WinQueryPointerPos( HWND_DESKTOP, &ptl );
+            int x = ptl.x;
+            int y = ( pFactory->getScreenHeight() - 1 ) - ptl.y;
+            EvtMotion evt( getIntf(), x, y );
+            win.processEvent( evt );
+
+            return MRFROMLONG( TRUE );
+            break;
+        }
+        case WM_MOUSELEAVE:
+        {
+            EvtLeave evt( getIntf() );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_BUTTON1DOWN:
+        {
+            WinSetCapture( HWND_DESKTOP, hwnd );
+            EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
+                          GET_Y_MP( mp1 ), EvtMouse::kLeft,
+                          EvtMouse::kDown, getMod( mp2 ) );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_BUTTON2DOWN:
+        {
+            WinSetCapture( HWND_DESKTOP, hwnd );
+            EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
+                          GET_Y_MP( mp1 ), EvtMouse::kRight,
+                          EvtMouse::kDown, getMod( mp2 ) );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_BUTTON1UP:
+        {
+            WinSetCapture( HWND_DESKTOP, NULLHANDLE );
+            EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
+                          GET_Y_MP( mp1 ), EvtMouse::kLeft,
+                          EvtMouse::kUp, getMod( mp2 ) );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_BUTTON2UP:
+        {
+            WinSetCapture( HWND_DESKTOP, NULLHANDLE );
+            EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
+                          GET_Y_MP( mp1 ), EvtMouse::kRight,
+                          EvtMouse::kUp, getMod( mp2 ) );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_BUTTON1DBLCLK:
+        {
+            WinSetCapture( HWND_DESKTOP, NULLHANDLE );
+            EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
+                          GET_Y_MP( mp1 ), EvtMouse::kLeft,
+                          EvtMouse::kDblClick, getMod( mp2 ) );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_BUTTON2DBLCLK:
+        {
+            WinSetCapture( HWND_DESKTOP, NULLHANDLE );
+            EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
+                          GET_Y_MP( mp1 ), EvtMouse::kRight,
+                          EvtMouse::kDblClick, getMod( mp2 ) );
+            win.processEvent( evt );
+            return MRFROMLONG( TRUE );
+        }
+        case WM_CHAR:
+        {
+            // The key events are first processed here and not translated
+            // into WM_CHAR events because we need to know the status of
+            // the modifier keys.
+
+            USHORT fsFlags = SHORT1FROMMP( mp1 );
+            USHORT usCh    = SHORT1FROMMP( mp2 );
+            USHORT usVk    = SHORT2FROMMP( mp2 );
+
+            // Get VLC key code from the virtual key code
+            int key = ( fsFlags & KC_VIRTUALKEY ) ?
+                            virtKeyToVlcKey[ usVk ] : 0;
+            if( !key )
+            {
+                // This appears to be a "normal" (ascii) key
+                key = tolower( usCh );
+            }
+
+            if( key )
+            {
+                // Get the modifier
+                int mod = 0;
+                if( fsFlags & KC_CTRL )
+                {
+                    mod |= EvtInput::kModCtrl;
+                }
+                if( fsFlags & KC_SHIFT )
+                {
+                    mod |= EvtInput::kModShift;
+                }
+                if( fsFlags & KC_ALT )
+                {
+                    mod |= EvtInput::kModAlt;
+                }
+
+                // Get the state
+                EvtKey::ActionType_t state;
+                if( fsFlags & KC_KEYUP )
+                {
+                    state = EvtKey::kUp;
+                }
+                else
+                {
+                    state = EvtKey::kDown;
+                }
+
+                EvtKey evt( getIntf(), key, state, mod );
+                win.processEvent( evt );
+            }
+            return MRFROMLONG( TRUE );
+        }
+        default:
+            break;
+    }
+    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
+}
+
+
+int OS2Loop::getMod( MPARAM mp ) const
+{
+    int mod = EvtInput::kModNone;
+    if( SHORT2FROMMP( mp ) & KC_CTRL )
+        mod |= EvtInput::kModCtrl;
+    if( SHORT2FROMMP( mp ) & KC_SHIFT )
+        mod |= EvtInput::kModShift;
+
+    return mod;
+}
+
+
+void OS2Loop::exit()
+{
+    WinPostQueueMsg( HMQ_CURRENT, WM_QUIT, 0, 0 );
+}
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_loop.hpp b/modules/gui/skins2/os2/os2_loop.hpp
new file mode 100644
index 0000000..3873377
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_loop.hpp
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * os2_loop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_LOOP_HPP
+#define OS2_LOOP_HPP
+
+#include "../events/evt_mouse.hpp"
+#include "../src/os_loop.hpp"
+#include <map>
+
+
+class GenericWindow;
+
+/// Main event loop for OS2
+class OS2Loop: public OSLoop
+{
+public:
+    /// Get the instance of OS2Loop
+    static OSLoop *instance( intf_thread_t *pIntf );
+
+    /// Destroy the instance of OS2Loop
+    static void destroy( intf_thread_t *pIntf );
+
+    /// Enter the event loop
+    virtual void run();
+
+    /// Exit the main loop
+    virtual void exit();
+
+    /// called by the window procedure callback
+    virtual MRESULT EXPENTRY processEvent( HWND hwnd, ULONG msg,
+                                           MPARAM mp1, MPARAM mp2 );
+
+private:
+    // Private because it is a singleton
+    OS2Loop( intf_thread_t *pIntf );
+    virtual ~OS2Loop();
+
+    /// Map associating special (i.e. non ascii) virtual key codes with
+    /// internal vlc key codes
+    map<int, int> virtKeyToVlcKey;
+
+    /// Helper function to find the modifier in a Windows message
+    int getMod( MPARAM mp ) const;
+};
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_popup.cpp b/modules/gui/skins2/os2/os2_popup.cpp
new file mode 100644
index 0000000..6479bdd
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_popup.cpp
@@ -0,0 +1,129 @@
+/*****************************************************************************
+ * os2_popup.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "os2_popup.hpp"
+#include "os2_factory.hpp"
+
+
+OS2Popup::OS2Popup( intf_thread_t *pIntf, HWND hAssociatedWindow )
+    : OSPopup( pIntf ), m_hWnd( hAssociatedWindow )
+{
+    // Create the popup menu
+    m_hMenu = WinCreateWindow( m_hWnd,          // parent
+                               WC_MENU,         // menu
+                               "",              // title
+                               0,               // style
+                               0, 0,            // x, y
+                               0, 0,            // cx, cy
+                               m_hWnd,          // owner
+                               HWND_TOP,        // z-order
+                               1,               // id
+                               NULL, NULL );    // ctrl data, pres params
+
+    if( !m_hMenu )
+    {
+        msg_Err( getIntf(), "CreatePopupMenu failed" );
+        return;
+    }
+}
+
+
+OS2Popup::~OS2Popup()
+{
+    if( m_hMenu )
+        WinDestroyWindow( m_hMenu );
+}
+
+
+void OS2Popup::show( int xPos, int yPos )
+{
+    POINTL ptl = { xPos, yPos };
+    // Invert Y
+    ptl.y = ( WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - 1 ) - ptl.y;
+    WinMapWindowPoints( HWND_DESKTOP, m_hWnd, &ptl, 1 );
+
+    WinPopupMenu( m_hWnd, m_hWnd, m_hMenu, ptl.x, ptl.y, 0,
+                  PU_HCONSTRAIN | PU_VCONSTRAIN | PU_NONE |
+                  PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 );
+}
+
+
+void OS2Popup::hide()
+{
+    WinSendMsg( m_hMenu, WM_CHAR,
+                MPFROM2SHORT( KC_VIRTUALKEY, 0 ),
+                MPFROM2SHORT( 0, VK_ESC ));
+}
+
+
+void OS2Popup::addItem( const string &rLabel, int pos )
+{
+    MENUITEM mi;
+
+    mi.iPosition   = findInsertionPoint( pos );
+    mi.afStyle     = MIS_TEXT;
+    mi.afAttribute = 0;
+    mi.id          = pos;
+    mi.hwndSubMenu = NULLHANDLE;
+    mi.hItem       = NULLHANDLE;
+
+    WinSendMsg( m_hMenu, MM_INSERTITEM, MPFROMP( &mi ),
+                MPFROMP( rLabel.c_str()));
+}
+
+
+void OS2Popup::addSeparator( int pos )
+{
+    MENUITEM mi;
+
+    mi.iPosition   = findInsertionPoint( pos );
+    mi.afStyle     = MIS_SEPARATOR;
+    mi.afAttribute = 0;
+    mi.id          = 0;
+    mi.hwndSubMenu = NULLHANDLE;
+    mi.hItem       = NULLHANDLE;
+
+    WinSendMsg( m_hMenu, MM_INSERTITEM, MPFROMP( &mi ), 0 );
+}
+
+
+unsigned int OS2Popup::findInsertionPoint( unsigned int pos ) const
+{
+    int nCount = LONGFROMMR( WinSendMsg( m_hMenu, MM_QUERYITEMCOUNT, 0, 0 ));
+
+    // For this simple algorithm, we rely on the fact that in the final state
+    // of the menu, the ID of each item is equal to its position in the menu
+    int i = 0;
+    while( i < nCount &&
+           SHORT1FROMMR( WinSendMsg( m_hMenu, MM_ITEMIDFROMPOSITION,
+                                     MPFROMLONG( i ), 0 )) < pos )
+    {
+        i++;
+    }
+    return i;
+}
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_popup.hpp b/modules/gui/skins2/os2/os2_popup.hpp
new file mode 100644
index 0000000..939dd39
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_popup.hpp
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * os2_popup.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_POPUP_HPP
+#define OS2_POPUP_HPP
+
+#include "../src/os_popup.hpp"
+
+
+/// OS2 implementation of OSPopup
+class OS2Popup: public OSPopup
+{
+public:
+    OS2Popup( intf_thread_t *pIntf, HWND hAssociatedWindow );
+
+    virtual ~OS2Popup();
+
+    /// Show the popup menu at the given (absolute) corrdinates
+    virtual void show( int xPos, int yPos );
+
+    /// Hide the popup menu
+    virtual void hide();
+
+    /// Append a new menu item with the given label to the popup menu
+    virtual void addItem( const string &rLabel, int pos );
+
+    /// Create a dummy menu item to separate sections
+    virtual void addSeparator( int pos );
+
+    /// Return the position of the item identified by the given id
+    virtual int getPosFromId( int id ) const { return id; }
+
+private:
+    /// Menu handle
+    HWND m_hMenu;
+    /// Handle of the window which will receive the menu events
+    HWND m_hWnd;
+
+    /**
+     * Find the item before which to insert another item so that the
+     * newly added item is at the position pos _when the whole menu has
+     * been built_ (no assumption is made for the order of insertion of
+     * the items)
+     */
+    unsigned int findInsertionPoint( unsigned int pos ) const;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_timer.cpp b/modules/gui/skins2/os2/os2_timer.cpp
new file mode 100644
index 0000000..2bf1e8c
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_timer.cpp
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ * os2_timer.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "os2_timer.hpp"
+#include "../commands/cmd_generic.hpp"
+
+#define OS2_TIMER_CLASS "OS2Timer Window Class"
+
+#define ID_TIMER 0x100
+
+static MRESULT EXPENTRY TimerWindowProc( HWND hwnd, ULONG msg,
+                                         MPARAM mp1, MPARAM mp2 )
+{
+    if( msg == WM_TIMER )
+    {
+        OS2Timer *pTimer = ( OS2Timer * )WinQueryWindowPtr( hwnd, 0 );
+
+        pTimer->execute();
+
+        return 0;
+    }
+
+    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
+}
+
+
+OS2Timer::OS2Timer( intf_thread_t *pIntf, CmdGeneric &rCmd, HWND hWnd ):
+    OSTimer( pIntf ), m_rCommand( rCmd ), m_hWnd( hWnd ), m_hwndTimer( 0 )
+{
+    WinRegisterClass( 0, OS2_TIMER_CLASS, TimerWindowProc, 0,
+                      sizeof( PVOID ));
+}
+
+
+OS2Timer::~OS2Timer()
+{
+    stop();
+}
+
+
+void OS2Timer::start( int delay, bool oneShot )
+{
+    m_interval = delay;
+    m_oneShot = oneShot;
+
+    m_hwndTimer = WinCreateWindow( HWND_OBJECT, OS2_TIMER_CLASS,
+                                   "", 0, 0, 0, 0, 0, NULLHANDLE,
+                                   HWND_TOP, 0, NULL, NULL );
+
+    WinSetWindowPtr( m_hwndTimer, 0, this );
+
+    WinStartTimer( 0, m_hwndTimer, ID_TIMER, m_interval );
+}
+
+
+void OS2Timer::stop()
+{
+    if( !m_hwndTimer )
+        return;
+
+    WinStopTimer( 0, m_hwndTimer, ID_TIMER );
+
+    WinDestroyWindow( m_hwndTimer );
+
+    m_hwndTimer = NULLHANDLE;
+}
+
+
+void OS2Timer::execute()
+{
+    // Execute the callback
+    m_rCommand.execute();
+
+    // Stop the timer if requested
+    if( m_oneShot )
+        stop();
+}
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_timer.hpp b/modules/gui/skins2/os2/os2_timer.hpp
new file mode 100644
index 0000000..67a63d7
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_timer.hpp
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * os2_timer.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_TIMER_HPP
+#define OS2_TIMER_HPP
+
+#include "../src/os_timer.hpp"
+
+class CmdGeneric;
+
+// OS2 specific timer
+class OS2Timer: public OSTimer
+{
+public:
+    OS2Timer( intf_thread_t *pIntf, CmdGeneric &rCmd, HWND hWnd );
+    virtual ~OS2Timer();
+
+    /// (Re)start the timer with the given delay (in ms). If oneShot is
+    /// true, stop it after the first execution of the callback.
+    virtual void start( int delay, bool oneShot );
+
+    /// Stop the timer
+    virtual void stop();
+
+    /// Execute the callback
+    void execute();
+
+private:
+    /// Command to execute
+    CmdGeneric &m_rCommand;
+
+    /// Delay between two execute
+    mtime_t m_interval;
+
+    /// Flag to tell whether the timer must be stopped after the
+    /// first execution
+    bool m_oneShot;
+
+    /// Handle of the window to which the timer will be attached
+    HWND m_hWnd;
+
+    /// Handle of the timer window
+    HWND m_hwndTimer;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_tooltip.cpp b/modules/gui/skins2/os2/os2_tooltip.cpp
new file mode 100644
index 0000000..6b6e4c9
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_tooltip.cpp
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * os2_tooltip.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "os2_tooltip.hpp"
+#include "os2_graphics.hpp"
+#include "../src/generic_window.hpp"
+
+OS2Tooltip::OS2Tooltip( intf_thread_t *pIntf, HMODULE hInst,
+                        HWND hParentWindow ):
+    OSTooltip( pIntf )
+{
+    // Create the window
+    ULONG flFrame = FCF_SHELLPOSITION;
+    m_hWnd = WinCreateStdWindow( HWND_DESKTOP,
+                                 WS_DISABLED,
+                                 &flFrame,
+                                 "SkinWindowClass",
+                                 "tooltip",
+                                 0,
+                                 hInst,
+                                 0,
+                                 &m_hWndClient );
+
+    if( !m_hWnd )
+    {
+        msg_Err( getIntf(), "createWindow failed" );
+    }
+}
+
+
+OS2Tooltip::~OS2Tooltip()
+{
+    if( m_hWnd )
+        WinDestroyWindow( m_hWnd );
+}
+
+
+void OS2Tooltip::show( int left, int top, OSGraphics &rText )
+{
+    // Source drawable
+    HPS hpsSrc = ((OS2Graphics&)rText).getPS();
+    int width = rText.getWidth();
+    int height = rText.getHeight();
+
+    RECTL rclParent;
+
+    WinQueryWindowRect( WinQueryWindow( m_hWnd, QW_PARENT ), &rclParent );
+
+    // Find bottom and invert it
+    int bottom = ( rclParent.yTop - 1 ) - ( top + height - 1 );
+
+    // Set the window on top, resize it, and show it
+    WinSetWindowPos( m_hWnd, HWND_TOP, left, bottom, width, height,
+                     SWP_ZORDER | SWP_MOVE | SWP_SIZE | SWP_SHOW );
+
+    HPS hps = WinGetPS( m_hWnd );
+    POINTL aptl[] = {{ 0, 0 }, { width, height }, { 0, 0 }};
+    GpiBitBlt( hps, hpsSrc, 3, aptl, ROP_SRCCOPY, BBO_IGNORE );
+    WinReleasePS( hps );
+}
+
+
+void OS2Tooltip::hide()
+{
+    WinShowWindow( m_hWnd, FALSE );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_tooltip.hpp b/modules/gui/skins2/os2/os2_tooltip.hpp
new file mode 100644
index 0000000..dc42234
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_tooltip.hpp
@@ -0,0 +1,54 @@
+/*****************************************************************************
+ * os2_tooltip.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_TOOLTIP_HPP
+#define OS2_TOOLTIP_HPP
+
+#include "../src/os_tooltip.hpp"
+
+
+/// OS2 implementation of OSTooltip
+class OS2Tooltip: public OSTooltip
+{
+public:
+    OS2Tooltip( intf_thread_t *pIntf, HMODULE hInst, HWND hParentWindow );
+
+    virtual ~OS2Tooltip();
+
+    /// Show the tooltip
+    virtual void show( int left, int top, OSGraphics &rText );
+
+    /// Hide the tooltip
+    virtual void hide();
+
+private:
+    /// Window ID
+    HWND m_hWnd;
+
+    /// Client window ID
+    HWND m_hWndClient;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_window.cpp b/modules/gui/skins2/os2/os2_window.cpp
new file mode 100644
index 0000000..8bc44ef
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_window.cpp
@@ -0,0 +1,237 @@
+/*****************************************************************************
+ * os2_window.cpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef OS2_SKINS
+
+#include "../src/generic_window.hpp"
+#include "../src/vlcproc.hpp"
+#include "../src/vout_manager.hpp"
+#include "os2_window.hpp"
+#include "os2_dragdrop.hpp"
+#include "os2_factory.hpp"
+
+
+OS2Window::OS2Window( intf_thread_t *pIntf, GenericWindow &rWindow,
+                      HMODULE hInst, HWND hParentWindow,
+                      bool dragDrop, bool playOnDrop,
+                      OS2Window *pParentWindow,
+                      GenericWindow::WindowType_t type ):
+    OSWindow( pIntf ), m_dragDrop( dragDrop ), m_isLayered( false ),
+    m_pParent( pParentWindow ), m_type ( type )
+{
+    (void)hParentWindow;
+    OS2Factory *pFactory = (OS2Factory*)OS2Factory::instance( getIntf() );
+
+    PCSZ  vlc_name  = "VlC Media Player";
+    PCSZ  vlc_class = "SkinWindowClass";
+    ULONG flFrame = 0;
+
+    // Create the window
+    if( type == GenericWindow::VoutWindow )
+    {
+        // Child window (for vout)
+        m_hWnd_parent = pParentWindow->getHandle();
+        m_hWnd = WinCreateStdWindow( m_hWnd_parent,
+                                     WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+                                     &flFrame,
+                                     vlc_class,
+                                     vlc_name,
+                                     0,
+                                     hInst,
+                                     0,
+                                     &m_hWndClient );
+    }
+    else if( type == GenericWindow::FullscreenWindow )
+    {
+        // top-level window
+        m_hWnd = WinCreateStdWindow( HWND_DESKTOP,
+                                     WS_CLIPCHILDREN,
+                                     &flFrame,
+                                     vlc_class,
+                                     vlc_name,
+                                     0,
+                                     hInst,
+                                     0,
+                                     &m_hWndClient );
+
+        WinSetOwner( m_hWnd, pFactory->getParentWindow());
+    }
+    else if( type == GenericWindow::FscWindow )
+    {
+        VoutManager* pVoutManager = VoutManager::instance( getIntf() );
+        GenericWindow* pParent =
+           (GenericWindow*)pVoutManager->getVoutMainWindow();
+
+        m_hWnd_parent = (HWND)pParent->getOSHandle();
+
+        // top-level window
+        m_hWnd = WinCreateStdWindow( HWND_DESKTOP,
+                                     WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+                                     &flFrame,
+                                     vlc_class,
+                                     vlc_name,
+                                     0,
+                                     hInst,
+                                     0,
+                                     &m_hWndClient );
+
+        WinSetOwner( m_hWnd, m_hWnd_parent );
+    }
+    else
+    {
+        // top-level window (owned by the root window)
+        HWND hWnd_owner = pFactory->getParentWindow();
+        m_hWnd = WinCreateStdWindow( HWND_DESKTOP,
+                                     WS_CLIPCHILDREN,
+                                     &flFrame,
+                                     vlc_class,
+                                     vlc_name,
+                                     0,
+                                     hInst,
+                                     0,
+                                     &m_hWndClient );
+
+        WinSetOwner( m_hWnd, hWnd_owner );
+    }
+
+    if( !m_hWnd )
+    {
+        msg_Err( getIntf(), "CreateWindow failed" );
+        return;
+    }
+
+    // Store with it a pointer to the interface thread
+    WinSetWindowPtr( m_hWndClient, 0, getIntf());
+
+    // Store a pointer to the GenericWindow in a map
+    pFactory->m_windowMap[m_hWndClient] = &rWindow;
+
+    // Drag & drop
+    if( m_dragDrop )
+    {
+        // TODO
+    }
+}
+
+
+OS2Window::~OS2Window()
+{
+    OS2Factory *pFactory = (OS2Factory*)OS2Factory::instance( getIntf() );
+    pFactory->m_windowMap[m_hWndClient] = NULL;
+
+    if( m_hWnd )
+    {
+        if( m_dragDrop )
+        {
+            // TODO
+        }
+
+        WinDestroyWindow( m_hWnd );
+    }
+}
+
+
+void OS2Window::reparent( void* OSHandle, int x, int y, int w, int h )
+{
+    HWND hwndParent = ( HWND )OSHandle;
+
+    // Reparent the window
+    if( !WinSetParent( m_hWnd, hwndParent, TRUE ) )
+        msg_Err( getIntf(), "SetParent failed (%lx)", WinGetLastError( 0 ));
+    RECTL rclParent;
+    WinQueryWindowRect( hwndParent, &rclParent );
+    // Find bottom and invert it
+    y = ( rclParent.yTop - 1 ) - ( y + h - 1 );
+    WinSetWindowPos( m_hWnd, NULLHANDLE, x, y, w, h, SWP_MOVE | SWP_SIZE );
+}
+
+
+bool OS2Window::invalidateRect( int x, int y, int w, int h ) const
+{
+    RECTL rcl;
+    WinQueryWindowRect( m_hWnd, &rcl );
+
+    // Find bottom and invert it
+    y = ( rcl.yTop - 1 ) - ( y + h - 1 );
+    WinSetRect( 0, &rcl, x, y, x + w, y + h );
+    WinInvalidateRect( m_hWndClient, &rcl, TRUE );
+    WinUpdateWindow( m_hWndClient );
+
+    return true;
+}
+
+
+void OS2Window::show() const
+{
+    if( m_type == GenericWindow::VoutWindow )
+    {
+        WinSetWindowPos( m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER );
+    }
+    else if( m_type == GenericWindow::FullscreenWindow )
+    {
+        WinSetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER );
+    }
+
+    WinSetWindowPos( m_hWnd, NULLHANDLE, 0, 0, 0, 0,
+                     SWP_SHOW | SWP_ACTIVATE );
+}
+
+
+void OS2Window::hide() const
+{
+    WinShowWindow( m_hWnd, FALSE );
+}
+
+
+void OS2Window::moveResize( int left, int top, int width, int height ) const
+{
+    RECTL rclParent;
+    WinQueryWindowRect( WinQueryWindow( m_hWnd, QW_PARENT ), &rclParent );
+    // Find bottom and invert it
+    int bottom = ( rclParent.yTop - 1 ) - ( top + height - 1 );
+    WinSetWindowPos( m_hWnd, NULLHANDLE, left, bottom , width, height,
+                     SWP_MOVE | SWP_SIZE );
+}
+
+
+void OS2Window::raise() const
+{
+    WinSetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER | SWP_SHOW );
+}
+
+
+void OS2Window::setOpacity( uint8_t value ) const
+{
+    // Not supported
+}
+
+
+void OS2Window::toggleOnTop( bool onTop ) const
+{
+    // Just bring a window to the top
+    WinSetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0, onTop ? SWP_ZORDER : 0 );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/os2/os2_window.hpp b/modules/gui/skins2/os2/os2_window.hpp
new file mode 100644
index 0000000..e0aed77
--- /dev/null
+++ b/modules/gui/skins2/os2/os2_window.hpp
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ * os2_window.hpp
+ *****************************************************************************
+ * Copyright (C) 2003, 2013 the VideoLAN team
+ *
+ * Authors: Cyril Deguet      <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *          KO Myung-Hun      <komh@chollian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef OS2_WINDOW_HPP
+#define OS2_WINDOW_HPP
+
+#include "../src/generic_window.hpp"
+#include "../src/os_window.hpp"
+
+
+/// OS2 implementation of OSWindow
+class OS2Window: public OSWindow
+{
+public:
+    OS2Window( intf_thread_t *pIntf, GenericWindow &rWindow,
+               HMODULE hInst, HWND hParentWindow,
+               bool dragDrop, bool playOnDrop,
+               OS2Window *pParentWindow, GenericWindow::WindowType_t );
+    virtual ~OS2Window();
+
+    // Show the window
+    virtual void show() const;
+
+    // Hide the window
+    virtual void hide() const;
+
+    /// Move and resize the window
+    virtual void moveResize( int left, int top, int width, int height ) const;
+
+    /// Bring the window on top
+    virtual void raise() const;
+
+    /// Set the opacity of the window (0 = transparent, 255 = opaque)
+    virtual void setOpacity( uint8_t value ) const;
+
+    /// Toggle the window on top
+    virtual void toggleOnTop( bool onTop ) const;
+
+    /// Getter for the window handle
+    HWND getHandle() const { return m_hWndClient; }
+
+    /// Getter for the window handle
+    void* getOSHandle() const { return (void*) m_hWndClient; }
+
+    /// reparent the window
+    void reparent( void* OSHandle, int x, int y, int w, int h );
+
+    /// invalidate a window surface
+    bool invalidateRect( int x, int y, int w, int h ) const;
+
+private:
+    /// Window handle
+    HWND m_hWnd;
+    /// Client window handle
+    HWND m_hWndClient;
+    /// Window parent's handle
+    HWND m_hWnd_parent;
+    /// Indicates whether the window handles drag&drop events
+    bool m_dragDrop;
+    /// Indicates whether the window is layered
+    mutable bool m_isLayered;
+    /// Parent window
+    OS2Window *m_pParent;
+    /// window type
+    GenericWindow::WindowType_t m_type;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/parser/builder.cpp b/modules/gui/skins2/parser/builder.cpp
index 15e5490..260befa 100644
--- a/modules/gui/skins2/parser/builder.cpp
+++ b/modules/gui/skins2/parser/builder.cpp
@@ -1251,7 +1251,7 @@ string Builder::getFilePath( const string &rFileName ) const
            file[pos] = '/';
     }
 
-#ifdef WIN32
+#if defined( WIN32 ) || defined( __OS2__ )
     string::size_type pos;
     while( ( pos = file.find( "/" ) ) != string::npos )
        file.replace( pos, 1, sep );
diff --git a/modules/gui/skins2/src/os_factory.cpp b/modules/gui/skins2/src/os_factory.cpp
index 297485c..cbf81ab 100644
--- a/modules/gui/skins2/src/os_factory.cpp
+++ b/modules/gui/skins2/src/os_factory.cpp
@@ -30,6 +30,8 @@
 #include "../win32/win32_factory.hpp"
 #elif defined MACOSX_SKINS
 #include "../macosx/macosx_factory.hpp"
+#elif defined OS2_SKINS
+#include "../os2/os2_factory.hpp"
 #endif
 
 OSFactory *OSFactory::instance( intf_thread_t *pIntf )
@@ -43,6 +45,8 @@ OSFactory *OSFactory::instance( intf_thread_t *pIntf )
         pOsFactory = new Win32Factory( pIntf );
 #elif defined MACOSX_SKINS
         pOsFactory = new MacOSXFactory( pIntf );
+#elif defined OS2_SKINS
+        pOsFactory = new OS2Factory( pIntf );
 #else
 #error "No OSFactory implementation !"
 #endif
diff --git a/modules/gui/skins2/src/skin_main.cpp b/modules/gui/skins2/src/skin_main.cpp
index d681996..52200b1 100644
--- a/modules/gui/skins2/src/skin_main.cpp
+++ b/modules/gui/skins2/src/skin_main.cpp
@@ -511,7 +511,7 @@ vlc_module_begin ()
     add_shortcut( "skins" )
 
     add_submodule ()
-#ifdef WIN32
+#if defined( WIN32 ) || defined( __OS2__ )
         set_capability( "vout window hwnd", 51 )
 #else
         set_capability( "vout window xid", 51 )
diff --git a/modules/gui/skins2/src/vout_manager.hpp b/modules/gui/skins2/src/vout_manager.hpp
index 3d0bf39..615c945 100644
--- a/modules/gui/skins2/src/vout_manager.hpp
+++ b/modules/gui/skins2/src/vout_manager.hpp
@@ -71,7 +71,7 @@ public:
     }
     virtual ~VoutMainWindow() { }
 
-#ifdef WIN32
+#if defined( WIN32 ) || defined( __OS2__ )
 
     virtual void processEvent( EvtKey &rEvtKey )
     {
diff --git a/modules/gui/skins2/src/window_manager.cpp b/modules/gui/skins2/src/window_manager.cpp
index 780b765..093e6d3 100644
--- a/modules/gui/skins2/src/window_manager.cpp
+++ b/modules/gui/skins2/src/window_manager.cpp
@@ -275,13 +275,13 @@ void WindowManager::resize( GenericLayout &rLayout,
     int xNewOffset = newWidth - rLayout.getWidth();
     int yNewOffset = newHeight - rLayout.getHeight();
 
-    // Do the actual resizing
-    rLayout.resize( newWidth, newHeight );
-
     // Resize the window
     TopWindow *pWindow = rLayout.getWindow();
     pWindow->resize( newWidth, newHeight );
 
+    // Do the actual resizing
+    rLayout.resize( newWidth, newHeight );
+
     // refresh content
     rLayout.refreshAll();
 
-- 
1.7.3.2

