vlc | branch: master | Erwan Tulou <[email protected]> | Fri Jan 12 18:12:34 2018 +0100| [9f475faac675e1baadb022134d1936ef868926f1] | committer: Erwan Tulou
skins2(x11): implement cursor management > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9f475faac675e1baadb022134d1936ef868926f1 --- configure.ac | 3 +- modules/gui/skins2/src/generic_window.cpp | 4 +-- modules/gui/skins2/src/generic_window.hpp | 4 +++ modules/gui/skins2/x11/x11_factory.cpp | 54 ++++++++++++++++++++++++++++++- modules/gui/skins2/x11/x11_factory.hpp | 13 ++++++-- modules/gui/skins2/x11/x11_loop.cpp | 13 ++++---- 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 030832e3e3..efe861b613 100644 --- a/configure.ac +++ b/configure.ac @@ -3750,9 +3750,10 @@ AS_IF([test "${enable_skins2}" != "no"], [ ], [ PKG_CHECK_MODULES([XPM], [xpm],, [have_skins_deps="no"]) PKG_CHECK_MODULES([XINERAMA], [xinerama],, [have_skins_deps="no"]) + PKG_CHECK_MODULES([XCURSOR], [xcursor],, [have_skins_x11_deps="no"]) PKG_CHECK_MODULES([XEXT], [xext],, [have_skins_deps="no"]) VLC_ADD_CPPFLAGS([skins2],[${X_CFLAGS} ${XEXT_CFLAGS} ${XPM_CFLAGS} -DX11_SKINS]) - VLC_ADD_LIBS([skins2],[${X_LIBS} ${X_PRE_LIBS} ${XEXT_LIBS} ${XPM_LIBS} ${XINERAMA_LIBS} -lX11]) + VLC_ADD_LIBS([skins2],[${X_LIBS} ${X_PRE_LIBS} ${XEXT_LIBS} ${XPM_LIBS} ${XINERAMA_LIBS} ${XCURSOR_LIBS} -lX11]) ]) dnl we need freetype diff --git a/modules/gui/skins2/src/generic_window.cpp b/modules/gui/skins2/src/generic_window.cpp index 445a3a2824..49d9beef1f 100644 --- a/modules/gui/skins2/src/generic_window.cpp +++ b/modules/gui/skins2/src/generic_window.cpp @@ -32,8 +32,8 @@ GenericWindow::GenericWindow( intf_thread_t *pIntf, int left, int top, bool dragDrop, bool playOnDrop, GenericWindow *pParent, WindowType_t type ): - SkinObject( pIntf ), m_left( left ), m_top( top ), m_width( 0 ), - m_height( 0 ), m_pVarVisible( NULL ) + SkinObject( pIntf ), m_type( type ), m_left( left ), m_top( top ), + m_width( 0 ), m_height( 0 ), m_pVarVisible( NULL ) { // Get the OSFactory OSFactory *pOsFactory = OSFactory::instance( getIntf() ); diff --git a/modules/gui/skins2/src/generic_window.hpp b/modules/gui/skins2/src/generic_window.hpp index b8f4b70660..86343e234e 100644 --- a/modules/gui/skins2/src/generic_window.hpp +++ b/modules/gui/skins2/src/generic_window.hpp @@ -114,6 +114,9 @@ public: /// windows handle vlc_wnd_type getOSHandle() const; + /// window type + WindowType_t getType() { return m_type; } + /// reparent void setParent( GenericWindow* pParent, int x = 0, int y = 0, int w = -1, int h = -1 ); @@ -157,6 +160,7 @@ protected: virtual void onUpdate( Subject<VarBool> &rVariable , void*); private: + WindowType_t m_type; /// Window position and size int m_left, m_top, m_width, m_height; /// OS specific implementation diff --git a/modules/gui/skins2/x11/x11_factory.cpp b/modules/gui/skins2/x11/x11_factory.cpp index 6e7c671884..008c64bddb 100644 --- a/modules/gui/skins2/x11/x11_factory.cpp +++ b/modules/gui/skins2/x11/x11_factory.cpp @@ -45,7 +45,8 @@ #include <vlc_xlib.h> X11Factory::X11Factory( intf_thread_t *pIntf ): OSFactory( pIntf ), - m_pDisplay( NULL ), m_pTimerLoop( NULL ), m_dirSep( "/" ) + m_pDisplay( NULL ), m_pTimerLoop( NULL ), m_dirSep( "/" ), + mPointerWindow( None ), mVoutWindow( None ), mEmptyCursor( None ) { // see init() } @@ -53,6 +54,8 @@ X11Factory::X11Factory( intf_thread_t *pIntf ): OSFactory( pIntf ), X11Factory::~X11Factory() { + if( mEmptyCursor != None ) + XFreeCursor( m_pDisplay->getDisplay(), mEmptyCursor ); delete m_pTimerLoop; delete m_pDisplay; } @@ -107,6 +110,9 @@ bool X11Factory::init() XFree( info ); } + // init cursors + initCursors(); + return true; } @@ -370,4 +376,50 @@ void X11Factory::rmDir( const std::string &rPath ) rmdir( rPath.c_str() ); } + +void X11Factory::changeCursor( CursorType_t type ) const +{ + Cursor cursor = mCursors[type]; + Window win = (type == OSFactory::kNoCursor) ? mVoutWindow : mPointerWindow; + + if( win != None ) + XDefineCursor( m_pDisplay->getDisplay(), win, cursor ); +} + +void X11Factory::initCursors( ) +{ + Display *display = m_pDisplay->getDisplay(); + static const struct { + CursorType_t type; + const char *name; + } cursors[] = { + { kDefaultArrow, "left_ptr" }, + { kResizeNWSE, "bottom_right_corner" }, + { kResizeNS, "bottom_side" }, + { kResizeWE, "right_side" }, + { kResizeNESW, "bottom_left_corner" }, + }; + // retrieve cursors from default theme + for( unsigned i = 0; i < sizeof(cursors) / sizeof(cursors[0]); i++ ) + mCursors[cursors[i].type] = + XcursorLibraryLoadCursor( display, cursors[i].name ); + + // build an additional empty cursor + XColor color; + const char data[] = { 0 }; + Window root = DefaultRootWindow( display ); + Pixmap pix = XCreateBitmapFromData( display, root, data, 1, 1 ); + mEmptyCursor = XCreatePixmapCursor( display, pix, pix, &color, &color, 0, 0 ); + XFreePixmap( display, pix ); + mCursors[kNoCursor] = mEmptyCursor; +} + + +void X11Factory::setPointerWindow( Window win ) +{ + GenericWindow *pWin = m_windowMap[win]; + if( pWin->getType() == GenericWindow::VoutWindow ) + mVoutWindow = win; + mPointerWindow = win; +} #endif diff --git a/modules/gui/skins2/x11/x11_factory.hpp b/modules/gui/skins2/x11/x11_factory.hpp index c8f2ce00ac..c9094c8064 100644 --- a/modules/gui/skins2/x11/x11_factory.hpp +++ b/modules/gui/skins2/x11/x11_factory.hpp @@ -26,6 +26,7 @@ #define X11_FACTORY_HPP #include <X11/Xlib.h> +#include <X11/Xcursor/Xcursor.h> #include "../src/os_factory.hpp" #include "../src/generic_window.hpp" @@ -144,8 +145,7 @@ public: virtual void getMousePos( int &rXPos, int &rYPos ) const; /// Change the cursor - virtual void changeCursor( CursorType_t type ) const - { /*TODO*/ (void)type; } + virtual void changeCursor( CursorType_t type ) const; /// Delete a directory recursively virtual void rmDir( const std::string &rPath ); @@ -153,6 +153,10 @@ public: /// Get the timer loop X11TimerLoop *getTimerLoop() const { return m_pTimerLoop; } + /// retain current window where mouse pointer lies + void setPointerWindow( Window win ); + + private: /// X11 display X11Display *m_pDisplay; @@ -164,6 +168,11 @@ private: std::list<std::string> m_resourcePath; /// Monitor geometry int m_screenWidth, m_screenHeight; + /// cursor management variables + mutable std::map<CursorType_t, Cursor> mCursors; + void initCursors(); + Window mPointerWindow, mVoutWindow; + Cursor mEmptyCursor; }; #endif diff --git a/modules/gui/skins2/x11/x11_loop.cpp b/modules/gui/skins2/x11/x11_loop.cpp index 0aa682e0a3..4355c9f232 100644 --- a/modules/gui/skins2/x11/x11_loop.cpp +++ b/modules/gui/skins2/x11/x11_loop.cpp @@ -161,7 +161,7 @@ inline int X11Loop::X11ModToMod( unsigned state ) void X11Loop::handleX11Event() { XEvent event; - OSFactory *pOsFactory = OSFactory::instance( getIntf() ); + X11Factory *pFactory = (X11Factory*)OSFactory::instance( getIntf() ); // Look for the next event in the queue XNextEvent( XDISPLAY, &event ); @@ -186,8 +186,7 @@ void X11Loop::handleX11Event() } // Find the window to which the event is sent - GenericWindow *pWin = - ((X11Factory*)pOsFactory)->m_windowMap[event.xany.window]; + GenericWindow *pWin = pFactory->m_windowMap[event.xany.window]; if( !pWin ) { @@ -223,7 +222,8 @@ void X11Loop::handleX11Event() // Don't trust the position in the event, it is // out of date. Get the actual current position instead int x, y; - pOsFactory->getMousePos( x, y ); + pFactory->getMousePos( x, y ); + pFactory->setPointerWindow( event.xany.window ); EvtMotion evt( getIntf(), x, y ); pWin->processEvent( evt ); break; @@ -256,7 +256,7 @@ void X11Loop::handleX11Event() { mtime_t time = mdate(); int x, y; - pOsFactory->getMousePos( x, y ); + pFactory->getMousePos( x, y ); if( time - m_lastClickTime < m_dblClickDelay && x == m_lastClickPosX && y == m_lastClickPosY ) { @@ -343,8 +343,7 @@ void X11Loop::handleX11Event() std::string type = XGetAtomName( XDISPLAY, event.xclient.message_type ); // Find the DnD object for this window - X11DragDrop *pDnd = - ((X11Factory*)pOsFactory)->m_dndMap[event.xany.window]; + X11DragDrop *pDnd = pFactory->m_dndMap[event.xany.window]; if( !pDnd ) { msg_Err( getIntf(), "no associated D&D object" ); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
