summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Watkins <amaranth@ubuntu.com>2009-01-21 01:47:19 -0600
committerTravis Watkins <travis@ronin.(none)>2009-01-21 01:47:19 -0600
commita6973aa7911087a884f46683824a6969e7517daa (patch)
tree02a453cb6af5cd0aaf8f1add2ec2e8a1e7e0a317
parenta89a2651fe8a154ed8e1be41d119fec6e4ebef57 (diff)
downloadautoresize-a6973aa7911087a884f46683824a6969e7517daa.tar.gz
autoresize-a6973aa7911087a884f46683824a6969e7517daa.tar.bz2
compiles, loads, doesn't do anything
-rw-r--r--snap.cpp1623
-rw-r--r--snap.h178
2 files changed, 824 insertions, 977 deletions
diff --git a/snap.cpp b/snap.cpp
index da316bc..68279de 100644
--- a/snap.cpp
+++ b/snap.cpp
@@ -1,12 +1,15 @@
/*
- * Beryl Snap Plugin
+ * Compiz snap plugin
* Author : Guillaume "iXce" Seguin
* Email : ixce@beryl-project.org
*
- * Ported by : Patrick "marex" Niklaus
- * Email : marex@beryl-project.org
+ * Ported to compiz by : Patrick "marex" Niklaus
+ * Email : marex@beryl-project.org
*
- * Copyright (C) 2007 Guillaume Seguin
+ * Ported to C++ by : Travis Watkins
+ * Email : amaranth@ubuntu.com
+ *
+ * Copyright (C) 2009 Guillaume Seguin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -32,271 +35,93 @@
#include <string.h>
#include <math.h>
-#include <compiz-core.h>
-
-#include "snap_options.h"
-
-/*
- * The neat window coordinates macros
- */
-#define WIN_X(w) ((w)->attrib.x - (w)->input.left)
-#define WIN_Y(w) ((w)->attrib.y - (w)->input.top)
-#define WIN_W(w) ((w)->width + (w)->input.left + (w)->input.right)
-#define WIN_H(w) ((w)->height + (w)->input.top + (w)->input.bottom)
-
-/*
- * The window we should snap too if snapping to windows
- */
-#define SNAP_WINDOW_TYPE (CompWindowTypeNormalMask | \
- CompWindowTypeToolbarMask | \
- CompWindowTypeMenuMask | \
- CompWindowTypeUtilMask)
-
-#define VerticalSnap (1L << 0)
-#define HorizontalSnap (1L << 1)
-
-#define MoveGrab (1L << 0)
-#define ResizeGrab (1L << 1)
-
-typedef enum
-{
- LeftEdge = 0,
- RightEdge,
- TopEdge,
- BottomEdge
-} EdgeType;
-
-typedef struct _Edge Edge;
-
-/* Custom Edge struct, linked list
- * Position, start, end meanings are specific to type :
- * - LeftEdge/RightEdge : position : x, start/end : y1/y2
- * - TopEdge/BottomEdge : position : y, start/end : x1/x2
- * id/passed are used during visibility detection when adding edges
- * snapped is straight forward
- */
-struct _Edge
-{
- Edge *prev;
- Edge *next;
-
- int position;
- int start;
- int end;
- EdgeType type;
- Bool screenEdge;
-
- Window id;
- Bool passed;
-
- Bool snapped;
-};
-
-static int displayPrivateIndex;
-
-typedef struct _SnapDisplay
-{
- int screenPrivateIndex;
- HandleEventProc handleEvent;
-
- int avoidSnapMask;
-
- // Used to check is avoidSnapMask is currently matched
- Bool snapping;
-} SnapDisplay;
-
-#define SNAP_SCREEN_OPTION_SNAP_TYPE 0
-#define SNAP_SCREEN_OPTION_EDGES_CATEGORIES 1
-#define SNAP_SCREEN_OPTION_RESISTANCE_DISTANCE 2
-#define SNAP_SCREEN_OPTION_ATTRACTION_DISTANCE 3
-#define SNAP_SCREEN_OPTION_NUM 4
-
-typedef struct _SnapScreen
-{
- int windowPrivateIndex;
-
- WindowResizeNotifyProc windowResizeNotify;
- WindowMoveNotifyProc windowMoveNotify;
- WindowGrabNotifyProc windowGrabNotify;
- WindowUngrabNotifyProc windowUngrabNotify;
-} SnapScreen;
-
-typedef struct _SnapWindow
-{
- // Linked lists
- Edge *edges;
- Edge *reverseEdges;
-
- // bitfield
- int snapDirection;
-
- // dx/dy/dw/dh when a window is resisting to user
- int dx;
- int dy;
- int dw;
- int dh;
-
- // Internals
- Bool snapped;
- int grabbed;
-
- // Internal, avoids infinite notify loops
- Bool skipNotify;
-} SnapWindow;
-
-#define GET_SNAP_DISPLAY(d) \
- ((SnapDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
-
-#define SNAP_DISPLAY(d) \
- SnapDisplay *sd = GET_SNAP_DISPLAY (d)
-
-#define GET_SNAP_SCREEN(s, sd) \
- ((SnapScreen *) (s)->base.privates[(sd)->screenPrivateIndex].ptr)
-
-#define SNAP_SCREEN(s) \
- SnapScreen *ss = GET_SNAP_SCREEN (s, GET_SNAP_DISPLAY (s->display))
+#include "snap.h"
-#define GET_SNAP_WINDOW(w, ss) \
- ((SnapWindow *) (w)->base.privates[(ss)->windowPrivateIndex].ptr)
-#define SNAP_WINDOW(w) \
- SnapWindow *sw = GET_SNAP_WINDOW (w, \
- GET_SNAP_SCREEN (w->screen, \
- GET_SNAP_DISPLAY (w->screen->display)))
+COMPIZ_PLUGIN_20081216 (snap, SnapPluginVTable);
-// Helper functions ------------------------------------------------------------
-
-/*
- * copied from Beryl's core
- */
-static void snapScreenGetOutputDevRect(CompScreen * s, int outputDev, XRectangle * outputRect)
-{
- if (!outputRect)
- return;
-
- if (outputDev >= s->nOutputDev)
- outputDev = 0;
-
- outputRect->x = s->outputDev[outputDev].region.extents.x1;
- outputRect->y = s->outputDev[outputDev].region.extents.y1;
- outputRect->width =
- s->outputDev[outputDev].region.extents.x2 -
- s->outputDev[outputDev].region.extents.x1;
- outputRect->height =
- s->outputDev[outputDev].region.extents.y2 -
- s->outputDev[outputDev].region.extents.y1;
-}
+// helper functions
/*
* Wrapper functions to avoid infinite notify loops
*/
-static void snapMoveWindow(CompWindow * w, int dx, int dy)
+void
+SnapWindow::move (int dx, int dy)
{
- SNAP_WINDOW(w);
- sw->skipNotify = TRUE;
- moveWindow(w, dx, dy, TRUE, TRUE);
- warpPointer(w->screen, dx, dy);
- sw->skipNotify = FALSE;
+ skipNotify = true;
+ window->move (dx, dy, true);
+ screen->warpPointer (dx, dy);
+ skipNotify = false;
}
-static void snapResizeWindow(CompWindow * w, int dx, int dy, int dw, int dh)
+void
+SnapWindow::resize (int dx, int dy, int dwidth, int dheight)
{
- SNAP_WINDOW(w);
- //fprintf (stderr, "Resizing: %d, %d, %d, %d\n", dx, dy, dw, dh);
- sw->skipNotify = TRUE;
- resizeWindow(w, w->attrib.x + dx, w->attrib.y + dy,
- w->attrib.width + dw, w->attrib.height + dh,
- w->attrib.border_width);
- sw->skipNotify = FALSE;
+ CompWindow::Geometry geometry = window->geometry ();
+ skipNotify = true;
+ window->resize (geometry.x () + dx, geometry.y () + dy,
+ geometry.width () + dwidth, geometry.height () + dheight,
+ geometry.border ());
+ skipNotify = false;
}
-static void snapFreeEdges(CompWindow * w)
+Edge *
+SnapWindow::addEdge (Window id,
+ int position,
+ int start,
+ int end,
+ EdgeType type,
+ bool screenEdge)
{
- SNAP_WINDOW(w);
- Edge *current = sw->edges, *next;
+ Edge *edge = (Edge *)malloc (sizeof (Edge));
+ if (!edge)
+ return NULL;
- while (current)
- {
- next = current->next;
- free(current);
- current = next;
- }
- sw->edges = sw->reverseEdges = NULL;
-}
+ edge->position = position;
+ edge->start = start;
+ edge->end = end;
+ edge->type = type;
+ edge->screenEdge = screenEdge;
+ edge->snapped = false;
+ edge->passed = false;
+ edge->id = id;
-static void snapRemoveEdge(Edge * edge)
-{
- if (edge == NULL)
- return;
- if (edge->prev)
- edge->prev->next = edge->next;
- if (edge->next)
- edge->next->prev = edge->prev;
- free(edge);
-}
+ edges.push_back (edge);
-static Edge *snapAddEdge(Edge ** edges, Edge ** reverseEdges, Window id,
- int position, int start, int end, EdgeType type,
- Bool screenEdge)
-{
- Edge *edge = malloc(sizeof(Edge));
-
- if (!edge)
- return NULL;
- edge->next = NULL;
- edge->position = position;
- edge->start = start;
- edge->end = end;
- edge->type = type;
- edge->screenEdge = screenEdge;
- edge->snapped = FALSE;
- edge->passed = FALSE;
- edge->id = id;
- if (!*edges)
- {
- edge->prev = NULL;
- *reverseEdges = *edges = edge;
- }
- else
- {
- edge->prev = *reverseEdges;
- edge->prev->next = edge;
- *reverseEdges = edge;
- }
- return edge;
+ return edge;
}
/*
* Add an edge for each rectangle of the region
*/
-static void snapAddRegionEdges(SnapWindow * sw, Edge * parent, Region region)
+void
+SnapWindow::addRegionEdges (Edge *parent, CompRegion region)
{
- Edge *edge;
- int i, position, start, end;
+ Edge *edge;
+ int i, position, start, end;
- for (i = 0; i < region->numRects; i++)
+ for (i = 0; i < region.numRects (); i++)
+ {
+ switch (parent->type)
{
- switch (parent->type)
- {
- case LeftEdge:
- case RightEdge:
- position = region->rects[i].x1;
- start = region->rects[i].y1;
- end = region->rects[i].y2;
- break;
- case TopEdge:
- case BottomEdge:
- default:
- position = region->rects[i].y1;
- start = region->rects[i].x1;
- end = region->rects[i].x2;
- }
- edge = snapAddEdge(&sw->edges, &sw->reverseEdges, parent->id,
- position, start, end, parent->type,
- parent->screenEdge);
- if (edge)
- edge->passed = parent->passed;
+ case LeftEdge:
+ case RightEdge:
+ position = region.rects ()[i].x1 ();
+ start = region.rects ()[i].y1 ();
+ end = region.rects ()[i].y2 ();
+ break;
+ case TopEdge:
+ case BottomEdge:
+ default:
+ position = region.rects ()[i].y1 ();
+ start = region.rects ()[i].x1 ();
+ end = region.rects ()[i].x2 ();
}
+ edge = addEdge (parent->id, position, start, end, parent->type,
+ parent->screenEdge);
+ if (edge)
+ edge->passed = parent->passed;
+ }
}
/* Checks if a window is considered a snap window. If it's
@@ -306,123 +131,114 @@ static void snapAddRegionEdges(SnapWindow * sw, Edge * parent, Region region)
#define UNLIKELY(x) __builtin_expect(!!(x),0)
-static inline Bool isSnapWindow(CompWindow * w)
+static inline bool
+isSnapWindow (CompWindow *w)
{
- //SNAP_SCREEN(w->screen);
-
- if (UNLIKELY(!w))
- return FALSE;
- if (w->invisible || w->hidden || w->minimized)
- return FALSE;
- if ((w->type & SNAP_WINDOW_TYPE) &&
- (snapGetEdgesCategoriesMask(w->screen) & EdgesCategoriesWindowEdgesMask))
- return TRUE;
- if (w->struts &&
- (snapGetEdgesCategoriesMask(w->screen) & EdgesCategoriesScreenEdgesMask))
- return TRUE;
- return FALSE;
+ SNAP_SCREEN (screen);
+
+ if (UNLIKELY(!w))
+ return false;
+ if (w->invisible () || /*w->hidden () ||*/ w->minimized ())
+ return false;
+ if ((w->type () & SNAP_WINDOW_TYPE) &&
+ (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesWindowEdgesMask))
+ return true;
+ if (w->struts () &&
+ (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask))
+ return true;
+ return false;
}
// Edges update functions ------------------------------------------------------
/*
* Detect visible windows edges
*/
-static void snapUpdateWindowsEdges(CompWindow * w)
-{
- CompWindow *c = NULL;
- Edge *e = NULL, *next = NULL;
-
- SNAP_WINDOW(w);
- Region edgeRegion, resultRegion;
- XRectangle rect;
- Bool remove = FALSE;
-
- // First add all the windows
- c = w->screen->windows;
- while (c)
+void
+SnapWindow::updateWindowsEdges ()
+{
+ CompRegion edgeRegion, resultRegion;
+ XRectangle rect;
+ CompRect *cRect;
+ bool remove = false;
+
+ // First add all the windows
+ foreach (CompWindow *w, screen->windows ())
+ {
+ // Just check that we're not trying to snap to current window,
+ // that the window is not invisible and of a valid type
+ if (w == window || !isSnapWindow (w))
{
- // Just check that we're not trying to snap to current window,
- // that the window is not invisible and of a valid type
- if (c == w || !isSnapWindow(c))
- {
- c = c->next;
- continue;
- }
- snapAddEdge(&sw->edges, &sw->reverseEdges, c->id,
- WIN_Y(c), WIN_X(c), WIN_X(c) + WIN_W(c), TopEdge, FALSE);
- snapAddEdge(&sw->edges, &sw->reverseEdges, c->id,
- WIN_Y(c) + WIN_H(c), WIN_X(c), WIN_X(c) + WIN_W(c),
- BottomEdge, FALSE);
- snapAddEdge(&sw->edges, &sw->reverseEdges, c->id,
- WIN_X(c), WIN_Y(c), WIN_Y(c) + WIN_H(c), LeftEdge, FALSE);
- snapAddEdge(&sw->edges, &sw->reverseEdges, c->id,
- WIN_X(c) + WIN_W(c), WIN_Y(c), WIN_Y(c) + WIN_H(c),
- RightEdge, FALSE);
- c = c->next;
+ continue;
}
-
- // Now strip invisible edges
- // Loop through all the windows stack, and through all the edges
- // If an edge has been passed, check if it's in the region window,
- // if the edge is fully under the window, drop it, or if it's only
- // partly covered, cut it/split it in one/two smaller visible edges
- for (c = w->screen->windows; c; c = c->next)
+ addEdge (w->id (), WIN_Y (w), WIN_X (w), WIN_X (w) + WIN_W (w),
+ TopEdge, false);
+ addEdge (w->id (), WIN_Y (w) + WIN_H (w), WIN_X (w),
+ WIN_X (w) + WIN_W (w), BottomEdge, false);
+ addEdge (w->id (), WIN_X (w), WIN_Y (w), WIN_Y (w) + WIN_H (w),
+ LeftEdge, false);
+ addEdge (w->id (), WIN_X (w) + WIN_W (w), WIN_Y (w),
+ WIN_Y (w) + WIN_H (w), RightEdge, false);
+ }
+
+ // Now strip invisible edges
+ // Loop through all the windows stack, and through all the edges
+ // If an edge has been passed, check if it's in the region window,
+ // if the edge is fully under the window, drop it, or if it's only
+ // partly covered, cut it/split it in one/two smaller visible edges
+ foreach (CompWindow *w, screen->windows ())
+ {
+ if (w == window || !isSnapWindow (w))
+ continue;
+
+ // can't use foreach here because we need the iterator for erase()
+ for (std::list<Edge *>::iterator it = edges.begin ();
+ it != edges.end ();)
{
- if (c == w || !isSnapWindow(c))
- continue;
- for (e = sw->edges; e; e = next)
- {
- if (!e->passed)
- {
- if (e->id == c->id)
- e->passed = TRUE;
- next = e->next;
- continue;
- }
- switch (e->type)
- {
- case LeftEdge:
- case RightEdge:
- rect.x = e->position;
- rect.y = e->start;
- rect.width = 1;
- rect.height = e->end - e->start;
- break;
- case TopEdge:
- case BottomEdge:
- default:
- rect.x = e->start;
- rect.y = e->position;
- rect.width = e->end - e->start;
- rect.height = 1;
- }
- // If the edge is in the window region, remove it,
- // if it's partly in the region, split it
- edgeRegion = XCreateRegion();
- resultRegion = XCreateRegion();
- XUnionRectWithRegion(&rect, edgeRegion, edgeRegion);
- XSubtractRegion(edgeRegion, c->region, resultRegion);
- if (XEmptyRegion(resultRegion))
- remove = TRUE;
- else if (!XEqualRegion(edgeRegion, resultRegion))
- {
- snapAddRegionEdges(sw, e, resultRegion);
- remove = TRUE;
- }
- next = e->next;
- if (remove)
- {
- if (e->prev == NULL)
- sw->edges = e->next;
- if (e->next == NULL)
- sw->reverseEdges = e->prev;
- snapRemoveEdge(e);
- remove = FALSE;
- }
- XDestroyRegion(resultRegion);
- XDestroyRegion(edgeRegion);
- }
+ Edge *e = *it;
+ if (!e->passed)
+ {
+ if (e->id == w->id ())
+ e->passed = TRUE;
+ continue;
+ }
+ switch (e->type)
+ {
+ case LeftEdge:
+ case RightEdge:
+ rect.x = e->position;
+ rect.y = e->start;
+ rect.width = 1;
+ rect.height = e->end - e->start;
+ break;
+ case TopEdge:
+ case BottomEdge:
+ default:
+ rect.x = e->start;
+ rect.y = e->position;
+ rect.width = e->end - e->start;
+ rect.height = 1;
+ }
+
+ // If the edge is in the window region, remove it,
+ // if it's partly in the region, split it
+ cRect = new CompRect (rect);
+ edgeRegion = edgeRegion.united (*cRect);
+ resultRegion = edgeRegion.subtracted (w->region ());
+ if (resultRegion.isEmpty ())
+ remove = true;
+ else if (edgeRegion != resultRegion)
+ {
+ addRegionEdges (e, resultRegion);
+ remove = true;
+ }
+
+ if (remove)
+ {
+ edges.erase (it);
+ remove = false;
+ }
}
+ }
}
/*
@@ -431,104 +247,90 @@ static void snapUpdateWindowsEdges(CompWindow * w)
* top side a bottom edge and bottom side a top edge,
* since they will be snapped as the right/left/bottom/top edge of a window
*/
-static void snapUpdateScreenEdges(CompWindow * w)
-{
- CompWindow *c = NULL;
- Edge *e = NULL, *next = NULL;
-
- SNAP_WINDOW(w);
- Region edgeRegion, resultRegion;
- XRectangle rect;
- Bool remove = FALSE;
-
- XRectangle area;
- int i;
-
- for (i = 0; i < w->screen->nOutputDev; i++)
- {
- snapScreenGetOutputDevRect(w->screen, i, &area);
- snapAddEdge(&sw->edges, &sw->reverseEdges, 0,
- area.y, area.x, area.x + area.width - 1, BottomEdge, TRUE);
- snapAddEdge(&sw->edges, &sw->reverseEdges, 0,
- area.y + area.height, area.x,
- area.x + area.width - 1, TopEdge, TRUE);
- snapAddEdge(&sw->edges, &sw->reverseEdges, 0,
- area.x, area.y, area.y + area.height - 1, RightEdge, TRUE);
- snapAddEdge(&sw->edges, &sw->reverseEdges, 0,
- area.x + area.width, area.y,
- area.y + area.height - 1, LeftEdge, TRUE);
- }
-
- // Drop screen edges parts that are under struts, basically apply the
- // same strategy than for windows edges visibility
- for (c = w->screen->windows; c; c = c->next)
+void
+SnapWindow::updateScreenEdges ()
+{
+ CompRegion edgeRegion, resultRegion;
+ XRectangle rect;
+ CompRect *cRect;
+ bool remove = false;
+
+ foreach (CompOutput output, screen->outputDevs ())
+ {
+ XRectangle area = output.workArea ();
+ addEdge (0, area.y, area.x, area.x + area.width - 1, BottomEdge, true);
+ addEdge (0, area.y + area.height, area.x, area.x + area.width - 1,
+ TopEdge, true);
+ addEdge (0, area.x, area.y, area.y + area.height - 1, RightEdge, true);
+ addEdge (0, area.x + area.width, area.y, area.y + area.height - 1,
+ LeftEdge, true);
+ }
+
+ // Drop screen edges parts that are under struts, basically apply the
+ // same strategy than for windows edges visibility
+ foreach (CompWindow *w, screen->windows ())
+ {
+ if (w == window || !w->struts ())
+ continue;
+
+ for (std::list<Edge *>::iterator it = edges.begin ();
+ it != edges.end ();)
{
- if (c == w || !c->struts)
- continue;
- for (e = sw->edges; e; e = next)
- {
- if (!e->screenEdge)
- {
- next = e->next;
- continue;
- }
- switch (e->type)
- {
- case LeftEdge:
- case RightEdge:
- rect.x = e->position;
- rect.y = e->start;
- rect.width = 1;
- rect.height = e->end - e->start;
- break;
- case TopEdge:
- case BottomEdge:
- default:
- rect.x = e->start;
- rect.y = e->position;
- rect.width = e->end - e->start;
- rect.height = 1;
- }
- edgeRegion = XCreateRegion();
- resultRegion = XCreateRegion();
- XUnionRectWithRegion(&rect, edgeRegion, edgeRegion);
- XSubtractRegion(edgeRegion, c->region, resultRegion);
- if (XEmptyRegion(resultRegion))
- remove = TRUE;
- else if (!XEqualRegion(edgeRegion, resultRegion))
- {
- snapAddRegionEdges(sw, e, resultRegion);
- remove = TRUE;
- }
- next = e->next;
- if (remove)
- {
- if (e->prev == NULL)
- sw->edges = e->next;
- if (e->next == NULL)
- sw->reverseEdges = e->prev;
- snapRemoveEdge(e);
- remove = FALSE;
- }
- XDestroyRegion(resultRegion);
- XDestroyRegion(edgeRegion);
- }
+ Edge *e = *it;
+ if (!e->screenEdge)
+ continue;
+
+ switch (e->type)
+ {
+ case LeftEdge:
+ case RightEdge:
+ rect.x = e->position;
+ rect.y = e->start;
+ rect.width = 1;
+ rect.height = e->end - e->start;
+ break;
+ case TopEdge:
+ case BottomEdge:
+ default:
+ rect.x = e->start;
+ rect.y = e->position;
+ rect.width = e->end - e->start;
+ rect.height = 1;
+ }
+
+ cRect = new CompRect (rect);
+ edgeRegion = edgeRegion.united (*cRect);
+ resultRegion = edgeRegion.subtracted (w->region ());
+ if (resultRegion.isEmpty ())
+ remove = true;
+ else if (edgeRegion != resultRegion)
+ {
+ addRegionEdges (e, resultRegion);
+ remove = true;
+ }
+
+ if (remove)
+ {
+ edges.erase (it);
+ remove = false;
+ }
}
+ }
}
/*
* Clean edges and fill it again with appropriate edges
*/
-static void snapUpdateEdges(CompWindow * w)
+void
+SnapWindow::updateEdges ()
{
- //SNAP_SCREEN(w->screen);
+ SNAP_SCREEN (screen);
- snapFreeEdges(w);
+ edges.clear ();
+ updateWindowsEdges ();
- snapUpdateWindowsEdges(w);
-
- if (snapGetEdgesCategoriesMask(w->screen) & EdgesCategoriesScreenEdgesMask)
- snapUpdateScreenEdges(w);
+ if (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask)
+ updateScreenEdges ();
}
// Edges checking functions (move) ---------------------------------------------
@@ -539,94 +341,97 @@ static void snapUpdateEdges(CompWindow * w)
* before : if true the window has to be before the edge (top/left being origin)
* snapDirection : just an helper, related to type
*/
-static void
-snapMoveCheckNearestEdge(CompWindow * w, int position, int start, int end,
- Bool before, EdgeType type, int snapDirection)
-{
- //SNAP_SCREEN(w->screen);
- SNAP_WINDOW(w);
- Edge *current = sw->edges;
- Edge *edge = current;
- int dist, min = 65535;
+void
+SnapWindow::moveCheckNearestEdge (int position,
+ int start,
+ int end,
+ bool before,
+ EdgeType type,
+ int snapDirection)
+{
+ SNAP_SCREEN (screen);
+
+ Edge *edge = edges.front ();
+ int dist, min = 65535;
+
+ foreach (Edge *current, edges)
+ {
+ // Skip wrong type or outbound edges
+ if (current->type != type || current->end < start ||
+ current->start > end)
+ {
+ continue;
+ }
- while (current)
+ // Compute distance
+ dist = before ? position - current->position
+ : current->position - position;
+ // Update minimum distance if needed
+ if (dist < min && dist >= 0)
{
- // Skip wrong type or outbound edges
- if (current->type != type
- || current->end < start || current->start > end)
- {
- current = current->next;
- continue;
- }
- // Compute distance
- dist = before ? position - current->position
- : current->position - position;
- // Update minimum distance if needed
- if (dist < min && dist >= 0)
- {
- min = dist;
- edge = current;
- }
- // 0-dist edge, just break
- if (dist == 0)
- break;
- // Unsnap edges that aren't snapped anymore
- if (current->snapped && dist > snapGetResistanceDistance(w->screen))
- current->snapped = FALSE;
- current = current->next;
+ min = dist;
+ edge = current;
}
- // We found a 0-dist edge, or we have a snapping candidate
- if (min == 0 || (min <= snapGetAttractionDistance(w->screen)
- && snapGetSnapTypeMask(w->screen) & SnapTypeEdgeAttractionMask))
+ // 0-dist edge, just break
+ if (dist == 0)
+ break;
+ // Unsnap edges that aren't snapped anymore
+ if (current->snapped && dist > ss->optionGetResistanceDistance ())
+ current->snapped = false;
+ }
+ // We found a 0-dist edge, or we have a snapping candidate
+ if (min == 0 || (min <= ss->optionGetAttractionDistance ()
+ && ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask))
+ {
+ // Update snapping data
+ if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
{
- // Update snapping data
- if (snapGetSnapTypeMask(w->screen) & SnapTypeEdgeResistanceMask)
- {
- sw->snapped = TRUE;
- sw->snapDirection |= snapDirection;
- }
- // Attract the window if needed, moving it of the correct dist
- if (min != 0 && !edge->snapped)
- {
- edge->snapped = TRUE;
- switch (type)
- {
- case LeftEdge:
- snapMoveWindow(w, min, 0);
- break;
- case RightEdge:
- snapMoveWindow(w, -min, 0);
- break;
- case TopEdge:
- snapMoveWindow(w, 0, min);
- break;
- case BottomEdge:
- snapMoveWindow(w, 0, -min);
- break;
- default:
- break;
- }
- }
+ snapped = true;
+ snapDirection |= snapDirection;
}
+ // Attract the window if needed, moving it of the correct dist
+ if (min != 0 && !edge->snapped)
+ {
+ edge->snapped = true;
+ switch (type)
+ {
+ case LeftEdge:
+ move (min, 0);
+ break;
+ case RightEdge:
+ move (-min, 0);
+ break;
+ case TopEdge:
+ move (0, min);
+ break;
+ case BottomEdge:
+ move (0, -min);
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
/*
* Call the previous function for each of the 4 sides of the window
*/
-static void snapMoveCheckEdges(CompWindow * w)
-{
- snapMoveCheckNearestEdge(w, WIN_X(w),
- WIN_Y(w), WIN_Y(w) + WIN_H(w),
- TRUE, RightEdge, HorizontalSnap);
- snapMoveCheckNearestEdge(w, WIN_X(w) + WIN_W(w),
- WIN_Y(w), WIN_Y(w) + WIN_H(w),
- FALSE, LeftEdge, HorizontalSnap);
- snapMoveCheckNearestEdge(w, WIN_Y(w),
- WIN_X(w), WIN_X(w) + WIN_W(w),
- TRUE, BottomEdge, VerticalSnap);
- snapMoveCheckNearestEdge(w, WIN_Y(w) + WIN_H(w),
- WIN_X(w), WIN_X(w) + WIN_W(w),
- FALSE, TopEdge, VerticalSnap);
+void
+SnapWindow::moveCheckEdges ()
+{
+ moveCheckNearestEdge (WIN_X (window), WIN_Y (window),
+ WIN_Y (window) + WIN_H (window), true, RightEdge,
+ HorizontalSnap);
+ moveCheckNearestEdge (WIN_X (window) + WIN_W (window), WIN_Y (window),
+ WIN_Y (window) + WIN_H (window), false, LeftEdge,
+ HorizontalSnap);
+ moveCheckNearestEdge (WIN_Y (window), WIN_X(window),
+ WIN_X (window) + WIN_W (window), true, BottomEdge,
+ VerticalSnap);
+ moveCheckNearestEdge (WIN_Y (window) + WIN_H (window),
+ WIN_X (window), WIN_X (window) + WIN_W (window),
+ false, TopEdge, VerticalSnap);
}
// Edges checking functions (resize) -------------------------------------------
@@ -634,548 +439,412 @@ static void snapMoveCheckEdges(CompWindow * w)
/*
* Similar function for Snap on Resize
*/
-static void
-snapResizeCheckNearestEdge(CompWindow * w, int position, int start, int end,
- Bool before, EdgeType type, int snapDirection)
-{
- //SNAP_SCREEN(w->screen);
- SNAP_WINDOW(w);
- Edge *current = sw->edges;
- Edge *edge = current;
- int dist, min = 65535;
+void
+SnapWindow::resizeCheckNearestEdge (int position,
+ int start,
+ int end,
+ bool before,
+ EdgeType type,
+ int snapDirection)
+{
+ SNAP_SCREEN (screen);
+
+ Edge *edge = edges.front ();
+ int dist, min = 65535;
+
+ foreach (Edge *current, edges)
+ {
+ // Skip wrong type or outbound edges
+ if (current->type != type || current->end < start ||
+ current->start > end)
+ {
+ continue;
+ }
- while (current)
+ // Compute distance
+ dist = before ? position - current->position
+ : current->position - position;
+ // Update minimum distance if needed
+ if (dist < min && dist >= 0)
{
- // Skip wrong type or outbound edges
- if (current->type != type
- || current->end < start || current->start > end)
- {
- current = current->next;
- continue;
- }
- // Compute distance
- dist = before ? position - current->position
- : current->position - position;
- // Update minimum distance if needed
- if (dist < min && dist >= 0)
- {
- min = dist;
- edge = current;
- }
- // 0-dist edge, just break
- if (dist == 0)
- break;
- // Unsnap edges that aren't snapped anymore
- if (current->snapped && dist > snapGetResistanceDistance(w->screen))
- current->snapped = FALSE;
- current = current->next;
+ min = dist;
+ edge = current;
}
- // We found a 0-dist edge, or we have a snapping candidate
- if (min == 0 || (min <= snapGetAttractionDistance(w->screen)
- && snapGetSnapTypeMask(w->screen) & SnapTypeEdgeAttractionMask))
+ // 0-dist edge, just break
+ if (dist == 0)
+ break;
+ // Unsnap edges that aren't snapped anymore
+ if (current->snapped && dist > ss->optionGetResistanceDistance ())
+ current->snapped = false;
+ }
+ // We found a 0-dist edge, or we have a snapping candidate
+ if (min == 0 || (min <= ss->optionGetAttractionDistance ()
+ && ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask))
+ {
+ // Update snapping data
+ if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
{
- // Update snapping data
- if (snapGetSnapTypeMask(w->screen) & SnapTypeEdgeResistanceMask)
- {
- sw->snapped = TRUE;
- sw->snapDirection |= snapDirection;
- }
- // FIXME : this needs resize-specific code.
- // Attract the window if needed, moving it of the correct dist
- if (min != 0 && !edge->snapped)
- {
- edge->snapped = TRUE;
- switch (type)
- {
- case LeftEdge:
- snapResizeWindow(w, min, 0, 0, 0);
- break;
- case RightEdge:
- snapResizeWindow(w, -min, 0, 0, 0);
- break;
- case TopEdge:
- snapResizeWindow(w, 0, min, 0, 0);
- break;
- case BottomEdge:
- snapResizeWindow(w, 0, -min, 0, 0);
- break;
- default:
- break;
- }
- }
+ snapped = true;
+ snapDirection |= snapDirection;
}
+ // FIXME : this needs resize-specific code.
+ // Attract the window if needed, moving it of the correct dist
+ if (min != 0 && !edge->snapped)
+ {
+ edge->snapped = true;
+ switch (type)
+ {
+ case LeftEdge:
+ resize (min, 0, 0, 0);
+ break;
+ case RightEdge:
+ resize (-min, 0, 0, 0);
+ break;
+ case TopEdge:
+ resize (0, min, 0, 0);
+ break;
+ case BottomEdge:
+ resize (0, -min, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ }
}
/*
* Call the previous function for each of the 4 sides of the window
*/
-static void snapResizeCheckEdges(CompWindow * w, int dx, int dy, int dw, int dh)
+void
+SnapWindow::resizeCheckEdges (int dx, int dy, int dwidth, int dheight)
{
- int x, y, width, height;
- x = WIN_W(w);
- y = WIN_Y(w);
- width = WIN_W(w);
- height = WIN_H(w);
-
- snapResizeCheckNearestEdge(w, x, y, y + height, TRUE, RightEdge,
- HorizontalSnap);
- snapResizeCheckNearestEdge(w, x + width, y, y + height, FALSE, LeftEdge,
- HorizontalSnap);
- snapResizeCheckNearestEdge(w, y, x, x + width, TRUE, BottomEdge,
- VerticalSnap);
- snapResizeCheckNearestEdge(w, y + height, x, x + width, FALSE, TopEdge,
- VerticalSnap);
+ int x, y, width, height;
+ x = WIN_W (window);
+ y = WIN_Y (window);
+ width = WIN_W (window);
+ height = WIN_H (window);
+
+ resizeCheckNearestEdge (x, y, y + height, true, RightEdge, HorizontalSnap);
+ resizeCheckNearestEdge (x + width, y, y + height, false, LeftEdge,
+ HorizontalSnap);
+ resizeCheckNearestEdge (y, x, x + width, true, BottomEdge, VerticalSnap);
+ resizeCheckNearestEdge (y + height, x, x + width, false, TopEdge,
+ VerticalSnap);
}
// avoidSnap functions ---------------------------------------------------------
-static Bool
-snapEnableSnapping(CompDisplay * d,
- CompAction * action,
- CompActionState state, CompOption * option, int nOption)
+bool
+SnapScreen::enableSnapping (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
{
- SNAP_DISPLAY(d);
- sd->snapping = TRUE;
- return FALSE;
+ snapping = true;
+ return false;
}
-static Bool
-snapDisableSnapping(CompDisplay * d,
- CompAction * action,
- CompActionState state, CompOption * option, int nOption)
+bool
+SnapScreen::disableSnapping (CompAction *action,
+ CompAction::State state,
+ CompOption::Vector &options)
{
- SNAP_DISPLAY(d);
- sd->snapping = FALSE;
- return FALSE;
+ snapping = false;
+ return false;
}
// Check if avoidSnap is matched, and enable/disable snap consequently
-static void snapHandleEvent(CompDisplay * d, XEvent * event)
+void
+SnapScreen::handleEvent (XEvent *event)
{
- SNAP_DISPLAY(d);
+/* if (event->type == d->xkbEvent)
+ {
+ XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event;
- if (event->type == d->xkbEvent)
+ if (xkbEvent->xkb_type == XkbStateNotify)
{
- XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event;
+ XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event;
- if (xkbEvent->xkb_type == XkbStateNotify)
- {
- XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event;
- unsigned int mods = 0xffffffff;
+ unsigned int mods = 0xffffffff;
+ if (avoidSnapMask)
+ mods = avoidSnapMask;
- if (sd->avoidSnapMask)
- mods = sd->avoidSnapMask;
-
- if ((stateEvent->mods & mods) == mods)
- snapDisableSnapping(d, NULL, 0, NULL, 0);
- else
- snapEnableSnapping(d, NULL, 0, NULL, 0);
- }
+ if ((stateEvent->mods & mods) == mods)
+ disableSnapping (NULL, 0, NULL);
+ else
+ enableSnapping (NULL, 0, NULL);
}
-
- UNWRAP(sd, d, handleEvent);
- (*d->handleEvent) (d, event);
- WRAP(sd, d, handleEvent, snapHandleEvent);
+ }
+*/
+ screen->handleEvent (event);
}
// Events notifications --------------------------------------------------------
-static void
-snapWindowResizeNotify(CompWindow * w, int dx, int dy, int dw, int dh)
+void
+SnapWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
{
- SNAP_DISPLAY (w->screen->display);
- SNAP_SCREEN(w->screen);
- SNAP_WINDOW (w);
+ SNAP_SCREEN (screen);
- UNWRAP(ss, w->screen, windowResizeNotify);
- (*w->screen->windowResizeNotify) (w, dx, dy, dw, dh);
- WRAP(ss, w->screen, windowResizeNotify, snapWindowResizeNotify);
+ window->resizeNotify (dx, dy, dwidth, dheight);
- // avoid-infinite-notify-loop mode/not grabbed
- if (sw->skipNotify || !(sw->grabbed & ResizeGrab))
- return;
+ // avoid-infinite-notify-loop mode/not grabbed
+ if (skipNotify || !(grabbed & ResizeGrab))
+ return;
- // we have to avoid snapping but there's still some buffered moving
- if (!sd->snapping && (sw->dx || sw->dy || sw->dw || sw->dh))
- {
- snapResizeWindow(w, sw->dx, sw->dy, sw->dw, sw->dh);
- sw->dx = sw->dy = sw->dw = sw->dh = 0;
- return;
- }
+ // we have to avoid snapping but there's still some buffered moving
+ if (!ss->snapping && (this->dx || this->dy || this->dwidth || this->dheight))
+ {
+ resize (this->dx, this->dy, this->dwidth, this->dheight);
+ this->dx = this->dy = this->dwidth = this->dheight = 0;
+ return;
+ }
- // avoiding snap, nothing buffered
- if (!sd->snapping)
- return;
+ // avoiding snap, nothing buffered
+ if (!ss->snapping)
+ return;
- // apply edge resistance
- if (snapGetSnapTypeMask(w->screen) & SnapTypeEdgeResistanceMask)
+ // apply edge resistance
+ if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
+ {
+ // If there's horizontal snapping, add dx to current buffered
+ // dx and resist (move by -dx) or release the window and move
+ // by buffered dx - dx, same for dh
+ if (snapped && snapDirection & HorizontalSnap)
{
- // If there's horizontal snapping, add dx to current buffered
- // dx and resist (move by -dx) or release the window and move
- // by buffered dx - dx, same for dh
- if (sw->snapped && sw->snapDirection & HorizontalSnap)
- {
- sw->dx += dx;
- if (sw->dx < snapGetResistanceDistance(w->screen)
- && sw->dx > -snapGetResistanceDistance(w->screen))
- snapResizeWindow(w, -dx, 0, 0, 0);
- else
- {
- snapResizeWindow(w, sw->dx - dx, 0, 0, 0);
- sw->dx = 0;
- if (!sw->dw)
- sw->snapDirection &= VerticalSnap;
- }
- sw->dw += dw;
- if (sw->dw < snapGetResistanceDistance(w->screen)
- && sw->dw > -snapGetResistanceDistance(w->screen))
- snapResizeWindow(w, 0, 0, -dw, 0);
- else
- {
- snapResizeWindow(w, 0, 0, sw->dw - dw, 0);
- sw->dw = 0;
- if (!sw->dx)
- sw->snapDirection &= VerticalSnap;
- }
- }
- // Same for vertical snapping and dy/dh
- if (sw->snapped && sw->snapDirection & VerticalSnap)
- {
- sw->dy += dy;
- if (sw->dy < snapGetResistanceDistance(w->screen)
- && sw->dy > -snapGetResistanceDistance(w->screen))
- snapResizeWindow(w, 0, -dy, 0, 0);
- else
- {
- snapResizeWindow(w, 0, sw->dy - dy, 0, 0);
- sw->dy = 0;
- if (!sw->dh)
- sw->snapDirection &= HorizontalSnap;
- }
- sw->dh += dh;
- if (sw->dh < snapGetResistanceDistance(w->screen)
- && sw->dh > -snapGetResistanceDistance(w->screen))
- snapResizeWindow(w, 0, 0, 0, -dh);
- else
- {
- snapResizeWindow(w, 0, 0, 0, sw->dh - dh);
- sw->dh = 0;
- if (!sw->dy)
- sw->snapDirection &= HorizontalSnap;
- }
- }
- // If we are no longer snapping in any direction, reset snapped
- if (sw->snapped && !sw->snapDirection)
- sw->snapped = FALSE;
+ this->dx += dx;
+ if (this->dx < ss->optionGetResistanceDistance ()
+ && this->dx > -ss->optionGetResistanceDistance ())
+ {
+ resize (-dx, 0, 0, 0);
+ }
+ else
+ {
+ resize (this->dx - dx, 0, 0, 0);
+ this->dx = 0;
+ if (!this->dwidth)
+ snapDirection &= VerticalSnap;
+ }
+ this->dwidth += dwidth;
+ if (this->dwidth < ss->optionGetResistanceDistance ()
+ && this->dwidth > -ss->optionGetResistanceDistance ())
+ {
+ resize (0, 0, -dwidth, 0);
+ }
+ else
+ {
+ resize (0, 0, this->dwidth - dwidth, 0);
+ this->dwidth = 0;
+ if (!this->dx)
+ snapDirection &= VerticalSnap;
+ }
}
- // If we don't already snap vertically and horizontally,
- // check edges status
- if (sw->snapDirection != (VerticalSnap | HorizontalSnap))
- snapResizeCheckEdges(w, dx, dy, dw, dh);
-}
-
-static void
-snapWindowMoveNotify(CompWindow * w, int dx, int dy, Bool immediate)
-{
- SNAP_DISPLAY(w->screen->display);
- SNAP_SCREEN(w->screen);
- SNAP_WINDOW(w);
-
- UNWRAP(ss, w->screen, windowMoveNotify);
- (*w->screen->windowMoveNotify) (w, dx, dy, immediate);
- WRAP(ss, w->screen, windowMoveNotify, snapWindowMoveNotify);
-
- // avoid-infinite-notify-loop mode/not grabbed
- if (sw->skipNotify || !(sw->grabbed & MoveGrab))
- return;
-
- // we have to avoid snapping but there's still some buffered moving
- if (!sd->snapping && (sw->dx || sw->dy))
+ // Same for vertical snapping and dy/dh
+ if (snapped && snapDirection & VerticalSnap)
{
- snapMoveWindow(w, sw->dx, sw->dy);
- sw->dx = sw->dy = 0;
- return;
+ this->dy += dy;
+ if (this->dy < ss->optionGetResistanceDistance ()
+ && this->dy > -ss->optionGetResistanceDistance ())
+ {
+ resize (0, -dy, 0, 0);
+ }
+ else
+ {
+ resize (0, this->dy - dy, 0, 0);
+ this->dy = 0;
+ if (!this->dheight)
+ snapDirection &= HorizontalSnap;
+ }
+ this->dheight += dheight;
+ if (this->dheight < ss->optionGetResistanceDistance ()
+ && this->dheight > -ss->optionGetResistanceDistance ())
+ {
+ resize (0, 0, 0, -dheight);
+ }
+ else
+ {
+ resize (0, 0, 0, this->dheight - dheight);
+ this->dheight = 0;
+ if (!this->dy)
+ snapDirection &= HorizontalSnap;
+ }
}
-
- // avoiding snap, nothing buffered
- if (!sd->snapping)
- return;
-
- // apply edge resistance
- if (snapGetSnapTypeMask(w->screen) & SnapTypeEdgeResistanceMask)
+ // If we are no longer snapping in any direction, reset snapped
+ if (snapped && !snapDirection)
+ snapped = false;
+ }
+
+ // If we don't already snap vertically and horizontally,
+ // check edges status
+ if (snapDirection != (VerticalSnap | HorizontalSnap))
+ resizeCheckEdges (dx, dy, dwidth, dheight);
+}
+
+void
+SnapWindow::moveNotify (int dx, int dy, bool immediate)
+{
+ SNAP_SCREEN (screen);
+
+ window->moveNotify (dx, dy, immediate);
+
+ // avoid-infinite-notify-loop mode/not grabbed
+ if (skipNotify || !(grabbed & MoveGrab))
+ return;
+
+ // we have to avoid snapping but there's still some buffered moving
+ if (!ss->snapping && (this->dx || this->dy))
+ {
+ move (this->dx, this->dy);
+ this->dx = this->dy = 0;
+ return;
+ }
+
+ // avoiding snap, nothing buffered
+ if (!ss->snapping)
+ return;
+
+ // apply edge resistance
+ if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
+ {
+ // If there's horizontal snapping, add dx to current buffered
+ // dx and resist (move by -dx) or release the window and move
+ // by buffered dx - dx
+ if (snapped && snapDirection & HorizontalSnap)
{
- // If there's horizontal snapping, add dx to current buffered
- // dx and resist (move by -dx) or release the window and move
- // by buffered dx - dx
- if (sw->snapped && sw->snapDirection & HorizontalSnap)
- {
- sw->dx += dx;
- if (sw->dx < snapGetResistanceDistance(w->screen)
- && sw->dx > -snapGetResistanceDistance(w->screen))
- snapMoveWindow(w, -dx, 0);
- else
- {
- snapMoveWindow(w, sw->dx - dx, 0);
- sw->dx = 0;
- sw->snapDirection &= VerticalSnap;
- }
- }
- // Same for vertical snapping and dy
- if (sw->snapped && sw->snapDirection & VerticalSnap)
- {
- sw->dy += dy;
- if (sw->dy < snapGetResistanceDistance(w->screen)
- && sw->dy > -snapGetResistanceDistance(w->screen))
- snapMoveWindow(w, 0, -dy);
- else
- {
- snapMoveWindow(w, 0, sw->dy - dy);
- sw->dy = 0;
- sw->snapDirection &= HorizontalSnap;
- }
- }
- // If we are no longer snapping in any direction, reset snapped
- if (sw->snapped && !sw->snapDirection)
- sw->snapped = FALSE;
+ this->dx += dx;
+ if (this->dx < ss->optionGetResistanceDistance ()
+ && this->dx > -ss->optionGetResistanceDistance ())
+ {
+ move (-dx, 0);
+ }
+ else
+ {
+ move (this->dx - dx, 0);
+ this->dx = 0;
+ snapDirection &= VerticalSnap;
+ }
}
- // If we don't already snap vertically and horizontally,
- // check edges status
- if (sw->snapDirection != (VerticalSnap | HorizontalSnap))
- snapMoveCheckEdges(w);
+ // Same for vertical snapping and dy
+ if (snapped && snapDirection & VerticalSnap)
+ {
+ this->dy += dy;
+ if (this->dy < ss->optionGetResistanceDistance ()
+ && this->dy > -ss->optionGetResistanceDistance ())
+ {
+ move (0, -dy);
+ }
+ else
+ {
+ move (0, this->dy - dy);
+ this->dy = 0;
+ snapDirection &= HorizontalSnap;
+ }
+ }
+ // If we are no longer snapping in any direction, reset snapped
+ if (snapped && !snapDirection)
+ snapped = false;
+ }
+ // If we don't already snap vertically and horizontally,
+ // check edges status
+ if (snapDirection != (VerticalSnap | HorizontalSnap))
+ moveCheckEdges ();
}
/*
* Initiate snap, get edges
*/
-static void
-snapWindowGrabNotify(CompWindow * w,
- int x, int y, unsigned int state, unsigned int mask)
+void
+SnapWindow::grabNotify (int x, int y, unsigned int state, unsigned int mask)
{
- SNAP_SCREEN(w->screen);
- SNAP_WINDOW(w);
-
- sw->grabbed = (mask & CompWindowGrabResizeMask) ? ResizeGrab : MoveGrab;
- snapUpdateEdges(w);
+ grabbed = (mask & CompWindowGrabResizeMask) ? ResizeGrab : MoveGrab;
+ updateEdges ();
- UNWRAP(ss, w->screen, windowGrabNotify);
- (*w->screen->windowGrabNotify) (w, x, y, state, mask);
- WRAP(ss, w->screen, windowGrabNotify, snapWindowGrabNotify);
+ window->grabNotify (x, y, state, mask);
}
/*
* Clean edges data, reset dx/dy to avoid buggy moves
* when snap will be triggered again.
*/
-static void snapWindowUngrabNotify(CompWindow * w)
-{
- SNAP_SCREEN(w->screen);
- SNAP_WINDOW(w);
-
- snapFreeEdges(w);
- sw->snapped = FALSE;
- sw->snapDirection = 0;
- sw->grabbed = 0;
- sw->dx = sw->dy = sw->dw = sw->dh = 0;
-
- UNWRAP(ss, w->screen, windowUngrabNotify);
- (*w->screen->windowUngrabNotify) (w);
- WRAP(ss, w->screen, windowUngrabNotify, snapWindowUngrabNotify);
-}
-
-// Internal stuff --------------------------------------------------------------
-
-static void snapDisplayOptionChanged(CompDisplay *d, CompOption *opt, SnapDisplayOptions num)
-{
- SNAP_DISPLAY(d);
-
- switch (num)
- {
- case SnapDisplayOptionAvoidSnap:
- {
- unsigned int mask = snapGetAvoidSnapMask(d);
- sd->avoidSnapMask = 0;
- if (mask & AvoidSnapShiftMask)
- sd->avoidSnapMask |= ShiftMask;
- if (mask & AvoidSnapAltMask)
- sd->avoidSnapMask |= CompAltMask;
- if (mask & AvoidSnapControlMask)
- sd->avoidSnapMask |= ControlMask;
- if (mask & AvoidSnapMetaMask)
- sd->avoidSnapMask |= CompMetaMask;
- }
-
- default:
- break;
- }
-}
-
-static Bool snapInitDisplay(CompPlugin * p, CompDisplay * d)
-{
- SnapDisplay *sd;
-
- if (!checkPluginABI ("core", CORE_ABIVERSION))
- return FALSE;
-
- sd = malloc(sizeof(SnapDisplay));
- if (!sd)
- return FALSE;
-
- sd->screenPrivateIndex = allocateScreenPrivateIndex(d);
- if (sd->screenPrivateIndex < 0)
- {
- free(sd);
- return FALSE;
- }
-
- WRAP(sd, d, handleEvent, snapHandleEvent);
-
- snapSetAvoidSnapNotify(d, snapDisplayOptionChanged);
-
- sd->avoidSnapMask = 0;
- sd->snapping = TRUE;
-
- d->base.privates[displayPrivateIndex].ptr = sd;
-
- return TRUE;
-}
-
-static void snapFiniDisplay(CompPlugin * p, CompDisplay * d)
+void
+SnapWindow::ungrabNotify ()
{
- SNAP_DISPLAY(d);
+ edges.clear ();
- freeScreenPrivateIndex(d, sd->screenPrivateIndex);
+ snapped = false;
+ snapDirection = 0;
+ grabbed = 0;
+ dx = dy = dwidth = dheight = 0;
- UNWRAP(sd, d, handleEvent);
-
- free(sd);
+ window->ungrabNotify ();
}
-static Bool snapInitScreen(CompPlugin * p, CompScreen * s)
-{
- SnapScreen *ss;
-
- SNAP_DISPLAY(s->display);
-
- ss = malloc(sizeof(SnapScreen));
- if (!ss)
- return FALSE;
-
- ss->windowPrivateIndex = allocateWindowPrivateIndex(s);
- if (ss->windowPrivateIndex < 0)
- {
- free(ss);
- return FALSE;
- }
-
- //WRAP(ss, s, windowResizeNotify, snapWindowResizeNotify);
- WRAP(ss, s, windowMoveNotify, snapWindowMoveNotify);
- WRAP(ss, s, windowGrabNotify, snapWindowGrabNotify);
- WRAP(ss, s, windowUngrabNotify, snapWindowUngrabNotify);
-
- s->base.privates[sd->screenPrivateIndex].ptr = ss;
-
- return TRUE;
-}
+// Internal stuff --------------------------------------------------------------
-static void snapFiniScreen(CompPlugin * p, CompScreen * s)
+void
+SnapScreen::optionChanged (CompOption *opt, SnapOptions::Options num)
{
- SNAP_SCREEN(s);
-
- freeWindowPrivateIndex(s, ss->windowPrivateIndex);
-
- //UNWRAP(ss, s, windowResizeNotify);
- UNWRAP(ss, s, windowMoveNotify);
- UNWRAP(ss, s, windowGrabNotify);
- UNWRAP(ss, s, windowUngrabNotify);
+ switch (num)
+ {
+ case SnapOptions::AvoidSnap:
+ {
+ unsigned int mask = optionGetAvoidSnapMask ();
+ avoidSnapMask = 0;
+ if (mask & AvoidSnapShiftMask)
+ avoidSnapMask |= ShiftMask;
+ if (mask & AvoidSnapAltMask)
+ avoidSnapMask |= CompAltMask;
+ if (mask & AvoidSnapControlMask)
+ avoidSnapMask |= ControlMask;
+ if (mask & AvoidSnapMetaMask)
+ avoidSnapMask |= CompMetaMask;
+ }
- free(ss);
+ default:
+ break;
+ }
}
-static Bool snapInitWindow(CompPlugin * p, CompWindow * w)
+SnapScreen::SnapScreen (CompScreen *screen) :
+ PrivateHandler <SnapScreen, CompScreen> (screen),
+ SnapOptions (snapVTable->getMetadata ()),
+ snapping (true),
+ avoidSnapMask (0)
{
- SnapWindow *sw;
+ ScreenInterface::setHandler (screen);
- SNAP_SCREEN(w->screen);
+#define setNotify(func) \
+ optionSet##func##Notify (boost::bind (&SnapScreen::optionChanged, this, _1, _2))
- sw = malloc(sizeof(SnapWindow));
- if (!sw)
- return FALSE;
-
- sw->edges = sw->reverseEdges = NULL;
- sw->snapDirection = 0;
- sw->dx = sw->dy = sw->dw = sw->dh = 0;
- sw->grabbed = 0;
- sw->snapped = FALSE;
- sw->skipNotify = FALSE;
-
- w->base.privates[ss->windowPrivateIndex].ptr = sw;
-
- return TRUE;
+ setNotify (AvoidSnap);
}
-static void snapFiniWindow(CompPlugin * p, CompWindow * w)
+SnapWindow::SnapWindow (CompWindow *window) :
+ PrivateHandler <SnapWindow, CompWindow> (window),
+ window (window),
+ snapDirection (0),
+ dx (0),
+ dy (0),
+ dwidth (0),
+ dheight (0),
+ snapped (false),
+ grabbed (0),
+ skipNotify (false)
{
- SNAP_WINDOW(w);
-
- snapFreeEdges(w);
-
- free(sw);
-}
-
-static CompBool
-snapInitObject (CompPlugin *p,
- CompObject *o)
-{
- static InitPluginObjectProc dispTab[] = {
- (InitPluginObjectProc) 0, /* InitCore */
- (InitPluginObjectProc) snapInitDisplay,
- (InitPluginObjectProc) snapInitScreen,
- (InitPluginObjectProc) snapInitWindow
- };
-
- RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
}
-static void
-snapFiniObject (CompPlugin *p,
- CompObject *o)
+SnapWindow::~SnapWindow ()
{
- static FiniPluginObjectProc dispTab[] = {
- (FiniPluginObjectProc) 0, /* FiniCore */
- (FiniPluginObjectProc) snapFiniDisplay,
- (FiniPluginObjectProc) snapFiniScreen,
- (FiniPluginObjectProc) snapFiniWindow
- };
-
- DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
+ edges.clear ();
}
-static Bool snapInit(CompPlugin * p)
+bool
+SnapPluginVTable::init ()
{
- displayPrivateIndex = allocateDisplayPrivateIndex();
- if (displayPrivateIndex < 0)
- return FALSE;
- return TRUE;
-}
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
+ return false;
-static void snapFini(CompPlugin * p)
-{
- freeDisplayPrivateIndex(displayPrivateIndex);
+ return true;
}
-CompPluginVTable snapVTable = {
- "snap",
- 0,
- snapInit,
- snapFini,
- snapInitObject,
- snapFiniObject,
- 0,
- 0
-};
-
-CompPluginVTable *getCompPluginInfo(void)
-{
- return &snapVTable;
-}
diff --git a/snap.h b/snap.h
new file mode 100644
index 0000000..86593c7
--- /dev/null
+++ b/snap.h
@@ -0,0 +1,178 @@
+/*
+ * Compiz snap plugin
+ * Author : Guillaume "iXce" Seguin
+ * Email : ixce@beryl-project.org
+ *
+ * Ported to compiz by : Patrick "marex" Niklaus
+ * Email : marex@beryl-project.org
+ *
+ * Ported to C++ by : Travis Watkins
+ * Email : amaranth@ubuntu.com
+ *
+ * Copyright (C) 2009 Guillaume Seguin
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <vector>
+
+#include <core/core.h>
+#include <core/privatehandler.h>
+
+#include "snap_options.h"
+
+/*
+ * The neat window coordinates macros
+ */
+#define WIN_X(w) ((w)->x () - (w)->input ().left)
+#define WIN_Y(w) ((w)->y () - (w)->input ().top)
+#define WIN_W(w) ((w)->width () + (w)->input ().left + (w)->input ().right)
+#define WIN_H(w) ((w)->height () + (w)->input ().top + (w)->input ().bottom)
+
+/*
+ * The window we should snap too if snapping to windows
+ */
+#define SNAP_WINDOW_TYPE (CompWindowTypeNormalMask | \
+ CompWindowTypeToolbarMask | \
+ CompWindowTypeMenuMask | \
+ CompWindowTypeUtilMask)
+
+#define VerticalSnap (1L << 0)
+#define HorizontalSnap (1L << 1)
+
+#define MoveGrab (1L << 0)
+#define ResizeGrab (1L << 1)
+
+typedef enum
+{
+ LeftEdge = 0,
+ RightEdge,
+ TopEdge,
+ BottomEdge
+} EdgeType;
+
+/* Custom Edge struct
+ * Position, start, end meanings are specific to type :
+ * - LeftEdge/RightEdge : position : x, start/end : y1/y2
+ * - TopEdge/BottomEdge : position : y, start/end : x1/x2
+ * id/passed are used during visibility detection when adding edges
+ * snapped is straight forward
+ */
+typedef struct
+{
+ int position;
+ int start;
+ int end;
+ EdgeType type;
+ bool screenEdge;
+
+ Window id;
+ bool passed;
+
+ bool snapped;
+} Edge;
+
+class SnapScreen :
+ public ScreenInterface,
+ public PrivateHandler <SnapScreen, CompScreen>,
+ public SnapOptions
+{
+ public:
+ bool snapping;
+
+ SnapScreen (CompScreen *s);
+
+ void handleEvent (XEvent *event);
+ bool enableSnapping (CompAction *action, CompAction::State state,
+ CompOption::Vector &options);
+ bool disableSnapping (CompAction *action, CompAction::State state,
+ CompOption::Vector &options);
+ void optionChanged (CompOption *opt, SnapOptions::Options num);
+
+ private:
+ // used to allow moving windows without snapping
+ int avoidSnapMask;
+};
+
+class SnapWindow :
+ public WindowInterface,
+ public PrivateHandler <SnapWindow, CompWindow>
+{
+ public:
+ SnapWindow (CompWindow *window);
+ ~SnapWindow ();
+
+ void resizeNotify (int dx, int dy, int dwidth, int dheight);
+ void moveNotify (int dx, int dy, bool immediate);
+ void grabNotify (int x, int y, unsigned int state, unsigned int mask);
+ void ungrabNotify ();
+
+ private:
+ CompWindow *window;
+
+ // linked lists
+ std::list<Edge *> edges;
+
+ // bitfield
+ int snapDirection;
+
+ // dx/dy/dw/dh when a window is resisting to user
+ int dx;
+ int dy;
+ int dwidth;
+ int dheight;
+
+ // internals
+ bool snapped;
+ int grabbed;
+
+ // internal, avoids infinite notify loops
+ bool skipNotify;
+
+
+ void move (int dx, int dy);
+ void resize (int dx, int dy, int dwidth, int dheight);
+
+ Edge *addEdge (Window id, int position, int start, int end,
+ EdgeType type, bool screenEdge);
+ void addRegionEdges (Edge *parent, CompRegion region);
+ void updateWindowsEdges ();
+ void updateScreenEdges ();
+ void updateEdges ();
+ void moveCheckNearestEdge (int position, int start, int end,
+ bool before, EdgeType type,
+ int snapDirection);
+ void moveCheckEdges ();
+ void resizeCheckNearestEdge (int position, int start, int end,
+ bool before, EdgeType type,
+ int snapDirection);
+ void resizeCheckEdges (int dx, int dy, int dwidth, int dheight);
+};
+
+#define SNAP_SCREEN(s) \
+ SnapScreen *ss = SnapScreen::get (s)
+
+#define SNAP_WINDOW(w) \
+ SnapWindow *sw = SnapWindow::get (w)
+
+class SnapPluginVTable :
+ public CompPlugin::VTableForScreenAndWindow <SnapScreen, SnapWindow>
+{
+ public:
+ bool init ();
+
+ PLUGIN_OPTION_HELPER (SnapScreen);
+};
+