The only way to work around is immediate mode UI, but this requires fairly powerful CPU, so it's only feasible on the modern machines. Certainly not something that people would want about 30 years ago, they still cared about performance back then.
Compare a hypothetical "Immediate Mode" counter:
void render_and_handle_button_click(struct ctx *ctx){
draw_text(ctx, "Count: %d", ctx->count);
if(draw_button(ctx, "Increment")){
ctx->count++;
}
}
To the equivalent "Retained" counter: void render(struct ctx *ctx){
set_textbox_text(ctx->textbox, "Count: %d", ctx->count);
}
void handle_button_click(void *ctx_in){
struct ctx *ctx = ctx_in;
ctx->count++;
render(ctx);
}
void init(struct ctx *ctx){
ctx->textbox = create_textbox(ctx);
ctx->button = create_button(ctx);
set_button_text(ctx->button, "Increment");
set_button_click_handler(ctx->button, ctx, handle_button_click);
render(ctx);
}
The only difference I see here is whether the stateful "cache" of UI components (ctx->textbox and ctx->button) is library-side or application-side.- If you have partial redraw request, can you quickly locate _only_ the controls which are covered and only redraw those?
- If you are clicking on something, can you quickly locate which component will receive the click?
- If you are moving mouse, or dragging a selection, can you quickly determine if any components should change the state? Can you avoid running the full event loop on every mouse move event?
- If your application state has updated, do you need to force redraw or not? (Many immediate mode UIs fail badly here, never going to idle even if nothing is happening)
This is all trivial in the old-style UI - efficient redraw / mouse mapping is table stakes in the older GUIs. While all that immediate mode can do is to keep running redraw loop _every_ _single_ _time_ something as trivial as mouse move is happening, just in case this can change highlighted item or something.
(Unless the "immediate mode UI" is just a thin veneer, and library is using good-old OOP based GUI components under the hood... but in this case, it's still faster to cut out the middleman and control components yourself)
And yes, back when I was doing "game development" class in college, around that time, I've used the immediate mode UI for menus. This only makes sense - games run on foreground _anyway_, and they basically consume 100% of CPU anyway. But for regular apps? Please don't.
Example: I just opened https://www.egui.rs/#demo in background tab... The browser's task manager shows this tab never goes idle, consuming between 0.1% and 3%. Considering I often have 40+ tabs open, this can take a significant part of CPU.
Immediate mode GUIs, unless in app which already uses 100% CPU, like game or video player, will always be less efficient than classical event-driven ones.