kdeui: keep reference to the QByteArray object in x11SetCursorName() function

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2023-08-22 05:44:17 +03:00
parent b4657deb95
commit 58dfa5c884
4 changed files with 140 additions and 131 deletions

View file

@ -497,6 +497,7 @@ void KGlobalSettings::Private::_k_slotNotifyChange(int changeType, int arg)
}
default: {
kWarning() << "Unknown type of change in KGlobalSettings::slotNotifyChange: " << changeType;
break;
}
}
}

View file

@ -100,13 +100,13 @@ namespace
// stored in pairs in the font, with the shape glyph first. There's only one
// name for each pair. This function always returns the index for the
// shape glyph.
if (shapes.isEmpty())
{
if (shapes.isEmpty()) {
int num = XC_num_glyphs / 2;
shapes.reserve(num + 5);
for (int i = 0; i < num; ++i)
for (int i = 0; i < num; ++i) {
shapes.insert(standard_names[i], i << 1);
}
// Qt uses alternative names for some core cursors
shapes.insert("size_all", XC_fleur);
@ -122,22 +122,20 @@ namespace
static Qt::HANDLE x11LoadFontCursor(const QString &name)
{
int shape = x11CursorShape(name);
if (shape != -1)
if (shape != -1) {
return XCreateFontCursor(QX11Info::display(), shape);
}
return 0;
}
bool x11HaveXfixes()
{
bool result = false;
#ifdef HAVE_XFIXES
int event_base, error_base;
if (XFixesQueryExtension(QX11Info::display(), &event_base, &error_base))
{
int major, minor;
if (XFixesQueryExtension(QX11Info::display(), &event_base, &error_base)) {
int major = 0;
int minor = 0;
XFixesQueryVersion(QX11Info::display(), &major, &minor);
result = (major >= 2);
}
@ -149,14 +147,15 @@ namespace
{
#ifdef HAVE_XFIXES
static bool haveXfixes = x11HaveXfixes();
if (haveXfixes)
XFixesSetCursorName(QX11Info::display(), handle, QFile::encodeName(name));
if (haveXfixes) {
const QByteArray namebytes = QFile::encodeName(name);
XFixesSetCursorName(QX11Info::display(), handle, namebytes.constData());
}
#endif
}
}
QCursor KCursor::fromName( const QString& name, Qt::CursorShape fallback )
QCursor KCursor::fromName(const QString &name, Qt::CursorShape fallback)
{
Qt::HANDLE handle = x11LoadXcursor(name);
if (!handle) {
@ -171,18 +170,18 @@ QCursor KCursor::fromName( const QString& name, Qt::CursorShape fallback )
return QCursor(fallback);
}
void KCursor::setAutoHideCursor( QWidget *w, bool enable,
bool customEventFilter )
void KCursor::setAutoHideCursor(QWidget *w, bool enable,
bool customEventFilter)
{
KCursorPrivate::self()->setAutoHideCursor( w, enable, customEventFilter );
KCursorPrivate::self()->setAutoHideCursor(w, enable, customEventFilter);
}
void KCursor::autoHideEventFilter( QObject *o, QEvent *e )
void KCursor::autoHideEventFilter(QObject *o, QEvent *e)
{
KCursorPrivate::self()->eventFilter( o, e );
KCursorPrivate::self()->eventFilter(o, e);
}
void KCursor::setHideCursorDelay( int ms )
void KCursor::setHideCursorDelay(int ms)
{
KCursorPrivate::self()->hideCursorDelay = ms;
}
@ -194,64 +193,69 @@ int KCursor::hideCursorDelay()
// **************************************************************************
KCursorPrivateAutoHideEventFilter::KCursorPrivateAutoHideEventFilter( QWidget* widget )
: m_widget( widget )
, m_wasMouseTracking( m_widget->hasMouseTracking() )
, m_isCursorHidden( false )
, m_isOwnCursor( false )
KCursorPrivateAutoHideEventFilter::KCursorPrivateAutoHideEventFilter(QWidget* widget)
: m_widget(widget)
, m_wasMouseTracking(m_widget->hasMouseTracking())
, m_isCursorHidden(false)
, m_isOwnCursor(false)
{
mouseWidget()->setMouseTracking( true );
connect( &m_autoHideTimer, SIGNAL(timeout()),
this, SLOT(hideCursor()) );
mouseWidget()->setMouseTracking(true);
connect(&m_autoHideTimer, SIGNAL(timeout()), this, SLOT(hideCursor()));
}
KCursorPrivateAutoHideEventFilter::~KCursorPrivateAutoHideEventFilter()
{
if( m_widget != NULL )
mouseWidget()->setMouseTracking( m_wasMouseTracking );
if (m_widget) {
mouseWidget()->setMouseTracking(m_wasMouseTracking);
}
}
void KCursorPrivateAutoHideEventFilter::resetWidget()
{
m_widget = NULL;
m_widget = nullptr;
}
void KCursorPrivateAutoHideEventFilter::hideCursor()
{
m_autoHideTimer.stop();
if ( m_isCursorHidden )
if (m_isCursorHidden) {
return;
}
m_isCursorHidden = true;
QWidget* w = mouseWidget();
m_isOwnCursor = w->testAttribute(Qt::WA_SetCursor);
if ( m_isOwnCursor )
if (m_isOwnCursor) {
m_oldCursor = w->cursor();
}
w->setCursor( QCursor( Qt::BlankCursor ) );
w->setCursor(QCursor(Qt::BlankCursor));
}
void KCursorPrivateAutoHideEventFilter::unhideCursor()
{
m_autoHideTimer.stop();
if ( !m_isCursorHidden )
if (!m_isCursorHidden) {
return;
}
m_isCursorHidden = false;
QWidget* w = mouseWidget();
if ( w->cursor().shape() != Qt::BlankCursor ) // someone messed with the cursor already
if (w->cursor().shape() != Qt::BlankCursor) {
// someone messed with the cursor already
return;
}
if ( m_isOwnCursor )
w->setCursor( m_oldCursor );
else
if (m_isOwnCursor) {
w->setCursor(m_oldCursor);
} else {
w->unsetCursor();
}
}
// The widget which gets mouse events, and that shows the cursor
@ -261,64 +265,67 @@ QWidget* KCursorPrivateAutoHideEventFilter::mouseWidget() const
QWidget* w = m_widget;
// Is w a QAbstractScrollArea ? Call setCursor on the viewport in that case.
QAbstractScrollArea * sv = qobject_cast<QAbstractScrollArea *>( w );
if ( sv )
QAbstractScrollArea * sv = qobject_cast<QAbstractScrollArea*>(w);
if (sv) {
w = sv->viewport();
}
return w;
}
bool KCursorPrivateAutoHideEventFilter::eventFilter( QObject *o, QEvent *e )
bool KCursorPrivateAutoHideEventFilter::eventFilter(QObject *o, QEvent *e)
{
Q_UNUSED(o);
// o is m_widget or its viewport
//Q_ASSERT( o == m_widget );
// Q_ASSERT(o == m_widget);
switch ( e->type() )
{
case QEvent::Leave:
case QEvent::FocusOut:
case QEvent::WindowDeactivate:
unhideCursor();
break;
case QEvent::KeyPress:
case QEvent::ShortcutOverride:
hideCursor();
break;
case QEvent::Enter:
case QEvent::FocusIn:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::Show:
case QEvent::Hide:
case QEvent::Wheel:
unhideCursor();
if ( m_widget->hasFocus() )
{
m_autoHideTimer.setSingleShot( true );
m_autoHideTimer.start( KCursorPrivate::self()->hideCursorDelay );
switch (e->type()) {
case QEvent::Leave:
case QEvent::FocusOut:
case QEvent::WindowDeactivate: {
unhideCursor();
break;
}
case QEvent::KeyPress:
case QEvent::ShortcutOverride: {
hideCursor();
break;
}
case QEvent::Enter:
case QEvent::FocusIn:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::Show:
case QEvent::Hide:
case QEvent::Wheel: {
unhideCursor();
if (m_widget->hasFocus()) {
m_autoHideTimer.setSingleShot(true);
m_autoHideTimer.start( KCursorPrivate::self()->hideCursorDelay);
}
break;
}
default: {
break;
}
break;
default:
break;
}
return false;
}
KCursorPrivate * KCursorPrivate::s_self = 0L;
KCursorPrivate * KCursorPrivate::s_self = nullptr;
KCursorPrivate * KCursorPrivate::self()
{
if ( !s_self )
s_self = new KCursorPrivate;
if (!s_self) {
s_self = new KCursorPrivate();
}
// WABA: Don't delete KCursorPrivate, it serves no real purpose.
// Even worse it causes crashes because it seems to get deleted
// during ~QApplication and ~QApplication doesn't seem to like it
// when we delete a QCursor. No idea if that is a bug itself.
return s_self;
}
@ -326,71 +333,74 @@ KCursorPrivate::KCursorPrivate()
{
hideCursorDelay = 5000; // 5s default value
KConfigGroup cg( KGlobal::config(), QLatin1String("KDE") );
enabled = cg.readEntry( QLatin1String("Autohiding cursor enabled"), true);
KConfigGroup cg(KGlobal::config(), QLatin1String("KDE"));
enabled = cg.readEntry(QLatin1String("Autohiding cursor enabled"), true);
}
KCursorPrivate::~KCursorPrivate()
{
}
void KCursorPrivate::setAutoHideCursor( QWidget *w, bool enable, bool customEventFilter )
void KCursorPrivate::setAutoHideCursor(QWidget *w, bool enable, bool customEventFilter)
{
if ( !w || !enabled )
if (!w || !enabled) {
return;
}
QWidget* viewport = 0;
QAbstractScrollArea * sv = qobject_cast<QAbstractScrollArea *>( w );
if ( sv )
QAbstractScrollArea* sv = qobject_cast<QAbstractScrollArea*>(w);
if (sv) {
viewport = sv->viewport();
}
if ( enable )
{
if ( m_eventFilters.contains( w ) )
if (enable) {
if (m_eventFilters.contains(w)) {
return;
KCursorPrivateAutoHideEventFilter* filter = new KCursorPrivateAutoHideEventFilter( w );
m_eventFilters.insert( w, filter );
}
KCursorPrivateAutoHideEventFilter* filter = new KCursorPrivateAutoHideEventFilter(w);
m_eventFilters.insert(w, filter);
if (viewport) {
m_eventFilters.insert( viewport, filter );
m_eventFilters.insert(viewport, filter);
connect(viewport, SIGNAL(destroyed(QObject*)), this, SLOT(slotViewportDestroyed(QObject*)));
}
if ( !customEventFilter ) {
w->installEventFilter( filter ); // for key events
if (viewport)
viewport->installEventFilter( filter ); // for mouse events
if (!customEventFilter) {
// for key events
w->installEventFilter(filter);
if (viewport) {
// for mouse events
viewport->installEventFilter(filter);
}
}
connect( w, SIGNAL(destroyed(QObject*)),
this, SLOT(slotWidgetDestroyed(QObject*)) );
}
else
{
KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( w );
if ( filter == 0 )
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(slotWidgetDestroyed(QObject*)));
} else {
KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take(w);
if (!filter) {
return;
w->removeEventFilter( filter );
}
w->removeEventFilter(filter);
if (viewport) {
m_eventFilters.remove( viewport );
m_eventFilters.remove(viewport);
disconnect(viewport, SIGNAL(destroyed(QObject*)), this, SLOT(slotViewportDestroyed(QObject*)));
viewport->removeEventFilter( filter );
viewport->removeEventFilter(filter);
}
delete filter;
disconnect( w, SIGNAL(destroyed(QObject*)),
this, SLOT(slotWidgetDestroyed(QObject*)) );
disconnect(w, SIGNAL(destroyed(QObject*)), this, SLOT(slotWidgetDestroyed(QObject*)));
}
}
bool KCursorPrivate::eventFilter( QObject *o, QEvent *e )
bool KCursorPrivate::eventFilter(QObject *o, QEvent *e)
{
if ( !enabled )
if (!enabled) {
return false;
}
KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.value( o );
Q_ASSERT( filter != 0 );
if ( filter == 0 )
KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.value(o);
Q_ASSERT(filter != nullptr);
if (!filter) {
return false;
}
return filter->eventFilter( o, e );
return filter->eventFilter(o, e);
}
void KCursorPrivate::slotViewportDestroyed(QObject *o)
@ -398,12 +408,10 @@ void KCursorPrivate::slotViewportDestroyed(QObject *o)
m_eventFilters.remove(o);
}
void KCursorPrivate::slotWidgetDestroyed( QObject* o )
void KCursorPrivate::slotWidgetDestroyed(QObject *o)
{
KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( o );
Q_ASSERT( filter != 0 );
KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take(o);
Q_ASSERT(filter != nullptr);
filter->resetWidget(); // so that dtor doesn't access it
delete filter;
}

View file

@ -52,7 +52,7 @@ public:
* @param name the name of the cursor to try and load
* @param fallback the cursor to load if @p name cursor can not be loaded
*/
static QCursor fromName( const QString & name, Qt::CursorShape fallback = Qt::ArrowCursor );
static QCursor fromName(const QString &name, Qt::CursorShape fallback = Qt::ArrowCursor);
/**
* Sets auto-hiding the cursor for widget @p w. Enabling it will result in
@ -76,8 +76,8 @@ public:
* a QCanvasView, then you have to pass all key-events that should trigger
* auto-hiding to autoHideEventFilter().
*/
static void setAutoHideCursor( QWidget *w, bool enable,
bool customEventFilter = false );
static void setAutoHideCursor(QWidget *w, bool enable,
bool customEventFilter = false);
/**
* Sets the delay time in milliseconds for auto-hiding. When no keyboard
@ -85,7 +85,7 @@ public:
*
* Default is 5000, i.e. 5 seconds.
*/
static void setHideCursorDelay( int ms );
static void setHideCursorDelay(int ms);
/**
* @returns the current auto-hide delay time.
@ -104,13 +104,13 @@ public:
* to tell KCursor not to install an eventFilter. Then you call this method
* from the beginning of your eventFilter, for example:
* \code
* edit = new KEdit( this, "some edit widget" );
* edit->installEventFilter( this );
* KCursor::setAutoHideCursor( edit, true, true );
* edit = new KTextEdit(this, "some edit widget");
* edit->installEventFilter(this);
* KCursor::setAutoHideCursor(edit, true, true);
*
* [...]
*
* bool YourClass::eventFilter( QObject *o, QEvent *e )
* bool YourClass::eventFilter(QObject *o, QEvent *e )
* {
* if ( o == edit ) // only that widget where you enabled auto-hide!
* KCursor::autoHideEventFilter( o, e );
@ -123,7 +123,7 @@ public:
* Note that you must not call KCursor::autoHideEventFilter() when you
* didn't enable or after disabling auto-hiding.
*/
static void autoHideEventFilter( QObject *, QEvent * );
static void autoHideEventFilter(QObject *o, QEvent *e);
};

View file

@ -40,10 +40,10 @@ class KCursorPrivateAutoHideEventFilter : public QObject
Q_OBJECT
public:
KCursorPrivateAutoHideEventFilter( QWidget* widget );
KCursorPrivateAutoHideEventFilter(QWidget*widget);
~KCursorPrivateAutoHideEventFilter();
virtual bool eventFilter( QObject *o, QEvent *e );
virtual bool eventFilter(QObject *o, QEvent *e);
void resetWidget();
@ -75,14 +75,14 @@ class KCursorPrivate : public QObject
public:
static KCursorPrivate *self();
void setAutoHideCursor( QWidget *w, bool enable, bool customEventFilter );
virtual bool eventFilter( QObject *o, QEvent *e );
void setAutoHideCursor(QWidget *w, bool enable, bool customEventFilter);
virtual bool eventFilter(QObject *o, QEvent *e);
int hideCursorDelay;
private Q_SLOTS:
void slotViewportDestroyed(QObject *);
void slotWidgetDestroyed( QObject* );
void slotViewportDestroyed(QObject *o);
void slotWidgetDestroyed(QObject *o);
private:
KCursorPrivate();