~compiz-team/compiz-core/compiz-core.fix_694169

« back to all changes in this revision

Viewing changes to src/window.cpp

  • Committer: Sam Spilsbury
  • Date: 2011-10-11 17:05:13 UTC
  • mfrom: (2876.1.2 compiz-core)
  • Revision ID: sam.spilsbury@canonical.com-20111011170513-ym53becy3mt3kbob
MergeĀ lp:~compiz-team/compiz-core/compiz-core.fix_864330

Show diffs side-by-side

added added

removed removed

Lines of Context:
897
897
 
898
898
            }
899
899
 
900
 
            gettimeofday (&lastConfigureRequest, NULL);
901
900
            compiz::X11::PendingEvent::Ptr pc =
902
901
                    boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
903
902
                                                                              new compiz::X11::PendingConfigureEvent (
904
903
                                                                                  screen->dpy (), serverFrame, valueMask, &xwc)));
905
904
 
906
905
            pendingConfigures.add (pc);
 
906
            if (priv->mClearCheckTimeout.active ())
 
907
                priv->mClearCheckTimeout.stop ();
 
908
            priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
909
                                            2000, 2500);
907
910
 
908
911
            XSendEvent (screen->dpy (), screen->root (), false,
909
912
                        SubstructureNotifyMask, (XEvent *) &xev);
913
916
        }
914
917
        else
915
918
        {
916
 
            gettimeofday (&lastConfigureRequest, NULL);
917
919
            compiz::X11::PendingEvent::Ptr pc =
918
920
                    boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
919
921
                                                                              new compiz::X11::PendingConfigureEvent (
920
922
                                                                                  screen->dpy (), serverFrame, valueMask, &xwc)));
921
923
 
922
924
            pendingConfigures.add (pc);
 
925
            if (priv->mClearCheckTimeout.active ())
 
926
                priv->mClearCheckTimeout.stop ();
 
927
            priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
928
                                            2000, 2500);
923
929
            XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
924
930
        }
925
931
 
951
957
        if (shaded)
952
958
            xwc.height = bw;
953
959
        else
954
 
            xwc.height = bw;
955
 
 
956
 
        if (shaded)
957
 
            height = 0;
 
960
            xwc.height = serverGeometry.height () + bw;
958
961
 
959
962
        if (serverFrameGeometry.x () == xwc.x)
960
963
            valueMask &= ~(CWX);
1032
1035
 
1033
1036
            }
1034
1037
 
1035
 
            gettimeofday (&lastConfigureRequest, NULL);
1036
1038
            compiz::X11::PendingEvent::Ptr pc =
1037
1039
                    boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
1038
1040
                                                                              new compiz::X11::PendingConfigureEvent (
1039
1041
                                                                                  screen->dpy (), serverFrame, valueMask, &xwc)));
1040
1042
 
1041
1043
            pendingConfigures.add (pc);
 
1044
            if (priv->mClearCheckTimeout.active ())
 
1045
                priv->mClearCheckTimeout.stop ();
 
1046
            priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
1047
                                            2000, 2500);
1042
1048
 
1043
1049
            XSendEvent (screen->dpy (), screen->root (), false,
1044
1050
                        SubstructureNotifyMask, (XEvent *) &xev);
1048
1054
        }
1049
1055
        else
1050
1056
        {
1051
 
            gettimeofday (&lastConfigureRequest, NULL);
1052
1057
            compiz::X11::PendingEvent::Ptr pc =
1053
1058
                    boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
1054
1059
                                                                              new compiz::X11::PendingConfigureEvent (
1055
1060
                                                                                  screen->dpy (), serverFrame, valueMask, &xwc)));
1056
1061
 
1057
1062
            pendingConfigures.add (pc);
 
1063
            if (priv->mClearCheckTimeout.active ())
 
1064
                priv->mClearCheckTimeout.stop ();
 
1065
            priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
1066
                                            2000, 2500);
1058
1067
 
1059
1068
            XConfigureWindow (screen->dpy (), serverFrame, valueMask, &xwc);
1060
1069
        }
2088
2097
#ifdef DEBUG
2089
2098
        abort ();
2090
2099
#else
2091
 
        pendingConfigures = compiz::X11::PendingEventQueue (screen->dpy ());
 
2100
        pendingConfigures.clear ();
2092
2101
#endif
2093
2102
    }
2094
2103
 
2199
2208
        {
2200
2209
            XWindowChanges xwc;
2201
2210
            unsigned int   valueMask = CWX | CWY;
2202
 
            struct timeval tv, old;
2203
 
            compLogMessage ("core", CompLogLevelDebug, "pending configure notifies on 0x%x,"\
 
2211
            compLogMessage ("core", CompLogLevelDebug, "pending configure notifies on 0x%x, "\
2204
2212
                            "moving window asyncrhonously!", (unsigned int) priv->serverId);
2205
2213
 
2206
 
            old = priv->lastConfigureRequest;
2207
 
            gettimeofday (&tv, NULL);
2208
 
 
2209
2214
            xwc.x = priv->serverGeometry.x () + dx;
2210
2215
            xwc.y = priv->serverGeometry.y () + dy;
2211
2216
 
2212
2217
            configureXWindow (valueMask, &xwc);
2213
 
 
2214
 
            priv->lastConfigureRequest = old;
2215
 
 
2216
 
            /* FIXME: This is a hack to avoid performance regressions
2217
 
             * and must be removed in 0.9.6 */
2218
 
            if (tv.tv_usec - priv->lastConfigureRequest.tv_usec > 30000)
2219
 
            {
2220
 
                compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event from request at %i (now: %i)\n",
2221
 
                                priv->lastConfigureRequest.tv_usec, tv.tv_usec);
2222
 
                priv->pendingConfigures = compiz::X11::PendingEventQueue (screen->dpy ());
2223
 
            }
2224
2218
        }
2225
2219
    }
2226
2220
}
2231
2225
    return !mEvents.empty ();
2232
2226
}
2233
2227
 
 
2228
bool
 
2229
PrivateWindow::checkClear ()
 
2230
{
 
2231
    if (pendingConfigures.pending ())
 
2232
    {
 
2233
        /* FIXME: This is a hack to avoid performance regressions
 
2234
         * and must be removed in 0.9.6 */
 
2235
        compLogMessage ("core", CompLogLevelWarn, "failed to receive ConfigureNotify event on 0x%x\n",
 
2236
                        id);
 
2237
        pendingConfigures.dump ();
 
2238
        pendingConfigures.clear ();
 
2239
    }
 
2240
 
 
2241
    return false;
 
2242
}
 
2243
 
2234
2244
void
2235
2245
compiz::X11::PendingEventQueue::add (PendingEvent::Ptr p)
2236
2246
{
 
2247
    compLogMessage ("core", CompLogLevelDebug, "pending request:");
 
2248
    p->dump ();
 
2249
 
2237
2250
    mEvents.push_back (p);
2238
2251
}
2239
2252
 
2240
2253
bool
2241
2254
compiz::X11::PendingEventQueue::removeIfMatching (const PendingEvent::Ptr &p, XEvent *event)
2242
2255
{
2243
 
    return p->match (event);
 
2256
    if (p->match (event))
 
2257
    {
 
2258
        compLogMessage ("core", CompLogLevelDebug, "received event:");
 
2259
        p->dump ();
 
2260
        return true;
 
2261
    }
 
2262
 
 
2263
    return false;
 
2264
}
 
2265
 
 
2266
void
 
2267
compiz::X11::PendingEvent::dump ()
 
2268
{
 
2269
    compLogMessage ("core", CompLogLevelDebug, "- event serial: %i", mSerial);
 
2270
    compLogMessage ("core", CompLogLevelDebug,  "- event window 0x%x", mWindow);
 
2271
}
 
2272
 
 
2273
void
 
2274
compiz::X11::PendingConfigureEvent::dump ()
 
2275
{
 
2276
    compiz::X11::PendingEvent::dump ();
 
2277
 
 
2278
    compLogMessage ("core", CompLogLevelDebug,  "- x: %i y: %i width: %i height: %i "\
 
2279
                                                 "border: %i, sibling: 0x%x",
 
2280
                                                 mXwc.x, mXwc.y, mXwc.width, mXwc.height, mXwc.border_width, mXwc.sibling);
2244
2281
}
2245
2282
 
2246
2283
bool
2266
2303
    return false;
2267
2304
}
2268
2305
 
 
2306
void
 
2307
compiz::X11::PendingEventQueue::dump ()
 
2308
{
 
2309
    foreach (compiz::X11::PendingEvent::Ptr p, mEvents)
 
2310
        p->dump ();
 
2311
}
 
2312
 
2269
2313
compiz::X11::PendingEventQueue::PendingEventQueue (Display *d)
2270
2314
{
 
2315
    /* mClearCheckTimeout.setTimes (0, 0)
 
2316
     *
 
2317
     * XXX: For whatever reason, calling setTimes (0, 0) here causes
 
2318
     * the destructor of the timer object to be called twice later on
 
2319
     * in execution and the stack gets smashed. This could be a
 
2320
     * compiler bug, but requires further investigation */
2271
2321
}
2272
2322
 
2273
2323
compiz::X11::PendingEventQueue::~PendingEventQueue ()
2310
2360
bool
2311
2361
compiz::X11::PendingConfigureEvent::matchVM (unsigned int valueMask)
2312
2362
{
2313
 
    return valueMask & mValueMask;
 
2363
    unsigned int result = mValueMask != 0 ? valueMask & mValueMask : 1;
 
2364
 
 
2365
    return result != 0;
 
2366
}
 
2367
 
 
2368
bool
 
2369
compiz::X11::PendingConfigureEvent::matchRequest (XWindowChanges &xwc, unsigned int valueMask)
 
2370
{
 
2371
    if (matchVM (valueMask))
 
2372
    {
 
2373
        if (valueMask & CWX)
 
2374
            if (xwc.x != mXwc.x)
 
2375
                return false;
 
2376
 
 
2377
        if (valueMask & CWY)
 
2378
            if (xwc.y != mXwc.y)
 
2379
                return false;
 
2380
 
 
2381
        if (valueMask & CWWidth)
 
2382
            if (xwc.width != mXwc.width)
 
2383
                return false;
 
2384
 
 
2385
        if (valueMask & CWHeight)
 
2386
            if (xwc.height != mXwc.height)
 
2387
                return false;
 
2388
 
 
2389
        if (valueMask & CWBorderWidth)
 
2390
            if (xwc.border_width != mXwc.border_width)
 
2391
                return false;
 
2392
 
 
2393
        if (valueMask & (CWStackMode | CWSibling))
 
2394
            if (xwc.sibling != mXwc.sibling)
 
2395
                return false;
 
2396
 
 
2397
        return true;
 
2398
    }
 
2399
 
 
2400
    return false;
2314
2401
}
2315
2402
 
2316
2403
bool
2322
2409
    if (!compiz::X11::PendingEvent::match (event))
2323
2410
        return false;
2324
2411
 
2325
 
    if (mValueMask & CWX)
2326
 
        if (ce->x != mXwc.x)
2327
 
            matched = false;
2328
 
 
2329
 
    if (mValueMask & CWY)
2330
 
        if (ce->y != mXwc.y)
2331
 
            matched = false;
2332
 
 
2333
 
    if (mValueMask & CWWidth)
2334
 
        if (ce->width != mXwc.width)
2335
 
            matched = false;
2336
 
 
2337
 
    if (mValueMask & CWHeight)
2338
 
        if (ce->height != mXwc.height)
2339
 
            matched = false;
2340
 
 
2341
 
    if (mValueMask & CWBorderWidth)
2342
 
        if (ce->border_width != mXwc.border_width)
2343
 
            matched = false;
2344
 
 
2345
 
    if (mValueMask & (CWStackMode | CWSibling))
2346
 
        if (ce->above != mXwc.sibling)
2347
 
            matched = false;
 
2412
    XWindowChanges xwc;
 
2413
 
 
2414
    xwc.x = ce->x;
 
2415
    xwc.y = ce->y;
 
2416
    xwc.width = ce->width;
 
2417
    xwc.height = ce->height;
 
2418
    xwc.border_width = ce->border_width;
 
2419
    xwc.sibling = ce->above;
 
2420
 
 
2421
    matched = matchRequest (xwc, mValueMask);
2348
2422
 
2349
2423
    /* Remove events from the queue
2350
2424
     * even if they didn't match what
2440
2514
            xwc.x = priv->serverFrameGeometry.x ();
2441
2515
            xwc.y = priv->serverFrameGeometry.y ();
2442
2516
 
2443
 
            gettimeofday (&priv->lastConfigureRequest, NULL);
2444
2517
            compiz::X11::PendingEvent::Ptr pc =
2445
2518
                    boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
2446
2519
                                                                              new compiz::X11::PendingConfigureEvent (
2448
2521
 
2449
2522
            priv->pendingConfigures.add (pc);
2450
2523
 
 
2524
            /* Got 3 seconds to get its stuff together */
 
2525
            if (priv->mClearCheckTimeout.active ())
 
2526
                priv->mClearCheckTimeout.stop ();
 
2527
            priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
2528
                                            2000, 2500);
2451
2529
            XConfigureWindow (screen->dpy (), ROOTPARENT (this), valueMask, &xwc);
2452
2530
 
2453
2531
            if (priv->serverFrame)
3259
3337
    return pc->matchVM (CWStackMode | CWSibling);
3260
3338
}
3261
3339
 
 
3340
static bool isExistingRequest (compiz::X11::PendingEvent::Ptr p, XWindowChanges &xwc, unsigned int valueMask)
 
3341
{
 
3342
    compiz::X11::PendingConfigureEvent::Ptr pc = boost::shared_static_cast <compiz::X11::PendingConfigureEvent> (p);
 
3343
 
 
3344
    return pc->matchRequest (xwc, valueMask);
 
3345
}
 
3346
 
3262
3347
void
3263
3348
PrivateWindow::reconfigureXWindow (unsigned int   valueMask,
3264
3349
                                   XWindowChanges *xwc)
3265
3350
{
3266
 
    unsigned int frameValueMask = valueMask;
 
3351
    unsigned int frameValueMask = 0;
3267
3352
 
3268
3353
    /* Immediately sync window position
3269
3354
     * if plugins were updating w->geometry () directly
3273
3358
 
3274
3359
    /* Remove redundant bits */
3275
3360
 
3276
 
    if (serverGeometry.x () == xwc->x)
 
3361
    if (valueMask & CWX && serverGeometry.x () == xwc->x)
3277
3362
        valueMask &= ~(CWX);
3278
3363
 
3279
 
    if (serverGeometry.y () == xwc->y)
 
3364
    if (valueMask & CWY && serverGeometry.y () == xwc->y)
3280
3365
        valueMask &= ~(CWY);
3281
3366
 
3282
 
    if (serverGeometry.width () == xwc->width)
 
3367
    if (valueMask & CWWidth && serverGeometry.width () == xwc->width)
3283
3368
        valueMask &= ~(CWWidth);
3284
3369
 
3285
 
    if (serverGeometry.height () == xwc->height)
 
3370
    if (valueMask & CWHeight && serverGeometry.height () == xwc->height)
3286
3371
        valueMask &= ~(CWHeight);
3287
3372
 
3288
 
    if (serverGeometry.border () == xwc->border_width)
 
3373
    if (valueMask & CWBorderWidth && serverGeometry.border () == xwc->border_width)
3289
3374
        valueMask &= ~(CWBorderWidth);
3290
3375
 
3291
 
    if (window->serverPrev && ROOTPARENT (window->serverPrev) == xwc->sibling)
 
3376
    if (valueMask & CWSibling && window->serverPrev)
3292
3377
    {
3293
3378
        /* check if the sibling is also pending a restack,
3294
3379
         * if not, then setting this bit is useless */
3295
 
 
3296
 
        if (window->serverPrev->priv->pendingConfigures.forEachIf (boost::bind (isPendingRestack, _1)))
3297
 
            valueMask &= ~(CWSibling | CWStackMode);
 
3380
        if (ROOTPARENT (window->serverPrev) == xwc->sibling)
 
3381
        {
 
3382
            bool matchingRequest = priv->pendingConfigures.forEachIf (boost::bind (isExistingRequest, _1, *xwc, valueMask));
 
3383
            bool restackPending = window->serverPrev->priv->pendingConfigures.forEachIf (boost::bind (isPendingRestack, _1));
 
3384
            bool remove = matchingRequest;
 
3385
 
 
3386
            if (!remove)
 
3387
                remove = !restackPending;
 
3388
 
 
3389
            if (remove)
 
3390
                valueMask &= ~(CWSibling | CWStackMode);
 
3391
        }
3298
3392
    }
3299
3393
 
3300
3394
    if (valueMask & CWBorderWidth)
3330
3424
            compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
3331
3425
    }
3332
3426
 
3333
 
    if (serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
 
3427
    frameValueMask = valueMask;
 
3428
 
 
3429
    if (frameValueMask & CWX &&
 
3430
        serverFrameGeometry.x () == xwc->x - serverGeometry.border () - serverInput.left)
3334
3431
        frameValueMask &= ~(CWX);
3335
3432
 
3336
 
    if (serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
 
3433
    if (frameValueMask & CWY &&
 
3434
        serverFrameGeometry.y () == xwc->y - serverGeometry.border () - serverInput.top)
3337
3435
        frameValueMask &= ~(CWY);
3338
3436
 
3339
 
   if (serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
 
3437
   if (frameValueMask & CWWidth &&
 
3438
        serverFrameGeometry.width () == xwc->width + serverGeometry.border () * 2
3340
3439
                                      + serverInput.left + serverInput.right)
3341
3440
        frameValueMask &= ~(CWWidth);
3342
3441
 
3346
3445
 
3347
3446
    if (shaded)
3348
3447
    {
3349
 
        if (serverFrameGeometry.height () == serverGeometry.border () * 2
 
3448
        if (frameValueMask & CWHeight &&
 
3449
            serverFrameGeometry.height () == serverGeometry.border () * 2
3350
3450
            + serverInput.top + serverInput.bottom)
3351
3451
            frameValueMask &= ~(CWHeight);
3352
3452
    }
3353
3453
    else
3354
3454
    {
3355
 
        if (serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
 
3455
        if (frameValueMask & CWHeight &&
 
3456
            serverFrameGeometry.height () == xwc->height + serverGeometry.border () * 2
3356
3457
            + serverInput.top + serverInput.bottom)
3357
3458
            frameValueMask &= ~(CWHeight);
3358
3459
    }
3397
3498
            wc.width  = serverFrameGeometry.width ();
3398
3499
            wc.height = serverFrameGeometry.height ();
3399
3500
 
3400
 
            gettimeofday (&lastConfigureRequest, NULL);
3401
 
 
3402
3501
            compiz::X11::PendingEvent::Ptr pc =
3403
3502
                    boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
3404
3503
                                                                              new compiz::X11::PendingConfigureEvent (
3405
3504
                                                                                  screen->dpy (), priv->serverFrame, frameValueMask, &wc)));
3406
3505
 
3407
3506
            pendingConfigures.add (pc);
 
3507
            if (priv->mClearCheckTimeout.active ())
 
3508
                priv->mClearCheckTimeout.stop ();
 
3509
            priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
3510
                                            2000, 2500);
3408
3511
 
3409
3512
            XConfigureWindow (screen->dpy (), serverFrame, frameValueMask, &wc);
3410
3513
        }
4196
4299
 
4197
4300
                if (serverFrame)
4198
4301
                {
4199
 
                    gettimeofday (&lastConfigureRequest, NULL);
4200
4302
                    compiz::X11::PendingEvent::Ptr pc =
4201
4303
                            boost::shared_static_cast<compiz::X11::PendingEvent> (compiz::X11::PendingConfigureEvent::Ptr (
4202
4304
                                                                                      new compiz::X11::PendingConfigureEvent (
4203
4305
                                                                                          screen->dpy (), serverFrame, valueMask, &lxwc)));
4204
4306
 
4205
4307
                    pendingConfigures.add (pc);
 
4308
                    if (priv->mClearCheckTimeout.active ())
 
4309
                        priv->mClearCheckTimeout.stop ();
 
4310
                    priv->mClearCheckTimeout.start (boost::bind (&PrivateWindow::checkClear, priv),
 
4311
                                                    2000, 2500);
4206
4312
                }
4207
4313
 
4208
4314
                /* Below with no sibling puts the window at the bottom
4215
4321
            }
4216
4322
            else if (sibling)
4217
4323
            {
 
4324
                bool matchingRequest = priv->pendingConfigures.forEachIf (boost::bind (isExistingRequest, _1, *xwc, (CWStackMode | CWSibling)));
 
4325
                bool restackPending = window->serverPrev->priv->pendingConfigures.forEachIf (boost::bind (isPendingRestack, _1));
 
4326
                bool processAnyways = restackPending;
 
4327
 
 
4328
                if (matchingRequest)
 
4329
                    processAnyways = false;
 
4330
 
4218
4331
                if (sibling->priv->id != window->serverPrev->priv->id ||
4219
 
                    window->serverPrev->priv->pendingConfigures.forEachIf (boost::bind (isPendingRestack, _1)))
 
4332
                    processAnyways)
4220
4333
                {
4221
4334
                    mask |= CWSibling | CWStackMode;
4222
4335
 
6295
6408
    if (dbg)
6296
6409
        dbg->overrideRedirectRestack (priv->id, aboveId);
6297
6410
 
6298
 
    gettimeofday (&priv->lastConfigureRequest, NULL);
6299
 
 
6300
6411
    priv->attrib = wa;
6301
6412
    priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,
6302
6413
                              priv->attrib.width, priv->attrib.height,
7229
7340
    XDestroyWindow (screen->dpy (), wrapper);
7230
7341
 
7231
7342
    window->windowNotify (CompWindowNotifyUnreparent);
 
7343
    /* This window is no longer "managed" in the
 
7344
     * reparenting sense so clear its pending event
 
7345
     * queue ... though maybe in future it would
 
7346
     * be better to bookeep these events too and
 
7347
     * handle the ReparentNotify */
 
7348
    pendingConfigures.clear ();
7232
7349
 
7233
7350
    frame = None;
7234
7351
    wrapper = None;