Andreas Schömann schrieb:
  > I have developped two classes that implement most of the behaviour I 
need:
> 
> 1. All windows of an application shall come to the top by just clicking 
> one window.
> 2. Minimizing the main window shall minimize all other windows too.
> 3. Restoring the main window (from minimized state) shall restore all 
> other windows too.
> 
> Both classes are derived from Fl_Window. JoinedVisibilityWindow 
> implements 1. JoinedMinimizeWindow implements 2. and 3. A 
> JoinedMinimizeWindow is also a JointVisibilityWindow hence derived from it.
> 
> All this works good. However, there is one major problem: Clicking the 
> _border_ of a window does not bring all joined windows to the top as I 
> want it. Clicking the border of a window does not produce a FL_PUSH 
> event but a FL_FOCUS event. Trying to utilize FL_FOCUS produces only 
> nonsense!? Please try.


Here is an improved version. It seems as if it solves all mentioned 
problems. The main idea is a simple approach to the problem how to 
detect whether one of our windows is covered by other application's 
windows or not: the observation is that as long as our application is 
active all windows are on top. When the user jumps from one window to 
another window within our application then we see quick unfocus/focus 
event sequences: old window is unfocused, new window is focused. Now, if 
the user changes to another application we see an unfocus event. When 
the user then returns to our application we see a focus event. However, 
normally there is a considerable time shift between these events. We use 
this observation and activate a timer upon an unfocus event. If after a 
short time (0.2 sec seems reasonable) we don't see a focus event again 
then the user probably has changed the application. This is the signal 
to show all our windows when the next focus event comes.

This works pretty well. Tested on Windows XP and OS X, but FLTK needs a 
small change in Fl_mac.cxx to work properly on OS X:

   case kEventWindowCollapsed:
     Fl::handle( FL_HIDE, window);
     break;
   case kEventWindowExpanded:
     Fl::handle( FL_SHOW, window);
     break;

I'm not sure whether this is safe. Matthias?


#include <iostream>
#include <list>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>

class JoinedVisibilityWindow : public Fl_Window
{
protected:
   struct Window
   {
     Fl_Window * pointer;
     bool joined;
     Window(Fl_Window * p, bool j)
       : pointer(p),
         joined(j)
     {}
     bool operator==(Window const & w) { return pointer == w.pointer; }
   };
   typedef std::list<Window> Windows;

   static Windows windows_;
   static bool focus_;
   static void timeout_cb(void *);

public:
   JoinedVisibilityWindow(int x, int y, int w, int h, const char * l = 0)
     : Fl_Window(x, y, w, h, l)
   {
     windows_.push_back(Window(this, false));
   }
   JoinedVisibilityWindow(int w, int h, const char * l = 0)
     : Fl_Window(w, h, l)
   {
     windows_.push_back(Window(this, false));
   }

   int handle(int e)
   {
     switch(e)
     {
       case FL_UNFOCUS:
       {
         Fl::remove_timeout(timeout_cb, NULL);
         Fl::add_timeout(0.2, timeout_cb, NULL);
         break;
       }
       case FL_FOCUS:
       {
         Fl::remove_timeout(timeout_cb, NULL);
         if(!focus_)
         {
           focus_ = true;
           Windows::const_iterator window;
           for(window = windows_.begin(); window != windows_.end(); 
++window)
             if(window->pointer == this)
               break;
           //
           // move activated window to the end of the list
           // this makes sense but is also necessary on Windows
           // though it should not!?
           //
           windows_.remove(*window);
           windows_.push_back(*window);
           for(window = windows_.begin(); window != windows_.end(); 
++window)
             if(window->joined)
               window->pointer->show();
           //
           // extra show is necessary on Windows though it should not!?
           //
           this->show();
         }
         break;
       }
       case FL_SHOW:
       {
         Windows::iterator window;
         for(window = windows_.begin(); window != windows_.end(); ++window)
           if(window->pointer == this)
             window->joined = true;
         break;
       }
       case FL_HIDE:
       {
         Windows::iterator window;
         for(window = windows_.begin(); window != windows_.end(); ++window)
           if(window->pointer == this)
             window->joined = false;
         break;
       }
     }
     return Fl_Window::handle(e);
   }
};

JoinedVisibilityWindow::Windows JoinedVisibilityWindow::windows_;
bool JoinedVisibilityWindow::focus_ = true;

void JoinedVisibilityWindow::timeout_cb(void *)
{
   focus_ = false;
}


class JoinedMinimizeWindow : public JoinedVisibilityWindow
{
public:
   JoinedMinimizeWindow(int x, int y, int w, int h, const char * l = 0)
     : JoinedVisibilityWindow(x, y, w, h, l)
   {}
   JoinedMinimizeWindow(int w, int h, const char * l = 0)
     : JoinedVisibilityWindow(w, h, l)
   {}

   int handle(int e)
   {
     switch(e)
     {
       case FL_SHOW:
       {
         Windows::iterator window;
         for(window = windows_.begin(); window != windows_.end(); ++window)
           if(window->joined)
             window->pointer->show();
         this->show();
         break;
       }
       case FL_HIDE:
       {
         Windows::iterator window;
         for(window = windows_.begin(); window != windows_.end(); ++window)
         {
           //
           // test for visibility, otherwise all windows will be destroyed
           // due to an hide()->handle()->hide()... endless loop
           // calling hide() twice on a window destroys it!?
           //
           if(window->pointer->visible())
           {
             window->pointer->hide();
             if(window->pointer != this)
               window->joined = true;
           }
         }
         return 1;
       }
     }
     return JoinedVisibilityWindow::handle(e);
   }
};

int main(int argc,char **argv)
{
   JoinedMinimizeWindow a(200, 200, "min 1");
   a.end();
   a.show();

   JoinedVisibilityWindow b(200, 200, "vis 1");
   b.end();
   b.show();

   JoinedVisibilityWindow c(200, 200, "vis 2");
   c.end();
   c.show();

   Fl::run();
   return (0);
}
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to