1. Porting Notes
1.1. General Guide
https://developer.gnome.org/Gnome3PortingGuide/
https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html
References need to be changed to GTK#3, can be done with the MonoDevelop GTK# integration settings option menu.
MonoDevelop now has a GTK# 3 starter template available, use the add-in manager to download it.
See http://nullreference.me for the biggest and best list of blog posts from the hackfest.
GTK#3 2.99.1 beta release: http://lists.ximian.com/pipermail/gtk-sharp-list/2013-September/011323.html
GTK#3 packages for Ubuntu: https://launchpad.net/~meebey/+archive/mono-preview
1.2. Existing Ported Applications
Sparkleshare (branch: https://github.com/hbons/SparkleShare/tree/GNOME3)
Smuxi (branch: https://github.com/meebey/smuxi/tree/gtk3)
Tomboy (branch: https://github.com/tomboy-notes/tomboy/tree/2.0)
- Banshee (in git master)
Mono.Addins.Gui (name Mono.Addins.GuiGtk3) - See https://github.com/mono/mono-addins/pull/8 - use this for projects with Mono.Addins. If you want to run it, you need to pull down the Mono.Addins.GuiGtk3 branch mentioned previously and make install it to have the GTK3 Gui available, until it is packaged
Blam (branch: https://git.gnome.org/browse/blam/log/?h=gtk3)
- gbrainy (in git master)
1.3. Partially Ported Applications
- Pinta
- F-Spot
1.4. Known Type/Method Changes
- All interfaces are now prefixed with an I
Gtk.TreeModel -> Gtk.ITreeModel
Gtk.Dialog.HasSeparator property has been removed, dialogs always have a separator
Gtk.Dialog.VBox -> Gtk.Dialog.ContentArea
Gtk.Table -> Gtk.Grid
Gtk.StatusIcon.Tooltip -> Gtk.StatusIcon.TooltipText (Or any other widget with a tooltip)
Gtk.Box.PackStart(widget) -> Gtk.Box.PackStart(widget, false, false, 0)
new Gtk.ComboBoxEntry() -> Gtk.ComboBox.NewWithEntry()
Gtk.Spinner -> Remove your own spinner implementations!
Gtk.Label -> Use <a href=""></a> in .Markup to create links and remove your link implementation.
Widget.State = Gtk.StateType.Normal -> Widget.SetStateFlags (Gtk.StateFlags.Normal, true);
Gtk.TagAppliedArgs : args.StartChar -> args.Start
Gtk.Widget.HideAll() -> Gtk.Widget.Hide()
Resize grips have moved from Statusbar to Window : status_bar.HasResizeGrip = true; -> HasResizeGrip = true;
Replace GLib.Signal.Lookup (this, "name").AddDelegate (handler) by AddSignalHandler ("name", handler). Similar for RemoveDelegate.
1.5. Major API Breakages
All drawing is now with Cairo, most everything Gdk has been removed.
RulerWidget has been removed.
For custom widgets: as mentioned in the general porting guide, OnExposeEvent (Gdk.Window) (absolute coordinate) has been replaced by Draw (Cairo.Context cr) (relative coordinate)
GetSize () has been replaced with public override void OnGetPreferredWidth (out int width) and equivalent for height
1.6. Behavior Changes
For the mouse scroll wheel to work with a custom widget, you now need to set the ScrollMask EventMask:
WindowAttr attributes = new WindowAttr ();
attributes.EventMask = (int)(EventMask.ScrollMask);
1.7. Settings Changes
Migrate from GConf to GSettings, in package gio-sharp
See https://developer.gnome.org/gio/2.38/ch31.html for general overview.
If your app has a GConf schema (was optional, is mandatory in GSettings), you can convert it with https://developer.gnome.org/gio/2.38/ch31s06.html
To manually install a schema:
sudo cp data/org.gnome.tomboy.gschema.xml /usr/share/glib-2.0/schemas/ && sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
See Tomboy (gtk3-dev branch) or Banshee for makefile integration and translation of schemas.
1.8. Migrating from Stetic to GtkBuilder
Stetic, the GUI development tool of MonoDevelop, doesn't support GTK+ 3.x for now. The easiest solution is to use GtkBuilder instead.
Both Smuxi and Mono.Addins did this. Pinta should have done this! The GTK#3 Start project add-in for MonoDevelop uses this approach.
Take the old gui.stetic file and use an xslt transformer with this: https://github.com/xDarkice/stetic2ui
The new .ui files need to be opened and saved once in glade to get rid of properties that no longer exist. They will also probably need some manual tweaking for fill/expand properties. Some people have experienced them not working in glade, but working anyway with GtkBuilder! In the project they should be added as embedded resources.
Rename the gtk-ui folder to stop MonoDevelop from trying to use Stetic on everything there. Remove the partial modifier from your classes since they are no no longer combined with auto-generated classes. Add this statement: using UI = Gtk.Builder.ObjectAttribute; then define all the objects that you reference in your no-longer partial class, i.e. [UI] Entry pathEntry; etc. Manually wire all of your button listeners etc.
Example of a new independent window opening a dialog wired with GtkBuilder, where the dialog has some custom widgets (custom widgets are represented in ui files with boxes without children):
public static Gtk.Window Show (Gtk.Window parent) { Gtk.Builder builder = new Gtk.Builder (null, "Mono.Addins.GuiGtk3.interfaces.AddinManagerDialog.ui", null); AddinManagerDialog dlg = new AddinManagerDialog (builder, builder.GetObject ("AddinManagerDialog").Handle); InitDialog (dlg); parent.Add (dlg); dlg.Show (); return dlg; } public AddinManagerDialog (Builder builder, IntPtr handle): base (handle) { builder.Autoconnect (this); addininfoGallery = new AddinInfoView (); addininfoGallery.InstallClicked += OnInstallClicked; addininfoGallery.UninstallClicked += OnUninstallClicked; addininfoGallery.UpdateClicked += OnUpdateClicked; addininfoGallery.EnableDisableClicked += OnEnableDisableClicked; eventbox1.Child = addininfoGallery; ... //Wiring more buttons buttonUpdateAll.Clicked += OnUpdateAll; buttonRefreshUpdates.Clicked += OnButtonRefreshClicked; buttonRefresh.Clicked += OnButtonRefreshClicked; buttonInstallFromFile.Clicked += OnButtonInstallFromFileClicked; repoCombo.Changed += OnRepoComboChanged; ... ShowAll (); }
It is important to call ShowAll() at the end of the constructor
Example of an independent custom widget that doesn't get constructed by a parent window:
public AddinInfoView () { Builder builder = new Gtk.Builder (null, "Mono.Addins.GuiGtk3.interfaces.AddinInfoView.ui", null); builder.Autoconnect (this); Add ((Box) builder.GetObject ("AddinInfoView")); AllowInstall = true; titleWidth = labelName.SizeRequest ().Width; ... //Enable our buttons for clicking btnDisable.Clicked += OnBtnDisableClicked; btnInstall.Clicked += OnBtnInstallClicked; btnUninstall.Clicked += OnBtnUninstallClicked; btnUpdate.Clicked += OnBtnUpdateClicked; urlButton.Clicked += OnUrlButtonClicked; ShowAll (); }