[comp.os.os2] Focus Cycling

osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) (11/10/89)

A PM programming point to ponder:

I have an application that owns a number of child standard windows.
(Each is a window on a tuple of a table, but that's not important.)
I want the keyboard controls to cycle the focus through them in both
directions, like when the user hits Tab and Shift-Tab.

Okay, fine, to go one of the two directions, I set the focus to the
bottommost child window.  That takes care of Shift-Tab.

However, when it comes to setting the focus to the window that is
just below the focus window, I am having difficulty.  Somehow I need
to make the focus window become the bottommost window.  This is what
OS/2 does to windows listed in Task List when one hits Alt-Esc.

Setting the focus to the window next to the top causes the focus
window to be moved second.  This limits you to switching between the
two topmost windows, so that's out.  Any ideas?  (Proven, please.)

-Kasey

paulb@minster.york.ac.uk (11/21/89)

In article 92, osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) writes:

>...
>Okay, fine, to go one of the two directions, I set the focus to the
>bottommost child window.  That takes care of Shift-Tab.
>
>However, when it comes to setting the focus to the window that is
>just below the focus window, I am having difficulty.  Somehow I need
>to make the focus window become the bottommost window.  This is what
>OS/2 does to windows listed in Task List when one hits Alt-Esc.
>
>Setting the focus to the window next to the top causes the focus
>window to be moved second.  This limits you to switching between the
>two topmost windows, so that's out.  Any ideas?  (Proven, please.)
>
I think the problem here is one of interface design, rather than a
programming problem.  There is no way in which you can cycle through the
windows based upon their order on the screen, as you change the order
when you bring a window to the top.  If you think about it there's no
sensible way to handle this.  Imagine a user in this position; he brings
the second window to the top with shift tab, and then goes away for a
day.  When he comes back, he wants to look at the window which is now
second, and (sensibly) presses shift tab again, only to get the THIRD
window.

The way I have coded this, is to impose another order on the windows,
(e.g. the order in which the windows were opened), maintain a separate
list in this order, and cause shift tab to cycle through this list.  If
you examine the task manager, I think you'll find that this is the
method that it uses.

Paul Butcher.
JANET:paulb@uk.ac.york.minster

osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) (11/24/89)

In article <627646071.19046@minster.york.ac.uk> writes:
>In article 92, osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) writes:
>>Okay, fine, to go one of the two directions, I set the focus to the
>>bottommost child window.  That takes care of Shift-Tab.
>>
>>However, when it comes to setting the focus to the window that is
>>just below the focus window, I am having difficulty.  Somehow I need
>>to make the focus window become the bottommost window.  This is what
>>OS/2 does to windows listed in Task List when one hits Alt-Esc.
>>
>>Setting the focus to the window next to the top causes the focus
>>window to be moved second.  This limits you to switching between the
>>two topmost windows, so that's out.  Any ideas?  (Proven, please.)
>
>I think the problem here is one of interface design, rather than a
>programming problem.  There is no way in which you can cycle through the
>windows based upon their order on the screen, as you change the order
>when you bring a window to the top.

I disagree.  A direct analogy would be a circular queue:  When you move
the head pointer, the ordering does not change, only the ranks of the
members of the queue.  (By rank, I mean distance from the head.)

>If you think about it there's no sensible way to handle this.

I have though about it.  And thought about it, and thought about it...
I remain convinced that the capability is there, if not the means.

>Imagine a user in this position; he brings
>the second window to the top with shift tab, and then goes away for a
>day.  When he comes back, he wants to look at the window which is now
>second, and (sensibly) presses shift tab again, only to get the THIRD
>window.

Ah, but I want the top window to be moved LAST.  Thus, the second window
becomes the first, and the third the second...  When the user hits
shift-tab the second time, there is conceptually no difference than
when he hits it the first time.  This is what PM already does to Task
List windows, so it CAN be done.

>The way I have coded this, is to impose another order on the windows,
>(e.g. the order in which the windows were opened), maintain a separate
>list in this order, and cause shift tab to cycle through this list.

Yes, adding another layer of indirection would work.  However, windows
would not overlap consistently with the ordering presented to the
user through the tab keys.  Is this the case with your application?
With PM's Task List windows, the overlapping is correct.

In addition, I would like the user to be able to change the ordering
on the fly (i.e. by right clicking the mouse on a window, moving it to
the top).  With your method, the user would be locked into a particular
ordering.  Correct?

>If you examine the task manager, I think you'll find that this is the
>method that it uses.

But PM ALREADY knows the window ranking.  If it creates another list
on top of this, that list would be redundant.  The problem is that
PM will not manipulate the window ranking in the manner I desire.  (Or
more precisely, I don't know how to tell it to.)  It seems a shame to
have to create a linked list just to track information that PM already
has.  There must be an elegant solution.

And yes, I would like very much to examine the task manager.  Please
mail me the source.  :-)

Kasey

cs169054@brunix (Peter Golde) (11/28/89)

>>In article 92, osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) writes:
>>>Okay, fine, to go one of the two directions, I set the focus to the
>>>bottommost child window.  That takes care of Shift-Tab.
>>>
>>>However, when it comes to setting the focus to the window that is
>>>just below the focus window, I am having difficulty.  Somehow I need
>>>to make the focus window become the bottommost window.  This is what
>>>OS/2 does to windows listed in Task List when one hits Alt-Esc.
>>>
>>>Setting the focus to the window next to the top causes the focus
>>>window to be moved second.  This limits you to switching between the
>>>two topmost windows, so that's out.  Any ideas?  (Proven, please.)

How about, in each of the subwindow's window procedures, whenever they
loses the focus or become de-activated, setting themselves to the 
bottom most window (with WinSetWindowPos).  I.e., the window procedure
would have something like (I don't have a manual here, so this is
probably not correct in any details:

   switch (msg) {
   case WM_ACTIVATE or WM_SETFOCUS:
      if (SHORT?FROMMP(mp?) == 0) {
	// losing focus...
        WinSetWindowPos(hwndFrame, ..., HWND_BOTTOM, ...., SWP_ZORDER);
      }
      
That should work, but of course I've never actually tried it.  Alternatively,
whatever function is causing the window to lose the focus could do the 
moving of the window.  Whatever is more elegant for your app.

--Peter Golde

osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) (11/29/89)

In article <21629@brunix.UUCP> cs169054@cslab7f.UUCP (Peter Golde) writes:
>>>In article 92, osbornk@uther.CS.ORST.EDU (Kasey S. Osborn) writes:
>>>>However, when it comes to setting the focus to the window that is
>>>>just below the focus window, I am having difficulty.  Somehow I need
>>>>to make the focus window become the bottommost window.  This is what
>>>>OS/2 does to windows listed in Task List when one hits Alt-Esc.
>
>How about, in each of the subwindow's window procedures, whenever they
>loses the focus or become de-activated, setting themselves to the 
>bottom most window (with WinSetWindowPos).  I.e., the window procedure

This looks like the solution.  It seems strange using WinSetWindowPos
to do something other than set coordinates, but it does the job.

One catch:  the focus does not automatically move to the new topmost
window after the call to WinSetWindowPos.  My code looks like this:

{
  HWND *ParentWindow, *Window, *ChildClientWindow;

  // Get client's frame handle.
  Window = WinQueryWindow (hWnd, QW_PARENT, FALSE);

  // Move topmost window to the bottom.
  WinSetWindowPos (Window,
		   HWND_BOTTOM,     // Put tuple at the bottom.
		   0, 0,	    // Ignored.
		   0, 0,	    // Ignored.
		   SWP_ZORDER);     // Look at hwndInsertBehind.

  // And later...
  WinSetFocus (HWND_DESKTOP, ChildClientWindow);
}

paulb@minster.york.ac.uk (12/01/89)

In article <13958@orstcs.CS.ORST.EDU> you write:
>...
>Ah, but I want the top window to be moved LAST.  Thus, the second window
>becomes the first, and the third the second...  When the user hits
>shift-tab the second time, there is conceptually no difference than
>when he hits it the first time.  This is what PM already does to Task
>List windows, so it CAN be done.
>...

I'm sorry, I misunderstood, your previous message.  It is certainly
possible to do this.  Call WinBeginEnumWindows(), and then
WinGetNextWindow() to find the ordering of the windows.  Put the top
window to the bottom using WinSetWindowPos() (giving the parameter
HWND_BOTTOM), and change focus to the second window (N.B. I haven't
actually tried this, but from reading the doc. I see no reason why it
shouldn't work).  This will also allow the user to change the order "on
the fly"; when he clicks on another window, simply bring it to the top,
and call WinBeginEnumWindows() and WinGetNextWindow() as before, to find
out what the new ordering is.

I'm temporarily without an OS/2 system, so this is from memory, but I
think I'm right in saying that this is not the method used by the task
manager.  Instead, the order in which you flip between windows is the
order of the task list maintained by the task manager. (i.e. a second
ordering).  Forgive me if I'm mistaken.

There was an article in the MS Systems Journal that you may find
interesting called "MDI: An Emerging Standard for Manipulating Document
Windows" by Kevin P. Welch (Vol 4, No 2, March 1989).  It describes the 
Multiple Document Interface, as defined by IBM in their SAA.  I gives a 
definition of a whole bunch of services that should be provided by any 
application program handling multiple documents via child windows.

Have fun!

PaulB->msgCount++