[vlc-commits] skins2(x11): implement cursor management

Erwan Tulou git at videolan.org
Fri Jan 12 23:22:27 CET 2018


vlc | branch: master | Erwan Tulou <erwan10 at videolan.org> | 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" );



More information about the vlc-commits mailing list