summaryrefslogtreecommitdiff
path: root/src/snap.h
blob: 794bb405dd04b49b51a61fb4649f0ed828a58374 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * 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/pluginclasshandler.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 PluginClassHandler <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 PluginClassHandler <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 m_dx;
	int m_dy;
	int m_dwidth;
	int m_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);

	void 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 ();
};