~lbrulet-8/compiz-plugins-main/fix-876591

22 by Didier Roche
* debian/patches/fix-872161.patch:
1
/*
2
 * Compiz snap plugin
3
 * Author : Guillaume "iXce" Seguin
4
 * Email  : ixce@beryl-project.org
5
 *
6
 * Ported to compiz by : Patrick "marex" Niklaus
7
 * Email               : marex@beryl-project.org
8
 *
9
 * Ported to C++ by : Travis Watkins
10
 * Email            : amaranth@ubuntu.com
11
 *
12
 * Copyright (C) 2009 Guillaume Seguin
13
 *
14
 * This program is free software; you can redistribute it and/or
15
 * modify it under the terms of the GNU General Public License
16
 * as published by the Free Software Foundation; either version 2
17
 * of the License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
27
 */
28
29
/*
30
 * TODO
31
 *  - Apply Edge Resistance to resize
32
 */
33
34
#include <stdlib.h>
35
#include <string.h>
36
#include <math.h>
37
38
#include "snap.h"
39
40
41
COMPIZ_PLUGIN_20090315 (snap, SnapPluginVTable);
42
43
// helper functions
44
45
/*
46
 * Wrapper functions to avoid infinite notify loops
47
 */
48
void
49
SnapWindow::move (int dx, int dy)
50
{
51
    skipNotify = true;
52
    window->move (dx, dy, true);
53
    screen->warpPointer (dx, dy);
54
    skipNotify = false;
55
}
56
57
void
58
SnapWindow::resize (int dx, int dy, int dwidth, int dheight)
59
{
60
    CompWindow::Geometry geometry = window->geometry ();
61
    skipNotify = true;
62
    window->resize (geometry.x () + dx, geometry.y () + dy,
63
		    geometry.width () + dwidth, geometry.height () + dheight,
64
		    geometry.border ());
65
    skipNotify = false;
66
}
67
68
void
69
SnapWindow::addEdge (Window   id,
70
		     int       position,
71
		     int      start,
72
		     int      end,
73
		     EdgeType type,
74
		     bool     screenEdge)
75
{
76
    Edge edge;
77
78
    edge.position = position;
79
    edge.start = start;
80
    edge.end = end;
81
    edge.type = type;
82
    edge.screenEdge = screenEdge;
83
    edge.snapped = false;
84
    edge.passed = false;
85
    edge.id = id;
86
87
    edges.push_back (edge);
88
}
89
90
/*
91
 * Add an edge for each rectangle of the region
92
 */
93
void
94
SnapWindow::addRegionEdges (Edge *parent, CompRegion region)
95
{
96
    int position, start, end;
97
98
    foreach (const CompRect &r, region.rects ())
99
    {
100
	switch (parent->type)
101
	{
102
	case LeftEdge:
103
	case RightEdge:
104
	    position = r.x1 ();
105
	    start = r.y1 ();
106
	    end = r.y2 ();
107
	    break;
108
	case TopEdge:
109
	case BottomEdge:
110
	default:
111
	    position = r.y1 ();
112
	    start = r.x1 ();
113
	    end = r.x2 ();
114
	}
115
	
116
	addEdge (parent->id, position, start, end,
117
		 parent->type, parent->screenEdge);
118
	edges.back ().passed = parent->passed;
119
    }
120
}
121
122
/* Checks if a window is considered a snap window. If it's
123
 * not visible, returns false. If it's a panel and we're
124
 * snapping to screen edges, it's considered a snap-window.
125
 */
126
127
#define UNLIKELY(x) __builtin_expect(!!(x),0)
128
129
static inline bool
130
isSnapWindow (CompWindow *w)
131
{
132
    SNAP_SCREEN (screen);
133
134
    if (UNLIKELY(!w))
135
	return false;
136
    if (!w->isViewable ())
137
	return false;
138
    if ((w->type () & SNAP_WINDOW_TYPE) && 
139
	(ss->optionGetEdgesCategoriesMask () & EdgesCategoriesWindowEdgesMask))
140
	return true;
141
    if (w->struts () && 
142
	(ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask))
143
	return true;
144
    return false;
145
}
146
147
// Edges update functions ------------------------------------------------------
148
/*
149
 * Detect visible windows edges
150
 */
151
void
152
SnapWindow::updateWindowsEdges ()
153
{
154
    CompRegion edgeRegion, resultRegion;
155
    CompRect   input;
156
    bool       remove = false;
157
158
    // First add all the windows
159
    foreach (CompWindow *w, screen->windows ())
160
    {
161
162
	// Just check that we're not trying to snap to current window,
163
	// that the window is not invisible and of a valid type
164
	if (w == window || !isSnapWindow (w))
165
	{
166
	    continue;
167
	}
168
169
	input = w->borderRect ();
170
	addEdge (w->id (), input.top (), input.left (),
171
		 input.right (), TopEdge, false);
172
	addEdge (w->id (), input.bottom (), input.left (),
173
		 input.right (), BottomEdge, false);
174
	addEdge (w->id (), input.left (), input.top (),
175
		 input.bottom (), LeftEdge, false);
176
	addEdge (w->id (), input.right (), input.top (),
177
		 input.bottom (), RightEdge, false);
178
    }
179
180
    // Now strip invisible edges
181
    // Loop through all the windows stack, and through all the edges
182
    // If an edge has been passed, check if it's in the region window,
183
    // if the edge is fully under the window, drop it, or if it's only
184
    // partly covered, cut it/split it in one/two smaller visible edges
185
    foreach (CompWindow *w, screen->windows ())
186
    {
187
	if (w == window || !isSnapWindow (w))
188
	    continue;
189
190
	// can't use foreach here because we need the iterator for erase()
191
	for (std::list<Edge>::iterator it = edges.begin (); it != edges.end (); )
192
	{
193
	    Edge     *e = &*it;
194
	    CompRect rect;
195
196
	    if (!e->passed)
197
	    {
198
		if (e->id == w->id ())
199
		    e->passed = true;
200
		it++;
201
		continue;
202
	    }
203
204
	    switch (e->type)
205
	    {
206
		case LeftEdge:
207
		case RightEdge:
208
		    rect.setGeometry (e->position,
209
				      e->start,
210
				      1,
211
				      e->end - e->start);
212
		    break;
213
		case TopEdge:
214
		case BottomEdge:
215
		default:
216
		    rect.setGeometry (e->start,
217
				      e->position,
218
				      e->end - e->start,
219
				      1);
220
	    }
221
222
	    // If the edge is in the window region, remove it,
223
	    // if it's partly in the region, split it
224
	    edgeRegion = CompRegion (rect);
225
	    resultRegion = edgeRegion - w->region ();
226
	    if (resultRegion.isEmpty ())
227
	    {
228
		remove = true;
229
	    }
230
	    else if (edgeRegion != resultRegion)
231
	    {
232
		addRegionEdges (e, resultRegion);
233
		remove = true;
234
	    }
235
236
	    if (remove)
237
	    {
238
		it = edges.erase (it);
239
		remove = false;
240
	    }
241
	    else
242
	    {
243
		it++;
244
	    }
245
	}
246
    }
247
}
248
249
/*
250
 * Loop on outputDevs and add the extents as edges
251
 * Note that left side is a right edge, right side a left edge,
252
 * top side a bottom edge and bottom side a top edge,
253
 * since they will be snapped as the right/left/bottom/top edge of a window
254
 */
255
void
256
SnapWindow::updateScreenEdges ()
257
{
258
    CompRegion edgeRegion, resultRegion;
259
    bool remove = false;
260
261
    foreach (CompOutput output, screen->outputDevs ())
262
    {
263
	const CompRect& area = output.workArea ();
264
	addEdge (0, area.top (), area.left (), area.right () - 1,
265
		 BottomEdge, true);
266
	addEdge (0, area.bottom (), area.left (), area.right () - 1,
267
		 TopEdge, true);
268
	addEdge (0, area.left (), area.top (), area.bottom () - 1,
269
		 RightEdge, true);
270
	addEdge (0, area.right (), area.top (), area.bottom () - 1,
271
		 LeftEdge, true);
272
    }
273
274
    // Drop screen edges parts that are under struts, basically apply the
275
    // same strategy than for windows edges visibility
276
    foreach (CompWindow *w, screen->windows ())
277
    {
278
	if (w == window || !w->struts ())
279
	    continue;
280
281
	for (std::list<Edge>::iterator it = edges.begin (); it != edges.end ();)
282
	{
283
	    Edge     *e = &*it;
284
	    CompRect rect;
285
286
	    if (!e->screenEdge)
287
	    {
288
		it++;
289
		continue;
290
	    }
291
292
	    switch (e->type)
293
	    {
294
		case LeftEdge:
295
		case RightEdge:
296
		    rect.setGeometry (e->position,
297
				      e->start,
298
				      1,
299
				      e->end - e->start);
300
		    break;
301
		case TopEdge:
302
		case BottomEdge:
303
		default:
304
		    rect.setGeometry (e->start,
305
				      e->position,
306
				      e->end - e->start,
307
				      1);
308
	    }
309
310
            edgeRegion = CompRegion (rect);
311
	    resultRegion = edgeRegion - w->region ();
312
	    if (resultRegion.isEmpty ())
313
	    {
314
		remove = true;
315
	    }
316
	    else if (edgeRegion != resultRegion)
317
	    {
318
		addRegionEdges (e, resultRegion);
319
		remove = true;
320
	    }
321
322
	    if (remove)
323
	    {
324
		it = edges.erase (it);
325
		remove = false;
326
	    }
327
	    else
328
	    {
329
		it++;
330
	    }
331
	}
332
    }
333
}
334
335
/*
336
 * Clean edges and fill it again with appropriate edges
337
 */
338
void
339
SnapWindow::updateEdges ()
340
{
341
    SNAP_SCREEN (screen);
342
343
    edges.clear ();
344
    updateWindowsEdges ();
345
346
    if (ss->optionGetEdgesCategoriesMask () & EdgesCategoriesScreenEdgesMask)
347
	updateScreenEdges ();
348
}
349
350
// Edges checking functions (move) ---------------------------------------------
351
352
/*
353
 * Find nearest edge in the direction set by "type",
354
 * w is the grabbed window, position/start/end are the window edges coordinates
355
 * before : if true the window has to be before the edge (top/left being origin)
356
 * snapDirection : just an helper, related to type
357
 */
358
void
359
SnapWindow::moveCheckNearestEdge (int position,
360
				  int start,
361
				  int end,
362
				  bool before,
363
				  EdgeType type,
364
				  int snapDirection)
365
{
366
    SNAP_SCREEN (screen);
367
368
    Edge *edge = &edges.front ();
369
    int dist, min = 65535;
370
371
    foreach (Edge &current, edges)
372
    {
373
	// Skip wrong type or outbound edges
374
	if (current.type != type || current.end < start || current.start > end)
375
	    continue;
376
377
	// Compute distance
378
	dist = before ? position - current.position : current.position - position;
379
	// Update minimum distance if needed
380
	if (dist < min && dist >= 0)
381
	{
382
	    min = dist;
383
	    edge = &current;
384
	}
385
	// 0-dist edge, just break
386
	if (dist == 0)
387
	    break;
388
	// Unsnap edges that aren't snapped anymore
389
	if (current.snapped && dist > ss->optionGetResistanceDistance ())
390
	    current.snapped = false;
391
    }
392
    // We found a 0-dist edge, or we have a snapping candidate
393
    if (min == 0 || (min <= ss->optionGetAttractionDistance ()
394
	&& ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask))
395
    {
396
	// Update snapping data
397
	if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
398
	{
399
	    snapGeometry = window->geometry ();
400
	    this->snapDirection |= snapDirection;
401
	}
402
	// Attract the window if needed, moving it of the correct dist
403
	if (min != 0 && !edge->snapped)
404
	{
405
	    edge->snapped = true;
406
	    switch (type)
407
	    {
408
	    case LeftEdge:
409
		move (min, 0);
410
		break;
411
	    case RightEdge:
412
		move (-min, 0);
413
		break;
414
	    case TopEdge:
415
		move (0, min);
416
		break;
417
	    case BottomEdge:
418
		move (0, -min);
419
		break;
420
	    default:
421
		break;
422
	    }
423
	}
424
    }
425
}
426
427
/*
428
 * Call the previous function for each of the 4 sides of the window
429
 */
430
void
431
SnapWindow::moveCheckEdges ()
432
{
433
    CompRect input (window->borderRect ());
434
    moveCheckNearestEdge (input.left (), input.top (), input.bottom (),
435
			  true, RightEdge, HorizontalSnap);
436
    moveCheckNearestEdge (input.right (), input.top (), input.bottom (),
437
			  false, LeftEdge, HorizontalSnap);
438
    moveCheckNearestEdge (input.top (), input.left (), input.right (),
439
			  true, BottomEdge, VerticalSnap);
440
    moveCheckNearestEdge (input.bottom (), input.left (), input.right (),
441
			  false, TopEdge, VerticalSnap);
442
}
443
444
// Edges checking functions (resize) -------------------------------------------
445
446
/*
447
 * Similar function for Snap on Resize
448
 */
449
void
450
SnapWindow::resizeCheckNearestEdge (int position,
451
				    int start,
452
				    int end,
453
				    bool before,
454
				    EdgeType type,
455
				    int snapDirection)
456
{
457
    SNAP_SCREEN (screen);
458
459
    Edge *edge = &edges.front ();
460
    int dist, min = 65535;
461
462
    foreach (Edge &current, edges)
463
    {
464
	// Skip wrong type or outbound edges
465
	if (current.type != type || current.end < start || current.start > end)
466
	    continue;
467
468
	// Compute distance
469
	dist = before ? position - current.position : current.position - position;
470
	// Update minimum distance if needed
471
	if (dist < min && dist >= 0)
472
	{
473
	    min = dist;
474
	    edge = &current;
475
	}
476
	// 0-dist edge, just break
477
	if (dist == 0)
478
	    break;
479
	// Unsnap edges that aren't snapped anymore
480
	if (current.snapped && dist > ss->optionGetResistanceDistance ())
481
	    current.snapped = false;
482
    }
483
    // We found a 0-dist edge, or we have a snapping candidate
484
    if (min == 0 || (min <= ss->optionGetAttractionDistance ()
485
	&& ss->optionGetSnapTypeMask () & SnapTypeEdgeAttractionMask))
486
    {
487
	// Update snapping data
488
	if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
489
	{
490
	    snapGeometry = window->serverGeometry ();
491
	    this->snapDirection |= snapDirection;
492
	}
493
	// FIXME : this needs resize-specific code.
494
	// Attract the window if needed, moving it of the correct dist
495
	if (min != 0 && !edge->snapped)
496
	{
497
	    edge->snapped = true;
498
	    switch (type)
499
	    {
500
	    case LeftEdge:
501
		resize (min, 0, 0, 0);
502
		break;
503
	    case RightEdge:
504
		resize (-min, 0, 0, 0);
505
		break;
506
	    case TopEdge:
507
		resize (0, min, 0, 0);
508
		break;
509
	    case BottomEdge:
510
		resize (0, -min, 0, 0);
511
		break;
512
	    default:
513
		break;
514
	    }
515
	}
516
    }
517
}
518
519
/*
520
 * Call the previous function for each of the 4 sides of the window
521
 */
522
void
523
SnapWindow::resizeCheckEdges (int dx, int dy, int dwidth, int dheight)
524
{
525
    CompRect input (window->borderRect ());
526
527
    resizeCheckNearestEdge (input.left (), input.top (), input.bottom (),
528
			    true, RightEdge, HorizontalSnap);
529
    resizeCheckNearestEdge (input.right (), input.top (), input.bottom (),
530
			    false, LeftEdge, HorizontalSnap);
531
    resizeCheckNearestEdge (input.top (), input.left (), input.right (),
532
			    true, BottomEdge, VerticalSnap);
533
    resizeCheckNearestEdge (input.bottom (), input.left (), input.right (),
534
			    false, TopEdge, VerticalSnap);
535
}
536
537
// Check if avoidSnap is matched, and enable/disable snap consequently
538
void
539
SnapScreen::handleEvent (XEvent *event)
540
{
541
    if (event->type == screen->xkbEvent ())
542
    {
543
	XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event;
544
545
	if (xkbEvent->xkb_type == XkbStateNotify)
546
	{
547
	    XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event;
548
549
	    unsigned int mods = 0xffffffff;
550
	    if (avoidSnapMask)
551
		mods = avoidSnapMask;
552
553
	    if ((stateEvent->mods & mods) == mods)
554
		snapping = false;
555
	    else
556
		snapping = true;
557
	}
558
    }
559
560
    screen->handleEvent (event);
561
}
562
563
// Events notifications --------------------------------------------------------
564
565
void
566
SnapWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
567
{
568
    SNAP_SCREEN (screen);
569
570
    window->resizeNotify (dx, dy, dwidth, dheight);
571
572
    // avoid-infinite-notify-loop mode/not grabbed
573
    if (skipNotify || !(grabbed & ResizeGrab))
574
	return;
575
576
    // we have to avoid snapping but there's still some buffered moving
577
    if (!ss->snapping && (m_dx || m_dy || m_dwidth || m_dheight))
578
    {
579
	resize (m_dx, m_dy, m_dwidth, m_dheight);
580
	m_dx = m_dy = m_dwidth = m_dheight = 0;
581
	return;
582
    }
583
584
    // don't snap maximized windows
585
    if (window->state () & CompWindowStateMaximizedHorzMask)
586
	dx = 0;
587
588
    if (window->state () & CompWindowStateMaximizedVertMask)
589
	dy = 0;
590
591
    // avoiding snap, nothing buffered
592
    if (!ss->snapping)
593
	return;
594
595
    // apply edge resistance
596
    if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
597
    {
598
	// If there's horizontal snapping, add dx to current buffered
599
	// dx and resist (move by -dx) or release the window and move
600
	// by buffered dx - dx, same for dh
601
	if (!snapGeometry.isEmpty () && snapDirection & HorizontalSnap)
602
	{
603
	    m_dx += dx;
604
	    if (m_dx < ss->optionGetResistanceDistance ()
605
		&& m_dx > -ss->optionGetResistanceDistance ())
606
	    {
607
		resize (-dx, 0, 0, 0);
608
	    }
609
	    else
610
	    {
611
		resize (m_dx - dx, 0, 0, 0);
612
		m_dx = 0;
613
		if (!m_dwidth)
614
		    snapDirection &= VerticalSnap;
615
	    }
616
	    m_dwidth += dwidth;
617
	    if (m_dwidth < ss->optionGetResistanceDistance ()
618
		&& m_dwidth > -ss->optionGetResistanceDistance ())
619
	    {
620
		resize (0, 0, -dwidth, 0);
621
	    }
622
	    else
623
	    {
624
		resize (0, 0, m_dwidth - dwidth, 0);
625
		m_dwidth = 0;
626
		if (!m_dx)
627
		    snapDirection &= VerticalSnap;
628
	    }
629
	}
630
631
	// Same for vertical snapping and dy/dh
632
	if (snapGeometry.isEmpty () && snapDirection & VerticalSnap)
633
	{
634
	    m_dy += dy;
635
	    if (m_dy < ss->optionGetResistanceDistance ()
636
		&& m_dy > -ss->optionGetResistanceDistance ())
637
	    {
638
		resize (0, -dy, 0, 0);
639
	    }
640
	    else
641
	    {
642
		resize (0, m_dy - dy, 0, 0);
643
		m_dy = 0;
644
		if (!m_dheight)
645
		    snapDirection &= HorizontalSnap;
646
	    }
647
	    m_dheight += dheight;
648
	    if (m_dheight < ss->optionGetResistanceDistance ()
649
		&& m_dheight > -ss->optionGetResistanceDistance ())
650
	    {
651
		resize (0, 0, 0, -dheight);
652
	    }
653
	    else
654
	    {
655
		resize (0, 0, 0, m_dheight - dheight);
656
		m_dheight = 0;
657
		if (!m_dy)
658
		    snapDirection &= HorizontalSnap;
659
	    }
660
	}
661
	// If we are no longer snapping in any direction, reset snapped
662
	if (!snapGeometry.isEmpty () && !snapDirection)
663
	    snapGeometry = CompWindow::Geometry ();
664
    }
665
666
    // If we don't already snap vertically and horizontally,
667
    // check edges status
668
    if (snapDirection != (VerticalSnap | HorizontalSnap))
669
	resizeCheckEdges (dx, dy, dwidth, dheight);
670
}
671
672
void
673
SnapWindow::moveNotify (int dx, int dy, bool immediate)
674
{
675
    SNAP_SCREEN (screen);
676
677
    window->moveNotify (dx, dy, immediate);
678
679
    // avoid-infinite-notify-loop mode/not grabbed
680
    if (skipNotify || !(grabbed & MoveGrab))
681
	return;
682
683
    // we have to avoid snapping but there's still some buffered moving
684
    if (!ss->snapping && (m_dx || m_dy))
685
    {
686
	move (m_dx, m_dy);
687
	m_dx = m_dy = 0;
688
	return;
689
    }
690
691
    // don't snap maximized windows
692
    if (window->state () & CompWindowStateMaximizedHorzMask)
693
	dx = 0;
694
695
    if (window->state () & CompWindowStateMaximizedVertMask)
696
	dy = 0;
697
698
    // avoiding snap, nothing buffered
699
    if (!ss->snapping)
700
	return;
701
702
    // apply edge resistance
703
    if (ss->optionGetSnapTypeMask () & SnapTypeEdgeResistanceMask)
704
    {
705
	// If there's horizontal snapping, add dx to current buffered
706
	// dx and resist (move by -dx) or release the window and move
707
	// by buffered dx - dx
708
	if (!snapGeometry.isEmpty () && snapDirection & HorizontalSnap)
709
	{
710
	    m_dx += dx;
711
	    if (m_dx < ss->optionGetResistanceDistance ()
712
		&& m_dx > -ss->optionGetResistanceDistance ())
713
	    {
714
		dx = snapGeometry.x () - window->geometry ().x ();
715
		move (dx, 0);
716
	    }
717
	    else
718
	    {
719
		move (m_dx - dx, 0);
720
		m_dx = 0;
721
		snapDirection &= VerticalSnap;
722
	    }
723
	}
724
	// Same for vertical snapping and dy
725
	if (!snapGeometry.isEmpty () && snapDirection & VerticalSnap)
726
	{
727
	    m_dy += dy;
728
	    if (m_dy < ss->optionGetResistanceDistance ()
729
		&& m_dy > -ss->optionGetResistanceDistance ())
730
	    {
731
		dy = snapGeometry.y () - window->geometry ().y ();
732
		move (0, dy);
733
	    }
734
	    else
735
	    {
736
		move (0, m_dy - dy);
737
		m_dy = 0;
738
		snapDirection &= HorizontalSnap;
739
	    }
740
	}
741
	// If we are no longer snapping in any direction, reset snapped
742
	if (!snapGeometry.isEmpty () && !snapDirection)
743
	    snapGeometry = CompWindow::Geometry ();
744
    }
745
    // If we don't already snap vertically and horizontally,
746
    // check edges status
747
    if (snapDirection != (VerticalSnap | HorizontalSnap))
748
	moveCheckEdges ();
749
}
750
751
/*
752
 * Initiate snap, get edges
753
 */
754
void
755
SnapWindow::grabNotify (int x, int y, unsigned int state, unsigned int mask)
756
{
757
    grabbed = (mask & CompWindowGrabResizeMask) ? ResizeGrab : MoveGrab;
758
    updateEdges ();
759
760
    window->grabNotify (x, y, state, mask);
761
}
762
763
/*
764
 * Clean edges data, reset dx/dy to avoid buggy moves
765
 * when snap will be triggered again.
766
 */
767
void
768
SnapWindow::ungrabNotify ()
769
{
770
    edges.clear ();
771
772
    snapGeometry = CompWindow::Geometry ();
773
    snapDirection = 0;
774
    grabbed = 0;
775
    m_dx = m_dy = m_dwidth = m_dheight = 0;
776
777
    window->ungrabNotify ();
778
}
779
780
// Internal stuff --------------------------------------------------------------
781
782
void
783
SnapScreen::optionChanged (CompOption *opt, SnapOptions::Options num)
784
{
785
    switch (num)
786
    {
787
    case SnapOptions::AvoidSnap:
788
    {
789
	unsigned int mask = optionGetAvoidSnapMask ();
790
	avoidSnapMask = 0;
791
	if (mask & AvoidSnapShiftMask)
792
	    avoidSnapMask |= ShiftMask;
793
	if (mask & AvoidSnapAltMask)
794
	    avoidSnapMask |= CompAltMask;
795
	if (mask & AvoidSnapControlMask)
796
	    avoidSnapMask |= ControlMask;
797
	if (mask & AvoidSnapMetaMask)
798
	    avoidSnapMask |= CompMetaMask;
799
    }
800
801
    default:
802
	break;
803
    }
804
}
805
806
SnapScreen::SnapScreen (CompScreen *screen) :
807
    PluginClassHandler <SnapScreen, CompScreen> (screen),
808
    SnapOptions (),
809
    snapping (true),
810
    avoidSnapMask (0)
811
{
812
    ScreenInterface::setHandler (screen);
813
814
#define setNotify(func) \
815
    optionSet##func##Notify (boost::bind (&SnapScreen::optionChanged, this, _1, _2))
816
817
    setNotify (AvoidSnap);
818
}
819
820
SnapWindow::SnapWindow (CompWindow *window) :
821
    PluginClassHandler <SnapWindow, CompWindow> (window),
822
    window (window),
823
    snapDirection (0),
824
    m_dx (0),
825
    m_dy (0),
826
    m_dwidth (0),
827
    m_dheight (0),
828
    snapGeometry (0, 0, 0, 0, 0),
829
    grabbed (0),
830
    skipNotify (false)
831
{
832
    WindowInterface::setHandler (window);
833
}
834
835
SnapWindow::~SnapWindow ()
836
{
837
}
838
839
bool
840
SnapPluginVTable::init ()
841
{
842
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
843
	return false;
844
845
    return true;
846
}
847