Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve monitor event handling #1069

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 27 additions & 46 deletions fvwm/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -1775,10 +1775,10 @@ static void _refocus_stolen_focus_win(const evh_args_t *ea)

/* ---------------------------- event handlers ----------------------------- */

void monitor_update_ewmh(void)
static void monitor_update_ewmh(void)
{
FvwmWindow *t;
struct monitor *m, *mref, *mo, *mo1;
struct monitor *m, *mref;

if (Scr.bo.do_debug_randr)
{
Expand All @@ -1789,21 +1789,6 @@ void monitor_update_ewmh(void)

RB_FOREACH(m, monitors, &monitor_q) {
if (m->flags & MONITOR_CHANGED) {
fvwm_debug(__func__, "Applying EWMH changes to "
"existing %s", m->si->name);
TAILQ_FOREACH(mo, &monitorsold_q, oentry) {
if (strcmp(m->si->name, mo->si->name) != 0)
continue;
if (mo->Desktops == NULL)
continue;
for (t = Scr.FvwmRoot.next; t; t = t->next) {
if (t->m == mo) {
t->m = m;
update_fvwm_monitor(t);
}
}
m->emit |= MONITOR_CHANGED;
}
m->flags &= ~MONITOR_CHANGED;
continue;
}
Expand Down Expand Up @@ -1831,17 +1816,10 @@ void monitor_update_ewmh(void)
m->virtual_scr.Vy = 0;

set_ewmhc_strut_values(m, ewbs);

m->flags &= ~MONITOR_NEW;
}
EWMH_Init(m);

/* Clear the flag now that it's been registered. */
m->flags &= ~MONITOR_NEW;
}

TAILQ_FOREACH_SAFE(mo, &monitorsold_q, oentry, mo1) {
TAILQ_REMOVE(&monitorsold_q, mo, oentry);
fvwm_debug(__func__, "Removed mo '%s' from processing",
mo->si->name);
}


Expand All @@ -1852,7 +1830,7 @@ void monitor_update_ewmh(void)
}
}

void
static void
monitor_emit_broadcast(void)
{
struct monitor *m;
Expand All @@ -1861,44 +1839,37 @@ monitor_emit_broadcast(void)
RB_FOREACH (m, monitors, &monitor_q) {
if (m->emit > 0)
fvwm_debug(__func__, "%s: emit: %d\n", m->si->name, m->emit);
if (m->emit &= ~MONITOR_CHANGED) {
if (m->emit & MONITOR_CHANGED) {
fvwm_debug(__func__, "%s: emit monitor changed", m->si->name);
BroadcastName(
MX_MONITOR_CHANGED, -1, -1, -1, m->si->name);
m->emit &= ~MONITOR_CHANGED;

/* Run the RandRFunc in case a user has set it. */
execute_function_override_window(
NULL, NULL, randrfunc, NULL, 0, NULL);
}
if (m->emit &= ~MONITOR_ENABLED) {
if (m->emit & MONITOR_ENABLED) {
fvwm_debug(__func__, "%s: emit monitor enabled", m->si->name);
BroadcastName(
MX_MONITOR_ENABLED, -1, -1, -1, m->si->name);

/* Run the RandRFunc in case a user has set it. */
execute_function_override_window(
NULL, NULL, randrfunc, NULL, 0, NULL);
}
if (m->emit &= ~MONITOR_DISABLED) {
fvwm_debug(__func__, "MONITOR DISABLED: %s", m->si->name);
if (m->emit & MONITOR_DISABLED) {
fvwm_debug(__func__, "%s: emit monitor disabled", m->si->name);
BroadcastName(
MX_MONITOR_DISABLED, -1, -1, -1, m->si->name);

/* Run the RandRFunc in case a user has set it. */
execute_function_override_window(
NULL, NULL, randrfunc, NULL, 0, NULL);
}

if (m->flags & MONITOR_PRIMARY) {
struct monitor *pm = m, *mnew;

if ((mnew = monitor_by_last_primary()) == NULL)
break;
if ((m->flags & MONITOR_PRIMARY) &&
(m != monitor_by_last_primary())) {
fvwm_debug(__func__, "%s: emit monitor primary change", m->si->name);

if (pm != mnew) {
fvwm_debug(__func__, "MONITOR PRIMARY");
execute_function_override_window(
NULL, NULL, randrfunc, NULL, 0, NULL);
}
execute_function_override_window(
NULL, NULL, randrfunc, NULL, 0, NULL);
}
}
}
Expand Down Expand Up @@ -4152,11 +4123,21 @@ void dispatch_event(XEvent *e)
Window w = e->xany.window;
FvwmWindow *fw;
event_group_t *event_group;
static unsigned long prev_serial = 0;

XFlush(dpy);

switch (e->type - randr_event) {
case RRScreenChangeNotify:
/* Avoid processing identical RandR events twice. */
if (e->xany.serial == prev_serial)
{
fvwm_debug(__func__, "Ignoring duplicate event %lu\n",
e->xany.serial);
break;
}
prev_serial = e->xany.serial;

XRRUpdateConfiguration(e);
monitor_output_change(e->xany.display, NULL);
monitor_update_ewmh();
Expand Down Expand Up @@ -4807,4 +4788,4 @@ void CMD_XSync(F_CMD_ARGS)
XSync(dpy, 0);

return;
}
}
68 changes: 39 additions & 29 deletions libs/FScreen.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ enum monitor_tracking monitor_mode;
bool is_tracking_shared;
struct screen_infos screen_info_q, screen_info_q_temp;
struct monitors monitor_q;
struct monitorsold monitorsold_q;
int randr_event;
const char *prev_focused_monitor;
static struct monitor *monitor_global = NULL;
Expand Down Expand Up @@ -348,17 +347,6 @@ monitor_by_last_primary(void)
return (m);
}

int changed_monitor_count(void)
{
struct monitor *m;
int c = 0;

TAILQ_FOREACH(m, &monitorsold_q, oentry)
c++;

return (c);
}

static void
monitor_check_primary(void)
{
Expand Down Expand Up @@ -510,15 +498,13 @@ monitor_mark_changed(struct monitor *m, XRRMonitorInfo *rrm)
m->si->w != rrm->width ||
m->si->h != rrm->height) {
m->flags |= MONITOR_CHANGED;
m->emit |= MONITOR_CHANGED;

fvwm_debug(__func__, "%s: x: %d, y: %d, w: %d, h: %d "
"comp: x: %d, y: %d, w: %d, h: %d\n",
m->si->name, m->si->x, m->si->y, m->si->w, m->si->h,
rrm->x, rrm->y, rrm->width, rrm->height);

monitor_set_coords(m, *rrm);
TAILQ_INSERT_TAIL(&monitorsold_q, m, oentry);

return (true);
}
Expand Down Expand Up @@ -550,6 +536,10 @@ scan_screens(Display *dpy)
int i, n = 0;
Window root = RootWindow(dpy, DefaultScreen(dpy));

RB_FOREACH(m, monitors, &monitor_q) {
m->flags &= ~(MONITOR_NEW|MONITOR_CHANGED);
}

rrm = XRRGetMonitors(dpy, root, true, &n);
if (n <= 0 && (!randr_initialised && monitor_get_count() == 0)) {
fvwm_debug(__func__, "get monitors failed\n");
Expand Down Expand Up @@ -578,9 +568,12 @@ scan_screens(Display *dpy)
* - It's an existing monitor (position changed)
* - It's an existing monitor which has been toggled on or off.
*
* In such cases, we must detect if the monitor exists and what
* state it is in.
* In such cases, we must detect if the monitor exists and what state it
* is in. Regardless of how the monitor state has changed, we flag all
* monitors reported by XRRGetMonitors with flag MONITOR_FOUND, which we
* use below to determine its new state.
*/
fvwm_debug(__func__, "Case 2: processing %d monitors", n);
for (i = 0; i < n; i++) {
if ((name = XGetAtomName(dpy, rrm[i].name)) == NULL)
continue;
Expand All @@ -593,32 +586,52 @@ scan_screens(Display *dpy)
if (monitor_mark_changed(m, &rrm[i])) {
fvwm_debug(__func__, "Case 2.2: %s changed", m->si->name);
}

/* Flag monitor as MONITOR_FOUND. */
monitor_mark_inlist(name);

XFree(name);
}

out:
/* Update monitor order after changes. Do not mix that up with the
* following loop or some monitors might get their flags processed
* twice.
*/
RB_FOREACH_SAFE(m, monitors, &monitor_q, m1) {
if (m->flags & MONITOR_CHANGED) {
m->flags &= ~MONITOR_DISABLED;
fvwm_debug(__func__, "REINSERTING: %s\n", m->si->name);
RB_REMOVE(monitors, &monitor_q, m);
RB_INSERT(monitors, &monitor_q, m);
}
}

RB_FOREACH(m, monitors, &monitor_q) {
int flags = m->flags;
bool found = m->flags & MONITOR_FOUND;

/* Check for monitor connection status -- whether a monitor is
* active or not. Clearing the MONITOR_FOUND flag is
* important here so that the monitor is reconsidered again.
*/
if (!(m->flags & (MONITOR_FOUND|MONITOR_NEW))) {
m->flags |= MONITOR_DISABLED;
m->emit |= MONITOR_DISABLED;
} else if ((m->flags & (MONITOR_FOUND|MONITOR_DISABLED)) ==
(MONITOR_FOUND|MONITOR_DISABLED)) {
if (found && (flags & MONITOR_NEW)) {
m->flags &= ~MONITOR_DISABLED;
} else {
m->flags |= MONITOR_ENABLED;
m->emit = MONITOR_ENABLED;
} else if (found && (flags & MONITOR_CHANGED)) {
m->flags &= ~MONITOR_DISABLED;
m->emit = MONITOR_CHANGED;
} else if (found && (flags & MONITOR_DISABLED)) {
m->flags &= ~MONITOR_DISABLED;
m->emit = MONITOR_ENABLED;
} else if (found && (! (flags & MONITOR_DISABLED))) {
m->emit = 0;
} else if (!found && (flags & MONITOR_NEW)) {
/* This case happens if !randr_initialised. */
m->emit = 0;
} else if (!found && (flags & MONITOR_DISABLED)) {
m->emit = 0;
} else /* (!found && (! (flags & MONITOR_DISABLED))) */ {
m->flags |= MONITOR_DISABLED;
m->emit = MONITOR_DISABLED;
}
m->flags &= ~MONITOR_FOUND;
}
Expand Down Expand Up @@ -650,9 +663,6 @@ void FScreenInit(Display *dpy)
if (TAILQ_EMPTY(&screen_info_q))
TAILQ_INIT(&screen_info_q);

if (TAILQ_EMPTY(&monitorsold_q))
TAILQ_INIT(&monitorsold_q);

if (!XRRQueryExtension(dpy, &randr_event, &err_base) ||
!XRRQueryVersion (dpy, &major, &minor)) {
fvwm_debug(__func__, "RandR not present");
Expand Down Expand Up @@ -1439,4 +1449,4 @@ int FScreenFetchMangledScreenFromUSPosHints(XSizeHints *hints)
screen = 0;

return screen;
}
}
2 changes: 0 additions & 2 deletions libs/FScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,9 @@ struct monitor {
TAILQ_ENTRY(monitor) oentry;
};
RB_HEAD(monitors, monitor);
TAILQ_HEAD(monitorsold, monitor);

extern struct monitors monitors;
extern struct monitors monitor_q;
extern struct monitorsold monitorsold_q;
int monitor_compare(struct monitor *, struct monitor *);
RB_PROTOTYPE(monitors, monitor, entry, monitor_compare);

Expand Down
Loading