I am trying to "raise" (draw "on top" of other overlapping windows and possibly make "active") a specific window in response to an event. The official FLTK documentation seems to say that the Fl_Window::show()
method is the way to do this. However, there is no corresponding WindowExt::show()
(or any similar) method in fltk-rs
.
There is a WidgetExt::show()
method, but it does not raise a window when invoked. There is also a similarly promising but similarly disappointing DoubleWindow::platform_show()
method.
What I have gotten to work is to call .hide()
and then immediately call .show()
on the window in question. This produces the desired effect of raising the window in question to the top of the pile. However, this
- Seems hacky, right? Like going around one's rear to reach one's elbow.
- Really does hide then show the window. On my Debian system running i3, this is almost unnoticeable (the flicker might just be standard window-redrawing), but under Windows this is terrible, because
.hide()
ing the window triggers a short (but oh-so-noticeable) fade-out animation (and.show()
ing it a corresponding fade-in animation, plus there might even be a little shrink/grow action happening, too), which is bad user experience and looks like something is malfunctioning.
Here's an example:
use fltk::{
prelude::*,
app::App,
enums::Color,
frame::Frame,
window::DoubleWindow,
button::Button,
};
fn main() {
let a = App::default();
let mut sub_win = DoubleWindow::default()
.with_size(128, 128)
.with_pos(64, 64);
sub_win.set_border(false);
sub_win.set_color(Color::Magenta); // So you can see it clearly.
let _ = Frame::default().with_label("Sub Window")
.with_size(128, 128)
.with_pos(0, 0);
sub_win.end();
sub_win.show();
let mut main_win = DoubleWindow::default().with_label("Main Window")
.with_size(256, 128)
.with_pos(0, 0);
let mut b0 = Button::default().with_label("won't work")
.with_size(96, 64)
.with_pos(20, 32);
let mut b1 = Button::default().with_label("is hacky")
.with_size(96, 64)
.with_pos(130, 32);
main_win.end();
main_win.show();
b0.set_callback({
let mut sub_win = sub_win.clone();
move |_| {
sub_win.show(); // The FLTK docs suggest this should work.
sub_win.platform_show(); // This also disappoints.
}
});
b1.set_callback(move |_| {
sub_win.hide(); // This combination is what
sub_win.show(); // actually works.
});
a.run().unwrap();
}
If anybody knows the magic incantation I seek, I'd appreciate it.
Edit
I guess I didn't do enough investigation beforehand. The problem does not seem to be with fltk-rs specifically; in fact, it may not even be with FLTK; it might be specific to my X11 or window manager settings.
For example, the following C++ program exhibits the exact same behavior as the Rust one above:
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
Fl_Window *SUB_WIN;
void b_zero_cb(Fl_Widget *b) {
SUB_WIN->show();
SUB_WIN->redraw();
}
void b_one_cb(Fl_Widget *b) {
SUB_WIN->hide();
SUB_WIN->show();
SUB_WIN->redraw();
}
int main(int argc, char **argv) {
SUB_WIN = new Fl_Window(64, 64, 128, 128);
Fl_Box *sub_label = new Fl_Box(0, 0, 128, 128, "Sub Window");
SUB_WIN->color(FL_DARK_MAGENTA);
SUB_WIN->border(false);
SUB_WIN->xclass("Floating");
SUB_WIN->end();
SUB_WIN->show();
Fl_Window *win = new Fl_Window(0, 0, 256, 128, "Main Window");
Fl_Button *b0 = new Fl_Button(20, 32, 96, 64, "won't work");
Fl_Button *b1 = new Fl_Button(130, 32, 96, 64, "hacky?");
win->end();
win->xclass("Floating");
win->show();
b0->callback(b_zero_cb);
b1->callback(b_one_cb);
return Fl::run();
}
Several commenters report that the Rust version works as expected on their systems, and neither of the above programs work as expected on my system, so I'm going to assume it's an issue with my system.
If it matters, I am using X11 with the i3
tiling window manager. (I do have it configured so that the windows in these examples are all automatically placed in the floating layer and not tiled; I'm not that dense.)
I'm not sure what to do with this questions. Should I just delete it?