window geometry/positioning



Hi,

Owen and I discussed the issue of window positioning and geometry, and
worked out a proposal. This addresses bug:
  http://bugzilla.gnome.org/show_bug.cgi?id=17167

I'm going to try to write it down, but it's late at night and I may
get stuff wrong.

The basic problem is that right now we have a haphazard and
not-very-logical set of functions for getting/setting window size and
position. The result is that people resort to all kinds of weird hacks
involving widget->window.

A brief catalog of what we have now:

 gdk_window_get_origin(): gets the origin of a toplevel window 
 with respect to the root window; this is the origin of the window 
 itself, not the window manager decoration frame.

 gdk_window_get_root_origin(): I believe this one gets the origin of a
 toplevel window's frame. It uses the "walk up to one below the root
 window" heuristic to find the frame (this could be improved a bit for
 some WM's that set properties marking the frame).

 gdk_window_get_deskrelative_origin(): gets the origin with respect to
 enlightenment's weird desktops, on other window managers equivalent
 to gdk_window_get_origin() I believe.

I could be wrong about these three, I'm just briefly glancing at them.

When you map a window or move it with gdk_window_move(), you are
positioning the "reference point" determined by the window
gravity. The reference point is the top left corner with the default
NorthWest gravity (GdkWindows default to NorthWest, and GTK 1.2 has no
way to set the gravity; GTK 2 adds gravity to GdkGeometry). However,
you aren't really positioning the window itself, but rather the window
frame. That is, if you map a window at position 0,0, then the window
gets shifted down to make room for the titlebar and border. At least
this is what I remember, my ICCCM is at work and I'm at home. ;-) So
if you specify the geometry +0+0, the frame goes at that position, not
the window itself. The exception is if you specify StaticGravity,
which means that your requested position is for the window itself, not
the frame.

The freedesktop.org window manager spec clarifies this issue because
lots of WMs screw it up:
  http://www.freedesktop.org/standards/wm-spec/x277.html

If you gdk_window_resize(), then the reference point determined by the
gravity stays in a fixed position as the window resizes. Here I don't
think it makes a difference whether you think of the reference point
as a corner of the frame or a corner of the window itself.

On the GTK level, we have:

 gtk_widget_set_uposition(): for toplevels, this oddly enough sets the
 PPosition (program position) hint rather than the USPosition
 (user-specified position) hint, and also calls gdk_window_move() if
 the window is realized. So basically it positions the window frame
 unless StaticGravity is set. I'm not clear on what effect setting the
 PPosition hint actually has, since gdk_window_move() works anyway
 (?).

 gtk_window_set_default_size(): only works before mapping the window,
 emulates the user setting the window size, sets the size of the 
 window itself not the frame

 gtk_widget_set_usize(): on toplevels, changes the minimum size.
 

We came up with the following use-cases for where people are trying to
use these things on toplevels:

 - "do your own session management" - since all session managers
   seem to suck, apps try to save and restore window positions
   and sizes.

 - "Java IDE" - we saw a Java IDE - I think it was Forte - that did
   this fairly broken thing attempting to tile its windows
   itself. That is, it tried to snap the edges of window frames
   together, basically do its own window management.
   Another case of this: sometimes you see audio apps that are 
   conceptually a stack of stereo components, that can be stacked
   together. (However those usually turn off frames, which makes 
   it a different use case.)

 - XMMS/GtkHandleBox - this case is "I want to ignore the window
   manager", you turn off decorations (or much worse, use 
   override redirect) and then move/resize the window using controls
   inside the app

 - --geometry command line option; here you want to set the window
   position on startup

 - XawTV: XawTV apparently wanted to retrieve the position of a window
   in root window coordinates, so it could directly write into the 
   framebuffer at that point.

 - Full-screen presentation application: here you want to 
   turn off decorations and set your size to the full screen size.

 - panels, docks, etc. that position themselves manually and aren't 
   really window managed.

So we are proposing the following functions on the GTK level, with the
exact GDK implementation to be decided:

 gtk_window_set_gravity ()
 gtk_window_get_gravity ()
   
  These are convenience functions to avoid using GdkGeometry.

 gtk_window_set_size ()
 gtk_window_get_size ()
 
  These set and get the size of the frameless window; the resize
  keeps the reference point determined by the window gravity in 
  a fixed location. The size is set as for
  gtk_window_set_default_size(), as if the user had resized it.

 gtk_window_set_position ()
 gtk_window_get_position ()
 
  These set and get the position of the reference point as determined
  by the window gravity; so for StaticGravity, they are the same 
  as gdk_window_get_origin(), for NorthWest gravity the same as
  gdk_window_get_root_origin(). The position is always in root window
  coordinates, even on weird Enlightenment desktops where the
  desktop's 0,0 may not be 0,0 on the root window.

 gtk_window_set_frame_size ()
 gtk_window_get_frame_size ()
 
  Attempts as best we can to set and get the size of the window
  _including the window manager frame_. These functions can't 
  be implemented reliably, but we can do a good bit better
  than naive application authors might do.

 gdk_workspace_get_extents ()

  Returns the extents of the "workspace." This takes into 
  account Enlightenment's weird desktops, and also the WM spec
  "struts". So the workspace is the area in which you might consider
  positioning your app. If you want to position at 0,0, probably you
  really want the top left corner of the workspace. If you want to 
  "maximize" an app, you'd really use gtk_window_maximize(), but
  ignoring that you'd make it fill the workspace extents.

 gdk_desktop_get_extents ()

  (Not discussed with Owen, but I think needed for panels, fullscreen 
  apps, etc.)
  Returns the full extents of the current desktop in root window
  coordinates; this would normally be the area of the root window 
  which is on the user's monitor. Usually (0,0) to
  (screen_width,screen_height) but may not be on odd window managers.

So then the use cases are supposed to work as follows:

 - "do your own session management" just uses
   gtk_window_get/set_size(), gtk_window_get/set_position().  

   In current GTK you have to gdk_window_get_root_origin(), 
   but it doesn't work with the Enlightenment desktop case.
   Then you gtk_widget_set_uposition().

 - "Java IDE" uses gtk_window_get/set_frame_size(). There's no 
   sane way to do this with current GTK (since there's no very good
   way to implement it in X ...)

 - XMMS and GtkHandleBox can actually use
   gtk_window_begin_resize_drag() and gtk_window_begin_move_drag(). 
   But if they didn't do that, they would use set_size() and
   set_position().

   With current GTK, you can just use gdk_window_move_resize(), 
   since there's no frame to worry about.

 - --geometry command line arg just uses gtk_window_set_size() 
   and gtk_window_set_position(). Done in the same way as 
   "session management" with current GTK. 

 - XawTV would use gtk_window_get_position() after setting the 
   window to StaticGravity, or more likely just
   gdk_window_get_origin().

 - Full-screen presentation app would call gdk_desktop_get_extents()
   then gtk_window_set_size() to those extents.

 - Panels and docks could also just use set_size() and set_position().

   With current GTK, the panels and the presentation app would
   probably use gdk_screen_width()/gdk_screen_height() as the extents, 
   which may on occasion be wrong.

So find the bugs in this mail, I'm implementing this soon.

Havoc




 
 




 




 
 




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]