File indexing completed on 2024-11-10 04:57:13
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2008 Cédric Borgese <cedric.borgese@gmail.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "wobblywindows.h" 0011 #include "effect/effecthandler.h" 0012 #include "wobblywindowsconfig.h" 0013 0014 #include <cmath> 0015 0016 //#define COMPUTE_STATS 0017 0018 // if you enable it and run kwin in a terminal from the session it manages, 0019 // be sure to redirect the output of kwin in a file or 0020 // you'll propably get deadlocks. 0021 //#define VERBOSE_MODE 0022 0023 #if defined COMPUTE_STATS && !defined VERBOSE_MODE 0024 #ifdef __GNUC__ 0025 #warning "You enable COMPUTE_STATS without VERBOSE_MODE, computed stats will not be printed." 0026 #endif 0027 #endif 0028 0029 Q_LOGGING_CATEGORY(KWIN_WOBBLYWINDOWS, "kwin_effect_wobblywindows", QtWarningMsg) 0030 0031 namespace KWin 0032 { 0033 0034 struct ParameterSet 0035 { 0036 qreal stiffness; 0037 qreal drag; 0038 qreal move_factor; 0039 0040 qreal xTesselation; 0041 qreal yTesselation; 0042 0043 qreal minVelocity; 0044 qreal maxVelocity; 0045 qreal stopVelocity; 0046 qreal minAcceleration; 0047 qreal maxAcceleration; 0048 qreal stopAcceleration; 0049 }; 0050 0051 static const ParameterSet set_0 = { 0052 0.15, 0053 0.80, 0054 0.10, 0055 20.0, 0056 20.0, 0057 0.0, 0058 1000.0, 0059 0.5, 0060 0.0, 0061 1000.0, 0062 0.5, 0063 }; 0064 0065 static const ParameterSet set_1 = { 0066 0.10, 0067 0.85, 0068 0.10, 0069 20.0, 0070 20.0, 0071 0.0, 0072 1000.0, 0073 0.5, 0074 0.0, 0075 1000.0, 0076 0.5, 0077 }; 0078 0079 static const ParameterSet set_2 = { 0080 0.06, 0081 0.90, 0082 0.10, 0083 20.0, 0084 20.0, 0085 0.0, 0086 1000.0, 0087 0.5, 0088 0.0, 0089 1000.0, 0090 0.5, 0091 }; 0092 0093 static const ParameterSet set_3 = { 0094 0.03, 0095 0.92, 0096 0.20, 0097 20.0, 0098 20.0, 0099 0.0, 0100 1000.0, 0101 0.5, 0102 0.0, 0103 1000.0, 0104 0.5, 0105 }; 0106 0107 static const ParameterSet set_4 = { 0108 0.01, 0109 0.97, 0110 0.25, 0111 20.0, 0112 20.0, 0113 0.0, 0114 1000.0, 0115 0.5, 0116 0.0, 0117 1000.0, 0118 0.5, 0119 }; 0120 0121 static const ParameterSet pset[5] = {set_0, set_1, set_2, set_3, set_4}; 0122 0123 WobblyWindowsEffect::WobblyWindowsEffect() 0124 { 0125 WobblyWindowsConfig::instance(effects->config()); 0126 reconfigure(ReconfigureAll); 0127 connect(effects, &EffectsHandler::windowAdded, this, &WobblyWindowsEffect::slotWindowAdded); 0128 0129 const auto windows = effects->stackingOrder(); 0130 for (EffectWindow *window : windows) { 0131 slotWindowAdded(window); 0132 } 0133 } 0134 0135 WobblyWindowsEffect::~WobblyWindowsEffect() 0136 { 0137 if (!windows.empty()) { 0138 // we should be empty at this point... 0139 qCDebug(KWIN_WOBBLYWINDOWS) << "Windows list not empty. Left items : " << windows.count(); 0140 } 0141 } 0142 0143 void WobblyWindowsEffect::reconfigure(ReconfigureFlags) 0144 { 0145 WobblyWindowsConfig::self()->read(); 0146 0147 QString settingsMode = WobblyWindowsConfig::settings(); 0148 if (settingsMode != QStringLiteral("Custom")) { 0149 unsigned int wobblynessLevel = WobblyWindowsConfig::wobblynessLevel(); 0150 if (wobblynessLevel > 4) { 0151 qCDebug(KWIN_WOBBLYWINDOWS) << "Wrong value for \"WobblynessLevel\" : " << wobblynessLevel; 0152 wobblynessLevel = 4; 0153 } 0154 setParameterSet(pset[wobblynessLevel]); 0155 0156 if (WobblyWindowsConfig::advancedMode()) { 0157 m_stiffness = WobblyWindowsConfig::stiffness() / 100.0; 0158 m_drag = WobblyWindowsConfig::drag() / 100.0; 0159 m_move_factor = WobblyWindowsConfig::moveFactor() / 100.0; 0160 } 0161 } else { // Custom method, read all values from config file. 0162 m_stiffness = WobblyWindowsConfig::stiffness() / 100.0; 0163 m_drag = WobblyWindowsConfig::drag() / 100.0; 0164 m_move_factor = WobblyWindowsConfig::moveFactor() / 100.0; 0165 0166 m_xTesselation = WobblyWindowsConfig::xTesselation(); 0167 m_yTesselation = WobblyWindowsConfig::yTesselation(); 0168 0169 m_minVelocity = WobblyWindowsConfig::minVelocity(); 0170 m_maxVelocity = WobblyWindowsConfig::maxVelocity(); 0171 m_stopVelocity = WobblyWindowsConfig::stopVelocity(); 0172 m_minAcceleration = WobblyWindowsConfig::minAcceleration(); 0173 m_maxAcceleration = WobblyWindowsConfig::maxAcceleration(); 0174 m_stopAcceleration = WobblyWindowsConfig::stopAcceleration(); 0175 } 0176 0177 m_moveWobble = WobblyWindowsConfig::moveWobble(); 0178 m_resizeWobble = WobblyWindowsConfig::resizeWobble(); 0179 0180 #if defined VERBOSE_MODE 0181 qCDebug(KWIN_WOBBLYWINDOWS) << "Parameters :\n" 0182 << "grid(" << m_stiffness << ", " << m_drag << ", " << m_move_factor << ")\n" 0183 << "velocity(" << m_minVelocity << ", " << m_maxVelocity << ", " << m_stopVelocity << ")\n" 0184 << "acceleration(" << m_minAcceleration << ", " << m_maxAcceleration << ", " << m_stopAcceleration << ")\n" 0185 << "tesselation(" << m_xTesselation << ", " << m_yTesselation << ")"; 0186 #endif 0187 } 0188 0189 bool WobblyWindowsEffect::supported() 0190 { 0191 return OffscreenEffect::supported() && effects->animationsSupported(); 0192 } 0193 0194 void WobblyWindowsEffect::setParameterSet(const ParameterSet &pset) 0195 { 0196 m_stiffness = pset.stiffness; 0197 m_drag = pset.drag; 0198 m_move_factor = pset.move_factor; 0199 0200 m_xTesselation = pset.xTesselation; 0201 m_yTesselation = pset.yTesselation; 0202 0203 m_minVelocity = pset.minVelocity; 0204 m_maxVelocity = pset.maxVelocity; 0205 m_stopVelocity = pset.stopVelocity; 0206 m_minAcceleration = pset.minAcceleration; 0207 m_maxAcceleration = pset.maxAcceleration; 0208 m_stopAcceleration = pset.stopAcceleration; 0209 } 0210 0211 void WobblyWindowsEffect::setVelocityThreshold(qreal m_minVelocity) 0212 { 0213 this->m_minVelocity = m_minVelocity; 0214 } 0215 0216 void WobblyWindowsEffect::setMoveFactor(qreal factor) 0217 { 0218 m_move_factor = factor; 0219 } 0220 0221 void WobblyWindowsEffect::setStiffness(qreal stiffness) 0222 { 0223 m_stiffness = stiffness; 0224 } 0225 0226 void WobblyWindowsEffect::setDrag(qreal drag) 0227 { 0228 m_drag = drag; 0229 } 0230 0231 void WobblyWindowsEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) 0232 { 0233 effects->prePaintScreen(data, presentTime); 0234 } 0235 0236 static const std::chrono::milliseconds integrationStep(10); 0237 0238 void WobblyWindowsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) 0239 { 0240 auto infoIt = windows.find(w); 0241 if (infoIt != windows.end()) { 0242 data.setTransformed(); 0243 0244 while ((presentTime - infoIt->clock).count() > 0) { 0245 const auto delta = std::min(presentTime - infoIt->clock, integrationStep); 0246 infoIt->clock += delta; 0247 0248 if (!updateWindowWobblyDatas(w, delta.count())) { 0249 break; 0250 } 0251 } 0252 } 0253 0254 effects->prePaintWindow(w, data, presentTime); 0255 } 0256 0257 void WobblyWindowsEffect::apply(EffectWindow *w, int mask, WindowPaintData &data, WindowQuadList &quads) 0258 { 0259 if (!(mask & PAINT_SCREEN_TRANSFORMED) && windows.contains(w)) { 0260 WindowWobblyInfos &wwi = windows[w]; 0261 if (!wwi.wobblying) { 0262 return; 0263 } 0264 0265 int tx = w->frameGeometry().x(); 0266 int ty = w->frameGeometry().y(); 0267 int width = w->frameGeometry().width(); 0268 int height = w->frameGeometry().height(); 0269 double left = 0.0; 0270 double top = 0.0; 0271 double right = w->width(); 0272 double bottom = w->height(); 0273 0274 quads = quads.makeRegularGrid(m_xTesselation, m_yTesselation); 0275 for (int i = 0; i < quads.count(); ++i) { 0276 for (int j = 0; j < 4; ++j) { 0277 WindowVertex &v = quads[i][j]; 0278 Pair uv = {v.x() / width, v.y() / height}; 0279 Pair newPos = computeBezierPoint(wwi, uv); 0280 v.move(newPos.x - tx, newPos.y - ty); 0281 } 0282 left = std::min(left, quads[i].left()); 0283 top = std::min(top, quads[i].top()); 0284 right = std::max(right, quads[i].right()); 0285 bottom = std::max(bottom, quads[i].bottom()); 0286 } 0287 QRectF dirtyRect( 0288 left * data.xScale() + w->x() + data.xTranslation(), 0289 top * data.yScale() + w->y() + data.yTranslation(), 0290 (right - left + 1.0) * data.xScale(), 0291 (bottom - top + 1.0) * data.yScale()); 0292 // Expand the dirty region by 1px to fix potential round/floor issues. 0293 dirtyRect.adjust(-1.0, -1.0, 1.0, 1.0); 0294 m_updateRegion = m_updateRegion.united(dirtyRect.toRect()); 0295 } 0296 } 0297 0298 void WobblyWindowsEffect::postPaintScreen() 0299 { 0300 if (!m_updateRegion.isEmpty()) { 0301 effects->addRepaint(m_updateRegion); 0302 m_updateRegion = QRegion(); 0303 } 0304 0305 // Call the next effect. 0306 effects->postPaintScreen(); 0307 } 0308 0309 void WobblyWindowsEffect::slotWindowAdded(EffectWindow *w) 0310 { 0311 connect(w, &EffectWindow::windowStartUserMovedResized, this, &WobblyWindowsEffect::slotWindowStartUserMovedResized); 0312 connect(w, &EffectWindow::windowStepUserMovedResized, this, &WobblyWindowsEffect::slotWindowStepUserMovedResized); 0313 connect(w, &EffectWindow::windowFinishUserMovedResized, this, &WobblyWindowsEffect::slotWindowFinishUserMovedResized); 0314 connect(w, &EffectWindow::windowMaximizedStateChanged, this, &WobblyWindowsEffect::slotWindowMaximizeStateChanged); 0315 } 0316 0317 void WobblyWindowsEffect::slotWindowStartUserMovedResized(EffectWindow *w) 0318 { 0319 if (w->isSpecialWindow()) { 0320 return; 0321 } 0322 0323 if ((w->isUserMove() && m_moveWobble) || (w->isUserResize() && m_resizeWobble)) { 0324 startMovedResized(w); 0325 } 0326 } 0327 0328 void WobblyWindowsEffect::slotWindowStepUserMovedResized(EffectWindow *w, const QRectF &geometry) 0329 { 0330 if (windows.contains(w)) { 0331 WindowWobblyInfos &wwi = windows[w]; 0332 const QRectF rect = w->frameGeometry(); 0333 if (rect.y() != wwi.resize_original_rect.y()) { 0334 wwi.can_wobble_top = true; 0335 } 0336 if (rect.x() != wwi.resize_original_rect.x()) { 0337 wwi.can_wobble_left = true; 0338 } 0339 if (rect.right() != wwi.resize_original_rect.right()) { 0340 wwi.can_wobble_right = true; 0341 } 0342 if (rect.bottom() != wwi.resize_original_rect.bottom()) { 0343 wwi.can_wobble_bottom = true; 0344 } 0345 setVertexSnappingMode(RenderGeometry::VertexSnappingMode::None); 0346 } 0347 } 0348 0349 void WobblyWindowsEffect::slotWindowFinishUserMovedResized(EffectWindow *w) 0350 { 0351 if (windows.contains(w)) { 0352 WindowWobblyInfos &wwi = windows[w]; 0353 wwi.status = Free; 0354 const QRectF rect = w->frameGeometry(); 0355 if (rect.y() != wwi.resize_original_rect.y()) { 0356 wwi.can_wobble_top = true; 0357 } 0358 if (rect.x() != wwi.resize_original_rect.x()) { 0359 wwi.can_wobble_left = true; 0360 } 0361 if (rect.right() != wwi.resize_original_rect.right()) { 0362 wwi.can_wobble_right = true; 0363 } 0364 if (rect.bottom() != wwi.resize_original_rect.bottom()) { 0365 wwi.can_wobble_bottom = true; 0366 } 0367 } 0368 } 0369 0370 void WobblyWindowsEffect::slotWindowMaximizeStateChanged(EffectWindow *w, bool horizontal, bool vertical) 0371 { 0372 if (w->isUserMove() || w->isSpecialWindow()) { 0373 return; 0374 } 0375 0376 if (m_moveWobble && m_resizeWobble) { 0377 stepMovedResized(w); 0378 } 0379 0380 if (windows.contains(w)) { 0381 WindowWobblyInfos &wwi = windows[w]; 0382 const QRectF rect = w->frameGeometry(); 0383 if (rect.y() != wwi.resize_original_rect.y()) { 0384 wwi.can_wobble_top = true; 0385 } 0386 if (rect.x() != wwi.resize_original_rect.x()) { 0387 wwi.can_wobble_left = true; 0388 } 0389 if (rect.right() != wwi.resize_original_rect.right()) { 0390 wwi.can_wobble_right = true; 0391 } 0392 if (rect.bottom() != wwi.resize_original_rect.bottom()) { 0393 wwi.can_wobble_bottom = true; 0394 } 0395 } 0396 } 0397 0398 void WobblyWindowsEffect::startMovedResized(EffectWindow *w) 0399 { 0400 if (!windows.contains(w)) { 0401 WindowWobblyInfos new_wwi; 0402 initWobblyInfo(new_wwi, w->frameGeometry()); 0403 windows[w] = new_wwi; 0404 redirect(w); 0405 } 0406 0407 WindowWobblyInfos &wwi = windows[w]; 0408 wwi.status = Moving; 0409 const QRectF &rect = w->frameGeometry(); 0410 0411 qreal x_increment = rect.width() / (wwi.width - 1.0); 0412 qreal y_increment = rect.height() / (wwi.height - 1.0); 0413 0414 Pair picked = {static_cast<qreal>(cursorPos().x()), static_cast<qreal>(cursorPos().y())}; 0415 int indx = (picked.x - rect.x()) / x_increment + 0.5; 0416 int indy = (picked.y - rect.y()) / y_increment + 0.5; 0417 int pickedPointIndex = indy * wwi.width + indx; 0418 if (pickedPointIndex < 0) { 0419 qCDebug(KWIN_WOBBLYWINDOWS) << "Picked index == " << pickedPointIndex << " with (" << cursorPos().x() << "," << cursorPos().y() << ")"; 0420 pickedPointIndex = 0; 0421 } else if (static_cast<unsigned int>(pickedPointIndex) > wwi.count - 1) { 0422 qCDebug(KWIN_WOBBLYWINDOWS) << "Picked index == " << pickedPointIndex << " with (" << cursorPos().x() << "," << cursorPos().y() << ")"; 0423 pickedPointIndex = wwi.count - 1; 0424 } 0425 #if defined VERBOSE_MODE 0426 qCDebug(KWIN_WOBBLYWINDOWS) << "Original Picked point -- x : " << picked.x << " - y : " << picked.y; 0427 #endif 0428 wwi.constraint[pickedPointIndex] = true; 0429 0430 if (w->isUserResize()) { 0431 // on a resize, do not allow any edges to wobble until it has been moved from 0432 // its original location 0433 wwi.can_wobble_top = wwi.can_wobble_left = wwi.can_wobble_right = wwi.can_wobble_bottom = false; 0434 wwi.resize_original_rect = w->frameGeometry(); 0435 } else { 0436 wwi.can_wobble_top = wwi.can_wobble_left = wwi.can_wobble_right = wwi.can_wobble_bottom = true; 0437 } 0438 } 0439 0440 void WobblyWindowsEffect::stepMovedResized(EffectWindow *w) 0441 { 0442 QRectF new_geometry = w->frameGeometry(); 0443 if (!windows.contains(w)) { 0444 WindowWobblyInfos new_wwi; 0445 initWobblyInfo(new_wwi, new_geometry); 0446 windows[w] = new_wwi; 0447 } 0448 0449 WindowWobblyInfos &wwi = windows[w]; 0450 wwi.status = Free; 0451 0452 QRectF maximized_area = effects->clientArea(MaximizeArea, w); 0453 bool throb_direction_out = (new_geometry.top() == maximized_area.top() && new_geometry.bottom() == maximized_area.bottom()) || (new_geometry.left() == maximized_area.left() && new_geometry.right() == maximized_area.right()); 0454 qreal magnitude = throb_direction_out ? 10 : -30; // a small throb out when maximized, a larger throb inwards when restored 0455 for (unsigned int j = 0; j < wwi.height; ++j) { 0456 for (unsigned int i = 0; i < wwi.width; ++i) { 0457 Pair v = {magnitude * (i / qreal(wwi.width - 1) - 0.5), magnitude * (j / qreal(wwi.height - 1) - 0.5)}; 0458 wwi.velocity[j * wwi.width + i] = v; 0459 } 0460 } 0461 0462 // constrain the middle of the window, so that any asymetry wont cause it to drift off-center 0463 for (unsigned int j = 1; j < wwi.height - 1; ++j) { 0464 for (unsigned int i = 1; i < wwi.width - 1; ++i) { 0465 wwi.constraint[j * wwi.width + i] = true; 0466 } 0467 } 0468 } 0469 0470 void WobblyWindowsEffect::initWobblyInfo(WindowWobblyInfos &wwi, QRectF geometry) const 0471 { 0472 wwi.count = 4 * 4; 0473 wwi.width = 4; 0474 wwi.height = 4; 0475 0476 wwi.bezierWidth = m_xTesselation; 0477 wwi.bezierHeight = m_yTesselation; 0478 wwi.bezierCount = m_xTesselation * m_yTesselation; 0479 0480 wwi.origin.resize(wwi.count); 0481 wwi.position.resize(wwi.count); 0482 wwi.velocity.resize(wwi.count); 0483 wwi.acceleration.resize(wwi.count); 0484 wwi.buffer.resize(wwi.count); 0485 wwi.constraint.resize(wwi.count); 0486 0487 wwi.bezierSurface.resize(wwi.bezierCount); 0488 0489 wwi.status = Moving; 0490 wwi.clock = std::chrono::duration_cast<std::chrono::milliseconds>( 0491 std::chrono::steady_clock::now().time_since_epoch()); 0492 0493 qreal x = geometry.x(), y = geometry.y(); 0494 qreal width = geometry.width(), height = geometry.height(); 0495 0496 Pair initValue = {x, y}; 0497 static const Pair nullPair = {0.0, 0.0}; 0498 0499 qreal x_increment = width / (wwi.width - 1.0); 0500 qreal y_increment = height / (wwi.height - 1.0); 0501 0502 for (unsigned int j = 0; j < 4; ++j) { 0503 for (unsigned int i = 0; i < 4; ++i) { 0504 unsigned int idx = j * 4 + i; 0505 wwi.origin[idx] = initValue; 0506 wwi.position[idx] = initValue; 0507 wwi.velocity[idx] = nullPair; 0508 wwi.constraint[idx] = false; 0509 if (i != 4 - 2) { // x grid count - 2, i.e. not the last point 0510 initValue.x += x_increment; 0511 } else { 0512 initValue.x = width + x; 0513 } 0514 initValue.x = initValue.x; 0515 } 0516 initValue.x = x; 0517 initValue.x = initValue.x; 0518 if (j != 4 - 2) { // y grid count - 2, i.e. not the last point 0519 initValue.y += y_increment; 0520 } else { 0521 initValue.y = height + y; 0522 } 0523 initValue.y = initValue.y; 0524 } 0525 } 0526 0527 WobblyWindowsEffect::Pair WobblyWindowsEffect::computeBezierPoint(const WindowWobblyInfos &wwi, Pair point) const 0528 { 0529 const qreal tx = point.x; 0530 const qreal ty = point.y; 0531 0532 // compute polynomial coeff 0533 0534 qreal px[4]; 0535 px[0] = (1 - tx) * (1 - tx) * (1 - tx); 0536 px[1] = 3 * (1 - tx) * (1 - tx) * tx; 0537 px[2] = 3 * (1 - tx) * tx * tx; 0538 px[3] = tx * tx * tx; 0539 0540 qreal py[4]; 0541 py[0] = (1 - ty) * (1 - ty) * (1 - ty); 0542 py[1] = 3 * (1 - ty) * (1 - ty) * ty; 0543 py[2] = 3 * (1 - ty) * ty * ty; 0544 py[3] = ty * ty * ty; 0545 0546 Pair res = {0.0, 0.0}; 0547 0548 for (unsigned int j = 0; j < 4; ++j) { 0549 for (unsigned int i = 0; i < 4; ++i) { 0550 // this assume the grid is 4*4 0551 res.x += px[i] * py[j] * wwi.position[i + j * wwi.width].x; 0552 res.y += px[i] * py[j] * wwi.position[i + j * wwi.width].y; 0553 } 0554 } 0555 0556 return res; 0557 } 0558 0559 namespace 0560 { 0561 0562 static inline void fixVectorBounds(WobblyWindowsEffect::Pair &vec, qreal min, qreal max) 0563 { 0564 if (fabs(vec.x) < min) { 0565 vec.x = 0.0; 0566 } else if (fabs(vec.x) > max) { 0567 if (vec.x > 0.0) { 0568 vec.x = max; 0569 } else { 0570 vec.x = -max; 0571 } 0572 } 0573 0574 if (fabs(vec.y) < min) { 0575 vec.y = 0.0; 0576 } else if (fabs(vec.y) > max) { 0577 if (vec.y > 0.0) { 0578 vec.y = max; 0579 } else { 0580 vec.y = -max; 0581 } 0582 } 0583 } 0584 0585 #if defined COMPUTE_STATS 0586 static inline void computeVectorBounds(WobblyWindowsEffect::Pair &vec, WobblyWindowsEffect::Pair &bound) 0587 { 0588 if (fabs(vec.x) < bound.x) { 0589 bound.x = fabs(vec.x); 0590 } else if (fabs(vec.x) > bound.y) { 0591 bound.y = fabs(vec.x); 0592 } 0593 if (fabs(vec.y) < bound.x) { 0594 bound.x = fabs(vec.y); 0595 } else if (fabs(vec.y) > bound.y) { 0596 bound.y = fabs(vec.y); 0597 } 0598 } 0599 #endif 0600 0601 } // close the anonymous namespace 0602 0603 bool WobblyWindowsEffect::updateWindowWobblyDatas(EffectWindow *w, qreal time) 0604 { 0605 QRectF rect = w->frameGeometry(); 0606 WindowWobblyInfos &wwi = windows[w]; 0607 0608 qreal x_length = rect.width() / (wwi.width - 1.0); 0609 qreal y_length = rect.height() / (wwi.height - 1.0); 0610 0611 #if defined VERBOSE_MODE 0612 qCDebug(KWIN_WOBBLYWINDOWS) << "time " << time; 0613 qCDebug(KWIN_WOBBLYWINDOWS) << "increment x " << x_length << " // y" << y_length; 0614 #endif 0615 0616 Pair origine = {rect.x(), rect.y()}; 0617 0618 for (unsigned int j = 0; j < wwi.height; ++j) { 0619 for (unsigned int i = 0; i < wwi.width; ++i) { 0620 wwi.origin[wwi.width * j + i] = origine; 0621 if (i != wwi.width - 2) { 0622 origine.x += x_length; 0623 } else { 0624 origine.x = rect.width() + rect.x(); 0625 } 0626 } 0627 origine.x = rect.x(); 0628 if (j != wwi.height - 2) { 0629 origine.y += y_length; 0630 } else { 0631 origine.y = rect.height() + rect.y(); 0632 } 0633 } 0634 0635 Pair neibourgs[4]; 0636 Pair acceleration; 0637 0638 qreal acc_sum = 0.0; 0639 qreal vel_sum = 0.0; 0640 0641 // compute acceleration, velocity and position for each point 0642 0643 // for corners 0644 0645 // top-left 0646 0647 if (wwi.constraint[0]) { 0648 Pair window_pos = wwi.origin[0]; 0649 Pair current_pos = wwi.position[0]; 0650 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0651 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0652 wwi.acceleration[0] = accel; 0653 } else { 0654 Pair &pos = wwi.position[0]; 0655 neibourgs[0] = wwi.position[1]; 0656 neibourgs[1] = wwi.position[wwi.width]; 0657 0658 acceleration.x = ((neibourgs[0].x - pos.x) - x_length) * m_stiffness + (neibourgs[1].x - pos.x) * m_stiffness; 0659 acceleration.y = ((neibourgs[1].y - pos.y) - y_length) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness; 0660 0661 acceleration.x /= 2; 0662 acceleration.y /= 2; 0663 0664 wwi.acceleration[0] = acceleration; 0665 } 0666 0667 // top-right 0668 0669 if (wwi.constraint[wwi.width - 1]) { 0670 Pair window_pos = wwi.origin[wwi.width - 1]; 0671 Pair current_pos = wwi.position[wwi.width - 1]; 0672 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0673 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0674 wwi.acceleration[wwi.width - 1] = accel; 0675 } else { 0676 Pair &pos = wwi.position[wwi.width - 1]; 0677 neibourgs[0] = wwi.position[wwi.width - 2]; 0678 neibourgs[1] = wwi.position[2 * wwi.width - 1]; 0679 0680 acceleration.x = (x_length - (pos.x - neibourgs[0].x)) * m_stiffness + (neibourgs[1].x - pos.x) * m_stiffness; 0681 acceleration.y = ((neibourgs[1].y - pos.y) - y_length) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness; 0682 0683 acceleration.x /= 2; 0684 acceleration.y /= 2; 0685 0686 wwi.acceleration[wwi.width - 1] = acceleration; 0687 } 0688 0689 // bottom-left 0690 0691 if (wwi.constraint[wwi.width * (wwi.height - 1)]) { 0692 Pair window_pos = wwi.origin[wwi.width * (wwi.height - 1)]; 0693 Pair current_pos = wwi.position[wwi.width * (wwi.height - 1)]; 0694 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0695 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0696 wwi.acceleration[wwi.width * (wwi.height - 1)] = accel; 0697 } else { 0698 Pair &pos = wwi.position[wwi.width * (wwi.height - 1)]; 0699 neibourgs[0] = wwi.position[wwi.width * (wwi.height - 1) + 1]; 0700 neibourgs[1] = wwi.position[wwi.width * (wwi.height - 2)]; 0701 0702 acceleration.x = ((neibourgs[0].x - pos.x) - x_length) * m_stiffness + (neibourgs[1].x - pos.x) * m_stiffness; 0703 acceleration.y = (y_length - (pos.y - neibourgs[1].y)) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness; 0704 0705 acceleration.x /= 2; 0706 acceleration.y /= 2; 0707 0708 wwi.acceleration[wwi.width * (wwi.height - 1)] = acceleration; 0709 } 0710 0711 // bottom-right 0712 0713 if (wwi.constraint[wwi.count - 1]) { 0714 Pair window_pos = wwi.origin[wwi.count - 1]; 0715 Pair current_pos = wwi.position[wwi.count - 1]; 0716 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0717 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0718 wwi.acceleration[wwi.count - 1] = accel; 0719 } else { 0720 Pair &pos = wwi.position[wwi.count - 1]; 0721 neibourgs[0] = wwi.position[wwi.count - 2]; 0722 neibourgs[1] = wwi.position[wwi.width * (wwi.height - 1) - 1]; 0723 0724 acceleration.x = (x_length - (pos.x - neibourgs[0].x)) * m_stiffness + (neibourgs[1].x - pos.x) * m_stiffness; 0725 acceleration.y = (y_length - (pos.y - neibourgs[1].y)) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness; 0726 0727 acceleration.x /= 2; 0728 acceleration.y /= 2; 0729 0730 wwi.acceleration[wwi.count - 1] = acceleration; 0731 } 0732 0733 // for borders 0734 0735 // top border 0736 for (unsigned int i = 1; i < wwi.width - 1; ++i) { 0737 if (wwi.constraint[i]) { 0738 Pair window_pos = wwi.origin[i]; 0739 Pair current_pos = wwi.position[i]; 0740 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0741 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0742 wwi.acceleration[i] = accel; 0743 } else { 0744 Pair &pos = wwi.position[i]; 0745 neibourgs[0] = wwi.position[i - 1]; 0746 neibourgs[1] = wwi.position[i + 1]; 0747 neibourgs[2] = wwi.position[i + wwi.width]; 0748 0749 acceleration.x = (x_length - (pos.x - neibourgs[0].x)) * m_stiffness + ((neibourgs[1].x - pos.x) - x_length) * m_stiffness + (neibourgs[2].x - pos.x) * m_stiffness; 0750 acceleration.y = ((neibourgs[2].y - pos.y) - y_length) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness + (neibourgs[1].y - pos.y) * m_stiffness; 0751 0752 acceleration.x /= 3; 0753 acceleration.y /= 3; 0754 0755 wwi.acceleration[i] = acceleration; 0756 } 0757 } 0758 0759 // bottom border 0760 for (unsigned int i = wwi.width * (wwi.height - 1) + 1; i < wwi.count - 1; ++i) { 0761 if (wwi.constraint[i]) { 0762 Pair window_pos = wwi.origin[i]; 0763 Pair current_pos = wwi.position[i]; 0764 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0765 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0766 wwi.acceleration[i] = accel; 0767 } else { 0768 Pair &pos = wwi.position[i]; 0769 neibourgs[0] = wwi.position[i - 1]; 0770 neibourgs[1] = wwi.position[i + 1]; 0771 neibourgs[2] = wwi.position[i - wwi.width]; 0772 0773 acceleration.x = (x_length - (pos.x - neibourgs[0].x)) * m_stiffness + ((neibourgs[1].x - pos.x) - x_length) * m_stiffness + (neibourgs[2].x - pos.x) * m_stiffness; 0774 acceleration.y = (y_length - (pos.y - neibourgs[2].y)) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness + (neibourgs[1].y - pos.y) * m_stiffness; 0775 0776 acceleration.x /= 3; 0777 acceleration.y /= 3; 0778 0779 wwi.acceleration[i] = acceleration; 0780 } 0781 } 0782 0783 // left border 0784 for (unsigned int i = wwi.width; i < wwi.width * (wwi.height - 1); i += wwi.width) { 0785 if (wwi.constraint[i]) { 0786 Pair window_pos = wwi.origin[i]; 0787 Pair current_pos = wwi.position[i]; 0788 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0789 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0790 wwi.acceleration[i] = accel; 0791 } else { 0792 Pair &pos = wwi.position[i]; 0793 neibourgs[0] = wwi.position[i + 1]; 0794 neibourgs[1] = wwi.position[i - wwi.width]; 0795 neibourgs[2] = wwi.position[i + wwi.width]; 0796 0797 acceleration.x = ((neibourgs[0].x - pos.x) - x_length) * m_stiffness + (neibourgs[1].x - pos.x) * m_stiffness + (neibourgs[2].x - pos.x) * m_stiffness; 0798 acceleration.y = (y_length - (pos.y - neibourgs[1].y)) * m_stiffness + ((neibourgs[2].y - pos.y) - y_length) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness; 0799 0800 acceleration.x /= 3; 0801 acceleration.y /= 3; 0802 0803 wwi.acceleration[i] = acceleration; 0804 } 0805 } 0806 0807 // right border 0808 for (unsigned int i = 2 * wwi.width - 1; i < wwi.count - 1; i += wwi.width) { 0809 if (wwi.constraint[i]) { 0810 Pair window_pos = wwi.origin[i]; 0811 Pair current_pos = wwi.position[i]; 0812 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0813 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0814 wwi.acceleration[i] = accel; 0815 } else { 0816 Pair &pos = wwi.position[i]; 0817 neibourgs[0] = wwi.position[i - 1]; 0818 neibourgs[1] = wwi.position[i - wwi.width]; 0819 neibourgs[2] = wwi.position[i + wwi.width]; 0820 0821 acceleration.x = (x_length - (pos.x - neibourgs[0].x)) * m_stiffness + (neibourgs[1].x - pos.x) * m_stiffness + (neibourgs[2].x - pos.x) * m_stiffness; 0822 acceleration.y = (y_length - (pos.y - neibourgs[1].y)) * m_stiffness + ((neibourgs[2].y - pos.y) - y_length) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness; 0823 0824 acceleration.x /= 3; 0825 acceleration.y /= 3; 0826 0827 wwi.acceleration[i] = acceleration; 0828 } 0829 } 0830 0831 // for the inner points 0832 for (unsigned int j = 1; j < wwi.height - 1; ++j) { 0833 for (unsigned int i = 1; i < wwi.width - 1; ++i) { 0834 unsigned int index = i + j * wwi.width; 0835 0836 if (wwi.constraint[index]) { 0837 Pair window_pos = wwi.origin[index]; 0838 Pair current_pos = wwi.position[index]; 0839 Pair move = {window_pos.x - current_pos.x, window_pos.y - current_pos.y}; 0840 Pair accel = {move.x * m_stiffness, move.y * m_stiffness}; 0841 wwi.acceleration[index] = accel; 0842 } else { 0843 Pair &pos = wwi.position[index]; 0844 neibourgs[0] = wwi.position[index - 1]; 0845 neibourgs[1] = wwi.position[index + 1]; 0846 neibourgs[2] = wwi.position[index - wwi.width]; 0847 neibourgs[3] = wwi.position[index + wwi.width]; 0848 0849 acceleration.x = ((neibourgs[0].x - pos.x) - x_length) * m_stiffness + (x_length - (pos.x - neibourgs[1].x)) * m_stiffness + (neibourgs[2].x - pos.x) * m_stiffness + (neibourgs[3].x - pos.x) * m_stiffness; 0850 acceleration.y = (y_length - (pos.y - neibourgs[2].y)) * m_stiffness + ((neibourgs[3].y - pos.y) - y_length) * m_stiffness + (neibourgs[0].y - pos.y) * m_stiffness + (neibourgs[1].y - pos.y) * m_stiffness; 0851 0852 acceleration.x /= 4; 0853 acceleration.y /= 4; 0854 0855 wwi.acceleration[index] = acceleration; 0856 } 0857 } 0858 } 0859 0860 heightRingLinearMean(wwi.acceleration, wwi); 0861 0862 #if defined COMPUTE_STATS 0863 Pair accBound = {m_maxAcceleration, m_minAcceleration}; 0864 Pair velBound = {m_maxVelocity, m_minVelocity}; 0865 #endif 0866 0867 // compute the new velocity of each vertex. 0868 for (unsigned int i = 0; i < wwi.count; ++i) { 0869 Pair acc = wwi.acceleration[i]; 0870 fixVectorBounds(acc, m_minAcceleration, m_maxAcceleration); 0871 0872 #if defined COMPUTE_STATS 0873 computeVectorBounds(acc, accBound); 0874 #endif 0875 0876 Pair &vel = wwi.velocity[i]; 0877 vel.x = acc.x * time + vel.x * m_drag; 0878 vel.y = acc.y * time + vel.y * m_drag; 0879 0880 acc_sum += fabs(acc.x) + fabs(acc.y); 0881 } 0882 0883 heightRingLinearMean(wwi.velocity, wwi); 0884 0885 // compute the new pos of each vertex. 0886 for (unsigned int i = 0; i < wwi.count; ++i) { 0887 Pair &pos = wwi.position[i]; 0888 Pair &vel = wwi.velocity[i]; 0889 0890 fixVectorBounds(vel, m_minVelocity, m_maxVelocity); 0891 #if defined COMPUTE_STATS 0892 computeVectorBounds(vel, velBound); 0893 #endif 0894 0895 pos.x += vel.x * time * m_move_factor; 0896 pos.y += vel.y * time * m_move_factor; 0897 0898 vel_sum += fabs(vel.x) + fabs(vel.y); 0899 0900 #if defined VERBOSE_MODE 0901 if (wwi.constraint[i]) { 0902 qCDebug(KWIN_WOBBLYWINDOWS) << "Constraint point ** vel : " << vel.x << "," << vel.y << " ** move : " << vel.x * time << "," << vel.y * time; 0903 } 0904 #endif 0905 } 0906 0907 if (!wwi.can_wobble_top) { 0908 for (unsigned int i = 0; i < wwi.width; ++i) { 0909 for (unsigned j = 0; j < wwi.width - 1; ++j) { 0910 wwi.position[i + wwi.width * j].y = wwi.origin[i + wwi.width * j].y; 0911 } 0912 } 0913 } 0914 if (!wwi.can_wobble_bottom) { 0915 for (unsigned int i = wwi.width * (wwi.height - 1); i < wwi.count; ++i) { 0916 for (unsigned j = 0; j < wwi.width - 1; ++j) { 0917 wwi.position[i - wwi.width * j].y = wwi.origin[i - wwi.width * j].y; 0918 } 0919 } 0920 } 0921 if (!wwi.can_wobble_left) { 0922 for (unsigned int i = 0; i < wwi.count; i += wwi.width) { 0923 for (unsigned j = 0; j < wwi.width - 1; ++j) { 0924 wwi.position[i + j].x = wwi.origin[i + j].x; 0925 } 0926 } 0927 } 0928 if (!wwi.can_wobble_right) { 0929 for (unsigned int i = wwi.width - 1; i < wwi.count; i += wwi.width) { 0930 for (unsigned j = 0; j < wwi.width - 1; ++j) { 0931 wwi.position[i - j].x = wwi.origin[i - j].x; 0932 } 0933 } 0934 } 0935 0936 #if defined VERBOSE_MODE 0937 #if defined COMPUTE_STATS 0938 qCDebug(KWIN_WOBBLYWINDOWS) << "Acceleration bounds (" << accBound.x << ", " << accBound.y << ")"; 0939 qCDebug(KWIN_WOBBLYWINDOWS) << "Velocity bounds (" << velBound.x << ", " << velBound.y << ")"; 0940 #endif 0941 qCDebug(KWIN_WOBBLYWINDOWS) << "sum_acc : " << acc_sum << " *** sum_vel :" << vel_sum; 0942 #endif 0943 0944 wwi.wobblying = !(acc_sum < m_stopAcceleration && vel_sum < m_stopVelocity); 0945 if (wwi.status != Moving && !wwi.wobblying) { 0946 windows.remove(w); 0947 unredirect(w); 0948 if (windows.isEmpty()) { 0949 effects->addRepaintFull(); 0950 } 0951 return false; 0952 } else if (!wwi.wobblying) { 0953 setVertexSnappingMode(RenderGeometry::VertexSnappingMode::Round); 0954 } 0955 0956 return true; 0957 } 0958 0959 void WobblyWindowsEffect::heightRingLinearMean(QList<Pair> &data, WindowWobblyInfos &wwi) 0960 { 0961 Pair neibourgs[8]; 0962 0963 // for corners 0964 0965 // top-left 0966 { 0967 Pair &res = wwi.buffer[0]; 0968 Pair vit = data[0]; 0969 neibourgs[0] = data[1]; 0970 neibourgs[1] = data[wwi.width]; 0971 neibourgs[2] = data[wwi.width + 1]; 0972 0973 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0 * vit.x) / 6.0; 0974 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0 * vit.y) / 6.0; 0975 } 0976 0977 // top-right 0978 { 0979 Pair &res = wwi.buffer[wwi.width - 1]; 0980 Pair vit = data[wwi.width - 1]; 0981 neibourgs[0] = data[wwi.width - 2]; 0982 neibourgs[1] = data[2 * wwi.width - 1]; 0983 neibourgs[2] = data[2 * wwi.width - 2]; 0984 0985 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0 * vit.x) / 6.0; 0986 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0 * vit.y) / 6.0; 0987 } 0988 0989 // bottom-left 0990 { 0991 Pair &res = wwi.buffer[wwi.width * (wwi.height - 1)]; 0992 Pair vit = data[wwi.width * (wwi.height - 1)]; 0993 neibourgs[0] = data[wwi.width * (wwi.height - 1) + 1]; 0994 neibourgs[1] = data[wwi.width * (wwi.height - 2)]; 0995 neibourgs[2] = data[wwi.width * (wwi.height - 2) + 1]; 0996 0997 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0 * vit.x) / 6.0; 0998 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0 * vit.y) / 6.0; 0999 } 1000 1001 // bottom-right 1002 { 1003 Pair &res = wwi.buffer[wwi.count - 1]; 1004 Pair vit = data[wwi.count - 1]; 1005 neibourgs[0] = data[wwi.count - 2]; 1006 neibourgs[1] = data[wwi.width * (wwi.height - 1) - 1]; 1007 neibourgs[2] = data[wwi.width * (wwi.height - 1) - 2]; 1008 1009 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + 3.0 * vit.x) / 6.0; 1010 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + 3.0 * vit.y) / 6.0; 1011 } 1012 1013 // for borders 1014 1015 // top border 1016 for (unsigned int i = 1; i < wwi.width - 1; ++i) { 1017 Pair &res = wwi.buffer[i]; 1018 Pair vit = data[i]; 1019 neibourgs[0] = data[i - 1]; 1020 neibourgs[1] = data[i + 1]; 1021 neibourgs[2] = data[i + wwi.width]; 1022 neibourgs[3] = data[i + wwi.width - 1]; 1023 neibourgs[4] = data[i + wwi.width + 1]; 1024 1025 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + neibourgs[3].x + neibourgs[4].x + 5.0 * vit.x) / 10.0; 1026 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + neibourgs[3].y + neibourgs[4].y + 5.0 * vit.y) / 10.0; 1027 } 1028 1029 // bottom border 1030 for (unsigned int i = wwi.width * (wwi.height - 1) + 1; i < wwi.count - 1; ++i) { 1031 Pair &res = wwi.buffer[i]; 1032 Pair vit = data[i]; 1033 neibourgs[0] = data[i - 1]; 1034 neibourgs[1] = data[i + 1]; 1035 neibourgs[2] = data[i - wwi.width]; 1036 neibourgs[3] = data[i - wwi.width - 1]; 1037 neibourgs[4] = data[i - wwi.width + 1]; 1038 1039 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + neibourgs[3].x + neibourgs[4].x + 5.0 * vit.x) / 10.0; 1040 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + neibourgs[3].y + neibourgs[4].y + 5.0 * vit.y) / 10.0; 1041 } 1042 1043 // left border 1044 for (unsigned int i = wwi.width; i < wwi.width * (wwi.height - 1); i += wwi.width) { 1045 Pair &res = wwi.buffer[i]; 1046 Pair vit = data[i]; 1047 neibourgs[0] = data[i + 1]; 1048 neibourgs[1] = data[i - wwi.width]; 1049 neibourgs[2] = data[i + wwi.width]; 1050 neibourgs[3] = data[i - wwi.width + 1]; 1051 neibourgs[4] = data[i + wwi.width + 1]; 1052 1053 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + neibourgs[3].x + neibourgs[4].x + 5.0 * vit.x) / 10.0; 1054 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + neibourgs[3].y + neibourgs[4].y + 5.0 * vit.y) / 10.0; 1055 } 1056 1057 // right border 1058 for (unsigned int i = 2 * wwi.width - 1; i < wwi.count - 1; i += wwi.width) { 1059 Pair &res = wwi.buffer[i]; 1060 Pair vit = data[i]; 1061 neibourgs[0] = data[i - 1]; 1062 neibourgs[1] = data[i - wwi.width]; 1063 neibourgs[2] = data[i + wwi.width]; 1064 neibourgs[3] = data[i - wwi.width - 1]; 1065 neibourgs[4] = data[i + wwi.width - 1]; 1066 1067 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + neibourgs[3].x + neibourgs[4].x + 5.0 * vit.x) / 10.0; 1068 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + neibourgs[3].y + neibourgs[4].y + 5.0 * vit.y) / 10.0; 1069 } 1070 1071 // for the inner points 1072 for (unsigned int j = 1; j < wwi.height - 1; ++j) { 1073 for (unsigned int i = 1; i < wwi.width - 1; ++i) { 1074 unsigned int index = i + j * wwi.width; 1075 1076 Pair &res = wwi.buffer[index]; 1077 Pair &vit = data[index]; 1078 neibourgs[0] = data[index - 1]; 1079 neibourgs[1] = data[index + 1]; 1080 neibourgs[2] = data[index - wwi.width]; 1081 neibourgs[3] = data[index + wwi.width]; 1082 neibourgs[4] = data[index - wwi.width - 1]; 1083 neibourgs[5] = data[index - wwi.width + 1]; 1084 neibourgs[6] = data[index + wwi.width - 1]; 1085 neibourgs[7] = data[index + wwi.width + 1]; 1086 1087 res.x = (neibourgs[0].x + neibourgs[1].x + neibourgs[2].x + neibourgs[3].x + neibourgs[4].x + neibourgs[5].x + neibourgs[6].x + neibourgs[7].x + 8.0 * vit.x) / 16.0; 1088 res.y = (neibourgs[0].y + neibourgs[1].y + neibourgs[2].y + neibourgs[3].y + neibourgs[4].y + neibourgs[5].y + neibourgs[6].y + neibourgs[7].y + 8.0 * vit.y) / 16.0; 1089 } 1090 } 1091 1092 auto tmp = data; 1093 data = wwi.buffer; 1094 wwi.buffer = tmp; 1095 } 1096 1097 bool WobblyWindowsEffect::isActive() const 1098 { 1099 return !windows.isEmpty(); 1100 } 1101 1102 qreal WobblyWindowsEffect::stiffness() const 1103 { 1104 return m_stiffness; 1105 } 1106 1107 qreal WobblyWindowsEffect::drag() const 1108 { 1109 return m_drag; 1110 } 1111 1112 qreal WobblyWindowsEffect::moveFactor() const 1113 { 1114 return m_move_factor; 1115 } 1116 1117 qreal WobblyWindowsEffect::xTesselation() const 1118 { 1119 return m_xTesselation; 1120 } 1121 1122 qreal WobblyWindowsEffect::yTesselation() const 1123 { 1124 return m_yTesselation; 1125 } 1126 1127 qreal WobblyWindowsEffect::minVelocity() const 1128 { 1129 return m_minVelocity; 1130 } 1131 1132 qreal WobblyWindowsEffect::maxVelocity() const 1133 { 1134 return m_maxVelocity; 1135 } 1136 1137 qreal WobblyWindowsEffect::stopVelocity() const 1138 { 1139 return m_stopVelocity; 1140 } 1141 1142 qreal WobblyWindowsEffect::minAcceleration() const 1143 { 1144 return m_minAcceleration; 1145 } 1146 1147 qreal WobblyWindowsEffect::maxAcceleration() const 1148 { 1149 return m_maxAcceleration; 1150 } 1151 1152 qreal WobblyWindowsEffect::stopAcceleration() const 1153 { 1154 return m_stopAcceleration; 1155 } 1156 1157 bool WobblyWindowsEffect::isMoveWobble() const 1158 { 1159 return m_moveWobble; 1160 } 1161 1162 bool WobblyWindowsEffect::isResizeWobble() const 1163 { 1164 return m_resizeWobble; 1165 } 1166 1167 } // namespace KWin 1168 1169 #include "moc_wobblywindows.cpp"