mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 10:22:48 +00:00
kdeui: new KPixmap class
very much written for use case, not to make sense. while porting to it I already noticed there are leaks for X11 pixmaps and may have to write glue code to keep track of the pixmaps and release them before application quits, that will be a huge performance penalty tho so may have to be ifdef'ed for debug builds only Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
43cf97b00d
commit
a5734faf0f
6 changed files with 281 additions and 54 deletions
|
@ -219,6 +219,7 @@ install(
|
|||
KPassivePopupMessageHandler
|
||||
KPasswordDialog
|
||||
KPasteTextAction
|
||||
KPixmap
|
||||
KPixmapRegionSelectorDialog
|
||||
KPixmapRegionSelectorWidget
|
||||
KPluginFactory
|
||||
|
|
1
includes/KPixmap
Normal file
1
includes/KPixmap
Normal file
|
@ -0,0 +1 @@
|
|||
#include "../kpixmap.h"
|
|
@ -189,6 +189,7 @@ set(kdeui_LIB_SRCS
|
|||
util/kxerrorhandler.cpp
|
||||
util/kxmessages.cpp
|
||||
util/kundostack.cpp
|
||||
util/kpixmap.cpp
|
||||
util/kpixmapsequence.cpp
|
||||
util/kpixmapsequenceoverlaypainter.cpp
|
||||
util/kpixmapsequencewidget.cpp
|
||||
|
@ -508,6 +509,7 @@ install(
|
|||
util/kxerrorhandler.h
|
||||
util/kxmessages.h
|
||||
util/kundostack.h
|
||||
util/kpixmap.h
|
||||
util/kpixmapsequence.h
|
||||
util/kpixmapsequenceoverlaypainter.h
|
||||
util/kpixmapsequencewidget.h
|
||||
|
|
169
kdeui/util/kpixmap.cpp
Normal file
169
kdeui/util/kpixmap.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* This file is part of the KDE libraries
|
||||
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2, as published by the Free Software Foundation.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <fixx11h.h>
|
||||
|
||||
#include "kpixmap.h"
|
||||
#include "kxerrorhandler.h"
|
||||
#include "kdebug.h"
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QPainter>
|
||||
|
||||
class KPixmapPrivate
|
||||
{
|
||||
public:
|
||||
KPixmapPrivate();
|
||||
|
||||
QSize size;
|
||||
Qt::HANDLE handle;
|
||||
};
|
||||
|
||||
KPixmapPrivate::KPixmapPrivate()
|
||||
: handle(XNone)
|
||||
{
|
||||
}
|
||||
|
||||
KPixmap::KPixmap()
|
||||
: d(new KPixmapPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
KPixmap::KPixmap(const Qt::HANDLE pixmap)
|
||||
: d(new KPixmapPrivate())
|
||||
{
|
||||
d->handle = pixmap;
|
||||
if (pixmap) {
|
||||
Window x11window;
|
||||
int x11x = 0;
|
||||
int x11y = 0;
|
||||
uint x11width = 0;
|
||||
uint x11height = 0;
|
||||
uint x11borderwidth = 0;
|
||||
uint x11depth = 0;
|
||||
KXErrorHandler kx11errorhandler;
|
||||
XGetGeometry(
|
||||
QX11Info::display(), pixmap,
|
||||
&x11window, &x11x, &x11y,
|
||||
&x11width, &x11height,
|
||||
&x11borderwidth, &x11depth
|
||||
);
|
||||
d->size = QSize(x11width, x11height);
|
||||
if (kx11errorhandler.error(true)) {
|
||||
kWarning() << KXErrorHandler::errorMessage(kx11errorhandler.errorEvent());
|
||||
// in the worst case the pixmap will be leaked
|
||||
d->handle = XNone;
|
||||
d->size = QSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KPixmap::KPixmap(const QPixmap &pixmap)
|
||||
: d(new KPixmapPrivate())
|
||||
{
|
||||
if (!pixmap.isNull()) {
|
||||
KXErrorHandler kx11errorhandler;
|
||||
d->handle = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), pixmap.width(), pixmap.height(), 32);
|
||||
if (kx11errorhandler.error(true)) {
|
||||
kWarning() << KXErrorHandler::errorMessage(kx11errorhandler.errorEvent());
|
||||
d->handle = XNone;
|
||||
return;
|
||||
}
|
||||
// TODO: optimize
|
||||
QPixmap tempPix = QPixmap::fromX11Pixmap(d->handle, QPixmap::ExplicitlyShared);
|
||||
tempPix.fill(Qt::transparent);
|
||||
QPainter p(&tempPix);
|
||||
p.drawPixmap(QPoint(0, 0), pixmap);
|
||||
p.end();
|
||||
d->size = pixmap.size();
|
||||
}
|
||||
}
|
||||
|
||||
KPixmap::KPixmap(const KPixmap &pixmap)
|
||||
: d(new KPixmapPrivate(*pixmap.d))
|
||||
{
|
||||
}
|
||||
|
||||
KPixmap::KPixmap(const QSize &size)
|
||||
: d(new KPixmapPrivate())
|
||||
{
|
||||
if (!size.isEmpty()) {
|
||||
KXErrorHandler kx11errorhandler;
|
||||
d->handle = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), size.width(), size.height(), 32);
|
||||
if (kx11errorhandler.error(true)) {
|
||||
kWarning() << KXErrorHandler::errorMessage(kx11errorhandler.errorEvent());
|
||||
d->handle = XNone;
|
||||
return;
|
||||
}
|
||||
d->size = size;
|
||||
GC x11gc = XCreateGC(QX11Info::display(), d->handle, 0, 0);
|
||||
XSetForeground(QX11Info::display(), x11gc, XBlackPixel(QX11Info::display(), QX11Info::appScreen()));
|
||||
XFillRectangle(QX11Info::display(), d->handle, x11gc, 0, 0, size.width(), size.height());
|
||||
XFreeGC(QX11Info::display(), x11gc);
|
||||
}
|
||||
}
|
||||
|
||||
KPixmap::~KPixmap()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool KPixmap::isNull() const
|
||||
{
|
||||
return (d->handle == XNone);
|
||||
}
|
||||
|
||||
QSize KPixmap::size() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
|
||||
Qt::HANDLE KPixmap::handle() const
|
||||
{
|
||||
return d->handle;
|
||||
}
|
||||
|
||||
void KPixmap::release()
|
||||
{
|
||||
if (d->handle == XNone) {
|
||||
kDebug() << "No handle";
|
||||
return;
|
||||
}
|
||||
// NOTE: catching errors here is done to not get fatal I/O
|
||||
KXErrorHandler kx11errorhandler;
|
||||
XFreePixmap(QX11Info::display(), d->handle);
|
||||
if (kx11errorhandler.error(true)) {
|
||||
kWarning() << KXErrorHandler::errorMessage(kx11errorhandler.errorEvent());
|
||||
}
|
||||
d->handle = XNone;
|
||||
d->size = QSize();
|
||||
}
|
||||
|
||||
QImage KPixmap::toImage() const
|
||||
{
|
||||
// TODO: optimize
|
||||
return QPixmap::fromX11Pixmap(d->handle).toImage();
|
||||
}
|
||||
|
||||
KPixmap& KPixmap::operator=(const KPixmap &other)
|
||||
{
|
||||
delete d;
|
||||
d = new KPixmapPrivate(*other.d);
|
||||
return *this;
|
||||
}
|
78
kdeui/util/kpixmap.h
Normal file
78
kdeui/util/kpixmap.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* This file is part of the KDE libraries
|
||||
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2, as published by the Free Software Foundation.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KPIXMAP_H
|
||||
#define KPIXMAP_H
|
||||
|
||||
#include <kdeui_export.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
|
||||
class KPixmapPrivate;
|
||||
|
||||
/*!
|
||||
Class to deal with X11 pixmaps.
|
||||
*/
|
||||
class KDEUI_EXPORT KPixmap
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
@brief Constructs null object.
|
||||
*/
|
||||
KPixmap();
|
||||
/*!
|
||||
@brief Constructs object from X11 pixmap @p pixmap, the @p pixmap is not deep-copied.
|
||||
*/
|
||||
KPixmap(const Qt::HANDLE pixmap);
|
||||
/*!
|
||||
@brief Constructs object from QPixmap @p pixmap, the @p pixmap is deep-copied and must be released.
|
||||
*/
|
||||
KPixmap(const QPixmap &pixmap);
|
||||
/*!
|
||||
@brief Constructs object from other KPixmap @p pixmap, the @p pixmap is not deep-copied.
|
||||
*/
|
||||
KPixmap(const KPixmap &pixmap);
|
||||
/*!
|
||||
@brief Constructs object for X11 pixmap with size @p size, the @p pixmap must be released.
|
||||
*/
|
||||
KPixmap(const QSize &size);
|
||||
~KPixmap();
|
||||
|
||||
bool isNull() const;
|
||||
QSize size() const;
|
||||
int width() const { return size().width(); }
|
||||
int height() const { return size().height(); }
|
||||
Qt::HANDLE handle() const;
|
||||
|
||||
/*!
|
||||
@brief Releases the X11 pixmap if not null.
|
||||
*/
|
||||
void release();
|
||||
/*!
|
||||
@brief Returns QImage copy of the X11 pixmap.
|
||||
*/
|
||||
QImage toImage() const;
|
||||
|
||||
KPixmap &operator=(const KPixmap &other);
|
||||
|
||||
private:
|
||||
KPixmapPrivate* d;
|
||||
};
|
||||
|
||||
#endif // KPIXMAP_H
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
|
||||
#include "dialogshadows.h"
|
||||
#include "kpixmap.h"
|
||||
#include "kdebug.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
|
@ -28,8 +30,6 @@
|
|||
#include <fixx11h.h>
|
||||
#endif
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
|
@ -43,8 +43,6 @@ public:
|
|||
|
||||
~DialogShadowsPrivate()
|
||||
{
|
||||
// Do not call clearPixmaps() from here: it creates new QPixmap(),
|
||||
// which causes a crash when application is stopping.
|
||||
freeX11Pixmaps();
|
||||
}
|
||||
|
||||
|
@ -52,7 +50,7 @@ public:
|
|||
void clearPixmaps();
|
||||
void setupPixmaps();
|
||||
void initPixmap(const QString &element);
|
||||
QPixmap initEmptyPixmap(const QSize &size);
|
||||
KPixmap initEmptyPixmap(const QSize &size);
|
||||
void updateShadow(const QWidget *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void clearShadow(const QWidget *window);
|
||||
void updateShadows();
|
||||
|
@ -60,15 +58,15 @@ public:
|
|||
void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders);
|
||||
|
||||
DialogShadows *q;
|
||||
QList<QPixmap> m_shadowPixmaps;
|
||||
QList<KPixmap> m_shadowPixmaps;
|
||||
|
||||
QPixmap m_emptyCornerPix;
|
||||
QPixmap m_emptyCornerLeftPix;
|
||||
QPixmap m_emptyCornerTopPix;
|
||||
QPixmap m_emptyCornerRightPix;
|
||||
QPixmap m_emptyCornerBottomPix;
|
||||
QPixmap m_emptyVerticalPix;
|
||||
QPixmap m_emptyHorizontalPix;
|
||||
KPixmap m_emptyCornerPix;
|
||||
KPixmap m_emptyCornerLeftPix;
|
||||
KPixmap m_emptyCornerTopPix;
|
||||
KPixmap m_emptyCornerRightPix;
|
||||
KPixmap m_emptyCornerBottomPix;
|
||||
KPixmap m_emptyVerticalPix;
|
||||
KPixmap m_emptyHorizontalPix;
|
||||
|
||||
QHash<Plasma::FrameSvg::EnabledBorders, QVector<unsigned long> > data;
|
||||
QHash<const QWidget *, Plasma::FrameSvg::EnabledBorders> m_windows;
|
||||
|
@ -135,34 +133,12 @@ void DialogShadowsPrivate::updateShadows()
|
|||
|
||||
void DialogShadowsPrivate::initPixmap(const QString &element)
|
||||
{
|
||||
#ifdef Q_WS_X11
|
||||
QPixmap pix = q->pixmap(element);
|
||||
QPixmap tempPix;
|
||||
if (!pix.isNull()) {
|
||||
Pixmap xPix = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), pix.width(), pix.height(), 32);
|
||||
tempPix = QPixmap::fromX11Pixmap(xPix, QPixmap::ExplicitlyShared);
|
||||
tempPix.fill(Qt::transparent);
|
||||
QPainter p(&tempPix);
|
||||
p.drawPixmap(QPoint(0, 0), pix);
|
||||
p.end();
|
||||
}
|
||||
m_shadowPixmaps << tempPix;
|
||||
#endif
|
||||
m_shadowPixmaps << KPixmap(q->pixmap(element));
|
||||
}
|
||||
|
||||
QPixmap DialogShadowsPrivate::initEmptyPixmap(const QSize &size)
|
||||
KPixmap DialogShadowsPrivate::initEmptyPixmap(const QSize &size)
|
||||
{
|
||||
#ifdef Q_WS_X11
|
||||
QPixmap tempEmptyPix;
|
||||
if (!size.isEmpty()) {
|
||||
Pixmap emptyXPix = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), size.width(), size.height(), 32);
|
||||
tempEmptyPix = QPixmap::fromX11Pixmap(emptyXPix, QPixmap::ExplicitlyShared);
|
||||
tempEmptyPix.fill(Qt::transparent);
|
||||
}
|
||||
return tempEmptyPix;
|
||||
#else
|
||||
return QPixmap();
|
||||
#endif
|
||||
return KPixmap(size);
|
||||
}
|
||||
|
||||
void DialogShadowsPrivate::setupPixmaps()
|
||||
|
@ -321,35 +297,35 @@ void DialogShadowsPrivate::setupData(Plasma::FrameSvg::EnabledBorders enabledBor
|
|||
void DialogShadowsPrivate::freeX11Pixmaps()
|
||||
{
|
||||
#ifdef Q_WS_X11
|
||||
foreach (const QPixmap &pixmap, m_shadowPixmaps) {
|
||||
foreach (KPixmap &pixmap, m_shadowPixmaps) {
|
||||
if (!QX11Info::display()) {
|
||||
return;
|
||||
}
|
||||
if (!pixmap.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), pixmap.handle());
|
||||
pixmap.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_emptyCornerPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyCornerPix.handle());
|
||||
m_emptyCornerPix.release();
|
||||
}
|
||||
if (!m_emptyCornerBottomPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyCornerBottomPix.handle());
|
||||
m_emptyCornerBottomPix.release();
|
||||
}
|
||||
if (!m_emptyCornerLeftPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyCornerLeftPix.handle());
|
||||
m_emptyCornerLeftPix.release();
|
||||
}
|
||||
if (!m_emptyCornerRightPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyCornerRightPix.handle());
|
||||
m_emptyCornerRightPix.release();
|
||||
}
|
||||
if (!m_emptyCornerTopPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyCornerTopPix.handle());
|
||||
m_emptyCornerTopPix.release();
|
||||
}
|
||||
if (!m_emptyVerticalPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyVerticalPix.handle());
|
||||
m_emptyVerticalPix.release();
|
||||
}
|
||||
if (!m_emptyHorizontalPix.isNull()) {
|
||||
XFreePixmap(QX11Info::display(), m_emptyHorizontalPix.handle());
|
||||
m_emptyHorizontalPix.release();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -359,13 +335,13 @@ void DialogShadowsPrivate::clearPixmaps()
|
|||
#ifdef Q_WS_X11
|
||||
freeX11Pixmaps();
|
||||
|
||||
m_emptyCornerPix = QPixmap();
|
||||
m_emptyCornerBottomPix = QPixmap();
|
||||
m_emptyCornerLeftPix = QPixmap();
|
||||
m_emptyCornerRightPix = QPixmap();
|
||||
m_emptyCornerTopPix = QPixmap();
|
||||
m_emptyVerticalPix = QPixmap();
|
||||
m_emptyHorizontalPix = QPixmap();
|
||||
m_emptyCornerPix = KPixmap();
|
||||
m_emptyCornerBottomPix = KPixmap();
|
||||
m_emptyCornerLeftPix = KPixmap();
|
||||
m_emptyCornerRightPix = KPixmap();
|
||||
m_emptyCornerTopPix = KPixmap();
|
||||
m_emptyVerticalPix = KPixmap();
|
||||
m_emptyHorizontalPix = KPixmap();
|
||||
#endif
|
||||
m_shadowPixmaps.clear();
|
||||
data.clear();
|
||||
|
|
Loading…
Add table
Reference in a new issue