2018-10-04 05:14:51 +08:00
|
|
|
// SPDX-License-Identifier: MIT
|
2003-11-10 11:45:17 +08:00
|
|
|
/*
|
2012-02-27 12:00:12 +08:00
|
|
|
* Compton - a compositor for X11
|
2003-11-10 11:45:17 +08:00
|
|
|
*
|
2012-02-27 12:00:12 +08:00
|
|
|
* Based on `xcompmgr` - Copyright (c) 2003, Keith Packard
|
2003-11-10 11:45:17 +08:00
|
|
|
*
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
* Copyright (c) 2011-2013, Christopher Jeffrey
|
2018-10-04 05:24:12 +08:00
|
|
|
* See LICENSE-mit for more information.
|
2003-11-10 11:45:17 +08:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-02-08 09:27:46 +08:00
|
|
|
#include <fcntl.h>
|
2019-01-21 05:15:20 +08:00
|
|
|
#include <stdio.h>
|
2018-09-09 09:29:45 +08:00
|
|
|
#include <string.h>
|
2019-01-21 05:15:20 +08:00
|
|
|
#include <inttypes.h>
|
2018-11-11 05:52:42 +08:00
|
|
|
#include <X11/Xlib.h>
|
2019-01-21 05:15:20 +08:00
|
|
|
#include <X11/Xutil.h>
|
2018-12-30 15:06:47 +08:00
|
|
|
#include <X11/Xlib-xcb.h>
|
2018-11-11 05:52:42 +08:00
|
|
|
#include <X11/Xlibint.h>
|
2018-12-30 15:06:47 +08:00
|
|
|
#include <X11/extensions/sync.h>
|
2018-09-23 06:44:44 +08:00
|
|
|
#include <xcb/randr.h>
|
2018-11-04 06:15:38 +08:00
|
|
|
#include <xcb/present.h>
|
2018-09-23 06:44:44 +08:00
|
|
|
#include <xcb/damage.h>
|
2018-09-24 02:10:46 +08:00
|
|
|
#include <xcb/render.h>
|
2019-01-21 05:15:20 +08:00
|
|
|
#include <xcb/xfixes.h>
|
|
|
|
#include <xcb/sync.h>
|
|
|
|
#include <xcb/composite.h>
|
2018-09-07 02:17:26 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
#include <ev.h>
|
|
|
|
|
2019-02-13 10:04:05 +08:00
|
|
|
#include "err.h"
|
2019-01-28 03:34:26 +08:00
|
|
|
#include "kernel.h"
|
2019-01-19 07:30:44 +08:00
|
|
|
#include "common.h"
|
2018-12-16 02:47:21 +08:00
|
|
|
#include "compiler.h"
|
2012-02-08 18:31:39 +08:00
|
|
|
#include "compton.h"
|
2018-09-30 06:30:19 +08:00
|
|
|
#ifdef CONFIG_OPENGL
|
|
|
|
#include "opengl.h"
|
|
|
|
#endif
|
2018-09-07 02:17:26 +08:00
|
|
|
#include "win.h"
|
|
|
|
#include "x.h"
|
2018-08-22 19:58:49 +08:00
|
|
|
#include "config.h"
|
2018-11-04 06:15:38 +08:00
|
|
|
#include "diagnostic.h"
|
2018-12-16 05:11:41 +08:00
|
|
|
#include "render.h"
|
2018-12-16 02:47:21 +08:00
|
|
|
#include "utils.h"
|
2019-01-19 07:30:44 +08:00
|
|
|
#include "region.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "c2.h"
|
2018-12-16 01:53:17 +08:00
|
|
|
#include "log.h"
|
2019-02-09 23:52:40 +08:00
|
|
|
#include "backend/backend.h"
|
2018-12-21 06:31:34 +08:00
|
|
|
#ifdef CONFIG_DBUS
|
|
|
|
#include "dbus.h"
|
|
|
|
#endif
|
2018-12-21 21:09:27 +08:00
|
|
|
#include "options.h"
|
2018-09-07 02:17:26 +08:00
|
|
|
|
2019-01-28 07:57:43 +08:00
|
|
|
#define CASESTRRET(s) case s: return #s
|
2018-11-11 05:52:42 +08:00
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
/// Get session_t pointer from a pointer to a member of session_t
|
|
|
|
#define session_ptr(ptr, member) ({ \
|
|
|
|
const __typeof__( ((session_t *)0)->member ) *__mptr = (ptr); \
|
|
|
|
(session_t *)((char *)__mptr - offsetof(session_t, member)); \
|
|
|
|
})
|
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
static void
|
|
|
|
update_refresh_rate(session_t *ps);
|
|
|
|
|
|
|
|
static bool
|
|
|
|
swopti_init(session_t *ps);
|
|
|
|
|
|
|
|
static void
|
|
|
|
cxinerama_upd_scrs(session_t *ps);
|
|
|
|
|
|
|
|
static void
|
|
|
|
session_destroy(session_t *ps);
|
|
|
|
|
|
|
|
static void
|
|
|
|
cxinerama_upd_scrs(session_t *ps);
|
|
|
|
|
2019-02-25 08:07:12 +08:00
|
|
|
static bool must_use
|
2018-09-07 02:17:26 +08:00
|
|
|
redir_start(session_t *ps);
|
|
|
|
|
|
|
|
static void
|
|
|
|
redir_stop(session_t *ps);
|
|
|
|
|
|
|
|
static win *
|
|
|
|
recheck_focus(session_t *ps);
|
|
|
|
|
|
|
|
static void
|
2018-12-28 04:45:38 +08:00
|
|
|
restack_win(session_t *ps, win *w, xcb_window_t new_above);
|
2018-09-07 02:17:26 +08:00
|
|
|
|
|
|
|
static void
|
|
|
|
update_ewmh_active_win(session_t *ps);
|
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
static void
|
|
|
|
draw_callback(EV_P_ ev_idle *w, int revents);
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Global constants ===
|
2012-02-27 12:00:12 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
/// Name strings for window types.
|
2013-01-24 13:38:03 +08:00
|
|
|
const char * const WINTYPES[NUM_WINTYPES] = {
|
2012-09-25 21:04:10 +08:00
|
|
|
"unknown",
|
|
|
|
"desktop",
|
|
|
|
"dock",
|
|
|
|
"toolbar",
|
|
|
|
"menu",
|
|
|
|
"utility",
|
|
|
|
"splash",
|
|
|
|
"dialog",
|
|
|
|
"normal",
|
|
|
|
"dropdown_menu",
|
|
|
|
"popup_menu",
|
|
|
|
"tooltip",
|
|
|
|
"notify",
|
|
|
|
"combo",
|
|
|
|
"dnd",
|
|
|
|
};
|
|
|
|
|
2013-01-30 13:41:08 +08:00
|
|
|
/// Names of VSync modes.
|
2013-04-21 22:30:22 +08:00
|
|
|
const char * const VSYNC_STRS[NUM_VSYNC + 1] = {
|
2013-03-23 22:06:41 +08:00
|
|
|
"none", // VSYNC_NONE
|
|
|
|
"drm", // VSYNC_DRM
|
|
|
|
"opengl", // VSYNC_OPENGL
|
|
|
|
"opengl-oml", // VSYNC_OPENGL_OML
|
|
|
|
"opengl-swc", // VSYNC_OPENGL_SWC
|
|
|
|
"opengl-mswc", // VSYNC_OPENGL_MSWC
|
2013-04-21 22:30:22 +08:00
|
|
|
NULL
|
2013-01-30 13:41:08 +08:00
|
|
|
};
|
|
|
|
|
2013-03-16 22:54:43 +08:00
|
|
|
/// Names of backends.
|
2013-04-21 22:30:22 +08:00
|
|
|
const char * const BACKEND_STRS[NUM_BKEND + 1] = {
|
2013-03-16 22:54:43 +08:00
|
|
|
"xrender", // BKEND_XRENDER
|
|
|
|
"glx", // BKEND_GLX
|
2013-12-24 07:46:48 +08:00
|
|
|
"xr_glx_hybrid",// BKEND_XR_GLX_HYBRID
|
2013-04-21 22:30:22 +08:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Global variables ===
|
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-22 11:42:39 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
/// Pointer to current session, as a global variable. Only used by
|
2018-11-27 07:56:55 +08:00
|
|
|
/// xerror(), which could not have a pointer to current session passed in.
|
|
|
|
/// XXX Limit what xerror can access by not having this pointer
|
2012-11-19 09:46:07 +08:00
|
|
|
session_t *ps_g = NULL;
|
2003-11-25 01:11:00 +08:00
|
|
|
|
2018-11-04 06:38:18 +08:00
|
|
|
/**
|
|
|
|
* Free Xinerama screen info.
|
|
|
|
*
|
|
|
|
* XXX consider moving to x.c
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
free_xinerama_info(session_t *ps) {
|
|
|
|
if (ps->xinerama_scr_regs) {
|
|
|
|
for (int i = 0; i < ps->xinerama_nscrs; ++i)
|
|
|
|
pixman_region32_fini(&ps->xinerama_scr_regs[i]);
|
|
|
|
free(ps->xinerama_scr_regs);
|
|
|
|
}
|
|
|
|
cxfree(ps->xinerama_scrs);
|
|
|
|
ps->xinerama_scrs = NULL;
|
|
|
|
ps->xinerama_nscrs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get current system clock in milliseconds.
|
|
|
|
*/
|
2019-02-21 11:36:51 +08:00
|
|
|
static inline uint64_t
|
2018-11-04 06:38:18 +08:00
|
|
|
get_time_ms(void) {
|
2019-02-21 11:36:51 +08:00
|
|
|
struct timespec tp;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
|
|
return tp.tv_sec * ((uint64_t)1000ul) + tp.tv_nsec / 1000000;
|
2018-11-04 06:38:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// XXX Move to x.c
|
|
|
|
static void
|
|
|
|
cxinerama_upd_scrs(session_t *ps) {
|
|
|
|
// XXX Consider deprecating Xinerama, switch to RandR when necessary
|
|
|
|
free_xinerama_info(ps);
|
|
|
|
|
|
|
|
if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return;
|
|
|
|
|
|
|
|
xcb_xinerama_is_active_reply_t *active =
|
|
|
|
xcb_xinerama_is_active_reply(ps->c,
|
|
|
|
xcb_xinerama_is_active(ps->c), NULL);
|
|
|
|
if (!active || !active->state) {
|
|
|
|
free(active);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
free(active);
|
|
|
|
|
|
|
|
ps->xinerama_scrs = xcb_xinerama_query_screens_reply(ps->c,
|
|
|
|
xcb_xinerama_query_screens(ps->c), NULL);
|
|
|
|
if (!ps->xinerama_scrs)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs);
|
|
|
|
ps->xinerama_nscrs = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs);
|
|
|
|
|
2018-12-16 02:47:21 +08:00
|
|
|
ps->xinerama_scr_regs = ccalloc(ps->xinerama_nscrs, region_t);
|
2018-11-04 06:38:18 +08:00
|
|
|
for (int i = 0; i < ps->xinerama_nscrs; ++i) {
|
|
|
|
const xcb_xinerama_screen_info_t * const s = &scrs[i];
|
|
|
|
pixman_region32_init_rect(&ps->xinerama_scr_regs[i], s->x_org, s->y_org, s->width, s->height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find matched window.
|
|
|
|
*
|
|
|
|
* XXX move to win.c
|
|
|
|
*/
|
|
|
|
static inline win *
|
2018-12-28 04:45:38 +08:00
|
|
|
find_win_all(session_t *ps, const xcb_window_t wid) {
|
2018-11-04 06:38:18 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
void queue_redraw(session_t *ps) {
|
|
|
|
// If --benchmark is used, redraw is always queued
|
|
|
|
if (!ps->redraw_needed && !ps->o.benchmark)
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_idle_start(ps->loop, &ps->draw_idle);
|
2018-10-03 03:22:26 +08:00
|
|
|
ps->redraw_needed = true;
|
|
|
|
}
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
/**
|
|
|
|
* Get a region of the screen size.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
get_screen_region(session_t *ps, region_t *res) {
|
|
|
|
pixman_box32_t b = {
|
|
|
|
.x1 = 0, .y1 = 0,
|
|
|
|
.x2 = ps->root_width,
|
|
|
|
.y2 = ps->root_height
|
|
|
|
};
|
|
|
|
pixman_region32_fini(res);
|
|
|
|
pixman_region32_init_rects(res, &b, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void add_damage(session_t *ps, const region_t *damage) {
|
2018-09-09 09:29:45 +08:00
|
|
|
// Ignore damage when screen isn't redirected
|
|
|
|
if (!ps->redirected)
|
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-30 11:56:00 +08:00
|
|
|
return;
|
2018-09-09 09:29:45 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
if (!damage)
|
|
|
|
return;
|
2019-01-09 07:15:00 +08:00
|
|
|
pixman_region32_union(ps->damage, ps->damage, (region_t *)damage);
|
2018-09-09 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Fading ===
|
2012-09-26 15:37:11 +08:00
|
|
|
|
2012-09-19 20:49:16 +08:00
|
|
|
/**
|
|
|
|
* Get the time left before next fading point.
|
|
|
|
*
|
|
|
|
* In milliseconds.
|
|
|
|
*/
|
2018-10-03 03:22:26 +08:00
|
|
|
static double
|
2012-11-19 09:46:07 +08:00
|
|
|
fade_timeout(session_t *ps) {
|
2018-12-22 00:25:28 +08:00
|
|
|
auto now = get_time_ms();
|
|
|
|
if (ps->o.fade_delta + ps->fade_time < now)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int diff = ps->o.fade_delta + ps->fade_time - now;
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2013-01-11 21:31:02 +08:00
|
|
|
diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2);
|
2004-07-08 15:07:26 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
return diff / 1000.0;
|
2004-07-08 15:07:26 +08:00
|
|
|
}
|
|
|
|
|
2012-09-19 20:49:16 +08:00
|
|
|
/**
|
|
|
|
* Run fading on a window.
|
|
|
|
*
|
|
|
|
* @param steps steps of fading
|
2019-02-12 09:53:50 +08:00
|
|
|
* @return whether we are still in fading mode
|
2012-09-19 20:49:16 +08:00
|
|
|
*/
|
2019-02-12 09:53:50 +08:00
|
|
|
static bool
|
2019-02-09 23:50:40 +08:00
|
|
|
run_fade(session_t *ps, win **_w, unsigned steps) {
|
|
|
|
win *w = *_w;
|
|
|
|
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
|
|
|
|
// We are not fading
|
|
|
|
assert(w->opacity_tgt == w->opacity);
|
2019-02-12 09:53:50 +08:00
|
|
|
return false;
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
2004-07-08 15:07:26 +08:00
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
if (!win_should_fade(ps, w)) {
|
|
|
|
log_debug("Window %#010x %s doesn't need fading", w->id, w->name);
|
2012-09-19 20:49:16 +08:00
|
|
|
w->opacity = w->opacity_tgt;
|
2019-02-09 23:50:40 +08:00
|
|
|
}
|
|
|
|
if (w->opacity == w->opacity_tgt) {
|
2019-02-12 09:53:50 +08:00
|
|
|
// We have reached target opacity, wrapping up.
|
|
|
|
// Note, we reach here after we have rendered the window with the target
|
|
|
|
// opacity at least once. If the window is destroyed because it is faded out,
|
|
|
|
// there is no need to add damage here.
|
2019-02-09 23:50:40 +08:00
|
|
|
log_debug("Fading finished for window %#010x %s", w->id, w->name);
|
|
|
|
win_check_fade_finished(ps, _w);
|
2019-02-12 09:53:50 +08:00
|
|
|
return false;
|
2019-02-09 23:50:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (steps) {
|
|
|
|
if (w->opacity < w->opacity_tgt) {
|
2012-09-19 20:49:16 +08:00
|
|
|
w->opacity = normalize_d_range(
|
2019-02-09 23:50:40 +08:00
|
|
|
w->opacity + ps->o.fade_in_step * steps,
|
2012-09-19 20:49:16 +08:00
|
|
|
0.0, w->opacity_tgt);
|
2019-02-09 23:50:40 +08:00
|
|
|
} else {
|
2012-09-19 20:49:16 +08:00
|
|
|
w->opacity = normalize_d_range(
|
2019-02-09 23:50:40 +08:00
|
|
|
w->opacity - ps->o.fade_out_step * steps,
|
|
|
|
w->opacity_tgt, 1);
|
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
2004-07-08 15:07:26 +08:00
|
|
|
|
2019-02-12 09:53:50 +08:00
|
|
|
// Note even if opacity == opacity_tgt, we still want to run preprocess one last
|
|
|
|
// time to finish state transition. So return true in that case too.
|
|
|
|
return true;
|
2004-07-08 15:07:26 +08:00
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Error handling ===
|
2012-02-09 06:45:08 +08:00
|
|
|
|
2012-02-27 12:00:12 +08:00
|
|
|
static void
|
2012-11-19 09:46:07 +08:00
|
|
|
discard_ignore(session_t *ps, unsigned long sequence) {
|
|
|
|
while (ps->ignore_head) {
|
2018-09-09 09:29:45 +08:00
|
|
|
if (sequence > ps->ignore_head->sequence) {
|
2012-11-19 09:46:07 +08:00
|
|
|
ignore_t *next = ps->ignore_head->next;
|
|
|
|
free(ps->ignore_head);
|
|
|
|
ps->ignore_head = next;
|
|
|
|
if (!ps->ignore_head) {
|
|
|
|
ps->ignore_tail = &ps->ignore_head;
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
|
|
|
} else {
|
2011-11-04 14:33:23 +08:00
|
|
|
break;
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
2004-06-27 12:48:37 +08:00
|
|
|
}
|
|
|
|
|
2012-02-27 12:00:12 +08:00
|
|
|
static int
|
2012-11-19 09:46:07 +08:00
|
|
|
should_ignore(session_t *ps, unsigned long sequence) {
|
|
|
|
discard_ignore(ps, sequence);
|
|
|
|
return ps->ignore_head && ps->ignore_head->sequence == sequence;
|
2004-06-27 12:48:37 +08:00
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Windows ===
|
2012-02-09 06:45:08 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
/**
|
|
|
|
* Determine the event mask for a window.
|
|
|
|
*/
|
2018-12-28 04:45:38 +08:00
|
|
|
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
|
2018-10-04 15:15:38 +08:00
|
|
|
long evmask = 0;
|
2012-12-08 11:10:08 +08:00
|
|
|
win *w = NULL;
|
2012-09-13 22:30:18 +08:00
|
|
|
|
2012-12-08 11:10:08 +08:00
|
|
|
// Check if it's a mapped frame window
|
|
|
|
if (WIN_EVMODE_FRAME == mode
|
2018-11-05 02:54:04 +08:00
|
|
|
|| ((w = find_win(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
|
2018-10-04 15:15:38 +08:00
|
|
|
evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.track_focus && !ps->o.use_ewmh_active_win)
|
2018-10-04 15:15:38 +08:00
|
|
|
evmask |= XCB_EVENT_MASK_FOCUS_CHANGE;
|
2012-09-13 22:30:18 +08:00
|
|
|
}
|
2012-09-13 23:12:54 +08:00
|
|
|
|
2012-12-08 11:10:08 +08:00
|
|
|
// Check if it's a mapped client window
|
|
|
|
if (WIN_EVMODE_CLIENT == mode
|
2018-11-05 02:54:04 +08:00
|
|
|
|| ((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst
|
2012-11-19 09:46:07 +08:00
|
|
|
|| ps->o.detect_client_opacity)
|
2018-10-04 15:15:38 +08:00
|
|
|
evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
|
2012-09-13 22:30:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return evmask;
|
|
|
|
}
|
|
|
|
|
2012-09-13 21:38:55 +08:00
|
|
|
/**
|
|
|
|
* Find out the WM frame of a client window by querying X.
|
|
|
|
*
|
2012-11-19 09:46:07 +08:00
|
|
|
* @param ps current session
|
2013-01-29 09:57:04 +08:00
|
|
|
* @param wid window ID
|
2012-09-13 21:38:55 +08:00
|
|
|
* @return struct _win object of the found window, NULL if not found
|
|
|
|
*/
|
2018-12-28 04:45:38 +08:00
|
|
|
win *find_toplevel2(session_t *ps, xcb_window_t wid) {
|
2018-09-07 02:17:26 +08:00
|
|
|
// TODO this should probably be an "update tree", then find_toplevel.
|
|
|
|
// current approach is a bit more "racy"
|
2012-09-13 21:38:55 +08:00
|
|
|
win *w = NULL;
|
|
|
|
|
|
|
|
// We traverse through its ancestors to find out the frame
|
2012-11-19 09:46:07 +08:00
|
|
|
while (wid && wid != ps->root && !(w = find_win(ps, wid))) {
|
2018-10-03 21:06:16 +08:00
|
|
|
xcb_query_tree_reply_t *reply;
|
2012-09-13 21:38:55 +08:00
|
|
|
|
2018-10-03 21:06:16 +08:00
|
|
|
// xcb_query_tree probably fails if you run compton when X is somehow
|
2012-09-13 21:38:55 +08:00
|
|
|
// initializing (like add it in .xinitrc). In this case
|
|
|
|
// just leave it alone.
|
2018-10-03 21:27:48 +08:00
|
|
|
reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL);
|
2018-10-03 21:06:16 +08:00
|
|
|
if (reply == NULL) {
|
2012-09-13 21:38:55 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-10-03 21:06:16 +08:00
|
|
|
wid = reply->parent;
|
2012-09-13 23:12:54 +08:00
|
|
|
|
2018-10-03 21:06:16 +08:00
|
|
|
free(reply);
|
2012-09-13 21:38:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Recheck currently focused window and set its <code>w->focused</code>
|
2012-11-19 09:46:07 +08:00
|
|
|
* to true.
|
2012-09-13 21:38:55 +08:00
|
|
|
*
|
2012-11-19 09:46:07 +08:00
|
|
|
* @param ps current session
|
2012-09-13 21:38:55 +08:00
|
|
|
* @return struct _win of currently focused window, NULL if not found
|
|
|
|
*/
|
2012-09-13 23:12:54 +08:00
|
|
|
static win *
|
2012-11-19 09:46:07 +08:00
|
|
|
recheck_focus(session_t *ps) {
|
2012-11-04 18:11:08 +08:00
|
|
|
// Use EWMH _NET_ACTIVE_WINDOW if enabled
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.use_ewmh_active_win) {
|
|
|
|
update_ewmh_active_win(ps);
|
|
|
|
return ps->active_win;
|
2012-11-04 18:11:08 +08:00
|
|
|
}
|
|
|
|
|
2012-09-13 21:38:55 +08:00
|
|
|
// Determine the currently focused window so we can apply appropriate
|
|
|
|
// opacity on it
|
2018-10-03 20:17:08 +08:00
|
|
|
xcb_window_t wid = XCB_NONE;
|
|
|
|
xcb_get_input_focus_reply_t *reply =
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL);
|
2012-09-13 21:38:55 +08:00
|
|
|
|
2018-10-03 20:17:08 +08:00
|
|
|
if (reply) {
|
|
|
|
wid = reply->focus;
|
|
|
|
free(reply);
|
|
|
|
}
|
2012-09-13 21:38:55 +08:00
|
|
|
|
2013-09-18 21:50:57 +08:00
|
|
|
win *w = find_win_all(ps, wid);
|
2012-09-13 21:38:55 +08:00
|
|
|
|
2018-12-20 10:49:29 +08:00
|
|
|
log_trace("%#010" PRIx32 " (%#010lx \"%s\") focused.", wid,
|
2018-12-28 04:45:38 +08:00
|
|
|
(w ? w->id: XCB_NONE), (w ? w->name: NULL));
|
2013-10-21 22:17:01 +08:00
|
|
|
|
2013-09-18 21:50:57 +08:00
|
|
|
// And we set the focus state here
|
2012-09-13 21:38:55 +08:00
|
|
|
if (w) {
|
2012-11-28 11:44:00 +08:00
|
|
|
win_set_focused(ps, w, true);
|
2012-09-13 21:38:55 +08:00
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2012-02-01 06:10:30 +08:00
|
|
|
}
|
|
|
|
|
2012-10-21 20:44:24 +08:00
|
|
|
/**
|
2018-09-07 02:17:26 +08:00
|
|
|
* Look for the client window of a particular window.
|
2012-10-21 20:44:24 +08:00
|
|
|
*/
|
2018-10-03 20:59:27 +08:00
|
|
|
xcb_window_t
|
|
|
|
find_client_win(session_t *ps, xcb_window_t w) {
|
2018-09-07 02:17:26 +08:00
|
|
|
if (wid_has_prop(ps, w, ps->atom_client)) {
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c,
|
|
|
|
xcb_query_tree(ps->c, w), NULL);
|
2018-10-03 20:59:27 +08:00
|
|
|
if (!reply)
|
2018-09-07 02:17:26 +08:00
|
|
|
return 0;
|
2018-10-03 20:59:27 +08:00
|
|
|
|
|
|
|
xcb_window_t *children = xcb_query_tree_children(reply);
|
|
|
|
int nchildren = xcb_query_tree_children_length(reply);
|
|
|
|
int i;
|
|
|
|
xcb_window_t ret = 0;
|
2018-09-07 02:17:26 +08:00
|
|
|
|
|
|
|
for (i = 0; i < nchildren; ++i) {
|
|
|
|
if ((ret = find_client_win(ps, children[i])))
|
|
|
|
break;
|
|
|
|
}
|
2012-10-21 20:44:24 +08:00
|
|
|
|
2018-10-03 20:59:27 +08:00
|
|
|
free(reply);
|
2012-10-21 20:44:24 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
return ret;
|
2012-10-21 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
2012-09-19 20:49:16 +08:00
|
|
|
static win *
|
2019-02-21 09:40:04 +08:00
|
|
|
paint_preprocess(session_t *ps, bool *fade_running) {
|
2019-02-12 09:53:50 +08:00
|
|
|
// XXX need better, more general name for `fade_running`. It really
|
|
|
|
// means if fade is still ongoing after the current frame is rendered
|
2012-09-19 20:49:16 +08:00
|
|
|
win *t = NULL, *next = NULL;
|
2019-02-12 09:53:50 +08:00
|
|
|
*fade_running = false;
|
2011-11-04 16:41:56 +08: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-08 10:20:01 +08:00
|
|
|
// Fading step calculation
|
2018-12-22 00:25:28 +08:00
|
|
|
unsigned long steps = 0L;
|
|
|
|
auto now = get_time_ms();
|
2019-02-21 11:36:51 +08:00
|
|
|
if (ps->fade_time) {
|
|
|
|
assert(now >= ps->fade_time);
|
|
|
|
steps = (now - ps->fade_time) / ps->o.fade_delta;
|
2018-12-22 00:25:28 +08:00
|
|
|
} else {
|
2019-02-21 11:36:51 +08:00
|
|
|
// Reset fade_time if unset
|
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-08 08:50:58 +08:00
|
|
|
ps->fade_time = get_time_ms();
|
2013-01-11 21:31:02 +08:00
|
|
|
steps = 0L;
|
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-08 08:50:58 +08:00
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->fade_time += steps * ps->o.fade_delta;
|
2011-11-04 16:41:56 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// First, let's process fading
|
2019-02-21 09:40:04 +08:00
|
|
|
for (win *w = ps->list; w; w = next) {
|
2012-09-19 20:49:16 +08:00
|
|
|
next = w->next;
|
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-30 11:56:00 +08:00
|
|
|
const winmode_t mode_old = w->mode;
|
|
|
|
const bool was_painted = w->to_paint;
|
|
|
|
const opacity_t opacity_old = w->opacity;
|
2014-04-19 21:52:20 +08:00
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
if (win_should_dim(ps, w) != w->dim) {
|
|
|
|
w->dim = win_should_dim(ps, w);
|
|
|
|
add_damage_from_win(ps, w);
|
2012-11-28 11:44:00 +08:00
|
|
|
}
|
|
|
|
|
2012-09-19 20:49:16 +08:00
|
|
|
// Run fading
|
2019-02-12 09:53:50 +08:00
|
|
|
if (run_fade(ps, &w, steps)) {
|
|
|
|
*fade_running = true;
|
|
|
|
}
|
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
if (!w) {
|
|
|
|
// the window might have been destroyed because fading finished
|
|
|
|
continue;
|
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
if (win_has_frame(w)) {
|
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-30 11:56:00 +08:00
|
|
|
w->frame_opacity = ps->o.frame_opacity;
|
2019-02-09 23:50:40 +08:00
|
|
|
} else {
|
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-30 11:56:00 +08:00
|
|
|
w->frame_opacity = 1.0;
|
2019-02-09 23:50:40 +08:00
|
|
|
}
|
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-30 11:56:00 +08:00
|
|
|
|
|
|
|
// Update window mode
|
2019-02-21 22:08:08 +08:00
|
|
|
w->mode = win_calc_mode(w);
|
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-30 11:56:00 +08:00
|
|
|
|
|
|
|
// Destroy all reg_ignore above when frame opaque state changes on
|
|
|
|
// SOLID mode
|
2019-02-09 23:50:40 +08:00
|
|
|
if (was_painted && w->mode != mode_old) {
|
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-30 11:56:00 +08:00
|
|
|
w->reg_ignore_valid = false;
|
2019-02-09 23:50:40 +08:00
|
|
|
}
|
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-30 11:56:00 +08:00
|
|
|
|
|
|
|
// Add window to damaged area if its opacity changes
|
|
|
|
// If was_painted == false, and to_paint is also false, we don't care
|
|
|
|
// If was_painted == false, but to_paint is true, damage will be added in the loop below
|
2019-02-09 23:50:40 +08:00
|
|
|
if (was_painted && w->opacity != opacity_old) {
|
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-30 11:56:00 +08:00
|
|
|
add_damage_from_win(ps, w);
|
2019-02-09 23:50:40 +08:00
|
|
|
}
|
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-30 11:56:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Opacity will not change, from now on.
|
|
|
|
rc_region_t *last_reg_ignore = rc_region_new();
|
|
|
|
|
|
|
|
bool unredir_possible = false;
|
|
|
|
// Trace whether it's the highest window to paint
|
|
|
|
bool is_highest = true;
|
|
|
|
bool reg_ignore_valid = true;
|
2019-02-21 09:40:04 +08:00
|
|
|
for (win *w = ps->list; w; w = next) {
|
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-30 11:56:00 +08:00
|
|
|
__label__ skip_window;
|
|
|
|
bool to_paint = true;
|
|
|
|
// w->to_paint remembers whether this window is painted last time
|
|
|
|
const bool was_painted = w->to_paint;
|
|
|
|
|
|
|
|
// In case calling the fade callback function destroys this window
|
|
|
|
next = w->next;
|
|
|
|
|
|
|
|
// Destroy reg_ignore if some window above us invalidated it
|
|
|
|
if (!reg_ignore_valid)
|
|
|
|
rc_region_unref(&w->reg_ignore);
|
|
|
|
|
2018-12-20 10:49:29 +08:00
|
|
|
//log_trace("%d %d %s", w->a.map_state, w->ever_damaged, w->name);
|
2013-09-12 21:23:20 +08:00
|
|
|
|
2012-10-31 08:54:09 +08:00
|
|
|
// Give up if it's not damaged or invisible, or it's unmapped and its
|
2013-09-12 21:23:20 +08:00
|
|
|
// pixmap is gone (for example due to a ConfigureNotify), or when it's
|
|
|
|
// excluded
|
2018-09-09 09:29:45 +08:00
|
|
|
if (!w->ever_damaged
|
2018-09-24 02:10:46 +08:00
|
|
|
|| w->g.x + w->g.width < 1 || w->g.y + w->g.height < 1
|
|
|
|
|| w->g.x >= ps->root_width || w->g.y >= ps->root_height
|
2019-02-09 23:50:40 +08:00
|
|
|
|| w->state == WSTATE_UNMAPPED
|
|
|
|
|| (double) w->opacity * MAX_ALPHA < 1
|
2013-09-12 21:23:20 +08:00
|
|
|
|| w->paint_excluded)
|
2012-11-19 09:46:07 +08:00
|
|
|
to_paint = false;
|
2018-12-20 10:49:29 +08:00
|
|
|
//log_trace("%s %d %d %d", w->name, to_paint, w->opacity, w->paint_excluded);
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2013-09-12 21:23:20 +08:00
|
|
|
// Add window to damaged area if its painting status changes
|
|
|
|
// or opacity changes
|
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-30 11:56:00 +08:00
|
|
|
if (to_paint != was_painted) {
|
|
|
|
w->reg_ignore_valid = false;
|
2018-09-07 02:17:26 +08:00
|
|
|
add_damage_from_win(ps, w);
|
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-30 11:56:00 +08:00
|
|
|
}
|
2013-09-12 21:23:20 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// to_paint will never change afterward
|
|
|
|
if (!to_paint)
|
|
|
|
goto skip_window;
|
|
|
|
|
|
|
|
// Calculate shadow opacity
|
2019-02-09 23:50:40 +08:00
|
|
|
w->shadow_opacity = ps->o.shadow_opacity * w->opacity * ps->o.frame_opacity;
|
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-30 11:56:00 +08:00
|
|
|
|
|
|
|
// Generate ignore region for painting to reduce GPU load
|
|
|
|
if (!w->reg_ignore)
|
|
|
|
w->reg_ignore = rc_region_ref(last_reg_ignore);
|
|
|
|
|
|
|
|
// If the window is solid, we add the window region to the
|
|
|
|
// ignored region
|
|
|
|
// Otherwise last_reg_ignore shouldn't change
|
|
|
|
if (w->mode == WMODE_SOLID && !ps->o.force_win_blend) {
|
|
|
|
region_t *tmp = rc_region_new();
|
|
|
|
if (w->frame_opacity == 1)
|
2018-10-13 08:17:59 +08:00
|
|
|
*tmp = win_get_bounding_shape_global_by_val(w);
|
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-30 11:56:00 +08:00
|
|
|
else {
|
2018-10-22 05:07:48 +08:00
|
|
|
win_get_region_noframe_local(w, tmp);
|
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-30 11:56:00 +08:00
|
|
|
pixman_region32_intersect(tmp, tmp, &w->bounding_shape);
|
2018-10-13 08:17:59 +08:00
|
|
|
pixman_region32_translate(tmp, w->g.x, w->g.y);
|
2012-11-09 21:44:02 +08:00
|
|
|
}
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
pixman_region32_union(tmp, tmp, last_reg_ignore);
|
|
|
|
rc_region_unref(&last_reg_ignore);
|
|
|
|
last_reg_ignore = tmp;
|
2012-10-21 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// (Un)redirect screen
|
|
|
|
// We could definitely unredirect the screen when there's no window to
|
|
|
|
// paint, but this is typically unnecessary, may cause flickering when
|
|
|
|
// fading is enabled, and could create inconsistency when the wallpaper
|
|
|
|
// is not correctly set.
|
|
|
|
if (ps->o.unredir_if_possible && is_highest) {
|
|
|
|
if (win_is_solid(ps, w)
|
|
|
|
&& (w->frame_opacity == 1 || !win_has_frame(w))
|
|
|
|
&& win_is_fullscreen(ps, w)
|
|
|
|
&& !w->unredir_if_possible_excluded)
|
|
|
|
unredir_possible = true;
|
2012-10-31 08:54:09 +08:00
|
|
|
}
|
2012-11-04 19:14:21 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// Reset flags
|
|
|
|
w->flags = 0;
|
|
|
|
w->prev_trans = t;
|
|
|
|
t = w;
|
2018-12-04 23:30:07 +08:00
|
|
|
|
|
|
|
// If the screen is not redirected and the window has redir_ignore set,
|
|
|
|
// this window should not cause the screen to become redirected
|
|
|
|
if (!(ps->o.wintype_option[w->window_type].redir_ignore && !ps->redirected)) {
|
|
|
|
is_highest = false;
|
|
|
|
}
|
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-30 11:56:00 +08:00
|
|
|
|
|
|
|
skip_window:
|
|
|
|
reg_ignore_valid = reg_ignore_valid && w->reg_ignore_valid;
|
|
|
|
w->reg_ignore_valid = true;
|
|
|
|
|
2018-12-16 05:11:41 +08:00
|
|
|
win_check_fade_finished(ps, &w);
|
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-30 11:56:00 +08:00
|
|
|
|
|
|
|
// Avoid setting w->to_paint if w is freed
|
2018-09-30 06:30:19 +08:00
|
|
|
if (w) {
|
2012-11-04 19:14:21 +08:00
|
|
|
w->to_paint = to_paint;
|
2014-04-19 21:52:20 +08:00
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
rc_region_unref(&last_reg_ignore);
|
2013-09-04 22:00:51 +08:00
|
|
|
|
2012-11-09 21:44:02 +08:00
|
|
|
// If possible, unredirect all windows and stop painting
|
2019-02-09 23:50:40 +08:00
|
|
|
if (ps->o.redirected_force != UNSET)
|
2013-07-26 12:52:16 +08:00
|
|
|
unredir_possible = !ps->o.redirected_force;
|
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-30 11:56:00 +08:00
|
|
|
else if (ps->o.unredir_if_possible && is_highest && !ps->redirected)
|
|
|
|
// If there's no window to paint, and the screen isn't redirected,
|
|
|
|
// don't redirect it.
|
2013-09-12 21:23:20 +08:00
|
|
|
unredir_possible = true;
|
2013-09-04 22:00:51 +08:00
|
|
|
if (unredir_possible) {
|
|
|
|
if (ps->redirected) {
|
2018-12-16 05:11:41 +08:00
|
|
|
if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit)
|
|
|
|
redir_stop(ps);
|
|
|
|
else if (!ev_is_active(&ps->unredir_timer)) {
|
|
|
|
ev_timer_set(&ps->unredir_timer,
|
|
|
|
ps->o.unredir_if_possible_delay / 1000.0, 0);
|
|
|
|
ev_timer_start(ps->loop, &ps->unredir_timer);
|
2013-01-29 09:57:04 +08:00
|
|
|
}
|
2013-01-12 22:21:35 +08:00
|
|
|
}
|
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-30 11:56:00 +08:00
|
|
|
} else {
|
2018-12-16 05:11:41 +08:00
|
|
|
ev_timer_stop(ps->loop, &ps->unredir_timer);
|
2019-02-25 08:07:12 +08:00
|
|
|
if (!redir_start(ps)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-10-21 20:44:24 +08:00
|
|
|
}
|
|
|
|
|
2018-12-16 05:11:41 +08:00
|
|
|
return t;
|
|
|
|
}
|
2013-03-25 11:36:39 +08:00
|
|
|
|
2018-12-16 05:11:41 +08:00
|
|
|
/*
|
|
|
|
* WORK-IN-PROGRESS!
|
|
|
|
static void
|
|
|
|
xr_take_screenshot(session_t *ps) {
|
|
|
|
XImage *img = XGetImage(ps->dpy, get_tgt_window(ps), 0, 0,
|
|
|
|
ps->root_width, ps->root_height, AllPlanes, XYPixmap);
|
|
|
|
if (!img) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_error("Failed to get XImage.");
|
2018-12-16 05:11:41 +08:00
|
|
|
return NULL;
|
2012-10-21 20:44:24 +08:00
|
|
|
}
|
2018-12-16 05:11:41 +08:00
|
|
|
assert(0 == img->xoffset);
|
2012-10-21 20:44:24 +08:00
|
|
|
}
|
2018-12-16 05:11:41 +08:00
|
|
|
*/
|
2012-10-21 20:44:24 +08:00
|
|
|
|
2012-11-03 10:30:32 +08:00
|
|
|
/**
|
|
|
|
* Rebuild cached <code>screen_reg</code>.
|
|
|
|
*/
|
|
|
|
static void
|
2012-11-19 09:46:07 +08:00
|
|
|
rebuild_screen_reg(session_t *ps) {
|
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-30 11:56:00 +08:00
|
|
|
get_screen_region(ps, &ps->screen_reg);
|
2012-11-03 10:30:32 +08:00
|
|
|
}
|
|
|
|
|
2013-06-09 17:06:35 +08:00
|
|
|
/**
|
|
|
|
* Rebuild <code>shadow_exclude_reg</code>.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rebuild_shadow_exclude_reg(session_t *ps) {
|
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-30 11:56:00 +08:00
|
|
|
bool ret = parse_geometry(ps, ps->o.shadow_exclude_reg_str,
|
|
|
|
&ps->shadow_exclude_reg);
|
|
|
|
if (!ret)
|
|
|
|
exit(1);
|
2018-09-09 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-11-20 00:12:15 +08:00
|
|
|
static void
|
2018-09-23 02:43:35 +08:00
|
|
|
repair_win(session_t *ps, win *w) {
|
2018-11-05 02:54:04 +08:00
|
|
|
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
return;
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
region_t parts;
|
|
|
|
pixman_region32_init(&parts);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-09-09 09:29:45 +08:00
|
|
|
if (!w->ever_damaged) {
|
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-30 11:56:00 +08:00
|
|
|
win_extents(w, &parts);
|
2018-09-29 17:18:09 +08:00
|
|
|
set_ignore_cookie(ps,
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE));
|
2011-11-04 14:33:23 +08:00
|
|
|
} else {
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_xfixes_region_t tmp = xcb_generate_id(ps->c);
|
|
|
|
xcb_xfixes_create_region(ps->c, tmp, 0, NULL);
|
2018-09-29 17:18:09 +08:00
|
|
|
set_ignore_cookie(ps,
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp));
|
|
|
|
xcb_xfixes_translate_region(ps->c, tmp,
|
2018-09-24 02:10:46 +08:00
|
|
|
w->g.x + w->g.border_width,
|
|
|
|
w->g.y + w->g.border_width);
|
2019-02-03 23:59:31 +08:00
|
|
|
x_fetch_region(ps->c, tmp, &parts);
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_xfixes_destroy_region(ps->c, tmp);
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2018-09-09 09:29:45 +08:00
|
|
|
w->ever_damaged = true;
|
2013-09-04 22:00:51 +08:00
|
|
|
w->pixmap_damaged = true;
|
|
|
|
|
|
|
|
// Why care about damage when screen is unredirected?
|
|
|
|
// We will force full-screen repaint on redirection.
|
2015-05-13 04:14:39 +08:00
|
|
|
if (!ps->redirected) {
|
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-30 11:56:00 +08:00
|
|
|
pixman_region32_fini(&parts);
|
2015-05-13 04:14:39 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-09-04 22:00:51 +08:00
|
|
|
|
2012-10-21 20:44:24 +08:00
|
|
|
// Remove the part in the damage area that could be ignored
|
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-30 11:56:00 +08:00
|
|
|
if (w->reg_ignore && win_is_region_ignore_valid(ps, w))
|
|
|
|
pixman_region32_subtract(&parts, &parts, w->reg_ignore);
|
2012-10-21 20:44:24 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
add_damage(ps, &parts);
|
|
|
|
pixman_region32_fini(&parts);
|
2003-11-09 15:08:23 +08:00
|
|
|
}
|
2019-02-09 23:52:40 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
static void
|
2018-12-28 04:45:38 +08:00
|
|
|
restack_win(session_t *ps, win *w, xcb_window_t new_above) {
|
|
|
|
xcb_window_t old_above;
|
2003-11-25 01:11:00 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
if (w->next) {
|
|
|
|
old_above = w->next->id;
|
2011-11-04 14:33:23 +08:00
|
|
|
} else {
|
2018-12-28 04:45:38 +08:00
|
|
|
old_above = XCB_NONE;
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
2019-02-20 08:17:23 +08:00
|
|
|
log_debug("Restack %#010x (%s), old_above: %#010x, new_above: %#010x",
|
|
|
|
w->id, w->name, old_above, new_above);
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
if (old_above != new_above) {
|
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-30 11:56:00 +08:00
|
|
|
w->reg_ignore_valid = false;
|
|
|
|
rc_region_unref(&w->reg_ignore);
|
|
|
|
if (w->next) {
|
|
|
|
w->next->reg_ignore_valid = false;
|
|
|
|
rc_region_unref(&w->next->reg_ignore);
|
|
|
|
}
|
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
win **prev = NULL, **prev_old = NULL;
|
2012-09-11 22:22:58 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
bool found = false;
|
|
|
|
for (prev = &ps->list; *prev; prev = &(*prev)->next) {
|
2019-02-09 23:50:40 +08:00
|
|
|
if ((*prev)->id == new_above && (*prev)->state != WSTATE_DESTROYING) {
|
2018-09-07 02:17:26 +08:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-09-12 10:52:52 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
if (new_above && !found) {
|
2018-12-28 04:45:38 +08:00
|
|
|
log_error("(%#010x, %#010x): Failed to found new above window.", w->id, new_above);
|
2018-09-07 02:17:26 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-11-28 11:44:00 +08:00
|
|
|
|
2019-02-20 08:17:23 +08:00
|
|
|
for (prev_old = &ps->list; *prev_old; prev_old = &(*prev_old)->next) {
|
|
|
|
if ((*prev_old) == w) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-09-12 10:52:52 +08:00
|
|
|
|
2019-02-20 08:17:23 +08:00
|
|
|
*prev_old = w->next;
|
2018-09-07 02:17:26 +08:00
|
|
|
w->next = *prev;
|
|
|
|
*prev = w;
|
2012-09-12 10:52:52 +08:00
|
|
|
|
2018-10-30 01:13:23 +08:00
|
|
|
// add damage for this window
|
|
|
|
add_damage_from_win(ps, w);
|
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
#ifdef DEBUG_RESTACK
|
2019-02-20 08:17:23 +08:00
|
|
|
log_trace("Window stack modified. Current stack:");
|
|
|
|
for (win *c = ps->list; c; c = c->next) {
|
|
|
|
const char *desc = "";
|
2019-02-20 09:21:58 +08:00
|
|
|
if (c->state == WSTATE_DESTROYING) {
|
2019-02-20 08:17:23 +08:00
|
|
|
desc = "(D) ";
|
2018-09-07 02:17:26 +08:00
|
|
|
}
|
2019-02-20 08:17:23 +08:00
|
|
|
log_trace("%#010x \"%s\" %s", c->id, c->name, desc);
|
2018-09-07 02:17:26 +08:00
|
|
|
}
|
|
|
|
#endif
|
2012-10-28 17:02:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
void
|
2018-09-23 06:44:44 +08:00
|
|
|
configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
2018-09-07 02:17:26 +08:00
|
|
|
// On root window changes
|
2019-02-21 11:50:34 +08:00
|
|
|
auto bi = backend_list[ps->o.backend];
|
2018-09-07 02:17:26 +08:00
|
|
|
if (ce->window == ps->root) {
|
2019-02-09 23:52:40 +08:00
|
|
|
if (ps->o.experimental_backends) {
|
2019-02-21 11:50:34 +08:00
|
|
|
assert(bi);
|
|
|
|
if (!bi->root_change) {
|
2019-02-09 23:52:40 +08:00
|
|
|
// deinit/reinit backend if the backend cannot handle root change
|
2019-02-21 11:50:34 +08:00
|
|
|
bi->deinit(ps->backend_data, ps);
|
2019-02-25 08:07:12 +08:00
|
|
|
ps->backend_data = NULL;
|
2019-02-09 23:52:40 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
free_paint(ps, &ps->tgt_buffer);
|
|
|
|
}
|
2012-11-09 11:35:40 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
ps->root_width = ce->width;
|
|
|
|
ps->root_height = ce->height;
|
2012-11-09 11:35:40 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
rebuild_screen_reg(ps);
|
|
|
|
rebuild_shadow_exclude_reg(ps);
|
2019-01-09 07:15:00 +08:00
|
|
|
for (int i = 0; i < ps->ndamage; i++) {
|
2019-02-25 08:07:12 +08:00
|
|
|
pixman_region32_clear(&ps->damage_ring[i]);
|
2019-01-09 07:15:00 +08:00
|
|
|
}
|
|
|
|
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
2014-04-19 21:52:20 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
// Re-redirect screen if required
|
|
|
|
if (ps->o.reredir_on_root_change && ps->redirected) {
|
|
|
|
redir_stop(ps);
|
2019-02-25 08:07:12 +08:00
|
|
|
if (!redir_start(ps)) {
|
|
|
|
return;
|
|
|
|
}
|
2018-09-07 02:17:26 +08:00
|
|
|
}
|
2014-04-19 21:52:20 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// Invalidate reg_ignore from the top
|
|
|
|
rc_region_unref(&ps->list->reg_ignore);
|
|
|
|
ps->list->reg_ignore_valid = false;
|
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
#ifdef CONFIG_OPENGL
|
|
|
|
// Reinitialize GLX on root change
|
|
|
|
if (ps->o.glx_reinit_on_root_change && ps->psglx) {
|
|
|
|
if (!glx_reinit(ps, bkend_use_glx(ps)))
|
2018-12-20 10:49:29 +08:00
|
|
|
log_error("Failed to reinitialize GLX, troubles ahead.");
|
2018-12-16 08:53:41 +08:00
|
|
|
if (BKEND_GLX == ps->o.backend && !glx_init_blur(ps))
|
2018-12-20 10:49:29 +08:00
|
|
|
log_error("Failed to initialize filters.");
|
2018-09-07 02:17:26 +08:00
|
|
|
}
|
2014-04-19 21:52:20 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
// GLX root change callback
|
|
|
|
if (BKEND_GLX == ps->o.backend)
|
|
|
|
glx_on_root_change(ps);
|
|
|
|
#endif
|
2019-02-09 23:52:40 +08:00
|
|
|
if (ps->o.experimental_backends) {
|
2019-02-21 11:50:34 +08:00
|
|
|
if (bi->root_change) {
|
|
|
|
bi->root_change(ps->backend_data, ps);
|
2019-02-09 23:52:40 +08:00
|
|
|
} else {
|
2019-02-21 11:50:34 +08:00
|
|
|
ps->backend_data = bi->init(ps);
|
2019-02-25 08:07:12 +08:00
|
|
|
if (!ps->backend_data) {
|
|
|
|
log_fatal("Failed to re-initialize backend after root change, aborting...");
|
|
|
|
ps->quit = true;
|
|
|
|
ev_break(ps->loop, EVBREAK_ALL);
|
|
|
|
return;
|
|
|
|
}
|
2019-02-09 23:52:40 +08:00
|
|
|
}
|
|
|
|
}
|
2018-09-07 02:17:26 +08:00
|
|
|
force_repaint(ps);
|
2012-09-17 22:15:04 +08:00
|
|
|
|
2018-09-07 02:17:26 +08:00
|
|
|
return;
|
|
|
|
}
|
2013-01-12 22:21:35 +08:00
|
|
|
|
2019-02-20 08:17:23 +08:00
|
|
|
// Non-root window changes
|
2018-09-07 02:17:26 +08:00
|
|
|
win *w = find_win(ps, ce->window);
|
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-30 11:56:00 +08:00
|
|
|
region_t damage;
|
|
|
|
pixman_region32_init(&damage);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2019-02-20 08:17:23 +08:00
|
|
|
if (!w) {
|
2011-11-04 14:33:23 +08:00
|
|
|
return;
|
2019-02-20 08:17:23 +08:00
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2019-02-23 08:14:26 +08:00
|
|
|
if (w->state == WSTATE_UNMAPPED ||
|
|
|
|
w->state == WSTATE_UNMAPPING ||
|
|
|
|
w->state == WSTATE_DESTROYING) {
|
2011-11-04 14:33:23 +08:00
|
|
|
/* save the configure event for when the window maps */
|
2012-11-19 09:46:07 +08:00
|
|
|
w->need_configure = true;
|
2011-11-04 14:33:23 +08:00
|
|
|
w->queue_configure = *ce;
|
2018-09-23 06:44:44 +08:00
|
|
|
restack_win(ps, w, ce->above_sibling);
|
2011-11-04 14:33:23 +08:00
|
|
|
} else {
|
2019-02-20 08:17:23 +08:00
|
|
|
if (!w->need_configure) {
|
2018-09-23 06:44:44 +08:00
|
|
|
restack_win(ps, w, ce->above_sibling);
|
2019-02-20 08:17:23 +08:00
|
|
|
}
|
2012-09-13 13:58:05 +08:00
|
|
|
|
2013-06-19 19:36:48 +08:00
|
|
|
bool factor_change = false;
|
2012-11-19 09:46:07 +08:00
|
|
|
w->need_configure = false;
|
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-30 11:56:00 +08:00
|
|
|
win_extents(w, &damage);
|
2008-02-15 13:55:17 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// If window geometry change, free old extents
|
2018-09-24 02:10:46 +08:00
|
|
|
if (w->g.x != ce->x || w->g.y != ce->y
|
|
|
|
|| w->g.width != ce->width || w->g.height != ce->height
|
2018-10-13 08:17:59 +08:00
|
|
|
|| w->g.border_width != ce->border_width)
|
2013-06-19 19:36:48 +08:00
|
|
|
factor_change = true;
|
2012-11-01 10:43:15 +08:00
|
|
|
|
2018-09-24 02:10:46 +08:00
|
|
|
w->g.x = ce->x;
|
|
|
|
w->g.y = ce->y;
|
2011-11-05 20:00:39 +08:00
|
|
|
|
2018-09-24 02:10:46 +08:00
|
|
|
if (w->g.width != ce->width || w->g.height != ce->height
|
|
|
|
|| w->g.border_width != ce->border_width) {
|
|
|
|
w->g.width = ce->width;
|
|
|
|
w->g.height = ce->height;
|
|
|
|
w->g.border_width = ce->border_width;
|
2019-02-21 22:08:08 +08:00
|
|
|
win_on_win_size_change(ps, w);
|
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-30 11:56:00 +08:00
|
|
|
win_update_bounding_shape(ps, w);
|
2012-09-17 22:15:04 +08:00
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
region_t new_extents;
|
|
|
|
pixman_region32_init(&new_extents);
|
|
|
|
win_extents(w, &new_extents);
|
|
|
|
pixman_region32_union(&damage, &damage, &new_extents);
|
|
|
|
pixman_region32_fini(&new_extents);
|
2013-06-19 19:36:48 +08:00
|
|
|
|
2013-08-22 21:15:04 +08:00
|
|
|
if (factor_change) {
|
2018-10-17 00:16:18 +08:00
|
|
|
win_on_factor_change(ps, w);
|
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-30 11:56:00 +08:00
|
|
|
add_damage(ps, &damage);
|
2019-02-09 23:50:40 +08:00
|
|
|
win_update_screen(ps, w);
|
2013-08-22 21:15:04 +08:00
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
2008-02-20 14:20:40 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
pixman_region32_fini(&damage);
|
|
|
|
|
2013-01-29 09:57:04 +08:00
|
|
|
// override_redirect flag cannot be changed after window creation, as far
|
|
|
|
// as I know, so there's no point to re-match windows here.
|
2011-11-04 14:33:23 +08:00
|
|
|
w->a.override_redirect = ce->override_redirect;
|
2003-11-09 15:08:23 +08:00
|
|
|
}
|
|
|
|
|
2003-11-24 07:20:42 +08:00
|
|
|
static void
|
2018-09-23 06:44:44 +08:00
|
|
|
circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce) {
|
2012-11-19 09:46:07 +08:00
|
|
|
win *w = find_win(ps, ce->window);
|
2018-12-28 04:45:38 +08:00
|
|
|
xcb_window_t new_above;
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2011-11-04 16:41:56 +08:00
|
|
|
if (!w) return;
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2011-11-04 16:41:56 +08:00
|
|
|
if (ce->place == PlaceOnTop) {
|
2012-11-19 09:46:07 +08:00
|
|
|
new_above = ps->list->id;
|
2011-11-04 16:41:56 +08:00
|
|
|
} else {
|
2018-12-28 04:45:38 +08:00
|
|
|
new_above = XCB_NONE;
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
restack_win(ps, w, new_above);
|
2003-11-24 07:20:42 +08:00
|
|
|
}
|
|
|
|
|
2012-10-24 10:09:59 +08:00
|
|
|
static inline void
|
2012-11-19 09:46:07 +08:00
|
|
|
root_damaged(session_t *ps) {
|
2013-03-15 23:16:23 +08:00
|
|
|
if (ps->root_tile_paint.pixmap) {
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_clear_area(ps->c, true, ps->root, 0, 0, 0, 0);
|
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-30 11:56:00 +08:00
|
|
|
free_root_tile(ps);
|
2012-10-24 10:09:59 +08:00
|
|
|
}
|
2013-01-24 13:38:03 +08:00
|
|
|
|
|
|
|
// Mark screen damaged
|
|
|
|
force_repaint(ps);
|
2012-10-24 10:09:59 +08:00
|
|
|
}
|
|
|
|
|
2018-09-29 17:11:43 +08:00
|
|
|
/**
|
|
|
|
* Xlib error handler function.
|
|
|
|
*/
|
|
|
|
static int
|
2018-12-20 04:50:02 +08:00
|
|
|
xerror(Display attr_unused *dpy, XErrorEvent *ev) {
|
2018-09-30 21:37:21 +08:00
|
|
|
if (!should_ignore(ps_g, ev->serial))
|
|
|
|
x_print_error(ev->serial, ev->request_code, ev->minor_code, ev->error_code);
|
2011-11-04 14:33:23 +08:00
|
|
|
return 0;
|
2003-11-09 15:08:23 +08:00
|
|
|
}
|
|
|
|
|
2018-09-29 17:11:43 +08:00
|
|
|
/**
|
|
|
|
* XCB error handler function.
|
|
|
|
*/
|
2018-09-30 15:31:22 +08:00
|
|
|
void
|
2019-02-03 23:59:31 +08:00
|
|
|
ev_xcb_error(session_t *ps, xcb_generic_error_t *err) {
|
2018-09-30 21:37:21 +08:00
|
|
|
if (!should_ignore(ps, err->sequence))
|
|
|
|
x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code);
|
2018-09-29 17:11:43 +08:00
|
|
|
}
|
|
|
|
|
2003-11-20 00:12:15 +08:00
|
|
|
static 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-30 11:56:00 +08:00
|
|
|
expose_root(session_t *ps, const rect_t *rects, int nrects) {
|
|
|
|
region_t region;
|
|
|
|
pixman_region32_init_rects(®ion, rects, nrects);
|
|
|
|
add_damage(ps, ®ion);
|
2003-11-09 15:08:23 +08:00
|
|
|
}
|
2013-01-24 13:38:03 +08:00
|
|
|
/**
|
|
|
|
* Force a full-screen repaint.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
force_repaint(session_t *ps) {
|
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-30 11:56:00 +08:00
|
|
|
assert(pixman_region32_not_empty(&ps->screen_reg));
|
2018-10-03 03:22:26 +08:00
|
|
|
queue_redraw(ps);
|
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-30 11:56:00 +08:00
|
|
|
add_damage(ps, &ps->screen_reg);
|
2013-01-24 13:38:03 +08:00
|
|
|
}
|
|
|
|
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
#ifdef CONFIG_DBUS
|
|
|
|
/** @name DBus hooks
|
|
|
|
*/
|
|
|
|
///@{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set w->shadow_force of a window.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
win_set_shadow_force(session_t *ps, win *w, switch_t val) {
|
|
|
|
if (val != w->shadow_force) {
|
|
|
|
w->shadow_force = val;
|
|
|
|
win_determine_shadow(ps, w);
|
2018-10-03 03:22:26 +08:00
|
|
|
queue_redraw(ps);
|
2013-05-20 18:04:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set w->fade_force of a window.
|
2019-02-09 23:50:40 +08:00
|
|
|
*
|
|
|
|
* Doesn't affect fading already in progress
|
2013-05-20 18:04:40 +08:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
win_set_fade_force(session_t *ps, win *w, switch_t val) {
|
2019-02-09 23:50:40 +08:00
|
|
|
w->fade_force = val;
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set w->focused_force of a window.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
win_set_focused_force(session_t *ps, win *w, switch_t val) {
|
|
|
|
if (val != w->focused_force) {
|
|
|
|
w->focused_force = val;
|
|
|
|
win_update_focused(ps, w);
|
2018-10-03 03:22:26 +08:00
|
|
|
queue_redraw(ps);
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set w->invert_color_force of a window.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
win_set_invert_color_force(session_t *ps, win *w, switch_t val) {
|
|
|
|
if (val != w->invert_color_force) {
|
|
|
|
w->invert_color_force = val;
|
|
|
|
win_determine_invert_color(ps, w);
|
2018-10-03 03:22:26 +08:00
|
|
|
queue_redraw(ps);
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
}
|
|
|
|
}
|
2013-03-10 18:45:54 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable focus tracking.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
opts_init_track_focus(session_t *ps) {
|
|
|
|
// Already tracking focus
|
|
|
|
if (ps->o.track_focus)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ps->o.track_focus = true;
|
|
|
|
|
|
|
|
if (!ps->o.use_ewmh_active_win) {
|
|
|
|
// Start listening to FocusChange events
|
|
|
|
for (win *w = ps->list; w; w = w->next)
|
2018-11-05 02:54:04 +08:00
|
|
|
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE)
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK,
|
2018-10-03 20:34:24 +08:00
|
|
|
(const uint32_t[]) { determine_evmask(ps, w->id, WIN_EVMODE_FRAME) });
|
2013-03-10 18:45:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recheck focus
|
|
|
|
recheck_focus(ps);
|
|
|
|
}
|
2013-05-20 18:04:40 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set no_fading_openclose option.
|
2019-02-09 23:50:40 +08:00
|
|
|
*
|
|
|
|
* Don't affect fading already in progress
|
2013-05-20 18:04:40 +08:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
opts_set_no_fading_openclose(session_t *ps, bool newval) {
|
2019-02-09 23:50:40 +08:00
|
|
|
ps->o.no_fading_openclose = newval;
|
2013-05-20 18:04:40 +08:00
|
|
|
}
|
|
|
|
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
//!@}
|
|
|
|
#endif
|
|
|
|
|
2018-12-20 04:50:02 +08:00
|
|
|
static inline int attr_unused
|
2018-09-24 02:10:46 +08:00
|
|
|
ev_serial(xcb_generic_event_t *ev) {
|
|
|
|
return ev->full_sequence;
|
2003-11-24 07:20:42 +08:00
|
|
|
}
|
|
|
|
|
2018-12-20 04:50:02 +08:00
|
|
|
static inline const char * attr_unused
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_name(session_t *ps, xcb_generic_event_t *ev) {
|
2011-11-04 17:18:10 +08:00
|
|
|
static char buf[128];
|
2018-09-23 06:44:44 +08:00
|
|
|
switch (ev->response_type & 0x7f) {
|
2012-11-03 05:51:40 +08:00
|
|
|
CASESTRRET(FocusIn);
|
|
|
|
CASESTRRET(FocusOut);
|
|
|
|
CASESTRRET(CreateNotify);
|
|
|
|
CASESTRRET(ConfigureNotify);
|
|
|
|
CASESTRRET(DestroyNotify);
|
|
|
|
CASESTRRET(MapNotify);
|
|
|
|
CASESTRRET(UnmapNotify);
|
|
|
|
CASESTRRET(ReparentNotify);
|
|
|
|
CASESTRRET(CirculateNotify);
|
|
|
|
CASESTRRET(Expose);
|
|
|
|
CASESTRRET(PropertyNotify);
|
|
|
|
CASESTRRET(ClientMessage);
|
2014-03-17 23:25:34 +08:00
|
|
|
}
|
2012-09-13 13:58:05 +08:00
|
|
|
|
2018-09-27 23:29:51 +08:00
|
|
|
if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type)
|
2014-03-17 23:25:34 +08:00
|
|
|
return "Damage";
|
2012-09-13 13:58:05 +08:00
|
|
|
|
2018-09-23 06:44:44 +08:00
|
|
|
if (ps->shape_exists && ev->response_type == ps->shape_event)
|
2014-03-17 23:25:34 +08:00
|
|
|
return "ShapeNotify";
|
2012-09-13 13:58:05 +08:00
|
|
|
|
2018-11-08 22:53:13 +08:00
|
|
|
if (ps->xsync_exists) {
|
|
|
|
int o = ev->response_type - ps->xsync_event;
|
|
|
|
switch (o) {
|
|
|
|
CASESTRRET(XSyncCounterNotify);
|
|
|
|
CASESTRRET(XSyncAlarmNotify);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-23 06:44:44 +08:00
|
|
|
sprintf(buf, "Event %d", ev->response_type);
|
2014-03-17 23:25:34 +08:00
|
|
|
|
|
|
|
return buf;
|
2003-11-24 07:20:42 +08:00
|
|
|
}
|
|
|
|
|
2018-12-28 04:45:38 +08:00
|
|
|
static inline xcb_window_t attr_unused
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_window(session_t *ps, xcb_generic_event_t *ev) {
|
|
|
|
switch (ev->response_type) {
|
2012-09-11 21:33:03 +08:00
|
|
|
case FocusIn:
|
|
|
|
case FocusOut:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_focus_in_event_t *)ev)->event;
|
2012-09-11 21:33:03 +08:00
|
|
|
case CreateNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_create_notify_event_t *)ev)->window;
|
2012-09-11 21:33:03 +08:00
|
|
|
case ConfigureNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_configure_notify_event_t *)ev)->window;
|
2012-09-19 20:49:16 +08:00
|
|
|
case DestroyNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_destroy_notify_event_t *)ev)->window;
|
2011-11-04 16:41:56 +08:00
|
|
|
case MapNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_map_notify_event_t *)ev)->window;
|
2011-11-04 16:41:56 +08:00
|
|
|
case UnmapNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_unmap_notify_event_t *)ev)->window;
|
2011-11-04 16:41:56 +08:00
|
|
|
case ReparentNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_reparent_notify_event_t *)ev)->window;
|
2011-11-04 16:41:56 +08:00
|
|
|
case CirculateNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_circulate_notify_event_t *)ev)->window;
|
2012-09-11 21:33:03 +08:00
|
|
|
case Expose:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_expose_event_t *)ev)->window;
|
2012-09-11 21:33:03 +08:00
|
|
|
case PropertyNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_property_notify_event_t *)ev)->window;
|
2012-09-18 11:28:09 +08:00
|
|
|
case ClientMessage:
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_client_message_event_t *)ev)->window;
|
2011-11-04 16:41:56 +08:00
|
|
|
default:
|
2018-09-27 23:29:51 +08:00
|
|
|
if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) {
|
2018-09-23 06:44:44 +08:00
|
|
|
return ((xcb_damage_notify_event_t *)ev)->drawable;
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
2012-09-13 13:58:05 +08:00
|
|
|
|
2018-09-23 06:44:44 +08:00
|
|
|
if (ps->shape_exists && ev->response_type == ps->shape_event) {
|
|
|
|
return ((xcb_shape_notify_event_t *) ev)->affected_window;
|
2012-09-13 13:58:05 +08:00
|
|
|
}
|
|
|
|
|
2011-11-04 16:41:56 +08:00
|
|
|
return 0;
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
2003-11-24 07:20:42 +08:00
|
|
|
}
|
2012-11-03 05:51:40 +08:00
|
|
|
|
|
|
|
static inline const char *
|
2018-09-24 02:10:46 +08:00
|
|
|
ev_focus_mode_name(xcb_focus_in_event_t* ev) {
|
2012-11-03 05:51:40 +08:00
|
|
|
switch (ev->mode) {
|
|
|
|
CASESTRRET(NotifyNormal);
|
|
|
|
CASESTRRET(NotifyWhileGrabbed);
|
|
|
|
CASESTRRET(NotifyGrab);
|
|
|
|
CASESTRRET(NotifyUngrab);
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const char *
|
2018-09-24 02:10:46 +08:00
|
|
|
ev_focus_detail_name(xcb_focus_in_event_t* ev) {
|
2012-11-03 05:51:40 +08:00
|
|
|
switch (ev->detail) {
|
|
|
|
CASESTRRET(NotifyAncestor);
|
|
|
|
CASESTRRET(NotifyVirtual);
|
|
|
|
CASESTRRET(NotifyInferior);
|
|
|
|
CASESTRRET(NotifyNonlinear);
|
|
|
|
CASESTRRET(NotifyNonlinearVirtual);
|
|
|
|
CASESTRRET(NotifyPointer);
|
|
|
|
CASESTRRET(NotifyPointerRoot);
|
|
|
|
CASESTRRET(NotifyDetailNone);
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
2018-12-20 04:50:02 +08:00
|
|
|
static inline void attr_unused
|
2018-09-24 02:10:46 +08:00
|
|
|
ev_focus_report(xcb_focus_in_event_t *ev) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_trace("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev),
|
2012-11-03 05:51:40 +08:00
|
|
|
ev_focus_detail_name(ev));
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Events ===
|
2012-02-09 17:37:46 +08:00
|
|
|
|
2012-11-03 22:02:07 +08:00
|
|
|
/**
|
|
|
|
* Determine whether we should respond to a <code>FocusIn/Out</code>
|
|
|
|
* event.
|
|
|
|
*/
|
2014-04-19 19:41:26 +08:00
|
|
|
/*
|
2012-11-03 05:51:40 +08:00
|
|
|
inline static bool
|
|
|
|
ev_focus_accept(XFocusChangeEvent *ev) {
|
2013-09-18 21:50:57 +08:00
|
|
|
return NotifyNormal == ev->mode || NotifyUngrab == ev->mode;
|
2012-11-03 05:51:40 +08:00
|
|
|
}
|
2014-04-19 19:41:26 +08:00
|
|
|
*/
|
2012-11-03 05:51:40 +08:00
|
|
|
|
2013-09-18 21:50:57 +08:00
|
|
|
static inline void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) {
|
2012-11-03 05:51:40 +08:00
|
|
|
#ifdef DEBUG_EVENTS
|
|
|
|
ev_focus_report(ev);
|
|
|
|
#endif
|
|
|
|
|
2013-10-21 22:17:01 +08:00
|
|
|
recheck_focus(ps);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) {
|
2012-11-03 05:51:40 +08:00
|
|
|
#ifdef DEBUG_EVENTS
|
|
|
|
ev_focus_report(ev);
|
|
|
|
#endif
|
|
|
|
|
2013-10-21 22:17:01 +08:00
|
|
|
recheck_focus(ps);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) {
|
2012-11-19 09:46:07 +08:00
|
|
|
assert(ev->parent == ps->root);
|
2012-11-21 09:15:49 +08:00
|
|
|
add_win(ps, ev->window, 0);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) {
|
2019-02-20 08:17:23 +08:00
|
|
|
log_trace("{ send_event: %d, id: %#010x, above: %#010x, override_redirect: %d }",
|
|
|
|
ev->event, ev->window, ev->above_sibling, ev->override_redirect);
|
2012-11-19 09:46:07 +08:00
|
|
|
configure_win(ps, ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *ev) {
|
2019-02-09 23:50:40 +08:00
|
|
|
win *w = find_win(ps, ev->window);
|
|
|
|
if (w) {
|
|
|
|
unmap_win(ps, &w, true);
|
|
|
|
}
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) {
|
2019-02-21 10:29:06 +08:00
|
|
|
map_win_by_id(ps, ev->window);
|
2019-02-09 23:50:40 +08:00
|
|
|
// FocusIn/Out may be ignored when the window is unmapped, so we must
|
|
|
|
// recheck focus here
|
|
|
|
if (ps->o.track_focus) {
|
|
|
|
recheck_focus(ps);
|
|
|
|
}
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) {
|
2013-01-29 09:57:04 +08:00
|
|
|
win *w = find_win(ps, ev->window);
|
2019-02-09 23:50:40 +08:00
|
|
|
if (w) {
|
|
|
|
unmap_win(ps, &w, false);
|
|
|
|
}
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_trace("{ new_parent: %#010x, override_redirect: %d }",
|
|
|
|
ev->parent, ev->override_redirect);
|
2013-03-03 21:53:08 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ev->parent == ps->root) {
|
2019-02-09 23:50:40 +08:00
|
|
|
// new window
|
2012-11-21 09:15:49 +08:00
|
|
|
add_win(ps, ev->window, 0);
|
2012-02-09 17:37:46 +08:00
|
|
|
} else {
|
2019-02-09 23:50:40 +08:00
|
|
|
// otherwise, find and destroy the window first
|
|
|
|
win *w = find_win(ps, ev->window);
|
|
|
|
if (w) {
|
|
|
|
unmap_win(ps, &w, true);
|
|
|
|
}
|
2012-12-07 22:38:10 +08:00
|
|
|
|
2012-09-13 22:30:18 +08:00
|
|
|
// Reset event mask in case something wrong happens
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK,
|
2018-10-03 20:34:24 +08:00
|
|
|
(const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) });
|
2012-12-07 22:38:10 +08:00
|
|
|
|
|
|
|
// Check if the window is an undetected client window
|
|
|
|
// Firstly, check if it's a known client window
|
|
|
|
if (!find_toplevel(ps, ev->window)) {
|
|
|
|
// If not, look for its frame window
|
|
|
|
win *w_top = find_toplevel2(ps, ev->parent);
|
2012-12-08 11:10:08 +08:00
|
|
|
// If found, and the client window has not been determined, or its
|
|
|
|
// frame may not have a correct client, continue
|
|
|
|
if (w_top && (!w_top->client_win
|
|
|
|
|| w_top->client_win == w_top->id)) {
|
2012-12-07 22:38:10 +08:00
|
|
|
// If it has WM_STATE, mark it the client window
|
|
|
|
if (wid_has_prop(ps, ev->window, ps->atom_client)) {
|
|
|
|
w_top->wmwin = false;
|
|
|
|
win_unmark_client(ps, w_top);
|
|
|
|
win_mark_client(ps, w_top, ev->window);
|
|
|
|
}
|
|
|
|
// Otherwise, watch for WM_STATE on it
|
|
|
|
else {
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) {
|
2018-10-04 15:15:38 +08:00
|
|
|
determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | XCB_EVENT_MASK_PROPERTY_CHANGE });
|
2012-12-07 22:38:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_circulate_notify(session_t *ps, xcb_circulate_notify_event_t *ev) {
|
2012-11-19 09:46:07 +08:00
|
|
|
circulate_win(ps, ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_expose(session_t *ps, xcb_expose_event_t *ev) {
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ev->window == ps->root || (ps->overlay && ev->window == ps->overlay)) {
|
2012-02-09 17:37:46 +08:00
|
|
|
int more = ev->count + 1;
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->n_expose == ps->size_expose) {
|
|
|
|
if (ps->expose_rects) {
|
2018-12-16 02:47:21 +08:00
|
|
|
ps->expose_rects = crealloc(ps->expose_rects, ps->size_expose + more);
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->size_expose += more;
|
2012-02-09 17:37:46 +08:00
|
|
|
} else {
|
2018-12-16 02:47:21 +08:00
|
|
|
ps->expose_rects = ccalloc(more, rect_t);
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->size_expose = more;
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
ps->expose_rects[ps->n_expose].x1 = ev->x;
|
|
|
|
ps->expose_rects[ps->n_expose].y1 = ev->y;
|
|
|
|
ps->expose_rects[ps->n_expose].x2 = ev->x + ev->width;
|
|
|
|
ps->expose_rects[ps->n_expose].y2 = ev->y + ev->height;
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->n_expose++;
|
2012-02-09 17:37:46 +08:00
|
|
|
|
|
|
|
if (ev->count == 0) {
|
2012-11-19 09:46:07 +08:00
|
|
|
expose_root(ps, ps->expose_rects, ps->n_expose);
|
|
|
|
ps->n_expose = 0;
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-04 18:11:08 +08:00
|
|
|
/**
|
|
|
|
* Update current active window based on EWMH _NET_ACTIVE_WIN.
|
|
|
|
*
|
|
|
|
* Does not change anything if we fail to get the attribute or the window
|
|
|
|
* returned could not be found.
|
|
|
|
*/
|
|
|
|
static void
|
2012-11-19 09:46:07 +08:00
|
|
|
update_ewmh_active_win(session_t *ps) {
|
2012-11-04 18:11:08 +08:00
|
|
|
// Search for the window
|
2018-12-28 04:45:38 +08:00
|
|
|
xcb_window_t wid = wid_get_prop_window(ps, ps->root, ps->atom_ewmh_active_win);
|
2013-09-18 21:50:57 +08:00
|
|
|
win *w = find_win_all(ps, wid);
|
2012-11-04 18:11:08 +08:00
|
|
|
|
2013-09-18 21:50:57 +08:00
|
|
|
// Mark the window focused. No need to unfocus the previous one.
|
|
|
|
if (w) win_set_focused(ps, w, true);
|
2012-11-04 18:11:08 +08:00
|
|
|
}
|
|
|
|
|
2012-02-09 17:37:46 +08:00
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) {
|
2013-03-01 12:41:16 +08:00
|
|
|
#ifdef DEBUG_EVENTS
|
|
|
|
{
|
|
|
|
// Print out changed atom
|
2018-10-03 20:54:03 +08:00
|
|
|
xcb_get_atom_name_reply_t *reply =
|
|
|
|
xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, ev->atom), NULL);
|
|
|
|
const char *name = "?";
|
|
|
|
int name_len = 1;
|
|
|
|
if (reply) {
|
|
|
|
name = xcb_get_atom_name_name(reply);
|
|
|
|
name_len = xcb_get_atom_name_name_length(reply);
|
|
|
|
}
|
|
|
|
|
2018-12-20 10:49:29 +08:00
|
|
|
log_trace("{ atom = %.*s }", name_len, name);
|
2018-10-03 20:54:03 +08:00
|
|
|
free(reply);
|
2013-03-01 12:41:16 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->root == ev->window) {
|
|
|
|
if (ps->o.track_focus && ps->o.use_ewmh_active_win
|
|
|
|
&& ps->atom_ewmh_active_win == ev->atom) {
|
|
|
|
update_ewmh_active_win(ps);
|
2019-02-07 08:30:32 +08:00
|
|
|
} else {
|
2012-11-04 18:11:08 +08:00
|
|
|
// Destroy the root "image" if the wallpaper probably changed
|
2019-02-07 08:30:32 +08:00
|
|
|
if (x_is_root_back_pixmap_atom(ps, ev->atom)) {
|
2012-11-19 09:46:07 +08:00
|
|
|
root_damaged(ps);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-04 18:11:08 +08:00
|
|
|
|
2012-10-24 10:09:59 +08:00
|
|
|
// Unconcerned about any other proprties on root window
|
|
|
|
return;
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
2012-12-07 22:38:10 +08:00
|
|
|
// If WM_STATE changes
|
|
|
|
if (ev->atom == ps->atom_client) {
|
|
|
|
// Check whether it could be a client window
|
|
|
|
if (!find_toplevel(ps, ev->window)) {
|
|
|
|
// Reset event mask anyway
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) {
|
2018-10-03 20:34:24 +08:00
|
|
|
determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) });
|
2012-12-07 22:38:10 +08:00
|
|
|
|
|
|
|
win *w_top = find_toplevel2(ps, ev->window);
|
2012-12-10 10:31:24 +08:00
|
|
|
// Initialize client_win as early as possible
|
|
|
|
if (w_top && (!w_top->client_win || w_top->client_win == w_top->id)
|
2012-12-07 22:38:10 +08:00
|
|
|
&& wid_has_prop(ps, ev->window, ps->atom_client)) {
|
|
|
|
w_top->wmwin = false;
|
|
|
|
win_unmark_client(ps, w_top);
|
|
|
|
win_mark_client(ps, w_top, ev->window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-15 11:07:49 +08:00
|
|
|
// If _NET_WM_WINDOW_TYPE changes... God knows why this would happen, but
|
|
|
|
// there are always some stupid applications. (#144)
|
|
|
|
if (ev->atom == ps->atom_win_type) {
|
|
|
|
win *w = NULL;
|
|
|
|
if ((w = find_toplevel(ps, ev->window)))
|
2019-02-21 22:08:08 +08:00
|
|
|
win_update_wintype(ps, w);
|
2013-09-15 11:07:49 +08:00
|
|
|
}
|
|
|
|
|
2012-10-03 21:13:34 +08:00
|
|
|
// If _NET_WM_OPACITY changes
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ev->atom == ps->atom_opacity) {
|
2018-08-12 01:22:49 +08:00
|
|
|
win *w = find_win(ps, ev->window) ?: find_toplevel(ps, ev->window);
|
2012-02-09 17:37:46 +08:00
|
|
|
if (w) {
|
2018-08-12 01:22:49 +08:00
|
|
|
win_update_opacity_prop(ps, w);
|
2019-02-09 23:50:40 +08:00
|
|
|
// we cannot receive OPACITY change when window is destroyed
|
|
|
|
assert(w->state != WSTATE_DESTROYING);
|
|
|
|
if (w->state == WSTATE_MAPPED) {
|
|
|
|
// See the winstate_t transition table
|
|
|
|
w->state = WSTATE_FADING;
|
|
|
|
}
|
2019-02-21 22:08:08 +08:00
|
|
|
w->opacity_tgt = win_calc_opacity_target(ps, w);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-22 11:42:39 +08:00
|
|
|
// If frame extents property changes
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.frame_opacity && ev->atom == ps->atom_frame_extents) {
|
|
|
|
win *w = find_toplevel(ps, ev->window);
|
2012-02-09 17:37:46 +08:00
|
|
|
if (w) {
|
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-30 11:56:00 +08:00
|
|
|
win_update_frame_extents(ps, w, ev->window);
|
2012-09-20 13:50:27 +08:00
|
|
|
// If frame extents change, the window needs repaint
|
2018-09-07 02:17:26 +08:00
|
|
|
add_damage_from_win(ps, w);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
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-22 11:42:39 +08:00
|
|
|
|
|
|
|
// If name changes
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.track_wdata
|
|
|
|
&& (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) {
|
|
|
|
win *w = find_toplevel(ps, ev->window);
|
2012-11-28 11:44:00 +08:00
|
|
|
if (w && 1 == win_get_name(ps, w)) {
|
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 21:39:38 +08:00
|
|
|
win_on_factor_change(ps, w);
|
2012-11-28 11:44:00 +08:00
|
|
|
}
|
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-22 11:42:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If class changes
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.track_wdata && ps->atom_class == ev->atom) {
|
|
|
|
win *w = find_toplevel(ps, ev->window);
|
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-22 11:42:39 +08:00
|
|
|
if (w) {
|
2012-11-19 09:46:07 +08:00
|
|
|
win_get_class(ps, w);
|
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 21:39:38 +08:00
|
|
|
win_on_factor_change(ps, w);
|
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-22 11:42:39 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-09 11:35:40 +08:00
|
|
|
|
2012-12-05 18:12:21 +08:00
|
|
|
// If role changes
|
|
|
|
if (ps->o.track_wdata && ps->atom_role == ev->atom) {
|
|
|
|
win *w = find_toplevel(ps, ev->window);
|
|
|
|
if (w && 1 == win_get_role(ps, w)) {
|
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 21:39:38 +08:00
|
|
|
win_on_factor_change(ps, w);
|
2012-12-05 18:12:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-09 11:35:40 +08:00
|
|
|
// If _COMPTON_SHADOW changes
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.respect_prop_shadow && ps->atom_compton_shadow == ev->atom) {
|
|
|
|
win *w = find_win(ps, ev->window);
|
2012-11-09 11:35:40 +08:00
|
|
|
if (w)
|
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-08 08:50:58 +08:00
|
|
|
win_update_prop_shadow(ps, w);
|
2012-11-09 11:35:40 +08:00
|
|
|
}
|
2012-12-12 12:01:51 +08:00
|
|
|
|
|
|
|
// If a leader property changes
|
|
|
|
if ((ps->o.detect_transient && ps->atom_transient == ev->atom)
|
|
|
|
|| (ps->o.detect_client_leader && ps->atom_client_leader == ev->atom)) {
|
|
|
|
win *w = find_toplevel(ps, ev->window);
|
|
|
|
if (w) {
|
|
|
|
win_update_leader(ps, w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
// Check for other atoms we are tracking
|
|
|
|
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) {
|
|
|
|
if (platom->atom == ev->atom) {
|
|
|
|
win *w = find_win(ps, ev->window);
|
|
|
|
if (!w)
|
|
|
|
w = find_toplevel(ps, ev->window);
|
|
|
|
if (w)
|
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 21:39:38 +08:00
|
|
|
win_on_factor_change(ps, w);
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_damage_notify(session_t *ps, xcb_damage_notify_event_t *de) {
|
2018-09-09 09:29:45 +08:00
|
|
|
/*
|
|
|
|
if (ps->root == de->drawable) {
|
|
|
|
root_damaged();
|
|
|
|
return;
|
|
|
|
} */
|
|
|
|
|
|
|
|
win *w = find_win(ps, de->drawable);
|
|
|
|
|
|
|
|
if (!w) return;
|
|
|
|
|
2018-09-23 02:43:35 +08:00
|
|
|
repair_win(ps, w);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
2012-09-13 13:58:05 +08:00
|
|
|
inline static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_shape_notify(session_t *ps, xcb_shape_notify_event_t *ev) {
|
|
|
|
win *w = find_win(ps, ev->affected_window);
|
2018-11-05 02:54:04 +08:00
|
|
|
if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED) return;
|
2012-09-11 21:33:03 +08:00
|
|
|
|
|
|
|
/*
|
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-30 11:56:00 +08:00
|
|
|
* Empty bounding_shape may indicated an
|
2012-09-11 21:33:03 +08:00
|
|
|
* unmapped/destroyed window, in which case
|
|
|
|
* seemingly BadRegion errors would be triggered
|
|
|
|
* if we attempt to rebuild border_size
|
|
|
|
*/
|
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-30 11:56:00 +08:00
|
|
|
// Mark the old border_size as damaged
|
2018-10-13 08:17:59 +08:00
|
|
|
region_t tmp = win_get_bounding_shape_global_by_val(w);
|
|
|
|
add_damage(ps, &tmp);
|
|
|
|
pixman_region32_fini(&tmp);
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
win_update_bounding_shape(ps, w);
|
2018-10-13 08:17:59 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
// Mark the new border_size as damaged
|
2018-10-13 08:17:59 +08:00
|
|
|
tmp = win_get_bounding_shape_global_by_val(w);
|
|
|
|
add_damage(ps, &tmp);
|
|
|
|
pixman_region32_fini(&tmp);
|
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
w->reg_ignore_valid = false;
|
2012-09-11 21:33:03 +08: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-08 10:20:01 +08:00
|
|
|
/**
|
|
|
|
* Handle ScreenChangeNotify events from X RandR extension.
|
|
|
|
*/
|
|
|
|
static void
|
2012-11-21 09:15:49 +08:00
|
|
|
ev_screen_change_notify(session_t *ps,
|
2018-12-20 04:50:02 +08:00
|
|
|
xcb_randr_screen_change_notify_event_t attr_unused *ev) {
|
2013-08-28 21:47:16 +08:00
|
|
|
if (ps->o.xinerama_shadow_crop)
|
|
|
|
cxinerama_upd_scrs(ps);
|
|
|
|
|
|
|
|
if (ps->o.sw_opti && !ps->o.refresh_rate) {
|
2012-11-19 09:46:07 +08:00
|
|
|
update_refresh_rate(ps);
|
|
|
|
if (!ps->refresh_rate) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_warn("Refresh rate detection failed. swopti will be temporarily disabled");
|
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-08 10:20:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-24 18:42:16 +08:00
|
|
|
inline static void
|
|
|
|
ev_selection_clear(session_t *ps,
|
2018-12-20 04:50:02 +08:00
|
|
|
xcb_selection_clear_event_t attr_unused *ev) {
|
2015-10-24 18:42:16 +08:00
|
|
|
// The only selection we own is the _NET_WM_CM_Sn selection.
|
|
|
|
// If we lose that one, we should exit.
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Another composite manager started and took the _NET_WM_CM_Sn selection.");
|
2015-10-24 18:42:16 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2012-11-14 21:34:51 +08:00
|
|
|
/**
|
|
|
|
* Get a window's name from window ID.
|
|
|
|
*/
|
2018-12-20 04:50:02 +08:00
|
|
|
static inline void attr_unused
|
2018-12-28 04:45:38 +08:00
|
|
|
ev_window_name(session_t *ps, xcb_window_t wid, char **name) {
|
2012-11-14 21:34:51 +08:00
|
|
|
*name = "";
|
|
|
|
if (wid) {
|
|
|
|
*name = "(Failed to get title)";
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->root == wid)
|
2012-11-14 21:34:51 +08:00
|
|
|
*name = "(Root window)";
|
2012-11-19 09:46:07 +08:00
|
|
|
else if (ps->overlay == wid)
|
2012-11-14 21:34:51 +08:00
|
|
|
*name = "(Overlay)";
|
|
|
|
else {
|
2012-11-19 09:46:07 +08:00
|
|
|
win *w = find_win(ps, wid);
|
2012-11-14 21:34:51 +08:00
|
|
|
if (!w)
|
2012-11-19 09:46:07 +08:00
|
|
|
w = find_toplevel(ps, wid);
|
2012-11-14 21:34:51 +08:00
|
|
|
|
2018-09-09 09:29:45 +08:00
|
|
|
if (w)
|
|
|
|
win_get_name(ps, w);
|
2012-11-14 21:34:51 +08:00
|
|
|
if (w && w->name)
|
|
|
|
*name = w->name;
|
2018-09-09 09:29:45 +08:00
|
|
|
else
|
|
|
|
*name = "unknown";
|
2012-11-14 21:34:51 +08: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-08 10:20:01 +08:00
|
|
|
static void
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_handle(session_t *ps, xcb_generic_event_t *ev) {
|
|
|
|
if ((ev->response_type & 0x7f) != KeymapNotify) {
|
|
|
|
discard_ignore(ps, ev->full_sequence);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
|
2012-09-12 09:08:15 +08:00
|
|
|
#ifdef DEBUG_EVENTS
|
2018-10-03 04:24:34 +08:00
|
|
|
if (ev->response_type != ps->damage_event + XCB_DAMAGE_NOTIFY) {
|
2018-12-28 04:45:38 +08:00
|
|
|
xcb_window_t wid = ev_window(ps, ev);
|
2012-11-14 21:34:51 +08:00
|
|
|
char *window_name = NULL;
|
2018-09-09 09:29:45 +08:00
|
|
|
ev_window_name(ps, wid, &window_name);
|
2012-09-13 13:58:05 +08:00
|
|
|
|
2018-12-20 10:49:29 +08:00
|
|
|
log_trace("event %10.10s serial %#010x window %#010lx \"%s\"",
|
|
|
|
ev_name(ps, ev), ev_serial(ev), wid, window_name);
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-11-11 05:52:42 +08:00
|
|
|
// Check if a custom XEvent constructor was registered in xlib for this event
|
|
|
|
// type, and call it discarding the constructed XEvent if any. XESetWireToEvent
|
|
|
|
// might be used by libraries to intercept messages from the X server e.g. the
|
|
|
|
// OpenGL lib waiting for DRI2 events.
|
|
|
|
|
|
|
|
// XXX This exists to workaround compton issue #33, #34, #47
|
|
|
|
// For even more details, see:
|
|
|
|
// https://bugs.freedesktop.org/show_bug.cgi?id=35945
|
|
|
|
// https://lists.freedesktop.org/archives/xcb/2011-November/007337.html
|
|
|
|
auto proc = XESetWireToEvent(ps->dpy, ev->response_type, 0);
|
|
|
|
if (proc) {
|
|
|
|
XESetWireToEvent(ps->dpy, ev->response_type, proc);
|
|
|
|
XEvent dummy;
|
|
|
|
|
|
|
|
// Stop Xlib from complaining about lost sequence numbers.
|
|
|
|
// proc might also just be Xlib internal event processing functions, and
|
|
|
|
// because they probably won't see all X replies, they will complain about
|
|
|
|
// missing sequence numbers.
|
2018-12-17 08:45:13 +08:00
|
|
|
//
|
|
|
|
// We only need the low 16 bits
|
|
|
|
ev->sequence = (uint16_t)(LastKnownRequestProcessed(ps->dpy) & 0xffff);
|
2018-11-11 05:52:42 +08:00
|
|
|
proc(ps->dpy, &dummy, (xEvent *)ev);
|
|
|
|
}
|
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
// XXX redraw needs to be more fine grained
|
|
|
|
queue_redraw(ps);
|
|
|
|
|
2018-09-23 06:44:44 +08:00
|
|
|
switch (ev->response_type) {
|
2012-02-09 17:37:46 +08:00
|
|
|
case FocusIn:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_focus_in(ps, (xcb_focus_in_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case FocusOut:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_focus_out(ps, (xcb_focus_out_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case CreateNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_create_notify(ps, (xcb_create_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case ConfigureNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_configure_notify(ps, (xcb_configure_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case DestroyNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_destroy_notify(ps, (xcb_destroy_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case MapNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_map_notify(ps, (xcb_map_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case UnmapNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_unmap_notify(ps, (xcb_unmap_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case ReparentNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_reparent_notify(ps, (xcb_reparent_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case CirculateNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_circulate_notify(ps, (xcb_circulate_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case Expose:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_expose(ps, (xcb_expose_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
|
|
|
case PropertyNotify:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_property_notify(ps, (xcb_property_notify_event_t *)ev);
|
2012-02-09 17:37:46 +08:00
|
|
|
break;
|
2015-10-24 18:42:16 +08:00
|
|
|
case SelectionClear:
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev);
|
2015-10-24 18:42:16 +08:00
|
|
|
break;
|
2018-09-29 17:11:43 +08:00
|
|
|
case 0:
|
|
|
|
ev_xcb_error(ps, (xcb_generic_error_t *)ev);
|
|
|
|
break;
|
2012-02-09 17:37:46 +08:00
|
|
|
default:
|
2018-09-23 06:44:44 +08:00
|
|
|
if (ps->shape_exists && ev->response_type == ps->shape_event) {
|
|
|
|
ev_shape_notify(ps, (xcb_shape_notify_event_t *) ev);
|
2012-09-11 21:33:03 +08:00
|
|
|
break;
|
|
|
|
}
|
2018-09-27 23:38:24 +08:00
|
|
|
if (ps->randr_exists && ev->response_type == (ps->randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) {
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_screen_change_notify(ps, (xcb_randr_screen_change_notify_event_t *) ev);
|
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-08 10:20:01 +08:00
|
|
|
break;
|
|
|
|
}
|
2018-09-27 23:29:51 +08:00
|
|
|
if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) {
|
2018-09-23 06:44:44 +08:00
|
|
|
ev_damage_notify(ps, (xcb_damage_notify_event_t *) ev);
|
2013-09-04 22:00:51 +08:00
|
|
|
break;
|
2012-02-09 17:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// === Main ===
|
2012-02-09 17:37:46 +08:00
|
|
|
|
2004-06-27 13:08:33 +08: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-08 10:20:01 +08:00
|
|
|
/**
|
|
|
|
* Register a window as symbol, and initialize GLX context if wanted.
|
|
|
|
*/
|
2013-01-30 13:41:08 +08:00
|
|
|
static bool
|
2013-03-01 12:41:16 +08:00
|
|
|
register_cm(session_t *ps) {
|
2013-01-31 22:53:44 +08:00
|
|
|
assert(!ps->reg_win);
|
|
|
|
|
2013-03-01 12:41:16 +08:00
|
|
|
ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0,
|
2018-12-28 04:45:38 +08:00
|
|
|
XCB_NONE, XCB_NONE);
|
2006-09-07 01:04:47 +08:00
|
|
|
|
2013-01-30 13:41:08 +08:00
|
|
|
if (!ps->reg_win) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Failed to create window.");
|
2013-01-30 13:41:08 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2013-01-31 22:53:44 +08:00
|
|
|
// Unredirect the window if it's redirected, just in case
|
|
|
|
if (ps->redirected)
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_composite_unredirect_window(ps->c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL);
|
2013-01-31 22:53:44 +08:00
|
|
|
|
2013-11-10 10:13:18 +08:00
|
|
|
{
|
|
|
|
XClassHint *h = XAllocClassHint();
|
|
|
|
if (h) {
|
|
|
|
h->res_name = "compton";
|
|
|
|
h->res_class = "xcompmgr";
|
|
|
|
}
|
|
|
|
Xutf8SetWMProperties(ps->dpy, ps->reg_win, "xcompmgr", "xcompmgr",
|
|
|
|
NULL, 0, NULL, NULL, h);
|
|
|
|
cxfree(h);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set _NET_WM_PID
|
|
|
|
{
|
2018-10-03 20:13:59 +08:00
|
|
|
uint32_t pid = getpid();
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
|
2018-10-03 20:13:59 +08:00
|
|
|
get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, &pid);
|
2013-11-10 10:13:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set COMPTON_VERSION
|
2018-12-20 10:49:29 +08:00
|
|
|
if (!wid_set_text_prop(ps, ps->reg_win, get_atom(ps, "COMPTON_VERSION"),
|
|
|
|
COMPTON_VERSION)) {
|
|
|
|
log_error("Failed to set COMPTON_VERSION.");
|
2013-11-10 10:13:18 +08:00
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2014-07-13 09:34:38 +08:00
|
|
|
// Acquire X Selection _NET_WM_CM_S?
|
|
|
|
if (!ps->o.no_x_selection) {
|
2013-01-30 13:41:08 +08:00
|
|
|
unsigned len = strlen(REGISTER_PROP) + 2;
|
|
|
|
int s = ps->scr;
|
2015-10-24 18:32:55 +08:00
|
|
|
Atom atom;
|
2013-01-30 13:41:08 +08:00
|
|
|
|
|
|
|
while (s >= 10) {
|
|
|
|
++len;
|
|
|
|
s /= 10;
|
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-12-16 02:47:21 +08:00
|
|
|
auto buf = ccalloc(len, char);
|
2013-01-30 13:41:08 +08:00
|
|
|
snprintf(buf, len, REGISTER_PROP "%d", ps->scr);
|
|
|
|
buf[len - 1] = '\0';
|
2015-10-24 18:32:55 +08:00
|
|
|
atom = get_atom(ps, buf);
|
2018-10-03 20:20:33 +08:00
|
|
|
free(buf);
|
|
|
|
|
|
|
|
xcb_get_selection_owner_reply_t *reply =
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_get_selection_owner_reply(ps->c,
|
|
|
|
xcb_get_selection_owner(ps->c, atom), NULL);
|
2015-10-24 18:32:55 +08:00
|
|
|
|
2018-10-03 20:20:33 +08:00
|
|
|
if (reply && reply->owner != XCB_NONE) {
|
|
|
|
free(reply);
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Another composite manager is already running");
|
2015-10-24 18:32:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
2018-10-03 20:20:33 +08:00
|
|
|
free(reply);
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_set_selection_owner(ps->c, ps->reg_win, atom, 0);
|
2013-01-30 13:41:08 +08:00
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2013-01-30 13:41:08 +08:00
|
|
|
return true;
|
2005-10-07 08:08:02 +08:00
|
|
|
}
|
|
|
|
|
2013-11-09 21:38:31 +08:00
|
|
|
/**
|
|
|
|
* Write PID to a file.
|
|
|
|
*/
|
|
|
|
static inline bool
|
|
|
|
write_pid(session_t *ps) {
|
|
|
|
if (!ps->o.write_pid_path)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
FILE *f = fopen(ps->o.write_pid_path, "w");
|
|
|
|
if (unlikely(!f)) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_error("Failed to write PID to \"%s\".", ps->o.write_pid_path);
|
2013-11-09 21:38:31 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(f, "%ld\n", (long) getpid());
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
/**
|
|
|
|
* Fetch all required atoms and save them to a session.
|
|
|
|
*/
|
2012-09-25 10:19:20 +08:00
|
|
|
static void
|
2012-11-19 09:46:07 +08:00
|
|
|
init_atoms(session_t *ps) {
|
2013-01-09 20:25:01 +08:00
|
|
|
ps->atom_opacity = get_atom(ps, "_NET_WM_WINDOW_OPACITY");
|
|
|
|
ps->atom_frame_extents = get_atom(ps, "_NET_FRAME_EXTENTS");
|
|
|
|
ps->atom_client = get_atom(ps, "WM_STATE");
|
2018-10-03 01:53:28 +08:00
|
|
|
ps->atom_name = XCB_ATOM_WM_NAME;
|
2013-01-09 20:25:01 +08:00
|
|
|
ps->atom_name_ewmh = get_atom(ps, "_NET_WM_NAME");
|
2018-10-03 01:53:28 +08:00
|
|
|
ps->atom_class = XCB_ATOM_WM_CLASS;
|
2013-01-09 20:25:01 +08:00
|
|
|
ps->atom_role = get_atom(ps, "WM_WINDOW_ROLE");
|
2018-10-03 01:53:28 +08:00
|
|
|
ps->atom_transient = XCB_ATOM_WM_TRANSIENT_FOR;
|
2013-01-09 20:25:01 +08:00
|
|
|
ps->atom_client_leader = get_atom(ps, "WM_CLIENT_LEADER");
|
|
|
|
ps->atom_ewmh_active_win = get_atom(ps, "_NET_ACTIVE_WINDOW");
|
|
|
|
ps->atom_compton_shadow = get_atom(ps, "_COMPTON_SHADOW");
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2013-01-09 20:25:01 +08:00
|
|
|
ps->atom_win_type = get_atom(ps, "_NET_WM_WINDOW_TYPE");
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->atoms_wintypes[WINTYPE_UNKNOWN] = 0;
|
2013-01-09 20:25:01 +08:00
|
|
|
ps->atoms_wintypes[WINTYPE_DESKTOP] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_DESKTOP");
|
|
|
|
ps->atoms_wintypes[WINTYPE_DOCK] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_DOCK");
|
|
|
|
ps->atoms_wintypes[WINTYPE_TOOLBAR] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_TOOLBAR");
|
|
|
|
ps->atoms_wintypes[WINTYPE_MENU] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_MENU");
|
|
|
|
ps->atoms_wintypes[WINTYPE_UTILITY] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_UTILITY");
|
|
|
|
ps->atoms_wintypes[WINTYPE_SPLASH] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_SPLASH");
|
|
|
|
ps->atoms_wintypes[WINTYPE_DIALOG] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_DIALOG");
|
|
|
|
ps->atoms_wintypes[WINTYPE_NORMAL] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_NORMAL");
|
|
|
|
ps->atoms_wintypes[WINTYPE_DROPDOWN_MENU] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
|
|
|
|
ps->atoms_wintypes[WINTYPE_POPUP_MENU] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_POPUP_MENU");
|
|
|
|
ps->atoms_wintypes[WINTYPE_TOOLTIP] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_TOOLTIP");
|
|
|
|
ps->atoms_wintypes[WINTYPE_NOTIFY] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_NOTIFICATION");
|
|
|
|
ps->atoms_wintypes[WINTYPE_COMBO] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_COMBO");
|
|
|
|
ps->atoms_wintypes[WINTYPE_DND] = get_atom(ps,
|
|
|
|
"_NET_WM_WINDOW_TYPE_DND");
|
2012-09-25 10:19:20 +08: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-08 10:20:01 +08:00
|
|
|
/**
|
|
|
|
* Update refresh rate info with X Randr extension.
|
|
|
|
*/
|
|
|
|
static void
|
2012-11-19 09:46:07 +08:00
|
|
|
update_refresh_rate(session_t *ps) {
|
2018-09-27 23:38:24 +08:00
|
|
|
xcb_randr_get_screen_info_reply_t *randr_info =
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_randr_get_screen_info_reply(ps->c,
|
|
|
|
xcb_randr_get_screen_info(ps->c, ps->root), NULL);
|
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-08 10:20:01 +08:00
|
|
|
|
2018-09-27 23:38:24 +08:00
|
|
|
if (!randr_info)
|
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-08 10:20:01 +08:00
|
|
|
return;
|
2018-09-27 23:38:24 +08:00
|
|
|
ps->refresh_rate = randr_info->rate;
|
|
|
|
free(randr_info);
|
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-08 10:20:01 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->refresh_rate)
|
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-08 08:50:58 +08:00
|
|
|
ps->refresh_intv = US_PER_SEC / ps->refresh_rate;
|
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-08 10:20:01 +08:00
|
|
|
else
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->refresh_intv = 0;
|
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-08 10:20:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-10-26 11:12:28 +08:00
|
|
|
* Initialize refresh-rated based software optimization.
|
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-08 10:20:01 +08:00
|
|
|
*
|
2012-11-19 09:46:07 +08:00
|
|
|
* @return true for success, false otherwise
|
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-08 10:20:01 +08:00
|
|
|
*/
|
2012-11-19 09:46:07 +08:00
|
|
|
static bool
|
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-08 08:50:58 +08:00
|
|
|
swopti_init(session_t *ps) {
|
2019-02-21 11:42:03 +08:00
|
|
|
log_warn("--sw-opti is going to be deprecated. If you get real benefits from using "
|
|
|
|
"this option, please open an issue to let us know.");
|
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-08 10:20:01 +08:00
|
|
|
// Prepare refresh rate
|
|
|
|
// Check if user provides one
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->refresh_rate = ps->o.refresh_rate;
|
|
|
|
if (ps->refresh_rate)
|
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-08 08:50:58 +08:00
|
|
|
ps->refresh_intv = US_PER_SEC / ps->refresh_rate;
|
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-08 10:20:01 +08:00
|
|
|
|
|
|
|
// Auto-detect refresh rate otherwise
|
2012-11-19 09:46:07 +08:00
|
|
|
if (!ps->refresh_rate && ps->randr_exists) {
|
|
|
|
update_refresh_rate(ps);
|
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-08 10:20:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Turn off vsync_sw if we can't get the refresh rate
|
2012-11-19 09:46:07 +08:00
|
|
|
if (!ps->refresh_rate)
|
|
|
|
return false;
|
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-08 10:20:01 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
return true;
|
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-08 10:20:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
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-08 08:50:58 +08:00
|
|
|
* Modify a struct timeval timeout value to render at a fixed pace.
|
2012-10-26 11:12:28 +08:00
|
|
|
*
|
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-08 08:50:58 +08:00
|
|
|
* @param ps current session
|
|
|
|
* @param[in,out] ptv pointer to the timeout
|
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-08 10:20:01 +08:00
|
|
|
*/
|
2018-10-03 03:22:26 +08:00
|
|
|
static double
|
|
|
|
swopti_handle_timeout(session_t *ps) {
|
2018-11-27 00:53:57 +08:00
|
|
|
if (!ps->refresh_intv)
|
|
|
|
return 0;
|
|
|
|
|
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-08 08:50:58 +08:00
|
|
|
// Get the microsecond offset of the time when the we reach the timeout
|
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-08 10:20:01 +08:00
|
|
|
// I don't think a 32-bit long could overflow here.
|
2018-10-03 03:22:26 +08:00
|
|
|
long offset = (get_time_timeval().tv_usec - ps->paint_tm_offset) % ps->refresh_intv;
|
2019-02-21 11:36:51 +08:00
|
|
|
// XXX this formula dones't work if refresh rate is not a whole number
|
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-08 08:50:58 +08:00
|
|
|
if (offset < 0)
|
|
|
|
offset += ps->refresh_intv;
|
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-08 10:20:01 +08:00
|
|
|
|
2012-10-26 11:12:28 +08:00
|
|
|
// If the target time is sufficiently close to a refresh time, don't add
|
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-08 10:20:01 +08:00
|
|
|
// an offset, to avoid certain blocking conditions.
|
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-08 08:50:58 +08:00
|
|
|
if (offset < SWOPTI_TOLERANCE
|
|
|
|
|| offset > ps->refresh_intv - SWOPTI_TOLERANCE)
|
2018-10-03 03:22:26 +08:00
|
|
|
return 0;
|
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-08 10:20:01 +08:00
|
|
|
|
2012-10-26 11:12:28 +08:00
|
|
|
// Add an offset so we wait until the next refresh after timeout
|
2018-10-03 03:22:26 +08:00
|
|
|
return (ps->refresh_intv - offset) / 1e6;
|
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-08 08:50:58 +08:00
|
|
|
}
|
|
|
|
|
2012-10-24 10:09:59 +08:00
|
|
|
/**
|
|
|
|
* Initialize X composite overlay window.
|
|
|
|
*/
|
2014-07-28 12:50:15 +08:00
|
|
|
static bool
|
2012-11-19 09:46:07 +08:00
|
|
|
init_overlay(session_t *ps) {
|
2018-09-29 00:44:51 +08:00
|
|
|
xcb_composite_get_overlay_window_reply_t *reply =
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_composite_get_overlay_window_reply(ps->c,
|
|
|
|
xcb_composite_get_overlay_window(ps->c, ps->root), NULL);
|
2018-09-29 00:44:51 +08:00
|
|
|
if (reply) {
|
|
|
|
ps->overlay = reply->overlay_win;
|
|
|
|
free(reply);
|
|
|
|
} else {
|
|
|
|
ps->overlay = XCB_NONE;
|
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->overlay) {
|
2012-10-24 10:09:59 +08:00
|
|
|
// Set window region of the overlay window, code stolen from
|
|
|
|
// compiz-0.8.8
|
2018-09-30 22:39:14 +08:00
|
|
|
xcb_generic_error_t *e;
|
2018-10-03 21:27:48 +08:00
|
|
|
e = XCB_SYNCED_VOID(xcb_shape_mask, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
|
2018-09-30 22:39:14 +08:00
|
|
|
ps->overlay, 0, 0, 0);
|
|
|
|
if (e) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Failed to set the bounding shape of overlay, giving up.");
|
2018-09-30 22:39:14 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-10-03 21:27:48 +08:00
|
|
|
e = XCB_SYNCED_VOID(xcb_shape_rectangles, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT,
|
2018-09-30 22:39:14 +08:00
|
|
|
XCB_CLIP_ORDERING_UNSORTED, ps->overlay, 0, 0, 0, NULL);
|
|
|
|
if (e) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Failed to set the input shape of overlay, giving up.");
|
2018-09-30 22:39:14 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2012-10-24 10:09:59 +08:00
|
|
|
|
2012-10-29 22:00:11 +08:00
|
|
|
// Listen to Expose events on the overlay
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_window_attributes(ps->c, ps->overlay, XCB_CW_EVENT_MASK,
|
2018-10-03 20:34:24 +08:00
|
|
|
(const uint32_t[]) { XCB_EVENT_MASK_EXPOSURE });
|
2012-10-29 22:00:11 +08:00
|
|
|
|
2012-10-24 10:09:59 +08:00
|
|
|
// Retrieve DamageNotify on root window if we are painting on an
|
|
|
|
// overlay
|
2012-11-19 09:46:07 +08:00
|
|
|
// root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty);
|
2013-09-12 21:23:20 +08:00
|
|
|
|
|
|
|
// Unmap overlay, firstly. But this typically does not work because
|
|
|
|
// the window isn't created yet.
|
2018-10-03 19:51:00 +08:00
|
|
|
// xcb_unmap_window(c, ps->overlay);
|
2013-09-12 21:23:20 +08:00
|
|
|
// XFlush(ps->dpy);
|
2018-12-20 10:49:29 +08:00
|
|
|
} else {
|
|
|
|
log_error("Cannot get X Composite overlay window. Falling "
|
|
|
|
"back to painting on root window.");
|
2012-10-24 10:09:59 +08:00
|
|
|
}
|
2018-12-28 04:45:38 +08:00
|
|
|
log_debug("overlay = %#010x", ps->overlay);
|
2014-07-28 12:50:15 +08:00
|
|
|
|
|
|
|
return ps->overlay;
|
2012-10-24 10:09:59 +08:00
|
|
|
}
|
|
|
|
|
2012-11-09 21:44:02 +08:00
|
|
|
/**
|
|
|
|
* Redirect all windows.
|
2019-02-25 08:07:12 +08:00
|
|
|
*
|
|
|
|
* @return whether the operation succeeded or not
|
2012-11-09 21:44:02 +08:00
|
|
|
*/
|
2019-02-25 08:07:12 +08:00
|
|
|
static bool
|
2012-11-19 09:46:07 +08:00
|
|
|
redir_start(session_t *ps) {
|
|
|
|
if (!ps->redirected) {
|
2019-02-09 23:50:40 +08:00
|
|
|
log_debug("Screen redirected.");
|
2012-11-09 21:44:02 +08:00
|
|
|
|
|
|
|
// Map overlay window. Done firstly according to this:
|
|
|
|
// https://bugzilla.gnome.org/show_bug.cgi?id=597014
|
2019-02-09 23:52:40 +08:00
|
|
|
if (ps->overlay) {
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_map_window(ps->c, ps->overlay);
|
2019-02-09 23:52:40 +08:00
|
|
|
}
|
2012-11-09 21:44:02 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_composite_redirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL);
|
2012-11-09 21:44:02 +08:00
|
|
|
|
2019-02-09 23:52:40 +08:00
|
|
|
x_sync(ps->c);
|
|
|
|
|
|
|
|
if (ps->o.experimental_backends) {
|
|
|
|
// Reinitialize win_data
|
|
|
|
backend_info_t *bi = backend_list[ps->o.backend];
|
|
|
|
assert(bi);
|
|
|
|
ps->backend_data = bi->init(ps);
|
2019-02-25 08:07:12 +08:00
|
|
|
if (!ps->backend_data) {
|
|
|
|
log_fatal("Failed to initialize backend, aborting...");
|
|
|
|
ps->quit = true;
|
|
|
|
ev_break(ps->loop, EVBREAK_ALL);
|
|
|
|
return false;
|
|
|
|
}
|
2019-02-09 23:52:40 +08:00
|
|
|
for (win *w = ps->list; w; w = w->next) {
|
|
|
|
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
|
|
|
|
w->win_data = bi->prepare_win(ps->backend_data, ps, w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 12:41:16 +08:00
|
|
|
/*
|
|
|
|
// Unredirect GL context window as this may have an effect on VSync:
|
2013-01-30 13:41:08 +08:00
|
|
|
// < http://dri.freedesktop.org/wiki/CompositeSwap >
|
2018-09-29 16:41:14 +08:00
|
|
|
xcb_composite_unredirect_window(c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL);
|
2013-03-01 12:41:16 +08:00
|
|
|
if (ps->o.paint_on_overlay && ps->overlay) {
|
2018-09-29 00:41:24 +08:00
|
|
|
xcb_composite_unredirect_window(c, ps->overlay,
|
2018-09-29 16:41:14 +08:00
|
|
|
XCB_COMPOSITE_REDIRECT_MANUAL);
|
2013-03-01 12:41:16 +08:00
|
|
|
} */
|
2013-01-30 13:41:08 +08:00
|
|
|
|
2012-11-09 21:44:02 +08:00
|
|
|
// Must call XSync() here
|
2018-10-03 21:27:48 +08:00
|
|
|
x_sync(ps->c);
|
2012-11-09 21:44:02 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->redirected = true;
|
2013-09-04 22:00:51 +08:00
|
|
|
|
|
|
|
// Repaint the whole screen
|
|
|
|
force_repaint(ps);
|
2012-11-09 21:44:02 +08:00
|
|
|
}
|
2019-02-25 08:07:12 +08:00
|
|
|
return true;
|
2012-11-09 21:44:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unredirect all windows.
|
|
|
|
*/
|
|
|
|
static void
|
2012-11-19 09:46:07 +08:00
|
|
|
redir_stop(session_t *ps) {
|
|
|
|
if (ps->redirected) {
|
2019-02-09 23:50:40 +08:00
|
|
|
log_debug("Screen unredirected.");
|
2019-02-09 23:52:40 +08:00
|
|
|
backend_info_t *bi = backend_list[ps->o.backend];
|
2012-11-09 21:44:02 +08:00
|
|
|
// Destroy all Pictures as they expire once windows are unredirected
|
|
|
|
// If we don't destroy them here, looks like the resources are just
|
|
|
|
// kept inaccessible somehow
|
2019-02-21 01:37:53 +08:00
|
|
|
for (win *w = ps->list, *next; w; w = next) {
|
|
|
|
next = w->next;
|
|
|
|
// Wrapping up fading in progress
|
2019-02-21 10:12:07 +08:00
|
|
|
win_skip_fading(ps, &w);
|
2019-02-21 01:37:53 +08:00
|
|
|
|
|
|
|
// `w` might be freed by win_check_fade_finished
|
2019-02-09 23:52:40 +08:00
|
|
|
if (!w) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (ps->o.experimental_backends) {
|
|
|
|
assert(bi);
|
|
|
|
if (w->state == WSTATE_MAPPED) {
|
|
|
|
bi->release_win(ps->backend_data, ps, w, w->win_data);
|
|
|
|
w->win_data = NULL;
|
|
|
|
} else {
|
|
|
|
assert(!w->win_data);
|
|
|
|
}
|
|
|
|
} else {
|
2019-02-21 01:37:53 +08:00
|
|
|
free_paint(ps, &w->paint);
|
|
|
|
}
|
2018-11-08 22:53:13 +08:00
|
|
|
}
|
2012-11-09 21:44:02 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_composite_unredirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL);
|
2012-11-09 21:44:02 +08:00
|
|
|
// Unmap overlay window
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->overlay)
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_unmap_window(ps->c, ps->overlay);
|
2012-11-09 21:44:02 +08:00
|
|
|
|
2019-02-09 23:52:40 +08:00
|
|
|
if (ps->o.experimental_backends) {
|
|
|
|
// deinit backend
|
|
|
|
bi->deinit(ps->backend_data, ps);
|
|
|
|
ps->backend_data = NULL;
|
|
|
|
}
|
|
|
|
|
2012-11-09 21:44:02 +08:00
|
|
|
// Must call XSync() here
|
2018-10-03 21:27:48 +08:00
|
|
|
x_sync(ps->c);
|
2012-11-09 21:44:02 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->redirected = false;
|
2012-11-09 21:44:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
// Handle queued events before we go to sleep
|
|
|
|
static void
|
|
|
|
handle_queued_x_events(EV_P_ ev_prepare *w, int revents) {
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, event_check);
|
2018-10-03 03:22:26 +08:00
|
|
|
xcb_generic_event_t *ev;
|
2018-10-03 21:27:48 +08:00
|
|
|
while ((ev = xcb_poll_for_queued_event(ps->c))) {
|
2018-10-03 03:22:26 +08:00
|
|
|
ev_handle(ps, ev);
|
|
|
|
free(ev);
|
|
|
|
};
|
2019-02-07 08:41:24 +08:00
|
|
|
// Flush because if we go into sleep when there is still
|
|
|
|
// requests in the outgoing buffer, they will not be sent
|
|
|
|
// for an indefinite amount of time.
|
|
|
|
// Use XFlush here too, we might still use some Xlib functions
|
|
|
|
// because OpenGL.
|
2018-10-03 03:22:26 +08:00
|
|
|
XFlush(ps->dpy);
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_flush(ps->c);
|
2018-10-04 15:36:48 +08:00
|
|
|
int err = xcb_connection_has_error(ps->c);
|
|
|
|
if (err) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("X11 server connection broke (error %d)", err);
|
|
|
|
exit(1);
|
2018-10-04 15:36:48 +08:00
|
|
|
}
|
2018-10-03 03:22:26 +08:00
|
|
|
}
|
|
|
|
|
2013-09-04 22:00:51 +08:00
|
|
|
/**
|
|
|
|
* Unredirection timeout callback.
|
|
|
|
*/
|
2018-10-03 03:22:26 +08:00
|
|
|
static void
|
|
|
|
tmout_unredir_callback(EV_P_ ev_timer *w, int revents) {
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, unredir_timer);
|
|
|
|
ps->tmout_unredir_hit = true;
|
|
|
|
queue_redraw(ps);
|
2013-09-04 22:00:51 +08:00
|
|
|
}
|
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
static void
|
|
|
|
fade_timer_callback(EV_P_ ev_timer *w, int revents) {
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, fade_timer);
|
|
|
|
queue_redraw(ps);
|
2018-10-03 03:22:26 +08:00
|
|
|
}
|
2013-01-11 21:31:02 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
static void
|
|
|
|
_draw_callback(EV_P_ session_t *ps, int revents) {
|
|
|
|
if (ps->o.benchmark) {
|
|
|
|
if (ps->o.benchmark_wid) {
|
|
|
|
win *wi = find_win(ps, ps->o.benchmark_wid);
|
|
|
|
if (!wi) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Couldn't find specified benchmark window.");
|
2018-10-03 03:22:26 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
add_damage_from_win(ps, wi);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
force_repaint(ps);
|
|
|
|
}
|
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-08 08:50:58 +08:00
|
|
|
}
|
|
|
|
|
2019-02-12 09:53:50 +08:00
|
|
|
bool fade_running = false;
|
2019-02-21 09:40:04 +08:00
|
|
|
win *t = paint_preprocess(ps, &fade_running);
|
2018-10-03 03:22:26 +08:00
|
|
|
ps->tmout_unredir_hit = false;
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
// Start/stop fade timer depends on whether window are fading
|
2019-02-12 09:53:50 +08:00
|
|
|
if (!fade_running && ev_is_active(&ps->fade_timer))
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_timer_stop(ps->loop, &ps->fade_timer);
|
2019-02-12 09:53:50 +08:00
|
|
|
else if (fade_running && !ev_is_active(&ps->fade_timer)) {
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_timer_set(&ps->fade_timer, fade_timeout(ps), 0);
|
|
|
|
ev_timer_start(ps->loop, &ps->fade_timer);
|
2018-10-03 03:22:26 +08:00
|
|
|
}
|
2013-01-11 21:31:02 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
// If the screen is unredirected, free all_damage to stop painting
|
2019-01-09 07:15:00 +08:00
|
|
|
if (ps->redirected && ps->o.stoppaint_force != ON) {
|
2018-10-03 03:22:26 +08:00
|
|
|
static int paint = 0;
|
2019-02-09 23:52:40 +08:00
|
|
|
if (ps->o.experimental_backends) {
|
|
|
|
paint_all_new(ps, t, false);
|
|
|
|
} else {
|
|
|
|
paint_all(ps, t, false);
|
|
|
|
}
|
2018-10-03 03:22:26 +08:00
|
|
|
|
|
|
|
paint++;
|
|
|
|
if (ps->o.benchmark && paint >= ps->o.benchmark)
|
|
|
|
exit(0);
|
2013-01-11 21:31:02 +08:00
|
|
|
}
|
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-08 08:50:58 +08:00
|
|
|
|
2019-02-12 09:53:50 +08:00
|
|
|
if (!fade_running)
|
2018-10-03 03:22:26 +08:00
|
|
|
ps->fade_time = 0L;
|
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-08 08:50:58 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
ps->redraw_needed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
draw_callback(EV_P_ ev_idle *w, int revents) {
|
|
|
|
// This function is not used if we are using --swopti
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, draw_idle);
|
2018-10-03 03:22:26 +08:00
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
_draw_callback(EV_A_ ps, revents);
|
2018-10-03 03:22:26 +08:00
|
|
|
|
|
|
|
// Don't do painting non-stop unless we are in benchmark mode
|
2018-11-27 08:32:08 +08:00
|
|
|
if (!ps->o.benchmark)
|
|
|
|
ev_idle_stop(ps->loop, &ps->draw_idle);
|
2018-10-03 03:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
delayed_draw_timer_callback(EV_P_ ev_timer *w, int revents) {
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, delayed_draw_timer);
|
|
|
|
_draw_callback(EV_A_ ps, revents);
|
2018-10-03 03:22:26 +08:00
|
|
|
|
|
|
|
// We might have stopped the ev_idle in delayed_draw_callback,
|
|
|
|
// so we restart it if we are in benchmark mode
|
2018-11-27 08:32:08 +08:00
|
|
|
if (ps->o.benchmark)
|
|
|
|
ev_idle_start(EV_A_ &ps->draw_idle);
|
2018-10-03 03:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
delayed_draw_callback(EV_P_ ev_idle *w, int revents) {
|
|
|
|
// This function is only used if we are using --swopti
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, draw_idle);
|
2019-01-25 08:27:38 +08:00
|
|
|
assert(ps->redraw_needed);
|
|
|
|
assert(!ev_is_active(&ps->delayed_draw_timer));
|
2018-10-03 03:22:26 +08:00
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
double delay = swopti_handle_timeout(ps);
|
2019-01-25 08:27:38 +08:00
|
|
|
if (delay < 1e-6) {
|
|
|
|
if (!ps->o.benchmark) {
|
|
|
|
ev_idle_stop(ps->loop, &ps->draw_idle);
|
|
|
|
}
|
2018-11-27 08:32:08 +08:00
|
|
|
return _draw_callback(EV_A_ ps, revents);
|
2019-01-25 08:27:38 +08:00
|
|
|
}
|
2018-10-03 03:22:26 +08:00
|
|
|
|
|
|
|
// This is a little bit hacky. When we get to this point in code, we need
|
2018-11-27 08:32:08 +08:00
|
|
|
// to update the screen , but we will only be updating after a delay, So
|
2018-10-03 03:22:26 +08:00
|
|
|
// we want to stop the ev_idle, so this callback doesn't get call repeatedly
|
|
|
|
// during the delay, we also want queue_redraw to not restart the ev_idle.
|
2018-11-27 08:32:08 +08:00
|
|
|
// So we stop ev_idle and leave ps->redraw_needed to be true. (effectively,
|
|
|
|
// ps->redraw_needed means if redraw is needed or if draw is in progress).
|
2018-10-03 03:22:26 +08:00
|
|
|
//
|
|
|
|
// We do this anyway even if we are in benchmark mode. That means we will
|
|
|
|
// have to restart draw_idle after the draw actually happened when we are in
|
|
|
|
// benchmark mode.
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_idle_stop(ps->loop, &ps->draw_idle);
|
2018-10-03 03:22:26 +08:00
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_timer_set(&ps->delayed_draw_timer, delay, 0);
|
|
|
|
ev_timer_start(ps->loop, &ps->delayed_draw_timer);
|
2018-10-03 03:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
x_event_callback(EV_P_ ev_io *w, int revents) {
|
|
|
|
session_t *ps = (session_t *)w;
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_generic_event_t *ev = xcb_poll_for_event(ps->c);
|
2018-10-03 03:22:26 +08:00
|
|
|
if (ev) {
|
|
|
|
ev_handle(ps, ev);
|
|
|
|
free(ev);
|
|
|
|
}
|
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-08 08:50:58 +08:00
|
|
|
}
|
|
|
|
|
2018-11-27 07:56:55 +08:00
|
|
|
/**
|
|
|
|
* Turn on the program reset flag.
|
|
|
|
*
|
|
|
|
* This will result in compton resetting itself after next paint.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
reset_enable(EV_P_ ev_signal *w, int revents) {
|
2018-11-27 08:32:08 +08:00
|
|
|
session_t *ps = session_ptr(w, usr1_signal);
|
2019-02-12 07:13:39 +08:00
|
|
|
log_info("compton is resetting...");
|
|
|
|
ev_break(ps->loop, EVBREAK_ALL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
exit_enable(EV_P_ ev_signal *w, int revents) {
|
|
|
|
session_t *ps = session_ptr(w, int_signal);
|
|
|
|
log_info("compton is quitting...");
|
|
|
|
ps->quit = true;
|
2018-11-27 07:56:55 +08:00
|
|
|
ev_break(ps->loop, EVBREAK_ALL);
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
/**
|
|
|
|
* Initialize a session.
|
|
|
|
*
|
|
|
|
* @param argc number of commandline arguments
|
|
|
|
* @param argv commandline arguments
|
2019-02-08 09:27:46 +08:00
|
|
|
* @param dpy the X Display
|
|
|
|
* @param config_file the path to the config file
|
|
|
|
* @param all_xerros whether we should report all X errors
|
|
|
|
* @param fork whether we will fork after initialization
|
2012-11-19 09:46:07 +08:00
|
|
|
*/
|
|
|
|
static session_t *
|
2019-02-08 09:27:46 +08:00
|
|
|
session_init(int argc, char **argv, Display *dpy, const char *config_file,
|
|
|
|
bool all_xerrors, bool fork) {
|
2018-08-22 22:26:08 +08:00
|
|
|
static const session_t s_def = {
|
2018-10-04 05:46:18 +08:00
|
|
|
.backend_data = NULL,
|
2012-11-19 09:46:07 +08:00
|
|
|
.dpy = NULL,
|
|
|
|
.scr = 0,
|
2018-10-03 21:27:48 +08:00
|
|
|
.c = NULL,
|
2018-09-24 02:10:46 +08:00
|
|
|
.vis = 0,
|
2012-11-19 09:46:07 +08:00
|
|
|
.depth = 0,
|
2018-12-28 04:45:38 +08:00
|
|
|
.root = XCB_NONE,
|
2012-11-19 09:46:07 +08:00
|
|
|
.root_height = 0,
|
|
|
|
.root_width = 0,
|
2018-12-28 04:45:38 +08:00
|
|
|
// .root_damage = XCB_NONE,
|
|
|
|
.overlay = XCB_NONE,
|
2013-03-15 23:16:23 +08:00
|
|
|
.root_tile_fill = false,
|
|
|
|
.root_tile_paint = PAINT_INIT,
|
2018-12-28 04:45:38 +08:00
|
|
|
.tgt_picture = XCB_NONE,
|
2013-12-10 22:06:02 +08:00
|
|
|
.tgt_buffer = PAINT_INIT,
|
2018-12-28 04:45:38 +08:00
|
|
|
.reg_win = XCB_NONE,
|
2018-12-22 00:25:28 +08:00
|
|
|
#ifdef CONFIG_OPENGL
|
|
|
|
.glx_prog_win = GLX_PROG_MAIN_INIT,
|
|
|
|
#endif
|
2012-11-19 09:46:07 +08:00
|
|
|
.o = {
|
2013-03-15 23:16:23 +08:00
|
|
|
.backend = BKEND_XRENDER,
|
2013-03-17 12:14:00 +08:00
|
|
|
.glx_no_stencil = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
.mark_wmwin_focused = false,
|
|
|
|
.mark_ovredir_focused = false,
|
|
|
|
.detect_rounded_corners = false,
|
2013-04-27 11:43:11 +08:00
|
|
|
.resize_damage = 0,
|
2012-11-19 09:46:07 +08:00
|
|
|
.unredir_if_possible = false,
|
2013-09-04 22:00:51 +08:00
|
|
|
.unredir_if_possible_blacklist = NULL,
|
|
|
|
.unredir_if_possible_delay = 0,
|
2013-07-26 12:52:16 +08:00
|
|
|
.redirected_force = UNSET,
|
2013-07-30 22:24:11 +08:00
|
|
|
.stoppaint_force = UNSET,
|
2013-01-11 21:31:02 +08:00
|
|
|
.dbus = false,
|
2013-03-19 20:58:55 +08:00
|
|
|
.benchmark = 0,
|
2018-12-28 04:45:38 +08:00
|
|
|
.benchmark_wid = XCB_NONE,
|
2013-01-11 21:31:02 +08:00
|
|
|
.logpath = NULL,
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
.refresh_rate = 0,
|
|
|
|
.sw_opti = false,
|
|
|
|
.vsync = VSYNC_NONE,
|
|
|
|
.vsync_aggressive = false,
|
|
|
|
|
|
|
|
.shadow_red = 0.0,
|
|
|
|
.shadow_green = 0.0,
|
|
|
|
.shadow_blue = 0.0,
|
2019-01-02 19:14:27 +08:00
|
|
|
.shadow_radius = 18,
|
2012-11-19 09:46:07 +08:00
|
|
|
.shadow_offset_x = -15,
|
|
|
|
.shadow_offset_y = -15,
|
|
|
|
.shadow_opacity = .75,
|
|
|
|
.shadow_blacklist = NULL,
|
|
|
|
.shadow_ignore_shaped = false,
|
|
|
|
.respect_prop_shadow = false,
|
2013-08-22 21:15:04 +08:00
|
|
|
.xinerama_shadow_crop = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
.fade_in_step = 0.028,
|
|
|
|
.fade_out_step = 0.03,
|
2012-11-19 09:46:07 +08:00
|
|
|
.fade_delta = 10,
|
|
|
|
.no_fading_openclose = false,
|
2014-05-16 15:18:17 +08:00
|
|
|
.no_fading_destroyed_argb = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
.fade_blacklist = NULL,
|
|
|
|
|
2019-02-09 23:50:40 +08:00
|
|
|
.inactive_opacity = 1.0,
|
2012-11-19 09:46:07 +08:00
|
|
|
.inactive_opacity_override = false,
|
2019-02-09 23:50:40 +08:00
|
|
|
.active_opacity = 1.0,
|
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-30 11:56:00 +08:00
|
|
|
.frame_opacity = 1.0,
|
2012-11-19 09:46:07 +08:00
|
|
|
.detect_client_opacity = false,
|
2013-01-12 22:21:35 +08:00
|
|
|
|
2012-12-14 20:32:46 +08:00
|
|
|
.blur_background = false,
|
|
|
|
.blur_background_frame = false,
|
2012-12-15 20:07:45 +08:00
|
|
|
.blur_background_fixed = false,
|
2013-03-23 22:06:41 +08:00
|
|
|
.blur_background_blacklist = NULL,
|
2013-05-20 18:04:40 +08:00
|
|
|
.blur_kerns = { NULL },
|
2013-01-12 22:21:35 +08:00
|
|
|
.inactive_dim = 0.0,
|
|
|
|
.inactive_dim_fixed = false,
|
|
|
|
.invert_color_list = NULL,
|
2013-05-21 09:18:41 +08:00
|
|
|
.opacity_rules = NULL,
|
2012-12-10 10:31:24 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
.use_ewmh_active_win = false,
|
2012-11-28 11:44:00 +08:00
|
|
|
.focus_blacklist = NULL,
|
2012-12-12 12:01:51 +08:00
|
|
|
.detect_transient = false,
|
|
|
|
.detect_client_leader = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
.track_focus = false,
|
|
|
|
.track_wdata = false,
|
2012-12-12 12:01:51 +08:00
|
|
|
.track_leader = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
.time_start = { 0, 0 },
|
|
|
|
.redirected = false,
|
|
|
|
.alpha_picts = NULL,
|
2013-01-11 21:31:02 +08:00
|
|
|
.fade_time = 0L,
|
2012-11-19 09:46:07 +08:00
|
|
|
.ignore_head = NULL,
|
|
|
|
.ignore_tail = NULL,
|
2018-10-03 03:22:26 +08:00
|
|
|
.quit = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
.expose_rects = NULL,
|
|
|
|
.size_expose = 0,
|
|
|
|
.n_expose = 0,
|
|
|
|
|
|
|
|
.list = NULL,
|
|
|
|
.active_win = NULL,
|
2018-12-28 04:45:38 +08:00
|
|
|
.active_leader = XCB_NONE,
|
2012-12-12 12:01:51 +08:00
|
|
|
|
2018-12-28 04:45:38 +08:00
|
|
|
.black_picture = XCB_NONE,
|
|
|
|
.cshadow_picture = XCB_NONE,
|
|
|
|
.white_picture = XCB_NONE,
|
2012-11-19 09:46:07 +08:00
|
|
|
.gaussian_map = NULL,
|
|
|
|
|
|
|
|
.refresh_rate = 0,
|
|
|
|
.refresh_intv = 0UL,
|
|
|
|
.paint_tm_offset = 0L,
|
|
|
|
|
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-08 08:50:58 +08:00
|
|
|
#ifdef CONFIG_VSYNC_DRM
|
2013-01-31 22:53:44 +08:00
|
|
|
.drm_fd = -1,
|
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-08 08:50:58 +08:00
|
|
|
#endif
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
.xfixes_event = 0,
|
|
|
|
.xfixes_error = 0,
|
|
|
|
.damage_event = 0,
|
|
|
|
.damage_error = 0,
|
|
|
|
.render_event = 0,
|
|
|
|
.render_error = 0,
|
|
|
|
.composite_event = 0,
|
|
|
|
.composite_error = 0,
|
|
|
|
.composite_opcode = 0,
|
|
|
|
.has_name_pixmap = false,
|
|
|
|
.shape_exists = false,
|
|
|
|
.shape_event = 0,
|
|
|
|
.shape_error = 0,
|
|
|
|
.randr_exists = 0,
|
|
|
|
.randr_event = 0,
|
|
|
|
.randr_error = 0,
|
2018-08-22 22:12:29 +08:00
|
|
|
#ifdef CONFIG_OPENGL
|
2012-11-19 09:46:07 +08:00
|
|
|
.glx_exists = false,
|
|
|
|
.glx_event = 0,
|
|
|
|
.glx_error = 0,
|
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-08 08:50:58 +08:00
|
|
|
#endif
|
2012-12-14 20:32:46 +08:00
|
|
|
.xrfilter_convolution_exists = false,
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2018-12-28 04:45:38 +08:00
|
|
|
.atom_opacity = XCB_NONE,
|
|
|
|
.atom_frame_extents = XCB_NONE,
|
|
|
|
.atom_client = XCB_NONE,
|
|
|
|
.atom_name = XCB_NONE,
|
|
|
|
.atom_name_ewmh = XCB_NONE,
|
|
|
|
.atom_class = XCB_NONE,
|
|
|
|
.atom_role = XCB_NONE,
|
|
|
|
.atom_transient = XCB_NONE,
|
|
|
|
.atom_ewmh_active_win = XCB_NONE,
|
|
|
|
.atom_compton_shadow = XCB_NONE,
|
|
|
|
.atom_win_type = XCB_NONE,
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
.atoms_wintypes = { 0 },
|
|
|
|
.track_atom_lst = NULL,
|
|
|
|
|
|
|
|
#ifdef CONFIG_DBUS
|
2018-12-21 06:31:34 +08:00
|
|
|
.dbus_data = NULL,
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
#endif
|
2012-11-19 09:46:07 +08:00
|
|
|
};
|
2012-09-25 10:19:20 +08:00
|
|
|
|
2018-12-20 07:10:58 +08:00
|
|
|
log_init_tls();
|
2019-02-08 05:48:39 +08:00
|
|
|
auto stderr_logger = stderr_logger_new();
|
2019-02-09 10:49:09 +08:00
|
|
|
if (stderr_logger) {
|
|
|
|
// stderr logger might fail to create if we are already
|
|
|
|
// daemonized.
|
|
|
|
log_add_target_tls(stderr_logger);
|
2018-12-22 06:49:42 +08:00
|
|
|
}
|
2018-12-20 07:10:58 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// Allocate a session and copy default values into it
|
2018-12-16 02:47:21 +08:00
|
|
|
session_t *ps = cmalloc(session_t);
|
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-30 11:56:00 +08:00
|
|
|
*ps = s_def;
|
2018-10-03 03:22:26 +08:00
|
|
|
ps->loop = EV_DEFAULT;
|
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-30 11:56:00 +08:00
|
|
|
pixman_region32_init(&ps->screen_reg);
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->ignore_tail = &ps->ignore_head;
|
|
|
|
gettimeofday(&ps->time_start, NULL);
|
|
|
|
|
2019-02-08 06:29:24 +08:00
|
|
|
ps->o.show_all_xerrors = all_xerrors;
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2019-02-08 06:29:24 +08:00
|
|
|
// Use the same Display across reset, primarily for resource leak checking
|
|
|
|
ps->dpy = dpy;
|
2018-10-03 21:27:48 +08:00
|
|
|
ps->c = XGetXCBConnection(ps->dpy);
|
2019-02-08 06:29:24 +08:00
|
|
|
|
2018-09-27 23:29:51 +08:00
|
|
|
const xcb_query_extension_reply_t *ext_info;
|
2008-02-15 12:38:32 +08:00
|
|
|
|
2014-03-17 23:25:34 +08:00
|
|
|
XSetErrorHandler(xerror);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->scr = DefaultScreen(ps->dpy);
|
|
|
|
ps->root = RootWindow(ps->dpy, ps->scr);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-09-24 02:10:46 +08:00
|
|
|
ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr));
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->depth = DefaultDepth(ps->dpy, ps->scr);
|
|
|
|
|
2013-06-09 17:06:35 +08:00
|
|
|
// Start listening to events on root earlier to catch all possible
|
|
|
|
// root geometry changes
|
2019-02-07 08:41:24 +08:00
|
|
|
auto e = xcb_request_check(
|
|
|
|
ps->c, xcb_change_window_attributes_checked(
|
|
|
|
ps->c, ps->root, XCB_CW_EVENT_MASK,
|
|
|
|
(const uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
|
|
|
|
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
|
|
|
XCB_EVENT_MASK_PROPERTY_CHANGE}));
|
|
|
|
if (e) {
|
|
|
|
log_error("Failed to setup root window event mask");
|
|
|
|
free(e);
|
|
|
|
}
|
2013-06-09 17:06:35 +08:00
|
|
|
|
|
|
|
ps->root_width = DisplayWidth(ps->dpy, ps->scr);
|
|
|
|
ps->root_height = DisplayHeight(ps->dpy, ps->scr);
|
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_render_id);
|
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_composite_id);
|
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_damage_id);
|
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_shape_id);
|
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id);
|
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_randr_id);
|
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_xinerama_id);
|
2018-11-04 06:15:38 +08:00
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_present_id);
|
2018-12-30 15:41:31 +08:00
|
|
|
xcb_prefetch_extension_data(ps->c, &xcb_sync_id);
|
2018-09-27 23:29:51 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_render_id);
|
2018-09-28 00:14:44 +08:00
|
|
|
if (!ext_info || !ext_info->present) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("No render extension");
|
2011-11-04 14:33:23 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-09-28 00:14:44 +08:00
|
|
|
ps->render_event = ext_info->first_event;
|
|
|
|
ps->render_error = ext_info->first_error;
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_composite_id);
|
2018-09-29 01:13:53 +08:00
|
|
|
if (!ext_info || !ext_info->present) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("No composite extension");
|
2011-11-04 14:33:23 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-09-29 01:13:53 +08:00
|
|
|
ps->composite_opcode = ext_info->major_opcode;
|
|
|
|
ps->composite_event = ext_info->first_event;
|
|
|
|
ps->composite_error = ext_info->first_error;
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
{
|
2018-09-29 01:13:53 +08:00
|
|
|
xcb_composite_query_version_reply_t *reply =
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_composite_query_version_reply(ps->c,
|
|
|
|
xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION),
|
2018-09-29 01:13:53 +08:00
|
|
|
NULL);
|
2003-11-25 01:11:00 +08:00
|
|
|
|
2018-12-21 07:42:38 +08:00
|
|
|
if (reply && (reply->major_version > 0 || reply->minor_version >= 2)) {
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->has_name_pixmap = true;
|
|
|
|
}
|
2018-09-29 01:13:53 +08:00
|
|
|
free(reply);
|
2011-11-04 16:41:56 +08:00
|
|
|
}
|
2004-06-27 12:48:37 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_damage_id);
|
2018-09-27 23:29:51 +08:00
|
|
|
if (!ext_info || !ext_info->present) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("No damage extension");
|
2011-11-04 14:33:23 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-09-27 23:29:51 +08:00
|
|
|
ps->damage_event = ext_info->first_event;
|
|
|
|
ps->damage_error = ext_info->first_error;
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_discard_reply(ps->c,
|
|
|
|
xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION).sequence);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id);
|
2018-09-29 00:31:00 +08:00
|
|
|
if (!ext_info || !ext_info->present) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("No XFixes extension");
|
2011-11-04 14:33:23 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-09-29 00:31:00 +08:00
|
|
|
ps->xfixes_event = ext_info->first_event;
|
|
|
|
ps->xfixes_error = ext_info->first_error;
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_discard_reply(ps->c,
|
|
|
|
xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-12-22 00:25:28 +08:00
|
|
|
// Parse configuration file
|
|
|
|
win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}};
|
|
|
|
bool shadow_enabled = false, fading_enable = false, hasneg = false;
|
2019-02-08 06:29:24 +08:00
|
|
|
char *config_file_to_free = NULL;
|
|
|
|
config_file = config_file_to_free =
|
|
|
|
parse_config(&ps->o, config_file, &shadow_enabled,
|
|
|
|
&fading_enable, &hasneg, winopt_mask);
|
2018-12-22 00:25:28 +08:00
|
|
|
|
2019-02-13 10:04:05 +08:00
|
|
|
if (IS_ERR(config_file_to_free)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-12-22 00:25:28 +08:00
|
|
|
// Parse all of the rest command line options
|
|
|
|
get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask);
|
|
|
|
|
2018-12-22 06:49:42 +08:00
|
|
|
if (ps->o.logpath) {
|
2019-02-08 05:48:39 +08:00
|
|
|
auto l = file_logger_new(ps->o.logpath);
|
|
|
|
if (l) {
|
2018-12-22 06:49:42 +08:00
|
|
|
log_info("Switching to log file: %s", ps->o.logpath);
|
2019-02-12 06:58:16 +08:00
|
|
|
if (stderr_logger) {
|
|
|
|
log_remove_target_tls(stderr_logger);
|
|
|
|
stderr_logger = NULL;
|
|
|
|
}
|
2019-02-08 05:48:39 +08:00
|
|
|
log_add_target_tls(l);
|
2019-02-08 09:27:46 +08:00
|
|
|
stderr_logger = NULL;
|
2018-12-22 06:49:42 +08:00
|
|
|
} else {
|
|
|
|
log_error("Failed to setup log file %s, I will keep using stderr", ps->o.logpath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-22 00:25:28 +08:00
|
|
|
// Get needed atoms for c2 condition lists
|
|
|
|
if (!(c2_list_postprocess(ps, ps->o.unredir_if_possible_blacklist) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.paint_blacklist) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.shadow_blacklist) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.fade_blacklist) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.blur_background_blacklist) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.invert_color_list) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.opacity_rules) &&
|
|
|
|
c2_list_postprocess(ps, ps->o.focus_blacklist))) {
|
|
|
|
log_error("Post-processing of conditionals failed, some of your rules might not work");
|
|
|
|
}
|
2013-06-09 17:06:35 +08:00
|
|
|
|
2018-12-21 05:57:32 +08:00
|
|
|
rebuild_shadow_exclude_reg(ps);
|
|
|
|
|
2014-03-17 23:25:34 +08:00
|
|
|
// Query X Shape
|
2018-10-03 21:27:48 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_shape_id);
|
2018-09-29 17:29:51 +08:00
|
|
|
if (ext_info && ext_info->present) {
|
|
|
|
ps->shape_event = ext_info->first_event;
|
|
|
|
ps->shape_error = ext_info->first_error;
|
2014-03-17 23:25:34 +08:00
|
|
|
ps->shape_exists = true;
|
|
|
|
}
|
|
|
|
|
2018-11-04 06:15:38 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_randr_id);
|
|
|
|
if (ext_info && ext_info->present) {
|
|
|
|
ps->randr_exists = true;
|
|
|
|
ps->randr_event = ext_info->first_event;
|
|
|
|
ps->randr_error = ext_info->first_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_present_id);
|
|
|
|
if (ext_info && ext_info->present) {
|
2019-01-01 22:23:51 +08:00
|
|
|
auto r =
|
|
|
|
xcb_present_query_version_reply(ps->c,
|
|
|
|
xcb_present_query_version(ps->c,
|
|
|
|
XCB_PRESENT_MAJOR_VERSION,
|
|
|
|
XCB_PRESENT_MINOR_VERSION),
|
|
|
|
NULL);
|
|
|
|
if (r) {
|
|
|
|
ps->present_exists = true;
|
2019-02-18 00:59:00 +08:00
|
|
|
free(r);
|
2019-01-01 22:23:51 +08:00
|
|
|
}
|
2018-11-04 06:15:38 +08:00
|
|
|
}
|
|
|
|
|
2018-11-08 22:53:13 +08:00
|
|
|
// Query X Sync
|
2018-12-30 15:41:31 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_sync_id);
|
|
|
|
if (ext_info && ext_info->present) {
|
|
|
|
ps->xsync_error = ext_info->first_error;
|
|
|
|
ps->xsync_event = ext_info->first_event;
|
|
|
|
// Need X Sync 3.1 for fences
|
2019-01-01 22:09:55 +08:00
|
|
|
auto r = xcb_sync_initialize_reply(ps->c,
|
|
|
|
xcb_sync_initialize(ps->c,
|
|
|
|
XCB_SYNC_MAJOR_VERSION,
|
|
|
|
XCB_SYNC_MINOR_VERSION),
|
|
|
|
NULL);
|
|
|
|
if (r && (r->major_version > 3 ||
|
|
|
|
(r->major_version == 3 && r->minor_version >= 1))) {
|
2018-11-08 22:53:13 +08:00
|
|
|
ps->xsync_exists = true;
|
2018-12-30 15:41:31 +08:00
|
|
|
free(r);
|
|
|
|
}
|
2018-11-08 22:53:13 +08:00
|
|
|
}
|
|
|
|
|
2018-12-30 15:41:31 +08:00
|
|
|
ps->sync_fence = XCB_NONE;
|
2018-11-08 22:53:13 +08:00
|
|
|
if (!ps->xsync_exists && ps->o.xrender_sync_fence) {
|
2018-12-30 15:41:31 +08:00
|
|
|
log_error("XSync extension not found. No XSync fence sync is "
|
2018-12-20 10:49:29 +08:00
|
|
|
"possible. (xrender-sync-fence can't be enabled)");
|
2018-12-30 15:41:31 +08:00
|
|
|
ps->o.xrender_sync_fence = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ps->o.xrender_sync_fence) {
|
|
|
|
ps->sync_fence = xcb_generate_id(ps->c);
|
2019-02-07 08:41:24 +08:00
|
|
|
e = xcb_request_check(ps->c, xcb_sync_create_fence(ps->c, ps->root, ps->sync_fence, 0));
|
2018-12-30 15:41:31 +08:00
|
|
|
if (e) {
|
|
|
|
log_error("Failed to create a XSync fence. xrender-sync-fence will be disabled");
|
|
|
|
ps->o.xrender_sync_fence = false;
|
2018-12-30 16:05:16 +08:00
|
|
|
ps->sync_fence = XCB_NONE;
|
2018-12-30 15:41:31 +08:00
|
|
|
free(e);
|
|
|
|
}
|
2018-11-08 22:53:13 +08: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-08 10:20:01 +08:00
|
|
|
// Query X RandR
|
2013-08-28 21:47:16 +08:00
|
|
|
if ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop) {
|
2018-11-04 06:15:38 +08:00
|
|
|
if (!ps->randr_exists) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("No XRandR extension. sw-opti, refresh-rate or xinerama-shadow-crop "
|
|
|
|
"cannot be enabled.");
|
|
|
|
exit(1);
|
2018-11-04 06:15:38 +08: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-08 10:20:01 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 21:15:04 +08:00
|
|
|
// Query X Xinerama extension
|
|
|
|
if (ps->o.xinerama_shadow_crop) {
|
2018-10-03 21:27:48 +08:00
|
|
|
ext_info = xcb_get_extension_data(ps->c, &xcb_xinerama_id);
|
2018-09-29 17:46:29 +08:00
|
|
|
ps->xinerama_exists = ext_info && ext_info->present;
|
2013-08-22 21:15:04 +08:00
|
|
|
}
|
|
|
|
|
2013-03-15 23:16:23 +08:00
|
|
|
rebuild_screen_reg(ps);
|
|
|
|
|
2013-03-12 09:43:14 +08:00
|
|
|
// Overlay must be initialized before double buffer, and before creation
|
|
|
|
// of OpenGL context.
|
2018-11-03 22:04:18 +08:00
|
|
|
init_overlay(ps);
|
2013-03-12 09:43:14 +08:00
|
|
|
|
2018-12-16 08:53:41 +08:00
|
|
|
// Initialize filters, must be preceded by OpenGL context creation
|
2019-02-21 02:04:04 +08:00
|
|
|
if (!ps->o.experimental_backends && !init_render(ps)) {
|
2018-12-21 00:50:11 +08:00
|
|
|
log_fatal("Failed to initialize the backend");
|
2018-12-16 08:53:41 +08:00
|
|
|
exit(1);
|
2018-12-21 00:50:11 +08:00
|
|
|
}
|
2018-12-16 08:53:41 +08:00
|
|
|
|
2019-02-21 02:17:16 +08:00
|
|
|
if (ps->o.experimental_backends) {
|
|
|
|
ps->ndamage = backend_list[ps->o.backend]->max_buffer_age;
|
|
|
|
} else {
|
|
|
|
ps->ndamage = maximum_buffer_age(ps);
|
|
|
|
}
|
|
|
|
ps->damage_ring = ccalloc(ps->ndamage, region_t);
|
|
|
|
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
|
|
|
|
|
|
|
for (int i = 0; i < ps->ndamage; i++) {
|
|
|
|
pixman_region32_init(&ps->damage_ring[i]);
|
|
|
|
}
|
|
|
|
|
2018-11-04 06:15:38 +08:00
|
|
|
if (ps->o.print_diagnostics) {
|
2019-02-08 06:29:24 +08:00
|
|
|
print_diagnostics(ps, config_file);
|
|
|
|
free(config_file_to_free);
|
2018-11-04 06:15:38 +08:00
|
|
|
exit(0);
|
|
|
|
}
|
2019-02-08 06:29:24 +08:00
|
|
|
free(config_file_to_free);
|
2018-11-04 06:15:38 +08:00
|
|
|
|
2019-02-22 07:25:31 +08:00
|
|
|
if (bkend_use_glx(ps) && !ps->o.experimental_backends) {
|
2019-01-10 05:58:16 +08:00
|
|
|
auto glx_logger = glx_string_marker_logger_new();
|
|
|
|
if (glx_logger) {
|
|
|
|
log_info("Enabling gl string marker");
|
|
|
|
log_add_target_tls(glx_logger);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-26 11:12:28 +08:00
|
|
|
// Initialize software optimization
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.sw_opti)
|
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-08 08:50:58 +08:00
|
|
|
ps->o.sw_opti = swopti_init(ps);
|
2012-10-26 11:12:28 +08:00
|
|
|
|
2013-08-28 21:47:16 +08:00
|
|
|
// Monitor screen changes if vsync_sw is enabled and we are using
|
|
|
|
// an auto-detected refresh rate, or when Xinerama features are enabled
|
|
|
|
if (ps->randr_exists && ((ps->o.sw_opti && !ps->o.refresh_rate)
|
|
|
|
|| ps->o.xinerama_shadow_crop))
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
|
2013-08-28 21:47:16 +08:00
|
|
|
|
2013-08-22 21:15:04 +08:00
|
|
|
cxinerama_upd_scrs(ps);
|
|
|
|
|
2013-01-31 22:53:44 +08:00
|
|
|
// Create registration window
|
2013-03-01 12:41:16 +08:00
|
|
|
if (!ps->reg_win && !register_cm(ps))
|
2013-01-31 22:53:44 +08:00
|
|
|
exit(1);
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
init_atoms(ps);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
{
|
2018-09-24 02:10:46 +08:00
|
|
|
xcb_render_create_picture_value_list_t pa = {
|
|
|
|
.subwindowmode = IncludeInferiors,
|
|
|
|
};
|
2012-11-03 10:30:32 +08:00
|
|
|
|
2019-02-03 23:59:31 +08:00
|
|
|
ps->root_picture = x_create_picture_with_visual_and_pixmap(ps->c,
|
2018-09-28 00:14:44 +08:00
|
|
|
ps->vis, ps->root, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
|
2018-11-03 22:04:18 +08:00
|
|
|
if (ps->overlay != XCB_NONE) {
|
2019-02-03 23:59:31 +08:00
|
|
|
ps->tgt_picture = x_create_picture_with_visual_and_pixmap(ps->c,
|
2018-09-28 00:14:44 +08:00
|
|
|
ps->vis, ps->overlay, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
|
2018-09-24 02:10:46 +08:00
|
|
|
} else
|
2012-11-19 09:46:07 +08:00
|
|
|
ps->tgt_picture = ps->root_picture;
|
2012-10-24 10:09:59 +08:00
|
|
|
}
|
2012-02-27 12:00:12 +08:00
|
|
|
|
2018-10-03 03:22:26 +08:00
|
|
|
ev_io_init(&ps->xiow, x_event_callback, ConnectionNumber(ps->dpy), EV_READ);
|
|
|
|
ev_io_start(ps->loop, &ps->xiow);
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_init(&ps->unredir_timer, tmout_unredir_callback);
|
2018-10-03 03:22:26 +08:00
|
|
|
if (ps->o.sw_opti)
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_idle_init(&ps->draw_idle, delayed_draw_callback);
|
2018-10-03 03:22:26 +08:00
|
|
|
else
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_idle_init(&ps->draw_idle, draw_callback);
|
2018-10-03 03:22:26 +08:00
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_init(&ps->fade_timer, fade_timer_callback);
|
|
|
|
ev_init(&ps->delayed_draw_timer, delayed_draw_timer_callback);
|
2018-10-03 03:22:26 +08:00
|
|
|
|
2018-11-27 07:56:55 +08:00
|
|
|
// Set up SIGUSR1 signal handler to reset program
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_signal_init(&ps->usr1_signal, reset_enable, SIGUSR1);
|
2019-02-12 07:13:39 +08:00
|
|
|
ev_signal_init(&ps->int_signal, exit_enable, SIGINT);
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_signal_start(ps->loop, &ps->usr1_signal);
|
2019-02-12 07:13:39 +08:00
|
|
|
ev_signal_start(ps->loop, &ps->int_signal);
|
2018-11-27 07:56:55 +08:00
|
|
|
|
2018-11-27 07:21:33 +08:00
|
|
|
// xcb can read multiple events from the socket when a request with reply is
|
|
|
|
// made.
|
2018-10-03 03:22:26 +08:00
|
|
|
//
|
|
|
|
// Use an ev_prepare to make sure we cannot accidentally forget to handle them
|
|
|
|
// before we go to sleep.
|
|
|
|
//
|
|
|
|
// If we don't drain the queue before goes to sleep (i.e. blocking on socket
|
|
|
|
// input), we will be sleeping with events available in queue. Which might
|
|
|
|
// cause us to block indefinitely because arrival of new events could be
|
|
|
|
// dependent on processing of existing events (e.g. if we don't process damage
|
2018-11-27 07:21:33 +08:00
|
|
|
// event and do damage subtract, new damage event won't be generated).
|
|
|
|
//
|
|
|
|
// So we make use of a ev_prepare handle, which is called right before libev
|
|
|
|
// goes into sleep, to handle all the queued X events.
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_prepare_init(&ps->event_check, handle_queued_x_events);
|
2018-10-03 03:22:26 +08:00
|
|
|
// Make sure nothing can cause xcb to read from the X socket after events are
|
|
|
|
// handled and before we going to sleep.
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_set_priority(&ps->event_check, EV_MINPRI);
|
|
|
|
ev_prepare_start(ps->loop, &ps->event_check);
|
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-08 08:50:58 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_grab_server(ps->c);
|
2011-11-04 14:33:23 +08:00
|
|
|
|
2018-12-21 06:31:34 +08:00
|
|
|
// Initialize DBus. We need to do this early, because add_win might call dbus functions
|
|
|
|
if (ps->o.dbus) {
|
|
|
|
#ifdef CONFIG_DBUS
|
2018-12-21 07:42:38 +08:00
|
|
|
cdbus_init(ps, DisplayString(ps->dpy));
|
2018-12-21 06:31:34 +08:00
|
|
|
if (!ps->dbus_data) {
|
|
|
|
ps->o.dbus = false;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
log_fatal("DBus support not compiled in!");
|
|
|
|
exit(1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
{
|
2018-10-03 21:06:16 +08:00
|
|
|
xcb_window_t *children;
|
|
|
|
int nchildren;
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c,
|
|
|
|
xcb_query_tree(ps->c, ps->root), NULL);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2018-10-03 21:06:16 +08:00
|
|
|
if (reply) {
|
|
|
|
children = xcb_query_tree_children(reply);
|
|
|
|
nchildren = xcb_query_tree_children_length(reply);
|
|
|
|
} else {
|
|
|
|
children = NULL;
|
|
|
|
nchildren = 0;
|
2012-11-19 09:46:07 +08:00
|
|
|
}
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2018-10-03 21:06:16 +08:00
|
|
|
for (int i = 0; i < nchildren; i++) {
|
|
|
|
add_win(ps, children[i], i ? children[i-1] : XCB_NONE);
|
|
|
|
}
|
|
|
|
|
2019-02-21 10:29:06 +08:00
|
|
|
for (win *i = ps->list; i; i = i->next) {
|
|
|
|
if (i->a.map_state == XCB_MAP_STATE_VIEWABLE) {
|
|
|
|
map_win(ps, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-03 21:06:16 +08:00
|
|
|
free(reply);
|
2019-02-20 08:17:23 +08:00
|
|
|
log_trace("Initial stack:");
|
|
|
|
for (win *c = ps->list; c; c = c->next) {
|
2019-02-20 09:21:58 +08:00
|
|
|
log_trace("%#010x \"%s\"", c->id, c->name);
|
2019-02-20 08:17:23 +08:00
|
|
|
}
|
2011-11-04 14:33:23 +08:00
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
if (ps->o.track_focus) {
|
|
|
|
recheck_focus(ps);
|
2012-09-13 23:12:54 +08:00
|
|
|
}
|
2012-09-13 21:38:55 +08:00
|
|
|
|
2019-02-07 08:41:24 +08:00
|
|
|
e = xcb_request_check(ps->c, xcb_ungrab_server(ps->c));
|
|
|
|
if (e) {
|
|
|
|
log_error("Failed to ungrad server");
|
|
|
|
free(e);
|
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2019-02-08 09:27:46 +08:00
|
|
|
write_pid(ps);
|
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-08 08:50:58 +08:00
|
|
|
|
2019-02-08 09:27:46 +08:00
|
|
|
if (fork && stderr_logger) {
|
|
|
|
// Remove the stderr logger if we will fork
|
|
|
|
log_remove_target_tls(stderr_logger);
|
2018-12-22 06:49:42 +08:00
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
return ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroy a session.
|
|
|
|
*
|
|
|
|
* Does not close the X connection or free the <code>session_t</code>
|
|
|
|
* structure, though.
|
|
|
|
*
|
|
|
|
* @param ps session to destroy
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
session_destroy(session_t *ps) {
|
|
|
|
redir_stop(ps);
|
|
|
|
|
|
|
|
// Stop listening to events on root window
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK,
|
2018-10-03 20:34:24 +08:00
|
|
|
(const uint32_t[]) { 0 });
|
2011-11-04 14:33:23 +08:00
|
|
|
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
#ifdef CONFIG_DBUS
|
|
|
|
// Kill DBus connection
|
2018-12-21 06:31:34 +08:00
|
|
|
if (ps->o.dbus) {
|
|
|
|
assert(ps->dbus_data);
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
cdbus_destroy(ps);
|
2018-12-21 06:31:34 +08:00
|
|
|
}
|
Feature #80: D-Bus support
- Add D-Bus support. Currently 7 methods are available: "reset" (same as
SIGUSR1), "list_win" (list the windows compton manages), "win_get"
(get a property of the window), "win_set" (set a property of the
window), "find_win" (find window based on client window / focus),
"opts_get" (get the value of a compton option), and "opts_set" (set
the value of a compton option), together with 4 signals: "win_added",
"win_destroyed", "win_mapped", "win_unmapped".
- D-Bus support depends on libdbus.
- As there are many items and my time is tight, no much tests are done.
Bugs to be expected.
- Create a new header file `common.h` that contains shared content.
- Fix some bugs in timeout handling.
- Update file headers in all source files.
- Re-enable --unredir-if-possible on multi-screen set-ups, as the user
could turn if off manually anyway.
- Check if the window is mapped in `repair_win()`.
- Add ps->track_atom_lst and its handlers, to prepare for the new
condition format.
- Known issue 1: "win_get", "win_set", "opts_get", "opts_set" support a
very limited number of targets only. New ones will be added gradually.
- Known issue 2: Accidental drop of D-Bus connection is not handled.
- Known issue 3: Introspection does not reveal all available methods,
because some methods have unpredictable prototypes. Still hesitating
about what to do...
- Known issue 4: Error handling is not finished yet. Compton does not
always reply with the correct error message (but it does print out the
correct error message, usually).
2013-01-19 20:20:27 +08:00
|
|
|
#endif
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// Free window linked list
|
|
|
|
{
|
|
|
|
win *next = NULL;
|
2019-02-03 03:42:05 +08:00
|
|
|
win *list = ps->list;
|
|
|
|
ps->list = NULL;
|
|
|
|
|
|
|
|
for (win *w = list; w; w = next) {
|
2012-11-19 09:46:07 +08:00
|
|
|
next = w->next;
|
2011-11-04 16:41:56 +08:00
|
|
|
|
2019-02-20 09:21:58 +08:00
|
|
|
if (w->state != WSTATE_DESTROYING) {
|
2012-11-19 09:46:07 +08:00
|
|
|
win_ev_stop(ps, w);
|
2019-02-20 09:21:58 +08: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-08 10:20:01 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
free_win_res(ps, w);
|
|
|
|
free(w);
|
|
|
|
}
|
|
|
|
}
|
2012-11-08 19:39:13 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// Free blacklists
|
|
|
|
free_wincondlst(&ps->o.shadow_blacklist);
|
|
|
|
free_wincondlst(&ps->o.fade_blacklist);
|
2013-01-12 22:21:35 +08:00
|
|
|
free_wincondlst(&ps->o.focus_blacklist);
|
|
|
|
free_wincondlst(&ps->o.invert_color_list);
|
2013-04-25 22:23:35 +08:00
|
|
|
free_wincondlst(&ps->o.blur_background_blacklist);
|
2013-05-21 09:18:41 +08:00
|
|
|
free_wincondlst(&ps->o.opacity_rules);
|
2013-06-19 19:36:48 +08:00
|
|
|
free_wincondlst(&ps->o.paint_blacklist);
|
2013-09-04 22:00:51 +08:00
|
|
|
free_wincondlst(&ps->o.unredir_if_possible_blacklist);
|
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 21:39:38 +08:00
|
|
|
|
|
|
|
// Free tracked atom list
|
|
|
|
{
|
|
|
|
latom_t *next = NULL;
|
|
|
|
for (latom_t *this = ps->track_atom_lst; this; this = next) {
|
|
|
|
next = this->next;
|
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
ps->track_atom_lst = NULL;
|
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
// Free ignore linked list
|
|
|
|
{
|
|
|
|
ignore_t *next = NULL;
|
|
|
|
for (ignore_t *ign = ps->ignore_head; ign; ign = next) {
|
|
|
|
next = ign->next;
|
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-08 10:20:01 +08:00
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
free(ign);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset head and tail
|
|
|
|
ps->ignore_head = NULL;
|
|
|
|
ps->ignore_tail = &ps->ignore_head;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free tgt_{buffer,picture} and root_picture
|
2013-12-10 22:06:02 +08:00
|
|
|
if (ps->tgt_buffer.pict == ps->tgt_picture)
|
2018-12-28 04:45:38 +08:00
|
|
|
ps->tgt_buffer.pict = XCB_NONE;
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
if (ps->tgt_picture == ps->root_picture)
|
2018-12-28 04:45:38 +08:00
|
|
|
ps->tgt_picture = XCB_NONE;
|
2012-11-19 09:46:07 +08:00
|
|
|
else
|
2018-12-16 05:11:41 +08:00
|
|
|
free_picture(ps->c, &ps->tgt_picture);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2018-12-16 05:11:41 +08:00
|
|
|
free_picture(ps->c, &ps->root_picture);
|
2013-12-10 22:06:02 +08:00
|
|
|
free_paint(ps, &ps->tgt_buffer);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
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-30 11:56:00 +08:00
|
|
|
pixman_region32_fini(&ps->screen_reg);
|
2012-11-19 09:46:07 +08:00
|
|
|
free(ps->expose_rects);
|
2013-11-09 21:38:31 +08:00
|
|
|
|
|
|
|
free(ps->o.write_pid_path);
|
2013-01-11 21:31:02 +08:00
|
|
|
free(ps->o.logpath);
|
2013-05-20 18:04:40 +08:00
|
|
|
for (int i = 0; i < MAX_BLUR_PASS; ++i) {
|
|
|
|
free(ps->o.blur_kerns[i]);
|
|
|
|
free(ps->blur_kerns_cache[i]);
|
|
|
|
}
|
2014-05-16 15:18:17 +08:00
|
|
|
free(ps->o.glx_fshader_win_str);
|
2013-08-22 21:15:04 +08:00
|
|
|
free_xinerama_info(ps);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
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-08 08:50:58 +08:00
|
|
|
#ifdef CONFIG_VSYNC_DRM
|
2012-11-19 09:46:07 +08:00
|
|
|
// Close file opened for DRM VSync
|
2013-01-31 22:53:44 +08:00
|
|
|
if (ps->drm_fd >= 0) {
|
2012-11-19 09:46:07 +08:00
|
|
|
close(ps->drm_fd);
|
2013-01-31 22:53:44 +08:00
|
|
|
ps->drm_fd = -1;
|
2012-11-19 09:46:07 +08:00
|
|
|
}
|
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-08 08:50:58 +08:00
|
|
|
#endif
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
// Release overlay window
|
|
|
|
if (ps->overlay) {
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_composite_release_overlay_window(ps->c, ps->overlay);
|
2018-12-28 04:45:38 +08:00
|
|
|
ps->overlay = XCB_NONE;
|
2012-11-19 09:46:07 +08:00
|
|
|
}
|
|
|
|
|
2018-12-30 15:41:31 +08:00
|
|
|
if (ps->sync_fence) {
|
|
|
|
xcb_sync_destroy_fence(ps->c, ps->sync_fence);
|
|
|
|
ps->sync_fence = XCB_NONE;
|
|
|
|
}
|
|
|
|
|
2013-03-15 23:16:23 +08:00
|
|
|
// Free reg_win
|
|
|
|
if (ps->reg_win) {
|
2018-10-03 21:27:48 +08:00
|
|
|
xcb_destroy_window(ps->c, ps->reg_win);
|
2018-12-28 04:45:38 +08:00
|
|
|
ps->reg_win = XCB_NONE;
|
2013-03-15 23:16:23 +08:00
|
|
|
}
|
|
|
|
|
2019-02-09 23:52:40 +08:00
|
|
|
if (ps->o.experimental_backends) {
|
|
|
|
// backend is deinitialized in redir_stop
|
|
|
|
assert(ps->backend_data == NULL);
|
|
|
|
} else {
|
|
|
|
deinit_render(ps);
|
|
|
|
}
|
|
|
|
|
2019-02-21 02:21:40 +08:00
|
|
|
// Free the damage ring
|
|
|
|
for (int i = 0; i < ps->ndamage; ++i) {
|
|
|
|
pixman_region32_fini(&ps->damage_ring[i]);
|
|
|
|
}
|
|
|
|
ps->ndamage = 0;
|
|
|
|
free(ps->damage_ring);
|
|
|
|
ps->damage_ring = ps->damage = NULL;
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// Flush all events
|
2018-10-03 21:27:48 +08:00
|
|
|
x_sync(ps->c);
|
2018-10-03 03:22:26 +08:00
|
|
|
ev_io_stop(ps->loop, &ps->xiow);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2014-08-03 19:40:40 +08:00
|
|
|
#ifdef DEBUG_XRC
|
|
|
|
// Report about resource leakage
|
|
|
|
xrc_report_xid();
|
|
|
|
#endif
|
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
// Stop libev event handlers
|
|
|
|
ev_timer_stop(ps->loop, &ps->unredir_timer);
|
|
|
|
ev_timer_stop(ps->loop, &ps->fade_timer);
|
|
|
|
ev_idle_stop(ps->loop, &ps->draw_idle);
|
|
|
|
ev_prepare_stop(ps->loop, &ps->event_check);
|
|
|
|
ev_signal_stop(ps->loop, &ps->usr1_signal);
|
2019-02-12 07:13:39 +08:00
|
|
|
ev_signal_stop(ps->loop, &ps->int_signal);
|
2018-11-27 07:56:55 +08:00
|
|
|
|
2018-12-20 07:10:58 +08:00
|
|
|
log_deinit_tls();
|
2012-11-19 09:46:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Do the actual work.
|
|
|
|
*
|
|
|
|
* @param ps current session
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
session_run(session_t *ps) {
|
|
|
|
if (ps->o.sw_opti)
|
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-08 08:50:58 +08:00
|
|
|
ps->paint_tm_offset = get_time_timeval().tv_usec;
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2018-11-27 08:32:08 +08:00
|
|
|
// In benchmark mode, we want draw_idle handler to always be active
|
2019-02-09 23:50:40 +08:00
|
|
|
if (ps->o.benchmark) {
|
2018-11-27 08:32:08 +08:00
|
|
|
ev_idle_start(ps->loop, &ps->draw_idle);
|
2019-02-09 23:50:40 +08:00
|
|
|
} else {
|
|
|
|
// Let's draw our first frame!
|
|
|
|
queue_redraw(ps);
|
|
|
|
}
|
2018-10-03 03:22:26 +08:00
|
|
|
ev_run(ps->loop, 0);
|
2003-11-09 15:08:23 +08:00
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The function that everybody knows.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
main(int argc, char **argv) {
|
|
|
|
// Set locale so window names with special characters are interpreted
|
|
|
|
// correctly
|
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
|
2019-02-08 06:29:24 +08:00
|
|
|
int exit_code;
|
|
|
|
char *config_file = NULL;
|
2019-02-08 09:27:46 +08:00
|
|
|
bool all_xerrors = false, need_fork = false;
|
|
|
|
if (get_early_config(argc, argv, &config_file, &all_xerrors, &need_fork, &exit_code)) {
|
2019-02-08 06:29:24 +08:00
|
|
|
return exit_code;
|
|
|
|
}
|
|
|
|
|
2019-02-08 09:27:46 +08:00
|
|
|
int pfds[2];
|
|
|
|
if (need_fork) {
|
|
|
|
if (pipe2(pfds, O_CLOEXEC)) {
|
|
|
|
perror("pipe2");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
auto pid = fork();
|
|
|
|
if (pid < 0) {
|
|
|
|
perror("fork");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (pid > 0) {
|
|
|
|
// We are the parent
|
|
|
|
close(pfds[1]);
|
|
|
|
// We wait for the child to tell us it has finished initialization
|
|
|
|
// by sending us something via the pipe.
|
|
|
|
int tmp;
|
|
|
|
if (read(pfds[0], &tmp, sizeof tmp) <= 0) {
|
|
|
|
// Failed to read, the child has most likely died
|
|
|
|
// We can probably waitpid() here.
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
// We are done
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We are the child
|
|
|
|
close(pfds[0]);
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:46:07 +08:00
|
|
|
// Main loop
|
2018-10-03 03:22:26 +08:00
|
|
|
bool quit = false;
|
2019-02-08 06:29:24 +08:00
|
|
|
Display *dpy = XOpenDisplay(NULL);
|
|
|
|
if (!dpy) {
|
|
|
|
log_fatal("Can't open display.");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
|
|
|
|
|
|
|
|
do {
|
2019-02-08 09:27:46 +08:00
|
|
|
ps_g = session_init(argc, argv, dpy, config_file, all_xerrors, need_fork);
|
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-08 08:50:58 +08:00
|
|
|
if (!ps_g) {
|
2018-12-20 10:49:29 +08:00
|
|
|
log_fatal("Failed to create new compton session.");
|
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-08 08:50:58 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2019-02-08 09:27:46 +08:00
|
|
|
if (need_fork) {
|
|
|
|
// Finishing up daemonization
|
|
|
|
// Close files
|
|
|
|
if (fclose(stdout) || fclose(stderr) || fclose(stdin)) {
|
|
|
|
log_fatal("Failed to close standard input/output");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
// Make us the session and process group leader so we don't get killed when
|
|
|
|
// our parent die.
|
|
|
|
setsid();
|
|
|
|
// Notify the parent that we are done. This might cause the parent to quit,
|
|
|
|
// so only do this after setsid()
|
|
|
|
int tmp = 1;
|
|
|
|
write(pfds[1], &tmp, sizeof tmp);
|
|
|
|
close(pfds[1]);
|
|
|
|
// We only do this once
|
|
|
|
need_fork = false;
|
|
|
|
}
|
2012-11-19 09:46:07 +08:00
|
|
|
session_run(ps_g);
|
2018-10-03 03:22:26 +08:00
|
|
|
quit = ps_g->quit;
|
2012-11-19 09:46:07 +08:00
|
|
|
session_destroy(ps_g);
|
2019-02-08 06:29:24 +08:00
|
|
|
free(ps_g);
|
2019-02-18 00:59:00 +08:00
|
|
|
ps_g = NULL;
|
2019-02-08 06:29:24 +08:00
|
|
|
} while (!quit);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
2019-02-08 06:29:24 +08:00
|
|
|
if (dpy) {
|
|
|
|
XCloseDisplay(dpy);
|
|
|
|
}
|
|
|
|
free(config_file);
|
2012-11-19 09:46:07 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-08-12 01:22:49 +08:00
|
|
|
|
|
|
|
// vim: set et sw=2 :
|