How to raise a window using fltk-rs - rust

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?

On the C++ end, Fl_Widget::show() is a virtual function that should raise the window, if the variable points to a top-level window (a window with no parent). On the Rust side, I see these lines:
extern "C" {
pub fn Fl_Window_show(arg1: *mut Fl_Window);
}
which seem to indicate that there is a direct interface for calling Fl_Window::show(), and the same for Fl_Double_Window.

Related

Moving windows in ncurses

I've read window(3NCURSES) man page, but I can't fully understand what mvwin() function actually does and what happens to its subwindows.
The code below creates a window with a title "Window" and a border, it also creates a subwindow that is used for printing y,x position without corrupting parent window border. It then moves the parent window to a new location, but the result is not what I expected:
After the window is moved, the outline of the windows border + text is not automatically erased at the old location.
After the move, writing text to a subwindow, outputs it at the old and new location.
After the move, parent window has new y,x coordinates, but subwindow still shows old coordinates.
I don't have a lot of experience with ncurses, and maybe I'm missing something, but this behaviour is completely illogical. If I have to manually erase windows at old location and manually move all subwindows, then this negates the benefit of using ncurses in the first place. I was expecting ncurses to automatically handle these low-level details.
My understanding of subwindows was that they are used to partition one large window into smaller non-overlapping areas. So when the parent window is moved or refreshed, all its subwindows should be moved or refreshed automatically. Is this correct?
#include <assert.h>
#include <ncurses.h>
#include <unistd.h>
int main()
{
WINDOW *win, *swin;
int lines, cols, y, x;
initscr();
keypad(stdscr, TRUE);
noecho();
// Create window
lines = 10; cols = 40;
y = 5; x = 5;
win = newwin(lines, cols, y, x);
assert(win != NULL);
// Create window border
box(win, 0, 0);
mvwprintw(win, 0, 2, " Window ");
// Create subwindow
swin = subwin(win, lines-2, cols-2, y+1, x+1);
assert(swin != NULL);
// Print window and subwindow y,x
mvwprintw(swin, 0, 0, "win y,x=%d,%d swin y,x=%d,%d\n",
getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));
// Refresh
wnoutrefresh(stdscr);
wnoutrefresh(win);
wnoutrefresh(swin);
doupdate();
sleep(2);
// Move window
y = 20; x = 40;
mvwin(win, y, x);
mvwprintw(swin, 0, 0, "win y,x=%d,%d swin y,x=%d,%d\n",
getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));
// Refresh
wnoutrefresh(stdscr);
wnoutrefresh(win);
wnoutrefresh(swin);
doupdate();
wgetch(swin);
endwin();
return 0;
}
Apparently not: a quick check with Solaris 10 gives the same behavior. You might find some scenario where ncurses differs unintentionally, but this is not one of those. The FAQ makes this point about compatibility:
extensions (deviations from SVr4 curses) are allowed only if they do not modify the documented/observed behavior of the API.
The Solaris manual page does not make this clear, since the only mention of subwindows is in regard to moving them:
The mvwin() routine moves the window so that the upper left-hand corner is at position (x, y). If the move would cause the window to be off the screen, it is an error and the window is not moved. Moving subwindows is allowed, but should be avoided.
The Solaris source code tells the story for that: it does nothing with subwindows. Some retesting a while back (early 2006) in response to a user's comment about differences pointed out that ncurses was incorrectly attempting to copy subwindows. That part is ifdef'd out (since it's too interesting to just delete). Since there's not much left for mvwin to do, the actual code is fairly similar.
X/Open's description of mvwin is too brief and vague to be of any use.

X11 - Setting Cursor Position Not Working

I'm trying to set my X11 cursor position. I tried calling XWarpPointer with the window set to None, root (DefaultRootWindow(display)), to the previously created window (XCreateWindow). The function IS being called, the mouse slows down a bit, but it does not physically move. Why could this be?
void GameWindow::ResetCursor() {
SetCursor(resX / 2, resY / 2);
}
void GameWindow::SetCursor(int x, int y) {
// Window root = DefaultRootWindow(display);
XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
XFlush(display);
}
EDIT: Here's the entire X11 Windowing file in case you can't find the reason here. https://gist.github.com/KarimIO/7db1f50778fda63a36c10242989baab6
The answer to this was relatively silly. I was using Gnome on Wayland, assuming it supported X11 as well. I assumed wrong.

fltk setting button's active label color

I am using fltk 1.3.2.
I set the button's label color with
_button->labelcolor(fl_rgb_color(162, 60, 62));
but when I press the button, the color is changed.
I couldn't find the function how set the active label color.
Does anyone know how to do that?
Edit:
I use Fl::background() and Fl::foreground() functions before creating the window. This make the problem.
Edit2:
This example shows the problem.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <iostream>
void HitMe(Fl_Widget* w)
{
std::cout << "Ouch" << std::endl;
}
int main(int argc, char ** argv)
{
Fl::background(0x60, 0x66, 0x60);
Fl_Window *window = new Fl_Window(320,130);
Fl_Button *b = new Fl_Button(10, 10, 130, 30, "A red label");
b->labelcolor(fl_rgb_color(162, 60, 20));
b->callback(HitMe);
window->end();
window->show(argc,argv);
return Fl::run();
}
When I commented out Fl::background() function everything is alright.
What you are seeing is the contrasting colour (see commented out code below). FLTK does this when the button is pressed. It gets the colour of the button, works out the contrasting colour based on the foreground and background colours. Have a look at the help for fl_contrast for more details.
Basically, if there is enough contrast, it will use the foreground colour otherwise it will find a contrasting colour for your background.
What can you do about it?
do nothing - that is how it is
choose a lighter background colour which will satisfy the contrast conditions
make your own button type with its own draw method
class KeepFGButton : public Fl_Button
{
public:
KeepFGButton(int x, int y, int w, int h, const char* s)
: Fl_Button(x, y, w, h, s)
{
}
void draw() {
if (type() == FL_HIDDEN_BUTTON) return;
Fl_Color col = value() ? selection_color() : color();
draw_box(value() ? (down_box() ? down_box() : fl_down(box())) : box(), col);
draw_backdrop();
// Remove the code that changes the contrast
//if (labeltype() == FL_NORMAL_LABEL && value()) {
// Fl_Color c = labelcolor();
// labelcolor(fl_contrast(c, col));
// draw_label();
// labelcolor(c);
//}
//else
draw_label();
if (Fl::focus() == this) draw_focus();
}
};
int main(int argc, char ** argv)
{
Fl::background(0x60, 0x66, 0x60);
Fl_Window *window = new Fl_Window(320, 130);
Fl_Button *b = new KeepFGButton(10, 10, 130, 30, "A red label");
...
Try the following and let me know if, when you run it, the label becomes white. If it doesn't then there is possibly something else that you are doing that is not quite right. If it does, I don't know what the problem is.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <iostream>
void HitMe(Fl_Widget* w)
{
std::cout << "Ouch" << std::endl;
}
int main(int argc, char ** argv) {
Fl_Window *window = new Fl_Window(320,130);
Fl_Button *b = new Fl_Button(10, 10, 130, 30, "A red label");
b->labelcolor(fl_rgb_color(162, 60, 20));
b->callback(HitMe);
window->end();
window->show(argc,argv);
return Fl::run();
}
This is definitely too late to help the author, but in the event that this helps anyone else searching for an answer to this still relevant issue in FLTK, I'm going to offer my solution:
If you dig through the source code for FLTK 1.3.4-2 (current stable as of this post), there are a couple of built-in colormap indices which are referenced when the drawing of shadow boxes or frames are called: FL_DARK3 (for the boxes) and FL_DARK2 (for the scrollbar back color in Fl_Scroll). You can look at this FLTK documentation to see how to reset these colors to anything you wish at runtime. In particular, anticipating that this ugly red default mess will show up whenever there's a sufficiently dark background, it works well for me to just set these to a slightly lighter version of the overlayed box color:
Fl_Color boxColor = 0x88888800;
Fl_Color boxShadowColor = 0xaaaaaa00;
Fl::set_color(FL_DARK3, boxShadowColor);
Fl::set_color(FL_DARK2, boxShadowColor);
Now create your label as above and the display will be free of the red shadow. N.b. it is also possible to override the standard background2() behavior which resets FL_BACKGROUND_COLOR to the one produced by fl_contrast:
Fl::set_color(FL_BACKGROUND2_COLOR, yourBgColor);
The same trick works for other hard to reset colors like FL_INACTIVE_COLOR and FL_SELECTION_COLOR.
Hope this workaround helps.

How to precompile SpiderMonkey code for faster execution?

I am using code like this:
JS_EvaluateScript(context, global,"go_back('blabla')", 17, "", 1, &R);
to call go_back(), which is already in the context. But this is extremely slow, and I think because the string have to be compiled each time.
I try to find the way to call the same piece of code many times in a fast way, without recompilation, or some object creation each time. But Mozilla docs and sources are not organized that way, there is only a reference, and you need to know every function before you can make any choice.
So any hints? What would be the best practice for this?
JSFunction * FUNC = 0;
static JSBool my_native(JSContext *cx, uintN argc, jsval *vp) {
jsval R = JSVAL_FALSE;
if (FUNC == 0) {
const char *ARGS[1] = {"s"}, *src = "go_back(s)";
FUNC = JS_CompileFunction(cx, 0, 0, 1, ARGS, src, 10, "", 0);
}
JS_CallFunction(cx, 0, FUNC, 1, &R, &R);
return JS_TRUE;
}
This is very fast (20 times in my example), compared to JS_EvaluateScript. Note that this code is very simplified, you still need to pass the string argument somehow. (I am not sure myself how to do that.) And you may need to JS_ReportPendingException() as go_back() can sometimes fail.

Freetype2 failing under WoW64

I built a tff to D3D texture function using freetype2(2.3.9) to generate grayscale maps from the fonts. it works great under native win32, however, on WoW64 it just explodes (well, FT_Done and FT_Load_Glyph do). from some debugging, it seems to be a problem with HeapFree as called by free from FT_Free.
I know it should work, as games like WCIII, which to the best of my knowledge use freetype2, run fine, this is my code, stripped of the D3D code(which causes no problems on its own):
FT_Face pFace = NULL;
FT_Error nError = 0;
FT_Byte* pFont = static_cast<FT_Byte*>(ARCHIVE_LoadFile(pBuffer,&nSize));
if((nError = FT_New_Memory_Face(pLibrary,pFont,nSize,0,&pFace)) == 0)
{
FT_Set_Char_Size(pFace,nSize << 6,nSize << 6,96,96);
for(unsigned char c = 0; c < 95; c++)
{
if(!FT_Load_Glyph(pFace,FT_Get_Char_Index(pFace,c + 32),FT_LOAD_RENDER))
{
FT_Glyph pGlyph;
if(!FT_Get_Glyph(pFace->glyph,&pGlyph))
{
LOG("GET: %c",c + 32);
FT_Glyph_To_Bitmap(&pGlyph,FT_RENDER_MODE_NORMAL,0,1);
FT_BitmapGlyph pGlyphMap = reinterpret_cast<FT_BitmapGlyph>(pGlyph);
FT_Bitmap* pBitmap = &pGlyphMap->bitmap;
const size_t nWidth = pBitmap->width;
const size_t nHeight = pBitmap->rows;
//add to texture atlas
}
}
}
}
else
{
FT_Done_Face(pFace);
delete pFont;
return FALSE;
}
FT_Done_Face(pFace);
delete pFont;
return TRUE;
}
ARCHIVE_LoadFile returns blocks allocated with new.
As a secondary question, I would like to render a font using pixel sizes, I came across FT_Set_Pixel_Sizes, but I'm unsure as to whether this stretches the font to fit the size, or bounds it to a size. what I would like to do is render all the glyphs at say 24px (MS Word size here), then turn it into a signed distance field in a 32px area.
Update
After much fiddling, I got a test app to work, which leads me to think the problems are arising from threading, as my code is running in a secondary thread. I have compiled freetype into a static lib using the multithread DLL, my app uses the multithreaded libs. gonna see if i can set up a multithreaded test.
Also updated to 2.4.4, to see if the problem was a known but fixed bug, didn't help however.
Update 2
After some more fiddling, it turns out I wasn't using the correct lib for 2.4.4 -.- after fixing that, the test app works 100%, but the main app still crashes when FT_Done_Face is called, still seems to be a crash in the memory heap management of windows. is it possible that there is a bug in freetype2 that makes it blow up under user threads?

Resources