[haiku] Re: Full-screen and multi-monitor handling, related: I haven't used Haiku, but from what i have seen, this is my atempt to make Haiku R2 compitable to other OSs when released

"André Braga" <meianoite@xxxxxxxxx> wrote:

> IMO a list of legal rectangles would work much better. The 
> programmer is likely going to construct it anyway given the illegal
> areas, so having the API to list legal areas is more valuable than
> having it list only the illegal areas. Of course both could (and
> should) be provided (since each illegal rectangle will create up to
> four legal areas, [...]

Fair enough. The reason I suggested only illegal areas is because
that seems to be the only one that's absolutely essential; legal
areas alone wouldn't be enough.

For example, the case with two monitors side-by-side (1280x1024
resolution each), deskbar in the top right corner, the illegal
rectangle case would look like this:

1) Top=0, left=1280, width=0, height=1024
2) Top=0, left=2448, width=112, height=156

Expanding a window to the maximum size would never traverse the
boundary between the two monitors due to the first rectangle, yet
within a single monitor it can always use the available space.

With legal rectangles only, I suppose it'd look like this:

1) Top=0, left=0, width=1280, height=1024
2) Top=0, left=1280, width=2448, height=156
3) Top=156, left=1280, width=2560, height=868

The problem now is that while expanding a window works as expected
on the left-hand monitor, on the right-hand monitor the window
will never cross the boundaries between rectangles #2 and #3
(which is about 1/6th of the way down the screen).

But it shouldn't be a problem to provide both, perhaps by a separate
function call. The only difficulty would be calculating the number of
rectangles created when there are several illegal areas on the screen
(e.g., deskbar instances in each corner of a very large monitor).
But as you say, I suppose that's best to put in the OS anyway rather
than have each app re-implement it if required.



> In the case of cornered rectangles like the Deskbar, only two areas
> will be created, but it probably makes sense to account for 
> potential other forbidden areas, like docks, launchers or other
> drawer-type widgets (think Control Strip and the ability to turn
> Finder windows into tabs on Mac OS 8.x/9).

Absolutely; that's why returning a variable-sized list of
rectangles would be better than some kind of modification to
app_server to make it handle the Deskbar as a special-case. The
areas may need to change dynamically too, in the case of moving
the Deskbar around, having it auto-hide, etc. I'm not sure if this
creates any additional complications -- on the face of it, it seems
like simply re-clipping all the windows to the new rectangle
(using the algorithm below) would be sufficient?


As for the actual algorithm to move and resize windows to make them
fit, I imagine it would have a similar effect to this pseudo-code:

uint32 directions[4]; /* 0 = left, 1 = right, 2 = up, 3 = down */

if( ! check_overlap(window_x_positon, window_y_position) ) {
    /*
     * If the window does not overlap any illegal
     * rectangles, end.
     */
    return;
}

/* Try shuffling it left */
directions[0] = 0;
temp_x = window_x_position;
for(;;) {
    /* Stop when no overlaps found. */
    if( ! check_overlap(temp_x, window_y_position) ) break;

    if( temp_x <= 0 ) {
        /* Cannot move it any further left. */
        directions[0] = 0xffffffff;
        break;
    }

    directions[0]++;
    temp_x--;
}

/* Try shuffling it right */
directions[1] = 0;
temp_x = window_x_position;
for(;;) {
    /* Stop when no overlaps found. */
    if( ! check_overlap(temp_x, window_y_position) ) break;

    if( temp_x + window_x_size >= desktop_x_size ) {
        /* Cannot move it any further right. */
        directions[1] = 0xffffffff;
        break;
    }

    directions[1]++;
    temp_x++;
}

/*
 * Do the same thing for up and down.
 */

/*
 * Decide which direction to move the window, if any.
 * This will be whatever direction needed the least number
 * of pixels movement to avoid overlaps.
 */

smallest = 0xffffffff;
dir = 0;

for( i = 0 ; i < 4 ; i++ ) {
    if( directions[i] < smallest ) {
        smallest = directions[i];
        dir = i;
    }
}

/*
 * Upon successfully moving the window, the function can return.
 */
if( smallest < 0xffffffff ) {
    move_window(smallest, dir);
    return;
}

/*
 * Upon reaching this point, the window could not be moved
 * to a location that avoided the illegal rectangles, so instead
 * it will need to be resized.
 * The simplest algorithm would be just to clip it in-place, but
 * that would give the worst results. A better algorithm might be
 * to find the window position that overlaps the least number of
 * illegal pixels and then perform the clipping.
 */


Obviously the above code is extremely inefficient (checking
pixel-by-pixel), but hopefully it illustrates the idea a bit more
clearly than a rough English description!

This algorithm specifically handles the case of opening new windows;
resizing to the maximum available size would probably need a separate
algorithm and API call.


> Since we're potentiallty changing the semantics of the zoom button 
> to snap to the largest legal area (given some criteria of
> "largest"), [...]

Hmm, are we? I was thinking more along the lines of leaving the
zoom button's function mostly unchanged (expanding the window to
best fit the document), but simply performing additional clipping
to ensure it doesn't traverse any illegal boundaries on the left
or bottom in the process.
At least, that's how I generally use the zoom button, but other
people might have different expectations?

Tracker is a good example: hitting the zoom button will expand the
window horizontally to fit all the columns on-screen but no larger,
and vertically it will expand to fit the entire list of files in
the window (unless it hits the bottom of the desktop first).
With clipping in place, it would do the same thing, except when
the Deskbar is at the bottom, it would stop just short of the
Deskbar instead of overlapping it (assuming there are enough files
in the window to make it reach the Deskbar).


> [...] it's better to have arguments/flags to the API call
> indicating whether to fit by height, by width or both, and return
> an error in case it's not possible, rather than having the
> app_server decide the window size behind the application's back.

True; there'd surely need to be some way of choosing priority between
horizontal and vertical for the function that expands to maximum
size. It could be more of a case of allowing the programmer to
override the default feature though, to save each app from
re-implementing those few lines of code (and in some cases
forgetting it completely, and letting users who care about overlaps
pay the price).




> Wasn't it decided that multiple monitor support would be 
> accomplished by mapping them to workspaces?

I don't recall what the consensus on multi-monitor support was,
but as a multi-monitor user myself, there would be some quite severe
changes necessary to do it this way!

The main problem is the lack of spatial orientation of the
workspaces -- a window cannot be dragged to overlap between
two or more workspaces, and the workspaces have no meaning in
the greater sense of space; a desktop is entirely one workspace,
and there's nothing larger.

I deliberately overlap windows between two monitors all the time,
to work on large images or just to move windows between the two.
It's essentially like having a small video wall -- each monitor
displays one fraction of a much larger desktop, and with the
narrow bezels on today's monitors, you pretty much tune out the gaps
between the monitors and see it as one continuous space.

Walling off the monitors into separate spaces of their own would
basically render multiple monitors useless for me, and I think it
would surprise a lot of users too. It's more than just overlapping
windows between the two -- when I press print screen, I expect to get
a dump of everything on the desktop (e.g., the total area I can see
with my eyes, on multiple monitors), rather than just a fraction
of it.


I'm not totally against the idea of mapping workspaces to monitors
though, if the necessary changes could be made. Essentially each
workspace would need its own BRect to tell it which area in
Greater Space it represents, to allow smooth traversal and deliberate
window overlaps between the monitors.

My concern though is after making these changes (which in some cases
change the definition of a workspace -- having part of one
application visible on one, and a different part of the same app
visible on another), it just amounts to having one big desktop!

Have these problems already been addressed in some form?


Also, on the topic of multi-monitor handling, I think it's worth
mentioning that some hardware imposes certain assumptions concerning
multiple monitors mapping to one continuous desktop space.
For example, some monitors have two video inputs, each representing
half of the screen (in order to handle the high bandwidth required),
and there are some products (e.g., Matrox TripleHead2Go) which take
a single video output and slice it horizontally to feed multiple
monitors.
In the former case, one workspace needs to be mapped to two video
outputs (as we do currently, with the dual head features built into
the video drivers), and in the latter, one workspace can be mapped
to one video output (for the one-workspace-on-multiple-monitors
method), or multiple workspaces would have to be mapped to a single
video output (for the workspaces-are-monitors method).
I suppose that's possible with a sufficiently powerful
implementation, but it sounds a bit involved...


Anyway, thanks for the feedback André; as you can see you've got me
pondering quite a few things. =P


Other related posts: