Skip to content

Commit

Permalink
Merge branch 'yshui:next' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
pijulius committed Jul 30, 2024
2 parents b8fe932 + 76af408 commit e489a48
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 54 deletions.
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 14 additions & 6 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,19 @@
(final: prev: {
stdenv = prev.withCFlags "-fno-omit-frame-pointer" prev.stdenv;
})
(final: prev: {
llvmPackages_18 = prev.llvmPackages_18 // {
stdenv = final.withCFlags "-fno-omit-frame-pointer" prev.llvmPackages_18.stdenv;
};
})
];
};

overlays = [overlay];
mkDevShell = p: p.overrideAttrs (o: {
nativeBuildInputs = o.nativeBuildInputs ++ (with pkgs; [
clang-tools_17
llvmPackages_17.clang-unwrapped.python
clang-tools_18
llvmPackages_18.clang-unwrapped.python
python
]);
hardeningDisable = ["fortify"];
Expand All @@ -72,15 +77,18 @@
overlay
overlays
;
defaultPackage = pkgs.picom;
devShells.default = mkDevShell defaultPackage;
packages = {
default = pkgs.picom;
llvm = profilePkgs.llvm_18;
};
devShells.default = mkDevShell packages.default;
devShells.useClang = devShells.default.override {
inherit (pkgs.llvmPackages_17) stdenv;
inherit (pkgs.llvmPackages_18) stdenv;
};
# build picom and all dependencies with frame pointer, making profiling/debugging easier.
# WARNING! many many rebuilds
devShells.useClangProfile = (mkDevShell profilePkgs.picom).override {
stdenv = profilePkgs.withCFlags "-fno-omit-frame-pointer" profilePkgs.llvmPackages_17.stdenv;
stdenv = profilePkgs.withCFlags "-fno-omit-frame-pointer" profilePkgs.llvmPackages_18.stdenv;
};
});
}
2 changes: 2 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ typedef struct session {
struct render_statistics render_stats;

// === Operation related ===
/// Whether there is a pending quest to get the focused window
bool pending_focus_check;
/// Flags related to the root window
uint64_t root_flags;
/// Program options.
Expand Down
49 changes: 32 additions & 17 deletions src/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ update_ewmh_active_win(struct x_connection * /*c*/, struct x_async_request_base
auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps;
free(req_base);

ps->pending_focus_check = false;
if (reply_or_error->response_type == 0) {
log_error("Failed to get _NET_ACTIVE_WINDOW: %s",
x_strerror(((xcb_generic_error_t *)reply_or_error)));
Expand Down Expand Up @@ -247,6 +248,8 @@ static void recheck_focus(struct x_connection * /*c*/, struct x_async_request_ba
auto ps = ((struct ev_ewmh_active_win_request *)req_base)->ps;
free(req_base);

ps->pending_focus_check = false;

// Determine the currently focused window so we can apply appropriate
// opacity on it
if (reply_or_error->response_type == 0) {
Expand Down Expand Up @@ -288,18 +291,39 @@ static void recheck_focus(struct x_connection * /*c*/, struct x_async_request_ba
}
}

void ev_update_focused(struct session *ps) {
if (ps->pending_focus_check) {
return;
}

if (ps->o.use_ewmh_active_win) {
auto req = ccalloc(1, struct ev_ewmh_active_win_request);
req->base.sequence =
xcb_get_property(ps->c.c, 0, ps->c.screen_info->root,
ps->atoms->a_NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, 1)
.sequence;
req->base.callback = update_ewmh_active_win;
req->ps = ps;
x_await_request(&ps->c, &req->base);
log_debug("Started async request to get _NET_ACTIVE_WINDOW");
} else {
auto req = ccalloc(1, struct ev_recheck_focus_request);
req->base.sequence = xcb_get_input_focus(ps->c.c).sequence;
req->base.callback = recheck_focus;
req->ps = ps;
x_await_request(&ps->c, &req->base);
log_debug("Started async request to recheck focus");
}

ps->pending_focus_check = true;
}

static inline void ev_focus_change(session_t *ps) {
if (ps->o.use_ewmh_active_win) {
// Not using focus_in/focus_out events.
return;
}

auto req = ccalloc(1, struct ev_recheck_focus_request);
req->base.sequence = xcb_get_input_focus(ps->c.c).sequence;
req->base.callback = recheck_focus;
req->ps = ps;
x_await_request(&ps->c, &req->base);
log_debug("Started async request to recheck focus");
ev_update_focused(ps);
}

static inline void ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) {
Expand Down Expand Up @@ -569,16 +593,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
}

if (ps->o.use_ewmh_active_win && ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
auto req = ccalloc(1, struct ev_ewmh_active_win_request);
req->base.sequence =
xcb_get_property(ps->c.c, 0, ps->c.screen_info->root,
ps->atoms->a_NET_ACTIVE_WINDOW,
XCB_ATOM_WINDOW, 0, 1)
.sequence;
req->base.callback = update_ewmh_active_win;
req->ps = ps;
x_await_request(&ps->c, &req->base);
log_debug("Started async request to get _NET_ACTIVE_WINDOW");
ev_update_focused(ps);
} else {
// Destroy the root "image" if the wallpaper probably changed
if (x_is_root_back_pixmap_atom(ps->atoms, ev->atom)) {
Expand Down
1 change: 1 addition & 0 deletions src/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
#include "common.h"

void ev_handle(session_t *ps, xcb_generic_event_t *ev);
void ev_update_focused(struct session *ps);
13 changes: 11 additions & 2 deletions src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,7 @@ static void handle_new_windows(session_t *ps) {
wm_ref_win_id(wm_change.toplevel),
wm_change.client.new_.x);
}
ev_update_focused(ps);
break;
case WM_TREE_CHANGE_TOPLEVEL_RESTACKED: invalidate_reg_ignore(ps); break;
default: unreachable();
Expand All @@ -1605,9 +1606,17 @@ static void handle_new_windows(session_t *ps) {
static void refresh_windows(session_t *ps) {
wm_stack_foreach(ps->wm, cursor) {
auto w = wm_ref_deref(cursor);
if (w != NULL) {
win_process_update_flags(ps, w);
if (w == NULL) {
continue;
}
win_process_primary_flags(ps, w);
}
wm_stack_foreach(ps->wm, cursor) {
auto w = wm_ref_deref(cursor);
if (w == NULL) {
continue;
}
win_process_secondary_flags(ps, w);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/vblank.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ static void *sgi_video_sync_thread(void *data) {
pthread_mutex_unlock(&args->start_mtx);

cleanup:
log_deinit_tls();
if (dpy) {
glXMakeCurrent(dpy, None, NULL);
if (ctx) {
Expand Down
3 changes: 3 additions & 0 deletions src/wm/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ enum win_flags {
WIN_FLAGS_PIXMAP_STALE = 1,
/// there was an error binding the window pixmap
WIN_FLAGS_PIXMAP_ERROR = 4,
/// Window is damaged, and should be added to the damage region
/// (only used by the legacy backends, remove)
WIN_FLAGS_DAMAGED = 8,
/// the client window needs to be updated
WIN_FLAGS_CLIENT_STALE = 32,
/// the window is mapped by X, we need to call map_win_start for it
Expand Down
62 changes: 37 additions & 25 deletions src/wm/win.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,9 @@ win_get_leader_property(struct x_connection *c, struct atom *atoms, xcb_window_t

static struct wm_ref *win_get_leader_raw(session_t *ps, struct win *w, int recursions);

/**
* Get the leader of a window.
*
* This function updates w->cache_leader if necessary.
*/
/// Get the leader of a window.
///
/// This function updates w->cache_leader if necessary.
static inline struct wm_ref *win_get_leader(session_t *ps, struct win *w) {
return win_get_leader_raw(ps, w, 0);
}
Expand Down Expand Up @@ -172,13 +170,7 @@ static inline void group_on_factor_change(session_t *ps, struct wm_ref *leader)
}
}

/**
* Return whether a window group is really focused.
*
* @param leader leader window ID
* @return true if the window group is focused, false otherwise
*/
static inline bool group_is_focused(session_t *ps, struct wm_ref *leader) {
static inline bool win_is_group_focused_inner(session_t *ps, struct wm_ref *leader) {
if (!leader) {
return false;
}
Expand All @@ -198,6 +190,15 @@ static inline bool group_is_focused(session_t *ps, struct wm_ref *leader) {
return false;
}

bool win_is_group_focused(session_t *ps, struct win *w) {
if (w->state != WSTATE_MAPPED) {
return false;
}

auto leader = win_get_leader(ps, w);
return win_is_group_focused_inner(ps, leader);
}

/**
* Set leader of a window.
*/
Expand All @@ -214,7 +215,7 @@ static inline void win_set_leader(session_t *ps, struct win *w, xcb_window_t nle
}
auto i = wm_ref_deref(cursor);
if (i != NULL) {
i->cache_leader = XCB_NONE;
i->cache_leader = NULL;
}
}

Expand Down Expand Up @@ -434,8 +435,9 @@ static void win_update_properties(session_t *ps, struct win *w) {
win_clear_all_properties_stale(w);
}

/// Handle non-image flags. This phase might set IMAGES_STALE flags
void win_process_update_flags(session_t *ps, struct win *w) {
/// Handle primary flags. These flags are set as direct results of raw X11 window data
/// changes.
void win_process_primary_flags(session_t *ps, struct win *w) {
log_trace("Processing flags for window %#010x (%s), was rendered: %d, flags: "
"%#" PRIx64,
win_id(w), w->name, w->to_paint, w->flags);
Expand All @@ -451,7 +453,6 @@ void win_process_update_flags(session_t *ps, struct win *w) {
return;
}

bool damaged = false;
if (win_check_flags_all(w, WIN_FLAGS_CLIENT_STALE)) {
win_on_client_update(ps, w);
win_clear_flags(w, WIN_FLAGS_CLIENT_STALE);
Expand Down Expand Up @@ -490,12 +491,12 @@ void win_process_update_flags(session_t *ps, struct win *w) {
ps->o.shadow_offset_y, ps->o.shadow_radius);
win_update_bounding_shape(&ps->c, w, ps->shape_exists,
ps->o.detect_rounded_corners);
damaged = true;
win_clear_flags(w, WIN_FLAGS_SIZE_STALE);

// Window shape/size changed, invalidate the images we built
// log_trace("free out dated pict");
win_set_flags(w, WIN_FLAGS_PIXMAP_STALE | WIN_FLAGS_FACTOR_CHANGED);
win_set_flags(w, WIN_FLAGS_PIXMAP_STALE |
WIN_FLAGS_FACTOR_CHANGED | WIN_FLAGS_DAMAGED);

win_release_mask(ps->backend_data, w);
win_release_shadow(ps->backend_data, w);
Expand All @@ -505,27 +506,38 @@ void win_process_update_flags(session_t *ps, struct win *w) {
}

if (win_check_flags_all(w, WIN_FLAGS_POSITION_STALE)) {
damaged = true;
win_clear_flags(w, WIN_FLAGS_POSITION_STALE);
win_set_flags(w, WIN_FLAGS_DAMAGED);
}
}

if (win_check_flags_all(w, WIN_FLAGS_PROPERTY_STALE)) {
win_update_properties(ps, w);
win_clear_flags(w, WIN_FLAGS_PROPERTY_STALE);
}
}

/// Handle secondary flags. These flags are set during the processing of primary flags.
/// Flags are separated into primaries and secondaries because processing of secondary
/// flags must happen after primary flags of ALL windows are processed, to make sure some
/// global states (e.g. active window group) are consistent because they will be used in
/// the processing of secondary flags.
void win_process_secondary_flags(session_t *ps, struct win *w) {
if (w->flags == 0 || w->state != WSTATE_MAPPED) {
return;
}

// Factor change flags could be set by previous stages, so must be handled
// last
if (win_check_flags_all(w, WIN_FLAGS_FACTOR_CHANGED)) {
win_on_factor_change(ps, w);
win_clear_flags(w, WIN_FLAGS_FACTOR_CHANGED);
}

// Add damage, has to be done last so the window has the latest geometry
// information.
if (damaged) {
if (win_check_flags_all(w, WIN_FLAGS_DAMAGED)) {
// Add damage, has to be done last so the window has the latest geometry
// information.
add_damage_from_win(ps, w);
win_clear_flags(w, WIN_FLAGS_DAMAGED);
}
}

Expand Down Expand Up @@ -1385,7 +1397,7 @@ struct win *win_maybe_allocate(session_t *ps, struct wm_ref *cursor,

.mode = WMODE_TRANS,
.leader = XCB_NONE,
.cache_leader = XCB_NONE,
.cache_leader = NULL,
.window_type = WINTYPE_UNKNOWN,
.opacity_prop = OPAQUE,
.opacity_set = 1,
Expand Down Expand Up @@ -1637,7 +1649,7 @@ static void win_on_focus_change(session_t *ps, struct win *w) {
}
// If the group get unfocused, remove it from active_leader
else if (!win_is_focused_raw(w) && leader && leader == active_leader &&
!group_is_focused(ps, leader)) {
!win_is_group_focused_inner(ps, leader)) {
wm_set_active_leader(ps->wm, XCB_NONE);
group_on_factor_change(ps, leader);
}
Expand Down
9 changes: 8 additions & 1 deletion src/wm/win.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,8 @@ static const struct script_output_info win_script_outputs[] = {
/// state change.
bool win_process_animation_and_state_change(struct session *ps, struct win *w, double delta_t);
double win_animatable_get(const struct win *w, enum win_script_output output);
void win_process_update_flags(session_t *ps, struct win *w);
void win_process_primary_flags(session_t *ps, struct win *w);
void win_process_secondary_flags(session_t *ps, struct win *w);
void win_process_image_flags(session_t *ps, struct win *w);

/// Start the unmap of a window. We cannot unmap immediately since we might need to fade
Expand Down Expand Up @@ -427,6 +428,12 @@ void win_destroy_finish(session_t *ps, struct win *w);
*/
bool attr_pure win_is_focused_raw(const struct win *w);

/// Return whether the group a window belongs to is really focused.
///
/// @param leader leader window ID
/// @return true if the window group is focused, false otherwise
bool win_is_group_focused(session_t *ps, struct win *w);

/// check if window has ARGB visual
bool attr_pure win_has_alpha(const struct win *w);

Expand Down

0 comments on commit e489a48

Please sign in to comment.