~ubuntu-branches/ubuntu/precise/xfwm4/precise-updates

« back to all changes in this revision

Viewing changes to src/compositor.c

  • Committer: Bazaar Package Importer
  • Author(s): Jérôme Guelfucci, Jérôme Guelfucci, Lionel Le Folgoc
  • Date: 2009-01-30 18:28:59 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20090130182859-1tci3n1f1hhppvc2
Tags: 4.5.99.1-0ubuntu1
[ Jérôme Guelfucci ]
* Merge with Debian Xfce UNRELEASED, remaining Ubuntu changes:
  - debian/xfwm4.1: update bug reporting address (LP instead of Debian BTS).

[ Lionel Le Folgoc ]
* debian/control: use our Vcs-* fields.
* Bugs fixed by this new release:
  - "User interface of focused application is covered by another application's
    new window in Xfce" (LP: #250101)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*      $Id: compositor.c 27454 2008-08-15 21:45:57Z olivier $
 
1
/*      $Id$
2
2
 
3
3
        This program is free software; you can redistribute it and/or modify
4
4
        it under the terms of the GNU General Public License as published by
12
12
 
13
13
        You should have received a copy of the GNU General Public License
14
14
        along with this program; if not, write to the Free Software
15
 
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
15
        Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
 
16
        MA 02110-1301, USA.
 
17
 
16
18
 
17
19
        xcompmgr - (c) 2003 Keith Packard
18
20
        metacity - (c) 2003, 2004 Red Hat, Inc.
19
 
        xfwm4    - (c) 2005-2008 Olivier Fourdan
 
21
        xfwm4    - (c) 2005-2009 Olivier Fourdan
20
22
 
21
23
*/
22
24
 
48
50
#include <X11/extensions/Xrender.h>
49
51
 
50
52
#ifndef SHADOW_RADIUS
51
 
#define SHADOW_RADIUS   6
 
53
#define SHADOW_RADIUS   12
52
54
#endif /* SHADOW_RADIUS */
53
55
 
54
 
#ifndef SHADOW_OPACITY
55
 
#define SHADOW_OPACITY  0.66
56
 
#endif /* SHADOW_OPACITY */
57
 
 
58
56
#ifndef SHADOW_OFFSET_X
59
 
#define SHADOW_OFFSET_X (SHADOW_RADIUS * -3 /2)
 
57
#define SHADOW_OFFSET_X (-3 * SHADOW_RADIUS / 2)
60
58
#endif /* SHADOW_OFFSET_X */
61
59
 
62
60
#ifndef SHADOW_OFFSET_Y
63
 
#define SHADOW_OFFSET_Y (SHADOW_RADIUS * -5 / 4)
 
61
#define SHADOW_OFFSET_Y (-3 * SHADOW_RADIUS / 2)
64
62
#endif /* SHADOW_OFFSET_Y */
65
63
 
66
64
/* Some convenient macros */
69
67
                                         !FLAG_TEST (cw->c->flags, CLIENT_FLAG_FULLSCREEN))
70
68
#define WIN_NO_SHADOW(cw)               ((cw->c) && \
71
69
                                           (FLAG_TEST (cw->c->flags, CLIENT_FLAG_FULLSCREEN | CLIENT_FLAG_BELOW) || \
72
 
                                              (cw->c->type & (WINDOW_DOCK | WINDOW_DESKTOP))))
 
70
                                            (cw->c->type & WINDOW_DESKTOP)))
73
71
#define WIN_IS_DOCK(cw)                 (WIN_HAS_CLIENT(cw) && (cw->c->type & WINDOW_DOCK))
74
72
#define WIN_IS_OVERRIDE(cw)             (cw->attr.override_redirect)
75
73
#define WIN_IS_ARGB(cw)                 (cw->argb)
76
 
#define WIN_IS_OPAQUE(cw)               (((cw->opacity == NET_WM_OPAQUE) && !WIN_IS_ARGB(cw)) || (cw->screen_info->wins_unredirected))
 
74
#define WIN_IS_OPAQUE(cw)               ((cw->opacity == NET_WM_OPAQUE) && !WIN_IS_ARGB(cw))
77
75
#define WIN_IS_NATIVE_OPAQUE(cw)        ((cw->native_opacity) && !WIN_IS_ARGB(cw))
78
76
#define WIN_IS_FULLSCREEN(cw)           ((cw->attr.x <= 0) && \
79
77
                                           (cw->attr.y <= 0) && \
87
85
#define WIN_IS_DAMAGED(cw)              (cw->damaged)
88
86
#define WIN_IS_REDIRECTED(cw)           (cw->redirected)
89
87
 
90
 
#define USE_IDLE_REPAINT
 
88
/* Set TIMEOUT_REPAINT to 0 to disable timeout repaint */
 
89
#define TIMEOUT_REPAINT       20 /* (1/50 sec.) */
91
90
 
92
91
typedef struct _CWindow CWindow;
93
92
struct _CWindow
935
934
              !WIN_IS_OVERRIDE(cw) &&
936
935
              !WIN_NO_SHADOW(cw) &&
937
936
              !WIN_IS_DOCK(cw) &&
938
 
              (WIN_HAS_FRAME(cw) || !(WIN_IS_ARGB(cw) || WIN_IS_SHAPED(cw)))))
 
937
              (WIN_HAS_FRAME(cw) || !(WIN_IS_ARGB(cw) || WIN_IS_SHAPED(cw)))) ||
 
938
          (screen_info->params->show_dock_shadow &&
 
939
              WIN_IS_DOCK(cw) &&
 
940
              !WIN_NO_SHADOW(cw) &&
 
941
              !WIN_IS_OVERRIDE(cw) &&
 
942
              (!(WIN_IS_ARGB(cw) || WIN_IS_SHAPED(cw)))))
939
943
    {
940
944
        XRectangle sr;
941
945
 
947
951
        {
948
952
            double shadow_opacity;
949
953
            shadow_opacity = (double) screen_info->params->frame_opacity
950
 
                                      * SHADOW_OPACITY
951
 
                                      * cw->opacity
952
 
                                      / (NET_WM_OPAQUE * 100.0);
 
954
                           * (screen_info->params->shadow_opacity / 100.0)
 
955
                           * cw->opacity
 
956
                           / (NET_WM_OPAQUE * 100.0);
953
957
 
954
958
            cw->shadow = shadow_picture (screen_info, shadow_opacity,
955
959
                                         cw->attr.width + 2 * cw->attr.border_width,
1083
1087
        cw->redirected = FALSE;
1084
1088
 
1085
1089
        XCompositeUnredirectWindow (display_info->dpy, cw->id, display_info->composite_mode);
1086
 
        XSync (display_info->dpy, FALSE);
1087
 
 
1088
1090
        TRACE ("Window 0x%lx unredirected, wins_unredirected is %i", cw->id, screen_info->wins_unredirected);
1089
1091
    }
1090
1092
}
1385
1387
    XFixesDestroyRegion (dpy, paint_region);
1386
1388
}
1387
1389
 
 
1390
#if TIMEOUT_REPAINT
 
1391
static void
 
1392
remove_timeouts (ScreenInfo *screen_info)
 
1393
{
 
1394
    if (screen_info->compositor_timeout_id != 0)
 
1395
    {
 
1396
        g_source_remove (screen_info->compositor_timeout_id);
 
1397
        screen_info->compositor_timeout_id = 0;
 
1398
    }
 
1399
}
 
1400
#endif /* TIMEOUT_REPAINT */
 
1401
 
1388
1402
static void
1389
1403
repair_screen (ScreenInfo *screen_info)
1390
1404
{
1398
1412
        return;
1399
1413
    }
1400
1414
 
 
1415
#if TIMEOUT_REPAINT
 
1416
    remove_timeouts (screen_info);
 
1417
#endif /* TIMEOUT_REPAINT */
 
1418
 
1401
1419
    display_info = screen_info->display_info;
1402
1420
    if (screen_info->allDamage != None)
1403
1421
    {
1407
1425
    }
1408
1426
}
1409
1427
 
1410
 
#ifdef USE_IDLE_REPAINT
 
1428
#if TIMEOUT_REPAINT
 
1429
static gboolean
 
1430
compositor_timeout_cb (gpointer data)
 
1431
{
 
1432
    ScreenInfo *screen_info;
 
1433
 
 
1434
    screen_info = (ScreenInfo *) data;
 
1435
    screen_info->compositor_timeout_id = 0;
 
1436
    repair_screen (screen_info);
 
1437
 
 
1438
    return FALSE;
 
1439
}
 
1440
#endif /* TIMEOUT_REPAINT */
 
1441
 
1411
1442
static void
1412
 
remove_timeouts (DisplayInfo *display_info)
 
1443
add_repair (ScreenInfo *screen_info)
1413
1444
{
1414
 
    if (display_info->compositor_idle_id != 0)
1415
 
    {
1416
 
        g_source_remove (display_info->compositor_idle_id);
1417
 
        display_info->compositor_idle_id = 0;
1418
 
    }
1419
 
 
1420
 
    if (display_info->compositor_timeout_id != 0)
1421
 
    {
1422
 
        g_source_remove (display_info->compositor_timeout_id);
1423
 
        display_info->compositor_timeout_id = 0;
1424
 
    }
 
1445
#if TIMEOUT_REPAINT
 
1446
    if (screen_info->compositor_timeout_id != 0)
 
1447
    {
 
1448
        return;
 
1449
    }
 
1450
    screen_info->compositor_timeout_id =
 
1451
        g_timeout_add (TIMEOUT_REPAINT,
 
1452
                       compositor_timeout_cb, screen_info);
 
1453
#endif /* TIMEOUT_REPAINT */
1425
1454
}
1426
 
#endif /* USE_IDLE_REPAINT */
1427
1455
 
 
1456
#if TIMEOUT_REPAINT == 0
1428
1457
static void
1429
1458
repair_display (DisplayInfo *display_info)
1430
1459
{
1433
1462
    g_return_if_fail (display_info);
1434
1463
    TRACE ("entering repair_display");
1435
1464
 
1436
 
#ifdef USE_IDLE_REPAINT
1437
 
    remove_timeouts (display_info);
1438
 
#endif /* USE_IDLE_REPAINT */
1439
1465
    for (screens = display_info->screens; screens; screens = g_slist_next (screens))
1440
1466
    {
1441
 
        repair_screen ((ScreenInfo *) screens->data);
1442
 
    }
1443
 
}
1444
 
 
1445
 
#ifdef USE_IDLE_REPAINT
1446
 
static gboolean
1447
 
compositor_idle_cb (gpointer data)
1448
 
{
1449
 
    DisplayInfo *display_info = (DisplayInfo *) data;
1450
 
 
1451
 
    display_info->compositor_idle_id = 0;
1452
 
    repair_display (display_info);
1453
 
 
1454
 
    return FALSE;
1455
 
}
1456
 
 
1457
 
static gboolean
1458
 
compositor_timeout_cb (gpointer data)
1459
 
{
1460
 
    DisplayInfo *display_info;
1461
 
 
1462
 
    display_info = (DisplayInfo *) data;
1463
 
    display_info->compositor_timeout_id = 0;
1464
 
    repair_display (display_info);
1465
 
 
1466
 
    return FALSE;
1467
 
}
1468
 
#endif /* USE_IDLE_REPAINT */
1469
 
 
1470
 
static void
1471
 
add_repair (DisplayInfo *display_info)
1472
 
{
1473
 
#ifdef USE_IDLE_REPAINT
1474
 
    if (display_info->compositor_idle_id != 0)
1475
 
    {
1476
 
        return;
1477
 
    }
1478
 
    display_info->compositor_idle_id =
1479
 
        g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1480
 
                         compositor_idle_cb, display_info, NULL);
1481
 
    if (display_info->compositor_timeout_id != 0)
1482
 
    {
1483
 
        return;
1484
 
    }
1485
 
 
1486
 
    display_info->compositor_timeout_id =
1487
 
        g_timeout_add (50 /* ms */,
1488
 
                       compositor_timeout_cb, display_info);
1489
 
#endif /* USE_IDLE_REPAINT */
1490
 
}
 
1467
        add_repair ((ScreenInfo *) screens->data);
 
1468
    }
 
1469
}
 
1470
#endif
1491
1471
 
1492
1472
static void
1493
1473
add_damage (ScreenInfo *screen_info, XserverRegion damage)
1516
1496
    }
1517
1497
 
1518
1498
    /* The per-screen allDamage region is freed by repair_screen () */
1519
 
    add_repair (screen_info->display_info);
 
1499
    add_repair (screen_info);
1520
1500
}
1521
1501
 
1522
1502
static void
1747
1727
            XFixesDestroyRegion (display_info->dpy, cw->extents);
1748
1728
        }
1749
1729
        cw->extents = win_extents (cw);
1750
 
        add_repair (display_info);
 
1730
        add_repair (screen_info);
1751
1731
    }
1752
1732
}
1753
1733
 
1846
1826
            }
1847
1827
#endif /* HAVE_OVERLAYS */
1848
1828
            damage_screen (screen_info);
1849
 
            repair_screen (screen_info);
1850
1829
       }
1851
1830
    }
1852
1831
    else if (WIN_IS_VISIBLE(cw))
1879
1858
    cw->native_opacity = FALSE;
1880
1859
    if (c)
1881
1860
    {
1882
 
        cw->opacity_locked = c->opacity_locked;
 
1861
        cw->opacity_locked = FLAG_TEST (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED);
1883
1862
        cw->opacity = c->opacity_applied;
1884
1863
        cw->native_opacity = WIN_IS_OPAQUE(cw);
1885
1864
    }
2059
2038
}
2060
2039
 
2061
2040
static void
2062
 
resize_win (CWindow *cw, gint x, gint y, gint width, gint height, gint bw, gboolean shape_notify)
 
2041
resize_win (CWindow *cw, gint x, gint y, gint width, gint height, gint bw)
2063
2042
{
2064
2043
    DisplayInfo *display_info;
2065
2044
    ScreenInfo *screen_info;
2088
2067
        cw->extents = None;
2089
2068
    }
2090
2069
 
2091
 
    if ((cw->attr.width != width) || (cw->attr.height != height) || shape_notify)
 
2070
    if ((cw->attr.width != width) || (cw->attr.height != height))
2092
2071
    {
2093
2072
#if HAVE_NAME_WINDOW_PIXMAP
2094
2073
        if (cw->name_window_pixmap)
2111
2090
    }
2112
2091
 
2113
2092
    if ((cw->attr.width != width) || (cw->attr.height != height) ||
2114
 
        (cw->attr.x != x) || (cw->attr.y != y) || shape_notify)
 
2093
        (cw->attr.x != x) || (cw->attr.y != y))
2115
2094
    {
2116
2095
        if (cw->borderSize)
2117
2096
        {
2136
2115
    {
2137
2116
        cw->extents = win_extents (cw);
2138
2117
        XFixesUnionRegion (display_info->dpy, damage, damage, cw->extents);
 
2118
 
 
2119
        fix_region (cw, damage);
 
2120
        /* damage region will be destroyed by add_damage () */
 
2121
        add_damage (screen_info, damage);
 
2122
    }
 
2123
}
 
2124
 
 
2125
static void
 
2126
reshape_win (CWindow *cw)
 
2127
{
 
2128
    DisplayInfo *display_info;
 
2129
    ScreenInfo *screen_info;
 
2130
    XserverRegion damage;
 
2131
 
 
2132
    g_return_if_fail (cw != NULL);
 
2133
    TRACE ("entering reshape_win");
 
2134
 
 
2135
    screen_info = cw->screen_info;
 
2136
    display_info = screen_info->display_info;
 
2137
 
 
2138
    damage = None;
 
2139
 
 
2140
    if (WIN_IS_VISIBLE(cw))
 
2141
    {
 
2142
        damage = XFixesCreateRegion (display_info->dpy, NULL, 0);
 
2143
        if (cw->extents)
 
2144
        {
 
2145
            XFixesCopyRegion (display_info->dpy, damage, cw->extents);
 
2146
        }
 
2147
    }
 
2148
 
 
2149
    if (cw->extents)
 
2150
    {
 
2151
        XFixesDestroyRegion (display_info->dpy, cw->extents);
 
2152
        cw->extents = None;
 
2153
    }
 
2154
 
 
2155
    if (cw->shadow)
 
2156
    {
 
2157
        XRenderFreePicture (display_info->dpy, cw->shadow);
 
2158
        cw->shadow = None;
 
2159
    }
 
2160
 
 
2161
    if (cw->borderSize)
 
2162
    {
 
2163
        XFixesDestroyRegion (display_info->dpy, cw->borderSize);
 
2164
        cw->borderSize = None;
 
2165
    }
 
2166
 
 
2167
    if (cw->clientSize)
 
2168
    {
 
2169
        XFixesDestroyRegion (display_info->dpy, cw->clientSize);
 
2170
        cw->clientSize = None;
 
2171
    }
 
2172
 
 
2173
    if (damage)
 
2174
    {
 
2175
        cw->extents = win_extents (cw);
 
2176
        XFixesUnionRegion (display_info->dpy, damage, damage, cw->extents);
 
2177
 
2139
2178
        /* A shape notify will likely change the shadows too, so clear the extents */
2140
 
        if (shape_notify)
2141
 
        {
2142
 
            XFixesDestroyRegion (display_info->dpy, cw->extents);
2143
 
            cw->extents = None;
2144
 
        }
 
2179
        XFixesDestroyRegion (display_info->dpy, cw->extents);
 
2180
        cw->extents = None;
 
2181
 
2145
2182
        fix_region (cw, damage);
2146
2183
        /* damage region will be destroyed by add_damage () */
2147
2184
        add_damage (screen_info, damage);
2176
2213
static void
2177
2214
compositorHandleDamage (DisplayInfo *display_info, XDamageNotifyEvent *ev)
2178
2215
{
 
2216
    ScreenInfo *screen_info;
2179
2217
    CWindow *cw;
2180
2218
 
2181
2219
    g_return_if_fail (display_info != NULL);
2192
2230
    cw = find_cwindow_in_display (display_info, ev->drawable);
2193
2231
    if ((cw) && WIN_IS_REDIRECTED(cw))
2194
2232
    {
 
2233
        screen_info = cw->screen_info;
2195
2234
        repair_win (cw, &ev->area);
2196
 
        display_info->damages_pending = ev->more;
2197
 
#ifdef USE_IDLE_REPAINT
2198
 
        /* If there are more damages to come, we'll schedule the repair later */
2199
 
        if (!display_info->damages_pending)
2200
 
        {
2201
 
            add_repair (display_info);
2202
 
        }
2203
 
#endif /* USE_IDLE_REPAINT */
 
2235
        screen_info->damages_pending = ev->more;
2204
2236
    }
2205
2237
}
2206
2238
 
2230
2262
                XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
2231
2263
                XRenderFreePicture (display_info->dpy, screen_info->rootTile);
2232
2264
                screen_info->rootTile = None;
2233
 
                add_repair (display_info);
 
2265
                add_repair (screen_info);
2234
2266
 
2235
2267
                return;
2236
2268
            }
2280
2312
            cw->opacity_locked = getOpacityLock (display_info, cw->id);
2281
2313
            if (cw->c)
2282
2314
            {
2283
 
                cw->c->opacity_locked = cw->opacity_locked;
 
2315
                if (cw->opacity_locked)
 
2316
                {
 
2317
                    FLAG_SET (cw->c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED);
 
2318
                }
 
2319
                else
 
2320
                {
 
2321
                    FLAG_UNSET (cw->c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED);
 
2322
                }
2284
2323
            }
2285
2324
        }
2286
2325
    }
2337
2376
    if (cw)
2338
2377
    {
2339
2378
        restack_win (cw, ev->above);
2340
 
        resize_win (cw, ev->x, ev->y, ev->width, ev->height, ev->border_width, FALSE);
 
2379
        resize_win (cw, ev->x, ev->y, ev->width, ev->height, ev->border_width);
2341
2380
    }
2342
2381
}
2343
2382
 
2371
2410
        above = None;
2372
2411
    }
2373
2412
    restack_win (cw, above);
2374
 
    add_repair (display_info);
2375
2413
}
2376
2414
 
2377
2415
static void
2481
2519
            {
2482
2520
                cw->shaped = FALSE;
2483
2521
            }
2484
 
            resize_win (cw, cw->attr.x, cw->attr.y,
2485
 
                            ev->width + ev->x, ev->height + ev->y,
2486
 
                            cw->attr.border_width, TRUE);
 
2522
            reshape_win  (cw);
2487
2523
            if ((ev->shaped) && !(cw->shaped))
2488
2524
            {
2489
2525
                cw->shaped = TRUE;
2644
2680
    cw = find_cwindow_in_display (display_info, id);
2645
2681
    if (cw)
2646
2682
    {
2647
 
        resize_win (cw, x, y, width, height, 0, FALSE);
 
2683
        resize_win (cw, x, y, width, height, 0);
2648
2684
    }
2649
2685
#endif /* HAVE_COMPOSITOR */
2650
2686
}
2705
2741
    {
2706
2742
        compositorHandleShapeNotify (display_info, (XShapeEvent *) ev);
2707
2743
    }
2708
 
#ifndef USE_IDLE_REPAINT
2709
 
    if (!display_info->damages_pending)
2710
 
    {
2711
 
        repair_display (display_info);
2712
 
    }
2713
 
#endif /* USE_IDLE_REPAINT */
 
2744
#if TIMEOUT_REPAINT == 0
 
2745
    repair_display (display_info);
 
2746
#endif /* TIMEOUT_REPAINT */
2714
2747
 
2715
2748
#endif /* HAVE_COMPOSITOR */
2716
2749
}
2780
2813
#endif /* DEBUG */
2781
2814
    }
2782
2815
 
2783
 
    display_info->compositor_idle_id = 0;
2784
 
    display_info->compositor_timeout_id = 0;
2785
 
    display_info->damages_pending = FALSE;
2786
 
 
2787
2816
    display_info->enable_compositor = ((display_info->have_render)
2788
2817
                                    && (display_info->have_composite)
2789
2818
                                    && (display_info->have_damage)
2923
2952
    screen_info->cwindows = NULL;
2924
2953
    screen_info->compositor_active = TRUE;
2925
2954
    screen_info->wins_unredirected = 0;
 
2955
    screen_info->compositor_timeout_id = 0;
 
2956
    screen_info->damages_pending = FALSE;
2926
2957
 
2927
2958
    XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
2928
2959
    compositorSetCMSelection (screen_info, screen_info->xfwm4_win);
2958
2989
    }
2959
2990
    screen_info->compositor_active = FALSE;
2960
2991
 
 
2992
#if TIMEOUT_REPAINT
 
2993
    remove_timeouts (screen_info);
 
2994
#endif /* TIMEOUT_REPAINT */
 
2995
 
2961
2996
    i = 0;
2962
2997
    for (index = screen_info->cwindows; index; index = g_list_next (index))
2963
2998
    {
3035
3070
        return;
3036
3071
    }
3037
3072
 
3038
 
    XSync (display_info->dpy, FALSE);
3039
3073
    myDisplayGrabServer (display_info);
3040
3074
    XQueryTree (display_info->dpy, screen_info->xroot, &w1, &w2, &wins, &count);
3041
3075
 
3043
3077
    {
3044
3078
        Client *c;
3045
3079
 
3046
 
        c = clientGetFromWindow (screen_info, wins[i], FRAME);
 
3080
        c = myScreenGetClientFromWindow (screen_info, wins[i], SEARCH_FRAME);
3047
3081
        compositorAddWindow (display_info, wins[i], c);
3048
3082
    }
3049
3083
    if (wins)
3051
3085
        XFree (wins);
3052
3086
    }
3053
3087
    myDisplayUngrabServer (display_info);
3054
 
    XSync (display_info->dpy, FALSE);
3055
3088
#endif /* HAVE_COMPOSITOR */
3056
3089
}
3057
3090