-
-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Making the fonts optional #55
Comments
Thanks for the ticket :) Just to clarify: Currently, if the font file is missing, no font is rendered at-all? It doesn't currently fallback to system fonts? If fallback is broken, that's terrible. I would expect that kivy would already handle this.. I know you build BusKill different from me. Could you please post the steps to reproduce this? I certainly plan to add the ability for a user to customize the font face and size after #16 unblocks #37. But I'm on the fence if I want the BusKill app to actually default to the system-defined font. I guess I would be open to this if I could programmatically determine if the system font is set to either [a] the OS default or [b] if the user explicitly customized the system font. If the system font was explicitly set by the user, then I agree it should default to the system font (eg for accessibility reasons). |
Currently if the font is not in the expected directory (
even if the font is available system-wide. |
If you want to replicate the setup I have:
Then, you can delete the |
I can reproduce the issue where the app doesn't load when the fonts file cannot be found. However:
On a fresh install of
The Roboto font is actually installed 3 times by the following packages:
So @fmarier you can probably remove the
|
As for fallbacks to system fonts, I don't think that's possible in python/kivy. The best I could do is find some random font in the fonts dir returned by kivy's The default font in kivy appears to be, in fact, Roboto
The one thing that I'm doing that diverges is that I've used |
TODO: make this more robust by
|
Both of these
So there's only one copy of it on the system. |
The one exception is |
I spent some time looking for how a user could specify their own custom font (eg for accessibility needs), but it's non-trivial. There is no built-in "font picker" in kivy. I didn't find any examples from others online. The best I've got is a list of directories with font files, and then I can recursively poke through those for I created a ComplexOption in the Settings screen for "font" and wrote some code to dynamically find all Most of these fonts are probably useless anyway. For example, I randomly picked-one and it was a font for the Tamil language. We need a way to par-down the list to be shorter. TODO
For #2, I found some code on SE that uses the python module fonttools, but I actually liked this one better -- as it just uses the built-in module |
Good news: I did succed in being able to populate the ComplexOption with a list of OptionItems for every font found on the system. Bad news: It crashed my system. Most of these fonts are probably useless anyway. For example, I randomly picked-one and it was a font for the Tamil language. We need a way to par-down the list to be shorter. TODO: 1. remove symlinks (duplicates) from the list of fonts 2. remove fonts that don't have glyphs for latin characters For #2, I found some code on SE that uses the python module fonttools, but I actually liked this one better -- as it just uses the built-in module unicodedata * https://superuser.com/questions/876572/how-do-i-find-out-which-font-contains-a-certain-special-character For more info, see: * #55 (comment)
I found that, on my dev system, I have:
I eliminated symlinks, but I still found the same number of fonts. Also, running this is actually very fast. The issue with kivy crashing the computer is just a kivy GUI issue with so many widgets being rendered on a screen. Perhaps it could be solved by a RecycleView. Or by going back to the normal non-complex OptionItem (if I can figure out how to populate it at runtime).
|
I opened an upstream feature request with the Kivy team to create a standard "FontPicker" SettingItem This is already standard in other GUI frameworks, such as GTK and .NET |
Last night I spent several hours trying to adapt our custom ComplexOptions class OptionsItem to be compatible with RecycleView (the positional arguments are an issue; I tried switching to kwargs, but it didn't work) I also just now tried to load the 6,182 fonts into a normal option widget The normal built-in "option" widget handled the >6,000 entries better than my custom ComplexOption widget, but it still doesn't work:
TODO: try file picker (defaulting inside the font dir with the most number of TTF files found) |
Is there a way to simply not set the font (in case of an exception while looking for it)? What I had in mind when initially filing this issue was that buskill should load even its font is missing. Yes, ideally, it should load whatever is defined as the default font for serif or sans serif on the system, but if that's too hard, then it should just pick an arbitrary font (ideally not picking anything and just letting the OS free to use whatever it wants). That would be better than not loading at all. But maybe Kivy has a requirement to specify a font and there's no default or fallback? |
If I don't set a font, then it will default to Roboto, which ships with kivy. If Roboto cannot be found, then it will throw an error.
A far as I can tell, there is no way to ask the OS to pick the font for us (at least not cross-platform let alone cross-DE). We could pick one arbitrarily, but then we risk picking a font that doesn't have glyphs for the characters we want. |
That sounds like a reasonable solution then. If Roboto cannot be found in the buskill directory, then try again without setting the font. In that case, it will use Kivy's default (i.e. Roboto in the Kivy directory). If that fails, then that's not buskill's problem and it's instead a bug in the Kivy installation. |
It sounds like the fact that there's no way to honor the OS defaults for fonts is a problem (or maybe feature request) with Kivy. If that ever gets fixed, then buskill will benefit from it automatically. |
Yes. And I'd say the problem goes higher than kivy. It seems that python in-general should have some cross-platform way to fetch the OS default font. |
This is not working. The biggest issue that I'm having with getting RecycleView working is that I used positional arguments for the creation of BusKillOptionItem() My understanding is that RecycleView maintains a list of some type of widget. In my case, I want RecycleView to be a set of my custom widget = BusKillOptionItem()s. But the way that RecycleView creates & recycles these objects is by a dictionary, which gets passed into the objects when they're created as kwargs. So in this commit I tried changing from positional args to kwargs, but it doesn't appear to be working yet. For more info, see: * #55 (comment) * https://groups.google.com/g/kivy-users/c/TLZoBXX5zZs * https://kivy.org/doc/stable/api-kivy.uix.recycleview.html
I didn't have very good luck with the FilePicker. Namely the I could have made a custom widget for this, but it also looked really bad and I figured it was likely just as much work to keep trying the RecycleView. Indeed, I had much better luck today getting the fonts to appear in a recycle view. My latest commit displays >500 fonts (not sure why it's less than the 6,000 items before), and (with RecycleView) it loads near-instantaneous and has no lag when clicking around the screen. This is just a proof of concept. I got the list of fonts to display, but I horribly broke the actual ability to click them and change the settings in the process. The biggest issue now is that my (this was all very difficult to wrap my head around, and this example was instrumental in helping me get this far https://groups.google.com/g/kivy-users/c/4_xaX7xtL_s) While I've managed to get ^ that working for the basic arguments (like icon, option value, description, etc), I'm not able to access them from within the object's functions itself -- namely
To address this, I've made a simplified example of this issue and posted it on SE: |
I was successfully able to get the I had to switch from using buskill-app/src/buskill_gui.py Lines 542 to 550 in 2d2264a
Unfortunately, I found some strange bug where if a user scrolls "up" at the top or "left" or "right" then it registers it like a click, so a user just scrolling through the list of fonts will change to the font under their cursor when they scroll at the "end". I've been fighting with this all day with no solution so-far. I created another SE question about this here: |
I built the app with Debian 12, and the issue still occurs. Unfortunately I just discovered that this issue occurs even on the Yeah, I just downloaded |
For some reason when someone was simply scrolling through all the options in a ComplexSetting screen and they reached the end, kivy would pass that scroll event as a click event to the OptionItem -- making us change the Config as if they had clicked on it. I don't know exactly why kivy does this, but it probably has to do with muti-touch gestures. Kivy thinks its better to bind and call all visible widgets (not just the ones touched) because gestures can sometimes end not where they started. This is different, but maybe related: * https://kivy.org/doc/stable/guide/inputs.html#touch-event-basics > By default, touch events are dispatched to all currently displayed widgets. This means widgets receive the touch event whether it occurs within their physical area or not. > > This can be counter intuitive if you have experience with other GUI toolkits. These typically divide the screen into geometric areas and only dispatch touch or mouse events to the widget if the coordinate lies within the widgets area. > > This requirement becomes very restrictive when working with touch input. Swipes, pinches and long presses may well originate from outside of the widget that wants to know about them and react to them. The solution to this was to check the touch.button instance field, which was either "left" or one of "scrollup", "scrolldown", "scrollright", and "scrollleft" * https://kivy.org/doc/stable/api-kivy.uix.behaviors.compoundselection.html#kivy.uix.behaviors.compoundselection.CompoundSelectionBehavior.goto_node For more info, see: * https://stackoverflow.com/questions/78183125/scrolling-causes-click-on-touch-up-event-on-widgets-in-kivy-recycleview/78183647#78183647 * #55 (comment)
I fixed the scroll-click bug by checking the value of the |
In my latest commit, I have eliminated all references in the markup to Roboto fonts. Now fonts will just be rendered using the The user can now select a font in the GUI Settings menu, which updates There's two exceptions to this where I specify a custom font:
I reference a custom font named "bkmono" in the text markup, which allows me to choose which mono font to use on-launch. By default, it will use RobotoMono. The startup is also much more robust. If for some reason there's an issue finding the Roboto default fonts, BusKill will search all the Kivy-given font dirs recursively for the Roboto fonts and use whatever it finds as the default. Of course, the app will still crash if it can't find any Roboto or Material Design Icons font on the system still, but what we have now is far more robust. And we have never had a report from a user indicating an issue with fonts. Currently it requires 2 restarts of the app to actually apply the changes of the user's font to the app actually using it. I opened this SE question to address how to change all the widget's label's font face during runtime: |
I've successfully gotten the app to update the font face of all widgets when the user exits the Settings menu, but now I'm struggling with the "reset" button again now that I've switched from using the buskill section's Now that I'm deleting the kivy section's options when the reset button is pressed, I get a This could be easily fixed by updating my The code for that is here: https://github.com/kivy/kivy/blob/c492a33f8cf79e89ea7240690feb5f6d25b08389/kivy/config.py#L902-L908 ...but I don't understand how to reference it because it's at the root of the file and not in any publicly-exposed method. I asked this question on SE about this: |
This commit hardcodes the default_font to Roboto. Actually all I'm doing here is copying these lines from kivy/config.py into our BusKillApp.build_config() function, but I don't like it because if Kivy changes from Roboto to something else in the future, this will break. * https://github.com/kivy/kivy/blob/c492a33f8cf79e89ea7240690feb5f6d25b08389/kivy/config.py#L902-L908 The best thing to do would be to somehow *call* the code in the above kivy/config.py script, but I'm not sure how to do it because its not in any method; it's just at the root of the script. I created this question on SE about it here: * https://stackoverflow.com/questions/78216476/how-to-get-kivy-to-set-its-defaults-in-the-config-at-runtime See also: * #55 (comment)
The latest commit to the font_setting branch now includes otf files (in addition to ttf files) for fonts, so users can now select a custom font in the GUI, including the Open Dyslexic fonts as mentioned in the OP See the following screenshot of the BusKill App using the Open Dyslexic font |
This has been merged into the |
TODO: test on macOS & Windows (blocked by #78) |
I finally was able to hack together a MacOS build, and I found a bug. The app crashes immediately with failure to find
|
Somehow it looks like the Material Design font is no longer being included in our MacOS builds From the logs we can see that our app's font dir is part of the list of font dirs returned by Kivy
But the dir doesn't have the MD font
It looks like we already have the fonts here
It looks like the stable version of buskill-app/src/buskill_gui.py Lines 1118 to 1122 in a585f03
|
…ign icons packaged with our app on MacOS * #55 (comment)
After adding the Unfortunately, the hamburger menu icon is missing. And, f I slide the navbar from the left with the mouse gesture and click
The files are, in fact, present. And they're the same both for new builds and the last stable release (v0.7.0).
It appears that this change somehow broke paths |
ok, so the issue is that my old MacOS release had a bunch of symlinks from Contents/MacOS/* -> Contents/Resources/* but the new one does not
|
This commit updates the SRC_DIR from the macos .app/Contents/MacoOS/ dir to .app/Contents/Resources/ dir Apparently PyInstaller used to put symlinks inside the .app/Contents/MacOS dir for things like 'packages' and 'fonts' to go back to the ../Resources/ dir, but that no longer happens * pyinstaller/pyinstaller#7713 * #55 (comment) now we'll point at the actual file, not the no-longer-existing symlink
This commit replaces the Config item name "buskill" with "buskill_trigger" Apparently I silently renamed this option in the Config file some months ago when I was switching the Settings screen to use RecycleView, for the font accessibility feature * #55 (comment) I don't know exactly why I made the change, but apparently I already updated it in other places, except here. The result: a bug where the first time you "arm" BusKill, it always defaulted to the 'lock-screen' trigger, instead of the setting the user already set it to. * #77 (comment)
Right now, it looks like the fonts are required for the UI to load. It would be great if the app would fallback to using whatever the defaults fonts are on the system when the
Roboto*
files are missing.Some dyslexic users for example choose to set their system fonts to https://opendyslexic.org/ and therefore it would be better on some systems to avoid overriding the user-selected fonts. (I would probably do this on Debian.)
The text was updated successfully, but these errors were encountered: