[vlc-devel] [PATCH] skins2: add OS/2 support

brezhoneg1 brezhoneg1 at yahoo.fr
Fri May 17 17:13:34 CEST 2013


Le 17/05/2013 10:39, KO Myung-Hun a écrit :
> ---
>   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    |  452 ++++++++++++++++++++++++++++
>   modules/gui/skins2/os2/os2_factory.hpp    |  152 ++++++++++
>   modules/gui/skins2/os2/os2_graphics.cpp   |  453 +++++++++++++++++++++++++++++
>   modules/gui/skins2/os2/os2_graphics.hpp   |  140 +++++++++
>   modules/gui/skins2/os2/os2_loop.cpp       |  295 +++++++++++++++++++
>   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, 2526 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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..d741196
> --- /dev/null
> +++ b/modules/gui/skins2/os2/os2_factory.cpp
> @@ -0,0 +1,452 @@
> +/*****************************************************************************
> + * os2_factory.cpp
> + *****************************************************************************
> + * Copyright (C) 2003, 2013 the VideoLAN team
> + *
> + * Authors: Cyril Deguet      <asmax at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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_dirSep( "\\" ), m_pfnwpOldFrameProc( 0 )
> +{
> +    // 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 );
> +
> +    // 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 );
> +}
> +
> +
> +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..cfe3fe4
> --- /dev/null
> +++ b/modules/gui/skins2/os2/os2_factory.hpp
> @@ -0,0 +1,152 @@
> +/*****************************************************************************
> + * os2_factory.hpp
> + *****************************************************************************
> + * Copyright (C) 2003, 2013 the VideoLAN team
> + *
> + * Authors: Cyril Deguet      <asmax at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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;
> +
> +    HWND getParentWindow() { return m_hParentClientWindow; }
> +
> +    /// 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;
> +    /// Window procedure of the old frame window
> +    PFNWP m_pfnwpOldFrameProc;
> +    /// Handle of the parent window
> +    HWND m_hParentWindow;
> +    /// Handle of the client window of the parent window
> +    HWND m_hParentClientWindow;
> +    /// 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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..5a23b5a
> --- /dev/null
> +++ b/modules/gui/skins2/os2/os2_loop.cpp
> @@ -0,0 +1,295 @@
> +/*****************************************************************************
> + * os2_loop.cpp
> + *****************************************************************************
> + * Copyright (C) 2003, 2013 the VideoLAN team
> + *
> + * Authors: Cyril Deguet      <asmax at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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:
> +        {
> +            // Compute the absolute position of the mouse
> +            int x = GET_X_MP( mp1 ) + win.getLeft();
> +            int y = GET_Y_MP( mp1 ) + win.getTop();
> +            EvtMotion evt( getIntf(), x, y );
> +            win.processEvent( evt );
> +
> +            // fall though to WinDefWindowProc()
> +            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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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 at via.ecp.fr>
> + *          Olivier Teulière <ipkiss at via.ecp.fr>
> + *          KO Myung-Hun      <komh at 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();
>   

Any technical reasons why you needed to move layout resizing after 
window resizing  just above ? Or is it just cosmetics? which is okay anyway.

It seems good to me, doesn't show any regression for Linux and I guess 
it compiles and runs fine on OS/2 too ...

I am not familiar with committing patches for somebody else. I leave it 
to sbdy who knows how to do it.

Erwan




More information about the vlc-devel mailing list