summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwarlock <warlock.cc@gmail.com>2010-11-14 18:34:26 -0300
committerwarlock <warlock.cc@gmail.com>2010-11-14 18:34:26 -0300
commited0dc14b6c89124790743a4ece7273b12d617339 (patch)
tree2f80da7030fac189b1d4af9b0da28aaad510a02f
parent54c31afd5c14e83dd3f86f2c89acabd3bf8fd15a (diff)
downloadwormouse-ed0dc14b6c89124790743a4ece7273b12d617339.tar.gz
wormouse-ed0dc14b6c89124790743a4ece7273b12d617339.tar.bz2
* Conditional compilation of pre calculated rotated imagesHEADmaster
* Replace the screen cursor correctly to avoid overriding
-rw-r--r--src/wormouse.cpp167
-rw-r--r--src/wormouse.h11
2 files changed, 149 insertions, 29 deletions
diff --git a/src/wormouse.cpp b/src/wormouse.cpp
index 1d41844..69b808e 100644
--- a/src/wormouse.cpp
+++ b/src/wormouse.cpp
@@ -16,32 +16,11 @@
**/
#include <math.h>
+#include <stdlib.h>
#include "wormouse.h"
COMPIZ_PLUGIN_20090315 (wormouse, WormousePluginVTable);
-/*boilerplate */
-WormouseScreen::WormouseScreen (CompScreen *screen):
- PluginClassHandler <WormouseScreen, CompScreen> (screen),
- cr (NULL), img (NULL), work (NULL), cursor (0), xci (NULL)
-{
- poller.setCallback (boost::bind (&WormouseScreen::mouseMove, this, _1));
-
- optionSetCursorImageNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
- optionSetShowHotspotNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
- optionSetHotspotXNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
- optionSetHotspotYNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
- optionSetTailFactorNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
-
- if (!updateConfig(NULL, Options()))
- setFailed ();
-}
-
-WormouseScreen::~WormouseScreen ()
-{
- freeResources ();
-}
-
bool
WormouseScreen::updateConfig (CompOption *opt, Options num)
{
@@ -62,12 +41,17 @@ WormouseScreen::updateConfig (CompOption *opt, Options num)
return false;
}
+
bool
WormouseScreen::loadCursor (CompString &path, int hotx, int hoty,
float tail_dist, float image_angle)
{
freeResources ();
+#ifdef _CACHE_ROTATION_
+ if (!buildCache (path))
+ return false;
+#else
img = cairo_image_surface_create_from_png (path.c_str ());
if (CAIRO_STATUS_SUCCESS != cairo_surface_status (img)) {
compLogMessage ("wormouse", CompLogLevelError,
@@ -93,11 +77,15 @@ WormouseScreen::loadCursor (CompString &path, int hotx, int hoty,
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_set_source_surface (cr, img, 0, 0);
cairo_paint(cr);
+#endif
// create a cursor image and set it
xci = XcursorImageCreate (2*wrk_r, 2*wrk_r);
xci->xhot = (2.0*wrk_r-wrk_w)/2 + hotx;
xci->yhot = (2.0*wrk_r-wrk_h)/2 + hoty;
+#ifdef _CACHE_ROTATION_
+ xci->pixels = imageCache[0];
+#else
xci->pixels = (XcursorPixel *)cairo_image_surface_get_data (work);
if (show_hotspot) {
@@ -107,10 +95,11 @@ WormouseScreen::loadCursor (CompString &path, int hotx, int hoty,
cairo_arc (cr, xci->xhot, xci->yhot, 1.0, 0, 2 * M_PI);
cairo_stroke (cr);
}
+#endif
+ Cursor original_cursor = screen->normalCursor ();
cursor = XcursorImageLoadCursor (screen->dpy(), xci);
- XDefineCursor (screen->dpy (), screen->root (), cursor);
- XFlush (screen->dpy ());
+ XFixesChangeCursor (screen->dpy (), cursor, original_cursor);
// using cairo coordinates (inverted y axis)
hot_a = atan2f(xci->yhot - wrk_r, xci->xhot - wrk_r);
@@ -127,7 +116,6 @@ void
WormouseScreen::freeResources ()
{
poller.stop ();
- //XUndefineCursor(screen->dpy(), screen->root());
if (cursor) {
XFreeCursor (screen->dpy(), cursor);
cursor = 0;
@@ -136,6 +124,14 @@ WormouseScreen::freeResources ()
XcursorImageDestroy (xci);
xci = NULL;
}
+#ifdef _CACHE_ROTATION_
+ int a;
+ for (a = 0; a < 360; a++)
+ if (imageCache[a]) {
+ free (imageCache[a]);
+ imageCache[a] = NULL;
+ }
+#else
if (cr) {
cairo_destroy (cr);
cr = NULL;
@@ -148,8 +144,34 @@ WormouseScreen::freeResources ()
cairo_surface_destroy (work);
work = NULL;
}
+#endif
}
+#ifdef _CACHE_ROTATION_
+void
+WormouseScreen::mouseMove (const CompPoint &pos)
+{
+ // get the new angle we're traveling
+ // needent invert y axis since cairo uses same coord system
+ float a = atan2f(pos.y() - piv_y, pos.x() - piv_x);
+ // update pivoting position
+ piv_x = pos.x() - tail_d * cosf(a);
+ piv_y = pos.y() - tail_d * sinf(a);
+
+ // compensate image orientation
+ a += wrk_a;
+
+ // create a cursor image and set it
+ xci->xhot = wrk_r + hot_d * cosf(hot_a + a);
+ xci->yhot = wrk_r + hot_d * sinf(hot_a + a);
+ xci->pixels = imageCache[ (int)(360 + a * 180.0 / M_PI) % 360 ];
+
+ Cursor newcur = XcursorImageLoadCursor (screen->dpy(), xci);
+ XFixesChangeCursor (screen->dpy (), newcur, cursor);
+ XFreeCursor (screen->dpy (), cursor);
+ cursor = newcur;
+}
+#else
void
WormouseScreen::mouseMove (const CompPoint &pos)
{
@@ -196,13 +218,102 @@ WormouseScreen::mouseMove (const CompPoint &pos)
XFreeCursor (screen->dpy (), cursor);
cursor = newcur;
}
+#endif
+
+#ifdef _CACHE_ROTATION_
+bool
+WormouseScreen::buildCache (const CompString &path)
+{
+ cairo_surface_t *img = cairo_image_surface_create_from_png (path.c_str ());
+ if (CAIRO_STATUS_SUCCESS != cairo_surface_status (img)) {
+ compLogMessage ("wormouse", CompLogLevelError,
+ "Failed to load cursor image [%s]\n", path.c_str ());
+ return false;
+ }
+
+ // calculate dimensions needed for rotate image
+ wrk_w = cairo_image_surface_get_width (img);
+ wrk_h = cairo_image_surface_get_height (img);
+ wrk_r = sqrt(wrk_w*wrk_w/4.0 + wrk_h*wrk_h/4.0);
+
+ // create a destination canvas
+ cairo_surface_t *work = cairo_image_surface_create (
+ CAIRO_FORMAT_ARGB32, 2*wrk_r, 2*wrk_r);
+ cairo_t *cr = cairo_create (work);
+
+ int a;
+ for (a = 0; a < 360; a++) {
+ // clear background
+ cairo_identity_matrix (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr);
+
+ // move to the center, rotate, translate back an to the final place
+ cairo_translate (cr, wrk_r, wrk_r);
+ cairo_rotate (cr, a * M_PI / 180.0);
+ cairo_translate (cr, -wrk_w/2.0, -wrk_h/2.0);
+
+ // paint rotate image
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_set_source_surface (cr, img, 0, 0);
+ cairo_paint(cr);
+
+ if (imageCache[a]) free (imageCache[a]);
+ // cache the image
+ int stride = cairo_image_surface_get_stride (work);
+ void *data = cairo_image_surface_get_data (work);
+ imageCache[a] = (XcursorPixel *)malloc((int)(wrk_r * wrk_r * stride));
+ memcpy(imageCache[a], data, wrk_r * wrk_r * stride);
+ }
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (img);
+ cairo_surface_destroy (work);
+
+ return true;
+}
+#endif
+
+/*boilerplate */
+WormouseScreen::WormouseScreen (CompScreen *screen):
+ PluginClassHandler <WormouseScreen, CompScreen> (screen),
+#ifndef _CACHE_ROTATION_
+ img (NULL), work (NULL), cr (NULL),
+#endif
+ cursor (0), xci (NULL)
+{
+ poller.setCallback (boost::bind (&WormouseScreen::mouseMove, this, _1));
+
+ optionSetCursorImageNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
+ optionSetShowHotspotNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
+ optionSetHotspotXNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
+ optionSetHotspotYNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
+ optionSetTailFactorNotify(boost::bind (&WormouseScreen::updateConfig, this, _1, _2));
+
+#ifdef _CACHE_ROTATION_
+ memset (imageCache, 0, sizeof(imageCache));
+#endif
+
+
+ if (!updateConfig(NULL, Options()))
+ setFailed ();
+}
+
+WormouseScreen::~WormouseScreen ()
+{
+ freeResources ();
+}
bool
WormousePluginVTable::init ()
{
- if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
- return false;
- //TODO: query Xfixes / Xcursor extensions
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
+ !CompPlugin::checkPluginABI ("mousepoll", COMPIZ_MOUSEPOLL_ABI))
+ return false;
+
+ int fixesEventBase, fixesErrorBase;
+ if (!XFixesQueryExtension(screen->dpy (), &fixesEventBase, &fixesErrorBase))
+ return false;
return true;
}
diff --git a/src/wormouse.h b/src/wormouse.h
index 8355855..9199d04 100644
--- a/src/wormouse.h
+++ b/src/wormouse.h
@@ -27,6 +27,8 @@ extern "C" {
#include "wormouse_options.h"
+#define _CACHE_ROTATION_
+
class WormouseScreen :
public PluginClassHandler <WormouseScreen, CompScreen>,
public WormouseOptions
@@ -44,11 +46,18 @@ class WormouseScreen :
private:
void freeResources ();
void rotateCursor (double radians);
+#ifdef _CACHE_ROTATION_
+ bool buildCache (const CompString &path);
+#endif
// workbench for cursor rotation
- cairo_t *cr;
+#ifdef _CACHE_ROTATION_
+ XcursorPixel *imageCache[360];
+#else
cairo_surface_t *img;
cairo_surface_t *work;
+ cairo_t *cr;
+#endif
Cursor cursor;
XcursorImage *xci;
MousePoller poller;