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 affects manuals, About GMenu2X, and the Log Viewer.
Instead of trying to compute the width of the entire string, then backing
off one word at a time, TextDialog::preProcess now performs a binary search
on Font::getTextWidth(string) and backs off to the last fitting space, if
there is one, at the last moment.
In Japanese and Chinese text, words are not usually separated by spaces.
Text in these languages is now wrapped when it would reach the edge of the
screen.
I implemented it as four 1-pixel-wide filled rectangles. While this
is not the fastest way to do it, I doubt this will have a significant
impact on overall performance.
Note that the proper way to clip a rectangle outline is to clip the
outline's four lines individually, not clip the rectangle and then
draw a smaller rectangle outline. This means that an optimized drawing
routine would have to be aware of whether clipping occurs, complicating
the code.
I want to remove the dependency on SDL_gfx, since only two functions
from that library are actually used. Also this new blend implementation
is more optimized, especially the 32bpp case, which is the one most
platforms are using.
This is the opposite of the old situation, when the structs were
unraveled.
The definitions for the alternative styles were moved to the header,
so the compiler has more opportunities for optimizing the conversions.
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.
When trying to test the previous commit, I couldn't find any place in
the application where strings containing newlines are drawn. So I'm
assuming this is an unnecessary feature, until someone comes up with
a test case proving otherwise.
Yeah, I'm too lazy to review all the code that draws text...
Instead of splitting everything at once, split off one line at a time.
The code could be more compact but I want to avoid using substr on the
very common special case when a string contains no newlines.
Asking FreeType for metrics before asking it for a render, when rendering
would compute the metrics anyway, is wasteful. Now the width of text, for
horizontal alignment purposes, is simply the width of the render.
In well-described fonts, this enables multi-line text (e.g. in manuals) to be
more readable.
The term "height" is also replaced with "line spacing" in Font's code.
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.
The alpha change is so that:
* some of the background is still visible, which includes the name of the
application for which the selector is being called, its description, and
text in the status bar;
* the preview, if bright, does not obscure the file names too much.
Selector previews are now shown full-screen (320x240) instead of being a
160x160px square on the right.
These issues are fixed:
* loadPNG gave RGBA surfaces unconditionally. Now it gives RGB surfaces if
its second parameter, defaulting to true, is false. This fixes adding per-
surface alpha values, because an RGBA surface ignores its per-surface value.
* Surface::loadImage is updated to receive a third parameter, defaulting to
true, to determine whether alpha is loaded.
* SurfaceCollection::defaultAlpha was never used.
* SurfaceCollection::defaultAlpha defaulted to false, so even if it were used,
it would have loaded images without alpha.
This commit ensures that a fully constructed Font object will not crash
gmenu2x when it is used, even if loading the font or initialising SDL_ttf
altogether has failed. Instead, it will render no text, but icons and
images are still drawn.
The proper way to signal an error would be to throw an exception and fail
to construct the Font object. However, gmenu2x does not use exceptions.
Since 2002-09-03, SDL_ttf performs reference counting on TTF_Init and
TTF_Quit. If two fonts were loaded concurrently via the Font class and
one was destructed, the destructor of the first object would call TTF_Quit,
making the second object unusable. The constructor now calls TTF_Init
unconditionally to prevent this situation.
The reference counting behavior was introduced in this SDL_ttf commit:
http://hg.libsdl.org/SDL_ttf/rev/fc0371908009
This breaks one thing: the "params" option of the links must be
only one parameter (without spaces). The only way to actually
set this option being to edit the config files manually, it is
pretty safe to assume it will never contain two parameters.
The comment of this code indicates that it is needed for
SDL apps to work correctly.
However, I don't see any valid reason for the apps we
launch to be running in a different group.
Removing it didn't make any apparent difference, so unless
I'm proven wrong, it'll stay gone from now on.
Loading dynamically at startup is a very bad idea, as it
confuses the "load state before exiting" feature of GMenu2X:
the file selector will pass the file to a different program,
the cursor will move to select a different app, etc.
This reverts commit 5c631d610e.
This fixes a segmentation fault occuring on the wallpaper dialog
when trying to select a wallpaper located in the Default skin in
the user directory, when the current skin is not "Default".
LinkApp::drawRun() assumes the layers below are already painted when
it is called, but this was not the case. With single buffering, the
previous frame was still there so it still looked good, but with
double buffering the buffer typically contains an outdated screen.
Long term I think the launch should happen at the outermost scope,
so all destructors get a chance to run. This commit is a small step
in that direction, by exiting the main loop before launching.
The scroll bar always spans the content area of the screen: the
position and height depend only on the theme and not on who is
drawing it.
Note that the coordinates passed were wrong in most cases, so this
commit fixes the scroll bar positioning for several dialogs.
If the application in question daemonizes, it will continue running
no matter whether we start it with system() or execlp(). So I don't
see a reason for this feature to exist and removing it means less
code paths to worry about.
The labels were longer than the space before the RGBA controls and
the fact that these are colors is already clear from the context
(such as having an RGBA control after it ;).
I tried to update the translated versions of these labels as well.
However, since I don't speak most of these languages, it is possible
the result is grammatically incorrect. If this is the case, please
mail me a correction.
It was only used to share implementation between IconButton and Link.
However, there was only one non-trivial method, handleTS(), and that
method used a different code path for each use case: doubleClick was
always false for IconButton and always true for Link. So the total
amount of code was actually reduced by eliminating this code sharing.
The main motivation for this split is that I can now freely refactor
Link without having to worry about IconButton.
Each part of the code deals with either Links or IconButtons, but
not both: the base class is only used to share implementation and
not interface. Make this explicit by doing private inheritance.
Nowhere in the code do we actually mix IconButtons and Links (the other
Button subclass), so I'm thinking of breaking up this class hierarchy
or at least making the inheritance private.
Also switched to C++11 style loops.
Previously, the links would scroll when the cursor was about to move
out of screen. By scrolling earlier, the user gets a view of the next
row before it becomes the current row. This allows a longer reaction
time to switch from vertical to horizontal navigation when looking for
a particular link in the grid.
This reduces the number of required preprocessor directives, leading to
more readable code and more code being examined by the compiler (useful
to spot problems). Since the method is inlined, the compiler should be
able to eliminate the same amount of code that the preprocessor would,
only at a later stage of the compilation.
This fixes a bug with the captured background being wrong when using
double buffering. Also it ensures that for example the clock in the
status bar is updated when the context menu is open.
All of the entries in the context menu affect sections and links, so
the context menu should be considered part of the main menu, not of
the global / background context.
Writing hours and minutes separately while the string representation
is being constructed could lead to an incorrect result on an hour
boundary. Avoid this by using an atomic timestamp.
With GCC 4.8.1 on MIPS this atomic timestamp is lock free.
SDL does not guard against the final callback still executing when the
call to remove the timer returns. So we have to make sure the object
we access on the callback is not prematurely destructed. This commit
uses shared_ptr and weak_ptr to ensure that.
Note that we sort-of have a singleton again, only now it is private
and safely destructed.
Removed the suspend check: the best thing we can do after oversleeping
is the same as when we're woken right on time: fetch the time and
reschedule for the next minute boundary.
Don't create a new timer on every callback; instead return the next
interval to SDL.
Don't make Clock a singleton. While there should be no reason to
instantiate this class more than once, there is no problem with doing
that either. Removing the singleton makes it easier to control access
to the instance. It also avoids the rather nasty construct that was
used to delete it.
Make sure the timer callback function is a proper C function, since
SDL is a C library. This requires some trickery to be able to call
a private method from the callback, but I found a way using an
intermediate nested class. The compiler should be able to inline this
to eliminate any overhead.
Also some minor cleanups.
This method was never called.
And I cannot really think of a scenario in which it is useful to wait
for any button to be released: a particular button or all buttons I can
imagine, but not any button.
Instead of having a list and wrapping between beginning and end, always
put the current section in the middle and show the previous and next
sections using wrap-around.
Made sure it fills the space between the top and bottom bar. Use a one
pixel margin; I tried without margins but it didn't look nice.
Also cleaned up the paint code a bit.
Replaced Font constructor with factory method, so that if the TTF
cannot be loaded, the Font object is not constructed. The normal C++
way of handling this is with exceptions, but we're compiling with
-fno-exceptions.
Originally the font implementation was based on SFont, but it was
recently replaced by an SDL_ttf based implementation, so the name
no longer made sense.
The code still has a lot of overlap with the other methods of Link and
LinkApp, but at least it is in the same place now.
Since this was the last outside use, setIconPath() could be declared
as 'protected'.
This could be used to create platform-independent packages. It can
be useful for instance in the case where the executable is a script,
or when the package points to an executable that is present on all
systems on which OPKs are supposed to run.
The empty "" filter was previously matching all the files; since
a few commits it now matches the files without extensions. The
new "*" filter allows again to match all files.
tolower() will trigger an assertion failure in the case where the
string contains UTF-8 codes. This is not a problem as only the
file extension needs to be processed, and that one should contain
only ASCII.
These are not actual OPK files, but metadata (I assume) storage that
Mac OS X adds to vfat file systems. The current version of libopk has
extremely poor error handling, so ignoring these files avoids a crash.
But even when libopk is fixed, not trying to open these files as OPKs
will be useful since it saves time.