Back to index

unity  6.0.0
unity-mt-grab-handles.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 Canonical Ltd
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License version 3 as
00006  * published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
00017  */
00018 
00019 #include "unity-mt-grab-handles.h"
00020 #include <iostream>
00021 
00022 COMPIZ_PLUGIN_20090315(unitymtgrabhandles, UnityMTGrabHandlesPluginVTable);
00023 
00024 unsigned int unity::MT::MaximizedHorzMask = CompWindowStateMaximizedHorzMask;
00025 unsigned int unity::MT::MaximizedVertMask = CompWindowStateMaximizedVertMask;
00026 unsigned int unity::MT::MoveMask = CompWindowActionMoveMask;
00027 unsigned int unity::MT::ResizeMask = CompWindowActionResizeMask;
00028 
00029 void
00030 unity::MT::X11TextureFactory::setActiveWrap (const GLTexture::List &t)
00031 {
00032   mWrap = t;
00033 }
00034 
00035 unity::MT::Texture::Ptr
00036 unity::MT::X11TextureFactory::create ()
00037 {
00038   return boost::shared_static_cast <unity::MT::Texture> (unity::MT::X11Texture::Ptr (new unity::MT::X11Texture (mWrap)));
00039 }
00040 
00041 unity::MT::X11Texture::X11Texture (const GLTexture::List &t)
00042 {
00043   mTexture = t;
00044 }
00045 
00046 const GLTexture::List &
00047 unity::MT::X11Texture::get ()
00048 {
00049   return mTexture;
00050 }
00051 
00052 unity::MT::X11ImplFactory::X11ImplFactory (Display *dpy) :
00053   mDpy (dpy)
00054 {
00055 }
00056 
00057 unity::MT::GrabHandle::Impl *
00058 unity::MT::X11ImplFactory::create (const GrabHandle::Ptr &handle)
00059 {
00060   unity::MT::GrabHandle::Impl *impl = new X11GrabHandleImpl (mDpy, handle);
00061   return impl;
00062 }
00063 
00064 unity::MT::X11GrabHandleImpl::X11GrabHandleImpl (Display *dpy, const GrabHandle::Ptr &h) :
00065   mGrabHandle (h),
00066   mIpw (None),
00067   mDpy (dpy)
00068 {
00069 
00070 }
00071 
00072 void
00073 unity::MT::X11GrabHandleImpl::show ()
00074 {
00075   if (mIpw)
00076   {
00077     XMapWindow (mDpy, mIpw);
00078     return;
00079   }
00080 
00081   XSetWindowAttributes xswa;
00082 
00083   xswa.override_redirect = TRUE;
00084 
00085   unity::MT::GrabHandle::Ptr gh = mGrabHandle.lock ();
00086 
00087   mIpw = XCreateWindow(mDpy,
00088                        DefaultRootWindow (mDpy),
00089                        -100, -100,
00090                        gh->width (),
00091                        gh->height (),
00092                        0,
00093                        CopyFromParent, InputOnly,
00094                        CopyFromParent, CWOverrideRedirect, &xswa);
00095 
00096   UnityMTGrabHandlesScreen::get(screen)->addHandleWindow(gh, mIpw);
00097 
00098   XMapWindow (mDpy, mIpw);
00099 }
00100 
00101 void
00102 unity::MT::X11GrabHandleImpl::hide ()
00103 {
00104   if (mIpw)
00105     XUnmapWindow (mDpy, mIpw);
00106 }
00107 
00108 void
00109 unity::MT::X11GrabHandleImpl::lockPosition (int x,
00110                                             int y,
00111                                             unsigned int flags)
00112 {
00113   XWindowChanges xwc;
00114   unsigned int   vm = 0;
00115 
00116   if (!mIpw)
00117     return;
00118 
00119   if (flags & unity::MT::PositionSet)
00120   {
00121     xwc.x = x;
00122     xwc.y = y;
00123     vm |= CWX | CWY;
00124   }
00125 
00126   unity::MT::GrabHandle::Ptr gh = mGrabHandle.lock ();
00127 
00128   gh->raise ();
00129 
00130   XConfigureWindow(screen->dpy(), mIpw, vm, &xwc);
00131   XSelectInput(screen->dpy(), mIpw, ButtonPressMask | ButtonReleaseMask);
00132 }
00133 
00134 unity::MT::X11GrabHandleImpl::~X11GrabHandleImpl ()
00135 {
00136   if (mIpw)
00137   {
00138     UnityMTGrabHandlesScreen::get(screen)->removeHandleWindow(mIpw);
00139 
00140     XDestroyWindow(mDpy, mIpw);
00141   }
00142 }
00143 
00144 void
00145 unity::MT::X11GrabHandleImpl::buttonPress (int x,
00146                                            int y,
00147                                            unsigned int button) const
00148 {
00149   unity::MT::GrabHandle::Ptr gh = mGrabHandle.lock ();
00150   gh->requestMovement (x, y, button);
00151 }
00152 
00153 void
00154 UnityMTGrabHandlesWindow::raiseGrabHandle (const boost::shared_ptr <const unity::MT::GrabHandle> &h)
00155 {
00156   UnityMTGrabHandlesScreen::get (screen)->raiseHandle (h, window->frame ());
00157 }
00158 
00159 void
00160 UnityMTGrabHandlesWindow::requestMovement (int x,
00161                                            int y,
00162                                       unsigned int direction,
00163                                       unsigned int button)
00164 {
00165   /* Send _NET_MOVERESIZE to root window so that a button-1
00166    * press on this window will start resizing the window around */
00167   XEvent     event;
00168 
00169   if (screen->getOption("raise_on_click"))
00170     window->updateAttributes(CompStackingUpdateModeAboveFullscreen);
00171 
00172   if (window->id() != screen->activeWindow())
00173     if (window->focus())
00174       window->moveInputFocusTo();
00175 
00176   event.xclient.type    = ClientMessage;
00177   event.xclient.display = screen->dpy ();
00178 
00179   event.xclient.serial      = 0;
00180   event.xclient.send_event  = true;
00181 
00182   event.xclient.window       = window->id();
00183   event.xclient.message_type = Atoms::wmMoveResize;
00184   event.xclient.format       = 32;
00185 
00186   event.xclient.data.l[0] = x;
00187   event.xclient.data.l[1] = y;
00188   event.xclient.data.l[2] = direction;
00189   event.xclient.data.l[3] = button;
00190   event.xclient.data.l[4] = 1;
00191 
00192   XSendEvent(screen->dpy(), screen->root(), false,
00193              SubstructureRedirectMask | SubstructureNotifyMask,
00194              &event);
00195 }
00196 
00197 /* Super speed hack */
00198 static bool
00199 sortPointers(void *p1, void *p2)
00200 {
00201   return (void*) p1 < (void*) p2;
00202 }
00203 
00204 void
00205 UnityMTGrabHandlesScreen::raiseHandle (const boost::shared_ptr <const unity::MT::GrabHandle> &h,
00206                                        Window                                                owner)
00207 {
00208   for (const auto &pair : mInputHandles)
00209   {
00210     if (*pair.second == *h)
00211     {
00212       unsigned int mask = CWSibling | CWStackMode;
00213       XWindowChanges xwc;
00214 
00215       xwc.stack_mode = Above;
00216       xwc.sibling = owner;
00217 
00218       XConfigureWindow (screen->dpy (), pair.first, mask, &xwc);
00219     }
00220   }
00221 }
00222 
00223 void
00224 UnityMTGrabHandlesScreen::handleEvent(XEvent* event)
00225 {
00226   CompWindow* w, *oldPrev, *oldNext;
00227 
00228   w = oldPrev = oldNext = NULL;
00229 
00230   switch (event->type)
00231   {
00232     case FocusIn:
00233     case FocusOut:
00234       if (event->xfocus.mode == NotifyUngrab)
00235       {
00236        for(CompWindow * w : screen->windows())
00237         {
00238           UnityMTGrabHandlesWindow* mtwindow = UnityMTGrabHandlesWindow::get(w);
00239           if (mtwindow->handleTimerActive())
00240             mtwindow->resetTimer();
00241         }
00242       }
00243       break;
00244     case ClientMessage:
00245 
00246       if (event->xclient.message_type == mCompResizeWindowAtom)
00247       {
00248         CompWindow* w = screen->findWindow(event->xclient.window);
00249 
00250         if (w)
00251         {
00252           CompRect r;
00253           UMTGH_WINDOW(w);
00254 
00255           r.setGeometry(event->xclient.data.l[0] - w->input().left,
00256                         event->xclient.data.l[1] - w->input().top,
00257                         event->xclient.data.l[2] + w->input().left + w->input().right,
00258                         event->xclient.data.l[3] + w->input().top + w->input().bottom);
00259 
00260           uw->relayout(r, false);
00261         }
00262       }
00263 
00264       break;
00265 
00266     case PropertyNotify:
00267 
00268       /* Stacking order of managed clients changed, check old
00269        * stacking order and ensure stacking of handles
00270        * that were changed in the stack */
00271 
00272 
00273       if (event->xproperty.atom == Atoms::clientListStacking)
00274       {
00275         CompWindowVector       invalidated(0);
00276         CompWindowVector       clients = screen->clientList(true);
00277         CompWindowVector       oldClients = mLastClientListStacking;
00278         CompWindowVector       clientListStacking = screen->clientList(true);
00279         /* Windows can be removed and added from the client list
00280          * here at the same time (eg hide/unhide launcher ... racy)
00281          * so we need to check if the client list contains the same
00282          * windows as it used to. Sort both lists and compare ... */
00283 
00284         std::sort(clients.begin(), clients.end(), sortPointers);
00285         std::sort(oldClients.begin(),
00286                   oldClients.end(), sortPointers);
00287 
00288         if (clients != mLastClientListStacking)
00289           invalidated = clients;
00290         else
00291         {
00292           CompWindowVector::const_iterator cit = clientListStacking.begin();
00293           CompWindowVector::const_iterator oit = mLastClientListStacking.begin();
00294 
00295           for (; cit != clientListStacking.end(); cit++, oit++)
00296           {
00297             /* All clients from this point onwards in cit are invalidated
00298              * so splice the list to the end of the new client list
00299              * and update the stacking of handles there */
00300             if ((*cit)->id() != (*oit)->id())
00301             {
00302               invalidated.push_back((*cit));
00303             }
00304           }
00305         }
00306 
00307        for(CompWindow * w : invalidated)
00308          UnityMTGrabHandlesWindow::get(w)->restackHandles();
00309 
00310         mLastClientListStacking = clients;
00311       }
00312 
00313       break;
00314 
00315     case ButtonPress:
00316     {
00317 
00318       if (event->xbutton.button != 1)
00319         break;
00320 
00321       auto it = mInputHandles.find(event->xbutton.window);
00322 
00323       if (it != mInputHandles.end())
00324       {
00325        if (it->second)
00326           it->second->buttonPress (event->xbutton.x_root,
00327                                    event->xbutton.y_root,
00328                                    event->xbutton.button);
00329       }
00330 
00331       break;
00332     }
00333     case ConfigureNotify:
00334 
00335       w = screen->findTopLevelWindow(event->xconfigure.window);
00336 
00337       if (w)
00338         UnityMTGrabHandlesWindow::get(w)->relayout(w->inputRect(), true);
00339 
00340       break;
00341 
00342     case MapNotify:
00343     {
00344 
00345       auto it = mInputHandles.find(event->xmap.window);
00346 
00347       if (it != mInputHandles.end())
00348       {
00349         if (it->second)
00350           it->second->reposition (0, 0, unity::MT::PositionLock);
00351       }
00352 
00353       break;
00354     }
00355     default:
00356 
00357       break;
00358   }
00359 
00360   screen->handleEvent(event);
00361 }
00362 
00363 void
00364 UnityMTGrabHandlesScreen::donePaint()
00365 {
00366   if (mMoreAnimate)
00367   {
00368     for (const unity::MT::GrabHandleGroup::Ptr &handles : mGrabHandles)
00369     {
00370       if (handles->needsAnimate())
00371       {
00372           handles->forEachHandle ([&](const unity::MT::GrabHandle::Ptr &h)
00373                               {
00374                                 h->damage (nux::Geometry (h->x (),
00375                                                        h->y (),
00376                                                        h->width (),
00377                                                        h->height ()));
00378                               });
00379       }
00380     }
00381   }
00382 
00383   cScreen->donePaint();
00384 }
00385 
00386 void
00387 UnityMTGrabHandlesScreen::preparePaint(int msec)
00388 {
00389   if (mMoreAnimate)
00390   {
00391     mMoreAnimate = false;
00392 
00393     for(const unity::MT::GrabHandleGroup::Ptr &handles : mGrabHandles)
00394     {
00395       mMoreAnimate |= handles->animate(msec);
00396     }
00397   }
00398 
00399   cScreen->preparePaint(msec);
00400 }
00401 
00402 bool
00403 UnityMTGrabHandlesWindow::handleTimerActive()
00404 {
00405   return mTimer.active ();
00406 }
00407 
00408 bool
00409 UnityMTGrabHandlesWindow::allowHandles()
00410 {
00411   /* Not on override redirect windows */
00412   if (window->overrideRedirect())
00413     return false;
00414 
00415   return true;
00416 }
00417 
00418 void
00419 UnityMTGrabHandlesWindow::getOutputExtents(CompWindowExtents& output)
00420 {
00421   auto f = [&] (const unity::MT::GrabHandle::Ptr &h)
00422   {
00423     output.left = std::max (window->borderRect().left() + h->width () / 2, static_cast <unsigned int> (output.left));
00424     output.right = std::max (window->borderRect().right()  + h->width () / 2, static_cast <unsigned int> (output.right));
00425     output.top = std::max (window->borderRect().top() + h->height () / 2, static_cast <unsigned int> (output.top));
00426     output.bottom = std::max (window->borderRect().bottom() + h->height () / 2, static_cast <unsigned int> (output.bottom));
00427   };
00428 
00429   if (mHandles)
00430   {
00431     /* Only care about the handle on the outside */
00432     mHandles->forEachHandle (f);
00433   }
00434   else
00435     window->getOutputExtents(output);
00436 
00437 }
00438 
00439 bool
00440 UnityMTGrabHandlesWindow::glDraw(const GLMatrix&            transform,
00441 #ifdef USE_MODERN_COMPIZ_GL
00442                                  const GLWindowPaintAttrib& attrib,
00443 #else
00444                                  GLFragment::Attrib&      fragment,
00445 #endif
00446                                  const CompRegion&          region,
00447                                  unsigned int              mask)
00448 {
00449   /* Draw the window on the bottom, we will be drawing the
00450    * handles on top */
00451 #ifdef USE_MODERN_COMPIZ_GL
00452   bool status = gWindow->glDraw(transform, attrib, region, mask);
00453 #else
00454   bool status = gWindow->glDraw(transform, fragment, region, mask);
00455 #endif
00456 
00457   if (mHandles && mHandles->visible())
00458   {
00459     unsigned int allowedHandles = unity::MT::getLayoutForMask (window->state (), window->actions ());
00460     unsigned int handle = 0;
00461 
00462     UMTGH_SCREEN (screen);
00463 
00464     for(unity::MT::TextureLayout layout : mHandles->layout (allowedHandles))
00465     {
00466       /* We want to set the geometry of the handle to the window
00467        * region */
00468       CompRegion reg = CompRegion(layout.second.x, layout.second.y, layout.second.width, layout.second.height);
00469 
00470       for(GLTexture * tex : boost::shared_static_cast <unity::MT::X11Texture> (layout.first)->get ())
00471       {
00472         GLTexture::MatrixList matl;
00473         GLTexture::Matrix     mat = tex->matrix();
00474         CompRegion        paintRegion(region);
00475 #ifdef USE_MODERN_COMPIZ_GL
00476         GLWindowPaintAttrib   wAttrib(attrib);
00477 #endif
00478 
00479         /* We can reset the window geometry since it will be
00480          * re-added later */
00481 #ifdef USE_MODERN_COMPIZ_GL
00482         gWindow->vertexBuffer()->begin();
00483 #else
00484         gWindow->geometry().reset();
00485 #endif
00486 
00487         /* Not sure what this does, but it is necessary
00488          * (adjusts for scale?) */
00489         mat.x0 -= mat.xx * reg.boundingRect().x1();
00490         mat.y0 -= mat.yy * reg.boundingRect().y1();
00491 
00492         matl.push_back(mat);
00493 
00494         if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
00495           paintRegion = infiniteRegion;
00496 
00497         /* Now allow plugins to mess with the geometry of our
00498          * dim (so we get a nice render for things like
00499          * wobbly etc etc */
00500         gWindow->glAddGeometry(matl, reg, paintRegion);
00501 #ifdef USE_MODERN_COMPIZ_GL
00502         gWindow->vertexBuffer()->end();
00503         wAttrib.opacity = mHandles->opacity();
00504 #else
00505         /* Did it succeed? */
00506         if (gWindow->geometry().vertices)
00507         {
00508           fragment.setOpacity(mHandles->opacity());
00509           /* Texture rendering set-up */
00510           us->gScreen->setTexEnvMode(GL_MODULATE);
00511 #endif
00512           glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
00513           /* Draw the dim texture with all of it's modified
00514            * geometry glory */
00515           gWindow->glDrawTexture(tex,
00516 #ifdef USE_MODERN_COMPIZ_GL
00517                                  transform, wAttrib,
00518 #else
00519                                  fragment,
00520 #endif
00521                                  mask | PAINT_WINDOW_BLEND_MASK
00522                                  | PAINT_WINDOW_TRANSLUCENT_MASK |
00523                                  PAINT_WINDOW_TRANSFORMED_MASK);
00524           /* Texture rendering tear-down */
00525           glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
00526 #ifndef USE_MODERN_COMPIZ_GL
00527           us->gScreen->setTexEnvMode(GL_REPLACE);
00528         }
00529 #endif
00530       }
00531 
00532       handle++;
00533     }
00534   }
00535 
00536   return status;
00537 }
00538 
00539 void
00540 UnityMTGrabHandlesWindow::relayout(const CompRect& r, bool hard)
00541 {
00542   if (mHandles)
00543     mHandles->relayout(nux::Geometry (r.x (), r.y (), r.width (), r.height ()), hard);
00544 }
00545 
00546 void
00547 UnityMTGrabHandlesWindow::grabNotify(int x, int y, unsigned int state, unsigned int mask)
00548 {
00549   window->grabNotify(x, y, state, mask);
00550 }
00551 
00552 void
00553 UnityMTGrabHandlesWindow::moveNotify(int dx, int dy, bool immediate)
00554 {
00555   if (mHandles)
00556     mHandles->relayout(nux::Geometry (window->inputRect ().x (), window->inputRect ().y (),
00557                                       window->inputRect ().width (), window->inputRect ().height ()), false);
00558 
00559   window->moveNotify(dx, dy, immediate);
00560 }
00561 
00562 void
00563 UnityMTGrabHandlesWindow::ungrabNotify()
00564 {
00565   window->ungrabNotify();
00566 }
00567 
00568 bool
00569 UnityMTGrabHandlesWindow::handlesVisible()
00570 {
00571   if (!mHandles)
00572     return false;
00573 
00574   return mHandles->visible();
00575 }
00576 
00577 void
00578 UnityMTGrabHandlesWindow::hideHandles()
00579 {
00580   if (mHandles)
00581     mHandles->hide();
00582 
00583   window->updateWindowOutputExtents();
00584   cWindow->damageOutputExtents();
00585 
00586   disableTimer();
00587 }
00588 
00589 bool
00590 UnityMTGrabHandlesWindow::onHideTimeout()
00591 {
00592   CompOption::Vector o (1);
00593   CompOption::Value  v;
00594 
00595   if (screen->grabbed())
00596     return true;
00597 
00598   v.set ((int) window->id ());
00599 
00600   o[0].setName ("window", CompOption::TypeInt);
00601   o[0].set (v);
00602 
00603   UnityMTGrabHandlesScreen::get (screen)->hideHandles (NULL, 0, o);
00604   return false;
00605 }
00606 
00607 void
00608 UnityMTGrabHandlesWindow::resetTimer()
00609 {
00610   mTimer.stop ();
00611   mTimer.setTimes (2000, 2200);
00612   mTimer.start ();
00613 }
00614 
00615 void
00616 UnityMTGrabHandlesWindow::disableTimer()
00617 {
00618   mTimer.stop ();
00619 }
00620 
00621 void
00622 UnityMTGrabHandlesWindow::showHandles(bool use_timer)
00623 {
00624   UMTGH_SCREEN (screen);
00625 
00626   if (!mHandles)
00627   {
00628     mHandles = unity::MT::GrabHandleGroup::create (this, us->textures ());
00629     us->addHandles(mHandles);
00630   }
00631 
00632   if (!mHandles->visible())
00633   {
00634     unsigned int showingMask = unity::MT::getLayoutForMask (window->state (), window->actions ());
00635     activate();
00636     mHandles->show(showingMask);
00637     mHandles->relayout(nux::Geometry (window->inputRect().x (),
00638                                       window->inputRect().y (),
00639                                       window->inputRect().width(),
00640                                       window->inputRect().height()), true);
00641 
00642     window->updateWindowOutputExtents();
00643     cWindow->damageOutputExtents();
00644   }
00645 
00646   if (use_timer)
00647     resetTimer();
00648   else
00649     disableTimer();
00650 }
00651 
00652 void
00653 UnityMTGrabHandlesWindow::restackHandles()
00654 {
00655   if (!mHandles)
00656     return;
00657 
00658   mHandles->forEachHandle ([&](const unity::MT::GrabHandle::Ptr &h)
00659                            { h->reposition (0, 0, unity::MT::PositionLock); });
00660 }
00661 
00662 void
00663 UnityMTGrabHandlesScreen::addHandleWindow(const unity::MT::GrabHandle::Ptr &h, Window w)
00664 {
00665   mInputHandles.insert(std::pair <Window, const unity::MT::GrabHandle::Ptr> (w, h));
00666 }
00667 
00668 void
00669 UnityMTGrabHandlesScreen::removeHandleWindow(Window w)
00670 {
00671   mInputHandles.erase(w);
00672 }
00673 
00674 void
00675 UnityMTGrabHandlesScreen::addHandles(const unity::MT::GrabHandleGroup::Ptr &handles)
00676 {
00677   mGrabHandles.push_back(handles);
00678 }
00679 
00680 void
00681 UnityMTGrabHandlesScreen::removeHandles(const unity::MT::GrabHandleGroup::Ptr &handles)
00682 {
00683   mGrabHandles.remove(handles);
00684 
00685   mMoreAnimate = true;
00686 }
00687 
00688 bool
00689 UnityMTGrabHandlesScreen::toggleHandles(CompAction*         action,
00690                                         CompAction::State  state,
00691                                         CompOption::Vector& options)
00692 {
00693   CompWindow* w = screen->findWindow(CompOption::getIntOptionNamed(options,
00694                                                                    "window",
00695                                                           0));
00696   if (w)
00697   {
00698     UMTGH_WINDOW(w);
00699 
00700     if (!uw->allowHandles())
00701       return false;
00702 
00703     if (uw->handlesVisible())
00704       uw->hideHandles();
00705     else
00706       uw->showHandles(true);
00707 
00708     mMoreAnimate = true;
00709   }
00710 
00711   return true;
00712 }
00713 
00714 bool
00715 UnityMTGrabHandlesScreen::showHandles(CompAction*         action,
00716                                       CompAction::State  state,
00717                                       CompOption::Vector& options)
00718 {
00719   CompWindow* w = screen->findWindow(CompOption::getIntOptionNamed(options,
00720                                                                    "window",
00721                                                                    0));
00722 
00723   bool use_timer = CompOption::getBoolOptionNamed(options, "use-timer", true);
00724 
00725   if (w)
00726   {
00727     UMTGH_WINDOW(w);
00728 
00729     if (!uw->allowHandles())
00730       return false;
00731 
00732     uw->showHandles(use_timer);
00733 
00734     if (!uw->handlesVisible())
00735       mMoreAnimate = true;
00736   }
00737 
00738   return true;
00739 }
00740 
00741 bool
00742 UnityMTGrabHandlesScreen::hideHandles(CompAction*         action,
00743                                       CompAction::State  state,
00744                                       CompOption::Vector& options)
00745 {
00746   CompWindow* w = screen->findWindow(CompOption::getIntOptionNamed(options,
00747                                                                    "window",
00748                                                                    0));
00749   if (w)
00750   {
00751     UMTGH_WINDOW(w);
00752 
00753     if (!uw->allowHandles())
00754       return false;
00755 
00756     if (uw->handlesVisible())
00757     {
00758       uw->hideHandles();
00759       mMoreAnimate = true;
00760     }
00761   }
00762 
00763   return true;
00764 }
00765 
00766 void
00767 UnityMTGrabHandlesScreen::optionChanged (CompOption *option,
00768                                          UnitymtgrabhandlesOptions::Options num)
00769 {
00770   if (num == UnitymtgrabhandlesOptions::FadeDuration)
00771   {
00772     unity::MT::FADE_MSEC = optionGetFadeDuration ();
00773   }
00774 }
00775 
00776 UnityMTGrabHandlesScreen::UnityMTGrabHandlesScreen(CompScreen* s) :
00777   PluginClassHandler <UnityMTGrabHandlesScreen, CompScreen> (s),
00778   cScreen(CompositeScreen::get(s)),
00779   gScreen(GLScreen::get(s)),
00780   mGrabHandles(0),
00781   mHandleTextures(0),
00782   mLastClientListStacking(screen->clientList(true)),
00783   mCompResizeWindowAtom(XInternAtom(screen->dpy(),
00784                                     "_COMPIZ_RESIZE_NOTIFY", 0)),
00785   mMoreAnimate(false)
00786 {
00787   unity::MT::GrabHandle::ImplFactory::SetDefault (new unity::MT::X11ImplFactory (screen->dpy ()));
00788   unity::MT::Texture::Factory::SetDefault (new unity::MT::X11TextureFactory ());
00789 
00790   ScreenInterface::setHandler(s);
00791   CompositeScreenInterface::setHandler(cScreen);
00792   GLScreenInterface::setHandler(gScreen);
00793 
00794   mHandleTextures.resize(unity::MT::NUM_HANDLES);
00795 
00796   for (unsigned int i = 0; i < unity::MT::NUM_HANDLES; i++)
00797   {
00798     CompString fname = "handle-";
00799     CompString pname("unitymtgrabhandles");
00800     CompSize   size;
00801 
00802     fname = compPrintf("%s%i.png", fname.c_str(), i);
00803     GLTexture::List t = GLTexture::readImageToTexture(fname, pname,
00804                                                       size);
00805 
00806     (boost::shared_static_cast <unity::MT::X11TextureFactory> (unity::MT::Texture::Factory::Default ()))->setActiveWrap (t);
00807 
00808     mHandleTextures.at(i).first = unity::MT::Texture::Factory::Default ()->create ();
00809     mHandleTextures.at (i).second.width = size.width ();
00810     mHandleTextures.at (i).second.height = size.height ();
00811   }
00812 
00813   unity::MT::FADE_MSEC = optionGetFadeDuration ();
00814 
00815   optionSetToggleHandlesKeyInitiate(boost::bind(&UnityMTGrabHandlesScreen::toggleHandles, this, _1, _2, _3));
00816   optionSetShowHandlesKeyInitiate(boost::bind(&UnityMTGrabHandlesScreen::showHandles, this, _1, _2, _3));
00817   optionSetHideHandlesKeyInitiate(boost::bind(&UnityMTGrabHandlesScreen::hideHandles, this, _1, _2, _3));
00818   optionSetFadeDurationNotify(boost::bind(&UnityMTGrabHandlesScreen::optionChanged, this, _1, _2));
00819 }
00820 
00821 UnityMTGrabHandlesScreen::~UnityMTGrabHandlesScreen()
00822 {
00823   mGrabHandles.clear ();
00824 }
00825 
00826 UnityMTGrabHandlesWindow::UnityMTGrabHandlesWindow(CompWindow* w) :
00827   PluginClassHandler <UnityMTGrabHandlesWindow, CompWindow> (w),
00828   window(w),
00829   cWindow(CompositeWindow::get(w)),
00830   gWindow(GLWindow::get(w)),
00831   mHandles()
00832 {
00833   WindowInterface::setHandler(window);
00834   CompositeWindowInterface::setHandler(cWindow);
00835   GLWindowInterface::setHandler(gWindow);
00836 
00837   mTimer.setCallback (boost::bind (&UnityMTGrabHandlesWindow::onHideTimeout, this));
00838 }
00839 
00840 UnityMTGrabHandlesWindow::~UnityMTGrabHandlesWindow()
00841 {
00842   mTimer.stop ();
00843 
00844   if (mHandles)
00845   {
00846     UnityMTGrabHandlesScreen::get(screen)->removeHandles(mHandles);
00847   }
00848 }
00849 
00850 bool
00851 UnityMTGrabHandlesPluginVTable::init()
00852 {
00853   if (!CompPlugin::checkPluginABI("core", CORE_ABIVERSION) ||
00854       !CompPlugin::checkPluginABI("composite", COMPIZ_COMPOSITE_ABI) ||
00855       !CompPlugin::checkPluginABI("opengl", COMPIZ_OPENGL_ABI))
00856     return false;
00857 
00858   return true;
00859 }