GSoC 2020 Final Submission

This summer is slowly coming to an end and with it the final month of Google Summer of Code. This blog post will serve as the final submission for my participation. I’ll go one by one over the Merge Requests that got accepted into Epiphany and give a short description of my work. 🙂

  • !651 – This MR splits the source code files for the Preferences Dialog into several smaller ones with separate widgets for each of the individual pages. There was a lot of manual work here as it can be seen from size of the patch, but it was definitely worthwhile as the pages are now a lot easier to maintain and develop.
  • !664 – This is a small fixup to the previous patch. I didn’t update the copyright headers after moving the files around and this patch adjusts that.
  • !678 – I was certainly expecting that after the split landed there would be reports of stuff going wrong. 🙂 This MR fixes runtime warnings caused by some bad casts.
  • !715 – Also as expected there was more than one thing that broke after the split. This patch fixes a crash in the webapps settings. In my defence webapps were not available in my local builds of Epiphany as they are not available with flatpak. This resulted in me spending several days trying to reproduce the crash and about several minutes to actually come up with a fix. 🙂
  • !670 – This is the next big patch that landed this summer. It includes a bunch of UI changes to the Preferences Privacy page. With useful widgets from libhandy we also implemented several mobile and touch friendly details.
  • !731 – This is a fixup patch to the previous one. Surprisingly enough this isn’t a fix to something that was broken, but instead it’s simply a small adjustment to the UI. 🙂
  • !733 – The time was finally arriving when I would move away from Preferences and go towards History. While I was playing around with the existing version of the History dialog, I noticed that errors were printed every time I would delete an item from the history list. I decided to fix this issue before applying my own changes and the small patch here solved the issue.
  • !734 – Another small tweak in Preferences which marks some strings as translatable and adds mnemonics to some buttons.
  • !741 – The rationale behind this patch is quite funny. When looking through the existing History dialog’s source code, I noticed there’s a function implemented which was supposed to be called every time the user selected an item from the history list. However the function wasn’t connected to the row-selected signal of the list. As such the function was never called. I thought that the writer of the function would have wished the function to be called so I wrote a patch which connected the signal. 🙂
  • !754, !768 – I’ve grouped these two together as they are both small fixes and tweaks regarding the previous big patch in Preferences UI
  • !758 – Working on this patch was a very educational experience as it involved async function calls, a concept which I wasn’t very familiar with. I even had to implement an async function here, which proved to be much trickier than expected, but thanks to help received from the mentors it was a good learning experience.
  • !740 – The next significant patch was implementing a selection mode for the History dialog. The selection mode is a fairly common pattern throughout GNOME applications. It’s used to select and manipulate a set of items from a list or grid. Here it’s used to delete or open in new tabs links from the history list.
  • !790 – A tweak to the behaviour of the History selection mode UI.
  • !793 – After the recent work done in the history dialog the source code files were left in a state which I found a bit difficult to read. This refactor patch rewrites the whole dialog in a single file such that all the logic is centralized and easier to follow. Contrary to expectations the new file wasn’t that large as the implementation was substantially simplified.

Work in Progress

Currently I am working on fixing this issue, which has proven to be a lot more stubborn than expected. 🙂

After that I’ll be on stand-by to implement some new design decisions in the History dialog. Currently these decisions haven’t been made and people are discussing here.

Thanks to Michael Catanzaro, Jan-Michael Brummer and Alexander Mikhaylenko for providing help and support throughout this summer !

Lastly, thank you for reading. I know this post was a bit more monotonic, but I wanted to keep it very tightly organized. 🙂

Epiphany History Selection Mode

Since my last blog post I have been working on implementing a selection mode for Epiphany’s History Dialog. The selection mode is a pretty common pattern seen throughout GNOME applications. It’s used to easily manipulate a set of selected items from a list or grid. I’ve used the selection mode from GNOME Boxes as a reference when implementing it in Epiphany.

This is how the History Dialog looked like before:

What’s New

The selection mode is not permanently visible. It is toggled on and off using the tick button at the top right of the dialog.

Activating the selection mode reveals the action bar at the bottom which can be used to delete the selected items from history or open them in new tabs in the main browser window.

Another new change is the addition of the Copy URL button located to the right of each history row. The button is used to copy the item’s URL to clipboard. This change is not directly related to the selection mode, but it was added in order to remove the right-click popover menu which was previously used to open history items in new tabs and copy URLs to clipboard.

Next Up

Recently I have been working on a very stubborn bug, #1281, which occurs when repeatedly opening and closing the Preferences dialog 3 to 4 times.

While working on this issue I have learned a handful of new debugging tricks:

  • using gdb to get a crash backtrace
  • using environment variables to alter an application’s behavior
  • using valgrind to find memory leaks

I’ll expand a bit on environment variables since there are two very nice use cases which are worth mentioning:

  • running G_DEBUG=fatal-criticals epiphany in a terminal causes Epiphany to crash whenever a critical error is printed, which is exceptionally useful for debugging (I honestly wish I found out about this sooner 🙂 )
  • running GTK_THEME=Adwaita epiphany in a terminal will force Epiphany to use the Adwaita theme, which is very useful when testing UI changes (it’s also the theme used in the above gif and screenshot)

Currently I am in the process of setting up JHBuild for building Epiphany because I want to print information from inside the Gtk calls. When all else fails, good ol’ printf() is always ready to assist 🙂

After this issue is fixed (hopefully soon), I’ll spend some time polishing the History dialog source code files, as they are quite disorganized and hard to read after the recent work.

Thanks to this year’s project mentors, Michael Catanzaro and Jan-Michael Brummer for the help!

Also thanks to Alexander Mikhaylenko and Tobias Bernard for giving design feedback!

Lastly, thank you for reading this post, stay safe and enjoy the rest of the summer! 🙂

Epiphany GSoC Milestone

During the past month I have been hacking on Epiphany’s Preferences dialog. The first piece of submitted work was splitting the dialog source code files into smaller ones. The split didn’t reflect any visual changes on Epiphany’s user interface so I decided to postpone writing this blog post. Personally I prefer to have some form of visual content in my blog posts 🙂

That leads me to the second piece of submitted work which does include modifications in Epiphany’s interface. If a picture is worth a thousand words, then a gif is worth a million so I’ll use them to illustrate the changes 🙂

This is how the Passwords dialog was invoked before the latest commits:

The main disadvantage with this method was that it would spawn a dialog from within another dialog which should be avoided, as explained in the original Gitlab issue which I used as a reference.

Passwords is now a view nested inside the Preferences dialog and is presented like this:

This approach also has the benefit of being intuitive on mobile and touch devices. When inside the Passwords view the user can swipe back to return to the main Preferences view. Lastly, instead of clicking on the small gear button, the user can now click/tap anywhere on the whole Passwords row inside the Privacy page in order to invoke the view.

A more subtle change is the red Clear all button which has been moved inside a GtkActionBar at the bottom of the view. The reasoning behind this was also concerning touch devices as in the previous layout it could have been very easy to tap the Back button instead of the Clear all button or vice versa. Another benefit is that the Clear all label is a bit more explicit than the trash icon.

Cookies were merged into Personal Data

Epiphany used to have a separate view for clearing Cookies but now they have been moved into the Clear Personal Data view because of the following reasons:

  • The previous Cookies view was slow as it contained a large GtkListBox
  • Cookies are actually a category of stored data

Next up

These have been the most substantial recent changes worth mentioning in this post. Stay tuned for upcoming news regarding the History dialog !

Lastly, a thanks message to this year’s project mentors, Michael Catanzaro and Jan-Michael Brummer, and also thanks to Alexander Mikhaylenko for helping out with guidance in how to use libhandy ! 🙂

GSoC 2020 with Epiphany

Fast-forwarding almost an entire school year since my last post, I am very happy to be writing this next one now as I’m participating again in Google Summer of Code 🙂

A student is allowed to participate in GSoC only twice in a lifetime. I’m thinking they chose this rule as an “only once in a lifetime” type of rule would have sounded too dramatic.

Humor aside, I have actually learned from a colleague over at university that Google implemented this rule because veteran students would keep returning every year taking most of the slots and thus leaving very little room for newcomers to make an entrance. Considering I’m a returning student myself, I can imagine that at the time I could have very easily been part of the problem 🙂

This year I will be working on Epiphany, also known as GNOME Web (or simply just Web), which is a GNOME-flavored browser.

Firstly, I’ll take a few sentences to congratulate the GNOME community on two fronts:

  1. The icons used in their applications are very nice 🙂 I’m no artist but one can imagine drawing them is no trivial feat so here’s a thanks to everyone who spent time on drawing these lovely pictures.
  2. The internal names used for applications are very interesting. I have heard about Epiphany on Matrix and I had no idea it’s a browser but the name sounded quite intriguing and made me curiously wonder “what could an app named like that be ?” 🙂

A few technical details

My last year’s GSoC project was focused on one large feature inside GNOME Games. In contrast to that, this year’s project consists of several smaller enhancements inside some of Epiphany’s components.

Specifically, I’ll be hacking inside the Preferences dialog, the History dialog and the Bookmarks popover.

I’ll also be working with a different programming language, as Games is written in Vala, whereas Epiphany is written in C. Working with C is definitely a bit more difficult than working with Vala. Thankfully, Builder’s code indexing combined with GNOME’s rich documentation does make it a learning experience rather than an impossible challenge.

Epiphany uses an external library called WebKit to actually render the web pages (this would be considered the heavy lifting core of any browser). The Epiphany project itself is responsible for all the other features of a browser, such as providing an interface for having multiple tabs, managing bookmarks, history, changing various settings and the list goes on.

Lastly, I’ll use this paragraph to send a thanks message to this year’s project mentors Michael Catanzaro and Jan-Michael Brummer for their guidance and help 🙂

Thanks for reading ! Have a great day and stay safe ! 🙂

GSoC 2019 Final submission

Since my last blog post the main merge request of my GSoC project has landed and after that I followed up with subsequent bugfixes and also a couple of enhancements to the savestates manager.

I will use this blog post for the final submission as part of my participation in the program. As such this post will be a bit longer than the others but I’ll still keep it visual and populate it with gifs and screenshots 🙂

Overview of the savestates manager

My main merge request

Merge request (MR) !278 is the largest and most important one that I have submitted for this project. The changes it introduces can be summarized as follows:

  • Automatic migration from the old directory layout
  • Backend changes to use the new directory layout and savestates
  • An initial implementation of the UI to manipulate savestates. This UI was capable of saving, loading and deleting savestates.

The most important change was the refactor of the RetroRunner class which is a class that manages the emulator core used to run games (the core is represented as an instance of a Retro.Core object). An instance of a RetroRunner manages an instance of a Retro.Core for one game and now it also manages the savestates for that game.

Secondary MR 1) Add the savestates renaming feature

!301 introduces a new enhancement to the savestates manager, it allows the user to rename savestates.

The renaming popover in action

Secondary MR 2) Add shortcuts for using savestates

!305 along with !317 introduce quality of life shortcuts for the savestates manager 🙂

The former MR implements the shortcuts themselves, while the latter (not yet merged) MR lists them in the Shortcuts window.

The shortcuts window with the the new savestates shortcuts listed

Secondary MR 3) Flash effect when creating savestates

!310 introduces a pretty flash effect which is played every time a new savestate is created. This effect was inspired by the one used by GNOME Screenshot and we attempted to mimic it’s implementation. 🙂

I was very surprised to find out the flash is actually not implemented by GNOME Screenshot but rather by GNOME Shell. This feature was very interesting to work on as I had to check the source code of GNOME Shell to find out what interpolation function and duration it used for the animation. Then, using that information, I had to write code that animated the opacity property of the background widget in order to achieve the same effect. We concluded that the initial version of the flash was too bright and might distract the user from the game. Because of that the Games flash has a reduced opacity compared to the GNOME Shell one and as such appears a bit dimmer.

A demonstration of the flash animation inspired by GNOME Screenshot 🙂

Secondary MR 4) Use a nicer date format for savestates

As I’m writing this post, !319 still needs a bit of work, but it aims to show the savestates dates similarly to how Nautilus shows the Modified date for files. Note that in the screenshot below the dates are of course fabricated (since there were no savestates back in 2018) in order to simply illustrate the various available formats.

Nicer date formats similar to Nautilus’ Modified column

Along with these MRs, there were also several others with bugfixes and small tweaks:

  • !294 Here an important bug was fixed in which the automatic savestates were not pruned properly and we also changed the way in which new savestate names were generated such that it works similarly to how new file names are generated by the file manager (e.g. If we have savestates “New savestate 1”, “A”, “B” and we create a new savestate it would be called “New savestate 2” rather than “New savestate 4”)
  • !295 Replace the Cancel button with a Back button
  • !296 Remove left and right borders from the savestates menu
  • !297 Fix a UI bug in which the user could apply Load/Delete operations even when there was no savestate selected
  • !298 Fix a UI bug in which the top header bar would cover the savestates menu in fullscreen
  • !299 A quickfix which renamed a method
  • !300 Before this MR the game would unpause before the savestates menu finished it’s animation which would confuse the user
  • !303 Fix a small UI bug in which the new savestate row (the one denoted by the + sign) could be selected, which is to be avoided
  • !304 Fix a small issue in which savestates would get saved with a wrong thumbnail
  • !306 These changes are a fix for bugs discovered in !294
  • !307 The Nintendo DS core caused crashes because it wasn’t properly de-initialized
  • !311 When renaming a savestate we iterate through the others to check if there exists one with the same name. This fix ensures that we don’t take the new savestate row into consideration when doing that
  • !312 Some games don’t support savestates (e.g. Steam games) and we must ignore the savestates shortcuts with these games
  • !313 UI fix for the edge case in which a savestate name spans multiple lines
  • !314 If we click the Rename button and the selected row is not visible on the screen then we scroll to it
  • !315 Allow creating multiple savestates per second. Creating savestates rapidly caused runtime errors because the new directories would have the same name based on time.
  • !316 Avoid runtime errors when spamming the Delete button

Possible future improvements to the project

  • Gamepad navigation – Allow the player to use the savestates manager with a gamepad. The difficulty of this task comes from the fact that the number of available buttons that games don’t use is limited.
  • Undo loading – This is a feature common to many emulators and it helps the users in case they accidentally loaded a savestate and lost the progress of their current session.

Towards a happy ending

Since my last blog post I have kept on working on my GSoC project while also making preparations for attending the GUADEC 2019 conference.

The main Merge Request of my project has been merged into the master branch of Games and then I followed up with a couple more bugfixes for bugs that my mentor has noticed after the merge.

A very mean bug 😦

A very important bug/regression that I’m glad we were able to fix is the NintendoDS crash that was caused by introducing the Savestates Manager. We couldn’t have included this feature in a release as long as this bug was present since it was a major regression as the user wasn’t even able to start a NintendoDS game at all.

The bug was caused by the fact that we used to re-instantiate the emulator core everytime we would start the game or load a new savestate. This didn’t cause any problems with other cores but it seems that the NintendoDS core didn’t like this.

The lucky fix \o/

Initially I had no idea how to approach this issue and I also doubted that re-instantiating is the cause of the problem because it was working perfectly fine with the other cores. Nevertheless I decided to try this out and was very surprised, happy and relieved when I saw that it actually fixed the problem completely and now we are able to play NintendoDS games with savestates. Now when loading a savestate the core is stopped, it’s state is changed and then the core is resumed.

A NintendoDS game being played with savestates 🙂

Last effort

There is still one week left of GSoC and during this time with one final effort I will attempt to implement Savestate renaming before submitting the final version of my project.

My next blog post will be after the GUADEC 2019 Conference at which I will have a lightning talk about my project and hopefully get to meet some of the people reading this post 🙂

Almost there

All good things come to an end and so does the 2019 Google Summer of Code. With the last coding period having officially started my project is slowly approaching it’s last commit.

Lately I have been working mostly on various issues regarding the looks and the behavior of the Savestates Manager, but there are also two new visible UI changes that can be seen in the following screenshot:

New UI changes

The Save button that used to be present in the header bar has been replaced with a special row which creates a new savestate when it’s selected.

The row labels have also been tweaked and now use different font sizes and colors for the savestates names and their dates. Another small change here is that the creation dates use a different format.

The list of current issues is quite large and sometimes if I fix one issue I manage to introduce another issue or even a bug in the process, but I am slowly making progress towards the end goal.

Current list of Issues with the Savestates Manager

Next up I will be working on adjusting how the savestates thumbnails are being drawn. Currently they are not scaled or resized which causes the UI to look quite weird with certain platforms. For example with this PlayStation game the savestate name and creation date can’t even be seen because the thumbnail is too wide:

The savestates names and creation dates are not visible

Getting closer

Since my last blog post I have been on a short vacation but I have also managed to make some progress on my GSoC project again with guidance from my mentor.

My latest work concerns the UI used for the Savestates Manager.

The current Savestates Manager

The available savestates are listed on the right. Note that every savestate has a thumbnail which is a screenshot of the game taken at the moment when the savestate was created. For me it was very satisfying to reach this milestone 🙂

Every savestate also has a creation date which is displayed in the menu, but that’s certainly not as eye-catching as the screenshots.

There are still many missing features and things that need improving (such as the date formatting) but with every commit I feel that I am getting closer to the finished project.

How the finished Savestates Manager is supposed to look like

Next up I will be working on the menu header bar which is going to contain the Load, Delete and Cancel buttons.

Something to show for

Since my last blog post I have kept working on my GSoC project with guidance from my mentor and we finally have some UI to show: a very primitive version of the Savestates Menu.

Primitive Savestates Menu

The current capabilities of this menu are as follows:

  • List the available savestates (they are currently named according to their creation date)
  • Load any of the savestates on click
  • Manually create a savestate of the current game using the “Save” button

Unfortunately along with the progress that was made we also encountered a bug with the NintendoDS core that causes Games to crash if we attempt to load a savestate. We are not yet 100% sure if the bug is caused by my changes or by the NintendoDS core itself.

I hope we are able to fix it by the end of the summer although I am not even sure where to start since savestates are working perfectly fine with other cores. Another confusing matter about this is that the Restart/Resume Dialog works fine with the NintendoDS core and it also uses savestates. This led me to believe that perhaps cores can be used to load savestates only once, but this can’t be the problem since we re-instantiate the core every time we load a savestate.

In the worst case we might just have to make a special case for the NintendoDS core and not use savestates with it, except for the Resume/Restart dialog. This would sadden me deeply since there are plenty of NintendoDS games which could benefit from this feature.

On the flip side of the coin, I have been successfully able to use the new menu in order to get a better high-score at Asteroids by loading to a previous savestate everytime I lost a life 🙂 This was one of the first use-cases I thought about when I decided to work on this project and it makes me very happy to see that our work has made it possible.

Labor of love

While this may not be the way the game was meant to be played initially and some might argue it’s considered “cheating”, it was still a very fun way to spend an evening after a long day of work.

In the end that’s why we play games: to have fun 🙂

Same UX, different backend

Lately I have been spending a lot of time staring at the Resume/Restart dialog of GNOME Games.

The Dialog

Games currently allows the user to resume most retro games from the exact state the game was left in last time it was quit. To do this Games saves several files required to restore the state of the emulator core and resume it’s execution. These files grouped together are called a “savestate”. Currently Games has only one savestate per game which is overwritten everytime the user exits the game.

The purpose of my GSoC project is to allow the user to store and manage more than one savestate. These past days I have been writing code that makes Games create a brand new savestate everytime the user exits the game.

Before my changes the Resume button would simply load the single savestate which existed for that particular game. Now it loads the latest savestate that was created, so from the user’s perspective nothing has changed (with one tiny exception I’ll explain later).

My changes are slowly amounting to 1000 lines of code (insertions + deletions). I admit it does feel a bit uneasy to edit 1000 lines from the app’s code and not see any changes from the user’s point of view. It makes me wonder how often does this also happen with other software that I’m using :S

Unfortunately, there is one minor downgrade that my changes have introduced. As can be seen from the first image in the post, there is a screenshot of the game behind the Dialog. My changes have altered the sequence of operations required to boot the emulator core, which in turn broke the loading of screenshots. Now, when starting the game there is always a black screen behind the Resume/Restart Dialog 😦

Gloomy Dialog

In the next days I will finally start working on a primitive UI that is going to display all of the savestates that are available when launching a game. The UI would also allow the user to boot the game from a particular savestate on click.