2018-10-03 17:14:51 -04:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// Copyright (c)
|
2012-02-26 23:00:12 -05:00
|
|
|
|
|
|
|
// Throw everything in here.
|
|
|
|
|
Feature: Issue #29: Alternative shadow blacklist implementation
- Add shadow blacklist feature, but a different implementation from
nicklan's. 5 matching modes (exact, starts-with, contains, wildcard,
PCRE) and 3 matching targets (window name, window class instance,
window general class). Not extensively tested, bugs to be expected.
It's slower for exact matching than nicklan's as it uses linear search
instead of hash table. Also, PCRE's JIT optimization may cause issues
on PaX kernels.
- Add dependency to libpcre. Could be made optional if we have a
graceful way to handle that in Makefile.
- Some matching functions are GNU extensions of glibc. So this version
may have troubles running on platforms not using glibc.
- Fix a bug that access freed memory blocks in set_fade_callcack() and
check_fade_fin(). valgrind found it out.
- Use WM_CLASS to detect client windows instead of WM_STATE. Some client
windows (like notification windows) have WM_CLASS but not WM_STATE.
- Mark the extents as damaged if shadow state changed in
determine_shadow().
- Rewrite wid_get_name(). Code clean-up.
- Two debugging options: DEBUG_WINDATA and DEBUG_WINMATCH.
- As the matching system is ready, it should be rather easy to add other
kinds of blacklists, like fading blacklist.
2012-09-21 23:42:39 -04:00
|
|
|
|
|
|
|
// === Includes ===
|
|
|
|
|
2012-02-08 05:31:39 -05:00
|
|
|
#include <math.h>
|
2013-01-11 08:31:02 -05:00
|
|
|
#include <sys/select.h>
|
|
|
|
#include <limits.h>
|
2012-02-08 05:31:39 -05:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <getopt.h>
|
Feature: Issue #29: Alternative shadow blacklist implementation
- Add shadow blacklist feature, but a different implementation from
nicklan's. 5 matching modes (exact, starts-with, contains, wildcard,
PCRE) and 3 matching targets (window name, window class instance,
window general class). Not extensively tested, bugs to be expected.
It's slower for exact matching than nicklan's as it uses linear search
instead of hash table. Also, PCRE's JIT optimization may cause issues
on PaX kernels.
- Add dependency to libpcre. Could be made optional if we have a
graceful way to handle that in Makefile.
- Some matching functions are GNU extensions of glibc. So this version
may have troubles running on platforms not using glibc.
- Fix a bug that access freed memory blocks in set_fade_callcack() and
check_fade_fin(). valgrind found it out.
- Use WM_CLASS to detect client windows instead of WM_STATE. Some client
windows (like notification windows) have WM_CLASS but not WM_STATE.
- Mark the extents as damaged if shadow state changed in
determine_shadow().
- Rewrite wid_get_name(). Code clean-up.
- Two debugging options: DEBUG_WINDATA and DEBUG_WINMATCH.
- As the matching system is ready, it should be rather easy to add other
kinds of blacklists, like fading blacklist.
2012-09-21 23:42:39 -04:00
|
|
|
#include <locale.h>
|
2012-11-18 20:46:07 -05:00
|
|
|
#include <signal.h>
|
2012-09-24 22:19:20 -04:00
|
|
|
|
Feature: #7: VSync
- Add VSync feature. 3 possible VSync methods available: "sw" (software,
not too reliable, but at least you have something to fallback to),
"drm" (using DRM_IOCTL_WAIT_VBLANK, should work only on DRI drivers),
"opengl" (using SGI_swap_control extension OpenGL, might work on more
drivers than the DRM method). "sw" and "opengl" are briefly tested,
"drm" received utterly no test (because I use the nVidia binary blob).
They are enabled with "--vsync sw" / "--vsync drm" / "--vsync opengl".
- Add --refresh-rate to let user specify a refresh rate for software
VSync, in case the automatic refresh rate detection does not work
well.
- Seemingly the automatic refresh rate detection using X RandR in
software VSync detects refresh rate incorrectly. Need further investigation.
- Fix a few bugs in fading timing.
- Add a workaround for client window detection on Fluxbox, as Fluxbox
(incorrectly?) sets the override-redirect flag upon all frame
windows.
- Software VSync adds dependency on librt (a part of glibc) for
nanosecond-level timing functions, and libXrandr for automatic refresh
rate detection; DRM VSync adds dependency on libdrm to use its drm.h,
but does not link to libdrm; OpenGL VSync adds dependency on libGL.
- Print timing information on DEBUG_REPAINT.
2012-10-07 22:20:01 -04:00
|
|
|
#ifdef CONFIG_VSYNC_DRM
|
|
|
|
#include <fcntl.h>
|
|
|
|
// We references some definitions in drm.h, which could also be found in
|
|
|
|
// /usr/src/linux/include/drm/drm.h, but that path is probably even less
|
|
|
|
// reliable than libdrm
|
2013-02-28 23:41:16 -05:00
|
|
|
#include <drm.h>
|
Feature: #7: VSync
- Add VSync feature. 3 possible VSync methods available: "sw" (software,
not too reliable, but at least you have something to fallback to),
"drm" (using DRM_IOCTL_WAIT_VBLANK, should work only on DRI drivers),
"opengl" (using SGI_swap_control extension OpenGL, might work on more
drivers than the DRM method). "sw" and "opengl" are briefly tested,
"drm" received utterly no test (because I use the nVidia binary blob).
They are enabled with "--vsync sw" / "--vsync drm" / "--vsync opengl".
- Add --refresh-rate to let user specify a refresh rate for software
VSync, in case the automatic refresh rate detection does not work
well.
- Seemingly the automatic refresh rate detection using X RandR in
software VSync detects refresh rate incorrectly. Need further investigation.
- Fix a few bugs in fading timing.
- Add a workaround for client window detection on Fluxbox, as Fluxbox
(incorrectly?) sets the override-redirect flag upon all frame
windows.
- Software VSync adds dependency on librt (a part of glibc) for
nanosecond-level timing functions, and libXrandr for automatic refresh
rate detection; DRM VSync adds dependency on libdrm to use its drm.h,
but does not link to libdrm; OpenGL VSync adds dependency on libGL.
- Print timing information on DEBUG_REPAINT.
2012-10-07 22:20:01 -04:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#endif
|
|
|
|
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
#include <pixman.h>
|
2018-09-29 17:47:12 -04:00
|
|
|
#ifdef CONFIG_OPENGL
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
#include "opengl.h" // XXX clean up
|
2018-09-29 17:47:12 -04:00
|
|
|
#endif
|
2018-08-22 08:26:42 -04:00
|
|
|
#include "common.h"
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
#include "x.h"
|
2018-08-22 08:26:42 -04:00
|
|
|
#include "c2.h"
|
|
|
|
|
2012-11-18 20:46:07 -05:00
|
|
|
// == Functions ==
|
2018-09-06 14:17:26 -04:00
|
|
|
// TODO move static inline functions that are only used in compton.c, into
|
|
|
|
// compton.c
|
2012-02-26 23:00:12 -05:00
|
|
|
|
2012-09-11 09:57:50 -04:00
|
|
|
// inline functions must be made static to compile correctly under clang:
|
|
|
|
// http://clang.llvm.org/compatibility.html#inline
|
|
|
|
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
void add_damage(session_t *ps, const region_t *damage);
|
2018-09-08 21:29:45 -04:00
|
|
|
|
2018-09-06 14:17:26 -04:00
|
|
|
long determine_evmask(session_t *ps, Window wid, win_evmode_t mode);
|
2012-09-16 11:12:02 -04:00
|
|
|
|
2018-10-03 08:59:27 -04:00
|
|
|
xcb_window_t
|
|
|
|
find_client_win(session_t *ps, xcb_window_t w);
|
2012-09-17 04:04:04 -04:00
|
|
|
|
2018-09-06 14:17:26 -04:00
|
|
|
win *find_toplevel2(session_t *ps, Window wid);
|
2012-11-18 20:46:07 -05:00
|
|
|
|
2018-09-06 14:17:26 -04:00
|
|
|
void map_win(session_t *ps, Window id);
|
|
|
|
|
|
|
|
void
|
2018-09-29 17:47:12 -04:00
|
|
|
render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
2018-09-06 14:17:26 -04:00
|
|
|
double opacity, bool argb, bool neg,
|
2018-09-27 12:14:44 -04:00
|
|
|
xcb_render_picture_t pict, glx_texture_t *ptex,
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
const region_t *reg_paint, const glx_prog_main_t *pprogram);
|
2012-09-17 04:04:04 -04:00
|
|
|
|
2012-12-14 07:32:46 -05:00
|
|
|
/**
|
|
|
|
* Reset filter on a <code>Picture</code>.
|
|
|
|
*/
|
|
|
|
static inline void
|
2018-09-27 12:14:44 -04:00
|
|
|
xrfilter_reset(session_t *ps, xcb_render_picture_t p) {
|
|
|
|
#define FILTER "Nearest"
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_render_set_picture_filter(ps->c, p, strlen(FILTER), FILTER, 0, NULL);
|
2018-09-27 12:14:44 -04:00
|
|
|
#undef FILTER
|
2012-12-14 07:32:46 -05:00
|
|
|
}
|
|
|
|
|
Feature: #7: VSync
- Add VSync feature. 3 possible VSync methods available: "sw" (software,
not too reliable, but at least you have something to fallback to),
"drm" (using DRM_IOCTL_WAIT_VBLANK, should work only on DRI drivers),
"opengl" (using SGI_swap_control extension OpenGL, might work on more
drivers than the DRM method). "sw" and "opengl" are briefly tested,
"drm" received utterly no test (because I use the nVidia binary blob).
They are enabled with "--vsync sw" / "--vsync drm" / "--vsync opengl".
- Add --refresh-rate to let user specify a refresh rate for software
VSync, in case the automatic refresh rate detection does not work
well.
- Seemingly the automatic refresh rate detection using X RandR in
software VSync detects refresh rate incorrectly. Need further investigation.
- Fix a few bugs in fading timing.
- Add a workaround for client window detection on Fluxbox, as Fluxbox
(incorrectly?) sets the override-redirect flag upon all frame
windows.
- Software VSync adds dependency on librt (a part of glibc) for
nanosecond-level timing functions, and libXrandr for automatic refresh
rate detection; DRM VSync adds dependency on libdrm to use its drm.h,
but does not link to libdrm; OpenGL VSync adds dependency on libGL.
- Print timing information on DEBUG_REPAINT.
2012-10-07 22:20:01 -04:00
|
|
|
/**
|
|
|
|
* Subtract two unsigned long values.
|
|
|
|
*
|
|
|
|
* Truncate to 0 if the result is negative.
|
|
|
|
*/
|
2012-11-18 20:46:07 -05:00
|
|
|
static inline unsigned long __attribute__((const))
|
Feature: #7: VSync
- Add VSync feature. 3 possible VSync methods available: "sw" (software,
not too reliable, but at least you have something to fallback to),
"drm" (using DRM_IOCTL_WAIT_VBLANK, should work only on DRI drivers),
"opengl" (using SGI_swap_control extension OpenGL, might work on more
drivers than the DRM method). "sw" and "opengl" are briefly tested,
"drm" received utterly no test (because I use the nVidia binary blob).
They are enabled with "--vsync sw" / "--vsync drm" / "--vsync opengl".
- Add --refresh-rate to let user specify a refresh rate for software
VSync, in case the automatic refresh rate detection does not work
well.
- Seemingly the automatic refresh rate detection using X RandR in
software VSync detects refresh rate incorrectly. Need further investigation.
- Fix a few bugs in fading timing.
- Add a workaround for client window detection on Fluxbox, as Fluxbox
(incorrectly?) sets the override-redirect flag upon all frame
windows.
- Software VSync adds dependency on librt (a part of glibc) for
nanosecond-level timing functions, and libXrandr for automatic refresh
rate detection; DRM VSync adds dependency on libdrm to use its drm.h,
but does not link to libdrm; OpenGL VSync adds dependency on libGL.
- Print timing information on DEBUG_REPAINT.
2012-10-07 22:20:01 -04:00
|
|
|
sub_unslong(unsigned long a, unsigned long b) {
|
|
|
|
return (a > b) ? a - b : 0;
|
|
|
|
}
|
|
|
|
|
2012-12-09 21:31:24 -05:00
|
|
|
/**
|
|
|
|
* Set a <code>switch_t</code> array of all unset wintypes to true.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
wintype_arr_enable_unset(switch_t arr[]) {
|
|
|
|
wintype_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_WINTYPES; ++i)
|
|
|
|
if (UNSET == arr[i])
|
|
|
|
arr[i] = ON;
|
|
|
|
}
|
|
|
|
|
2012-09-11 10:22:58 -04:00
|
|
|
/**
|
|
|
|
* Check if a window ID exists in an array of window IDs.
|
|
|
|
*
|
|
|
|
* @param arr the array of window IDs
|
|
|
|
* @param count amount of elements in the array
|
|
|
|
* @param wid window ID to search for
|
|
|
|
*/
|
2012-11-18 20:46:07 -05:00
|
|
|
static inline bool
|
2012-09-13 01:58:05 -04:00
|
|
|
array_wid_exists(const Window *arr, int count, Window wid) {
|
2012-09-11 10:22:58 -04:00
|
|
|
while (count--) {
|
2012-09-13 01:58:05 -04:00
|
|
|
if (arr[count] == wid) {
|
2012-11-18 20:46:07 -05:00
|
|
|
return true;
|
2012-09-13 01:58:05 -04:00
|
|
|
}
|
2012-09-11 10:22:58 -04:00
|
|
|
}
|
2012-09-13 01:39:43 -04:00
|
|
|
|
2012-11-18 20:46:07 -05:00
|
|
|
return false;
|
2012-09-11 10:22:58 -04:00
|
|
|
}
|
2012-09-16 11:12:02 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroy a <code>Picture</code>.
|
|
|
|
*/
|
|
|
|
inline static void
|
2018-09-27 12:14:44 -04:00
|
|
|
free_picture(session_t *ps, xcb_render_picture_t *p) {
|
2012-09-16 11:12:02 -04:00
|
|
|
if (*p) {
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_render_free_picture(ps->c, *p);
|
2012-09-16 11:12:02 -04:00
|
|
|
*p = None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroy a <code>Damage</code>.
|
|
|
|
*/
|
|
|
|
inline static void
|
2018-09-27 11:29:51 -04:00
|
|
|
free_damage(session_t *ps, xcb_damage_damage_t *p) {
|
2012-09-16 11:12:02 -04:00
|
|
|
if (*p) {
|
2012-09-17 04:04:04 -04:00
|
|
|
// BadDamage will be thrown if the window is destroyed
|
2018-09-29 05:18:09 -04:00
|
|
|
set_ignore_cookie(ps,
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_damage_destroy(ps->c, *p));
|
2012-09-16 11:12:02 -04:00
|
|
|
*p = None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-18 20:46:07 -05:00
|
|
|
/**
|
Feature #16: Advanced window matching
- Add advanced window matching system, capable of matching against
arbitrary window properties as well as a series of internal
properties, with 4 additional operators (>, <, >=, <=) useful for
integer targets, and support of logical operators. The old matching
system is removed, but compatibility with the format is retained.
- As the new matching system is pretty complicated, and I have no past
experience in writing a parser, it's pretty possible that bugs are
present. It also has inferior performance, but I hope it doesn't
matter on modern CPUs.
- It's possible to disable matching system at compile time with NO_C2=1
now.
- Add ps->o.config_file to track which config file we have actually
read. Queryable via D-Bus.
- Parse -d in first pass in get_cfg() as c2 needs to query X to get
atoms during condition parsing.
- Fix a bug in wid_get_prop_adv() that 0 == rformat is not handled
correctly.
- Fix incompatibility with FreeBSD sed in dbus-examples/cdbus-driver.sh
.
- Add recipe to generate .clang_complete in Makefile, used by Vim
clang_complete plugin.
- Add DEBUG_C2 for debugging condition string parsing. DEBUG_WINMATCH is
still used for match debugging.
- Rename win_on_wdata_change() to win_on_factor_change().
- Extra malloc() failure checks. Add const to matching cache members in
session_t. Code clean-up. Documentation update.
2013-01-28 08:39:38 -05:00
|
|
|
* Destroy a condition list.
|
2012-11-18 20:46:07 -05:00
|
|
|
*/
|
Feature #16: Advanced window matching
- Add advanced window matching system, capable of matching against
arbitrary window properties as well as a series of internal
properties, with 4 additional operators (>, <, >=, <=) useful for
integer targets, and support of logical operators. The old matching
system is removed, but compatibility with the format is retained.
- As the new matching system is pretty complicated, and I have no past
experience in writing a parser, it's pretty possible that bugs are
present. It also has inferior performance, but I hope it doesn't
matter on modern CPUs.
- It's possible to disable matching system at compile time with NO_C2=1
now.
- Add ps->o.config_file to track which config file we have actually
read. Queryable via D-Bus.
- Parse -d in first pass in get_cfg() as c2 needs to query X to get
atoms during condition parsing.
- Fix a bug in wid_get_prop_adv() that 0 == rformat is not handled
correctly.
- Fix incompatibility with FreeBSD sed in dbus-examples/cdbus-driver.sh
.
- Add recipe to generate .clang_complete in Makefile, used by Vim
clang_complete plugin.
- Add DEBUG_C2 for debugging condition string parsing. DEBUG_WINMATCH is
still used for match debugging.
- Rename win_on_wdata_change() to win_on_factor_change().
- Extra malloc() failure checks. Add const to matching cache members in
session_t. Code clean-up. Documentation update.
2013-01-28 08:39:38 -05:00
|
|
|
static inline void
|
|
|
|
free_wincondlst(c2_lptr_t **pcondlst) {
|
|
|
|
while ((*pcondlst = c2_free_lptr(*pcondlst)))
|
|
|
|
continue;
|
2013-05-09 09:47:09 -04:00
|
|
|
}
|
2012-11-18 20:46:07 -05:00
|
|
|
|
2013-08-22 09:15:04 -04:00
|
|
|
/**
|
|
|
|
* Free Xinerama screen info.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
free_xinerama_info(session_t *ps) {
|
|
|
|
#ifdef CONFIG_XINERAMA
|
|
|
|
if (ps->xinerama_scr_regs) {
|
|
|
|
for (int i = 0; i < ps->xinerama_nscrs; ++i)
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
pixman_region32_fini(&ps->xinerama_scr_regs[i]);
|
2013-08-22 09:15:04 -04:00
|
|
|
free(ps->xinerama_scr_regs);
|
|
|
|
}
|
|
|
|
cxfree(ps->xinerama_scrs);
|
|
|
|
ps->xinerama_scrs = NULL;
|
|
|
|
ps->xinerama_nscrs = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-09-29 17:47:12 -04:00
|
|
|
#ifdef CONFIG_OPENGL
|
2013-03-15 11:16:23 -04:00
|
|
|
/**
|
2013-03-16 10:54:43 -04:00
|
|
|
* Bind texture in paint_t if we are using GLX backend.
|
2013-03-15 11:16:23 -04:00
|
|
|
*/
|
|
|
|
static inline bool
|
2018-09-29 17:47:12 -04:00
|
|
|
paint_bind_tex(session_t *ps, paint_t *ppaint,
|
|
|
|
unsigned wid, unsigned hei, unsigned depth, bool force)
|
|
|
|
{
|
2013-12-10 09:06:02 -05:00
|
|
|
if (!ppaint->pixmap)
|
|
|
|
return false;
|
2013-03-17 23:48:28 -04:00
|
|
|
|
2013-12-10 09:06:02 -05:00
|
|
|
if (force || !glx_tex_binded(ppaint->ptex, ppaint->pixmap))
|
|
|
|
return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap, wid, hei, depth);
|
2013-03-15 11:16:23 -04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2018-09-29 17:47:12 -04:00
|
|
|
#else
|
2013-12-10 09:06:02 -05:00
|
|
|
static inline bool
|
|
|
|
paint_bind_tex(session_t *ps, paint_t *ppaint,
|
2018-09-29 17:47:12 -04:00
|
|
|
unsigned wid, unsigned hei, unsigned depth, bool force)
|
|
|
|
{
|
2013-12-10 09:06:02 -05:00
|
|
|
return true;
|
|
|
|
}
|
2018-09-29 17:47:12 -04:00
|
|
|
static inline void
|
|
|
|
free_paint_glx(session_t *ps, paint_t *p) {}
|
|
|
|
static inline void
|
|
|
|
free_win_res_glx(session_t *ps, win *w) {}
|
|
|
|
static inline void
|
|
|
|
free_texture(session_t *ps, glx_texture_t **t) {
|
|
|
|
assert(!*t);
|
|
|
|
}
|
|
|
|
#endif
|
2013-12-10 09:06:02 -05:00
|
|
|
|
2013-03-15 11:16:23 -04:00
|
|
|
/**
|
|
|
|
* Free paint_t.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
free_paint(session_t *ps, paint_t *ppaint) {
|
2014-07-28 00:50:15 -04:00
|
|
|
free_paint_glx(ps, ppaint);
|
2013-03-15 11:16:23 -04:00
|
|
|
free_picture(ps, &ppaint->pict);
|
2018-09-30 15:53:52 -04:00
|
|
|
if (ppaint->pixmap)
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_free_pixmap(ps->c, ppaint->pixmap);
|
2018-09-30 15:53:52 -04:00
|
|
|
ppaint->pixmap = XCB_NONE;
|
2013-03-15 11:16:23 -04:00
|
|
|
}
|
|
|
|
|
2014-03-17 11:25:34 -04:00
|
|
|
/**
|
|
|
|
* Free w->paint.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
free_wpaint(session_t *ps, win *w) {
|
|
|
|
free_paint(ps, &w->paint);
|
|
|
|
free_fence(ps, &w->fence);
|
|
|
|
}
|
|
|
|
|
2012-11-18 20:46:07 -05:00
|
|
|
/**
|
|
|
|
* Destroy all resources in a <code>struct _win</code>.
|
|
|
|
*/
|
2013-03-15 11:16:23 -04:00
|
|
|
static inline void
|
2012-11-18 20:46:07 -05:00
|
|
|
free_win_res(session_t *ps, win *w) {
|
2014-07-28 00:50:15 -04:00
|
|
|
free_win_res_glx(ps, w);
|
2013-03-15 11:16:23 -04:00
|
|
|
free_paint(ps, &w->paint);
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
pixman_region32_fini(&w->bounding_shape);
|
2013-03-15 11:16:23 -04:00
|
|
|
free_paint(ps, &w->shadow_paint);
|
2012-11-18 20:46:07 -05:00
|
|
|
free_damage(ps, &w->damage);
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
rc_region_unref(&w->reg_ignore);
|
2012-11-18 20:46:07 -05:00
|
|
|
free(w->name);
|
|
|
|
free(w->class_instance);
|
|
|
|
free(w->class_general);
|
2012-12-07 09:38:10 -05:00
|
|
|
free(w->role);
|
2012-11-18 20:46:07 -05:00
|
|
|
}
|
|
|
|
|
2013-03-15 11:16:23 -04:00
|
|
|
/**
|
|
|
|
* Free root tile related things.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
free_root_tile(session_t *ps) {
|
|
|
|
free_picture(ps, &ps->root_tile_paint.pict);
|
|
|
|
free_texture(ps, &ps->root_tile_paint.ptex);
|
2018-09-30 15:53:52 -04:00
|
|
|
if (ps->root_tile_fill) {
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_free_pixmap(ps->c, ps->root_tile_paint.pixmap);
|
2018-09-30 15:53:52 -04:00
|
|
|
ps->root_tile_paint.pixmap = XCB_NONE;
|
|
|
|
}
|
2013-03-15 11:16:23 -04:00
|
|
|
ps->root_tile_paint.pixmap = None;
|
|
|
|
ps->root_tile_fill = false;
|
|
|
|
}
|
|
|
|
|
2012-10-29 10:00:11 -04:00
|
|
|
/**
|
|
|
|
* Get current system clock in milliseconds.
|
|
|
|
*/
|
Improvement #74: Use libevent for main loop
- Use libevent for main loop. I will explain the reasons in #56 later.
The preferred libevent version is 2.x, yet 1.4.x should work as well.
- As a result, compton now should build fine on *BSD. Thanks to
DachiChang for the FreeBSD build issue report.
- Another consequence is we now use microsecond-level timing all the
way. Nanosecond-level code will be dropped soon. Start using long
instead of unsigned long to represent time in milliseconds, as both
can't hold the full epoch time in ms, anyway, and a signed type
requires less care in subtraction. Wrap the epoch time in ms to 15
days.
- Fix broken NO_VSYNC_DRM and NO_VSYNC_OPENGL compile-time options.
- Use git revision number for versioning in Makefile, and other small
improvements.
- Reorganize struct _win. Drop unused w->damaged_sequence. w->damaged is
turned to bool.
- Add type and format to winprop_t, as preparation for the new condition
format.
- Add w->shadow_force and w->focus_force, to prepare for D-Bus support.
- Rename wid_get_prop() to wid_get_prop_adv() with more options. Add
wrapper function wid_get_prop().
- Add some extra helper functions, for D-Bus support later.
- Make some functions return a bool value to indicate if it's
successful.
- Modify add_win(), use a static const structure to initialize the new
struct _win.
- Add some helper macros, like printf_err(f)(q). Make some errors fatal.
- Rename some types, constants, and functions. Code clean-up.
- Check for time disorder in paint_preprocess() when calculating fading
steps.
- Rename evpoll() to swopti_handle_timeout(), and partially rewrite it.
- Make -h / --help legal.
- Known issue: compton segfaults on FreeBSD with nvidia-drivers, unless
NO_VSYNC_OPENGL is used. Will look into it later. Thamls to DachiChang
for reporting.
2013-01-07 19:50:58 -05:00
|
|
|
static inline time_ms_t
|
2012-10-29 10:00:11 -04:00
|
|
|
get_time_ms(void) {
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
|
Improvement #74: Use libevent for main loop
- Use libevent for main loop. I will explain the reasons in #56 later.
The preferred libevent version is 2.x, yet 1.4.x should work as well.
- As a result, compton now should build fine on *BSD. Thanks to
DachiChang for the FreeBSD build issue report.
- Another consequence is we now use microsecond-level timing all the
way. Nanosecond-level code will be dropped soon. Start using long
instead of unsigned long to represent time in milliseconds, as both
can't hold the full epoch time in ms, anyway, and a signed type
requires less care in subtraction. Wrap the epoch time in ms to 15
days.
- Fix broken NO_VSYNC_DRM and NO_VSYNC_OPENGL compile-time options.
- Use git revision number for versioning in Makefile, and other small
improvements.
- Reorganize struct _win. Drop unused w->damaged_sequence. w->damaged is
turned to bool.
- Add type and format to winprop_t, as preparation for the new condition
format.
- Add w->shadow_force and w->focus_force, to prepare for D-Bus support.
- Rename wid_get_prop() to wid_get_prop_adv() with more options. Add
wrapper function wid_get_prop().
- Add some extra helper functions, for D-Bus support later.
- Make some functions return a bool value to indicate if it's
successful.
- Modify add_win(), use a static const structure to initialize the new
struct _win.
- Add some helper macros, like printf_err(f)(q). Make some errors fatal.
- Rename some types, constants, and functions. Code clean-up.
- Check for time disorder in paint_preprocess() when calculating fading
steps.
- Rename evpoll() to swopti_handle_timeout(), and partially rewrite it.
- Make -h / --help legal.
- Known issue: compton segfaults on FreeBSD with nvidia-drivers, unless
NO_VSYNC_OPENGL is used. Will look into it later. Thamls to DachiChang
for reporting.
2013-01-07 19:50:58 -05:00
|
|
|
return tv.tv_sec % SEC_WRAP * 1000 + tv.tv_usec / 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert time from milliseconds to struct timeval.
|
|
|
|
*/
|
|
|
|
static inline struct timeval
|
|
|
|
ms_to_tv(int timeout) {
|
|
|
|
return (struct timeval) {
|
|
|
|
.tv_sec = timeout / MS_PER_SEC,
|
|
|
|
.tv_usec = timeout % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC)
|
|
|
|
};
|
2012-10-29 10:00:11 -04:00
|
|
|
}
|
2012-02-08 05:31:39 -05:00
|
|
|
|
2013-01-30 00:41:08 -05:00
|
|
|
/**
|
|
|
|
* Create a XTextProperty of a single string.
|
|
|
|
*/
|
|
|
|
static inline XTextProperty *
|
|
|
|
make_text_prop(session_t *ps, char *str) {
|
2014-08-06 14:42:57 -04:00
|
|
|
XTextProperty *pprop = ccalloc(1, XTextProperty);
|
2013-01-30 00:41:08 -05:00
|
|
|
|
|
|
|
if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) {
|
2013-04-05 09:05:19 -04:00
|
|
|
cxfree(pprop->value);
|
2013-01-30 00:41:08 -05:00
|
|
|
free(pprop);
|
|
|
|
pprop = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pprop;
|
|
|
|
}
|
|
|
|
|
2013-11-09 21:13:18 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a single-string text property on a window.
|
|
|
|
*/
|
|
|
|
static inline bool
|
|
|
|
wid_set_text_prop(session_t *ps, Window wid, Atom prop_atom, char *str) {
|
|
|
|
XTextProperty *pprop = make_text_prop(ps, str);
|
|
|
|
if (!pprop) {
|
|
|
|
printf_errf("(\"%s\"): Failed to make text property.", str);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
XSetTextProperty(ps->dpy, wid, pprop, prop_atom);
|
|
|
|
cxfree(pprop->value);
|
|
|
|
cxfree(pprop);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-11-18 20:46:07 -05:00
|
|
|
/**
|
|
|
|
* Stop listening for events on a particular window.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
win_ev_stop(session_t *ps, win *w) {
|
|
|
|
// Will get BadWindow if the window is destroyed
|
2018-10-03 08:34:24 -04:00
|
|
|
set_ignore_cookie(ps,
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 }));
|
2012-11-18 20:46:07 -05:00
|
|
|
|
|
|
|
if (w->client_win) {
|
2018-10-03 08:34:24 -04:00
|
|
|
set_ignore_cookie(ps,
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 }));
|
2012-11-18 20:46:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ps->shape_exists) {
|
2018-09-29 05:29:51 -04:00
|
|
|
set_ignore_cookie(ps,
|
2018-10-03 09:27:48 -04:00
|
|
|
xcb_shape_select_input(ps->c, w->id, 0));
|
2012-11-04 05:11:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-09 08:44:02 -05:00
|
|
|
/**
|
|
|
|
* Check whether a window has WM frames.
|
|
|
|
*/
|
2015-09-06 10:32:52 -04:00
|
|
|
static inline bool __attribute__((pure))
|
2012-10-30 20:54:09 -04:00
|
|
|
win_has_frame(const win *w) {
|
2018-09-23 14:10:46 -04:00
|
|
|
return w->g.border_width
|
2015-09-06 08:53:07 -04:00
|
|
|
|| w->frame_extents.top || w->frame_extents.left
|
|
|
|
|| w->frame_extents.right || w->frame_extents.bottom;
|
2013-01-09 07:25:01 -05:00
|
|
|
}
|
|
|
|
|
2015-09-06 09:40:51 -04:00
|
|
|
/**
|
|
|
|
* Calculate the extents of the frame of the given window based on EWMH
|
|
|
|
* _NET_FRAME_EXTENTS and the X window border width.
|
|
|
|
*/
|
|
|
|
static inline margin_t __attribute__((pure))
|
|
|
|
win_calc_frame_extents(session_t *ps, const win *w) {
|
|
|
|
margin_t result = w->frame_extents;
|
2018-09-23 14:10:46 -04:00
|
|
|
result.top = max_i(result.top, w->g.border_width);
|
|
|
|
result.left = max_i(result.left, w->g.border_width);
|
|
|
|
result.bottom = max_i(result.bottom, w->g.border_width);
|
|
|
|
result.right = max_i(result.right, w->g.border_width);
|
2015-09-06 09:40:51 -04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-01-09 07:25:01 -05:00
|
|
|
/**
|
|
|
|
* Dump an drawable's info.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
dump_drawable(session_t *ps, Drawable drawable) {
|
|
|
|
Window rroot = None;
|
|
|
|
int x = 0, y = 0;
|
|
|
|
unsigned width = 0, height = 0, border = 0, depth = 0;
|
|
|
|
if (XGetGeometry(ps->dpy, drawable, &rroot, &x, &y, &width, &height,
|
|
|
|
&border, &depth)) {
|
|
|
|
printf_dbgf("(%#010lx): x = %u, y = %u, wid = %u, hei = %d, b = %u, d = %u\n", drawable, x, y, width, height, border, depth);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf_dbgf("(%#010lx): Failed\n", drawable);
|
|
|
|
}
|
2012-10-30 20:54:09 -04:00
|
|
|
}
|
|
|
|
|
2012-09-30 22:34:40 -04:00
|
|
|
|
2013-05-01 10:08:43 -04:00
|
|
|
/**
|
|
|
|
* Validate a pixmap.
|
|
|
|
*
|
|
|
|
* Detect whether the pixmap is valid with XGetGeometry. Well, maybe there
|
|
|
|
* are better ways.
|
|
|
|
*/
|
|
|
|
static inline bool
|
2018-09-30 15:53:52 -04:00
|
|
|
validate_pixmap(session_t *ps, xcb_pixmap_t pxmap) {
|
2013-05-01 10:08:43 -04:00
|
|
|
if (!pxmap) return false;
|
|
|
|
|
|
|
|
Window rroot = None;
|
|
|
|
int rx = 0, ry = 0;
|
|
|
|
unsigned rwid = 0, rhei = 0, rborder = 0, rdepth = 0;
|
|
|
|
return XGetGeometry(ps->dpy, pxmap, &rroot, &rx, &ry,
|
|
|
|
&rwid, &rhei, &rborder, &rdepth) && rwid && rhei;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Validate pixmap of a window, and destroy pixmap and picture if invalid.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
win_validate_pixmap(session_t *ps, win *w) {
|
|
|
|
// Destroy pixmap and picture, if invalid
|
|
|
|
if (!validate_pixmap(ps, w->paint.pixmap))
|
|
|
|
free_paint(ps, &w->paint);
|
|
|
|
}
|
2013-01-28 20:57:04 -05:00
|
|
|
|
2013-09-18 09:50:57 -04:00
|
|
|
/**
|
|
|
|
* Find matched window.
|
|
|
|
*/
|
|
|
|
static inline win *
|
|
|
|
find_win_all(session_t *ps, const Window wid) {
|
|
|
|
if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
win *w = find_win(ps, wid);
|
|
|
|
if (!w) w = find_toplevel(ps, wid);
|
|
|
|
if (!w) w = find_toplevel2(ps, wid);
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2013-05-20 06:04:40 -04:00
|
|
|
/**
|
|
|
|
* Normalize a convolution kernel.
|
|
|
|
*/
|
|
|
|
static inline void
|
2018-09-27 12:14:44 -04:00
|
|
|
normalize_conv_kern(int wid, int hei, xcb_render_fixed_t *kern) {
|
2013-05-20 06:04:40 -04:00
|
|
|
double sum = 0.0;
|
|
|
|
for (int i = 0; i < wid * hei; ++i)
|
2018-09-27 12:14:44 -04:00
|
|
|
sum += XFIXED_TO_DOUBLE(kern[i]);
|
2013-05-20 06:04:40 -04:00
|
|
|
double factor = 1.0 / sum;
|
|
|
|
for (int i = 0; i < wid * hei; ++i)
|
2018-09-27 12:14:44 -04:00
|
|
|
kern[i] = DOUBLE_TO_XFIXED(XFIXED_TO_DOUBLE(kern[i]) * factor);
|
2013-05-20 06:04:40 -04:00
|
|
|
}
|
|
|
|
|
2012-10-21 08:44:24 -04:00
|
|
|
/**
|
2013-04-26 23:43:11 -04:00
|
|
|
* Resize a region.
|
2012-10-21 08:44:24 -04:00
|
|
|
*/
|
|
|
|
static inline void
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
resize_region(session_t *ps, region_t *region, short mod) {
|
2013-04-26 23:43:11 -04:00
|
|
|
if (!mod || !region) return;
|
|
|
|
// Loop through all rectangles
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
int nrects;
|
|
|
|
int nnewrects = 0;
|
|
|
|
pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects);
|
|
|
|
pixman_box32_t *newrects = calloc(nrects, sizeof *newrects);
|
|
|
|
for (int i = 0; i < nrects; i++) {
|
|
|
|
int x1 = max_i(rects[i].x1 - mod, 0);
|
|
|
|
int y1 = max_i(rects[i].y1 - mod, 0);
|
|
|
|
int x2 = min_i(rects[i].x2 + mod, ps->root_width);
|
|
|
|
int y2 = min_i(rects[i].y2 + mod, ps->root_height);
|
2013-04-26 23:43:11 -04:00
|
|
|
int wid = x2 - x1;
|
|
|
|
int hei = y2 - y1;
|
|
|
|
if (wid <= 0 || hei <= 0)
|
|
|
|
continue;
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
newrects[nnewrects] = (pixman_box32_t) {
|
|
|
|
.x1 = x1, .x2 = x2, .y1 = y1, .y2 = y2
|
|
|
|
};
|
2013-04-26 23:43:11 -04:00
|
|
|
++nnewrects;
|
|
|
|
}
|
|
|
|
|
Convert XfixesRegion to pixman region
Re-did the painting logic, and document it.
It is unclear to me what is the previous painting logic. But the current
one is basically this:
1. Go through all windows top to bottom, and put visible windows (not
unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
region of screen that is obscured by all the windows above current
one.
3. Paint all the visible windows from bottom to top. Subtract the region
of ignore from the painting region. If we need to paint shadow, we
subtract the body of the window from the shadow painting region too,
because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
window on top moved or changed shape, when window changed between
opaque and transparent, etc.
Notes:
It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.
It is unclear if window shape related events are handled correctly or
not. Need more testing.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-09-29 23:56:00 -04:00
|
|
|
pixman_region32_fini(region);
|
|
|
|
pixman_region32_init_rects(region, newrects, nnewrects);
|
2012-10-21 08:44:24 -04:00
|
|
|
|
2013-04-26 23:43:11 -04:00
|
|
|
free(newrects);
|
|
|
|
}
|
|
|
|
|
2018-08-22 10:12:29 -04:00
|
|
|
#ifdef CONFIG_OPENGL
|
2013-02-28 23:41:16 -05:00
|
|
|
/**
|
|
|
|
* Ensure we have a GLX context.
|
|
|
|
*/
|
|
|
|
static inline bool
|
|
|
|
ensure_glx_context(session_t *ps) {
|
|
|
|
// Create GLX context
|
2014-07-28 00:50:15 -04:00
|
|
|
if (!glx_has_context(ps))
|
2013-03-15 11:16:23 -04:00
|
|
|
glx_init(ps, false);
|
2013-02-28 23:41:16 -05:00
|
|
|
|
2014-07-28 00:50:15 -04:00
|
|
|
return ps->psglx->context;
|
2013-02-28 23:41:16 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-08-22 09:15:04 -04:00
|
|
|
/**
|
|
|
|
* Get the Xinerama screen a window is on.
|
|
|
|
*
|
|
|
|
* Return an index >= 0, or -1 if not found.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
cxinerama_win_upd_scr(session_t *ps, win *w) {
|
|
|
|
#ifdef CONFIG_XINERAMA
|
|
|
|
w->xinerama_scr = -1;
|
2018-09-29 05:46:29 -04:00
|
|
|
|
|
|
|
if (!ps->xinerama_scrs)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs);
|
|
|
|
int length = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs);
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
xcb_xinerama_screen_info_t *s = &scrs[i];
|
2018-09-23 14:10:46 -04:00
|
|
|
if (s->x_org <= w->g.x && s->y_org <= w->g.y
|
|
|
|
&& s->x_org + s->width >= w->g.x + w->widthb
|
|
|
|
&& s->y_org + s->height >= w->g.y + w->heightb) {
|
2018-09-29 05:46:29 -04:00
|
|
|
w->xinerama_scr = i;
|
2013-08-22 09:15:04 -04:00
|
|
|
return;
|
|
|
|
}
|
2018-09-29 05:46:29 -04:00
|
|
|
}
|
2013-08-22 09:15:04 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-08-11 13:22:49 -04:00
|
|
|
// vim: set et sw=2 :
|