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?
|
// 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);
|
sf::RenderWindow* parentWin = &(parent ? parent->win : mainPtr);
|
||||||
cursor_type former_curs = Cursor::current;
|
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;
|
dialogNotToast = true;
|
||||||
|
set_cursor(sword_curs);
|
||||||
|
sf::Event currentEvent;
|
||||||
// Focus the first text field, if there is one
|
// Focus the first text field, if there is one
|
||||||
if(!tabOrder.empty()) {
|
if(!tabOrder.empty()) {
|
||||||
auto iter = std::find_if(tabOrder.begin(), tabOrder.end(), [](std::pair<std::string,cTextField*> ctrl){
|
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);
|
ModalSession dlog(win, *parentWin);
|
||||||
if(onopen) onopen(*this);
|
if(onopen) onopen(*this);
|
||||||
animTimer.restart();
|
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();
|
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;
|
location where;
|
||||||
switch(currentEvent.type){
|
|
||||||
|
switch(currentEvent.type) {
|
||||||
case sf::Event::KeyPressed:
|
case sf::Event::KeyPressed:
|
||||||
k = currentEvent.key.code;
|
switch(currentEvent.key.code){
|
||||||
switch(k){
|
|
||||||
case kb::Up:
|
case kb::Up:
|
||||||
key.spec = true;
|
key.spec = true;
|
||||||
key.k = key_up;
|
key.k = key_up;
|
||||||
@@ -497,10 +528,10 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
|||||||
case kb::RControl:
|
case kb::RControl:
|
||||||
case kb::LSystem:
|
case kb::LSystem:
|
||||||
case kb::RSystem:
|
case kb::RSystem:
|
||||||
continue;
|
return;
|
||||||
default:
|
default:
|
||||||
key.spec = false;
|
key.spec = false;
|
||||||
key.c = keyToChar(k, false);
|
key.c = keyToChar(currentEvent.key.code, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
key.mod = mod_none;
|
key.mod = mod_none;
|
||||||
@@ -512,11 +543,13 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
|||||||
// Now check for focused fields.
|
// Now check for focused fields.
|
||||||
if(currentFocus.empty()) break;
|
if(currentFocus.empty()) break;
|
||||||
// If it's a tab, handle tab order
|
// 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.
|
// Could use key.mod, but this is slightly easier.
|
||||||
if(currentEvent.key.shift)
|
if(currentEvent.key.shift) {
|
||||||
handleTabOrder(currentFocus, tabOrder.rbegin(), tabOrder.rend());
|
handleTabOrder(currentFocus, tabOrder.rbegin(), tabOrder.rend());
|
||||||
else handleTabOrder(currentFocus, tabOrder.begin(), tabOrder.end());
|
} else {
|
||||||
|
handleTabOrder(currentFocus, tabOrder.begin(), tabOrder.end());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it's a character key, and the system key (control/command) is not pressed,
|
// 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.
|
// 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);
|
if(!inField) set_cursor(sword_curs);
|
||||||
break;
|
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) {
|
template<typename Iter> void cDialog::handleTabOrder(string& itemHit, Iter begin, Iter end) {
|
||||||
|
|||||||
@@ -214,6 +214,8 @@ public:
|
|||||||
cDialog(cDialog& other) = delete;
|
cDialog(cDialog& other) = delete;
|
||||||
private:
|
private:
|
||||||
void draw();
|
void draw();
|
||||||
|
void handle_events();
|
||||||
|
void handle_one_event(const sf::Event&);
|
||||||
void process_keystroke(cKey keyHit);
|
void process_keystroke(cKey keyHit);
|
||||||
void process_click(location where, eKeyMod mods);
|
void process_click(location where, eKeyMod mods);
|
||||||
bool dialogNotToast, didAccept;
|
bool dialogNotToast, didAccept;
|
||||||
|
|||||||
Reference in New Issue
Block a user