First: the method gtk.Window.resize() doesnt't work with a single argument (setting the other to -1, as instead does gtk.Widget.set_size_request()). OK, this is documented, though ugly.
Now: if a gtk.Window w has size (100,100) and we run the following code:
w.resize(200,200) size = w.get_size() w.resize(*size)
, then the window won't resize to 200,200, but to 100,100. In fact “resize” doesn't really resize, it just queues a resize process, while if we use get_size we get the current size, not the queued one. This means if several functions try to resize (and it makes sense, if each one takes care of a single dimension), we have race conditions.
I solved that (both problems) with the following functions:
def unset_real_size(window, event): """Fields 'real width' and 'real height' become obsolete (or at least useless) when a resize actually takes place. """ window.set_data('real width', None) window.set_data('real height', None) handler = window.get_data('configure handler') if handler: # The callback is now useless; remove it. window.disconnect(handler) window.set_data('configure handler', None) def ensure_configure_handler(window): """Ensure that unset_real_size is called. """ if not window.get_data('configure handler'): new_handler = window.connect('configure-event', unset_real_size) window.set_data('configure handler', new_handler) def get_width(window): width = window.get_data('real width') if not width: width = window.get_size() return width def get_height(window): height = window.get_data('real height') if not height: height = window.get_size() return height def set_width(window, width): ensure_configure_handler(window) window.set_data('real width', width) height = get_height(window) window.resize(width, height) def set_height(window, height): ensure_configure_handler(window) window.set_data('real height', height) width = get_width(window) window.resize(width, height)
Notice that set_size_request has a similar problem: if a gtk.Widget widget's get_size_request gives (-1,-1) and I run the following code:
widget.set_size_request(100,100) widget.set_size_request(-1, -1)
, it won't expand at all, nothing will happen. This is an issue if you wanted to use this as a hack to resize the widget but let to the user the possibility to shrink it again; an hackish way to solve this is instead the following code:
widget.set_size_request(100,100) gobject.idle_add(widget.set_size_request, -1, -1)
While gtk.Containers usually propagate size requests from child(ren) to parent, gtk.ScrolledWindow doesn't; instead, it sets a predefined (hardcoded, presumably) size. Apparently, this makes sense: if you want the whole widget shown, why a ScrolledWindow?! However, there are 2 situations in which this is hateful:
I solved this with the following code (widget is the widget we want to resize so that it is fully shown), thanks to owen in freenode.irc's #gtk+ for the hint:
scrolledwindows =  scrolledwindows_policies =  scrolledwindows_hscrollbars =  while widget: # The ScrolledWindows stop propagation of queue_redraws, unless they # have the scrollbars disabled, so here we disable them... if gobject.type_is_a(widget, gtk.ScrolledWindow): scrolledwindows.append(widget) scrolledwindows_policies.append(widget.get_policy()) widget.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) scrolledwindows_hscrollbars.append(widget.get_hscrollbar()) widget = widget.get_parent() toplevel = treeview.get_toplevel() # ... then we can take the size... new_width = toplevel.size_request() # ... add the size of bars... bars_width = 0 for index in range(len(scrolledwindows)): # (not needed if the policy hides it) if scrolledwindows_policies[index] == gtk.POLICY_ALWAYS: bars_width += scrolledwindows_hscrollbars[index].size_request() scrolledwindows[index].set_policy(*scrolledwindows_policies[index]) # print "width:", new_width # ... and put together the total size. new_width += bars_width