diff --git a/HACKING b/HACKING new file mode 100644 index 000000000..5fccf41ed --- /dev/null +++ b/HACKING @@ -0,0 +1,48 @@ + +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 +or + DEBUG=memprof ./run-metacity.sh +or whatever. + +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. + +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. + +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. + +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. + +The code could use cleanup in a lot of places, feel free to do so. + + diff --git a/Makefile.am b/Makefile.am index e3f5d376e..e7cccc70a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,4 @@ SUBDIRS=src +EXTRA_DIST=HACKING diff --git a/README b/README index 423ff0d6a..a8daf3452 100644 --- a/README +++ b/README @@ -23,6 +23,8 @@ sometime probably. Feel free to send patches too; Metacity is really small and simple, so if you find a bug or want to add a feature it should be pretty easy. +See the HACKING file for some notes on hacking Metacity. + METACITY FEATURES === diff --git a/src/display.c b/src/display.c index 0c62bd269..df75a624b 100644 --- a/src/display.c +++ b/src/display.c @@ -1555,24 +1555,26 @@ meta_display_grab_window_buttons (MetaDisplay *display, meta_warning ("Failed to grab button %d with Mod1Mask for frame 0x%lx error code %d\n", i, xwindow, result); -#if 1 - /* This is just for debugging, since I end up moving - * the Xnest otherwise ;-) - */ - meta_error_trap_push (display); - result = XGrabButton (display->xdisplay, i, ControlMask, - xwindow, False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | PointerMotionHintMask, - GrabModeAsync, GrabModeAsync, - False, None); - XSync (display->xdisplay, False); - result = meta_error_trap_pop (display); - - if (result != Success) - meta_warning ("Failed to grab button %d with ControlMask for frame 0x%lx error code %d\n", - i, xwindow, result); -#endif + + if (g_getenv ("METACITY_DEBUG_BUTTON_GRABS")) + { + /* This is just for debugging, since I end up moving + * the Xnest otherwise ;-) + */ + meta_error_trap_push (display); + result = XGrabButton (display->xdisplay, i, ControlMask, + xwindow, False, + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | PointerMotionHintMask, + GrabModeAsync, GrabModeAsync, + False, None); + XSync (display->xdisplay, False); + result = meta_error_trap_pop (display); + + if (result != Success) + meta_warning ("Failed to grab button %d with ControlMask for frame 0x%lx error code %d\n", + i, xwindow, result); + } ++i; } diff --git a/src/place.c b/src/place.c index 8952d117f..1e091f4d0 100644 --- a/src/place.c +++ b/src/place.c @@ -185,6 +185,11 @@ find_next_cascade (MetaWindow *window, /* Find the leftmost, then topmost, empty area on the workspace * that can contain the new window. + * + * Cool feature to have: if we can't fit the current window size, + * try shrinking the window (within geometry constraints). But + * beware windows such as Emacs with no sane minimum size, we + * don't want to create a 1x1 Emacs. */ static gboolean find_first_fit (MetaWindow *window, @@ -196,7 +201,7 @@ find_first_fit (MetaWindow *window, int *new_x, int *new_y) { - + /* FIXME */ } void diff --git a/src/session.c b/src/session.c index 968fa952a..e5148f5b3 100644 --- a/src/session.c +++ b/src/session.c @@ -525,6 +525,10 @@ set_clone_restart_commands (void) SmcSetProperties (session_connection, 3, props); + g_free (prop1.vals); + g_free (prop2.vals); + g_free (prop3.vals); + g_free (session_file); } diff --git a/src/window.c b/src/window.c index 35649dbe7..4df03411e 100644 --- a/src/window.c +++ b/src/window.c @@ -70,13 +70,22 @@ static gboolean process_property_notify (MetaWindow *window, static void meta_window_show (MetaWindow *window); static void meta_window_hide (MetaWindow *window); -static void meta_window_move_resize_internal (MetaWindow *window, - gboolean is_configure_request, - int resize_gravity, - int root_x_nw, - int root_y_nw, - int w, - int h); +static void adjust_for_gravity (MetaWindow *window, + MetaFrameGeometry *fgeom, + gboolean coords_assume_border, + int x, + int y, + int *xp, + int *yp); +static void meta_window_move_resize_internal (MetaWindow *window, + gboolean is_configure_request, + gboolean do_gravity_adjust, + int resize_gravity, + int root_x_nw, + int root_y_nw, + int w, + int h); + void meta_window_move_resize_now (MetaWindow *window); @@ -446,7 +455,7 @@ meta_window_new (MetaDisplay *display, Window xwindow, * passing TRUE for is_configure_request, ICCCM says * initial map is handled same as configure request */ - meta_window_move_resize_internal (window, TRUE, + meta_window_move_resize_internal (window, TRUE, FALSE, NorthWestGravity, window->size_hints.x, window->size_hints.y, @@ -522,7 +531,7 @@ meta_window_apply_session_info (MetaWindow *window, * indeed valid, so we know we'll go right back to one. */ while (window->workspaces) - meta_workspace_remove_window (window->workspaces->next->data, window); + meta_workspace_remove_window (window->workspaces->data, window); tmp = spaces; while (tmp != NULL) @@ -543,6 +552,32 @@ meta_window_apply_session_info (MetaWindow *window, g_slist_free (spaces); } } + + if (info->geometry_set) + { + int x, y, w, h; + + window->placed = TRUE; /* don't do placement algorithms later */ + + x = info->rect.x; + y = info->rect.y; + + w = window->size_hints.base_width + + info->rect.width * window->size_hints.width_inc; + h = window->size_hints.base_height + + info->rect.height * window->size_hints.height_inc; + + /* Force old gravity, ignoring anything now set */ + window->size_hints.win_gravity = info->gravity; + + meta_verbose ("Restoring pos %d,%d size %d x %d for %s\n", + x, y, w, h, window->desc); + + meta_window_move_resize_internal (window, + FALSE, TRUE, + NorthWestGravity, + x, y, w, h); + } } void @@ -1020,7 +1055,7 @@ meta_window_unshade (MetaWindow *window) /* returns values suitable for meta_window_move */ -void +static void adjust_for_gravity (MetaWindow *window, MetaFrameGeometry *fgeom, gboolean coords_assume_border, @@ -1155,6 +1190,8 @@ adjust_for_gravity (MetaWindow *window, static void meta_window_move_resize_internal (MetaWindow *window, gboolean is_configure_request, + /* only relevant if !is_configure_request */ + gboolean do_gravity_adjust, int resize_gravity, int root_x_nw, int root_y_nw, @@ -1233,7 +1270,7 @@ meta_window_move_resize_internal (MetaWindow *window, frame_size_dy = 0; } - if (is_configure_request) + if (is_configure_request || do_gravity_adjust) { adjust_for_gravity (window, window->frame ? &fgeom : NULL, @@ -1424,7 +1461,7 @@ meta_window_resize (MetaWindow *window, meta_window_get_position (window, &x, &y); - meta_window_move_resize_internal (window, FALSE, + meta_window_move_resize_internal (window, FALSE, FALSE, NorthWestGravity, x, y, w, h); } @@ -1434,7 +1471,7 @@ meta_window_move (MetaWindow *window, int root_x_nw, int root_y_nw) { - meta_window_move_resize_internal (window, FALSE, + meta_window_move_resize_internal (window, FALSE, FALSE, NorthWestGravity, root_x_nw, root_y_nw, window->rect.width, @@ -1448,7 +1485,7 @@ meta_window_move_resize (MetaWindow *window, int w, int h) { - meta_window_move_resize_internal (window, FALSE, + meta_window_move_resize_internal (window, FALSE, FALSE, NorthWestGravity, root_x_nw, root_y_nw, w, h); @@ -1464,7 +1501,7 @@ meta_window_resize_with_gravity (MetaWindow *window, meta_window_get_position (window, &x, &y); - meta_window_move_resize_internal (window, FALSE, + meta_window_move_resize_internal (window, FALSE, FALSE, gravity, x, y, w, h); } @@ -1579,6 +1616,21 @@ meta_window_get_gravity_position (MetaWindow *window, *root_y = y; } +void +meta_window_get_geometry (MetaWindow *window, + int *x, + int *y, + int *width, + int *height) +{ + meta_window_get_gravity_position (window, x, y); + + *width = (window->rect.width - window->size_hints.base_width) / + window->size_hints.width_inc; + *height = (window->rect.height - window->size_hints.base_height) / + window->size_hints.height_inc; +} + void meta_window_get_outer_rect (MetaWindow *window, MetaRectangle *rect) @@ -1874,7 +1926,7 @@ meta_window_configure_request (MetaWindow *window, window->size_hints.width = width; window->size_hints.height = height; - meta_window_move_resize_internal (window, TRUE, + meta_window_move_resize_internal (window, TRUE, FALSE, NorthWestGravity, window->size_hints.x, window->size_hints.y, diff --git a/src/window.h b/src/window.h index 74217324d..3757d8d4c 100644 --- a/src/window.h +++ b/src/window.h @@ -257,6 +257,14 @@ void meta_window_get_position (MetaWindow *window, void meta_window_get_gravity_position (MetaWindow *window, int *x, int *y); +/* Get geometry for saving in the session; x/y are gravity + * position, and w/h are in resize inc above the base size. + */ +void meta_window_get_geometry (MetaWindow *window, + int *x, + int *y, + int *width, + int *height); void meta_window_get_outer_rect (MetaWindow *window, MetaRectangle *rect); void meta_window_delete (MetaWindow *window,