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);
>               }
>       }
>  }

Reply via email to