I ran across this while working on some complex GtkSharp grabbing behavior to mimic window focusing for a docking framework. Turns out there is a weird inconsistency in the way Gtk+ manages the grab stack. While the list of grabbed Widgets is indeed a stack, a flag on each Widget (
Widget.HasGrab) is used to check if a Widget has the grab or not. The problem is that
Grab.Add (which calls the Gtk+ method
gtk_grab_add) never clears the flag for the currently grabbed Widget if you're nesting grabs. That means that every Widget in the grab stack will have
Widget.HasGrab set to true. If you try to add a Widget to the grab stack and it's already in the stack (even if there are multiple other grabbed Widgets after it in the stack), it won't get added. Because the flag is set though, it will get removed at the first place it was in the stack on a call to
To show a context menu in GtkSharp (or "popup" as they're called in Gtk land), you would normally add an event handler for Widget.PopupMenu, create or use a Menu instance, and then call Menu.Popup. The only problem is that for many widgets, the right-click doesn't trigger the Widget.PopupMenu event. This is fine for systems where there is no right mouse button or where a right-click isn't the customary way of initiating context menus. However, on systems where there is a user expectation that the way to open a context menu is through a right-click (such as Windows), we need some way to trigger one.
I recently had to create some functionality to export a TreeView widget to a CSV file for further analysis. Since I tend to think about generic behavior, I decided to code up a method that would take any arbitrary TreeView and perform the export operation. Luckily, the TreeView widget and the attached TreeModel both contain a lot of functionality for accessing the data and it's presentation. I decided that I wanted the exported CSV file to represent the perspective of the model as currently represented in the TreeView including column visibility and sort order. This led to the trickiest part of the process. Because a CellRenderer can be customized using cell data functions (such as those added by a call to TreeViewColumn.SetCellDataFunc), I had to pull the content to export from the CellRenderer as opposed to pulling directly from the TreeModel. Turns out there's a method to take the TreeIter from a TreeModel and apply it to all the CellRenderers in a given TreeViewColumn. Since I really only care about textual content, I decided to only export those columns that contain CellRendererText renderers.