/*! * */ void TEDisplayEpson::showText(const QString & text, const QString & category, const QString & mode) { SEffect eff; if (mode=="scroll-left" || mode.left(2)=="sl") eff=se_scrollleft; else if (mode=="scroll-right" || mode.left(2)=="sr") eff=se_scrollright; else if (mode.left(1)=="w") eff=se_wobble; else eff=se_scrollleft; if (category=="line2") { l2=EString(text,displayWidth()); l2.setEffect(eff); } else if (category=="full") { l1=EString(text,displayWidth()*2); l1.setEffect(eff); } else { l1=EString(text,displayWidth()); l1.setEffect(eff); } };
void LogoutEffect::reconfigure( ReconfigureFlags ) { // Disable blur by default as some drivers don't correctly fallback if they don't // support it and I have yet to work out a way of accurately detecting support. KConfigGroup conf = effects->effectConfig( "Logout" ); bool useBlur = conf.readEntry( "UseBlur", false ); #ifdef KWIN_HAVE_OPENGL_COMPOSITING blurSupported = false; blurTexture = NULL; blurTarget = NULL; if( effects->compositingType() == OpenGLCompositing && GLTexture::NPOTTextureSupported() && useBlur ) { // TODO: It seems that it is not possible to create a GLRenderTarget that has // a different size than the display right now. Most likely a KWin core bug. // Create texture and render target blurTexture = new GLTexture( displayWidth(), displayHeight() ); blurTexture->setFilter( GL_LINEAR_MIPMAP_LINEAR ); blurTexture->setWrapMode( GL_CLAMP_TO_EDGE ); blurTarget = new GLRenderTarget( blurTexture ); if( blurTarget->valid() ) blurSupported = true; } #endif }
bool GlxBackend::initBuffer() { if (!initFbConfig()) return false; if (overlayWindow()->create()) { // Try to create double-buffered window in the overlay XVisualInfo* visual = glXGetVisualFromFBConfig(display(), fbconfig); if (!visual) { qCritical() << "Failed to get visual from fbconfig"; return false; } XSetWindowAttributes attrs; attrs.colormap = XCreateColormap(display(), rootWindow(), visual->visual, AllocNone); window = XCreateWindow(display(), overlayWindow()->window(), 0, 0, displayWidth(), displayHeight(), 0, visual->depth, InputOutput, visual->visual, CWColormap, &attrs); glxWindow = glXCreateWindow(display(), fbconfig, window, NULL); overlayWindow()->setup(window); XFree(visual); } else { qCritical() << "Failed to create overlay window"; return false; } int vis_buffer; glXGetFBConfigAttrib(display(), fbconfig, GLX_VISUAL_ID, &vis_buffer); XVisualInfo* visinfo_buffer = glXGetVisualFromFBConfig(display(), fbconfig); qDebug() << "Buffer visual (depth " << visinfo_buffer->depth << "): 0x" << QString::number(vis_buffer, 16); XFree(visinfo_buffer); return true; }
void VideoRecordEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) { effects->paintScreen( mask, region, data ); if( client != NULL ) capture_region = ( mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED )) ? QRect( 0, 0, displayWidth(), displayHeight()) : region; }
void ScreenEdge::switchDesktop(ElectricBorder border, const QPoint& _pos) { QPoint pos = _pos; int desk = Workspace::self()->currentDesktop(); const int OFFSET = 2; if (border == ElectricLeft || border == ElectricTopLeft || border == ElectricBottomLeft) { desk = Workspace::self()->desktopToLeft(desk, options->isRollOverDesktops()); pos.setX(displayWidth() - 1 - OFFSET); } if (border == ElectricRight || border == ElectricTopRight || border == ElectricBottomRight) { desk = Workspace::self()->desktopToRight(desk, options->isRollOverDesktops()); pos.setX(OFFSET); } if (border == ElectricTop || border == ElectricTopLeft || border == ElectricTopRight) { desk = Workspace::self()->desktopAbove(desk, options->isRollOverDesktops()); pos.setY(displayHeight() - 1 - OFFSET); } if (border == ElectricBottom || border == ElectricBottomLeft || border == ElectricBottomRight) { desk = Workspace::self()->desktopBelow(desk, options->isRollOverDesktops()); pos.setY(OFFSET); } Client *c = Workspace::self()->getMovingClient(); if (c && c->rules()->checkDesktop(desk) != desk) return; // user attempts to move a client to another desktop where it is ruleforced to not be int desk_before = Workspace::self()->currentDesktop(); Workspace::self()->setCurrentDesktop(desk); if (Workspace::self()->currentDesktop() != desk_before) QCursor::setPos(pos); }
// Create the compositing buffer. The root window is not double-buffered, // so it is done manually using this buffer, void SceneXrender::createBuffer() { if (buffer != None) XRenderFreePicture(display(), buffer); Pixmap pixmap = XCreatePixmap(display(), rootWindow(), displayWidth(), displayHeight(), DefaultDepth(display(), DefaultScreen(display()))); buffer = XRenderCreatePicture(display(), pixmap, format, 0, 0); XFreePixmap(display(), pixmap); // The picture owns the pixmap now }
void X11XRenderBackend::createBuffer() { xcb_pixmap_t pixmap = xcb_generate_id(connection()); xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displayWidth(), displayHeight()); xcb_render_picture_t b = xcb_generate_id(connection()); xcb_render_create_picture(connection(), b, pixmap, m_format, 0, NULL); xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now setBuffer(b); }
// Create the compositing buffer. The root window is not double-buffered, // so it is done manually using this buffer, void SceneXrender::createBuffer() { if (buffer != XCB_RENDER_PICTURE_NONE) xcb_render_free_picture(connection(), buffer); xcb_pixmap_t pixmap = xcb_generate_id(connection()); xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displayWidth(), displayHeight()); buffer = xcb_generate_id(connection()); xcb_render_create_picture(connection(), buffer, pixmap, format, 0, NULL); xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now }
void X11XRenderBackend::present(int mask, const QRegion &damage) { if (mask & Scene::PAINT_SCREEN_REGION) { // Use the damage region as the clip region for the root window XFixesRegion frontRegion(damage); xcb_xfixes_set_picture_clip_region(connection(), m_front, frontRegion, 0, 0); // copy composed buffer to the root window xcb_xfixes_set_picture_clip_region(connection(), buffer(), XCB_XFIXES_REGION_NONE, 0, 0); xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE, m_front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight()); xcb_xfixes_set_picture_clip_region(connection(), m_front, XCB_XFIXES_REGION_NONE, 0, 0); xcb_flush(connection()); } else { // copy composed buffer to the root window xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE, m_front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight()); xcb_flush(connection()); } }
VideoRecordEffect::VideoRecordEffect() : client( NULL ) { KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = static_cast< KAction* >( actionCollection->addAction( "VideoRecord" )); a->setText( i18n("Toggle Video Recording" )); a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_V )); connect( a, SIGNAL( triggered( bool )), this, SLOT( toggleRecording())); area = QRect( 0, 0, displayWidth(), displayHeight()); }
// create destination buffer bool SceneOpenGL::initBuffer() { if (!initBufferConfigs()) return false; if (fbcbuffer_db != NULL && m_overlayWindow->create()) { // we have overlay, try to create double-buffered window in it fbcbuffer = fbcbuffer_db; XVisualInfo* visual = glXGetVisualFromFBConfig(display(), fbcbuffer); XSetWindowAttributes attrs; attrs.colormap = XCreateColormap(display(), rootWindow(), visual->visual, AllocNone); buffer = XCreateWindow(display(), m_overlayWindow->window(), 0, 0, displayWidth(), displayHeight(), 0, visual->depth, InputOutput, visual->visual, CWColormap, &attrs); if (hasGLXVersion(1, 3)) glxbuffer = glXCreateWindow(display(), fbcbuffer, buffer, NULL); else glxbuffer = buffer; m_overlayWindow->setup(buffer); db = true; XFree(visual); } else if (fbcbuffer_nondb != NULL) { // cannot get any double-buffered drawable, will double-buffer using a pixmap fbcbuffer = fbcbuffer_nondb; XVisualInfo* visual = glXGetVisualFromFBConfig(display(), fbcbuffer); XGCValues gcattr; gcattr.subwindow_mode = IncludeInferiors; gcroot = XCreateGC(display(), rootWindow(), GCSubwindowMode, &gcattr); buffer = XCreatePixmap(display(), rootWindow(), displayWidth(), displayHeight(), visual->depth); glxbuffer = glXCreatePixmap(display(), fbcbuffer, buffer, NULL); db = false; XFree(visual); } else { kError(1212) << "Couldn't create output buffer (failed to create overlay window?) !"; return false; // error } int vis_buffer; glXGetFBConfigAttrib(display(), fbcbuffer, GLX_VISUAL_ID, &vis_buffer); XVisualInfo* visinfo_buffer = glXGetVisualFromFBConfig(display(), fbcbuffer); kDebug(1212) << "Buffer visual (depth " << visinfo_buffer->depth << "): 0x" << QString::number(vis_buffer, 16); XFree(visinfo_buffer); return true; }
/*! * */ void TEDisplayEpson::updateDisplay() { l1.update(); l2.update(); char gohome[1]={0x0b}; writeBlockSlow(gohome,1); writeBlockSlow( utf8ToDevice( l1.current() ).data(), l1.width() ); if(l1.width()==displayWidth()) // if first line is not in fullscreen mode writeBlockSlow( utf8ToDevice( l2.current() ).data(), l2.width() ); };
void LogoutEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) { effects->paintScreen( mask, region, data ); #ifdef KWIN_HAVE_OPENGL_COMPOSITING if( blurSupported && progress > 0.0 ) { assert( effects->popRenderTarget() == blurTarget ); // Render the blurred scene blurTexture->bind(); GLfloat bias[1]; glGetTexEnvfv( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, bias ); glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, progress * 2.75 ); glBegin( GL_QUADS ); glTexCoord2f( 0.0, 0.0 ); glVertex2f( 0.0, displayHeight() ); glTexCoord2f( 1.0, 0.0 ); glVertex2f( displayWidth(), displayHeight() ); glTexCoord2f( 1.0, 1.0 ); glVertex2f( displayWidth(), 0.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex2f( 0.0, 0.0 ); glEnd(); glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, bias[0] ); blurTexture->unbind(); // Render the logout window if( logoutWindow ) { int winMask = logoutWindow->hasAlpha() ? PAINT_WINDOW_TRANSLUCENT : PAINT_WINDOW_OPAQUE; WindowPaintData winData( logoutWindow ); winData.opacity = windowOpacity; effects->drawWindow( logoutWindow, winMask, region, winData ); } } #endif }
void EglOnXBackend::present() { if (lastDamage().isEmpty()) return; const QRegion displayRegion(0, 0, displayWidth(), displayHeight()); const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); if (fullRepaint || !surfaceHasSubPost) { if (gs_tripleBufferNeedsDetection) { eglWaitGL(); m_swapProfiler.begin(); } // the entire screen changed, or we cannot do partial updates (which implies we enabled surface preservation) eglSwapBuffers(dpy, surface); if (gs_tripleBufferNeedsDetection) { eglWaitGL(); if (char result = m_swapProfiler.end()) { gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false; if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) { // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) { options->setGlPreferBufferSwap(0); eglSwapInterval(dpy, 0); qWarning() << "\nIt seems you are using the nvidia driver without triple buffering\n" "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n" "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n" "For this reason, the tearing prevention has been disabled.\n" "See https://bugs.kde.org/show_bug.cgi?id=322060\n"; } } setBlocksForRetrace(result == 'd'); } } if (supportsBufferAge()) { eglQuerySurface(dpy, surface, EGL_BUFFER_AGE_EXT, &m_bufferAge); } } else { // a part of the screen changed, and we can use eglPostSubBufferNV to copy the updated area foreach (const QRect & r, lastDamage().rects()) { eglPostSubBufferNV(dpy, surface, r.left(), displayHeight() - r.bottom() - 1, r.width(), r.height()); } } setLastDamage(QRegion()); if (!supportsBufferAge()) { eglWaitGL(); xcb_flush(connection()); } }
void GlxBackend::present() { if (lastDamage().isEmpty()) return; const QRegion displayRegion(0, 0, displayWidth(), displayHeight()); const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); if (fullRepaint) { if (haveSwapInterval) { if (gs_tripleBufferNeedsDetection) { glXWaitGL(); m_swapProfiler.begin(); } glXSwapBuffers(display(), glxWindow); if (gs_tripleBufferNeedsDetection) { glXWaitGL(); if (char result = m_swapProfiler.end()) { gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false; if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) { // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) { options->setGlPreferBufferSwap(0); setSwapInterval(0); qWarning() << "\nIt seems you are using the nvidia driver without triple buffering\n" "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n" "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n" "For this reason, the tearing prevention has been disabled.\n" "See https://bugs.kde.org/show_bug.cgi?id=322060\n"; } } setBlocksForRetrace(result == 'd'); } } } else { waitSync(); glXSwapBuffers(display(), glxWindow); } if (supportsBufferAge()) { glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); } } else if (glXCopySubBuffer) { foreach (const QRect & r, lastDamage().rects()) { // convert to OpenGL coordinates int y = displayHeight() - r.y() - r.height(); glXCopySubBuffer(display(), glxWindow, r.x(), y, r.width(), r.height()); } } else { // Copy Pixels (horribly slow on Mesa)
void ScreenEdge::update(bool force) { m_screenEdgeTimeFirst = xTime(); m_screenEdgeTimeLast = xTime(); m_screenEdgeTimeLastTrigger = xTime(); m_currentScreenEdge = ElectricNone; QRect r = QRect(0, 0, displayWidth(), displayHeight()); m_screenEdgeTop = r.top(); m_screenEdgeBottom = r.bottom(); m_screenEdgeLeft = r.left(); m_screenEdgeRight = r.right(); for (int pos = 0; pos < ELECTRIC_COUNT; ++pos) { if (force || m_screenEdgeReserved[pos] == 0) { if (m_screenEdgeWindows[pos] != None) XDestroyWindow(display(), m_screenEdgeWindows[pos]); m_screenEdgeWindows[pos] = None; } if (m_screenEdgeReserved[pos] == 0) { continue; } if (m_screenEdgeWindows[pos] != None) continue; XSetWindowAttributes attributes; attributes.override_redirect = True; attributes.event_mask = EnterWindowMask | LeaveWindowMask; unsigned long valuemask = CWOverrideRedirect | CWEventMask; int xywh[ELECTRIC_COUNT][4] = { { r.left() + 1, r.top(), r.width() - 2, 1 }, // Top { r.right(), r.top(), 1, 1 }, // Top-right { r.right(), r.top() + 1, 1, r.height() - 2 }, // Etc. { r.right(), r.bottom(), 1, 1 }, { r.left() + 1, r.bottom(), r.width() - 2, 1 }, { r.left(), r.bottom(), 1, 1 }, { r.left(), r.top() + 1, 1, r.height() - 2 }, { r.left(), r.top(), 1, 1 } }; m_screenEdgeWindows[pos] = XCreateWindow(display(), rootWindow(), xywh[pos][0], xywh[pos][1], xywh[pos][2], xywh[pos][3], 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes); XMapWindow(display(), m_screenEdgeWindows[pos]); // Set XdndAware on the windows, so that DND enter events are received (#86998) Atom version = 4; // XDND version XChangeProperty(display(), m_screenEdgeWindows[pos], atoms->xdnd_aware, XA_ATOM, 32, PropModeReplace, (unsigned char*)(&version), 1); } }
void LogoutEffect::prePaintScreen(ScreenPrePaintData& data, int time) { if (!displayEffect && progress == 0.0) { if (blurTexture) { delete blurTexture; blurTexture = NULL; delete blurTarget; blurTarget = NULL; blurSupported = false; } } else if (!blurTexture) { blurSupported = false; delete blurTarget; // catch as we just tested the texture ;-P if (effects->compositingType() == OpenGLCompositing && GLTexture::NPOTTextureSupported() && GLRenderTarget::blitSupported() && useBlur) { // TODO: It seems that it is not possible to create a GLRenderTarget that has // a different size than the display right now. Most likely a KWin core bug. // Create texture and render target blurTexture = new GLTexture(displayWidth(), displayHeight()); blurTexture->setFilter(GL_LINEAR_MIPMAP_LINEAR); blurTexture->setWrapMode(GL_CLAMP_TO_EDGE); blurTarget = new GLRenderTarget(*blurTexture); if (blurTarget->valid()) blurSupported = true; // As creating the render target takes time it can cause the first two frames of the // blur animation to be jerky. For this reason we only start the animation after the // third frame. frameDelay = 2; } } if (frameDelay) --frameDelay; else { if (displayEffect) progress = qMin(1.0, progress + time / animationTime(2000.0)); else if (progress > 0.0) progress = qMax(0.0, progress - time / animationTime(500.0)); } if (blurSupported && progress > 0.0) { data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; } effects->prePaintScreen(data, time); }
void ScreenEdge::restoreSize(ElectricBorder border) { if (m_screenEdgeWindows[border] == None) return; QRect r(0, 0, displayWidth(), displayHeight()); int xywh[ELECTRIC_COUNT][4] = { { r.left() + 1, r.top(), r.width() - 2, 1 }, // Top { r.right(), r.top(), 1, 1 }, // Top-right { r.right(), r.top() + 1, 1, r.height() - 2 }, // Etc. { r.right(), r.bottom(), 1, 1 }, { r.left() + 1, r.bottom(), r.width() - 2, 1 }, { r.left(), r.bottom(), 1, 1 }, { r.left(), r.top() + 1, 1, r.height() - 2 }, { r.left(), r.top(), 1, 1 } }; XMoveResizeWindow(display(), m_screenEdgeWindows[border], xywh[border][0], xywh[border][1], xywh[border][2], xywh[border][3]); }
void LanczosFilter::updateOffscreenSurfaces() { int w = displayWidth(); int h = displayHeight(); if (!GLTexture::NPOTTextureSupported()) { w = nearestPowerOfTwo(w); h = nearestPowerOfTwo(h); } if (!m_offscreenTex || m_offscreenTex->width() != w || m_offscreenTex->height() != h) { if (m_offscreenTex) { delete m_offscreenTex; delete m_offscreenTarget; } m_offscreenTex = new GLTexture(w, h); m_offscreenTex->setFilter(GL_LINEAR); m_offscreenTex->setWrapMode(GL_CLAMP_TO_EDGE); m_offscreenTarget = new GLRenderTarget(*m_offscreenTex); } }
void VideoRecordEffect::postPaintScreen() { effects->postPaintScreen(); if( client != NULL ) { #if 1 if( CapturyProcessRegionStart( client ) == CAPTURY_SUCCESS ) { capture_region &= QRect( 0, 0, displayWidth(), displayHeight()); // limit to screen foreach( const QRect &r, capture_region.rects()) { int gly = displayHeight() - r.y() - r.height(); // opengl coords CapturyProcessRegion( client, r.x(), gly, r.width(), r.height()); } CapturyProcessRegionCommit( client ); } #else CapturyProcessFrame( client ); #endif }
void SceneOpenGL::setupModelViewProjectionMatrix() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); float fovy = 60.0f; float aspect = 1.0f; float zNear = 0.1f; float zFar = 100.0f; float ymax = zNear * tan(fovy * M_PI / 360.0f); float ymin = -ymax; float xmin = ymin * aspect; float xmax = ymax * aspect; // swap top and bottom to have OpenGL coordinate system match X system glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float scaleFactor = 1.1 * tan(fovy * M_PI / 360.0f) / ymax; glTranslatef(xmin * scaleFactor, ymax * scaleFactor, -1.1); glScalef((xmax - xmin)*scaleFactor / displayWidth(), -(ymax - ymin)*scaleFactor / displayHeight(), 0.001); m_resetModelViewProjectionMatrix = false; }
void MinimizeAnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { if( mTimeLineWindows.contains( w )) { // 0 = not minimized, 1 = fully minimized double progress = mTimeLineWindows[w].value(); QRect geo = w->geometry(); QRect icon = w->iconGeometry(); // If there's no icon geometry, minimize to the center of the screen if( !icon.isValid() ) icon = QRect( displayWidth() / 2, displayHeight() / 2, 0, 0 ); data.xScale *= interpolate(1.0, icon.width() / (double)geo.width(), progress); data.yScale *= interpolate(1.0, icon.height() / (double)geo.height(), progress); data.xTranslate = (int)interpolate(data.xTranslate, icon.x() - geo.x(), progress); data.yTranslate = (int)interpolate(data.yTranslate, icon.y() - geo.y(), progress); data.opacity *= 0.1 + (1-progress)*0.9; } // Call the next effect. effects->paintWindow( w, mask, region, data ); }
void SlideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) { if( mTimeLine.value() == 0 ) { effects->paintScreen( mask, region, data ); return; } /* Transformations are done by remembering starting position of the change and the progress of it, the destination is computed from the current desktop. Positions of desktops are done using their topleft corner. */ QPoint destPos = desktopRect( effects->currentDesktop() ).topLeft(); QPoint diffPos = destPos - slide_start_pos; int w = 0; int h = 0; if( effects->optionRollOverDesktops()) { w = effects->workspaceWidth(); h = effects->workspaceHeight(); // wrap around if shorter if( diffPos.x() > 0 && diffPos.x() > w / 2 ) diffPos.setX( diffPos.x() - w ); if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 ) diffPos.setX( diffPos.x() + w ); if( diffPos.y() > 0 && diffPos.y() > h / 2 ) diffPos.setY( diffPos.y() - h ); if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 ) diffPos.setY( diffPos.y() + h ); } QPoint currentPos = slide_start_pos + mTimeLine.value() * diffPos; QSize displaySize( displayWidth(), displayHeight()); QRegion currentRegion = QRect( currentPos, displaySize ); if( effects->optionRollOverDesktops()) { currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 ); currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h ); currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 ); currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h ); } bool do_sticky = true; for( int desktop = 1; desktop <= effects->numberOfDesktops(); ++desktop ) { QRect rect = desktopRect( desktop ); if( currentRegion.contains( rect )) // part of the desktop needs painting { painting_desktop = desktop; slide_painting_sticky = do_sticky; slide_painting_diff = rect.topLeft() - currentPos; if( effects->optionRollOverDesktops()) { if( slide_painting_diff.x() > displayWidth()) slide_painting_diff.setX( slide_painting_diff.x() - w ); if( slide_painting_diff.x() < -displayWidth()) slide_painting_diff.setX( slide_painting_diff.x() + w ); if( slide_painting_diff.y() > displayHeight()) slide_painting_diff.setY( slide_painting_diff.y() - h ); if( slide_painting_diff.y() < -displayHeight()) slide_painting_diff.setY( slide_painting_diff.y() + h ); } do_sticky = false; // paint on-all-desktop windows only once ScreenPaintData d = data; d.xTranslate += slide_painting_diff.x(); d.yTranslate += slide_painting_diff.y(); // TODO mask parts that are not visible? effects->paintScreen( mask, region, d ); } } }
// whole screen, not transformed, force region to be full *region = QRegion(0, 0, displayWidth(), displayHeight()); } painted_region = *region; if (*mask & PAINT_SCREEN_BACKGROUND_FIRST) { paintBackground(*region); } ScreenPaintData data; effects->paintScreen(*mask, *region, data); foreach (Window * w, stacking_order) { effects->postPaintWindow(effectWindow(w)); } effects->postPaintScreen(); *region |= painted_region; // make sure not to go outside of the screen area *region &= QRegion(0, 0, displayWidth(), displayHeight()); // make sure all clipping is restored Q_ASSERT(!PaintClipper::clip()); } // Compute time since the last painting pass. void Scene::updateTimeDiff() { if (!last_time.isValid()) { // Painting has been idle (optimized out) for some time, // which means time_diff would be huge and would break animations. // Simply set it to one (zero would mean no change at all and could // cause problems). time_diff = 1; last_time.start(); } else
// Gives a position of the given desktop when all desktops are arranged in a grid QRect SlideEffect::desktopRect( int desktop ) const { QRect rect( 0, 0, displayWidth(), displayHeight() ); rect.translate( effects->desktopCoords( desktop )); return rect; }
void SlideEffect::desktopChanged( int old ) { if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) return; if( slide ) // old slide still in progress { QPoint diffPos = desktopRect( old ).topLeft() - slide_start_pos; int w = 0; int h = 0; if( effects->optionRollOverDesktops()) { w = effects->workspaceWidth(); h = effects->workspaceHeight(); // wrap around if shorter if( diffPos.x() > 0 && diffPos.x() > w / 2 ) diffPos.setX( diffPos.x() - w ); if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 ) diffPos.setX( diffPos.x() + w ); if( diffPos.y() > 0 && diffPos.y() > h / 2 ) diffPos.setY( diffPos.y() - h ); if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 ) diffPos.setY( diffPos.y() + h ); } QPoint currentPos = slide_start_pos + mTimeLine.value() * diffPos; QRegion currentRegion = QRect( currentPos, QSize( displayWidth(), displayHeight())); if( effects->optionRollOverDesktops()) { currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 ); currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h ); currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 ); currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h ); } QRect rect = desktopRect( effects->currentDesktop() ); if( currentRegion.contains( rect )) { // current position is in new current desktop (e.g. quickly changing back), // don't do full progress if( abs( currentPos.x() - rect.x()) > abs( currentPos.y() - rect.y())) mTimeLine.setProgress(1 - abs( currentPos.x() - rect.x()) / double( displayWidth())); else mTimeLine.setProgress(1 - abs( currentPos.y() - rect.y()) / double( displayHeight())); } else // current position is not on current desktop, do full progress mTimeLine.setProgress(0); diffPos = rect.topLeft() - currentPos; if( mTimeLine.value() <= 0 ) { // Compute starting point for this new move (given current and end positions) slide_start_pos = rect.topLeft() - diffPos * 1 / ( 1 - mTimeLine.value() ); } else { // at the end, stop slide = false; mTimeLine.setProgress(0); effects->setActiveFullScreenEffect( NULL ); } } else { if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) return; mTimeLine.setProgress(0); slide_start_pos = desktopRect( old ).topLeft(); slide = true; effects->setActiveFullScreenEffect( this ); } effects->addRepaintFull(); }
Window EffectsHandler::createFullScreenInputWindow(Effect* e, const QCursor& cursor) { return createInputWindow(e, 0, 0, displayWidth(), displayHeight(), cursor); }