Provide more documentation to make it easier for people to contribute to

2005-01-02  Elijah Newren  <newren@gmail.com>

	Provide more documentation to make it easier for people to
	contribute to Metacity

	* HACKING: Add lots of information to extend this document: more
	on relevant standards and X properties, lots of information on
	debugging and testing, and add a list of some other important
	things to read; also move some information to
	src/code-overview.txt and organize this file into sections.

	* src/code-overview.txt: New file including some small parts from
	the old HACKING file and lots of new stuff.  This file gives a
	brief overview of some of the bigger structures and files, with
	guides for a variety of task categories providing places to start
	looking in the code and things to look for.
This commit is contained in:
Elijah Newren 2005-01-02 21:59:05 +00:00 committed by Elijah Newren
parent 890ffe18f2
commit 9382d5810f
3 changed files with 409 additions and 79 deletions

View File

@ -1,3 +1,20 @@
2005-01-02 Elijah Newren <newren@gmail.com>
Provide more documentation to make it easier for people to
contribute to Metacity
* HACKING: Add lots of information to extend this document: more
on relevant standards and X properties, lots of information on
debugging and testing, and add a list of some other important
things to read; also move some information to
src/code-overview.txt and organize this file into sections.
* src/code-overview.txt: New file including some small parts from
the old HACKING file and lots of new stuff. This file gives a
brief overview of some of the bigger structures and files, with
guides for a variety of task categories providing places to start
looking in the code and things to look for.
2004-12-28 Elijah Newren <newren@gmail.com>
Allow users to move the window around immediately after

270
HACKING
View File

@ -1,45 +1,165 @@
Making a release
===
Intro...
To make a release of metacity, do the following:
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.
- check out a fresh copy from CVS
Overview
Administrative issues
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
- increment the version number in configure.in,
see the comment above the version for the next fibonacci number
- update the file NEWS based on the ChangeLog
Administrative issues
Don't commit substantive code in here without asking hp@redhat.com.
Adding translations, no-brainer typo fixes, etc. is fine.
- add a ChangeLog entry containing the version number
you're releasing ("Released 2.5.4" or something)
so people can see which changes were before and after
a given release.
The code could use cleanup in a lot of places, feel free to do so.
- "make distcheck" (DO NOT just "make dist" - pass the check!)
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.
- if make distcheck fails, fix it.
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
- once distcheck succeeds, "cvs commit"
DO NOT GO AND READ THOSE THINGS. THEY ARE REALLY, REALLY BORING.
- if someone else made changes and the commit fails,
you have to "cvs up" and run "make distcheck" again
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.
- once the commit succeeds, WITHOUT cvs updating, "cvs tag
METACITY_X_Y_Z" where
X_Y_Z map to version X.Y.Z
You can refer to the COMPLIANCE file for additional information on these
specifications and Metacity's compliance therewith.
- scp the tarball to master.gnome.org
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. 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" 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 this from 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.
- run install-module on master.gnome.org to install the tarball
on the ftp site
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.
Misc stuff
===
Debugging logs
Don't commit substantive code in here without asking me,
hp@redhat.com. Adding translations, no-brainer typo fixes, etc. is
fine.
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
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 --logfile=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
src/run-metacity.sh
The script src/run-metacity.sh is useful to hack on the window manager.
It runs metacity in an Xnest. e.g.:
CLIENTS=3 ./run-metacity.sh
@ -49,61 +169,69 @@ or
DEBUG_TEST=1 ./run-metacity-sh
or whatever.
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
metacity-window-demo is good for trying behavior of various kinds of window
without launching a full desktop.
metacity-window-demo
metacity-window-demo is good for trying behavior of various kinds
of window without launching a full desktop.
src/window.c is where all the guts of the window manager live. This is
basically the only remotely scary file.
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.
src/frames.c is the GtkWidget that handles drawing window frames.
Files in the core (display.[hc], window.[hc]) are not supposed to include
gdk.h or gtk.h.
src/core.h defines the interface used by the GTK portion of the window
manager to talk to the other portions. There's some cruft in here
that's unused, since nearly all window operations have moved out of
this file so frameless apps can have window operations.
src/ui.h defines the interface the plain Xlib portion of the window
manager uses to talk to the GTK portion.
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.
src/theme.c and src/theme-parser.c have the theme system; this is
well-modularized from the rest of the code, since the theme viewer app
links to these files in addition to the WM itself.
When hacking, remember that you can have multiple screens. The code is
also written to support multiple displays, but this is useless, since
you can just run two copies of the WM. Also, an XKillClient() or
shutdown on any display causes Xlib to exit the app, so it would be
broken. So the multi-display thing is mostly just for code
cleanliness. Multi-screen on the other hand is important for some
people.
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.
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.
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.
Remember that not all windows have frames, and window->frame can be NULL.
The code could use cleanup in a lot of places, feel free to do so.
Other important reading & where to get started
Extra reading
Metacity is ideally a fully ICCCM and EWMH-compliant window manager.
Reading these specifications is a useful first step to understanding
the role of a window manager on an X11 desktop and the standards and
conventions on which X11 desktops are based. Please refer to the
COMPLIANCE file for additional information on these specifications and
metacity's compliance therewith.
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.

185
doc/code-overview.txt Normal file
View File

@ -0,0 +1,185 @@
This is not meant to be comprehensive by any means. Rather it is
meant as just a brief overview of some of the bigger structures and
files, with guides for a variety of task categories providing places
to start looking in the code and things to look for.
Overview
Jobs of various files
Major data structures and their relationships
Getting started -- where to look
Jobs of various files
src/window.c is where all the guts of the window manager live. This is
basically the only remotely scary file.
src/frames.c is the GtkWidget that handles drawing window frames.
src/core.h defines the interface used by the GTK portion of the window
manager to talk to the other portions. There's some cruft in here that's
unused, since nearly all window operations have moved out of this file so
frameless apps can have window operations.
src/ui.h defines the interface the plain Xlib portion of the window
manager uses to talk to the GTK portion.
src/theme.c and src/theme-parser.c have the theme system; this is
well-modularized from the rest of the code, since the theme viewer app
links to these files in addition to the WM itself.
Major data structures and their relationships
Major structs have a "Meta" prefix, thus MetaDisplay, MetaScreen,
MetaWindow, etc. This serves as a way of namespacing in C. It also has
the side effect of avoiding conflicts with common names that X already
uses such as Display, Screen, Window, etc. Note that when I refer to a
display below, I'm meaning a MetaDisplay and not a Display.
Don't confuse displays and screens. While Metacity can run with multiple
displays, it is kind of useless since you might as well just run two
copies of Metacity. However, having multiple screens per display is
useful and increasingly common (known as "multiscreen" and "xinerama"
setups, where users make use of more than one monitor). You should
basically think of a display as a combination of one or more monitors
with a single keyboard (...and usually only one mouse).
There is also a significant difference between multiscreen and xinerama
as well. Basically, each MetaScreen is a root window (root node in the
tree of windows). With Xinerama, a single root window appears to span
multiple monitors, whereas with multiscreen a root window is confined to
a single monitor. To re-emphasize the distinction between a display and
a screen, the pointer and keyboard are shared between all root windows
for a given display.
The display keeps track of a lot of various global quantities, but in
particular has a compositor and a list (GList) of screens.
A compositor is an opaque structure (only defined in compositor.c),
meaning that you'll only reference the API for it. It handles (or will
handle) cool stuff with the new X extensions, such as smooth resizing and
alpha transparency.
A screen keeps track of a number of quantities as well, in particular a
stack and a list of workspaces.
A stack is basically a list of windows, and the depth order they have
relative to each other (which thus determines which windows are on top
and which are obscured).
A workspace mostly contains a list of windows for the workspace, but also
has a few other quantities as well (a list of struts which are areas
where windows should not be placed and an mru_list or "most recently used
window list").
A window has a huge list of quantities for keeping track of things about
a window on the screen. (We want to avoid making this list larger
because the memory for all these quantities is per window.) One item in
particular that a window has, though, is a frame.
A frame is the decorations that surround the window (i.e. the titlebar and
the minimize and close buttons and the part that you can use to resize),
and contains a handful of variables related to that, but no other major
structures.
Getting started -- where to look
Getting started on developing free software projects can often be like
being dropped off in a town that is unknown to you and being told to make
a map, when various road and building signs are missing or fading. To
try to alleviate that initial difficulty in orientation, below I list a
variety of general task categories with file, function, variable, and x
property names that may be useful to fixing bugs or writing features that
fall within that category.
First, though, it's useful to note that most event and message passing
goes through display.c:event_callback(), so that's often a good place to
start reading for general familiarity with the code (actually, I'd
suggest skipping down to the first switch statement within that
function). Of course, not all events go through that function, as there
are a few other places that handle events too such as frames.c.
Anyway, without further ado, here are the categories and (hopefully)
useful things to look at for each:
Focus issues (i.e. issues with which window is active):
doc/how-to-get-focus-right.txt
meta_workspace_focus_default_window
_NET_ACTIVE_WINDOW
_NET_WM_USER_TIME
meta_window_focus
meta_display_(set_input|focus_the_no)_focus_window
XSetInputFocus (only for purposes of understanding how X focus/input works)
CurrentTime (mostly, you should just think "Bad; don't use it")
Compositor stuff (X extension for eye candy like transparency):
compositor.c
The luminocity module in CVS
Window depth (i.e. stacking or lowering/raising) issues:
stack.c
_NET_CLIENT_LIST_STACKING
transient_for
WM_TRANSIENT_FOR
meta_window_(raise|lower)
_NET_WM_WINDOW_TYPE
_NET_WM_MOUSE_ACTION/_NET_WM_TAKE_ACTIVITY? (aren't yet in EWMH)
Window placement issues:
place.c
constraints.c
_NET_WM_STRUT
WM_SIZE_HINTS
Moving and resizing issues:
constraints.c
update_move
update_resize
meta_window_handle_mouse_grab_op_event
_NET_MOVERESIZE_WINDOW
_NET_WM_STRUT
Drag and drop issues:
the XDND protocol (see http://www.newplanetsoftware.com/xdnd/ and
http://freedesktop.org/Standards/XDND)
_NET_WM_MOUSE_ACTION/_NET_WM_TAKE_ACTIVITY (aren't yet in EWMH)
A general pointer: what causes the difficulty here is that when the
application receives a mouse click to start a drag, it does a grab
so that the window manager doesn't get any further events; thus
correcting things require standards so that applications and window
managers can collaborate correctly
Theme issues: ???
doc/theme-format.txt
theme.c
theme-parser.c
(ui.c, core.c, frames.c, frame.c? I dunno...)
Session management issues: ???
session.c
http://www.x.org/X11R6.8.1/doc/SM/xsmp.pdf ?
http://www.x.org/X11R6.8.1/doc/SM/SMlib.pdf ?
meta_window_apply_session_info
Tasklist and Workspace switcher issues:
window-props.c
various functions in screen.c (especially ones using XChangeProperty)
xprops.c
The libwnck module in cvs
meta_window_client_message
Lots of the EWMH
Window and workspace selection/changing issues:
tabpopup.c
keybindings.c, functions: *_workspace*, *_tab_*
meta_screen_ensure_*_popup
display.c, functions: *_tab*
Key and mouse binding actions:
keybindings.c
meta_frames_button_(press|release)_event
display.c: event_callback, but only the (Key|Button)_(Press|Release) cases
Xinerama and multiscreen: ???
In general, just search for Xinerama, but in particular see
screen.c
window.c
place.c
constraints.c