diff --git a/ChangeLog b/ChangeLog index ab710bfa8..012b09824 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,56 @@ +2003-10-12 Havoc Pennington <hp@redhat.com> + + Merge reduced_resources mode patch from the branch. Offers + wireframe and no-animations. + + * src/window.c (implement_showing): no animation if we are + in reduced resources mode + + * src/prefs.c: add REDUCED_RESOURCES pref + + * src/window.c (meta_window_update_keyboard_resize): fix to + modify grab_anchor_window_pos to grab_wireframe_rect if + appropriate instead of window->rect + + * src/display.h (struct _MetaDisplay): add grab_start_serial used + to avoid responding to events that occurred prior to the grab + initialization. + + Still broken in various ways, specifically EnterNotify that + occurred prior to XGrabPointer is processed as if it occurred + after. + + * src/window.c (meta_window_update_keyboard_move): add this + instead of meta_window_warp_pointer() crack + + * src/effects.c (meta_effects_update_wireframe): draw a kind of + grid for the wireframe, instead of just a rectangle, like twm + + * src/screen.c (meta_screen_new): line width of 3 for the XOR gc + + "Reduced resources" mode based on wireframe patch from + Erwann Chenede. Still pretty buggy. + + * src/keybindings.c (process_keyboard_move_grab) + (process_keyboard_resize_grab): add gruesome wireframe hacks + + * src/display.c (meta_display_end_grab_op): end wireframe + (meta_display_begin_grab_op): begin wireframe + + * src/effects.c (meta_effects_end_wireframe) + (meta_effects_update_wireframe, meta_effects_begin_wireframe): + routines to draw the wireframe stuff + + * src/window.c (window_should_be_showing): hide window when + doing wireframe, commented out as it breaks grab + * src/window.c (meta_window_refresh_resize_popup): handle wireframe + + * src/screen.c (meta_screen_new): create a screen->root_xor_gc + for use in drawing wireframes + + * src/frames.c (meta_frames_push_delay_exposes): repaint + everything before we delay + 2003-10-11 Havoc Pennington <hp@pobox.com> * src/display.c (meta_display_begin_grab_op): initialize diff --git a/README b/README index 7d5716603..aacb0fb73 100644 --- a/README +++ b/README @@ -370,12 +370,11 @@ A: This one is also in rationales.txt. Because "ouija board" UI, where http://pobox.com/~hp/free-software-ui.html http://pobox.com/~hp/features.html -Q: Why no wireframe move/resize? +Q: Why does wireframe move/resize suck? -A: It's implemented in a patch that will be merged for GNOME 2.6 - and is already in some vendor packages. +A: You can turn it on with the reduced_resources setting. - But: Because it has low usability, and is a pain + But: it has low usability, and is a pain to implement, and there's no reason opaque move/resize should be a problem on any setup that can run a modern desktop worth a darn to begin with. diff --git a/src/display.c b/src/display.c index c09867692..719789c6a 100644 --- a/src/display.c +++ b/src/display.c @@ -35,6 +35,7 @@ #include "resizepopup.h" #include "workspace.h" #include "bell.h" +#include "effects.h" #include <X11/Xatom.h> #include <X11/cursorfont.h> #ifdef HAVE_SOLARIS_XINERAMA @@ -1219,7 +1220,8 @@ event_callback (XEvent *event, * goes to the frame. */ frame_was_receiver = TRUE; - meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event\n"); + meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n", + window->desc); } #ifdef HAVE_XSYNC @@ -1231,6 +1233,7 @@ event_callback (XEvent *event, if (display->grab_op != META_GRAB_OP_NONE && display->grab_window != NULL && + event->xany.serial > display->grab_start_serial && grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (display->grab_window, event); } @@ -1296,7 +1299,8 @@ event_callback (XEvent *event, case ButtonPress: if ((window && grab_op_is_mouse (display->grab_op) && - display->grab_button != (int) event->xbutton.button && + display->grab_button != (int) event->xbutton.button && + event->xany.serial > display->grab_start_serial && display->grab_window == window) || grab_op_is_keyboard (display->grab_op)) { @@ -1446,16 +1450,19 @@ event_callback (XEvent *event, break; case ButtonRelease: if (display->grab_window == window && + event->xany.serial > display->grab_start_serial && grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); break; case MotionNotify: if (display->grab_window == window && + event->xany.serial > display->grab_start_serial && grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); break; case EnterNotify: if (display->grab_window == window && + event->xany.serial > display->grab_start_serial && grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); /* do this even if window->has_focus to avoid races */ @@ -1519,6 +1526,7 @@ event_callback (XEvent *event, break; case LeaveNotify: if (display->grab_window == window && + event->xany.serial > display->grab_start_serial && grab_op_is_mouse (display->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); else if (window != NULL) @@ -2797,8 +2805,9 @@ meta_display_begin_grab_op (MetaDisplay *display, Window grab_xwindow; meta_topic (META_DEBUG_WINDOW_OPS, - "Doing grab op %d on window %s button %d pointer already grabbed: %d\n", - op, window ? window->desc : "none", button, pointer_already_grabbed); + "Doing grab op %d on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n", + op, window ? window->desc : "none", button, pointer_already_grabbed, + root_x, root_y); if (display->grab_op != META_GRAB_OP_NONE) { @@ -2808,6 +2817,9 @@ meta_display_begin_grab_op (MetaDisplay *display, return FALSE; } + /* We'll ignore any events < this serial. */ + display->grab_start_serial = XNextRequest (display->xdisplay); + /* FIXME: * If we have no MetaWindow we do our best * and try to do the grab on the RootWindow. @@ -2823,7 +2835,7 @@ meta_display_begin_grab_op (MetaDisplay *display, if (pointer_already_grabbed) display->grab_have_pointer = TRUE; - + meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow, timestamp); @@ -2860,8 +2872,8 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_xwindow = grab_xwindow; display->grab_button = button; display->grab_mask = modmask; - display->grab_initial_root_x = root_x; - display->grab_initial_root_y = root_y; + display->grab_anchor_root_x = root_x; + display->grab_anchor_root_y = root_y; display->grab_latest_motion_x = root_x; display->grab_latest_motion_y = root_y; display->grab_last_moveresize_time.tv_sec = 0; @@ -2870,6 +2882,7 @@ meta_display_begin_grab_op (MetaDisplay *display, #ifdef HAVE_XSYNC display->grab_update_alarm = None; #endif + display->grab_was_cancelled = FALSE; if (display->grab_window) { @@ -2877,9 +2890,34 @@ meta_display_begin_grab_op (MetaDisplay *display, meta_window_get_position (display->grab_window, &display->grab_initial_window_pos.x, &display->grab_initial_window_pos.y); + display->grab_anchor_window_pos = display->grab_initial_window_pos; + display->grab_wireframe_active = + meta_prefs_get_reduced_resources () && + (meta_grab_op_is_resizing (display->grab_op) || + meta_grab_op_is_moving (display->grab_op)); + + if (display->grab_wireframe_active) + { + /* FIXME we should really display the outer frame rect, + * but that complicates all the move/resize code since + * it works in terms of window rect. + */ + display->grab_wireframe_rect = window->rect; + if (window->frame) + { + display->grab_wireframe_rect.x += window->frame->rect.x; + display->grab_wireframe_rect.y += window->frame->rect.y; + } + + meta_window_calc_showing (display->grab_window); + meta_effects_begin_wireframe (display->grab_window->screen, + &display->grab_wireframe_rect); + } + #ifdef HAVE_XSYNC - if (meta_grab_op_is_resizing (display->grab_op) && + if (!display->grab_wireframe_active && + meta_grab_op_is_resizing (display->grab_op) && display->grab_window->update_counter != None) { XSyncAlarmAttributes values; @@ -3009,6 +3047,21 @@ meta_display_end_grab_op (MetaDisplay *display, display->grab_update_alarm); } #endif /* HAVE_XSYNC */ + + if (display->grab_wireframe_active) + { + display->grab_wireframe_active = FALSE; + meta_effects_end_wireframe (display->grab_window->screen, + &display->grab_wireframe_rect); + if (!display->grab_was_cancelled) + meta_window_move_resize (display->grab_window, + TRUE, + display->grab_wireframe_rect.x, + display->grab_wireframe_rect.y, + display->grab_wireframe_rect.width, + display->grab_wireframe_rect.height); + meta_window_calc_showing (display->grab_window); + } display->grab_window = NULL; display->grab_screen = NULL; diff --git a/src/display.h b/src/display.h index f96253d61..d6d349542 100644 --- a/src/display.h +++ b/src/display.h @@ -225,19 +225,24 @@ struct _MetaDisplay MetaScreen *grab_screen; MetaWindow *grab_window; Window grab_xwindow; + gulong grab_start_serial; int grab_button; - int grab_initial_root_x; - int grab_initial_root_y; + int grab_anchor_root_x; + int grab_anchor_root_y; + MetaRectangle grab_anchor_window_pos; int grab_latest_motion_x; int grab_latest_motion_y; gulong grab_mask; guint grab_have_pointer : 1; guint grab_have_keyboard : 1; + guint grab_wireframe_active : 1; + guint grab_was_cancelled : 1; + MetaRectangle grab_wireframe_rect; MetaRectangle grab_initial_window_pos; MetaResizePopup *grab_resize_popup; GTimeVal grab_last_moveresize_time; Time grab_motion_notify_time; - + /* we use property updates as sentinels for certain window focus events * to avoid some race conditions on EnterNotify events */ diff --git a/src/effects.c b/src/effects.c index 18fa59475..dee152961 100644 --- a/src/effects.c +++ b/src/effects.c @@ -409,5 +409,108 @@ meta_effects_draw_box_animation (MetaScreen *screen, XFlush (context->screen->display->xdisplay); } +void +meta_effects_begin_wireframe (MetaScreen *screen, + const MetaRectangle *rect) +{ + /* Grab the X server to avoid screen dirt */ + meta_display_grab (screen->display); + meta_ui_push_delay_exposes (screen->ui); + meta_effects_update_wireframe (screen, NULL, rect); +} + +static void +draw_xor_rect (MetaScreen *screen, + const MetaRectangle *rect) +{ + /* The lines in the center can't overlap the rectangle or each + * other, or the XOR gets reversed. So we have to draw things + * a bit oddly. + */ + XSegment segments[8]; + int i; + +#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH + + XDrawRectangle (screen->display->xdisplay, + screen->xroot, + screen->root_xor_gc, + rect->x, rect->y, + rect->width, rect->height); + + /* Don't put lines inside small rectangles where they won't fit */ + if (rect->width < (LINE_WIDTH * 4) || + rect->height < (LINE_WIDTH * 4)) + return; + + /* Two vertical lines at 1/3 and 2/3 */ + segments[0].x1 = rect->x + rect->width / 3; + segments[0].y1 = rect->y + LINE_WIDTH / 2 + LINE_WIDTH % 2; + segments[0].x2 = segments[0].x1; + segments[0].y2 = rect->y + rect->height - LINE_WIDTH / 2; + + segments[1] = segments[0]; + segments[1].x1 = rect->x + (rect->width / 3) * 2; + segments[1].x2 = segments[1].x1; + + /* Now make two horizontal lines at 1/3 and 2/3, but not + * overlapping the verticals + */ + + segments[2].x1 = rect->x + LINE_WIDTH / 2 + LINE_WIDTH % 2; + segments[2].x2 = segments[0].x1 - LINE_WIDTH / 2; + segments[2].y1 = rect->y + rect->height / 3; + segments[2].y2 = segments[2].y1; + + segments[3] = segments[2]; + segments[3].x1 = segments[2].x2 + LINE_WIDTH; + segments[3].x2 = segments[1].x1 - LINE_WIDTH / 2; + + segments[4] = segments[3]; + segments[4].x1 = segments[3].x2 + LINE_WIDTH; + segments[4].x2 = rect->x + rect->width - LINE_WIDTH / 2; + + /* Second horizontal line is just like the first, but + * shifted down + */ + i = 5; + while (i < 8) + { + segments[i] = segments[i - 3]; + segments[i].y1 = rect->y + (rect->height / 3) * 2; + segments[i].y2 = segments[i].y1; + ++i; + } + + XDrawSegments (screen->display->xdisplay, + screen->xroot, + screen->root_xor_gc, + segments, + G_N_ELEMENTS (segments)); +} + +void +meta_effects_update_wireframe (MetaScreen *screen, + const MetaRectangle *old_rect, + const MetaRectangle *new_rect) +{ + if (old_rect) + draw_xor_rect (screen, old_rect); + + if (new_rect) + draw_xor_rect (screen, new_rect); + + XFlush (screen->display->xdisplay); +} + +void +meta_effects_end_wireframe (MetaScreen *screen, + const MetaRectangle *old_rect) +{ + meta_effects_update_wireframe (screen, old_rect, NULL); + + meta_display_ungrab (screen->display); + meta_ui_pop_delay_exposes (screen->ui); +} diff --git a/src/effects.h b/src/effects.h index 744ffc12e..82dc0c518 100644 --- a/src/effects.h +++ b/src/effects.h @@ -41,4 +41,12 @@ void meta_effects_draw_box_animation (MetaScreen *screen, double seconds_duration, MetaBoxAnimType anim_type); +void meta_effects_begin_wireframe (MetaScreen *screen, + const MetaRectangle *rect); +void meta_effects_update_wireframe (MetaScreen *screen, + const MetaRectangle *old_rect, + const MetaRectangle *new_rect); +void meta_effects_end_wireframe (MetaScreen *screen, + const MetaRectangle *old_rect); + #endif /* META_EFFECTS_H */ diff --git a/src/frames.c b/src/frames.c index a99c13aa4..3086837ef 100644 --- a/src/frames.c +++ b/src/frames.c @@ -2110,6 +2110,13 @@ get_control (MetaFrames *frames, void meta_frames_push_delay_exposes (MetaFrames *frames) { + if (frames->expose_delay_count == 0) + { + /* Make sure we've repainted things */ + gdk_window_process_all_updates (); + XFlush (gdk_display); + } + frames->expose_delay_count += 1; } diff --git a/src/keybindings.c b/src/keybindings.c index 2d91fe2c5..3c50d390f 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -27,6 +27,7 @@ #include "frame.h" #include "place.h" #include "prefs.h" +#include "effects.h" #include <X11/keysym.h> #include <string.h> @@ -1693,10 +1694,24 @@ process_keyboard_move_grab (MetaDisplay *display, if (is_modifier (display, event->xkey.keycode)) return TRUE; - meta_window_get_position (window, &x, &y); + if (display->grab_wireframe_active) + { + x = display->grab_wireframe_rect.x; + y = display->grab_wireframe_rect.y; + } + else + { + meta_window_get_position (window, &x, &y); + } + /* FIXME in wireframe mode the edge snapping is all fucked up + * since the edge-find routines use window->rect. Window + * constraints are also broken with wireframe. + */ smart_snap = (event->xkey.state & ShiftMask) != 0; - + if (display->grab_wireframe_active) + smart_snap = FALSE; + #define SMALL_INCREMENT 1 #define NORMAL_INCREMENT 10 @@ -1709,13 +1724,18 @@ process_keyboard_move_grab (MetaDisplay *display, if (keysym == XK_Escape) { - /* End move and restore to original position */ + /* End resize and restore to original state. + * The move_resize is only needed when !wireframe + * since in wireframe we always moveresize at the end + * of the grab only. + */ meta_window_move_resize (display->grab_window, TRUE, display->grab_initial_window_pos.x, display->grab_initial_window_pos.y, display->grab_initial_window_pos.width, display->grab_initial_window_pos.height); + display->grab_was_cancelled = TRUE; } /* When moving by increments, we still snap to edges if the move @@ -1729,11 +1749,14 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_KP_Prior: case XK_Up: case XK_KP_Up: - edge = meta_window_find_next_horizontal_edge (window, FALSE); y -= incr; - - if (smart_snap || ((edge > y) && ABS (edge - y) < incr)) - y = edge; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_horizontal_edge (window, FALSE); + if (smart_snap || ((edge > y) && ABS (edge - y) < incr)) + y = edge; + } handled = TRUE; break; @@ -1741,11 +1764,14 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_KP_Next: case XK_Down: case XK_KP_Down: - edge = meta_window_find_next_horizontal_edge (window, TRUE); y += incr; - if (smart_snap || ((edge < y) && ABS (edge - y) < incr)) - y = edge; + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_horizontal_edge (window, TRUE); + if (smart_snap || ((edge < y) && ABS (edge - y) < incr)) + y = edge; + } handled = TRUE; break; @@ -1757,11 +1783,14 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_KP_End: case XK_Left: case XK_KP_Left: - edge = meta_window_find_next_vertical_edge (window, FALSE); x -= incr; - - if (smart_snap || ((edge > x) && ABS (edge - x) < incr)) - x = edge; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_vertical_edge (window, FALSE); + if (smart_snap || ((edge > x) && ABS (edge - x) < incr)) + x = edge; + } handled = TRUE; break; @@ -1769,18 +1798,43 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_KP_Next: case XK_Right: case XK_KP_Right: - edge = meta_window_find_next_vertical_edge (window, TRUE); x += incr; - if (smart_snap || ((edge < x) && ABS (edge - x) < incr)) - x = edge; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_vertical_edge (window, TRUE); + if (smart_snap || ((edge < x) && ABS (edge - x) < incr)) + x = edge; + } + handled = TRUE; break; } if (handled) { - meta_window_move (window, TRUE, x, y); - meta_window_warp_pointer (window, display->grab_op); + meta_topic (META_DEBUG_KEYBINDINGS, + "Computed new window location %d,%d due to keypress\n", + x, y); + if (display->grab_wireframe_active) + { + MetaRectangle new_xor; + + new_xor = display->grab_wireframe_rect; + new_xor.x = x; + new_xor.y = y; + + meta_effects_update_wireframe (window->screen, + &display->grab_wireframe_rect, + &new_xor); + display->grab_wireframe_rect = new_xor; + } + else + { + meta_window_move (window, TRUE, x, y); + } + + meta_window_update_keyboard_move (window); } return handled; @@ -1815,13 +1869,18 @@ process_keyboard_resize_grab (MetaDisplay *display, if (keysym == XK_Escape) { - /* End resize and restore to original state */ + /* End resize and restore to original state. + * The move_resize is only needed when !wireframe + * since in wireframe we always moveresize at the end + * of the grab only. + */ meta_window_move_resize (display->grab_window, TRUE, display->grab_initial_window_pos.x, display->grab_initial_window_pos.y, display->grab_initial_window_pos.width, display->grab_initial_window_pos.height); + display->grab_was_cancelled = TRUE; return FALSE; } @@ -1931,20 +1990,38 @@ process_keyboard_resize_grab (MetaDisplay *display, if (handled) { - meta_window_update_resize_grab_op (window, TRUE); + meta_window_update_keyboard_resize (window, TRUE); return TRUE; - } + } - meta_window_get_position (window, &orig_x, &orig_y); - x = orig_x; - y = orig_y; - width = window->rect.width; - height = window->rect.height; + if (display->grab_wireframe_active) + { + x = display->grab_wireframe_rect.x; + y = display->grab_wireframe_rect.y; + orig_x = x; + orig_y = y; + width = display->grab_wireframe_rect.width; + height = display->grab_wireframe_rect.height; + } + else + { + meta_window_get_position (window, &orig_x, &orig_y); + x = orig_x; + y = orig_y; + width = window->rect.width; + height = window->rect.height; + } gravity = meta_resize_gravity_from_grab_op (display->grab_op); - - smart_snap = (event->xkey.state & ShiftMask) != 0; + /* FIXME in wireframe mode the edge snapping is all fucked up + * since the edge-find routines use window->rect. Window + * constraints are also broken with wireframe. + */ + smart_snap = (event->xkey.state & ShiftMask) != 0; + if (display->grab_wireframe_active) + smart_snap = FALSE; + #define SMALL_INCREMENT 1 #define NORMAL_INCREMENT 10 @@ -1994,12 +2071,16 @@ process_keyboard_resize_grab (MetaDisplay *display, case NorthWestGravity: case NorthEastGravity: /* Move bottom edge up */ - edge = meta_window_find_next_horizontal_edge (window, TRUE); height -= height_inc; - if (smart_snap || ((edge > (y+height)) && - ABS (edge - (y+height)) < height_inc)) - height = edge - y; + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_horizontal_edge (window, TRUE); + + if (smart_snap || ((edge > (y+height)) && + ABS (edge - (y+height)) < height_inc)) + height = edge - y; + } handled = TRUE; break; @@ -2008,11 +2089,15 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthWestGravity: case SouthEastGravity: /* Move top edge up */ - edge = meta_window_find_next_horizontal_edge (window, FALSE); y -= height_inc; - - if (smart_snap || ((edge > y) && ABS (edge - y) < height_inc)) - y = edge; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_horizontal_edge (window, FALSE); + + if (smart_snap || ((edge > y) && ABS (edge - y) < height_inc)) + y = edge; + } height += (orig_y - y); break; @@ -2035,12 +2120,16 @@ process_keyboard_resize_grab (MetaDisplay *display, case NorthWestGravity: case NorthEastGravity: /* Move bottom edge down */ - edge = meta_window_find_next_horizontal_edge (window, TRUE); height += height_inc; - - if (smart_snap || ((edge < (y+height)) && - ABS (edge - (y+height)) < height_inc)) - height = edge - y; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_horizontal_edge (window, TRUE); + + if (smart_snap || ((edge < (y+height)) && + ABS (edge - (y+height)) < height_inc)) + height = edge - y; + } handled = TRUE; break; @@ -2049,11 +2138,15 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthWestGravity: case SouthEastGravity: /* Move top edge down */ - edge = meta_window_find_next_horizontal_edge (window, FALSE); y += height_inc; - - if (smart_snap || ((edge < y) && ABS (edge - y) < height_inc)) - y = edge; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_horizontal_edge (window, FALSE); + + if (smart_snap || ((edge < y) && ABS (edge - y) < height_inc)) + y = edge; + } height -= (y - orig_y); break; @@ -2076,11 +2169,15 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthEastGravity: case NorthEastGravity: /* Move left edge left */ - edge = meta_window_find_next_vertical_edge (window, TRUE); x -= width_inc; - if (smart_snap || ((edge > x) && ABS (edge - x) < width_inc)) - x = edge; + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_vertical_edge (window, TRUE); + + if (smart_snap || ((edge > x) && ABS (edge - x) < width_inc)) + x = edge; + } width += (orig_x - x); break; @@ -2089,12 +2186,16 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthWestGravity: case NorthWestGravity: /* Move right edge left */ - edge = meta_window_find_next_vertical_edge (window, FALSE); width -= width_inc; - if (smart_snap || ((edge > (x+width)) && - ABS (edge - (x+width)) < width_inc)) - width = edge - x; + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_vertical_edge (window, FALSE); + + if (smart_snap || ((edge > (x+width)) && + ABS (edge - (x+width)) < width_inc)) + width = edge - x; + } handled = TRUE; break; @@ -2117,11 +2218,15 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthEastGravity: case NorthEastGravity: /* Move left edge right */ - edge = meta_window_find_next_vertical_edge (window, FALSE); x += width_inc; - - if (smart_snap || ((edge < x) && ABS (edge - x) < width_inc)) - x = edge; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_vertical_edge (window, FALSE); + + if (smart_snap || ((edge < x) && ABS (edge - x) < width_inc)) + x = edge; + } width -= (x - orig_x); break; @@ -2130,12 +2235,16 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthWestGravity: case NorthWestGravity: /* Move right edge right */ - edge = meta_window_find_next_vertical_edge (window, TRUE); width += width_inc; - - if (smart_snap || ((edge > (x+width)) && - ABS (edge - (x+width)) < width_inc)) - width = edge - x; + + if (!display->grab_wireframe_active) + { + edge = meta_window_find_next_vertical_edge (window, TRUE); + + if (smart_snap || ((edge > (x+width)) && + ABS (edge - (x+width)) < width_inc)) + width = edge - x; + } handled = TRUE; break; @@ -2162,8 +2271,32 @@ process_keyboard_resize_grab (MetaDisplay *display, if (handled) { - meta_window_move_resize (window, TRUE, x, y, width, height); - meta_window_update_resize_grab_op (window, FALSE); + meta_topic (META_DEBUG_KEYBINDINGS, + "Computed new window location %d,%d %dx%d due to keypress\n", + x, y, width, height); + + if (display->grab_wireframe_active) + { + MetaRectangle new_xor; + + new_xor.x = x; + new_xor.y = y; + new_xor.width = width; + new_xor.height = height; + + meta_effects_update_wireframe (window->screen, + &window->display->grab_wireframe_rect, + &new_xor); + window->display->grab_wireframe_rect = new_xor; + + /* do this after drawing the wires, so we don't draw over it */ + meta_window_refresh_resize_popup (window); + } + else + { + meta_window_move_resize (window, TRUE, x, y, width, height); + } + meta_window_update_keyboard_resize (window, FALSE); } return handled; diff --git a/src/metacity.schemas.in b/src/metacity.schemas.in index 4350b67a4..5cf9f103d 100644 --- a/src/metacity.schemas.in +++ b/src/metacity.schemas.in @@ -257,6 +257,25 @@ </locale> </schema> + <schema> + <key>/schemas/apps/metacity/general/reduced_resources</key> + <applyto>/apps/metacity/general/reduced_resources</applyto> + <owner>metacity</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>If true, trade off usability for less resource usage</short> + <long> + If true, metacity will give the user less feedback and + less sense of "direct manipulation", by using wireframes, + avoiding animations, or other means. This is a significant + reduction in usability for many users, but may allow + legacy applications and terminal servers to function + when they would otherwise be impractical. + </long> + </locale> + </schema> + <!-- Window Keybindings --> <schema> diff --git a/src/prefs.c b/src/prefs.c index 9ed41bcd2..81af51e3e 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -51,6 +51,7 @@ #define KEY_APPLICATION_BASED "/apps/metacity/general/application_based" #define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds" #define KEY_BUTTON_LAYOUT "/apps/metacity/general/button_layout" +#define KEY_REDUCED_RESOURCES "/apps/metacity/general/reduced_resources" #define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_" #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings" @@ -83,6 +84,8 @@ static gboolean auto_raise = FALSE; static gboolean auto_raise_delay = 500; static gboolean provide_visual_bell = TRUE; static gboolean bell_is_audible = TRUE; +static gboolean reduced_resources = FALSE; + static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_INVALID; static MetaButtonLayout button_layout = { { @@ -129,6 +132,7 @@ static gboolean update_command (const char *name, const char *value); static gboolean update_workspace_name (const char *name, const char *value); +static gboolean update_reduced_resources (gboolean value); static void change_notify (GConfClient *client, guint cnxn_id, @@ -372,7 +376,6 @@ meta_prefs_init (void) cleanup_error (&err); update_button_layout (str_val); g_free (str_val); -#endif /* HAVE_GCONF */ bool_val = gconf_client_get_bool (default_client, KEY_VISUAL_BELL, &err); @@ -388,6 +391,12 @@ meta_prefs_init (void) update_visual_bell_type (str_val); g_free (str_val); + bool_val = gconf_client_get_bool (default_client, KEY_REDUCED_RESOURCES, + &err); + cleanup_error (&err); + update_reduced_resources (bool_val); +#endif /* HAVE_GCONF */ + /* Load keybindings prefs */ init_bindings (); @@ -733,6 +742,22 @@ change_notify (GConfClient *client, if (update_visual_bell_type (str)) queue_changed (META_PREF_VISUAL_BELL_TYPE); } + else if (strcmp (key, KEY_REDUCED_RESOURCES) == 0) + { + gboolean b; + + if (value && value->type != GCONF_VALUE_BOOL) + { + meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), + KEY_REDUCED_RESOURCES); + goto out; + } + + b = value ? gconf_value_get_bool (value) : reduced_resources; + + if (update_reduced_resources (b)) + queue_changed (META_PREF_REDUCED_RESOURCES); + } else { meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n", @@ -1239,6 +1264,16 @@ update_auto_raise_delay (int value) return old != auto_raise_delay; } + +static gboolean +update_reduced_resources (gboolean value) +{ + gboolean old = reduced_resources; + + reduced_resources = value; + + return old != reduced_resources; +} #endif /* HAVE_GCONF */ #ifdef WITH_VERBOSE_MODE @@ -1305,6 +1340,10 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_VISUAL_BELL_TYPE: return "VISUAL_BELL_TYPE"; break; + + case META_PREF_REDUCED_RESOURCES: + return "REDUCED_RESOURCES"; + break; } return "(unknown)"; @@ -1974,6 +2013,12 @@ meta_prefs_get_auto_raise_delay () return auto_raise_delay; } +gboolean +meta_prefs_get_reduced_resources () +{ + return reduced_resources; +} + MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name) { diff --git a/src/prefs.h b/src/prefs.h index 18a20df3f..c0a0bc667 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -45,7 +45,8 @@ typedef enum META_PREF_WORKSPACE_NAMES, META_PREF_VISUAL_BELL, META_PREF_AUDIBLE_BELL, - META_PREF_VISUAL_BELL_TYPE + META_PREF_VISUAL_BELL_TYPE, + META_PREF_REDUCED_RESOURCES } MetaPreference; typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, @@ -69,6 +70,7 @@ gboolean meta_prefs_get_application_based (void); gboolean meta_prefs_get_disable_workarounds (void); gboolean meta_prefs_get_auto_raise (void); int meta_prefs_get_auto_raise_delay (void); +gboolean meta_prefs_get_reduced_resources (void); const char* meta_prefs_get_command (int i); diff --git a/src/run-metacity.sh b/src/run-metacity.sh index 98ccbf74b..e0d9265ab 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -1,11 +1,11 @@ #! /bin/bash if test -z "$XNEST_DISPLAY"; then - XNEST_DISPLAY=:1 + XNEST_DISPLAY=:8 fi if test -z "$CLIENT_DISPLAY"; then - CLIENT_DISPLAY=:1 + CLIENT_DISPLAY=:8 fi if test -z "$METACITY_DISPLAY"; then diff --git a/src/screen.c b/src/screen.c index 348d467bb..18647d3a5 100644 --- a/src/screen.c +++ b/src/screen.c @@ -538,10 +538,23 @@ meta_screen_new (MetaDisplay *display, screen->starting_corner = META_SCREEN_TOPLEFT; screen->showing_desktop = FALSE; + + { + XGCValues gc_values; + + gc_values.subwindow_mode = IncludeInferiors; + gc_values.function = GXinvert; + gc_values.line_width = META_WIREFRAME_XOR_LINE_WIDTH; + + screen->root_xor_gc = XCreateGC (screen->display->xdisplay, + screen->xroot, + GCSubwindowMode | GCFunction | GCLineWidth, + &gc_values); + } screen->xinerama_infos = NULL; screen->n_xinerama_infos = 0; - screen->last_xinerama_index = 0; + screen->last_xinerama_index = 0; reload_xinerama_infos (screen); @@ -679,6 +692,9 @@ meta_screen_free (MetaScreen *screen) if (screen->work_area_idle != 0) g_source_remove (screen->work_area_idle); + + XFreeGC (screen->display->xdisplay, + screen->root_xor_gc); g_free (screen->screen_name); g_free (screen); diff --git a/src/screen.h b/src/screen.h index 64fa4948c..24b29ab7e 100644 --- a/src/screen.h +++ b/src/screen.h @@ -56,6 +56,8 @@ typedef enum META_SCREEN_RIGHT } MetaScreenDirection; +#define META_WIREFRAME_XOR_LINE_WIDTH 5 + struct _MetaScreen { MetaDisplay *display; @@ -108,6 +110,9 @@ struct _MetaScreen guint showing_desktop : 1; int closing; + + /* gc for XOR on root window */ + GC root_xor_gc; }; MetaScreen* meta_screen_new (MetaDisplay *display, diff --git a/src/window.c b/src/window.c index 9bb5b3e5c..edddc27e2 100644 --- a/src/window.c +++ b/src/window.c @@ -1206,6 +1206,14 @@ window_should_be_showing (MetaWindow *window) showing = FALSE; } +#if 0 + /* 5. See if we're drawing wireframe + */ + if (window->display->grab_window == window && + window->display->grab_wireframe_active) + showing = FALSE; +#endif + return showing; } @@ -1230,7 +1238,8 @@ implement_showing (MetaWindow *window, * if we are mapped now, we are supposed to * be minimized, and we are on the current workspace. */ - if (on_workspace && window->minimized && window->mapped) + if (on_workspace && window->minimized && window->mapped && + !meta_prefs_get_reduced_resources ()) { MetaRectangle icon_rect, window_rect; gboolean result; @@ -1856,7 +1865,7 @@ meta_window_unmaximize (MetaWindow *window) if (meta_grab_op_is_moving (window->display->grab_op) && window->display->grab_window == window) { - window->display->grab_initial_window_pos = window->saved_rect; + window->display->grab_anchor_window_pos = window->saved_rect; } meta_window_move_resize (window, @@ -5620,7 +5629,7 @@ check_moveresize_frequency (MetaWindow *window) window->display->grab_last_moveresize_time = current_time; meta_topic (META_DEBUG_RESIZING, - " Doing move/resize now (%g of %g seconds elapsed)\n", + " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)\n", elapsed / 1000.0, 1.0 / max_resizes_per_second); return TRUE; @@ -5639,12 +5648,20 @@ update_move (MetaWindow *window, window->display->grab_latest_motion_x = x; window->display->grab_latest_motion_y = y; - dx = x - window->display->grab_initial_root_x; - dy = y - window->display->grab_initial_root_y; + dx = x - window->display->grab_anchor_root_x; + dy = y - window->display->grab_anchor_root_y; - new_x = window->display->grab_initial_window_pos.x + dx; - new_y = window->display->grab_initial_window_pos.y + dy; + new_x = window->display->grab_anchor_window_pos.x + dx; + new_y = window->display->grab_anchor_window_pos.y + dy; + meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d\n", + x, y, + window->display->grab_anchor_root_x, + window->display->grab_anchor_root_y, + window->display->grab_anchor_window_pos.x, + window->display->grab_anchor_window_pos.y, + dx, dy); + /* shake loose (unmaximize) maximized window if dragged beyond the threshold * in the Y direction. You can't pull a window loose via X motion. */ @@ -5733,14 +5750,33 @@ update_move (MetaWindow *window, if (window->maximized) return; - if (mask & ShiftMask) + if (window->display->grab_wireframe_active) { - /* snap to edges */ - new_x = meta_window_find_nearest_vertical_edge (window, new_x); - new_y = meta_window_find_nearest_horizontal_edge (window, new_y); - } + /* FIXME Horribly broken, does not honor position + * constraints + */ + MetaRectangle new_xor; + new_xor = window->display->grab_wireframe_rect; + new_xor.x = new_x; + new_xor.y = new_y; - meta_window_move (window, TRUE, new_x, new_y); + meta_effects_update_wireframe (window->screen, + &window->display->grab_wireframe_rect, + &new_xor); + window->display->grab_wireframe_rect = new_xor; + } + else + { + /* FIXME, edge snapping broken in wireframe mode */ + if (mask & ShiftMask) + { + /* snap to edges */ + new_x = meta_window_find_nearest_vertical_edge (window, new_x); + new_y = meta_window_find_nearest_horizontal_edge (window, new_y); + } + + meta_window_move (window, TRUE, new_x, new_y); + } } static void @@ -5751,16 +5787,21 @@ update_resize (MetaWindow *window, int new_w, new_h; int gravity; MetaRectangle old; + int new_x, new_y; window->display->grab_latest_motion_x = x; window->display->grab_latest_motion_y = y; - dx = x - window->display->grab_initial_root_x; - dy = y - window->display->grab_initial_root_y; + dx = x - window->display->grab_anchor_root_x; + dy = y - window->display->grab_anchor_root_y; - new_w = window->display->grab_initial_window_pos.width; - new_h = window->display->grab_initial_window_pos.height; + new_w = window->display->grab_anchor_window_pos.width; + new_h = window->display->grab_anchor_window_pos.height; + /* FIXME this is only used in wireframe mode */ + new_x = window->display->grab_anchor_window_pos.x; + new_y = window->display->grab_anchor_window_pos.y; + switch (window->display->grab_op) { case META_GRAB_OP_RESIZING_SE: @@ -5779,6 +5820,7 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_SW: case META_GRAB_OP_KEYBOARD_RESIZING_W: new_w -= dx; + new_x += dx; break; default: @@ -5803,6 +5845,7 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_NE: case META_GRAB_OP_KEYBOARD_RESIZING_NW: new_h -= dy; + new_y += dy; break; default: break; @@ -5812,12 +5855,42 @@ update_resize (MetaWindow *window, return; old = window->rect; - + /* compute gravity of client during operation */ gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); g_assert (gravity >= 0); - meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); + if (window->display->grab_wireframe_active) + { + /* FIXME This is crap. For example, the wireframe isn't + * constrained in the way that a real resize would be. An + * obvious elegant solution is to unmap the window during + * wireframe, but still resize it; however, that probably + * confuses broken clients that have problems with opaque + * resize, they probably don't track their visibility. + */ + MetaRectangle new_xor; + + if ((new_x + new_w <= new_x) || (new_y + new_h <= new_y)) + return; + + new_xor.x = new_x; + new_xor.y = new_y; + new_xor.width = new_w; + new_xor.height = new_h; + + meta_effects_update_wireframe (window->screen, + &window->display->grab_wireframe_rect, + &new_xor); + window->display->grab_wireframe_rect = new_xor; + + /* do this after drawing the wires, so we don't draw over it */ + meta_window_refresh_resize_popup (window); + } + else + { + meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); + } /* If we don't actually resize the window, we clear the timestamp, * so we'll quickly try again. Otherwise you get "stuck" because @@ -6219,6 +6292,13 @@ meta_window_refresh_resize_popup (MetaWindow *window) if (window->display->grab_window != window) return; + /* FIXME for now we bail out when doing wireframe, because our + * server grab keeps us from being able to redraw the stuff + * underneath the resize popup. + */ + if (window->display->grab_wireframe_active) + return; + switch (window->display->grab_op) { case META_GRAB_OP_RESIZING_SE: @@ -6257,7 +6337,7 @@ meta_window_refresh_resize_popup (MetaWindow *window) if (window->display->grab_resize_popup != NULL) { int gravity; - int x, y; + int x, y, width, height; MetaFrameGeometry fgeom; if (window->frame) @@ -6273,13 +6353,24 @@ meta_window_refresh_resize_popup (MetaWindow *window) gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); g_assert (gravity >= 0); - meta_window_get_position (window, &x, &y); + if (window->display->grab_wireframe_active) + { + x = window->display->grab_wireframe_rect.x; + y = window->display->grab_wireframe_rect.y; + width = window->display->grab_wireframe_rect.width; + height = window->display->grab_wireframe_rect.height; + } + else + { + meta_window_get_position (window, &x, &y); + width = window->rect.width; + height = window->rect.height; + } meta_ui_resize_popup_set (window->display->grab_resize_popup, gravity, x, y, - window->rect.width, - window->rect.height, + width, height, window->size_hints.base_width, window->size_hints.base_height, window->size_hints.min_width, @@ -6406,53 +6497,70 @@ meta_window_is_ancestor_of_transient (MetaWindow *window, return d.found; } +/* Warp pointer to location appropriate for grab, + * return root coordinates where pointer ended up. + */ static gboolean -warp_pointer (MetaWindow *window, - MetaGrabOp grab_op, - int *x, - int *y) +warp_grab_pointer (MetaWindow *window, + MetaGrabOp grab_op, + int *x, + int *y) { + MetaRectangle rect; + + /* We may not have done begin_grab_op yet, i.e. may not be in a grab + */ + + if (window == window->display->grab_window && + window->display->grab_wireframe_active) + rect = window->display->grab_wireframe_rect; + else + { + rect = window->rect; + meta_window_get_position (window, &rect.x, &rect.y); + } + switch (grab_op) { case META_GRAB_OP_KEYBOARD_MOVING: case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - *x = window->rect.width / 2; - *y = window->rect.height / 2; + *x = rect.width / 2; + *y = rect.height / 2; break; case META_GRAB_OP_KEYBOARD_RESIZING_S: - *x = window->rect.width / 2; - *y = window->rect.height; + *x = rect.width / 2; + *y = rect.height; break; case META_GRAB_OP_KEYBOARD_RESIZING_N: - *x = window->rect.width / 2; + *x = rect.width / 2; *y = 0; break; case META_GRAB_OP_KEYBOARD_RESIZING_W: *x = 0; - *y = window->rect.height / 2; + *y = rect.height / 2; break; case META_GRAB_OP_KEYBOARD_RESIZING_E: - *x = window->rect.width; - *y = window->rect.height / 2; + *x = rect.width; + *y = rect.height / 2; break; case META_GRAB_OP_KEYBOARD_RESIZING_SE: - *x = window->rect.width; - *y = window->rect.height; + *x = rect.width; + *y = rect.height; break; case META_GRAB_OP_KEYBOARD_RESIZING_NE: - *x = window->rect.width; + *x = rect.width; *y = 0; break; case META_GRAB_OP_KEYBOARD_RESIZING_SW: *x = 0; - *y = window->rect.height; + *y = rect.height; break; case META_GRAB_OP_KEYBOARD_RESIZING_NW: @@ -6464,45 +6572,45 @@ warp_pointer (MetaWindow *window, return FALSE; } + *x += rect.x; + *y += rect.y; + meta_error_trap_push_with_return (window->display); + + meta_topic (META_DEBUG_WINDOW_OPS, + "Warping pointer to %d,%d with window at %d,%d\n", + *x, *y, rect.x, rect.y); XWarpPointer (window->display->xdisplay, None, - window->xwindow, + window->screen->xroot, 0, 0, 0, 0, - *x, - *y); + *x, *y); if (meta_error_trap_pop_with_return (window->display, FALSE) != Success) { - meta_verbose ("Failed to warp pointer for window %s\n", window->desc); + meta_verbose ("Failed to warp pointer for window %s\n", + window->desc); return FALSE; } - + return TRUE; } -gboolean -meta_window_warp_pointer (MetaWindow *window, - MetaGrabOp grab_op) -{ - int x, y; - - return warp_pointer (window, grab_op, &x, &y); -} - void meta_window_begin_grab_op (MetaWindow *window, MetaGrabOp op, Time timestamp) { - int x, y, x_offset, y_offset; - - meta_window_get_position (window, &x, &y); + int x, y; + gulong grab_start_serial; + grab_start_serial = XNextRequest (window->display->xdisplay); + meta_window_raise (window); - warp_pointer (window, op, &x_offset, &y_offset); + warp_grab_pointer (window, + op, &x, &y); meta_display_begin_grab_op (window->display, window->screen, @@ -6510,31 +6618,50 @@ meta_window_begin_grab_op (MetaWindow *window, op, FALSE, 0, 0, timestamp, - x + x_offset, - y + y_offset); + x, y); + + /* We override the one set in display_begin_grab_op since we + * did additional stuff as part of the grabbing process + */ + window->display->grab_start_serial = grab_start_serial; } void -meta_window_update_resize_grab_op (MetaWindow *window, - gboolean update_cursor) +meta_window_update_keyboard_resize (MetaWindow *window, + gboolean update_cursor) { - int x, y, x_offset, y_offset; - - meta_window_get_position (window, &x, &y); + int x, y; - warp_pointer (window, window->display->grab_op, &x_offset, &y_offset); + warp_grab_pointer (window, + window->display->grab_op, + &x, &y); - /* As we warped the pointer, we have to reset the apparent - * initial window state, since if the mouse moves we want - * to use those events to do the right thing. - */ - if (window->display->grab_window == window) - { - window->display->grab_initial_root_x = x + x_offset; - window->display->grab_initial_root_y = y + y_offset; - - window->display->grab_initial_window_pos = window->rect; - } + { + /* As we warped the pointer, we have to reset the anchor state, + * since if the mouse moves we want to use those events to do the + * right thing. Also, this means that the motion notify + * from the pointer warp comes back as a no-op. + */ + int dx, dy; + + dx = x - window->display->grab_anchor_root_x; + dy = y - window->display->grab_anchor_root_y; + + window->display->grab_anchor_root_x += dx; + window->display->grab_anchor_root_y += dy; + if (window->display->grab_wireframe_active) + { + window->display->grab_anchor_window_pos = + window->display->grab_wireframe_rect; + } + else + { + window->display->grab_anchor_window_pos = window->rect; + meta_window_get_position (window, + &window->display->grab_anchor_window_pos.x, + &window->display->grab_anchor_window_pos.y); + } + } if (update_cursor) { @@ -6547,6 +6674,16 @@ meta_window_update_resize_grab_op (MetaWindow *window, } } +void +meta_window_update_keyboard_move (MetaWindow *window) +{ + int x, y; + + warp_grab_pointer (window, + window->display->grab_op, + &x, &y); +} + void meta_window_update_layer (MetaWindow *window) { diff --git a/src/window.h b/src/window.h index 3b36872e8..91f3711c3 100644 --- a/src/window.h +++ b/src/window.h @@ -469,15 +469,13 @@ void meta_window_foreach_ancestor (MetaWindow *window, MetaWindowForeachFunc func, void *data); -gboolean meta_window_warp_pointer (MetaWindow *window, - MetaGrabOp grab_op); - void meta_window_begin_grab_op (MetaWindow *window, MetaGrabOp op, Time timestamp); -void meta_window_update_resize_grab_op (MetaWindow *window, - gboolean update_cursor); +void meta_window_update_keyboard_resize (MetaWindow *window, + gboolean update_cursor); +void meta_window_update_keyboard_move (MetaWindow *window); void meta_window_update_layer (MetaWindow *window);