Rearrange the dialog event loop a little
This patch is contributed by @x-qq and should improve CPU usage on Linux.
This commit is contained in:
@@ -387,13 +387,9 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
// TODO: The introduction of the static topWindow means I may be able to use this instead of parent->win; do I still need parent?
|
||||
sf::RenderWindow* parentWin = &(parent ? parent->win : mainPtr);
|
||||
cursor_type former_curs = Cursor::current;
|
||||
set_cursor(sword_curs);
|
||||
using kb = sf::Keyboard;
|
||||
kb::Key k;
|
||||
cKey key, pendingKey = {true};
|
||||
sf::Event currentEvent;
|
||||
std::string itemHit = "";
|
||||
dialogNotToast = true;
|
||||
set_cursor(sword_curs);
|
||||
sf::Event currentEvent;
|
||||
// Focus the first text field, if there is one
|
||||
if(!tabOrder.empty()) {
|
||||
auto iter = std::find_if(tabOrder.begin(), tabOrder.end(), [](std::pair<std::string,cTextField*> ctrl){
|
||||
@@ -421,14 +417,49 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
ModalSession dlog(win, *parentWin);
|
||||
if(onopen) onopen(*this);
|
||||
animTimer.restart();
|
||||
while(dialogNotToast){
|
||||
|
||||
handle_events();
|
||||
|
||||
win.setVisible(false);
|
||||
while(parentWin->pollEvent(currentEvent));
|
||||
set_cursor(former_curs);
|
||||
topWindow = formerTop;
|
||||
makeFrontWindow(*parentWin);
|
||||
}
|
||||
|
||||
// This method is a main event event loop of the dialog.
|
||||
void cDialog::handle_events() {
|
||||
sf::Event currentEvent;
|
||||
|
||||
sf::Clock framerate_clock;
|
||||
const sf::Int64 desired_microseconds_per_frame { 1000000 / 60 }; // us / FPS
|
||||
|
||||
while(dialogNotToast) {
|
||||
while(win.pollEvent(currentEvent)) handle_one_event(currentEvent);
|
||||
|
||||
// Ideally, this should be the only draw call that is done in a cycle.
|
||||
draw();
|
||||
if(!win.pollEvent(currentEvent)) continue;
|
||||
|
||||
// Prevent the loop from executing too fast.
|
||||
const sf::Int64 remaining_time_budget = desired_microseconds_per_frame - framerate_clock.getElapsedTime().asMicroseconds();
|
||||
if(remaining_time_budget > 0) sf::sleep(sf::microseconds(remaining_time_budget));
|
||||
framerate_clock.restart();
|
||||
}
|
||||
}
|
||||
|
||||
// This method handles one event received by the dialog.
|
||||
void cDialog::handle_one_event(const sf::Event& currentEvent) {
|
||||
using kb = sf::Keyboard;
|
||||
|
||||
cKey key;
|
||||
// HACK: This needs to be stored between consecutive invocations of this function
|
||||
static cKey pendingKey = {true};
|
||||
std::string itemHit = "";
|
||||
location where;
|
||||
switch(currentEvent.type){
|
||||
|
||||
switch(currentEvent.type) {
|
||||
case sf::Event::KeyPressed:
|
||||
k = currentEvent.key.code;
|
||||
switch(k){
|
||||
switch(currentEvent.key.code){
|
||||
case kb::Up:
|
||||
key.spec = true;
|
||||
key.k = key_up;
|
||||
@@ -497,10 +528,10 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
case kb::RControl:
|
||||
case kb::LSystem:
|
||||
case kb::RSystem:
|
||||
continue;
|
||||
return;
|
||||
default:
|
||||
key.spec = false;
|
||||
key.c = keyToChar(k, false);
|
||||
key.c = keyToChar(currentEvent.key.code, false);
|
||||
break;
|
||||
}
|
||||
key.mod = mod_none;
|
||||
@@ -512,11 +543,13 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
// Now check for focused fields.
|
||||
if(currentFocus.empty()) break;
|
||||
// If it's a tab, handle tab order
|
||||
if(key.spec && key.k == key_tab){
|
||||
if(key.spec && key.k == key_tab) {
|
||||
// Could use key.mod, but this is slightly easier.
|
||||
if(currentEvent.key.shift)
|
||||
if(currentEvent.key.shift) {
|
||||
handleTabOrder(currentFocus, tabOrder.rbegin(), tabOrder.rend());
|
||||
else handleTabOrder(currentFocus, tabOrder.begin(), tabOrder.end());
|
||||
} else {
|
||||
handleTabOrder(currentFocus, tabOrder.begin(), tabOrder.end());
|
||||
}
|
||||
} else {
|
||||
// If it's a character key, and the system key (control/command) is not pressed,
|
||||
// we have an upcoming TextEntered event which contains more information.
|
||||
@@ -562,12 +595,6 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
if(!inField) set_cursor(sword_curs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
win.setVisible(false);
|
||||
while(parentWin->pollEvent(currentEvent));
|
||||
set_cursor(former_curs);
|
||||
topWindow = formerTop;
|
||||
makeFrontWindow(*parentWin);
|
||||
}
|
||||
|
||||
template<typename Iter> void cDialog::handleTabOrder(string& itemHit, Iter begin, Iter end) {
|
||||
|
||||
@@ -214,6 +214,8 @@ public:
|
||||
cDialog(cDialog& other) = delete;
|
||||
private:
|
||||
void draw();
|
||||
void handle_events();
|
||||
void handle_one_event(const sf::Event&);
|
||||
void process_keystroke(cKey keyHit);
|
||||
void process_click(location where, eKeyMod mods);
|
||||
bool dialogNotToast, didAccept;
|
||||
|
||||
Reference in New Issue
Block a user