Back to index

unity  6.0.0
GestureEngine.cpp
Go to the documentation of this file.
00001 /*
00002  * GestureEngine.cpp
00003  * This file is part of Unity
00004  *
00005  * Copyright (C) 2011 - Canonical Ltd.
00006  *
00007  * Unity is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * Unity is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with Unity; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor,
00020  * Boston, MA  02110-1301  USA
00021  */
00022 
00023 #include <X11/cursorfont.h>
00024 
00025 #include "ubus-server.h"
00026 #include "UBusMessages.h"
00027 #include "GestureEngine.h"
00028 #include "PluginAdapter.h"
00029 
00030 GestureEngine::GestureEngine(CompScreen* screen)
00031 {
00032   _screen = screen;
00033 
00034   _drag_id = 0;
00035   _drag_window = 0;
00036   _pinch_id = 0;
00037   _touch_id = 0;
00038   _drag_grab = 0;
00039   _pinch_grab = 0;
00040   _fleur_cursor = XCreateFontCursor (screen->dpy (), XC_fleur);
00041 
00042   GeisAdapter& adapter = GeisAdapter::Instance();
00043 
00044   adapter.tap.connect(sigc::mem_fun(this, &GestureEngine::OnTap));
00045 
00046   adapter.drag_start.connect(sigc::mem_fun(this, &GestureEngine::OnDragStart));
00047   adapter.drag_update.connect(sigc::mem_fun(this, &GestureEngine::OnDragUpdate));
00048   adapter.drag_finish.connect(sigc::mem_fun(this, &GestureEngine::OnDragFinish));
00049 
00050   adapter.rotate_start.connect(sigc::mem_fun(this, &GestureEngine::OnRotateStart));
00051   adapter.rotate_update.connect(sigc::mem_fun(this, &GestureEngine::OnRotateUpdate));
00052   adapter.rotate_finish.connect(sigc::mem_fun(this, &GestureEngine::OnRotateFinish));
00053 
00054   adapter.pinch_start.connect(sigc::mem_fun(this, &GestureEngine::OnPinchStart));
00055   adapter.pinch_update.connect(sigc::mem_fun(this, &GestureEngine::OnPinchUpdate));
00056   adapter.pinch_finish.connect(sigc::mem_fun(this, &GestureEngine::OnPinchFinish));
00057 
00058   adapter.touch_start.connect(sigc::mem_fun(this, &GestureEngine::OnTouchStart));
00059   adapter.touch_update.connect(sigc::mem_fun(this, &GestureEngine::OnTouchUpdate));
00060   adapter.touch_finish.connect(sigc::mem_fun(this, &GestureEngine::OnTouchFinish));
00061 }
00062 
00063 GestureEngine::~GestureEngine()
00064 {
00065               if (_fleur_cursor)
00066        XFreeCursor (screen->dpy (), _fleur_cursor);
00067 }
00068 
00069 void
00070 GestureEngine::OnTap(GeisAdapter::GeisTapData* data)
00071 {
00072   if (data->touches == 4)
00073   {
00074     UBusServer* ubus = ubus_server_get_default();
00075     ubus_server_send_message(ubus, UBUS_DASH_EXTERNAL_ACTIVATION, NULL);
00076   }
00077 }
00078 
00079 CompWindow* GestureEngine::FindCompWindowAtPos(float fpos_x, float fpos_y)
00080 {
00081   const CompWindowVector& client_list_stacking = _screen->clientList(true);
00082 
00083   int pos_x = fpos_x;
00084   int pos_y = fpos_y;
00085 
00086   for (auto iter = client_list_stacking.rbegin(),
00087        end = client_list_stacking.rend();
00088        iter != end; ++iter)
00089   {
00090     CompWindow* window = *iter;
00091 
00092     if (pos_x >= window->x() && pos_x <= (window->width() + window->x())
00093         &&
00094         pos_y >= window->y() && pos_y <= (window->height() + window->y()))
00095       return window;
00096   }
00097 
00098   return nullptr;
00099 }
00100 
00101 void
00102 GestureEngine::OnDragStart(GeisAdapter::GeisDragData* data)
00103 {
00104   if (data->touches == 3)
00105   {
00106     _drag_window = FindCompWindowAtPos(data->focus_x, data->focus_y);
00107 
00108 
00109     if (!_drag_window)
00110       return;
00111 
00112     if (!(_drag_window->actions() & CompWindowActionMoveMask))
00113     {
00114       _drag_window = 0;
00115       return;
00116     }
00117 
00118     /* Don't allow windows to be dragged if completely maximized */
00119     if ((_drag_window->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE)
00120     {
00121       _drag_window = 0;
00122       return;
00123     }
00124 
00125     if (_drag_grab)
00126       _screen->removeGrab(_drag_grab, NULL);
00127     _drag_id = data->id;
00128     _drag_grab = _screen->pushGrab(_fleur_cursor, "unity");
00129     _drag_window->grabNotify (_drag_window->serverGeometry ().x (),
00130                               _drag_window->serverGeometry ().y (),
00131                               0, CompWindowGrabMoveMask | CompWindowGrabButtonMask);
00132   }
00133 }
00134 
00135 /* FIXME: CompScreen::warpPointer filters out motion events which
00136  * other plugins may need to process, but for most cases in core
00137  * they should be filtered out. */
00138 void
00139 GestureEngine::OnDragUpdate(GeisAdapter::GeisDragData* data)
00140 {
00141   if (_drag_id == data->id && _drag_window)
00142   {
00143     unsigned int px = std::max (std::min (pointerX + static_cast <int> (data->delta_x), screen->width ()), 0);
00144     unsigned int py = std::max (std::min (pointerY + static_cast <int> (data->delta_y), screen->height ()), 0);
00145 
00146     if (_drag_window->state () & CompWindowStateMaximizedVertMask)
00147       py = pointerY;
00148     if (_drag_window->state () & CompWindowStateMaximizedHorzMask)
00149       px = pointerX;
00150 
00151     XWarpPointer(screen->dpy (),
00152      None, screen->root (),
00153      0, 0, 0, 0,
00154      px, py);
00155 
00156     XSync(screen->dpy (), false);
00157     _drag_window->move(px - pointerX, py - pointerY, false);
00158 
00159     pointerX = px;
00160     pointerY = py;
00161   }
00162 }
00163 
00164 void
00165 GestureEngine::OnDragFinish(GeisAdapter::GeisDragData* data)
00166 {
00167   if (_drag_id == data->id && _drag_window)
00168   {
00169     _drag_window->ungrabNotify ();
00170     _drag_window->syncPosition();
00171     EndDrag();
00172   }
00173 }
00174 
00175 void
00176 GestureEngine::EndDrag()
00177 {
00178   if (_drag_window)
00179   {
00180     _screen->removeGrab(_drag_grab, NULL);
00181     _drag_grab = 0;
00182     _drag_window = 0;
00183     _drag_id = 0;
00184   }
00185 }
00186 
00187 void
00188 GestureEngine::OnRotateStart(GeisAdapter::GeisRotateData* data)
00189 {
00190 
00191 }
00192 void
00193 GestureEngine::OnRotateUpdate(GeisAdapter::GeisRotateData* data)
00194 {
00195 
00196 }
00197 void
00198 GestureEngine::OnRotateFinish(GeisAdapter::GeisRotateData* data)
00199 {
00200 
00201 }
00202 
00203 void
00204 GestureEngine::OnTouchStart(GeisAdapter::GeisTouchData* data)
00205 {
00206   if (data->touches == 3 && data->window != 0)
00207   {
00208     CompWindow* result = FindCompWindowAtPos(data->focus_x, data->focus_y);
00209 
00210     if (result)
00211     {
00212       PluginAdapter::Default()->ShowGrabHandles(result, false);
00213       _touch_id = data->id;
00214       _touch_window = result;
00215     }
00216   }
00217 }
00218 
00219 void
00220 GestureEngine::OnTouchUpdate(GeisAdapter::GeisTouchData* data)
00221 {
00222 
00223 }
00224 
00225 void
00226 GestureEngine::OnTouchFinish(GeisAdapter::GeisTouchData* data)
00227 {
00228   if (_touch_id == data->id)
00229   {
00230     if (_touch_window)
00231       PluginAdapter::Default()->ShowGrabHandles(_touch_window, true);
00232     _touch_id = 0;
00233     _touch_window = 0;
00234   }
00235 }
00236 
00237 void
00238 GestureEngine::OnPinchStart(GeisAdapter::GeisPinchData* data)
00239 {
00240   if (data->touches == 3)
00241   {
00242     _pinch_window = FindCompWindowAtPos(data->focus_x, data->focus_y);
00243 
00244     if (!_pinch_window)
00245       return;
00246 
00247     _pinch_id = data->id;
00248 
00249     if (_pinch_grab)
00250       _screen->removeGrab(_pinch_grab, NULL);
00251     _pinch_grab = _screen->pushGrab(_screen->invisibleCursor(), "unity");
00252   }
00253 }
00254 void
00255 GestureEngine::OnPinchUpdate(GeisAdapter::GeisPinchData* data)
00256 {
00257   if (data->id != _pinch_id)
00258     return;
00259 
00260   if (data->radius > 1.25)
00261   {
00262     _pinch_window->maximize(MAXIMIZE_STATE);
00263     EndDrag();
00264   }
00265   else if (data->radius < 0.8)
00266   {
00267     _pinch_window->maximize(0);
00268     EndDrag();
00269   }
00270 }
00271 void
00272 GestureEngine::OnPinchFinish(GeisAdapter::GeisPinchData* data)
00273 {
00274   if (_pinch_id == data->id && _pinch_window)
00275   {
00276     _screen->removeGrab(_pinch_grab, NULL);
00277     _pinch_grab = 0;
00278     _pinch_id = 0;
00279   }
00280 }