summaryrefslogtreecommitdiff
path: root/src/snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/snap.c')
-rw-r--r--src/snap.c1168
1 files changed, 0 insertions, 1168 deletions
diff --git a/src/snap.c b/src/snap.c
deleted file mode 100644
index 4bd7b43..0000000
--- a/src/snap.c
+++ /dev/null
@@ -1,1168 +0,0 @@
-/*
- * Beryl Snap Plugin
- * Author : Guillaume "iXce" Seguin
- * Email : ixce@beryl-project.org
- *
- * Ported by : Patrick "marex" Niklaus
- * Email : marex@beryl-project.org
- *
- * Copyright (C) 2007 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.
- */
-
-/*
- * TODO
- * - Apply Edge Resistance to resize
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include <compiz.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)->privates[displayPrivateIndex].ptr)
-
-#define SNAP_DISPLAY(d) \
- SnapDisplay *sd = GET_SNAP_DISPLAY (d)
-
-#define GET_SNAP_SCREEN(s, sd) \
- ((SnapScreen *) (s)->privates[(sd)->screenPrivateIndex].ptr)
-
-#define SNAP_SCREEN(s) \
- SnapScreen *ss = GET_SNAP_SCREEN (s, GET_SNAP_DISPLAY (s->display))
-
-#define GET_SNAP_WINDOW(w, ss) \
- ((SnapWindow *) (w)->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)))
-
-// 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;
-}
-
-/*
- * Wrapper functions to avoid infinite notify loops
- */
-static void snapMoveWindow(CompWindow * w, int dx, int dy)
-{
- SNAP_WINDOW(w);
- sw->skipNotify = TRUE;
- moveWindow(w, dx, dy, TRUE, TRUE);
- warpPointer(w->screen, dx, dy);
- sw->skipNotify = FALSE;
-}
-
-static void snapResizeWindow(CompWindow * w, int dx, int dy, int dw, int dh)
-{
- 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;
-}
-
-static void snapFreeEdges(CompWindow * w)
-{
- SNAP_WINDOW(w);
- Edge *current = sw->edges, *next;
-
- while (current)
- {
- next = current->next;
- free(current);
- current = next;
- }
- sw->edges = sw->reverseEdges = NULL;
-}
-
-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);
-}
-
-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;
-}
-
-/*
- * Add an edge for each rectangle of the region
- */
-static void snapAddRegionEdges(SnapWindow * sw, Edge * parent, Region region)
-{
- Edge *edge;
- int i, position, start, end;
-
- for (i = 0; i < region->numRects; i++)
- {
- 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;
- }
-}
-
-/* Checks if a window is considered a snap window. If it's
- * not visible, returns false. If it's a panel and we're
- * snapping to screen edges, it's considered a snap-window.
- */
-
-#define UNLIKELY(x) __builtin_expect(!!(x),0)
-
-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;
-}
-
-// 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)
- {
- // 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;
- }
-
- // 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)
- {
- 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);
- }
- }
-}
-
-/*
- * Loop on outputDevs and add the extents as edges
- * Note that left side is a right edge, right side a left edge,
- * 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)
- {
- 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);
- }
- }
-}
-
-/*
- * Clean edges and fill it again with appropriate edges
- */
-static void snapUpdateEdges(CompWindow * w)
-{
- //SNAP_SCREEN(w->screen);
-
- snapFreeEdges(w);
-
- snapUpdateWindowsEdges(w);
-
- if (snapGetEdgesCategoriesMask(w->screen) & EdgesCategoriesScreenEdgesMask)
- snapUpdateScreenEdges(w);
-}
-
-// Edges checking functions (move) ---------------------------------------------
-
-/*
- * Find nearest edge in the direction set by "type",
- * w is the grabbed window, position/start/end are the window edges coordinates
- * 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;
-
- while (current)
- {
- // 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;
- }
- // We found a 0-dist edge, or we have a snapping candidate
- if (min == 0 || (min <= snapGetAttractionDistance(w->screen)
- && snapGetSnapTypeMask(w->screen) & SnapTypeEdgeAttractionMask))
- {
- // 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;
- }
- }
- }
-}
-
-/*
- * 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);
-}
-
-// Edges checking functions (resize) -------------------------------------------
-
-/*
- * 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;
-
- while (current)
- {
- // 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;
- }
- // We found a 0-dist edge, or we have a snapping candidate
- if (min == 0 || (min <= snapGetAttractionDistance(w->screen)
- && snapGetSnapTypeMask(w->screen) & SnapTypeEdgeAttractionMask))
- {
- // 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;
- }
- }
- }
-}
-
-/*
- * 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)
-{
- 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);
-}
-
-// avoidSnap functions ---------------------------------------------------------
-
-static Bool
-snapEnableSnapping(CompDisplay * d,
- CompAction * action,
- CompActionState state, CompOption * option, int nOption)
-{
- SNAP_DISPLAY(d);
- sd->snapping = TRUE;
- return FALSE;
-}
-
-static Bool
-snapDisableSnapping(CompDisplay * d,
- CompAction * action,
- CompActionState state, CompOption * option, int nOption)
-{
- SNAP_DISPLAY(d);
- sd->snapping = FALSE;
- return FALSE;
-}
-
-// Check if avoidSnap is matched, and enable/disable snap consequently
-static void snapHandleEvent(CompDisplay * d, XEvent * event)
-{
- SNAP_DISPLAY(d);
-
- if (event->type == d->xkbEvent)
- {
- XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event;
-
- if (xkbEvent->xkb_type == XkbStateNotify)
- {
- XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event;
- unsigned int mods = 0xffffffff;
-
- if (sd->avoidSnapMask)
- mods = sd->avoidSnapMask;
-
- if ((stateEvent->mods & mods) == mods)
- snapDisableSnapping(d, NULL, 0, NULL, 0);
- else
- snapEnableSnapping(d, NULL, 0, NULL, 0);
- }
- }
-
- UNWRAP(sd, d, handleEvent);
- (*d->handleEvent) (d, event);
- WRAP(sd, d, handleEvent, snapHandleEvent);
-}
-
-// Events notifications --------------------------------------------------------
-
-static void
-snapWindowResizeNotify(CompWindow * w, int dx, int dy, int dw, int dh)
-{
- SNAP_DISPLAY (w->screen->display);
- SNAP_SCREEN(w->screen);
- SNAP_WINDOW (w);
-
- UNWRAP(ss, w->screen, windowResizeNotify);
- (*w->screen->windowResizeNotify) (w, dx, dy, dw, dh);
- WRAP(ss, w->screen, windowResizeNotify, snapWindowResizeNotify);
-
- // avoid-infinite-notify-loop mode/not grabbed
- if (sw->skipNotify || !(sw->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;
- }
-
- // avoiding snap, nothing buffered
- if (!sd->snapping)
- return;
-
- // apply edge resistance
- if (snapGetSnapTypeMask(w->screen) & 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 (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;
- }
-
- // 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))
- {
- snapMoveWindow(w, sw->dx, sw->dy);
- sw->dx = sw->dy = 0;
- return;
- }
-
- // avoiding snap, nothing buffered
- if (!sd->snapping)
- return;
-
- // apply edge resistance
- if (snapGetSnapTypeMask(w->screen) & 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 (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;
- }
- // If we don't already snap vertically and horizontally,
- // check edges status
- if (sw->snapDirection != (VerticalSnap | HorizontalSnap))
- snapMoveCheckEdges(w);
-}
-
-/*
- * Initiate snap, get edges
- */
-static void
-snapWindowGrabNotify(CompWindow * w,
- 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);
-
- UNWRAP(ss, w->screen, windowGrabNotify);
- (*w->screen->windowGrabNotify) (w, x, y, state, mask);
- WRAP(ss, w->screen, windowGrabNotify, snapWindowGrabNotify);
-}
-
-/*
- * 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;
-
- 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->privates[displayPrivateIndex].ptr = sd;
-
- return TRUE;
-}
-
-static void snapFiniDisplay(CompPlugin * p, CompDisplay * d)
-{
- SNAP_DISPLAY(d);
-
- freeScreenPrivateIndex(d, sd->screenPrivateIndex);
-
- UNWRAP(sd, d, handleEvent);
-
- free(sd);
-}
-
-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->privates[sd->screenPrivateIndex].ptr = ss;
-
- return TRUE;
-}
-
-static void snapFiniScreen(CompPlugin * p, CompScreen * s)
-{
- SNAP_SCREEN(s);
-
- freeWindowPrivateIndex(s, ss->windowPrivateIndex);
-
- //UNWRAP(ss, s, windowResizeNotify);
- UNWRAP(ss, s, windowMoveNotify);
- UNWRAP(ss, s, windowGrabNotify);
- UNWRAP(ss, s, windowUngrabNotify);
-
- free(ss);
-}
-
-static Bool snapInitWindow(CompPlugin * p, CompWindow * w)
-{
- SnapWindow *sw;
-
- SNAP_SCREEN(w->screen);
-
- 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->privates[ss->windowPrivateIndex].ptr = sw;
-
- return TRUE;
-}
-
-static void snapFiniWindow(CompPlugin * p, CompWindow * w)
-{
- SNAP_WINDOW(w);
-
- snapFreeEdges(w);
-
- free(sw);
-}
-
-static Bool snapInit(CompPlugin * p)
-{
- displayPrivateIndex = allocateDisplayPrivateIndex();
- if (displayPrivateIndex < 0)
- return FALSE;
- return TRUE;
-}
-
-static void snapFini(CompPlugin * p)
-{
- if (displayPrivateIndex >= 0)
- freeDisplayPrivateIndex(displayPrivateIndex);
-}
-
-static int
-snapGetVersion(CompPlugin * plugin, int version)
-{
- return ABIVERSION;
-}
-
-CompPluginVTable snapVTable = {
- "snap",
- snapGetVersion,
- 0,
- snapInit,
- snapFini,
- snapInitDisplay,
- snapFiniDisplay,
- snapInitScreen,
- snapFiniScreen,
- snapInitWindow,
- snapFiniWindow,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
-};
-
-CompPluginVTable *getCompPluginInfo(void)
-{
- return &snapVTable;
-}