Intro...

Window managers have a few ways in which they are significantly different
from other applications.  This file, combined with the code overview in
doc/code-overview.txt, should hopefully provide a series of relatively
quick pointers (hopefully only a few minutes each) to some of the places
one can look to orient themselves and get started.  Some of this will be
general to window managers on X, much will be specific to Metacity, and
there's probably some information that's common to programs in general but
is nonetheless useful.

Overview
  Administrative issues
  Minimal Building/Testing Environment
  Relevant standards and X properties
  Debugging and testing
    Debugging logs
    Adding information to the log
    Valgrind
    Testing Utilities
  Technical gotchas to keep in mind
  Other important reading
    Extra reading
    Ideas for tasks to work on


Administrative issues
  Don't commit substantive code in here without asking hp@redhat.com.
  Adding translations, no-brainer typo fixes, etc. is fine.

  The code could use cleanup in a lot of places, feel free to do so.

  See http://developer.gnome.org/dotplan/for_maintainers.html for
  information on how to make a release.  The only difference from those
  instructions is that the minor version number of a Metacity release
  should always be a number from the Fibonacci sequence.

Minimal Building/Testing Environment
  You do not need to _install_ a development version of Metacity to
  build, run and test it; you can run it from some temporary
  directory.  Also, you do not need to build all of Gnome in order to
  build a development version of Metacity -- odds are, you may be able
  to build metacity from CVS without building any other modules.

  As long as you have gtk+ >= 2.10 and GIO >= 2.25.10 with your distro
  (gtk+ >= 2.6 if you manually revert the change from bug 348633), you
  should be able to install your distro's development packages
  (e.g. gtk2-devel, glib-devel, startup-notification-devel on
  Fedora; also, remember to install the gnome-common package which is
  needed for building cvs versions of Gnome modules like Metacity) as
  well as the standard development tools (gcc, autoconf, automake,
  pkg-config, intltool, and libtool) and be ready to build and test
  Metacity.  Steps to do so:

  $ svn checkout http://svn.gnome.org/svn/metacity/trunk metacity
  $ cd metacity
  $ ./autogen.sh --prefix /usr
  $ make
  $ ./src/metacity --replace

  Again, note that you do not need to run 'make install'.

Relevant standards and X properties
  There are two documents that describe some basics about how window
  managers should behave: the ICCCM (Inter-Client Communication Conventions
  Manual) and EWMH (Extended Window Manager Hints).  You can find these at
  the following locations:
    ICCCM - http://tronche.com/gui/x/icccm/
    EWMH  - :pserver:anoncvs@pdx.freedesktop.org:/cvs
  The ICCCM is usually available in RPM or DEB format as well.  There is
  actually an online version of the EWMH, but it is almost always woefully
  out of date.  Just get it from cvs with these commands (the backslash
  means include the stuff from the next line):
    cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions login
    cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions \
      checkout wm-spec

  DO NOT GO AND READ THOSE THINGS.  THEY ARE REALLY, REALLY BORING.

  If you do, you'll probably end up catching up on your sleep instead of
  hacking on Metacity. ;-)  Instead, just look at the table of contents and
  glance at a page or two to get an idea of what's in there.  Then only
  refer to it if you see something weird in the code and you don't know
  what it is but has some funny looking name like you see in one of those
  two documents.

  You can refer to the COMPLIANCE file for additional information on these
  specifications and Metacity's compliance therewith.

  One of the major things those documents cover that are useful to learn
  about immediately are X properties.  The right way to learn about those,
  though, is through hand on experimentation with the xprop command (and
  then look up things you find from xprop in those two manuals if you're
  curious enough).  First, try running
    xprop
  in a terminal and click on one of the windows on your screen.  That gives
  you the x properties for that window.  Look through them and get a basic
  idea of what's there for kicks.  Note that you can get rid of some of the
  verboseness by grepping out the _NET_WM_ICON stuff, i.e.
    xprop | grep -v _NET_WM_ICON
  Next, try running
    xprop -root
  in a terminal.  There's all the properties of the root window (which you
  can think of as the "main" Xserver window).  You can also manually
  specify individual windows that you want the properties of with
    xprop -id <id>
  if you know the id of the window in question.  You can get the id of a
  given window by either running xwininfo, e.g.
    xwininfo | grep "Window id" | cut -f 4 -d ' '
  or by looking at the _NET_CLIENT_STACKING property of the root
  window.  Finally, it can also be useful to add "-spy" (without the
  quotes) to the xprop command to get it to continually monitor that
  window and report any changes to you.

Debugging information
  Trying to run a window manager under a typical debugger, such as gdb,
  unfortunately just doesn't work very well.  So, we have to resort to
  other methods.

  Debugging logs

  First, note that you can start a new version of metacity to replace the
  existing one by running
    metacity --replace
  (which also comes in handy in the form "./src/metacity --replace" when
  trying to quickly test a small change while hacking on metacity without
  doing a full "make install", though I'm going off topic...)  This will
  allow you to see any warnings printed at the terminal.  Sometimes it's
  useful to have these directed to a logfile instead, which you can do by
  running
    METACITY_USE_LOGFILE=1 metacity --replace
  The logfile it uses will be printed in the terminal.  Sometimes, it's
  useful to get more information than just warnings.  You can set
  METACITY_VERBOSE to do that, like so:
    METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 metacity --replace
  (note that METACITY_VERBOSE=1 can be problematic without
  METACITY_USE_LOGFILE=1; avoid it unless running in from something that
  won't be managed by the new Metacity--see bug 305091 for more details).
  There are also other flags, such as METACITY_DEBUG, most of which I
  haven't tried and don't know what they do.  Go to the source code
  directory and run
    grep "METACITY_" * | grep getenv
  to find out what the other ones are.

  Adding information to the log

  Since we can't single step with a debugger, we often have to fall back to
  the primitive method of getting information we want to know: adding
  "print" statements.  Metacity has a fairly structured way to do this,
  using the functions meta_warning, meta_topic, and meta_verbose.  All
  three have the same basic format as printf, except that meta_topic also
  takes a leading enumeration parameter to specify the type of message
  being shown (makes it easier for grepping in a verbose log).  You'll find
  tons of examples in the source code if you need them; just do a quick
  grep or look in most any file.  Note that meta_topic and meta_verbose
  messages only appear if verbosity is turned on.  I tend to frequently add
  temporary meta_warning statements (or switch meta_topic or meta_verbose
  ones to meta_warning ones) and then undo the changes once I've learned
  the info that I needed.

  There is also a meta_print_backtrace (which again is only active if
  verbosity is turned on) that can also be useful if you want to learn how
  a particular line of code gets called.  And, of course, there's always
  g_assert if you want to make sure some section isn't executed (or isn't
  executed under certain conditions).

  Valgrind

  Valgrind is awesome for finding memory leaks or corruption and
  uninitialized variables.  But I also tend to use it in a non-traditional
  way as a partial substitute for a normal debugger: it can provide me with
  a stack trace of where metacity is crashing if I made a change that
  caused it to do so, which is one of the major uses of debuggers.  (And,
  what makes it cooler than a debugger is that there will also often be
  warnings pinpointing the cause of the crash from either some kind of
  simple memory corruption or an uninitialized variable).  Sometimes, when
  I merely want to know what is calling a particular function I'll just
  throw in an "int i; printf("%d\n", i);" just because valgrind will give
  me a full stacktrace whenever it sees that uninitialized variable being
  used (yes, I could use meta_print_backtrace, but that means I have to
  turn verbosity on).

  To run metacity under valgrind, use options typical for any Gnome
  program, such as
    valgrind --log-file=metacity.log --tool=memcheck --num-callers=48 \
    --leak-check=yes --leak-resolution=high --show-reachable=yes     \
    ./src/metacity --replace
  where, again, the backslashes mean to join all the stuff on the following
  line with the previous one.

  However, there is a downside.  Things run a little bit slowly, and it
  appears that you'll need about 1.5GB of ram, which unfortunately prevents
  most people from trying this.

  Testing Utilities

  metacity-message
    The tool metacity-message can be used as follows:
      metacity-message reload-theme
      metacity-message restart
      metacity-message enable-keybindings
      metacity-message disable-keybindings
    The first of these is useful for testing themes, the second is just
    another way (besides the --restart flag to metacity itself) of
    restarting metacity, and the third is useful for testing Metacity when
    running it under an Xnest (typically, the Metacity under the Xnest
    wouldn't get keybinding notifications--making keyboard navigation not
    work--but if you disable the keybindings for the global Metacity then
    the Metacity under the Xnest can then get those keybinding notifications).

  metacity-window-demo
    metacity-window-demo is good for trying behavior of various kinds
    of window without launching a full desktop.

Technical gotchas to keep in mind
  Files that include gdk.h or gtk.h are not supposed to include
  display.h or window.h or other core files.  Files in the core
  (display.[hc], window.[hc]) are not supposed to include gdk.h or
  gtk.h.  Reasons:

    "Basically you don't want GDK most of the time. It adds
    abstractions that cause problems, because they aren't designed to
    be used in a WM where we do weird stuff (display grabs, and just
    being the WM). At best GDK adds inefficiency, at worst it breaks
    things in weird ways where you have to be a GDK guru to figure
    them out. Owen also told me that they didn't want to start adding
    a lot of hacks to GDK to let a WM use it; we both agreed back in
    the mists of time that metacity would only use it for the "UI"
    bits as it does.

    Having the split in the source code contains and makes very clear
    the interface between the WM and GDK/GTK. This keeps people from
    introducing extra GDK/GTK usage when it isn't needed or
    appropriate. Also, it speeds up the compilation a bit, though this
    was perhaps more relevant 5 years ago than it is now.

    There was also a very old worry that the GDK stuff might have to
    be in a separate process to work right; that turned out to be
    untrue. Though who knows what issues the CM will introduce."

  Remember that strings stored in X properties are not in UTF-8, and they
  have to end up in UTF-8 before we try putting them through Pango.

  If you make any X request involving a client window, you have to
  meta_error_trap_push() around the call; this is not necessary for X
  requests on the frame windows.

  Remember that not all windows have frames, and window->frame can be NULL.

Other important reading & where to get started
  Extra reading

  There are some other important things to read to get oriented as well.
  These are:
    http://pobox.com/~hp/features.html
    rationales.txt
    doc/code-overview.txt

  It pays to read http://pobox.com/~hp/features.html in order
  to understand the philosophy of Metacity.

  The rationales.txt file has two things: (1) a list of design choices with
  links in the form of bugzilla bugs that discuss the issue, and (2) a list
  outstanding bug categories, each of which is tracked by a particular
  tracker bug in bugzilla from which you can find several closely related
  bug reports.

  doc/code-overview.txt provides a fairly good overview of the code,
  including coverage of the function of the various files, the main
  structures and their relationships, and places to start looking in the
  code tailored to general categories of tasks.

  Ideas for tasks to work on

  There are a variety of things you could work on in the code.  You may
  have ideas of your own, but in case you don't, let me provide a list of
  ideas you could choose from:

  If you're ambitious, there's a list of things Havoc made that he'd really
  like to see tackled, which you can find at
  http://log.ometer.com/2004-05.html.  Be sure to double check with someone
  to make sure the item is still relevant if you're interested in one of
  these.  Another place to look for ideas, of course, is bugzilla.  One can
  just do queries and look for things that look fixable.

  However, perhaps the best way of getting ideas of related tasks to work
  on, is to look at the second half of the rationales.txt file, which tries
  to group bugs by type.
