port mouseclick to xcb using a tristrip

REVIEW: 108879
This commit is contained in:
Thomas Lübking 2013-02-08 18:02:26 +01:00
parent 839ac0ddeb
commit 06c725e685

View file

@ -26,7 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef KWIN_HAVE_XRENDER_COMPOSITING #ifdef KWIN_HAVE_XRENDER_COMPOSITING
#include <kwinxrenderutils.h> #include <kwinxrenderutils.h>
#include <QPainter> #include <xcb/xcb.h>
#include <xcb/render.h>
#endif #endif
#include <KDE/KAction> #include <KDE/KAction>
@ -41,10 +42,6 @@ namespace KWin
KWIN_EFFECT(mouseclick, MouseClickEffect) KWIN_EFFECT(mouseclick, MouseClickEffect)
KWIN_EFFECT_SUPPORTED(mouseclick, MouseClickEffect::supported()) KWIN_EFFECT_SUPPORTED(mouseclick, MouseClickEffect::supported())
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
static QPixmap s_XrBuffer;
#endif
MouseClickEffect::MouseClickEffect() MouseClickEffect::MouseClickEffect()
{ {
m_enabled = false; m_enabled = false;
@ -64,10 +61,6 @@ MouseClickEffect::MouseClickEffect()
MouseClickEffect::~MouseClickEffect() MouseClickEffect::~MouseClickEffect()
{ {
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if (!s_XrBuffer.isNull())
XFreePixmap(display(), s_XrBuffer.handle());
#endif
if (m_enabled) if (m_enabled)
effects->stopMousePolling(); effects->stopMousePolling();
foreach (const MouseEvent* click, m_clicks) { foreach (const MouseEvent* click, m_clicks) {
@ -316,29 +309,55 @@ void MouseClickEffect::drawCircleGl(const QColor& color, float cx, float cy, flo
void MouseClickEffect::drawCircleXr(const QColor& color, float cx, float cy, float r) void MouseClickEffect::drawCircleXr(const QColor& color, float cx, float cy, float r)
{ {
#ifdef KWIN_HAVE_XRENDER_COMPOSITING #ifdef KWIN_HAVE_XRENDER_COMPOSITING
const int bufferSize = qRound(1.41421356*(2*m_ringMaxSize + m_lineWidth)) | 1; if (r <= m_lineWidth)
if (bufferSize < 0) // should not happen, but we neither want to leak XPixmaps
return; return;
if (s_XrBuffer.size() != QSize(bufferSize, bufferSize)) {
if (!s_XrBuffer.isNull()) { int num_segments = r+8;
XFreePixmap(display(), s_XrBuffer.handle()); float theta = 2.0 * 3.1415926 / num_segments;
} float cos = cosf(theta); //precalculate the sine and cosine
Pixmap xpix = XCreatePixmap(display(), rootWindow(), bufferSize, bufferSize, 32); float sin = sinf(theta);
s_XrBuffer = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared); float x[2] = {r, r-m_lineWidth};
float y[2] = {0, 0};
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
QVector<xcb_render_pointfix_t> strip;
strip.reserve(2*num_segments+2);
xcb_render_pointfix_t point;
point.x = DOUBLE_TO_FIXED(x[1]+cx);
point.y = DOUBLE_TO_FIXED(y[1]+cy);
strip << point;
for (int i = 0; i < num_segments; ++i) {
//apply the rotation matrix
const float h[2] = {x[0], x[1]};
x[0] = cos * x[0] - sin * y[0];
x[1] = cos * x[1] - sin * y[1];
y[0] = sin * h[0] + cos * y[0];
y[1] = sin * h[1] + cos * y[1];
point.x = DOUBLE_TO_FIXED(x[0]+cx);
point.y = DOUBLE_TO_FIXED(y[0]+cy);
strip << point;
point.x = DOUBLE_TO_FIXED(x[1]+cx);
point.y = DOUBLE_TO_FIXED(y[1]+cy);
strip << point;
} }
s_XrBuffer.fill(Qt::transparent);
QRect rct(s_XrBuffer.rect()); const float h = x[0];
QPainter p(&s_XrBuffer); x[0] = cos * x[0] - sin * y[0];
p.setBrush(Qt::NoBrush); y[0] = sin * h + cos * y[0];
p.setPen(QPen(color, m_lineWidth));
p.setRenderHint(QPainter::Antialiasing); point.x = DOUBLE_TO_FIXED(x[0]+cx);
const int ir = qRound(r); point.y = DOUBLE_TO_FIXED(y[0]+cy);
p.drawEllipse(rct.center(), ir, ir); strip << point;
p.end();
rct.moveCenter(QPoint(qRound(cx), qRound(cy))); XRenderPicture fill = xRenderFill(color);
XRenderComposite( display(), PictOpOver, xcb_render_tri_strip(connection(), XCB_RENDER_PICT_OP_OVER,
s_XrBuffer.x11PictureHandle(), 0, effects->xrenderBufferPicture(), fill, effects->xrenderBufferPicture(), 0,
0, 0, 0, 0, rct.x(), rct.y(), rct.width(), rct.height() ); 0, 0, strip.count(), strip.constData());
#undef DOUBLE_TO_FIXED
#endif #endif
} }