mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
add opaque minimize/shade feature. The wireframe seemed kind of confusing
2001-08-06 Havoc Pennington <hp@pobox.com> * src/effects.c: add opaque minimize/shade feature. The wireframe seemed kind of confusing and unclear from a UI standpoint. I know, I know. The bloat begins here. Also, we don't need to grab the server during opaque min/shade, which has some nice implications. * src/ui.c: Add features to render a window with an image in it, and also wrap pixbuf_from_drawable * src/effects.c (meta_effects_draw_box_animation): modify to be smoother (at least theoretically) by syncing to current time and "dropping frames" as appropriate. * src/window.c (meta_window_shade): draw animation for shading too
This commit is contained in:
parent
d8561cb4c3
commit
11b14d327f
13
ChangeLog
13
ChangeLog
@ -1,10 +1,19 @@
|
|||||||
2001-08-06 Havoc Pennington <hp@pobox.com>
|
2001-08-06 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
|
* src/effects.c: add opaque minimize/shade feature. The wireframe
|
||||||
|
seemed kind of confusing and unclear from a UI standpoint.
|
||||||
|
I know, I know. The bloat begins here.
|
||||||
|
|
||||||
|
Also, we don't need to grab the server during opaque min/shade,
|
||||||
|
which has some nice implications.
|
||||||
|
|
||||||
|
* src/ui.c: Add features to render a window with an image in it,
|
||||||
|
and also wrap pixbuf_from_drawable
|
||||||
|
|
||||||
* src/effects.c (meta_effects_draw_box_animation):
|
* src/effects.c (meta_effects_draw_box_animation):
|
||||||
modify to be smoother (at least theoretically) by
|
modify to be smoother (at least theoretically) by
|
||||||
syncing to current time and "dropping frames"
|
syncing to current time and "dropping frames"
|
||||||
as appropriate. A precursor to flashier animations
|
as appropriate.
|
||||||
that take more CPU to do.
|
|
||||||
|
|
||||||
* src/window.c (meta_window_shade): draw animation
|
* src/window.c (meta_window_shade): draw animation
|
||||||
for shading too
|
for shading too
|
||||||
|
157
src/effects.c
157
src/effects.c
@ -21,12 +21,11 @@
|
|||||||
|
|
||||||
#include "effects.h"
|
#include "effects.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
|
|
||||||
GC gc;
|
|
||||||
|
|
||||||
double millisecs_duration;
|
double millisecs_duration;
|
||||||
GTimeVal start_time;
|
GTimeVal start_time;
|
||||||
@ -38,6 +37,18 @@ typedef struct
|
|||||||
|
|
||||||
/* rect to erase */
|
/* rect to erase */
|
||||||
MetaRectangle last_rect;
|
MetaRectangle last_rect;
|
||||||
|
|
||||||
|
/* used instead of the global flag, since
|
||||||
|
* we don't want to change midstream.
|
||||||
|
*/
|
||||||
|
gboolean use_opaque;
|
||||||
|
|
||||||
|
/* For wireframe */
|
||||||
|
GC gc;
|
||||||
|
|
||||||
|
/* For opaque */
|
||||||
|
MetaImageWindow *image_window;
|
||||||
|
GdkPixbuf *orig_pixbuf;
|
||||||
|
|
||||||
} BoxAnimationContext;
|
} BoxAnimationContext;
|
||||||
|
|
||||||
@ -51,12 +62,15 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
|||||||
|
|
||||||
if (!context->first_time)
|
if (!context->first_time)
|
||||||
{
|
{
|
||||||
/* Restore the previously drawn background */
|
if (!context->use_opaque)
|
||||||
XDrawRectangle (context->screen->display->xdisplay,
|
{
|
||||||
context->screen->xroot,
|
/* Restore the previously drawn background */
|
||||||
context->gc,
|
XDrawRectangle (context->screen->display->xdisplay,
|
||||||
context->last_rect.x, context->last_rect.y,
|
context->screen->xroot,
|
||||||
context->last_rect.width, context->last_rect.height);
|
context->gc,
|
||||||
|
context->last_rect.x, context->last_rect.y,
|
||||||
|
context->last_rect.width, context->last_rect.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context->first_time = FALSE;
|
context->first_time = FALSE;
|
||||||
@ -78,9 +92,18 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
|||||||
if (elapsed > context->millisecs_duration)
|
if (elapsed > context->millisecs_duration)
|
||||||
{
|
{
|
||||||
/* All done */
|
/* All done */
|
||||||
meta_display_ungrab (context->screen->display);
|
if (context->use_opaque)
|
||||||
XFreeGC (context->screen->display->xdisplay,
|
{
|
||||||
context->gc);
|
g_object_unref (G_OBJECT (context->orig_pixbuf));
|
||||||
|
meta_image_window_free (context->image_window);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_display_ungrab (context->screen->display);
|
||||||
|
XFreeGC (context->screen->display->xdisplay,
|
||||||
|
context->gc);
|
||||||
|
}
|
||||||
|
|
||||||
g_free (context);
|
g_free (context);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -96,24 +119,54 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
|||||||
draw_rect.width += (context->end_rect.width - context->start_rect.width) * fraction;
|
draw_rect.width += (context->end_rect.width - context->start_rect.width) * fraction;
|
||||||
draw_rect.height += (context->end_rect.height - context->start_rect.height) * fraction;
|
draw_rect.height += (context->end_rect.height - context->start_rect.height) * fraction;
|
||||||
|
|
||||||
/* don't confuse X with bogus rectangles */
|
/* don't confuse X or gdk-pixbuf with bogus rectangles */
|
||||||
if (draw_rect.width < 1)
|
if (draw_rect.width < 1)
|
||||||
draw_rect.width = 1;
|
draw_rect.width = 1;
|
||||||
if (draw_rect.height < 1)
|
if (draw_rect.height < 1)
|
||||||
draw_rect.height = 1;
|
draw_rect.height = 1;
|
||||||
|
|
||||||
context->last_rect = draw_rect;
|
context->last_rect = draw_rect;
|
||||||
|
|
||||||
/* Draw the rectangle */
|
|
||||||
XDrawRectangle (context->screen->display->xdisplay,
|
|
||||||
context->screen->xroot,
|
|
||||||
context->gc,
|
|
||||||
draw_rect.x, draw_rect.y,
|
|
||||||
draw_rect.width, draw_rect.height);
|
|
||||||
|
|
||||||
|
if (context->use_opaque)
|
||||||
|
{
|
||||||
|
GdkPixbuf *scaled;
|
||||||
|
|
||||||
|
scaled = gdk_pixbuf_scale_simple (context->orig_pixbuf,
|
||||||
|
draw_rect.width,
|
||||||
|
draw_rect.height,
|
||||||
|
GDK_INTERP_BILINEAR);
|
||||||
|
meta_image_window_set_image (context->image_window,
|
||||||
|
scaled);
|
||||||
|
meta_image_window_set_position (context->image_window,
|
||||||
|
draw_rect.x, draw_rect.y);
|
||||||
|
g_object_unref (G_OBJECT (scaled));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Draw the rectangle */
|
||||||
|
XDrawRectangle (context->screen->display->xdisplay,
|
||||||
|
context->screen->xroot,
|
||||||
|
context->gc,
|
||||||
|
draw_rect.x, draw_rect.y,
|
||||||
|
draw_rect.width, draw_rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* kick changes onto the server */
|
||||||
|
XFlush (context->screen->display->xdisplay);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* I really don't want this to be a configuration option,
|
||||||
|
* but I think the wireframe is sucky from a UI standpoint
|
||||||
|
* (more confusing than opaque), but the opaque is maybe
|
||||||
|
* too slow on some systems; so perhaps we could autodetect
|
||||||
|
* system beefiness or someting, or have some global
|
||||||
|
* "my system is slow" config option.
|
||||||
|
*/
|
||||||
|
static gboolean use_opaque_animations = TRUE;
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_effects_draw_box_animation (MetaScreen *screen,
|
meta_effects_draw_box_animation (MetaScreen *screen,
|
||||||
MetaRectangle *initial_rect,
|
MetaRectangle *initial_rect,
|
||||||
@ -121,7 +174,6 @@ meta_effects_draw_box_animation (MetaScreen *screen,
|
|||||||
double seconds_duration)
|
double seconds_duration)
|
||||||
{
|
{
|
||||||
BoxAnimationContext *context;
|
BoxAnimationContext *context;
|
||||||
XGCValues gc_values;
|
|
||||||
|
|
||||||
g_return_if_fail (seconds_duration > 0.0);
|
g_return_if_fail (seconds_duration > 0.0);
|
||||||
|
|
||||||
@ -129,26 +181,62 @@ meta_effects_draw_box_animation (MetaScreen *screen,
|
|||||||
seconds_duration *= 10; /* slow things down */
|
seconds_duration *= 10; /* slow things down */
|
||||||
|
|
||||||
/* Create the animation context */
|
/* Create the animation context */
|
||||||
context = g_new (BoxAnimationContext, 1);
|
context = g_new0 (BoxAnimationContext, 1);
|
||||||
|
|
||||||
gc_values.subwindow_mode = IncludeInferiors;
|
|
||||||
gc_values.function = GXinvert;
|
|
||||||
|
|
||||||
/* Create a gc for the root window */
|
|
||||||
context->screen = screen;
|
context->screen = screen;
|
||||||
context->gc = XCreateGC (screen->display->xdisplay,
|
|
||||||
screen->xroot,
|
|
||||||
GCSubwindowMode | GCFunction,
|
|
||||||
&gc_values);
|
|
||||||
|
|
||||||
context->millisecs_duration = seconds_duration * 1000.0;
|
context->millisecs_duration = seconds_duration * 1000.0;
|
||||||
g_get_current_time (&context->start_time);
|
g_get_current_time (&context->start_time);
|
||||||
context->first_time = TRUE;
|
context->first_time = TRUE;
|
||||||
context->start_rect = *initial_rect;
|
context->start_rect = *initial_rect;
|
||||||
context->end_rect = *destination_rect;
|
context->end_rect = *destination_rect;
|
||||||
|
|
||||||
/* Grab the X server to avoid screen dirt */
|
context->use_opaque = use_opaque_animations;
|
||||||
meta_display_grab (context->screen->display);
|
|
||||||
|
if (context->use_opaque)
|
||||||
|
{
|
||||||
|
GdkPixbuf *pix;
|
||||||
|
|
||||||
|
pix = meta_gdk_pixbuf_get_from_window (NULL,
|
||||||
|
screen->xroot,
|
||||||
|
initial_rect->x,
|
||||||
|
initial_rect->y,
|
||||||
|
0, 0,
|
||||||
|
initial_rect->width,
|
||||||
|
initial_rect->height);
|
||||||
|
|
||||||
|
if (pix == NULL)
|
||||||
|
{
|
||||||
|
/* Fall back to wireframe */
|
||||||
|
context->use_opaque = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context->image_window = meta_image_window_new ();
|
||||||
|
context->orig_pixbuf = pix;
|
||||||
|
meta_image_window_set_position (context->image_window,
|
||||||
|
initial_rect->x,
|
||||||
|
initial_rect->y);
|
||||||
|
meta_image_window_set_showing (context->image_window, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not an else, so that fallback works */
|
||||||
|
if (!context->use_opaque)
|
||||||
|
{
|
||||||
|
XGCValues gc_values;
|
||||||
|
|
||||||
|
gc_values.subwindow_mode = IncludeInferiors;
|
||||||
|
gc_values.function = GXinvert;
|
||||||
|
|
||||||
|
context->gc = XCreateGC (screen->display->xdisplay,
|
||||||
|
screen->xroot,
|
||||||
|
GCSubwindowMode | GCFunction,
|
||||||
|
&gc_values);
|
||||||
|
|
||||||
|
/* Grab the X server to avoid screen dirt */
|
||||||
|
meta_display_grab (context->screen->display);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add the timeout - a short one, could even use an idle,
|
/* Add the timeout - a short one, could even use an idle,
|
||||||
* but this is maybe more CPU-friendly.
|
* but this is maybe more CPU-friendly.
|
||||||
@ -157,3 +245,6 @@ meta_effects_draw_box_animation (MetaScreen *screen,
|
|||||||
(GSourceFunc)effects_draw_box_animation_timeout,
|
(GSourceFunc)effects_draw_box_animation_timeout,
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
#define META_MINIMIZE_ANIMATION_LENGTH 0.3
|
#define META_MINIMIZE_ANIMATION_LENGTH 0.5
|
||||||
#define META_SHADE_ANIMATION_LENGTH 0.15
|
#define META_SHADE_ANIMATION_LENGTH 0.2
|
||||||
|
|
||||||
void meta_effects_draw_box_animation (MetaScreen *screen,
|
void meta_effects_draw_box_animation (MetaScreen *screen,
|
||||||
MetaRectangle *initial_rect,
|
MetaRectangle *initial_rect,
|
||||||
|
91
src/ui.c
91
src/ui.c
@ -232,3 +232,94 @@ meta_ui_window_menu_free (MetaWindowMenu *menu)
|
|||||||
meta_window_menu_free (menu);
|
meta_window_menu_free (menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct _MetaImageWindow
|
||||||
|
{
|
||||||
|
GtkWidget *window;
|
||||||
|
GtkWidget *image;
|
||||||
|
};
|
||||||
|
|
||||||
|
MetaImageWindow*
|
||||||
|
meta_image_window_new (void)
|
||||||
|
{
|
||||||
|
MetaImageWindow *iw;
|
||||||
|
|
||||||
|
iw = g_new (MetaImageWindow, 1);
|
||||||
|
iw->window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||||
|
iw->image = g_object_new (GTK_TYPE_IMAGE, NULL);
|
||||||
|
|
||||||
|
gtk_container_add (GTK_CONTAINER (iw->window), iw->image);
|
||||||
|
|
||||||
|
/* Ensure we auto-shrink to fit image */
|
||||||
|
gtk_window_set_resizable (GTK_WINDOW (iw->window),
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
return iw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_image_window_free (MetaImageWindow *iw)
|
||||||
|
{
|
||||||
|
gtk_widget_destroy (iw->window);
|
||||||
|
g_free (iw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_image_window_set_showing (MetaImageWindow *iw,
|
||||||
|
gboolean showing)
|
||||||
|
{
|
||||||
|
if (showing)
|
||||||
|
gtk_widget_show_all (iw->window);
|
||||||
|
else
|
||||||
|
gtk_widget_hide (iw->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_image_window_set_image (MetaImageWindow *iw,
|
||||||
|
GdkPixbuf *pixbuf)
|
||||||
|
{
|
||||||
|
gtk_image_set_from_pixbuf (GTK_IMAGE (iw->image), pixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_image_window_set_position (MetaImageWindow *iw,
|
||||||
|
int x,
|
||||||
|
int y)
|
||||||
|
{
|
||||||
|
gtk_widget_set_uposition (iw->window, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
|
||||||
|
Window xwindow,
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dest_x,
|
||||||
|
int dest_y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
GdkDrawable *drawable;
|
||||||
|
GdkPixbuf *retval;
|
||||||
|
|
||||||
|
retval = NULL;
|
||||||
|
|
||||||
|
drawable = gdk_xid_table_lookup (xwindow);
|
||||||
|
|
||||||
|
if (drawable)
|
||||||
|
g_object_ref (G_OBJECT (drawable));
|
||||||
|
else
|
||||||
|
drawable = gdk_window_foreign_new (xwindow);
|
||||||
|
|
||||||
|
retval = gdk_pixbuf_get_from_drawable (dest,
|
||||||
|
drawable,
|
||||||
|
/* We assume root window cmap */
|
||||||
|
gdk_colormap_get_system (),
|
||||||
|
src_x, src_y,
|
||||||
|
dest_x, dest_y,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
g_object_unref (G_OBJECT (drawable));
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
22
src/ui.h
22
src/ui.h
@ -22,13 +22,16 @@
|
|||||||
#ifndef META_UI_H
|
#ifndef META_UI_H
|
||||||
#define META_UI_H
|
#define META_UI_H
|
||||||
|
|
||||||
/* Don't include gtk.h here */
|
/* Don't include gtk.h or gdk.h here */
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
typedef struct _MetaUI MetaUI;
|
typedef struct _MetaUI MetaUI;
|
||||||
|
|
||||||
|
typedef struct _MetaImageWindow MetaImageWindow;
|
||||||
|
|
||||||
typedef gboolean (* MetaEventFunc) (XEvent *xevent, gpointer data);
|
typedef gboolean (* MetaEventFunc) (XEvent *xevent, gpointer data);
|
||||||
|
|
||||||
void meta_ui_init (int *argc, char ***argv);
|
void meta_ui_init (int *argc, char ***argv);
|
||||||
@ -88,5 +91,22 @@ void meta_ui_window_menu_popup (MetaWindowMenu *menu,
|
|||||||
void meta_ui_window_menu_free (MetaWindowMenu *menu);
|
void meta_ui_window_menu_free (MetaWindowMenu *menu);
|
||||||
|
|
||||||
|
|
||||||
|
MetaImageWindow* meta_image_window_new (void);
|
||||||
|
void meta_image_window_free (MetaImageWindow *iw);
|
||||||
|
void meta_image_window_set_showing (MetaImageWindow *iw,
|
||||||
|
gboolean showing);
|
||||||
|
void meta_image_window_set_image (MetaImageWindow *iw,
|
||||||
|
GdkPixbuf *pixbuf);
|
||||||
|
void meta_image_window_set_position (MetaImageWindow *iw,
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
|
||||||
|
GdkPixbuf* meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
|
||||||
|
Window xwindow,
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dest_x,
|
||||||
|
int dest_y,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
#endif
|
#endif
|
||||||
|
36
src/window.c
36
src/window.c
@ -1063,22 +1063,26 @@ meta_window_shade (MetaWindow *window)
|
|||||||
meta_verbose ("Shading %s\n", window->desc);
|
meta_verbose ("Shading %s\n", window->desc);
|
||||||
if (!window->shaded)
|
if (!window->shaded)
|
||||||
{
|
{
|
||||||
{
|
if (window->mapped)
|
||||||
/* Animation */
|
{
|
||||||
MetaRectangle starting_size;
|
/* Animation */
|
||||||
MetaRectangle titlebar_size;
|
MetaRectangle starting_size;
|
||||||
|
MetaRectangle titlebar_size;
|
||||||
meta_window_get_outer_rect (window, &starting_size);
|
|
||||||
if (window->frame)
|
meta_window_get_outer_rect (window, &starting_size);
|
||||||
starting_size.y += window->frame->child_y;
|
if (window->frame)
|
||||||
titlebar_size = starting_size;
|
{
|
||||||
titlebar_size.height = 0;
|
starting_size.y += window->frame->child_y;
|
||||||
|
starting_size.height -= window->frame->child_y;
|
||||||
meta_effects_draw_box_animation (window->screen,
|
}
|
||||||
&starting_size,
|
titlebar_size = starting_size;
|
||||||
&titlebar_size,
|
titlebar_size.height = 0;
|
||||||
META_SHADE_ANIMATION_LENGTH);
|
|
||||||
}
|
meta_effects_draw_box_animation (window->screen,
|
||||||
|
&starting_size,
|
||||||
|
&titlebar_size,
|
||||||
|
META_SHADE_ANIMATION_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
window->shaded = TRUE;
|
window->shaded = TRUE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user