It didn't work anymore, at all. Touchscreen polling occurred only
*after* waiting for a button had completed. So the touchscreen events,
if any, would be ignored until the user had pressed a button, possibly
firing off another action with that button press and forwarding the
touchscreen event to the next interface that got brought up as a
result.
Reusing this code and fixing it would require far more work than
rewriting everything anew with touchscreen devices in mind from the
beginning.
MtH: Resolved conflicts, mainly from the GMenu2X pointer to reference
change I did on 2015-04-21.
Previously, the built-in actions would only be added if their
respective sections already existed.
This also works around the fact that Menu::paint() crashes if there
are no sections present.
When compiling with musl, I got a warning that <fcntl.h> should be used
instead of <sys/fcntl.h>, but it seems neither is necessary.
The comment suggested the battery code needed the header, but the code
that was moved to battery.cpp only uses functions from <stdio.h>.
Instead of correcting the returned coordinate with "- 10" externally,
omit the white space inside the methods.
Note that Font::getTextWidth, which was used until recently, considers
an empty string to have width 1, so 3 + getTextWidth("") + 6 == 10.
There is a difference in how buttons that have neither a label nor an
icon are positioned in the new code, but that is a situation that
should not occur in practice. Plus I'd argue that the new behavior is
actually better in that case.
This was only called form ButtonBox, so I moved the code there.
I still think a paint method shouldn't be repositioning widgets, but
that's something for a later cleanup.
Since this surface is created by initBG instead of loaded from skin
search paths, it didn't really fit in SurfaceCollection. After removing
it, one of SurfaceCollection's methods could be removed as well.
This avoids having to do separate getTextWidth calls in several places.
More getTextWidth calls could be saved by splitting the rendering of
the font to an off-screen buffer from the final composition onto the
destination surface: the routines that draw text inside a box have to
compute the width before they can draw the box and currently the box
has to be drawn before the text.
Instead, make the caller perform the lookup. This simplifies the
interface of loadImage and it removes the dependency from
OffscreenSurface on SurfaceCollection.
The instance-on-demand didn't really work, since we needed explicit
control over this object's destruction to ensure the timer is stopped
when launching an application. And trying to combine getInstance() with
explicit external delete was just ugly.
Browsing the user's translations directory will simply add no new files
to the list of translations available if the directory doesn't exist.
GMenu2X::showSettings() doesn't need to care about that.
Because translations are files, not directories, also don't return
directories in the result. The code that makes the translations list
calls FileLister::getFiles and ignores directories anyway.
A file existence check is already performed, atomically with respect to
the filesystem, by ifstream's constructor. The result of this check is
available using ifstream::is_open().
The constructor now has zero arguments. showDirectories and showFiles
are now set using setter methods.
FileLister::browse is now the sole way to start a scan for files and
directories, replacing the initial path in the constructor and the
setPath method. It allows merging results from multiple directories
as before.
This is all to make explicit how many times the costly task of browsing
a directory is actually carried out.
Instead of checking which input configuration file exists among 2
choices, then asking InputManager to load that file, InputManager
itself now performs the resolution based on whether ifstream::is_open
returns true for each choice.
The existence of modifications to the skin configuration in the home
directory is now checked with ifstream::is_open, and the system's skin
configuration is used if that returns false.
A file existence check is already performed, atomically with respect to
the filesystem, by ifstream's constructor. The result of this check is
available using ifstream::is_open().
There are a few exclusive operations for each type. Also we no longer
need the freeWhenDone flag since the class now determines whether the
surface should be freed or not.
Applications with this flag will not have their stdout/stderr
redirected to a log file when logging is enabled. That is a useful
feature also on platforms where we don't micromanage the console.
Currently the launched application is exec-ed from deep within the menu
code. This means a lot of destructors are never run and as a result
for example file descriptors from the menu remain open in the launched
process.
This is a first step to move the launch invocation from a deep call
stack to the top level.
Instead of reading the file line by line and then concatenating those
lines, just load the entire thing in one go. And pay more attention to
error conditions.
The constructors of those classes now accept a string to be wrapped, instead
of a vector to be modified with split lines inserted into its middle.
Along with this conversion, manuals for applications stored in OPK packages
are now transferred into a string without garbage at the end.
In commit 950518f3 I changed the component type of RGBAColor from
16-bit to 8-bit integers. Unfortunately, in C++ 8-bit integers are
identical to characters, so this broke the writing of colors to
output streams.
This allows for faster scrolling between section links, in file and directory
selectors, and in manuals, without repeatedly pressing buttons.
The setting's unit is repetitions per second. Its default value is set to
10, and anything between 0 (disabled) and 20 (50 ms) is acceptable.
Grabbing &(instance of GMenu2X).confInt["buttonRepeatRate"] is unsafe, because
the storage for the slot may move as the slot is deleted or added. Instead, a
callback jumps back into the context of an InputManager so the value can be
read from a GMenu2X object's configuration.
A GMenu2X object is also passed to InputManager::init.
Previously, one would check the value in &confInt["someKey"] by passing a
reference to it to evalIntConf. However, because this passing of the reference
went through std::unordered_map::operator[], it created a slot with the named
key and initialised its value with the default constructor of int, which
placed 0 there, if it didn't exist. If the value of 0 was acceptable for the
setting, then 0 as the value selected by the user was indistinguishable from
a slot that had been just created and had to be set to its default.
Now, the std::unordered_map is passed along with the key so that evalIntConf
can check whether the key exists and, if it doesn't exist, set the value to
its default.
Include utilities.h in gmenu2x.h instead of the reverse. One type definition
used by utilities.cpp is moved there (ConfIntHash) and for consistency
ConfStrHash is moved there as well.
This does away with per-link selector directories in link files. It is assumed
that, if a user has access to write files to be launched by an application at
some location, he or she also has access to write files in the previews/
subdirectory under it.