[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