Workspace::Workspace() : mDamage( None ), mWaitForClients( false ), mInitialRepaint( true ) { Extensions::initialize(); XGrabServer( dpy ); // Redirect all toplevel window contents to offscreen storage XCompositeRedirectSubwindows( dpy, rootId(), CompositeRedirectManual ); initClientList(); // Request notification about toplevel window state changes XSelectInput( dpy, rootId(), SubstructureNotifyMask | ExposureMask | StructureNotifyMask | PropertyChangeMask ); XUngrabServer( dpy ); // Get the picture format for the root window mFormat = XRenderFindVisualFormat( dpy, visual() ); // Create an unclipped picture for drawing on the root window XRenderPictureAttributes pa; pa.subwindow_mode = IncludeInferiors; mFrontbuffer = XRenderCreatePicture( dpy, rootId(), format(), CPSubwindowMode, &pa ); createBackbuffer(); XSync( dpy, false ); }
// Move, resize, or stacking order change void Workspace::configureNotifyEvent( const XConfigureEvent *event ) { Client *client = find( event->window ); if ( client ) { QRect geometry = QRect( event->x, event->y, event->width, event->height ); int borderWidth = event->border_width; Window above = event->above; // Compress configure events. There's no need to union each of these rects with // the damage region, since there are only two visibly affected rects; the rect // where the window is currently drawn, and the rect in the last configure event, // which is where we'll draw the window in the next paint cycle. XConfigureEvent e; while ( XCheckTypedWindowEvent( dpy, client->winId(), ConfigureNotify, (XEvent*)&e ) ) { geometry = QRect( e.x, e.y, e.width, e.height ); borderWidth = e.border_width; above = e.above; } client->geometryChanged( geometry, borderWidth ); restack( client, above ); } else if ( event->window == rootId() ) { // Recreate the back buffer releasePicture( mBackbuffer ); createBackbuffer(); } }
void Workspace::propertyNotifyEvent( const XPropertyEvent *event ) { //char *name = XGetAtomName( dpy, event->atom ); //std::cout << "property \"" << name << "\" changed.\n"; //XFree( name ); // Handle property events for the root window if ( event->window == rootId() ) { // Major optimization when switching desktops; we'll block updates and just // let damage accumulate until all newly mapped windows have been painted. if ( event->atom == ATOM(_NET_CURRENT_DESKTOP) ) { mWaitForClients = true; XSync( dpy, false ); // Helps to accumulate more events } // If the root window pixmap was changed else if ( event->atom == ATOM(_XROOTPMAP_ID) || event->atom == ATOM(_XSETROOT_ID) || event->atom == ATOM(ESETROOT_PMAP_ID) ) { // Compress these events XEvent dummy; while ( XCheckIfEvent( dpy, &dummy, rootPixmapPredicate, XPointer( rootId() ) ) ); // Destroy the root tile picture releasePicture( mRootTile ); // Damage the whole display XserverRegion r = createRegionFromQRect( QRect( 0, 0, width(), height() ) ); addDamage( r ); } } // Handle notifications of changes to window opacity hints else if ( event->atom == ATOM(_NET_WM_WINDOW_OPACITY)) { // Compress opacity change events for the window XEvent dummy; while ( XCheckIfEvent( dpy, &dummy, windowOpacityPredicate, XPointer(event->window) ) ); Client *client = find( event->window ); if ( client ) client->opacityChanged(); } }
void Workspace::createRootTile() { Pixmap pixmap = None; Atom actual_type; int actual_format; ulong nitems, bytes_remaining; uchar *data = 0L; // Try to find a root window property with a pixmap ID for a background pixmap. Atom atoms[] = { ATOM(ESETROOT_PMAP_ID), ATOM(_XROOTPMAP_ID), ATOM(_XSETROOT_ID) }; for (int i = 0; i < 3; i++ ) { int result = XGetWindowProperty( dpy, rootId(), atoms[i], 0, 4, false, XA_PIXMAP, &actual_type, &actual_format, &nitems, &bytes_remaining, &data ); if ( result == Success && actual_type == XA_PIXMAP && actual_format == 32 && nitems == 1 ) { pixmap = *reinterpret_cast<Pixmap*>( data ); XFree( data ); break; } } XRenderPictureAttributes pa; pa.repeat = true; // Create the root tile picture for the pixmap if one was found if ( pixmap != None ) { mRootTile = XRenderCreatePicture( dpy, pixmap, format(), CPRepeat, &pa ); } else { // If no background pixmap is set, create a simply 1x1 tile pixmap = XCreatePixmap( dpy, rootId(), 1, 1, depth() ); mRootTile = XRenderCreatePicture( dpy, pixmap, format(), CPRepeat, &pa ); // Fill it with a gray color XRenderColor col = { 0x8080, 0x8080, 0x8080, 0xffff }; XRenderFillRectangle( dpy, PictOpSrc, mRootTile, &col, 0, 0, 1, 1 ); } }
void SingeChildTask::load(ISerializableNode* node) { super::load(node); if (this->m_status != BT_INVALID) { CSerializationID rootId("root"); ISerializableNode* rootNode = node->findChild(rootId); BEHAVIAC_ASSERT(rootNode); this->m_root->load(rootNode); } }
// Handles expose events for the root window void Workspace::exposeEvent( const XExposeEvent *event ) { if ( event->window != rootId() ) return; int more = event->count + 1; if ( mExposeRects.count() + more > mExposeRects.capacity() ) mExposeRects.reserve( mExposeRects.count() + more ); XRectangle r = { event->x, event->y, event->width, event->height }; mExposeRects.append( r ); if ( event->count == 0 ) { XserverRegion damage = XFixesCreateRegion( dpy, &mExposeRects.first(), mExposeRects.count() ); addDamage( damage ); mExposeRects.clear(); } }
void Workspace::reparentNotifyEvent( const XReparentEvent *event ) { //std::cout << "got reparent event for window " // << std::hex << event->window << std::endl; if ( event->parent == rootId() ) { XWindowAttributes attr; if ( !XGetWindowAttributes( dpy, event->window, &attr ) ) return; //std::cout << "window " << std::hex << event->window << " reparented to root\n"; Client *client = new Client( event->window, attr ); mList.prepend( client ); } else { //std::cout << "window " << std::hex << event->window << " reparented to " // << event->parent << std::endl; remove( event->window ); } }
void Workspace::initClientList() { // Get a list of all toplevel windows from the X server, sorted bottom to top uint nwindows; Window root_return, parent_return, *windows; XQueryTree( dpy, rootId(), &root_return, &parent_return, &windows, &nwindows ); // Create a client object for each window and insert it into the window // list, which is sorted top to bottom. (the opposite of the order returned // by XQueryTree()). for ( uint i = 0; i < nwindows; i++ ) { XWindowAttributes attr; if ( !XGetWindowAttributes( dpy, windows[i], &attr ) ) continue; mList.prepend( new Client( windows[i], attr ) ); } XFree( windows ); }
void Workspace::createBackbuffer() { Pixmap pixmap = XCreatePixmap( dpy, rootId(), width(), height(), depth() ); mBackbuffer = XRenderCreatePicture( dpy, pixmap, format(), 0, 0 ); XFreePixmap( dpy, pixmap ); // The picture owns the pixmap now }