diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/display.c | 4 | ||||
-rw-r--r-- | src/display.h | 1 | ||||
-rw-r--r-- | src/effects.c | 124 | ||||
-rw-r--r-- | src/effects.h | 37 | ||||
-rw-r--r-- | src/window.c | 93 |
7 files changed, 266 insertions, 9 deletions
@@ -1,3 +1,17 @@ +2001-08-05 Anders Carlsson <andersca@gnu.org> + + * src/display.h, src/display.c: Add _NET_WM_ICON_GEOMETRY atom. + + * src/window.c (meta_window_calc_showing): See if the window has + an icon geometry and show a morphing animation from the window's + coordinates to the icon's coordinates. + (meta_window_get_icon_geometry): New function that fetches a + window's icon geometry. + + * src/Makefile.am: Add effects.[ch]. + + * src/effects.c: New file with cool effects. + 2001-08-03 Havoc Pennington <hp@pobox.com> * src/keybindings.c: Add Alt + left/right arrow to diff --git a/src/Makefile.am b/src/Makefile.am index dbd3e163..bec595fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,8 @@ metacity_SOURCES= \ core.h \ display.c \ display.h \ + effects.c \ + effects.h \ errors.c \ errors.h \ eventqueue.c \ diff --git a/src/display.c b/src/display.c index ccc82e85..66916215 100644 --- a/src/display.c +++ b/src/display.c @@ -130,7 +130,8 @@ meta_display_open (const char *name) "_WIN_PROTOCOLS", "_WIN_SUPPORTING_WM_CHECK", "_NET_WM_ICON_NAME", - "_NET_WM_ICON" + "_NET_WM_ICON", + "_NET_WM_ICON_GEOMETRY" }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -212,6 +213,7 @@ meta_display_open (const char *name) display->atom_win_supporting_wm_check = atoms[35]; display->atom_net_wm_icon_name = atoms[36]; display->atom_net_wm_icon = atoms[37]; + display->atom_net_wm_icon_geometry = atoms[38]; /* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK, * created in screen_new diff --git a/src/display.h b/src/display.h index c04d9654..df8dd291 100644 --- a/src/display.h +++ b/src/display.h @@ -95,6 +95,7 @@ struct _MetaDisplay Atom atom_win_supporting_wm_check; Atom atom_net_wm_icon_name; Atom atom_net_wm_icon; + Atom atom_net_wm_icon_geometry; /* This is the actual window from focus events, * not the one we last set diff --git a/src/effects.c b/src/effects.c new file mode 100644 index 00000000..b5d7150b --- /dev/null +++ b/src/effects.c @@ -0,0 +1,124 @@ +/* Metacity animation effects */ + +/* + * Copyright (C) 2001 Anders Carlsson, Havoc Pennington + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "effects.h" +#include "display.h" + +typedef struct +{ + MetaScreen *screen; + + GC gc; + + int step; + int steps; + + double current_x, current_y; + double current_width, current_height; + + double delta_x, delta_y; + double delta_width, delta_height; +} BoxAnimationContext; + +static gboolean +effects_draw_box_animation_timeout (BoxAnimationContext *context) +{ + if (context->step == 0) + { + /* It's our first time, grab the X server */ + meta_display_grab (context->screen->display); + } + else + { + /* Restore the previously drawn background */ + XDrawRectangle (context->screen->display->xdisplay, + context->screen->xroot, + context->gc, + context->current_x, context->current_y, + context->current_width, context->current_height); + } + + /* Return if we're done */ + if (context->step == context->steps) + { + meta_display_ungrab (context->screen->display); + XFreeGC (context->screen->display->xdisplay, + context->gc); + g_free (context); + return FALSE; + } + + context->current_x += context->delta_x; + context->current_y += context->delta_y; + context->current_width += context->delta_width; + context->current_height += context->delta_height; + + /* Draw the rectangle */ + XDrawRectangle (context->screen->display->xdisplay, + context->screen->xroot, + context->gc, + context->current_x, context->current_y, + context->current_width, context->current_height); + + context->step += 1; + + return TRUE; +} + +void +meta_effects_draw_box_animation (MetaScreen *screen, + MetaRectangle *initial_rect, + MetaRectangle *destination_rect, + int steps, + int delay) +{ + BoxAnimationContext *context; + XGCValues gc_values; + + /* Create the animation context */ + context = g_new (BoxAnimationContext, 1); + + gc_values.subwindow_mode = IncludeInferiors; + gc_values.function = GXinvert; + + /* Create a gc for the root window */ + context->screen = screen; + context->gc = XCreateGC (screen->display->xdisplay, + screen->xroot, + GCSubwindowMode | GCFunction, + &gc_values); + context->step = 0; + context->steps = steps; + context->delta_x = (destination_rect->x - initial_rect->x) / (double)steps; + context->delta_y = (destination_rect->y - initial_rect->y) / (double)steps; + context->delta_width = (destination_rect->width - initial_rect->width) / (double)steps; + context->delta_height = (destination_rect->height - initial_rect->height) / (double)steps; + + context->current_x = initial_rect->x; + context->current_y = initial_rect->y; + context->current_width = initial_rect->width; + context->current_height = initial_rect->height; + + /* Add the timeout */ + g_timeout_add (delay, + (GSourceFunc)effects_draw_box_animation_timeout, + context); +} diff --git a/src/effects.h b/src/effects.h new file mode 100644 index 00000000..d564103e --- /dev/null +++ b/src/effects.h @@ -0,0 +1,37 @@ +/* Metacity animation effects */ + +/* + * Copyright (C) 2001 Anders Carlsson, Havoc Pennington + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_EFFECTS_H +#define META_EFFECTS_H + +#include "util.h" +#include "screen.h" + +#define META_MINIMIZE_ANIMATION_STEPS 16 +#define META_MINIMIZE_ANIMATION_DELAY 20 + +void meta_effects_draw_box_animation (MetaScreen *screen, + MetaRectangle *initial_rect, + MetaRectangle *destination_rect, + int steps, + int delay); + +#endif /* META_EFFECTS_H */ diff --git a/src/window.c b/src/window.c index e13bbd40..917ddee0 100644 --- a/src/window.c +++ b/src/window.c @@ -1,7 +1,7 @@ /* Metacity X managed windows */ /* - * Copyright (C) 2001 Havoc Pennington + * Copyright (C) 2001 Havoc Pennington, Anders Carlsson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -29,6 +29,7 @@ #include "ui.h" #include "place.h" #include "session.h" +#include "effects.h" #include <X11/Xatom.h> @@ -70,6 +71,9 @@ static gboolean process_property_notify (MetaWindow *window, static void meta_window_show (MetaWindow *window); static void meta_window_hide (MetaWindow *window); +static gboolean meta_window_get_icon_geometry (MetaWindow *window, + MetaRectangle *rect); + static void adjust_for_gravity (MetaWindow *window, MetaFrameGeometry *fgeom, gboolean coords_assume_border, @@ -758,6 +762,41 @@ meta_window_calc_showing (MetaWindow *window) if (window->minimized || !on_workspace) { + /* Really this effects code should probably + * be in meta_window_hide so the window->mapped + * test isn't duplicated here. Anyhow, we animate + * 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) + { + MetaRectangle icon_rect, window_rect; + gboolean result; + + /* Check if the window has an icon geometry */ + result = meta_window_get_icon_geometry (window, &icon_rect); + + if (!result) + { + /* just animate into the corner somehow - maybe + * not a good idea... + */ + icon_rect.x = window->screen->width; + icon_rect.y = window->screen->height; + icon_rect.width = 1; + icon_rect.height = 1; + } + + meta_window_get_outer_rect (window, &window_rect); + + /* Draw a nice cool animation */ + meta_effects_draw_box_animation (window->screen, + &window_rect, + &icon_rect, + META_MINIMIZE_ANIMATION_STEPS, + META_MINIMIZE_ANIMATION_DELAY); + } + meta_window_hide (window); } else @@ -2668,7 +2707,7 @@ update_net_wm_state (MetaWindow *window) * clients don't change the property. */ Atom type; - gint format; + int format; gulong n_atoms; gulong bytes_after; Atom *atoms; @@ -2767,7 +2806,7 @@ update_mwm_hints (MetaWindow *window) { MotifWmHints *hints; Atom type; - gint format; + int format; gulong nitems; gulong bytes_after; int result; @@ -2884,6 +2923,44 @@ update_mwm_hints (MetaWindow *window) return Success; } +static gboolean +meta_window_get_icon_geometry (MetaWindow *window, + MetaRectangle *rect) +{ + Atom type; + int format; + gulong nitems; + gulong bytes_after; + gulong *geometry; + int result; + + meta_error_trap_push (window->display); + type = None; + XGetWindowProperty (window->display->xdisplay, + window->xwindow, + window->display->atom_net_wm_icon_geometry, + 0, G_MAXLONG, + False, XA_CARDINAL, &type, &format, &nitems, + &bytes_after, ((guchar **)&geometry)); + + result = meta_error_trap_pop (window->display); + + if (result != Success || type != XA_CARDINAL || nitems != 4) + return FALSE; + + if (rect) + { + rect->x = geometry[0]; + rect->y = geometry[1]; + rect->width = geometry[2]; + rect->height = geometry[3]; + } + + XFree (geometry); + + return TRUE; +} + static int update_wm_class (MetaWindow *window) { @@ -2933,7 +3010,7 @@ read_string_prop (MetaDisplay *display, char **strp) { Atom type; - gint format; + int format; gulong nitems; gulong bytes_after; guchar *str; @@ -2966,7 +3043,7 @@ read_client_leader (MetaDisplay *display, Window xwindow) { Atom type; - gint format; + int format; gulong nitems; gulong bytes_after; Window *leader; @@ -3094,7 +3171,7 @@ get_cardinal (MetaDisplay *display, gulong *val) { Atom type; - gint format; + int format; gulong nitems; gulong bytes_after; gulong *num; @@ -3137,7 +3214,7 @@ static int update_net_wm_type (MetaWindow *window) { Atom type; - gint format; + int format; gulong n_atoms; gulong bytes_after; Atom *atoms; @@ -3482,7 +3559,7 @@ constrain_size (MetaWindow *window, /* frame member variables should NEVER be used in here */ -#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) ) +#define FLOOR(value, base) ( ((int) ((value) / (base))) * (base) ) /* Get the allowed size ranges, considering maximized, etc. */ fullw = window->screen->active_workspace->workarea.width; |