FL_*_EVENT questions

113 views
Skip to first unread message

Pavel

unread,
Dec 13, 2023, 12:28:00 AM12/13/23
to fltk.general
Hello,

I am on Linux, xfce4. I have two questions related to FLTK event handling.

1.
My simple Fl_Window receives many (tens in a row) 0 events (FL_NO_EVENT). I noticed they coincide with the window's first appearance and moving (i.e. when I drag the window around the screen). I would like to have an event from a window when it is moved. Can I use these instead?

2.
I was trying to get FL_ACTIVATE event and I couldn't. I create and show a window, handle FL_SHOW event by calling activate() and the window does not receive FL_ACTIVATE. Here is my main window's handle() method (you can ignore wingmanWin_ thingy because it is never created -- because FL_ACTIVATE is never called):

  int handle(int event) override {
    if (event != FL_NO_EVENT)
      cout << "handling " << event << '(' << fl_eventnames[event] << ')' <<
        " wingman?:" << !!wingmanWin_.get() << endl;
    switch (event) {
    case FL_SHOW:
      if (!wingmanWin_.get()) {
        activate();
        cout << "activated, active_r:" << active_r() << endl;
      }
      break;
    case FL_ACTIVATE:
      if (!wingmanWin_.get()) {
        wingmanWin_ = CreateWingman(*this);
        wingmanWin_->show();
      }
      break;
    default:
      return 0;
    }
    return 1;
  }

And here is the output of a simple session where I run a program and press Alt+F4 to close the main window right after it appears:

handling 16(FL_SHOW) wingman?:0
activated, active_r:1
window x,y,w,h: 0 0 340 180 // this is printed from main(), please ignore
handling 3(FL_ENTER) wingman?:0
handling 6(FL_FOCUS) wingman?:0
handling 11(FL_MOVE) wingman?:0
handling 8(FL_KEYDOWN) wingman?:0
handling 12(FL_SHORTCUT) wingman?:0
handling 12(FL_SHORTCUT) wingman?:0
handling 7(FL_UNFOCUS) wingman?:0
handling 11(FL_MOVE) wingman?:0
handling 15(FL_HIDE) wingman?:0

What should I do to get FL_ACTIVATE? My idea was to rely on it and FL_DEACTIVATE to keep a satellite (wingman) window on the screen only while the main window is active. As can be seen from the above, active_r() returns true so I would expect FL_ACTIVATE. What else should I check.

TIA,
-Pavel

Ian MacArthur

unread,
Dec 13, 2023, 4:21:49 AM12/13/23
to fltk.general
On Wednesday 13 December 2023 at 05:28:00 UTC Pavel wrote:
 
What should I do to get FL_ACTIVATE? My idea was to rely on it and FL_DEACTIVATE to keep a satellite (wingman) window on the screen only while the main window is active. As can be seen from the above, active_r() returns true so I would expect FL_ACTIVATE. What else should I check.

If this is the objective, a floating window that is on screen only when it's main window is, then it *sounds* to me like you are talking about making a non-modal window...?
In which case, all that messing about with events is just unnecessary confusion; just set the satellite window as non-modal to the main window and it should Just Work.

Um, OK... Not sure this is actually what you want, but here's a worked example that seems to work (if I understood the question, at any rate!)

// fltk-config --compile sat-test.cxx

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>

static Fl_Double_Window *main_win=(Fl_Double_Window *)0;
static Fl_Double_Window *sat_win=(Fl_Double_Window *)0;

static Fl_Button *bt1=(Fl_Button *)0;
static Fl_Button *bt2=(Fl_Button *)0;
static Fl_Button *exit_bt=(Fl_Button *)0;

static void cb_bt1(Fl_Button*, void*) {
  // show wingman;
  if (sat_win) sat_win->show();
}

static void cb_bt2(Fl_Button*, void*) {
  // Hide wingman;
  if (sat_win) sat_win->hide();
}

static void cb_exit_bt(Fl_Button*, void*) {
  // exit
  if (sat_win) sat_win->hide();
  if (main_win) main_win->hide();
}

int main(int argc, char **argv)
{
  // Create the satellite window
  sat_win = new Fl_Double_Window(256, 256, "Wingman");
  sat_win->end();

  // create the main window
  main_win = new Fl_Double_Window(480, 320, "Main Window");

  bt1 = new Fl_Button(25, 21, 108, 40, "Show Wingman");
  bt1->box(FL_THIN_UP_BOX);
  bt1->callback((Fl_Callback*)cb_bt1);

  bt2 = new Fl_Button(29, 80, 108, 40, "Hide Wingman");
  bt2->box(FL_THIN_UP_BOX);
  bt2->callback((Fl_Callback*)cb_bt2);

  exit_bt = new Fl_Button(357, 265, 108, 40, "Exit");
  exit_bt->box(FL_THIN_UP_BOX);
  exit_bt->callback((Fl_Callback*)cb_exit_bt);

  main_win->resizable(main_win);
  main_win->end();

  // Make the satellite "non-modal" to the main window
  sat_win->set_non_modal();


  main_win->show(argc, argv);
  return Fl::run();
} // main

// End of File

 

Ian MacArthur

unread,
Dec 13, 2023, 4:37:14 AM12/13/23
to fltk.general
On Wednesday 13 December 2023 at 09:21:49 UTC Ian MacArthur wrote:
On Wednesday 13 December 2023 at 05:28:00 UTC Pavel wrote:
 
What should I do to get FL_ACTIVATE? My idea was to rely on it and FL_DEACTIVATE to keep a satellite (wingman) window on the screen only while the main window is active. As can be seen from the above, active_r() returns true so I would expect FL_ACTIVATE. What else should I check.

If this is the objective, a floating window that is on screen only when it's main window is, then it *sounds* to me like you are talking about making a non-modal window...?
In which case, all that messing about with events is just unnecessary confusion; just set the satellite window as non-modal to the main window and it should Just Work.

Um, OK... Not sure this is actually what you want, but here's a worked example that seems to work (if I understood the question, at any rate!)

Hmmm.
Just tried this with a couple of different WM... Seems it doesn't always work, and the WM seems to be the key. Works with some WM though!
I don't have XFCE to hand for testing, so... 
TBH, I expected this to work everywhere, so I'm surprised that it does not.


Pavel

unread,
Dec 14, 2023, 2:38:52 AM12/14/23
to fltk.general
Thanks Ian, for mentioning non-modal, I did not think about it. Your example works for me (i.e. the wingman shows on "show" button and disappears on "hide"). My goals are different though: I want to track events anyway to move the wingman at (more or less) fixed offset from the main window as the main window is moved. Hence that question #1 about what those FL_NO_EVENT were and whether they could be used (ax proxies?) to catch when main window is moved around or resized.

I think I figured out the answer to FL_ACTIVATE: these events are kinda "edge-triggered" and the initial state is "active" so nothing is generated. I deactivated main window on showing and then activated back on deactivation and the event appeared (and wingman got created), the relevant piece of the handle() is below:
    if (event != FL_NO_EVENT)
      cout << "handling " << event << '(' << fl_eventnames[event] << ')' <<
        " wingman?:" << !!wingmanWin_.get() << " active_r:" << active_r() <<
        endl;
    switch (event) {
    case FL_SHOW:
      if (!wingmanWin_.get()) {
        deactivate();
        cout << "deactivated, active_r:" << active_r() << endl;

      }
      break;
    case FL_ACTIVATE:
      if (!wingmanWin_.get()) {
        wingmanWin_ = CreateWingman(*this);
        wingmanWin_->show();
      }
      break;
    case FL_DEACTIVATE:

      if (!wingmanWin_.get()) {
        activate();
        cout << "activated, active_r:" << active_r() << endl;
      }
      break;

the log shows:

handling 16(FL_SHOW) wingman?:0 active_r:1
handling 13(FL_DEACTIVATE) wingman?:0 active_r:0
handling 14(FL_ACTIVATE) wingman?:0 active_r:1
activated, active_r:1
deactivated, active_r:1

window x,y,w,h: 0 0 340 180
handling 6(FL_FOCUS) wingman?:1 active_r:1
...
So, this works. How to track window size and position changes is still unclear. Although, tons of FL_NO_EVENT events are generated so hopefully piggy-backing on these will work, even though in a non-documented way..

HTH,
-Pavel

Albrecht Schlosser

unread,
Dec 14, 2023, 11:37:21 AM12/14/23
to fltkg...@googlegroups.com
On 12/14/23 02:52 Pavel wrote:
> I want to track events anyway to move the wingman at (more or less)
> fixed offset from the main window as the main window is moved. Hence
> that question #1 about what those FL_NO_EVENT were and whether they
> could be used (ax proxies?) to catch when main window is moved around
> or resized.
[...]
> How to track window size and position changes is still unclear.
> Although, tons of FL_NO_EVENT events are generated so hopefully
> piggy-backing on these will work, even though in a non-documented way..

Please don't rely on undocumented behavior like FL_NO_EVENT events.

These events are platform dependent and may be changed (removed) without
notice. I know of these events and I may try to "fix" them by not
sending them to the application. AFAICT these events are mostly sent on
X11 platforms but much less (or not at all when moving windows) on other
platforms like Windows. I don't see such events on Wayland, for instance.

There is also another issue with your "wingman" approach, particularly
on the Wayland platform. On this platform applications (in our case the
FLTK library) are not able to read the current window coordinates and we
can't position a new window at arbitrary screen coordinates. These two
features are prohibited by Wayland for security reasons. There is a
special Wayland option though so you can position a window relative to
an existing window (used for menus and other popup windows). I'm not
aware of a FLTK method to utilize this to position a window like your
"wingman" window near or relative to the main window, even if you could
track window movement.

Maybe you can use the virtual method resize() to catch resize (and maybe
move?) events of the main window (needs subclassing) but I'm not sure if
this works on Wayland or at all. This is just an idea (untested).

That said, using undocumented methods is not a good idea, and Wayland
may be another issue that prevents you from positioning your "wingman"
window. Maybe you should rethink your GUI. It would be possible to
extend your main window and put your wingman stuff in a separate group
in the main window. See e.g. test/demo.cxx how this works for the "debug
terminal" (right click on the demo window opens a menu to open/close the
debug terminal).

Pavel

unread,
Dec 14, 2023, 10:04:10 PM12/14/23
to fltk.general
Thanks Albrecht.

On Thursday, December 14, 2023 at 11:37:21 AM UTC-5 Albrecht Schlosser wrote:
On 12/14/23 02:52 Pavel wrote:
> I want to track events anyway to move the wingman at (more or less)
> fixed offset from the main window as the main window is moved. Hence
> that question #1 about what those FL_NO_EVENT were and whether they
> could be used (ax proxies?) to catch when main window is moved around
> or resized.
[...]
> How to track window size and position changes is still unclear.
> Although, tons of FL_NO_EVENT events are generated so hopefully
> piggy-backing on these will work, even though in a non-documented way..

Please don't rely on undocumented behavior like FL_NO_EVENT events.

These events are platform dependent and may be changed (removed) without
notice. I know of these events and I may try to "fix" them by not
sending them to the application.
ok, noted. I found that FL_MOVE can be used as an imperfect proxy, at least on my platform (because moving windows with keyboard (with either mouse drag, system menu or shortcuts) generates few of these around the beginning and the end of the movement). If worse comes to worse I can use a timer.

AFAICT these events are mostly sent on
X11 platforms but much less (or not at all when moving windows) on other
platforms like Windows. I don't see such events on Wayland, for instance.

There is also another issue with your "wingman" approach, particularly
on the Wayland platform. On this platform applications (in our case the
FLTK library) are not able to read the current window coordinates and we
can't position a new window at arbitrary screen coordinates.
Noted. Even on my xfce4 I noticed that x() and y() stay zeros while handling FL_SHOW, FL_DEACTIVATE and FL_ACTIVATE, and only become sensible on the next event (FL_FOCUS):
handling 16(FL_SHOW) mainWin(0,0,340,180), wingMan(null)
handling 13(FL_DEACTIVATE) mainWin(0,0,340,180), wingMan(null)
handling 14(FL_ACTIVATE) mainWin(0,0,340,180), wingMan(null)

activated, active_r:1
deactivated, active_r:1
window x,y,w,h: 0 0 340 180
handling 6(FL_FOCUS) mainWin(790,460,340,180), wingMan(390,0,340,180)
handling 6(FL_FOCUS) mainWin(790,460,340,180), wingMan(390,24,340,180)
 

These two
features are prohibited by Wayland for security reasons.
I guess I don't understand their concern: it would seem to me that if a user is allowed to move window around and be aware of its location, the process running with this user's permissions should, too. Need to do some reading about their rationale and how common it is.
 
There is a
special Wayland option though so you can position a window relative to
an existing window (used for menus and other popup windows). I'm not
aware of a FLTK method to utilize this to position a window like your
"wingman" window near or relative to the main window, even if you could
track window movement.
Thanks! It seems I could use the relative positioning for my purpose if it was exposed. If those security considerations becomes a mainstream, the APIs to just note movements (without coordinates) and do relative positioning could help achieve my goal.


Maybe you can use the virtual method resize() to catch resize (and maybe
move?) events of the main window (needs subclassing) but I'm not sure if
this works on Wayland or at all. This is just an idea (untested).
FL_MOVE comes as I described above, few around the beginning and few around the end of the movements


That said, using undocumented methods is not a good idea, and Wayland
may be another issue that prevents you from positioning your "wingman"
window. Maybe you should rethink your GUI. It would be possible to
extend your main window and put your wingman stuff in a separate group
in the main window.

What I would like my app look like is similar to gimp (when not in a single-window mode). The idea is to use those wingmans to configure a non-rectangular space so the user could read from the window  of another app below my app and do something with my app. For example, enter some piece of data based on the text in a non-top browser window (with my app being on top), click few buttons on my app's toolbar to fine-tune data visualizing in the main window, then read some more sentences from the browser, while constantly having the text in view, as unobstructed as feasible. The improvement over gimp scenario would be the ability to move the whole arrangement of windows at once by dragging the main window while still being able to modify the arrangement by dragging "wingmen".
See e.g. test/demo.cxx how this works for the "debug
terminal" (right click on the demo window opens a menu to open/close the
debug terminal).
Thanks, tried. It is a good example to explain what I want to achieve. Right now, when a user opens debug terminal the upper right part of the window gets lost (just takes the space and hides the underlying data. What I am trying to achieve is that the main and terminal panels are closely arranged independent windows, moving (dragging) main window moves the terminal window in parallel, whereas dragging the terminal window only moves the terminal window itself.

Albrecht Schlosser

unread,
Dec 15, 2023, 4:03:38 PM12/15/23
to fltkg...@googlegroups.com
On 12/15/23 04:04 Pavel wrote:
Thanks Albrecht.

Welcome.


On Thursday, December 14, 2023 at 11:37:21 AM UTC-5 Albrecht Schlosser wrote:
On 12/14/23 02:52 Pavel wrote:

There is also another issue with your "wingman" approach, particularly
on the Wayland platform. On this platform applications (in our case the
FLTK library) are not able to read the current window coordinates and we
can't position a new window at arbitrary screen coordinates.
Noted. Even on my xfce4 I noticed that x() and y() stay zeros while handling FL_SHOW, FL_DEACTIVATE and FL_ACTIVATE, and only become sensible on the next event (FL_FOCUS):
handling 16(FL_SHOW) mainWin(0,0,340,180), wingMan(null)
handling 13(FL_DEACTIVATE) mainWin(0,0,340,180), wingMan(null)
handling 14(FL_ACTIVATE) mainWin(0,0,340,180), wingMan(null)
activated, active_r:1
deactivated, active_r:1

Docs of Fl_Widget::deactivate() say: "Currently you cannot deactivate Fl_Window widgets.". I don't know why that is so but as you see active_r() is still 1 after deactivation (if I interpret your text correctly).


window x,y,w,h: 0 0 340 180
handling 6(FL_FOCUS) mainWin(790,460,340,180), wingMan(390,0,340,180)
handling 6(FL_FOCUS) mainWin(790,460,340,180), wingMan(390,24,340,180)

You may want to use Fl_Window::wait_for_expose() after Fl_Window::show(). Then you should be able to read x() and y() - provided your platform is not wayland which will always return 0.


These two features are prohibited by Wayland for security reasons.
I guess I don't understand their concern: it would seem to me that if a user is allowed to move window around and be aware of its location, the process running with this user's permissions should, too. Need to do some reading about their rationale and how common it is.

I believe many people don't understand this. I **believe** it has to do with the deficiencies of X11 where other applications can interfere with a user's windows etc.. On X11 it is possible to read other Windows' contents and a bad program might be able to *overlay* a window on another program's window and catch input events (passwords) etc..


There is a special Wayland option though so you can position a window relative to
an existing window (used for menus and other popup windows). I'm not
aware of a FLTK method to utilize this to position a window like your
"wingman" window near or relative to the main window, even if you could
track window movement.
Thanks! It seems I could use the relative positioning for my purpose if it was exposed. If those security considerations becomes a mainstream, the APIs to just note movements (without coordinates) and do relative positioning could help achieve my goal.

@Manolo: do you have an idea how we could expose a way to position a window relative to an existing window as it is done internally  for menus? This could also be useful for dialogs like fl_ask() etc. which have some positioning options - one is to position the dialog centered on the main window, for instance.

What I would like my app look like is similar to gimp (when not in a single-window mode). The idea is to use those wingmans to configure a non-rectangular space so the user could read from the window  of another app below my app and do something with my app. [...]

Interesting. But I believe this could be left to the user. Being able to move more windows in common has its own problems, e.g. screen limits.

Pavel

unread,
Dec 16, 2023, 12:10:02 AM12/16/23
to fltk.general


On Friday, December 15, 2023 at 4:03:38 PM UTC-5 Albrecht Schlosser wrote:
...
Docs of Fl_Widget::deactivate() say: "Currently you cannot deactivate Fl_Window widgets.". I don't know why that is so but as you see active_r() is still 1 after deactivation (if I interpret your text correctly).
 No, it works for me, it is just it seems both activate() and deactivate() deliver their events "synchronously" i.e. on the same call stack (on my system). The following, more verbose, handle() function and the output should illustrate this well:
// ------- function, cut here
  int handle(int event) override {

    if (event != FL_NO_EVENT) {
      cout << "handling " << event << '(' << fl_eventnames[event] << ')' <<
        " mainWin(" << *this << "), wingMan(";
        if (wingmanWin_.get()) {
          cout << *wingmanWin_.get();
        } else {
          cout << "null";
        }
        cout << "), active_r:" << active_r() << ", active:" << active() << endl;

    }
    switch (event) {
    case FL_SHOW:
      if (!wingmanWin_.get()) {
        deactivate();
        cout << "deactivated, active_r:" << active_r() << ", active:" <<
          active() << endl;

      }
      break;
    case FL_ACTIVATE:
      if (!wingmanWin_.get()) {
        wingmanWin_ = CreateWingman(*this);
        wingmanWin_->show();
      }
      wingmanWin_->position(x() + 50 + w(), y() /*- (h() * 4) / 3*/);
      break;
    case FL_DEACTIVATE:
      if (!wingmanWin_.get()) {
        activate();
        cout << "activated, active_r:" << active_r() << ", active:" <<
          active() << endl;

      }
      break;
    default:
      return 0;
    }
    return 1;
  }
// --------- output, 
./hello2
handling 16(FL_SHOW) mainWin(0,0,340,180), wingMan(null), active_r:1, active:1
handling 13(FL_DEACTIVATE) mainWin(0,0,340,180), wingMan(null), active_r:0, active:0
handling 14(FL_ACTIVATE) mainWin(0,0,340,180), wingMan(null), active_r:1, active:1
activated, active_r:1, active:1
deactivated, active_r:1, active:1

window x,y,w,h: 0 0 340 180
handling 6(FL_FOCUS) mainWin(790,460,340,180), wingMan(390,0,340,180), active_r:1, active:1
handling 6(FL_FOCUS) mainWin(790,460,340,180), wingMan(390,24,340,180), active_r:1, active:1


You may want to use Fl_Window::wait_for_expose() after Fl_Window::show(). Then you should be able to read x() and y() - provided your platform is not wayland which will always return 0.
 This is useful, now it seems all pieces came together to try the actual thing. Will try to write a simple app demonstrating this ui.
...
 
Interesting. But I believe this could be left to the user. Being able to move more windows in common has its own problems, e.g. screen limits.
True, but as long as these cases feel intuitive (to the user) and can be recovered from naturally (by simple actions of theirs), I think it should be ok. The user will still be able to arrange their windows at will but would be able to move them together as well (i.e., "the best of the two worlds"). Will try and report the result.
 

Manolo

unread,
Dec 16, 2023, 2:42:29 AM12/16/23
to fltk.general
In reply to : "@Manolo: do you have an idea how we could expose a way to position a window relative to an existing window as it is done internally  for menus? This could also be useful for dialogs like fl_ask() etc. which have some positioning options - one is to position the dialog centered on the main window, for instance."

I see the fl_message_position() functions. The 1st one intends to give an absolute screen position to the top-left or the center
of a dialog window. That's not possible with Wayland.

The 2nd one intends to position the center of the dialog relatively to a previously mapped widget. That should be doable
under Wayland, and I will look into it.


Pavel

unread,
Dec 16, 2023, 9:39:06 PM12/16/23
to fltk.general
So, just in case it's interesting or someone wants to try on their system and report the result, I implemented the window arrangement example that works as I wanted it to work, more or less. Below is the complete code. I had to write some extra code for this to work more or less reliably on my system (my guess is that without event filtering by OldPosKeeper too many events sometimes overloaded the system) but I think I did not really had to hack or rely on undefined behavior too much. I don't have wayland to try. It is likely that wingman won't follow main window there. If this is all that does not work, I would count this as graceful failing.

#include <cassert>
#include <iostream>
#include <memory>

#include <FL/Fl.H>

#include <FL/Fl_Rect.H>
#include <FL/Fl_Window.H>

using namespace std;

class PosSizeListener {
public:
  virtual void onNewPosSize(int x, int y, int w, int h) = 0;
};

class OldPosKeeper: public Fl_Window {
protected:
  using Fl_Window::Fl_Window;
  bool updatePosIfNeeded() {
    auto updateInt = [](int& oldInt, int newInt) -> bool {
      if (oldInt != newInt) {
        oldInt = newInt;
        return true;
      }
      return false;
    };
    return updateInt(oldX_, x()) || updateInt(oldY_, y());
  }
private:
  int oldX_ = -1;
  int oldY_ = -1;
};

class Wingman: public OldPosKeeper {
public:
  Wingman(PosSizeListener *l, int x, int y, int w, int h, const char* title):
    OldPosKeeper(x, y, w, h, title),
    posSizeListener_(l)
  {
    assert(!!l);
    resizable(*this);
    set_non_modal();
  }
  int handle(int event) override {
    switch (event) {
    case FL_MOVE:
      if (updatePosIfNeeded()) {
        posSizeListener_->onNewPosSize(x(), y(), w(), h());
      }
      break;
    default:
      break;
    }
    return 0;
  }
private:
  PosSizeListener *posSizeListener_;
};

class MainWin:
  public OldPosKeeper,
  public PosSizeListener {
public:
  using OldPosKeeper::OldPosKeeper;
  int handle(int event) override {
    bool isFocusEvent = false;
    if (!haveWingman_()) {
      switch (event) {
      case FL_FOCUS:
        cout << "Main got focus\n";
        createAndShowWingman_();
        cout << "Main created wm\n";
        break;
      default:
        break;
      }
    } else {
      switch (event) {
      case FL_FOCUS:
        isFocusEvent = true;
      case FL_MOVE:
        if (updatePosIfNeeded()) {
          cout << "Main " << (isFocusEvent ? "focused" : "moved") << " to " <<
            x() << ',' << y() << endl;
          syncWingman_();
          cout << "Main synced wm\n";
        }
        break;
      case FL_HIDE:
        if (!!wingmanWin_.get())
          wingmanWin_->hide();
        break;
      default:
        break;
      }
    }

    return 0; // try "not handled"
  }
  void onNewPosSize(int x, int y, int w, int h) override {
    assert(!!wingmanWin_.get());
    dx_ = wingmanWin_->x() - this->x();
    dy_ = wingmanWin_->y() - this->y();
  }
private:
  void createAndShowWingman_() {
    assert(!wingmanWin_.get());
    const Fl_Rect r = calcInitWmPosSize_();
    dx_ = r.x() - x();
    dy_ = r.y() - y();
    wingmanWin_.reset(new Wingman(this, r.x(), r.y(), r.w(), r.h(), "Wingman"));
    wingmanWin_->show();
  }
  Fl_Rect calcInitWmPosSize_() {
    return Fl_Rect(x() + w() + 50, y() - h() / 2 - 30, w() / 2, h() / 2);
  }
  bool haveWingman_() const { return !!wingmanWin_.get(); }
  void syncWingman_() {
    assert(!!wingmanWin_.get());
    const Fl_Rect r(x() + dx_, y() + dy_, wingmanWin_->w(), wingmanWin_->h());
    wingmanWin_->resize(r.x(), r.y(), r.w(), r.h());
  }
  unique_ptr<Fl_Window> wingmanWin_;
  int dx_ = 100;
  int dy_ = 50;

};

int
main(int argc, char **argv) {
  unique_ptr<Fl_Window> mainWin(new MainWin(500, 300, "MainWin"));
  mainWin->show();
  return Fl::run();
}


Pavel

unread,
Dec 16, 2023, 10:22:06 PM12/16/23
to fltk.general
There was a bug in the above, "updateInt(oldX_, x()) || updateInt(oldY_, y())" should have used | instead of || to avoid short-circuiting.

Ian MacArthur

unread,
Dec 18, 2023, 4:13:41 AM12/18/23
to fltk.general
As an alternate "works under Wayland" scheme, I was wondering about a mechanism somewhat based on Albrecht's suggestion of using a single larger window, with two (resizable, movable) groups in it, one for the "main window" and one for the "wingman".
The real window would be made as a shaped window, with opaque areas for the two "active groups" and the rest of the window area transparent - the idea is to give the *appearance* of two detached windows, whilst actually only having one window as far as Wayland is concerned.

This might not do what Pavel intended either, mind you, since it is not possible to "click-through" the transparent window regions to any underlying object, even though you can see the underlying object, the events are not delivered since they go to the "invisible" window region instead...

And I don't have code to post since I haven't made it work as I wanted yet anyway!

 
Reply all
Reply to author
Forward
0 new messages