On Sun 2011.05.15 at 16:44 +0300, Sviatoslav Chagaev wrote:
> I switch Xinerama screens on and off quite often (with the help of
> xrandr(1)). Sometimes, this results in windows ending up beyond the
> screen boundries.
> Like when a Xinerama screen has windows and is to the right or to the
> bottom from another Xinerama screen and you turn it off.
>
> Correct me if I'm wrong, but there's no way to bring such windows
> back to the screen.
> Even the "kill-the-app-and-start-it-again" approach doesn't always work
> (let alone it being inconvenient...) -- some apps remember their
> position and start up at that same location the next time (Sylpheed,
> Pidgin, epdfview...).
>
> This is how I solved it for myself: when an XRandR event comes, go thru
> the list of all client windows and move those which are beyond the
> screen boundries to (0,0) (or (gap_x, gap_y) if you configured them).
> This also works when rotation is applied to the screen, it can
> cause a window to fall off of the screen too.
So this has hit me as well in the past, when I used to have another
screen. I have a large re-work of all the xine stuff, but if I don't
get that in soonish, I'll look at this more closely - however, also
consider the fact that the w/h might also be out of range for the
remaining xinerama screens as well; maybe scale to xmax and ymax as
well if out of range.
Thanks though!
Cheers,
Okan
>
> Index: calmwm.h
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/calmwm.h,v
> retrieving revision 1.125
> diff -u -p -r1.125 calmwm.h
> --- calmwm.h 11 May 2011 13:53:51 -0000 1.125
> +++ calmwm.h 15 May 2011 13:02:31 -0000
> @@ -365,6 +365,9 @@ struct screen_ctx *screen_fromroot(Windo
> void screen_init_xinerama(struct screen_ctx *);
> void screen_update_geometry(struct screen_ctx *, int, int);
> void screen_updatestackingorder(struct screen_ctx *);
> +int screen_is_client_beyond(struct screen_ctx *,
> + struct client_ctx *);
> +void screen_assert_clients_within(struct screen_ctx *);
>
> void kbfunc_client_cycle(struct client_ctx *, union arg *);
> void kbfunc_client_cyclegroup(struct client_ctx *,
> Index: screen.c
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/screen.c,v
> retrieving revision 1.28
> diff -u -p -r1.28 screen.c
> --- screen.c 11 May 2011 13:53:51 -0000 1.28
> +++ screen.c 15 May 2011 13:02:31 -0000
> @@ -131,3 +131,55 @@ screen_update_geometry(struct screen_ctx
> XA_CARDINAL, 32, PropModeReplace,
> (unsigned char *)workareas, CALMWM_NGROUPS * 4);
> }
> +
> +/*
> + * Return non-zero if client is beyond the screen.
> + */
> +int
> +screen_is_client_beyond(struct screen_ctx *sc, struct client_ctx *cc)
> +{
> + int bw, top, left, right, bottom;
> +
> + bw = cc->bwidth * 2;
> + top = cc->geom.y;
> + left = cc->geom.x;
> + right = cc->geom.x + cc->geom.width + bw - 1;
> + bottom = cc->geom.y + cc->geom.height + bw - 1;
> +
> + if (HasXinerama) {
> + if (screen_find_xinerama(sc, left, top))
> + return 0;
> + if (screen_find_xinerama(sc, left, bottom))
> + return 0;
> + if (screen_find_xinerama(sc, right, top))
> + return 0;
> + if (screen_find_xinerama(sc, right, bottom))
> + return 0;
> + return 1;
> + } else {
> + if (top > sc->ymax || left > sc->xmax)
> + return 1;
> + if (bottom < 0 || right < 0)
> + return 1;
> + return 0;
> + }
> +}
> +
> +/*
> + * Bring clients which are beyond the screen back.
> + */
> +void
> +screen_assert_clients_within(struct screen_ctx *sc)
> +{
> + struct client_ctx *cc;
> +
> + TAILQ_FOREACH(cc, &Clientq, entry) {
> + if (cc->sc != sc)
> + continue;
> + if (screen_is_client_beyond(sc, cc)) {
> + cc->geom.x = sc->gap.left;
> + cc->geom.y = sc->gap.top;
> + client_move(cc);
> + }
> + }
> +}
> Index: xevents.c
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/xevents.c,v
> retrieving revision 1.53
> diff -u -p -r1.53 xevents.c
> --- xevents.c 11 May 2011 13:53:51 -0000 1.53
> +++ xevents.c 15 May 2011 13:02:31 -0000
> @@ -377,6 +377,7 @@ xev_handle_randr(XEvent *ee)
> XRRUpdateConfiguration(ee);
> screen_update_geometry(sc, rev->width, rev->height);
> screen_init_xinerama(sc);
> + screen_assert_clients_within(sc);
> }
> }
> }