~ubuntu-branches/ubuntu/trusty/xfwm4/trusty

« back to all changes in this revision

Viewing changes to .pc/0002-Implement-NET_WM_MOVERESIZE_CANCEL-message-bug-8949.patch/src/moveresize.c

  • Committer: Package Import Robot
  • Author(s): Micah Gersten
  • Date: 2013-08-08 22:00:03 UTC
  • mfrom: (3.2.9 sid)
  • Revision ID: package-import@ubuntu.com-20130808220003-p1lagfezt2kcrs42
Tags: 4.10.1-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - debian/control: demote xfwm4-themes from Recommends to Suggests, per
    the 'other-p-xubuntu-cleanthemes' spec.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*      $Id$
2
 
 
3
 
        This program is free software; you can redistribute it and/or modify
4
 
        it under the terms of the GNU General Public License as published by
5
 
        the Free Software Foundation; either version 2, or (at your option)
6
 
        any later version.
7
 
 
8
 
        This program is distributed in the hope that it will be useful,
9
 
        but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
        GNU General Public License for more details.
12
 
 
13
 
        You should have received a copy of the GNU General Public License
14
 
        along with this program; if not, write to the Free Software
15
 
        Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
16
 
        MA 02110-1301, USA.
17
 
 
18
 
 
19
 
        oroborus - (c) 2001 Ken Lynch
20
 
        xfwm4    - (c) 2002-2011 Olivier Fourdan
21
 
 
22
 
 */
23
 
 
24
 
#ifdef HAVE_CONFIG_H
25
 
#include "config.h"
26
 
#endif
27
 
 
28
 
#include <X11/X.h>
29
 
#include <X11/Xlib.h>
30
 
#include <X11/Xutil.h>
31
 
#include <X11/Xatom.h>
32
 
#include <X11/extensions/shape.h>
33
 
 
34
 
#include <glib.h>
35
 
#include <gdk/gdk.h>
36
 
#include <gdk/gdkx.h>
37
 
#include <gtk/gtk.h>
38
 
 
39
 
#include "client.h"
40
 
#include "focus.h"
41
 
#include "frame.h"
42
 
#include "moveresize.h"
43
 
#include "placement.h"
44
 
#include "poswin.h"
45
 
#include "screen.h"
46
 
#include "settings.h"
47
 
#include "transients.h"
48
 
#include "event_filter.h"
49
 
#include "workspaces.h"
50
 
#include "xsync.h"
51
 
 
52
 
#define MOVERESIZE_EVENT_MASK \
53
 
    PointerMotionMask | \
54
 
    ButtonMotionMask | \
55
 
    ButtonReleaseMask | \
56
 
    LeaveWindowMask
57
 
 
58
 
#define TILE_DISTANCE 2
59
 
 
60
 
typedef struct _MoveResizeData MoveResizeData;
61
 
struct _MoveResizeData
62
 
{
63
 
    Client *c;
64
 
    gboolean use_keys;
65
 
    gboolean grab;
66
 
    gboolean is_transient;
67
 
    gboolean move_resized;
68
 
    gboolean released;
69
 
    guint button;
70
 
    gint cancel_x, cancel_y;
71
 
    gint cancel_w, cancel_h;
72
 
    guint cancel_workspace;
73
 
    gint mx, my;
74
 
    gint px, py; /* pointer relative position */
75
 
    gint ox, oy;
76
 
    gint ow, oh;
77
 
    gint oldw, oldh;
78
 
    gint handle;
79
 
    Poswin *poswin;
80
 
};
81
 
 
82
 
static void
83
 
clientSetSize (Client * c, int *size, int size_min, int size_max, int size_inc, gboolean source_is_application)
84
 
{
85
 
    int temp;
86
 
 
87
 
    g_return_if_fail (c != NULL);
88
 
    g_return_if_fail (size != NULL);
89
 
    TRACE ("entering clientSetSize");
90
 
 
91
 
    /* Bypass resize increment and max sizes for fullscreen */
92
 
    if (!FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN)
93
 
        && !(FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED)
94
 
             && (c->screen_info->params->borderless_maximize)))
95
 
    {
96
 
        if (!source_is_application && (c->size->flags & PResizeInc) && (size_inc))
97
 
        {
98
 
            temp = (*size - size_min) / size_inc;
99
 
            *size = size_min + (temp * size_inc);
100
 
        }
101
 
        if (c->size->flags & PMaxSize)
102
 
        {
103
 
            if (*size > size_max)
104
 
            {
105
 
                *size = size_max;
106
 
            }
107
 
        }
108
 
    }
109
 
 
110
 
    if (c->size->flags & PMinSize)
111
 
    {
112
 
        if (*size < size_min)
113
 
        {
114
 
            *size = size_min;
115
 
        }
116
 
    }
117
 
    if (*size < 1)
118
 
    {
119
 
        *size = 1;
120
 
    }
121
 
}
122
 
 
123
 
void
124
 
clientSetWidth (Client * c, int w, gboolean source_is_application)
125
 
{
126
 
    int temp;
127
 
 
128
 
    g_return_if_fail (c != NULL);
129
 
    TRACE ("entering clientSetWidth");
130
 
    TRACE ("setting width %i for client \"%s\" (0x%lx)", w, c->name, c->window);
131
 
 
132
 
    temp = w;
133
 
    clientSetSize (c, &temp, c->size->min_width, c->size->max_width, c->size->width_inc, source_is_application);
134
 
    c->width = temp;
135
 
}
136
 
 
137
 
void
138
 
clientSetHeight (Client * c, int h, gboolean source_is_application)
139
 
{
140
 
    int temp;
141
 
 
142
 
    g_return_if_fail (c != NULL);
143
 
    TRACE ("entering clientSetHeight");
144
 
    TRACE ("setting height %i for client \"%s\" (0x%lx)", h, c->name, c->window);
145
 
 
146
 
    temp = h;
147
 
    clientSetSize (c, &temp, c->size->min_height, c->size->max_height, c->size->height_inc, source_is_application);
148
 
    c->height = temp;
149
 
}
150
 
 
151
 
static void
152
 
clientMovePointer (DisplayInfo *display_info, gint dx, gint dy, guint repeat)
153
 
{
154
 
    guint i;
155
 
    for (i = 0; i < repeat; ++i)
156
 
    {
157
 
        XWarpPointer (display_info->dpy, None, None, 0, 0, 0, 0, dx, dy);
158
 
    }
159
 
}
160
 
 
161
 
static gboolean
162
 
clientKeyPressIsModifier (XEvent *xevent)
163
 
{
164
 
    int keysym = XLookupKeysym (&xevent->xkey, 0);
165
 
    return (gboolean) IsModifierKey(keysym);
166
 
}
167
 
 
168
 
static void
169
 
clientSetHandle(MoveResizeData *passdata, int handle)
170
 
{
171
 
    ScreenInfo *screen_info;
172
 
    DisplayInfo *display_info;
173
 
    Client *c;
174
 
    int px, py;
175
 
 
176
 
    c = passdata->c;
177
 
    screen_info = c->screen_info;
178
 
    display_info = screen_info->display_info;
179
 
 
180
 
    switch (handle)
181
 
    {
182
 
        case CORNER_BOTTOM_LEFT:
183
 
            px = frameX (c) + frameLeft(c) / 2;
184
 
            py = frameY (c) + frameHeight (c) - frameBottom(c) / 2;
185
 
            break;
186
 
        case CORNER_BOTTOM_RIGHT:
187
 
            px = frameX (c) + frameWidth (c) - frameRight(c) / 2;
188
 
            py = frameY (c) + frameHeight (c) - frameBottom(c) / 2;
189
 
            break;
190
 
        case CORNER_TOP_LEFT:
191
 
            px = frameX (c) + frameLeft(c) / 2;
192
 
            py = frameY (c);
193
 
            break;
194
 
        case CORNER_TOP_RIGHT:
195
 
            px = frameX (c) + frameWidth (c) - frameRight(c) / 2;
196
 
            py = frameY (c);
197
 
            break;
198
 
        case CORNER_COUNT + SIDE_LEFT:
199
 
            px = frameX (c) + frameLeft(c) / 2;
200
 
            py = frameY (c) + frameHeight (c) / 2;
201
 
            break;
202
 
        case CORNER_COUNT + SIDE_RIGHT:
203
 
            px = frameX (c) + frameWidth (c) - frameRight(c) / 2;
204
 
            py = frameY (c) + frameHeight (c) / 2;
205
 
            break;
206
 
        case CORNER_COUNT + SIDE_TOP:
207
 
            px = frameX (c) + frameWidth (c) / 2;
208
 
            py = frameY (c);
209
 
            break;
210
 
        case CORNER_COUNT + SIDE_BOTTOM:
211
 
            px = frameX (c) + frameWidth (c) / 2;
212
 
            py = frameY (c) + frameHeight (c) - frameBottom(c) / 2;
213
 
            break;
214
 
        default:
215
 
            px = frameX (c) + frameWidth (c) / 2;
216
 
            py = frameY (c) + frameHeight (c) / 2;
217
 
            break;
218
 
    }
219
 
 
220
 
    XWarpPointer (display_info->dpy, None, screen_info->xroot, 0, 0, 0, 0, px, py);
221
 
    /* Update internal data */
222
 
    passdata->handle = handle;
223
 
    passdata->mx = px;
224
 
    passdata->my = py;
225
 
    passdata->px = passdata->mx - frameX (c);
226
 
    passdata->py = passdata->my - frameY (c);
227
 
    passdata->ox = c->x;
228
 
    passdata->oy = c->y;
229
 
    passdata->ow = c->width;
230
 
    passdata->oh = c->height;
231
 
}
232
 
 
233
 
/* clientConstrainRatio - adjust the given width and height to account for
234
 
   the constraints imposed by size hints
235
 
 
236
 
   The aspect ratio stuff, is borrowed from uwm's CheckConsistency routine.
237
 
 */
238
 
 
239
 
#define MAKE_MULT(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
240
 
static void
241
 
clientConstrainRatio (Client * c, int handle)
242
 
{
243
 
 
244
 
    g_return_if_fail (c != NULL);
245
 
    TRACE ("entering clientConstrainRatio");
246
 
    TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
247
 
 
248
 
    if (c->size->flags & PAspect)
249
 
    {
250
 
        int xinc, yinc, minx, miny, maxx, maxy, delta;
251
 
 
252
 
        xinc = c->size->width_inc;
253
 
        yinc = c->size->height_inc;
254
 
        minx = c->size->min_aspect.x;
255
 
        miny = c->size->min_aspect.y;
256
 
        maxx = c->size->max_aspect.x;
257
 
        maxy = c->size->max_aspect.y;
258
 
 
259
 
        if ((minx * c->height > miny * c->width) && (miny) &&
260
 
            ((handle == CORNER_COUNT + SIDE_TOP) || (handle == CORNER_COUNT + SIDE_BOTTOM)))
261
 
        {
262
 
            /* Change width to match */
263
 
            delta = MAKE_MULT (minx * c->height /  miny - c->width, xinc);
264
 
            if (!(c->size->flags & PMaxSize) ||
265
 
                (c->width + delta <= c->size->max_width))
266
 
            {
267
 
                c->width += delta;
268
 
            }
269
 
        }
270
 
        if ((minx * c->height > miny * c->width) && (minx))
271
 
        {
272
 
            delta = MAKE_MULT (c->height - c->width * miny / minx, yinc);
273
 
            if (!(c->size->flags & PMinSize) ||
274
 
                (c->height - delta >= c->size->min_height))
275
 
            {
276
 
                c->height -= delta;
277
 
            }
278
 
            else
279
 
            {
280
 
                delta = MAKE_MULT (minx * c->height / miny - c->width, xinc);
281
 
                if (!(c->size->flags & PMaxSize) ||
282
 
                    (c->width + delta <= c->size->max_width))
283
 
                  c->width += delta;
284
 
            }
285
 
        }
286
 
 
287
 
        if ((maxx * c->height < maxy * c->width) && (maxx) &&
288
 
            ((handle == CORNER_COUNT + SIDE_LEFT) || (handle == CORNER_COUNT + SIDE_RIGHT)))
289
 
        {
290
 
            delta = MAKE_MULT (c->width * maxy / maxx - c->height, yinc);
291
 
            if (!(c->size->flags & PMaxSize) ||
292
 
                (c->height + delta <= c->size->max_height))
293
 
            {
294
 
                c->height += delta;
295
 
            }
296
 
        }
297
 
        if ((maxx * c->height < maxy * c->width) && (maxy))
298
 
        {
299
 
            delta = MAKE_MULT (c->width - maxx * c->height / maxy, xinc);
300
 
            if (!(c->size->flags & PMinSize) ||
301
 
                (c->width - delta >= c->size->min_width))
302
 
            {
303
 
                c->width -= delta;
304
 
            }
305
 
            else
306
 
            {
307
 
                delta = MAKE_MULT (c->width * maxy / maxx - c->height, yinc);
308
 
                if (!(c->size->flags & PMaxSize) ||
309
 
                    (c->height + delta <= c->size->max_height))
310
 
                {
311
 
                    c->height += delta;
312
 
                }
313
 
            }
314
 
        }
315
 
    }
316
 
}
317
 
 
318
 
static void
319
 
clientDrawOutline (Client * c)
320
 
{
321
 
    TRACE ("entering clientDrawOutline");
322
 
 
323
 
    XDrawRectangle (clientGetXDisplay (c), c->screen_info->xroot, c->screen_info->box_gc, frameX (c), frameY (c),
324
 
        frameWidth (c) - 1, frameHeight (c) - 1);
325
 
    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_BORDER)
326
 
        &&!FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN | CLIENT_FLAG_SHADED))
327
 
    {
328
 
        XDrawRectangle (clientGetXDisplay (c), c->screen_info->xroot, c->screen_info->box_gc, c->x, c->y, c->width - 1,
329
 
            c->height - 1);
330
 
    }
331
 
}
332
 
 
333
 
static gboolean
334
 
clientCheckOverlap (int s1, int e1, int s2, int e2)
335
 
{
336
 
    /* Simple overlap test for an arbitary axis. -Cliff */
337
 
    if ((s1 >= s2 && s1 <= e2) ||
338
 
        (e1 >= s2 && e1 <= e2) ||
339
 
        (s2 >= s1 && s2 <= e1) ||
340
 
        (e2 >= s1 && e2 <= e1))
341
 
    {
342
 
        return TRUE;
343
 
    }
344
 
    return FALSE;
345
 
}
346
 
 
347
 
static int
348
 
clientFindClosestEdgeX (Client *c, int edge_pos)
349
 
{
350
 
    /* Find the closest edge of anything that we can snap to, taking
351
 
       frames into account, or just return the original value if nothing
352
 
       is within the snapping range. -Cliff */
353
 
 
354
 
    Client *c2;
355
 
    ScreenInfo *screen_info;
356
 
    guint i;
357
 
    int snap_width, closest;
358
 
 
359
 
    screen_info = c->screen_info;
360
 
    snap_width = screen_info->params->snap_width;
361
 
    closest = edge_pos + snap_width + 2; /* This only needs to be out of the snap range to work. -Cliff */
362
 
 
363
 
    for (c2 = screen_info->clients, i = 0; i < screen_info->client_count; c2 = c2->next, i++)
364
 
    {
365
 
        if (FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE)  && (c2 != c) &&
366
 
            (((screen_info->params->snap_to_windows) && (c2->win_layer == c->win_layer))
367
 
             || ((screen_info->params->snap_to_border)
368
 
                  && FLAG_TEST (c2->flags, CLIENT_FLAG_HAS_STRUT)
369
 
                  && FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE))))
370
 
        {
371
 
 
372
 
            if (clientCheckOverlap (c->y - frameTop (c) - 1, c->y + c->height + frameBottom (c) + 1, c2->y - frameTop (c) - 1, c2->y + c2->height + frameBottom (c) + 1))
373
 
            {
374
 
                if (abs (c2->x - frameLeft (c2) - edge_pos) < abs (closest - edge_pos))
375
 
                {
376
 
                    closest = c2->x - frameLeft (c2);
377
 
                }
378
 
                if (abs ((c2->x + c2->width) + frameRight (c2) - edge_pos) < abs (closest - edge_pos))
379
 
                {
380
 
                    closest = (c2->x + c2->width) + frameRight (c2);
381
 
                }
382
 
            }
383
 
        }
384
 
    }
385
 
 
386
 
    if (abs (closest - edge_pos) > snap_width)
387
 
    {
388
 
        closest = edge_pos;
389
 
    }
390
 
 
391
 
    return closest;
392
 
}
393
 
 
394
 
static int
395
 
clientFindClosestEdgeY (Client *c, int edge_pos)
396
 
{
397
 
    /* This function is mostly identical to the one above, but swaps the
398
 
       axes. If there's a better way to do it than this, I'd like to
399
 
       know. -Cliff */
400
 
 
401
 
    Client *c2;
402
 
    ScreenInfo *screen_info;
403
 
    guint i;
404
 
    int snap_width, closest;
405
 
 
406
 
    screen_info = c->screen_info;
407
 
    snap_width = screen_info->params->snap_width;
408
 
    closest = edge_pos + snap_width + 1; /* This only needs to be out of the snap range to work. -Cliff */
409
 
 
410
 
    for (c2 = screen_info->clients, i = 0; i < screen_info->client_count; c2 = c2->next, i++)
411
 
    {
412
 
        if (FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE)  && (c2 != c) &&
413
 
            (((screen_info->params->snap_to_windows) && (c2->win_layer == c->win_layer))
414
 
             || ((screen_info->params->snap_to_border)
415
 
                  && FLAG_TEST (c2->flags, CLIENT_FLAG_HAS_STRUT)
416
 
                  && FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE))))
417
 
        {
418
 
 
419
 
            if (clientCheckOverlap (c->x - frameLeft (c) - 1, c->x + c->width + frameRight (c) + 1, c2->x - frameLeft (c) - 1, c2->x + c2->width + frameRight (c) + 1))
420
 
            {
421
 
                if (abs (c2->y - frameTop(c2) - edge_pos) < abs (closest - edge_pos))
422
 
                {
423
 
                    closest = c2->y - frameTop (c2);
424
 
                }
425
 
                if (abs ((c2->y + c2->height) + frameBottom (c2) - edge_pos) < abs (closest - edge_pos))
426
 
                {
427
 
                    closest = (c2->y + c2->height) + frameBottom (c2);
428
 
                }
429
 
            }
430
 
        }
431
 
    }
432
 
 
433
 
    if (abs (closest - edge_pos) > snap_width)
434
 
    {
435
 
        closest = edge_pos;
436
 
    }
437
 
 
438
 
    return closest;
439
 
}
440
 
 
441
 
static void
442
 
clientSnapPosition (Client * c, int prev_x, int prev_y)
443
 
{
444
 
    ScreenInfo *screen_info;
445
 
    Client *c2;
446
 
    guint i;
447
 
    int cx, cy, delta;
448
 
    int disp_x, disp_y, disp_max_x, disp_max_y;
449
 
    int frame_x, frame_y, frame_height, frame_width;
450
 
    int frame_top, frame_left;
451
 
    int frame_x2, frame_y2;
452
 
    int best_frame_x, best_frame_y;
453
 
    int best_delta_x, best_delta_y;
454
 
    int c_frame_x1, c_frame_x2, c_frame_y1, c_frame_y2;
455
 
    GdkRectangle rect;
456
 
 
457
 
    g_return_if_fail (c != NULL);
458
 
    TRACE ("entering clientSnapPosition");
459
 
    TRACE ("Snapping client \"%s\" (0x%lx)", c->name, c->window);
460
 
 
461
 
    screen_info = c->screen_info;
462
 
    best_delta_x = screen_info->params->snap_width + 1;
463
 
    best_delta_y = screen_info->params->snap_width + 1;
464
 
 
465
 
    frame_x = frameX (c);
466
 
    frame_y = frameY (c);
467
 
    frame_height = frameHeight (c);
468
 
    frame_width = frameWidth (c);
469
 
    frame_top = frameTop (c);
470
 
    frame_left = frameLeft (c);
471
 
 
472
 
    cx = frame_x + (frame_width / 2);
473
 
    cy = frame_y + (frame_height / 2);
474
 
 
475
 
    frame_x2 = frame_x + frame_width;
476
 
    frame_y2 = frame_y + frame_height;
477
 
    best_frame_x = frame_x;
478
 
    best_frame_y = frame_y;
479
 
 
480
 
    myScreenFindMonitorAtPoint (screen_info, cx, cy, &rect);
481
 
 
482
 
    disp_x = rect.x;
483
 
    disp_y = rect.y;
484
 
    disp_max_x = rect.x + rect.width;
485
 
    disp_max_y = rect.y + rect.height;
486
 
 
487
 
    if (screen_info->params->snap_to_border)
488
 
    {
489
 
        if (abs (disp_x - frame_x) < abs (disp_max_x - frame_x2))
490
 
        {
491
 
            if (!screen_info->params->snap_resist || ((frame_x <= disp_x) && (c->x < prev_x)))
492
 
            {
493
 
                best_delta_x = abs (disp_x - frame_x);
494
 
                best_frame_x = disp_x;
495
 
            }
496
 
        }
497
 
        else
498
 
        {
499
 
            if (!screen_info->params->snap_resist || ((frame_x2 >= disp_max_x) && (c->x > prev_x)))
500
 
            {
501
 
                best_delta_x = abs (disp_max_x - frame_x2);
502
 
                best_frame_x = disp_max_x - frame_width;
503
 
            }
504
 
        }
505
 
 
506
 
        if (abs (disp_y - frame_y) < abs (disp_max_y - frame_y2))
507
 
        {
508
 
            if (!screen_info->params->snap_resist || ((frame_y <= disp_y) && (c->y < prev_y)))
509
 
            {
510
 
                best_delta_y = abs (disp_y - frame_y);
511
 
                best_frame_y = disp_y;
512
 
            }
513
 
        }
514
 
        else
515
 
        {
516
 
            if (!screen_info->params->snap_resist || ((frame_y2 >= disp_max_y) && (c->y > prev_y)))
517
 
            {
518
 
                best_delta_y = abs (disp_max_y - frame_y2);
519
 
                best_frame_y = disp_max_y - frame_height;
520
 
            }
521
 
        }
522
 
    }
523
 
 
524
 
    for (c2 = screen_info->clients, i = 0; i < screen_info->client_count; c2 = c2->next, i++)
525
 
    {
526
 
        if (FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE)  && (c2 != c) &&
527
 
            (((screen_info->params->snap_to_windows) && (c2->win_layer == c->win_layer))
528
 
             || ((screen_info->params->snap_to_border)
529
 
                  && FLAG_TEST (c2->flags, CLIENT_FLAG_HAS_STRUT)
530
 
                  && FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE))))
531
 
        {
532
 
            c_frame_x1 = frameX (c2);
533
 
            c_frame_x2 = c_frame_x1 + frameWidth (c2);
534
 
            c_frame_y1 = frameY (c2);
535
 
            c_frame_y2 = c_frame_y1 + frameHeight (c2);
536
 
 
537
 
            if ((c_frame_y1 <= frame_y2) && (c_frame_y2 >= frame_y))
538
 
            {
539
 
                delta = abs (c_frame_x2 - frame_x);
540
 
                if (delta < best_delta_x)
541
 
                {
542
 
                    if (!screen_info->params->snap_resist || ((frame_x <= c_frame_x2) && (c->x < prev_x)))
543
 
                    {
544
 
                        best_delta_x = delta;
545
 
                        best_frame_x = c_frame_x2;
546
 
                    }
547
 
                }
548
 
 
549
 
                delta = abs (c_frame_x1 - frame_x2);
550
 
                if (delta < best_delta_x)
551
 
                {
552
 
                    if (!screen_info->params->snap_resist || ((frame_x2 >= c_frame_x1) && (c->x > prev_x)))
553
 
                    {
554
 
                        best_delta_x = delta;
555
 
                        best_frame_x = c_frame_x1 - frame_width;
556
 
                    }
557
 
                }
558
 
            }
559
 
 
560
 
            if ((c_frame_x1 <= frame_x2) && (c_frame_x2 >= frame_x))
561
 
            {
562
 
                delta = abs (c_frame_y2 - frame_y);
563
 
                if (delta < best_delta_y)
564
 
                {
565
 
                    if (!screen_info->params->snap_resist || ((frame_y <= c_frame_y2) && (c->y < prev_y)))
566
 
                    {
567
 
                        best_delta_y = delta;
568
 
                        best_frame_y = c_frame_y2;
569
 
                    }
570
 
                }
571
 
 
572
 
                delta = abs (c_frame_y1 - frame_y2);
573
 
                if (delta < best_delta_y)
574
 
                {
575
 
                    if (!screen_info->params->snap_resist || ((frame_y2 >= c_frame_y1) && (c->y > prev_y)))
576
 
                    {
577
 
                        best_delta_y = delta;
578
 
                        best_frame_y = c_frame_y1 - frame_height;
579
 
                    }
580
 
                }
581
 
            }
582
 
        }
583
 
    }
584
 
 
585
 
    if (best_delta_x <= screen_info->params->snap_width)
586
 
    {
587
 
        c->x = best_frame_x + frame_left;
588
 
    }
589
 
    if (best_delta_y <= screen_info->params->snap_width)
590
 
    {
591
 
        c->y = best_frame_y + frame_top;
592
 
    }
593
 
}
594
 
 
595
 
static eventFilterStatus
596
 
clientButtonReleaseFilter (XEvent * xevent, gpointer data)
597
 
{
598
 
    MoveResizeData *passdata = (MoveResizeData *) data;
599
 
 
600
 
    TRACE ("entering clientButtonReleaseFilter");
601
 
 
602
 
    if ((xevent->type == ButtonRelease) &&
603
 
        (xevent->xbutton.button == passdata->button))
604
 
    {
605
 
        gtk_main_quit ();
606
 
        return EVENT_FILTER_STOP;
607
 
    }
608
 
 
609
 
    return EVENT_FILTER_CONTINUE;
610
 
}
611
 
 
612
 
static void
613
 
clientMoveWarp (Client * c, XMotionEvent *xevent)
614
 
{
615
 
    static guint32 lastresist = 0;
616
 
    static int edge_scroll_x = 0;
617
 
    static int edge_scroll_y = 0;
618
 
    ScreenInfo *screen_info;
619
 
    DisplayInfo *display_info;
620
 
    gboolean warp_pointer = FALSE;
621
 
    int msx, msy, maxx, maxy;
622
 
    int rx, ry, delta;
623
 
 
624
 
    g_return_if_fail (c != NULL);
625
 
    TRACE ("entering clientMoveWarp");
626
 
 
627
 
    screen_info = c->screen_info;
628
 
    display_info = screen_info->display_info;
629
 
 
630
 
    if (xevent == NULL)
631
 
    {
632
 
        /* Cleanup */
633
 
        edge_scroll_x = 0;
634
 
        edge_scroll_y = 0;
635
 
        return;
636
 
    }
637
 
 
638
 
    if ((screen_info->params->wrap_windows) && (screen_info->params->wrap_resistance))
639
 
    {
640
 
 
641
 
        msx = xevent->x_root;
642
 
        msy = xevent->y_root;
643
 
        maxx = screen_info->width - 1;
644
 
        maxy = screen_info->height - 1;
645
 
        rx = 0;
646
 
        ry = 0;
647
 
        warp_pointer = FALSE;
648
 
 
649
 
        if ((msx == 0) || (msx == maxx))
650
 
        {
651
 
            if ((xevent->time - lastresist) > 250)  /* ms */
652
 
            {
653
 
                edge_scroll_x = 0;
654
 
            }
655
 
            else
656
 
            {
657
 
                edge_scroll_x++;
658
 
            }
659
 
            if (msx == 0)
660
 
            {
661
 
                rx = 1;
662
 
            }
663
 
            else
664
 
            {
665
 
                rx = -1;
666
 
            }
667
 
            warp_pointer = TRUE;
668
 
            lastresist = xevent->time;
669
 
        }
670
 
        if ((msy == 0) || (msy == maxy))
671
 
        {
672
 
            if ((xevent->time - lastresist) > 250)  /* ms */
673
 
            {
674
 
                edge_scroll_y = 0;
675
 
            }
676
 
            else
677
 
            {
678
 
                edge_scroll_y++;
679
 
            }
680
 
            if (msy == 0)
681
 
            {
682
 
                ry = 1;
683
 
            }
684
 
            else
685
 
            {
686
 
                ry = -1;
687
 
            }
688
 
            warp_pointer = TRUE;
689
 
            lastresist = xevent->time;
690
 
        }
691
 
 
692
 
        if (edge_scroll_x > screen_info->params->wrap_resistance)
693
 
        {
694
 
            edge_scroll_x = 0;
695
 
            if ((msx == 0) || (msx == maxx))
696
 
            {
697
 
                delta = MAX (9 * maxx / 10, maxx - 5 * screen_info->params->wrap_resistance);
698
 
                if (msx == 0)
699
 
                {
700
 
                    if (workspaceMove (screen_info, 0, -1, c, xevent->time))
701
 
                    {
702
 
                        rx = delta;
703
 
                    }
704
 
                }
705
 
                else
706
 
                {
707
 
                    if (workspaceMove (screen_info, 0, 1, c, xevent->time))
708
 
                    {
709
 
                        rx = -delta;
710
 
                    }
711
 
                }
712
 
                warp_pointer = TRUE;
713
 
            }
714
 
            lastresist = 0;
715
 
        }
716
 
        if (edge_scroll_y > screen_info->params->wrap_resistance)
717
 
        {
718
 
            edge_scroll_y = 0;
719
 
            if ((msy == 0) || (msy == maxy))
720
 
            {
721
 
                delta = MAX (9 * maxy / 10, maxy - 5 * screen_info->params->wrap_resistance);
722
 
                if (msy == 0)
723
 
                {
724
 
                    if (workspaceMove (screen_info, -1, 0, c, xevent->time))
725
 
                    {
726
 
                        ry = delta;
727
 
                    }
728
 
                }
729
 
                else
730
 
                {
731
 
                    if (workspaceMove (screen_info, 1, 0, c, xevent->time))
732
 
                    {
733
 
                        ry = -delta;
734
 
                    }
735
 
                }
736
 
                warp_pointer = TRUE;
737
 
            }
738
 
            lastresist = 0;
739
 
        }
740
 
 
741
 
        if (warp_pointer)
742
 
        {
743
 
            XWarpPointer (display_info->dpy, None, None, 0, 0, 0, 0, rx, ry);
744
 
            msx += rx;
745
 
            msy += ry;
746
 
        }
747
 
 
748
 
        xevent->x_root = msx;
749
 
        xevent->y_root = msy;
750
 
    }
751
 
}
752
 
 
753
 
static gboolean
754
 
clientMoveTile (Client *c, XMotionEvent *xevent)
755
 
{
756
 
    ScreenInfo *screen_info;
757
 
    GdkRectangle rect;
758
 
    int x, y, disp_x, disp_y, disp_max_x, disp_max_y, dist;
759
 
    NetWmDesktopLayout layout;
760
 
 
761
 
    screen_info = c->screen_info;
762
 
 
763
 
    /*
764
 
     * Tiling when moving really relies on restore_on_move to work
765
 
     * reliably so just don't do anything if any of the above requirement
766
 
     * is not met (restore_on_move being disabled is from another time,
767
 
     * we should really not have such an option, I must have been weaked
768
 
     * in the past...)
769
 
     */
770
 
    if (!(screen_info->params->tile_on_move && screen_info->params->restore_on_move))
771
 
    {
772
 
        return FALSE;
773
 
    }
774
 
 
775
 
    x = xevent->x;
776
 
    y = xevent->y;
777
 
 
778
 
    myScreenFindMonitorAtPoint (screen_info, x, y, &rect);
779
 
    disp_x = rect.x;
780
 
    disp_y = rect.y;
781
 
    disp_max_x = rect.x + rect.width;
782
 
    disp_max_y = rect.y + rect.height;
783
 
 
784
 
    layout = screen_info->desktop_layout;
785
 
    dist = MIN (TILE_DISTANCE, frameDecorationTop (screen_info) / 2);
786
 
 
787
 
    if (!screen_info->params->wrap_windows || layout.cols < 2)
788
 
    {
789
 
        if ((x >= disp_x - 1) && (x < disp_x + dist) &&
790
 
            (y >= disp_y - 1) && (y < disp_max_y + 1))
791
 
        {
792
 
            return clientTile (c, x, y, TILE_LEFT, !screen_info->params->box_move);
793
 
        }
794
 
 
795
 
        if ((x >= disp_max_x - dist) && (x < disp_max_x + 1) &&
796
 
            (y >= disp_y - 1) && (y < disp_max_y + 1))
797
 
        {
798
 
            return clientTile (c, x, y, TILE_RIGHT, !screen_info->params->box_move);
799
 
        }
800
 
    }
801
 
 
802
 
    if (!screen_info->params->wrap_windows || layout.rows < 2)
803
 
    {
804
 
        if ((x >= disp_x - 1) && (x < disp_max_x + 1) &&
805
 
            (y >= disp_y - 1) && (y < disp_y + dist))
806
 
        {
807
 
            return clientTile (c, x, y, TILE_UP, !screen_info->params->box_move);
808
 
        }
809
 
 
810
 
        if ((x >= disp_x - 1) && (x < disp_max_x + 1) &&
811
 
            (y >= disp_max_y - dist) && (y < disp_max_y + 1))
812
 
        {
813
 
            return clientTile (c, x, y, TILE_DOWN, !screen_info->params->box_move);
814
 
        }
815
 
    }
816
 
 
817
 
    return FALSE;
818
 
}
819
 
 
820
 
static eventFilterStatus
821
 
clientMoveEventFilter (XEvent * xevent, gpointer data)
822
 
{
823
 
    static gboolean toggled_maximize = FALSE;
824
 
    unsigned long configure_flags;
825
 
    ScreenInfo *screen_info;
826
 
    DisplayInfo *display_info;
827
 
    eventFilterStatus status = EVENT_FILTER_STOP;
828
 
    MoveResizeData *passdata = (MoveResizeData *) data;
829
 
    Client *c = NULL;
830
 
    gboolean moving = TRUE;
831
 
    XWindowChanges wc;
832
 
    int prev_x, prev_y;
833
 
 
834
 
    TRACE ("entering clientMoveEventFilter");
835
 
 
836
 
    c = passdata->c;
837
 
    prev_x=c->x;
838
 
    prev_y=c->y;
839
 
    screen_info = c->screen_info;
840
 
    display_info = screen_info->display_info;
841
 
    configure_flags = NO_CFG_FLAG;
842
 
 
843
 
    /* Update the display time */
844
 
    myDisplayUpdateCurrentTime (display_info, xevent);
845
 
 
846
 
    if (xevent->type == KeyPress)
847
 
    {
848
 
        int key_move;
849
 
 
850
 
        while (XCheckMaskEvent (display_info->dpy, KeyPressMask, xevent))
851
 
        {
852
 
            /* Update the display time */
853
 
            myDisplayUpdateCurrentTime (display_info, xevent);
854
 
        }
855
 
 
856
 
        key_move = 16;
857
 
        if ((screen_info->params->snap_to_border) || (screen_info->params->snap_to_windows))
858
 
        {
859
 
            key_move = MAX (key_move, screen_info->params->snap_width + 1);
860
 
        }
861
 
        if (xevent->xkey.keycode == screen_info->params->keys[KEY_LEFT].keycode)
862
 
        {
863
 
            clientMovePointer (display_info, -1, 0, key_move);
864
 
        }
865
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_RIGHT].keycode)
866
 
        {
867
 
            clientMovePointer (display_info, 1, 0, key_move);
868
 
        }
869
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_UP].keycode)
870
 
        {
871
 
            clientMovePointer (display_info, 0, -1, key_move);
872
 
        }
873
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_DOWN].keycode)
874
 
        {
875
 
            clientMovePointer (display_info, 0, 1, key_move);
876
 
        }
877
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_CANCEL].keycode)
878
 
        {
879
 
            moving = FALSE;
880
 
            passdata->released = passdata->use_keys;
881
 
 
882
 
            if (screen_info->params->box_move)
883
 
            {
884
 
                clientDrawOutline (c);
885
 
            }
886
 
 
887
 
            c->x = passdata->cancel_x;
888
 
            c->y = passdata->cancel_y;
889
 
 
890
 
            if (screen_info->params->box_move)
891
 
            {
892
 
                clientDrawOutline (c);
893
 
            }
894
 
            else
895
 
            {
896
 
                wc.x = c->x;
897
 
                wc.y = c->y;
898
 
                clientConfigure (c, &wc, CWX | CWY, configure_flags);
899
 
            }
900
 
            if (screen_info->current_ws != passdata->cancel_workspace)
901
 
            {
902
 
                workspaceSwitch (screen_info, passdata->cancel_workspace, c, FALSE, xevent->xkey.time);
903
 
            }
904
 
            if (toggled_maximize)
905
 
            {
906
 
                toggled_maximize = FALSE;
907
 
                if (clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, FALSE))
908
 
                {
909
 
                    configure_flags = CFG_FORCE_REDRAW;
910
 
                    passdata->move_resized = TRUE;
911
 
                }
912
 
            }
913
 
        }
914
 
        else if (passdata->use_keys)
915
 
        {
916
 
            moving = clientKeyPressIsModifier(xevent);
917
 
        }
918
 
    }
919
 
    else if (xevent->type == ButtonRelease)
920
 
    {
921
 
        moving = FALSE;
922
 
        passdata->released = passdata->use_keys || (xevent->xbutton.button == passdata->button);
923
 
    }
924
 
    else if (xevent->type == MotionNotify)
925
 
    {
926
 
        while (XCheckMaskEvent (display_info->dpy, PointerMotionMask | ButtonMotionMask, xevent))
927
 
        {
928
 
            /* Update the display time */
929
 
            myDisplayUpdateCurrentTime (display_info, xevent);
930
 
        }
931
 
        if (!passdata->grab && screen_info->params->box_move)
932
 
        {
933
 
            myDisplayGrabServer (display_info);
934
 
            passdata->grab = TRUE;
935
 
            clientDrawOutline (c);
936
 
        }
937
 
        if (screen_info->params->box_move)
938
 
        {
939
 
            clientDrawOutline (c);
940
 
        }
941
 
        if ((screen_info->workspace_count > 1) && !(passdata->is_transient))
942
 
        {
943
 
            clientMoveWarp (c, (XMotionEvent *) xevent);
944
 
        }
945
 
 
946
 
        if ((screen_info->params->restore_on_move) && FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
947
 
        {
948
 
 
949
 
            if ((ABS (xevent->xmotion.x_root - passdata->mx) > 15) ||
950
 
                (ABS (xevent->xmotion.y_root - passdata->my) > 15))
951
 
            {
952
 
                /* to keep the distance from the edges of the window proportional. */
953
 
                double xratio, yratio;
954
 
 
955
 
                xratio = (xevent->xmotion.x_root - frameX (c)) / (double) frameWidth (c);
956
 
                yratio = (xevent->xmotion.y_root - frameY (c)) / (double) frameHeight (c);
957
 
 
958
 
                if (FLAG_TEST_ALL(c->flags, CLIENT_FLAG_MAXIMIZED))
959
 
                {
960
 
                    toggled_maximize = TRUE;
961
 
                }
962
 
                if (clientToggleMaximized (c, c->flags & CLIENT_FLAG_MAXIMIZED, FALSE))
963
 
                {
964
 
                    passdata->move_resized = TRUE;
965
 
 
966
 
                    passdata->ox = c->x;
967
 
                    passdata->mx =  frameX (c) + passdata->px;
968
 
                    if ((passdata->mx <  frameX (c)) || (passdata->mx >  frameX (c) + frameWidth (c)))
969
 
                    {
970
 
                        passdata->mx = CLAMP(frameX (c) + frameWidth (c) * xratio, frameX (c), frameX (c) + frameWidth (c));
971
 
                    }
972
 
 
973
 
                    passdata->oy = c->y;
974
 
                    passdata->my = frameY (c) + passdata->py;
975
 
                    if ((passdata->my < frameY (c)) || (passdata->my > frameY (c) + frameHeight (c)))
976
 
                    {
977
 
                        passdata->my = CLAMP(frameY (c) + frameHeight (c) * yratio, frameY (c), frameY (c) + frameHeight (c));
978
 
                    }
979
 
 
980
 
                    configure_flags = CFG_FORCE_REDRAW;
981
 
                }
982
 
            }
983
 
            else
984
 
            {
985
 
                xevent->xmotion.x_root = c->x - passdata->ox + passdata->mx;
986
 
                xevent->xmotion.y_root = c->y - passdata->oy + passdata->my;
987
 
            }
988
 
        }
989
 
 
990
 
        c->x = passdata->ox + (xevent->xmotion.x_root - passdata->mx);
991
 
        c->y = passdata->oy + (xevent->xmotion.y_root - passdata->my);
992
 
 
993
 
        clientSnapPosition (c, prev_x, prev_y);
994
 
        if (screen_info->params->restore_on_move && toggled_maximize)
995
 
        {
996
 
            if ((clientConstrainPos (c, FALSE) & CLIENT_CONSTRAINED_TOP) &&
997
 
                 clientToggleMaximized (c, CLIENT_FLAG_MAXIMIZED, FALSE))
998
 
            {
999
 
                configure_flags = CFG_FORCE_REDRAW;
1000
 
                toggled_maximize = FALSE;
1001
 
                passdata->move_resized = TRUE;
1002
 
            }
1003
 
        }
1004
 
        else if (!clientMoveTile (c, (XMotionEvent *) xevent))
1005
 
        {
1006
 
            clientConstrainPos(c, FALSE);
1007
 
        }
1008
 
 
1009
 
#ifdef SHOW_POSITION
1010
 
        if (passdata->poswin)
1011
 
        {
1012
 
            poswinSetPosition (passdata->poswin, c);
1013
 
        }
1014
 
#endif /* SHOW_POSITION */
1015
 
        if (screen_info->params->box_move)
1016
 
        {
1017
 
            clientDrawOutline (c);
1018
 
        }
1019
 
        else
1020
 
        {
1021
 
            int changes = CWX | CWY;
1022
 
 
1023
 
            if (passdata->move_resized)
1024
 
            {
1025
 
                wc.width = c->width;
1026
 
                wc.height = c->height;
1027
 
                changes |= CWWidth | CWHeight;
1028
 
                passdata->move_resized = FALSE;
1029
 
            }
1030
 
 
1031
 
            wc.x = c->x;
1032
 
            wc.y = c->y;
1033
 
            clientConfigure (c, &wc, changes, configure_flags);
1034
 
        }
1035
 
    }
1036
 
    else if ((xevent->type == UnmapNotify) && (xevent->xunmap.window == c->window))
1037
 
    {
1038
 
        moving = FALSE;
1039
 
    }
1040
 
    else if (xevent->type == EnterNotify)
1041
 
    {
1042
 
        /* Ignore enter events */
1043
 
    }
1044
 
    else
1045
 
    {
1046
 
        status = EVENT_FILTER_CONTINUE;
1047
 
    }
1048
 
 
1049
 
    TRACE ("leaving clientMoveEventFilter");
1050
 
 
1051
 
    if (!moving)
1052
 
    {
1053
 
        TRACE ("event loop now finished");
1054
 
        toggled_maximize = FALSE;
1055
 
        clientMoveWarp (c, NULL);
1056
 
        gtk_main_quit ();
1057
 
    }
1058
 
 
1059
 
    return status;
1060
 
}
1061
 
 
1062
 
void
1063
 
clientMove (Client * c, XEvent * ev)
1064
 
{
1065
 
    ScreenInfo *screen_info;
1066
 
    DisplayInfo *display_info;
1067
 
    XWindowChanges wc;
1068
 
    MoveResizeData passdata;
1069
 
    int changes;
1070
 
    gboolean g1, g2;
1071
 
 
1072
 
    g_return_if_fail (c != NULL);
1073
 
    TRACE ("entering clientDoMove");
1074
 
 
1075
 
    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING) ||
1076
 
        !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
1077
 
    {
1078
 
        return;
1079
 
    }
1080
 
 
1081
 
    if (FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
1082
 
    {
1083
 
        return;
1084
 
    }
1085
 
 
1086
 
    TRACE ("moving client \"%s\" (0x%lx)", c->name, c->window);
1087
 
    screen_info = c->screen_info;
1088
 
    display_info = screen_info->display_info;
1089
 
 
1090
 
    changes = CWX | CWY;
1091
 
 
1092
 
    passdata.c = c;
1093
 
    passdata.cancel_x = passdata.ox = c->x;
1094
 
    passdata.cancel_y = passdata.oy = c->y;
1095
 
    passdata.cancel_workspace = c->win_workspace;
1096
 
    passdata.use_keys = FALSE;
1097
 
    passdata.grab = FALSE;
1098
 
    passdata.released = FALSE;
1099
 
    passdata.button = 0;
1100
 
    passdata.is_transient = clientIsValidTransientOrModal (c);
1101
 
    passdata.move_resized = FALSE;
1102
 
 
1103
 
    clientSaveSizePos (c);
1104
 
 
1105
 
    if (ev && (ev->type == ButtonPress))
1106
 
    {
1107
 
        passdata.button = ev->xbutton.button;
1108
 
        passdata.mx = ev->xbutton.x_root;
1109
 
        passdata.my = ev->xbutton.y_root;
1110
 
        passdata.px = passdata.mx - frameX (c);
1111
 
        passdata.py = passdata.my - frameY (c);
1112
 
    }
1113
 
    else
1114
 
    {
1115
 
        clientSetHandle(&passdata, NO_HANDLE);
1116
 
        passdata.released = passdata.use_keys = TRUE;
1117
 
    }
1118
 
 
1119
 
    g1 = myScreenGrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info));
1120
 
    g2 = myScreenGrabPointer (screen_info, MOVERESIZE_EVENT_MASK,
1121
 
                              myDisplayGetCursorMove (display_info),
1122
 
                              myDisplayGetCurrentTime (display_info));
1123
 
    if (!g1 || !g2)
1124
 
    {
1125
 
        TRACE ("grab failed in clientMove");
1126
 
 
1127
 
        gdk_beep ();
1128
 
        myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info));
1129
 
        myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info));
1130
 
 
1131
 
        return;
1132
 
    }
1133
 
 
1134
 
    passdata.poswin = NULL;
1135
 
#ifdef SHOW_POSITION
1136
 
    passdata.poswin = poswinCreate(screen_info->gscr);
1137
 
    poswinSetPosition (passdata.poswin, c);
1138
 
    poswinShow (passdata.poswin);
1139
 
#endif /* SHOW_POSITION */
1140
 
 
1141
 
    /* Set window translucent while moving */
1142
 
    if ((screen_info->params->move_opacity < 100) &&
1143
 
        !(screen_info->params->box_move) &&
1144
 
        !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED))
1145
 
    {
1146
 
        clientSetOpacity (c, c->opacity, OPACITY_MOVE, OPACITY_MOVE);
1147
 
    }
1148
 
 
1149
 
    /*
1150
 
     * Need to remove the sidewalk windows while moving otherwise
1151
 
     * the motion events aren't reported on screen edges
1152
 
     */
1153
 
    placeSidewalks(screen_info, FALSE);
1154
 
 
1155
 
    /* Clear any previously saved pos flag from screen resize */
1156
 
    FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_SAVED_POS);
1157
 
 
1158
 
    FLAG_SET (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING);
1159
 
    TRACE ("entering move loop");
1160
 
    eventFilterPush (display_info->xfilter, clientMoveEventFilter, &passdata);
1161
 
    gtk_main ();
1162
 
    eventFilterPop (display_info->xfilter);
1163
 
    TRACE ("leaving move loop");
1164
 
    FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING);
1165
 
 
1166
 
    /* Put back the sidewalks as they ought to be */
1167
 
    placeSidewalks (screen_info, screen_info->params->wrap_workspaces);
1168
 
 
1169
 
#ifdef SHOW_POSITION
1170
 
    if (passdata.poswin)
1171
 
    {
1172
 
        poswinDestroy (passdata.poswin);
1173
 
    }
1174
 
#endif /* SHOW_POSITION */
1175
 
    if (passdata.grab && screen_info->params->box_move)
1176
 
    {
1177
 
        clientDrawOutline (c);
1178
 
    }
1179
 
    /* Set window opacity to its original value */
1180
 
    clientSetOpacity (c, c->opacity, OPACITY_MOVE, 0);
1181
 
 
1182
 
    wc.x = c->x;
1183
 
    wc.y = c->y;
1184
 
    if (passdata.move_resized)
1185
 
    {
1186
 
        wc.width = c->width;
1187
 
        wc.height = c->height;
1188
 
        changes |= CWWidth | CWHeight;
1189
 
    }
1190
 
    clientConfigure (c, &wc, changes, NO_CFG_FLAG);
1191
 
 
1192
 
    if (!passdata.released)
1193
 
    {
1194
 
        /* If this is a drag-move, wait for the button to be released.
1195
 
         * If we don't, we might get release events in the wrong place.
1196
 
         */
1197
 
        eventFilterPush (display_info->xfilter, clientButtonReleaseFilter, &passdata);
1198
 
        gtk_main ();
1199
 
        eventFilterPop (display_info->xfilter);
1200
 
    }
1201
 
 
1202
 
    myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info));
1203
 
    myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info));
1204
 
 
1205
 
    if (passdata.grab && screen_info->params->box_move)
1206
 
    {
1207
 
        myDisplayUngrabServer (display_info);
1208
 
    }
1209
 
}
1210
 
 
1211
 
static gboolean
1212
 
clientChangeHandle(MoveResizeData *passdata, int handle)
1213
 
{
1214
 
    ScreenInfo *screen_info;
1215
 
    DisplayInfo *display_info;
1216
 
    Client *c;
1217
 
    Cursor cursor;
1218
 
    gboolean grab;
1219
 
 
1220
 
    c = passdata->c;
1221
 
    screen_info = c->screen_info;
1222
 
    display_info = screen_info->display_info;
1223
 
 
1224
 
    clientSetHandle(passdata, handle);
1225
 
    if ((handle > NO_HANDLE) && (handle <= HANDLES_COUNT))
1226
 
    {
1227
 
        cursor = myDisplayGetCursorResize (display_info, handle);
1228
 
    }
1229
 
    else
1230
 
    {
1231
 
        cursor = myDisplayGetCursorMove (display_info);
1232
 
    }
1233
 
    grab = myScreenChangeGrabPointer (screen_info, MOVERESIZE_EVENT_MASK,
1234
 
                                      cursor, myDisplayGetCurrentTime (display_info));
1235
 
 
1236
 
    return (grab);
1237
 
}
1238
 
 
1239
 
static void
1240
 
clientResizeConfigure (Client *c, int px, int py, int pw, int ph)
1241
 
{
1242
 
    ScreenInfo *screen_info;
1243
 
    DisplayInfo *display_info;
1244
 
    XWindowChanges wc;
1245
 
 
1246
 
    screen_info = c->screen_info;
1247
 
    display_info = screen_info->display_info;
1248
 
 
1249
 
#ifdef HAVE_XSYNC
1250
 
    if (c->xsync_waiting)
1251
 
    {
1252
 
        return;
1253
 
    }
1254
 
    else
1255
 
    {
1256
 
        if ((display_info->have_xsync) && (c->xsync_enabled) && (c->xsync_counter))
1257
 
        {
1258
 
            clientXSyncRequest (c);
1259
 
        }
1260
 
#endif /* HAVE_XSYNC */
1261
 
        wc.x = c->x;
1262
 
        wc.y = c->y;
1263
 
        wc.width = c->width;
1264
 
        wc.height = c->height;
1265
 
        clientConfigure (c, &wc, CWX | CWY | CWWidth | CWHeight, NO_CFG_FLAG);
1266
 
#ifdef HAVE_XSYNC
1267
 
    }
1268
 
#endif /* HAVE_XSYNC */
1269
 
}
1270
 
 
1271
 
static eventFilterStatus
1272
 
clientResizeEventFilter (XEvent * xevent, gpointer data)
1273
 
{
1274
 
    ScreenInfo *screen_info;
1275
 
    DisplayInfo *display_info;
1276
 
    Client *c;
1277
 
    GdkRectangle rect;
1278
 
    MoveResizeData *passdata;
1279
 
    eventFilterStatus status;
1280
 
    int prev_x, prev_y, prev_width, prev_height;
1281
 
    int cx, cy, disp_x, disp_y, disp_max_x, disp_max_y;
1282
 
    int frame_x, frame_y, frame_height, frame_width, frame_top;
1283
 
    int move_top, move_bottom, move_left, move_right;
1284
 
    int temp;
1285
 
    gint min_visible;
1286
 
    gboolean resizing;
1287
 
    int right_edge; /* -Cliff */
1288
 
    int bottom_edge; /* -Cliff */
1289
 
 
1290
 
    TRACE ("entering clientResizeEventFilter");
1291
 
 
1292
 
    passdata = (MoveResizeData *) data;
1293
 
    c = passdata->c;
1294
 
    screen_info = c->screen_info;
1295
 
    display_info = screen_info->display_info;
1296
 
    status = EVENT_FILTER_STOP;
1297
 
    resizing = TRUE;
1298
 
 
1299
 
    frame_x = frameX (c);
1300
 
    frame_y = frameY (c);
1301
 
    frame_height = frameHeight (c);
1302
 
    frame_width = frameWidth (c);
1303
 
    frame_top = frameTop (c);
1304
 
    min_visible = MAX (frame_top, CLIENT_MIN_VISIBLE);
1305
 
 
1306
 
    cx = frame_x + (frame_width / 2);
1307
 
    cy = frame_y + (frame_height / 2);
1308
 
 
1309
 
    move_top = ((passdata->handle == CORNER_TOP_RIGHT)
1310
 
            || (passdata->handle == CORNER_TOP_LEFT)
1311
 
            || (passdata->handle == CORNER_COUNT + SIDE_TOP)) ?
1312
 
        1 : 0;
1313
 
    move_bottom = ((passdata->handle == CORNER_BOTTOM_RIGHT)
1314
 
            || (passdata->handle == CORNER_BOTTOM_LEFT)
1315
 
            || (passdata->handle == CORNER_COUNT + SIDE_BOTTOM)) ?
1316
 
        1 : 0;
1317
 
    move_right = ((passdata->handle == CORNER_TOP_RIGHT)
1318
 
            || (passdata->handle == CORNER_BOTTOM_RIGHT)
1319
 
            || (passdata->handle == CORNER_COUNT + SIDE_RIGHT)) ?
1320
 
        1 : 0;
1321
 
    move_left = ((passdata->handle == CORNER_TOP_LEFT)
1322
 
            || (passdata->handle == CORNER_BOTTOM_LEFT)
1323
 
            || (passdata->handle == CORNER_COUNT + SIDE_LEFT)) ?
1324
 
        1 : 0;
1325
 
 
1326
 
    myScreenFindMonitorAtPoint (screen_info, cx, cy, &rect);
1327
 
 
1328
 
    disp_x = rect.x;
1329
 
    disp_y = rect.y;
1330
 
    disp_max_x = rect.x + rect.width;
1331
 
    disp_max_y = rect.y + rect.height;
1332
 
 
1333
 
    /* Store previous values in case the resize puts the window title off bounds */
1334
 
    prev_x = c->x;
1335
 
    prev_y = c->y;
1336
 
    prev_width = c->width;
1337
 
    prev_height = c->height;
1338
 
 
1339
 
    /* Update the display time */
1340
 
    myDisplayUpdateCurrentTime (display_info, xevent);
1341
 
 
1342
 
    if (xevent->type == KeyPress)
1343
 
    {
1344
 
        int key_width_inc, key_height_inc;
1345
 
 
1346
 
        while (XCheckMaskEvent (display_info->dpy, KeyPressMask, xevent))
1347
 
        {
1348
 
            /* Update the display time */
1349
 
            myDisplayUpdateCurrentTime (display_info, xevent);
1350
 
        }
1351
 
 
1352
 
        key_width_inc = c->size->width_inc;
1353
 
        key_height_inc = c->size->height_inc;
1354
 
 
1355
 
        if (key_width_inc < 10)
1356
 
        {
1357
 
            key_width_inc = ((int) (10 / key_width_inc)) * key_width_inc;
1358
 
        }
1359
 
        if (key_height_inc < 10)
1360
 
        {
1361
 
            key_height_inc = ((int) (10 / key_height_inc)) * key_height_inc;
1362
 
        }
1363
 
 
1364
 
        if (xevent->xkey.keycode == screen_info->params->keys[KEY_UP].keycode)
1365
 
        {
1366
 
            if ((passdata->handle == CORNER_COUNT + SIDE_BOTTOM) ||
1367
 
                (passdata->handle == CORNER_COUNT + SIDE_TOP))
1368
 
            {
1369
 
                clientMovePointer (display_info, 0, -1, key_height_inc);
1370
 
            }
1371
 
            else
1372
 
            {
1373
 
                clientChangeHandle (passdata, CORNER_COUNT + SIDE_TOP);
1374
 
            }
1375
 
        }
1376
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_DOWN].keycode)
1377
 
        {
1378
 
            if ((passdata->handle == CORNER_COUNT + SIDE_BOTTOM) ||
1379
 
                (passdata->handle == CORNER_COUNT + SIDE_TOP))
1380
 
            {
1381
 
                clientMovePointer (display_info, 0, 1, key_height_inc);
1382
 
            }
1383
 
            else
1384
 
            {
1385
 
                clientChangeHandle (passdata, CORNER_COUNT + SIDE_BOTTOM);
1386
 
            }
1387
 
        }
1388
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_LEFT].keycode)
1389
 
        {
1390
 
            if ((passdata->handle == CORNER_COUNT + SIDE_LEFT) ||
1391
 
                (passdata->handle == CORNER_COUNT + SIDE_RIGHT))
1392
 
            {
1393
 
                clientMovePointer (display_info, -1, 0, key_width_inc);
1394
 
            }
1395
 
            else
1396
 
            {
1397
 
                clientChangeHandle (passdata, CORNER_COUNT + SIDE_LEFT);
1398
 
            }
1399
 
        }
1400
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_RIGHT].keycode)
1401
 
        {
1402
 
            if ((passdata->handle == CORNER_COUNT + SIDE_LEFT) ||
1403
 
                (passdata->handle == CORNER_COUNT + SIDE_RIGHT))
1404
 
            {
1405
 
                clientMovePointer (display_info, 1, 0, key_width_inc);
1406
 
            }
1407
 
            else
1408
 
            {
1409
 
                clientChangeHandle (passdata, CORNER_COUNT + SIDE_RIGHT);
1410
 
            }
1411
 
        }
1412
 
        else if (xevent->xkey.keycode == screen_info->params->keys[KEY_CANCEL].keycode)
1413
 
        {
1414
 
            resizing = FALSE;
1415
 
            passdata->released = passdata->use_keys;
1416
 
 
1417
 
            if (screen_info->params->box_resize)
1418
 
            {
1419
 
                clientDrawOutline (c);
1420
 
            }
1421
 
 
1422
 
            /* restore the pre-resize position & size */
1423
 
            c->x = passdata->cancel_x;
1424
 
            c->y = passdata->cancel_y;
1425
 
            c->width = passdata->cancel_w;
1426
 
            c->height = passdata->cancel_h;
1427
 
            if (screen_info->params->box_resize)
1428
 
            {
1429
 
                clientDrawOutline (c);
1430
 
            }
1431
 
            else
1432
 
            {
1433
 
                clientResizeConfigure (c, prev_x, prev_y, prev_width, prev_height);
1434
 
            }
1435
 
        }
1436
 
        else if (passdata->use_keys)
1437
 
        {
1438
 
            resizing = clientKeyPressIsModifier(xevent);
1439
 
        }
1440
 
    }
1441
 
    else if (xevent->type == MotionNotify)
1442
 
    {
1443
 
        while (XCheckMaskEvent (display_info->dpy, ButtonMotionMask | PointerMotionMask, xevent))
1444
 
        {
1445
 
            /* Update the display time */
1446
 
            myDisplayUpdateCurrentTime (display_info, xevent);
1447
 
        }
1448
 
 
1449
 
        if (xevent->type == ButtonRelease)
1450
 
        {
1451
 
            resizing = FALSE;
1452
 
        }
1453
 
        if (!passdata->grab && screen_info->params->box_resize)
1454
 
        {
1455
 
            myDisplayGrabServer (display_info);
1456
 
            passdata->grab = TRUE;
1457
 
            clientDrawOutline (c);
1458
 
        }
1459
 
        if (screen_info->params->box_resize)
1460
 
        {
1461
 
            clientDrawOutline (c);
1462
 
        }
1463
 
        passdata->oldw = c->width;
1464
 
        passdata->oldh = c->height;
1465
 
 
1466
 
        if (move_left)
1467
 
        {
1468
 
            c->width = passdata->ow - (xevent->xmotion.x_root - passdata->mx);
1469
 
        }
1470
 
        else if (move_right)
1471
 
        {
1472
 
            c->width = passdata->ow + (xevent->xmotion.x_root - passdata->mx);
1473
 
 
1474
 
            /* Attempt to snap the right edge to something. -Cliff */
1475
 
            c->width = clientFindClosestEdgeX (c, c->x + c->width + frameRight (c)) - c->x - frameRight (c);
1476
 
 
1477
 
        }
1478
 
        if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
1479
 
        {
1480
 
            if (move_top)
1481
 
            {
1482
 
                c->height = passdata->oh - (xevent->xmotion.y_root - passdata->my);
1483
 
            }
1484
 
            else if (move_bottom)
1485
 
            {
1486
 
                c->height = passdata->oh + (xevent->xmotion.y_root - passdata->my);
1487
 
 
1488
 
                /* Attempt to snap the bottom edge to something. -Cliff */
1489
 
                c->height = clientFindClosestEdgeY (c, c->y + c->height + frameBottom (c)) - c->y - frameBottom (c);
1490
 
            }
1491
 
        }
1492
 
        clientConstrainRatio (c, passdata->handle);
1493
 
 
1494
 
        clientSetWidth (c, c->width, FALSE);
1495
 
        if (move_left)
1496
 
        {
1497
 
            c->x = c->x - (c->width - passdata->oldw);
1498
 
 
1499
 
            /* Snap the left edge to something. -Cliff */
1500
 
            right_edge = c->x + c->width;
1501
 
            c->x = clientFindClosestEdgeX (c, c->x - frameLeft (c)) + frameLeft (c);
1502
 
            c->width = right_edge - c->x;
1503
 
 
1504
 
            frame_x = frameX (c);
1505
 
        }
1506
 
 
1507
 
        clientSetHeight (c, c->height, FALSE);
1508
 
        if (!FLAG_TEST (c->flags, CLIENT_FLAG_SHADED) && move_top)
1509
 
        {
1510
 
            c->y = c->y - (c->height - passdata->oldh);
1511
 
 
1512
 
            /* Snap the top edge to something. -Cliff */
1513
 
            bottom_edge = c->y + c->height;
1514
 
            c->y = clientFindClosestEdgeY (c, c->y - frameTop (c)) + frameTop (c);
1515
 
            c->height = bottom_edge - c->y;
1516
 
 
1517
 
            frame_y = frameY (c);
1518
 
        }
1519
 
 
1520
 
        if (move_top)
1521
 
        {
1522
 
            if ((c->y > MAX (disp_max_y - min_visible, screen_info->height - screen_info->margins [STRUTS_BOTTOM] - min_visible))
1523
 
                || (!clientCkeckTitle (c) && (frame_y < screen_info->margins [STRUTS_TOP])))
1524
 
            {
1525
 
                temp = c->y + c->height;
1526
 
                c->y = CLAMP (c->y, screen_info->margins [STRUTS_TOP] + frame_top,
1527
 
                         MAX (disp_max_y - min_visible,  screen_info->height - screen_info->margins [STRUTS_BOTTOM] - min_visible));
1528
 
                clientSetHeight (c, temp - c->y, FALSE);
1529
 
                c->y = temp - c->height;
1530
 
            }
1531
 
            else if (frame_y < 0)
1532
 
            {
1533
 
                temp = c->y + c->height;
1534
 
                c->y = frame_top;
1535
 
                clientSetHeight (c, temp - c->y, FALSE);
1536
 
                c->y = temp - c->height;
1537
 
            }
1538
 
        }
1539
 
        else if (move_bottom)
1540
 
        {
1541
 
            if (c->y + c->height < MAX (disp_y + min_visible, screen_info->margins [STRUTS_TOP] + min_visible))
1542
 
            {
1543
 
                temp = MAX (disp_y + min_visible, screen_info->margins [STRUTS_TOP] + min_visible);
1544
 
                clientSetHeight (c, temp - c->y, FALSE);
1545
 
            }
1546
 
        }
1547
 
        if (move_left)
1548
 
        {
1549
 
            if (c->x > MIN (disp_max_x - min_visible, screen_info->width - screen_info->margins [STRUTS_RIGHT] - min_visible))
1550
 
            {
1551
 
                temp = c->x + c->width;
1552
 
                c->x = MIN (disp_max_x - min_visible, screen_info->width - screen_info->margins [STRUTS_RIGHT] - min_visible);
1553
 
                clientSetWidth (c, temp - c->x, FALSE);
1554
 
                c->x = temp - c->width;
1555
 
            }
1556
 
        }
1557
 
        else if (move_right)
1558
 
        {
1559
 
            if (c->x + c->width < MAX (disp_x + min_visible, screen_info->margins [STRUTS_LEFT] + min_visible))
1560
 
            {
1561
 
                temp = MAX (disp_x + min_visible, screen_info->margins [STRUTS_LEFT] + min_visible);
1562
 
                clientSetWidth (c, temp - c->x, FALSE);
1563
 
            }
1564
 
        }
1565
 
 
1566
 
        if (passdata->poswin)
1567
 
        {
1568
 
            poswinSetPosition (passdata->poswin, c);
1569
 
        }
1570
 
        if (screen_info->params->box_resize)
1571
 
        {
1572
 
            clientDrawOutline (c);
1573
 
        }
1574
 
        else
1575
 
        {
1576
 
            clientResizeConfigure (c, prev_x, prev_y, prev_width, prev_height);
1577
 
        }
1578
 
    }
1579
 
    else if (xevent->type == ButtonRelease)
1580
 
    {
1581
 
        resizing = FALSE;
1582
 
        passdata->released = (passdata->use_keys || (xevent->xbutton.button == passdata->button));
1583
 
    }
1584
 
    else if ((xevent->type == UnmapNotify) && (xevent->xunmap.window == c->window))
1585
 
    {
1586
 
        resizing = FALSE;
1587
 
    }
1588
 
    else if (xevent->type == EnterNotify)
1589
 
    {
1590
 
        /* Ignore enter events */
1591
 
    }
1592
 
    else
1593
 
    {
1594
 
        status = EVENT_FILTER_CONTINUE;
1595
 
    }
1596
 
 
1597
 
    TRACE ("leaving clientResizeEventFilter");
1598
 
 
1599
 
    if (!resizing)
1600
 
    {
1601
 
        TRACE ("event loop now finished");
1602
 
        gtk_main_quit ();
1603
 
    }
1604
 
 
1605
 
    return status;
1606
 
}
1607
 
 
1608
 
void
1609
 
clientResize (Client * c, int handle, XEvent * ev)
1610
 
{
1611
 
    ScreenInfo *screen_info;
1612
 
    DisplayInfo *display_info;
1613
 
    XWindowChanges wc;
1614
 
    MoveResizeData passdata;
1615
 
    int w_orig, h_orig;
1616
 
    Cursor cursor;
1617
 
    gboolean g1, g2;
1618
 
 
1619
 
    g_return_if_fail (c != NULL);
1620
 
    TRACE ("entering clientResize");
1621
 
 
1622
 
    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING))
1623
 
    {
1624
 
        return;
1625
 
    }
1626
 
 
1627
 
    if (!FLAG_TEST_ALL (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_IS_RESIZABLE))
1628
 
    {
1629
 
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
1630
 
        {
1631
 
            clientMove (c, ev);
1632
 
        }
1633
 
        return;
1634
 
    }
1635
 
 
1636
 
    if (FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
1637
 
    {
1638
 
        return;
1639
 
    }
1640
 
 
1641
 
    screen_info = c->screen_info;
1642
 
    display_info = screen_info->display_info;
1643
 
 
1644
 
    if (FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED)
1645
 
        && (screen_info->params->borderless_maximize))
1646
 
    {
1647
 
        return;
1648
 
    }
1649
 
 
1650
 
    TRACE ("resizing client \"%s\" (0x%lx)", c->name, c->window);
1651
 
 
1652
 
    passdata.c = c;
1653
 
    passdata.cancel_x = passdata.ox = c->x;
1654
 
    passdata.cancel_y = passdata.oy = c->y;
1655
 
    passdata.cancel_w = passdata.ow = c->width;
1656
 
    passdata.cancel_h = passdata.oh = c->height;
1657
 
    passdata.use_keys = FALSE;
1658
 
    passdata.grab = FALSE;
1659
 
    passdata.released = FALSE;
1660
 
    passdata.button = 0;
1661
 
    passdata.handle = handle;
1662
 
    w_orig = c->width;
1663
 
    h_orig = c->height;
1664
 
 
1665
 
    if (ev && (ev->type == ButtonPress))
1666
 
    {
1667
 
        passdata.button = ev->xbutton.button;
1668
 
        passdata.mx = ev->xbutton.x_root;
1669
 
        passdata.my = ev->xbutton.y_root;
1670
 
    }
1671
 
    else
1672
 
    {
1673
 
        clientSetHandle (&passdata, handle);
1674
 
        passdata.released = passdata.use_keys = TRUE;
1675
 
    }
1676
 
    if ((handle > NO_HANDLE) && (handle <= HANDLES_COUNT))
1677
 
    {
1678
 
        cursor = myDisplayGetCursorResize (display_info, passdata.handle);
1679
 
    }
1680
 
    else
1681
 
    {
1682
 
        cursor = myDisplayGetCursorMove (display_info);
1683
 
    }
1684
 
 
1685
 
    g1 = myScreenGrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info));
1686
 
    g2 = myScreenGrabPointer (screen_info, MOVERESIZE_EVENT_MASK,
1687
 
                              cursor, myDisplayGetCurrentTime (display_info));
1688
 
 
1689
 
    if (!g1 || !g2)
1690
 
    {
1691
 
        TRACE ("grab failed in clientResize");
1692
 
 
1693
 
        gdk_beep ();
1694
 
        myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info));
1695
 
        myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info));
1696
 
 
1697
 
        return;
1698
 
    }
1699
 
 
1700
 
    passdata.poswin = NULL;
1701
 
#ifndef SHOW_POSITION
1702
 
    if ((c->size->width_inc > 1) || (c->size->height_inc > 1))
1703
 
#endif /* SHOW_POSITION */
1704
 
    {
1705
 
        passdata.poswin = poswinCreate(screen_info->gscr);
1706
 
        poswinSetPosition (passdata.poswin, c);
1707
 
        poswinShow (passdata.poswin);
1708
 
    }
1709
 
 
1710
 
#ifdef HAVE_XSYNC
1711
 
    clientXSyncEnable (c);
1712
 
#endif /* HAVE_XSYNC */
1713
 
 
1714
 
    /* Set window translucent while resizing */
1715
 
    if ((screen_info->params->resize_opacity < 100) &&
1716
 
        !(screen_info->params->box_resize) &&
1717
 
        !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED))
1718
 
    {
1719
 
        clientSetOpacity (c, c->opacity, OPACITY_RESIZE, OPACITY_RESIZE);
1720
 
    }
1721
 
 
1722
 
    /* Clear any previously saved pos flag from screen resize */
1723
 
    FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_SAVED_POS);
1724
 
 
1725
 
    FLAG_SET (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING);
1726
 
    TRACE ("entering resize loop");
1727
 
    eventFilterPush (display_info->xfilter, clientResizeEventFilter, &passdata);
1728
 
    gtk_main ();
1729
 
    eventFilterPop (display_info->xfilter);
1730
 
    TRACE ("leaving resize loop");
1731
 
    FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING);
1732
 
 
1733
 
    if (passdata.poswin)
1734
 
    {
1735
 
        poswinDestroy (passdata.poswin);
1736
 
    }
1737
 
    if (passdata.grab && screen_info->params->box_resize)
1738
 
    {
1739
 
        clientDrawOutline (c);
1740
 
    }
1741
 
    /* Set window opacity to its original value */
1742
 
    clientSetOpacity (c, c->opacity, OPACITY_RESIZE, 0);
1743
 
 
1744
 
    if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED) &&
1745
 
        ((w_orig != c->width) || (h_orig != c->height)))
1746
 
    {
1747
 
        clientRemoveMaximizeFlag (c);
1748
 
    }
1749
 
 
1750
 
    wc.x = c->x;
1751
 
    wc.y = c->y;
1752
 
    wc.width = c->width;
1753
 
    wc.height = c->height;
1754
 
    clientConfigure (c, &wc, CWX | CWY | CWHeight | CWWidth, NO_CFG_FLAG);
1755
 
#ifdef HAVE_XSYNC
1756
 
    clientXSyncClearTimeout (c);
1757
 
    c->xsync_waiting = FALSE;
1758
 
#endif /* HAVE_XSYNC */
1759
 
 
1760
 
    if (!passdata.released)
1761
 
    {
1762
 
        /* If this is a drag-resize, wait for the button to be released.
1763
 
         * If we don't, we might get release events in the wrong place.
1764
 
         */
1765
 
        eventFilterPush (display_info->xfilter, clientButtonReleaseFilter, &passdata);
1766
 
        gtk_main ();
1767
 
        eventFilterPop (display_info->xfilter);
1768
 
    }
1769
 
 
1770
 
    myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info));
1771
 
    myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info));
1772
 
 
1773
 
    if (passdata.grab && screen_info->params->box_resize)
1774
 
    {
1775
 
        myDisplayUngrabServer (display_info);
1776
 
    }
1777
 
}