mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
Call meta_compositor_begin_move if there is a compositor
Sat Feb 25 11:46:14 2006 Søren Sandmann <sandmann@redhat.com> * src/display.c (meta_display_begin_grab_op): Call meta_compositor_begin_move if there is a compositor * src/compositor.c (meta_compositor_begin/update/end_move): Implement those functions. * src/spring-model.[ch]: New files
This commit is contained in:
parent
e4cf87c985
commit
b1847959b1
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
Sat Feb 25 11:46:14 2006 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
|
* src/display.c (meta_display_begin_grab_op): Call
|
||||||
|
meta_compositor_begin_move if there is a compositor
|
||||||
|
|
||||||
|
* src/compositor.c (meta_compositor_begin/update/end_move):
|
||||||
|
Implement those functions.
|
||||||
|
|
||||||
|
* src/spring-model.[ch]: New files
|
||||||
|
|
||||||
Thu Feb 23 15:40:52 2006 Søren Sandmann <sandmann@redhat.com>
|
Thu Feb 23 15:40:52 2006 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
* src/compositor.c (meta_compositor_manage_screen): Don't attempt
|
* src/compositor.c (meta_compositor_manage_screen): Don't attempt
|
||||||
|
@ -70,6 +70,8 @@ metacity_SOURCES= \
|
|||||||
screen.h \
|
screen.h \
|
||||||
session.c \
|
session.c \
|
||||||
session.h \
|
session.h \
|
||||||
|
spring-model.c \
|
||||||
|
spring-model.h \
|
||||||
stack.c \
|
stack.c \
|
||||||
stack.h \
|
stack.h \
|
||||||
tabpopup.c \
|
tabpopup.c \
|
||||||
|
552
src/compositor.c
552
src/compositor.c
@ -32,7 +32,6 @@
|
|||||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
#include <cm/node.h>
|
#include <cm/node.h>
|
||||||
#include <cm/drawable-node.h>
|
#include <cm/drawable-node.h>
|
||||||
|
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glu.h>
|
#include <GL/glu.h>
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
@ -45,6 +44,7 @@
|
|||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
|
#include "spring-model.h"
|
||||||
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
||||||
|
|
||||||
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
|
#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
|
||||||
@ -59,6 +59,8 @@ typedef struct
|
|||||||
int idle_id;
|
int idle_id;
|
||||||
} ScreenInfo;
|
} ScreenInfo;
|
||||||
|
|
||||||
|
typedef struct MoveInfo MoveInfo;
|
||||||
|
|
||||||
struct MetaCompositor
|
struct MetaCompositor
|
||||||
{
|
{
|
||||||
MetaDisplay *meta_display;
|
MetaDisplay *meta_display;
|
||||||
@ -77,6 +79,8 @@ struct MetaCompositor
|
|||||||
guint debug_updates : 1;
|
guint debug_updates : 1;
|
||||||
|
|
||||||
GList *ignored_damage;
|
GList *ignored_damage;
|
||||||
|
|
||||||
|
MoveInfo *move_info;
|
||||||
};
|
};
|
||||||
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
||||||
|
|
||||||
@ -105,7 +109,7 @@ meta_compositor_new (MetaDisplay *display)
|
|||||||
gboolean has_extensions;
|
gboolean has_extensions;
|
||||||
|
|
||||||
compositor_display = ws_display_new (NULL);
|
compositor_display = ws_display_new (NULL);
|
||||||
|
|
||||||
has_extensions =
|
has_extensions =
|
||||||
ws_display_init_composite (compositor_display) &&
|
ws_display_init_composite (compositor_display) &&
|
||||||
ws_display_init_damage (compositor_display) &&
|
ws_display_init_damage (compositor_display) &&
|
||||||
@ -120,7 +124,7 @@ meta_compositor_new (MetaDisplay *display)
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_display_set_ignore_grabs (compositor_display, TRUE);
|
ws_display_set_ignore_grabs (compositor_display, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,10 +136,10 @@ meta_compositor_new (MetaDisplay *display)
|
|||||||
compositor->meta_display = display;
|
compositor->meta_display = display;
|
||||||
|
|
||||||
compositor->window_hash =
|
compositor->window_hash =
|
||||||
g_hash_table_new_full (meta_unsigned_long_hash,
|
g_hash_table_new_full (meta_unsigned_long_hash,
|
||||||
meta_unsigned_long_equal,
|
meta_unsigned_long_equal,
|
||||||
NULL,
|
NULL,
|
||||||
free_window_hash_value);
|
free_window_hash_value);
|
||||||
|
|
||||||
compositor->enabled = TRUE;
|
compositor->enabled = TRUE;
|
||||||
|
|
||||||
@ -296,6 +300,11 @@ process_configure_notify (MetaCompositor *compositor,
|
|||||||
&event->above);
|
&event->above);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
cm_drawable_node_set_size (node,
|
||||||
|
event->x, event->y, event->width, event->height);
|
||||||
|
#endif
|
||||||
|
|
||||||
handle_restacking (compositor, node, above_node);
|
handle_restacking (compositor, node, above_node);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
||||||
@ -757,10 +766,8 @@ update (gpointer data)
|
|||||||
glEnd ();
|
glEnd ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
|
||||||
glClearColor (0.0, 0.0, 0.0, 0.0);
|
glClearColor (0.0, 0.0, 0.0, 0.0);
|
||||||
glClear (GL_COLOR_BUFFER_BIT);
|
glClear (GL_COLOR_BUFFER_BIT);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
glEnable (GL_TEXTURE_2D);
|
glEnable (GL_TEXTURE_2D);
|
||||||
@ -973,9 +980,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
Atom cm_sn_atom;
|
Atom cm_sn_atom;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
if (screen->compositor_data)
|
if (screen->compositor_data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
scr_info->glw = ws_screen_get_gl_window (ws_screen);
|
scr_info->glw = ws_screen_get_gl_window (ws_screen);
|
||||||
scr_info->compositor_nodes = NULL;
|
scr_info->compositor_nodes = NULL;
|
||||||
@ -987,7 +994,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
ws_display_init_composite (compositor->display);
|
ws_display_init_composite (compositor->display);
|
||||||
ws_display_init_damage (compositor->display);
|
ws_display_init_damage (compositor->display);
|
||||||
ws_display_init_fixes (compositor->display);
|
ws_display_init_fixes (compositor->display);
|
||||||
|
|
||||||
g_print ("redirecting\n");
|
g_print ("redirecting\n");
|
||||||
ws_window_redirect_subwindows (root);
|
ws_window_redirect_subwindows (root);
|
||||||
ws_window_set_override_redirect (scr_info->glw, TRUE);
|
ws_window_set_override_redirect (scr_info->glw, TRUE);
|
||||||
@ -1046,11 +1053,11 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ws_window_raise (scr_info->glw);
|
ws_window_raise (scr_info->glw);
|
||||||
|
|
||||||
g_print ("unredirecting\n");
|
g_print ("unredirecting\n");
|
||||||
ws_window_unredirect_subwindows (root);
|
ws_window_unredirect_subwindows (root);
|
||||||
ws_window_unmap (scr_info->glw);
|
ws_window_unmap (scr_info->glw);
|
||||||
|
|
||||||
/* We need to sync here, because if someone is furiously
|
/* We need to sync here, because if someone is furiously
|
||||||
* clicking the 'compositing manager' check box, we might
|
* clicking the 'compositing manager' check box, we might
|
||||||
* attempt to redirect the window again before this unredirect
|
* attempt to redirect the window again before this unredirect
|
||||||
@ -1175,7 +1182,7 @@ interpolate_rectangle (gdouble t,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MINIMIZE_STYLE 1
|
#define MINIMIZE_STYLE 3
|
||||||
|
|
||||||
#ifndef HAVE_COMPOSITE_EXTENSIONS
|
#ifndef HAVE_COMPOSITE_EXTENSIONS
|
||||||
#undef MINIMIZE_STYLE
|
#undef MINIMIZE_STYLE
|
||||||
@ -1236,10 +1243,12 @@ set_geometry (MiniInfo *info, gdouble elapsed)
|
|||||||
|
|
||||||
interpolate_rectangle (elapsed, &info->current_geometry, &info->target_geometry, &rect);
|
interpolate_rectangle (elapsed, &info->current_geometry, &info->target_geometry, &rect);
|
||||||
|
|
||||||
|
#if 0
|
||||||
g_print ("y: %d %d (%f => %d)\n", info->current_geometry.y, info->target_geometry.y,
|
g_print ("y: %d %d (%f => %d)\n", info->current_geometry.y, info->target_geometry.y,
|
||||||
elapsed, rect.y);
|
elapsed, rect.y);
|
||||||
|
|
||||||
g_print ("setting: %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
|
g_print ("setting: %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
|
||||||
|
#endif
|
||||||
|
|
||||||
cm_drawable_node_set_geometry (info->node,
|
cm_drawable_node_set_geometry (info->node,
|
||||||
rect.x, rect.y,
|
rect.x, rect.y,
|
||||||
@ -1412,7 +1421,7 @@ run_animation_01 (gpointer data)
|
|||||||
{
|
{
|
||||||
cm_drawable_node_set_viewable (info->node, FALSE);
|
cm_drawable_node_set_viewable (info->node, FALSE);
|
||||||
|
|
||||||
cm_drawable_node_unset_geometry (info->node);
|
cm_drawable_node_unset_geometry (info->node);
|
||||||
|
|
||||||
cm_drawable_node_set_alpha (info->node, 1.0);
|
cm_drawable_node_set_alpha (info->node, 1.0);
|
||||||
|
|
||||||
@ -1540,65 +1549,6 @@ do_minimize_animation (gpointer data)
|
|||||||
|
|
||||||
#elif MINIMIZE_STYLE == 3
|
#elif MINIMIZE_STYLE == 3
|
||||||
|
|
||||||
|
|
||||||
typedef struct XYPair Point;
|
|
||||||
typedef struct XYPair Vector;
|
|
||||||
typedef struct Spring Spring;
|
|
||||||
typedef struct Object Object;
|
|
||||||
typedef struct Model Model;
|
|
||||||
|
|
||||||
struct XYPair {
|
|
||||||
double x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GRID_WIDTH 4
|
|
||||||
#define GRID_HEIGHT 4
|
|
||||||
|
|
||||||
#define MODEL_MAX_OBJECTS (GRID_WIDTH * GRID_HEIGHT)
|
|
||||||
#define MODEL_MAX_SPRINGS (MODEL_MAX_OBJECTS * 2)
|
|
||||||
|
|
||||||
#define DEFAULT_SPRING_K 5.0
|
|
||||||
#define DEFAULT_FRICTION 1.4
|
|
||||||
|
|
||||||
struct Spring {
|
|
||||||
Object *a;
|
|
||||||
Object *b;
|
|
||||||
/* Spring position at rest, from a to b:
|
|
||||||
offset = b.position - a.position
|
|
||||||
*/
|
|
||||||
Vector offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Object {
|
|
||||||
Vector force;
|
|
||||||
|
|
||||||
Point position;
|
|
||||||
Vector velocity;
|
|
||||||
|
|
||||||
double mass;
|
|
||||||
double theta;
|
|
||||||
|
|
||||||
int immobile;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Model {
|
|
||||||
int num_objects;
|
|
||||||
Object objects[MODEL_MAX_OBJECTS];
|
|
||||||
|
|
||||||
int num_springs;
|
|
||||||
Spring springs[MODEL_MAX_SPRINGS];
|
|
||||||
|
|
||||||
Object *anchor_object;
|
|
||||||
Vector anchor_offset;
|
|
||||||
|
|
||||||
double friction;/* Friction constant */
|
|
||||||
double k;/* Spring constant */
|
|
||||||
|
|
||||||
double last_time;
|
|
||||||
double steps;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CmDrawableNode *node;
|
CmDrawableNode *node;
|
||||||
@ -1606,13 +1556,14 @@ typedef struct
|
|||||||
gboolean expand;
|
gboolean expand;
|
||||||
|
|
||||||
MetaCompositor *compositor;
|
MetaCompositor *compositor;
|
||||||
ScreenInfo *scr_info;
|
MetaScreen *screen;
|
||||||
MetaRectangle rect;
|
MetaRectangle rect;
|
||||||
|
double last_time;
|
||||||
|
|
||||||
MetaAnimationFinishedFunc finished_func;
|
MetaAnimationFinishedFunc finished_func;
|
||||||
gpointer finished_data;
|
gpointer finished_data;
|
||||||
|
|
||||||
Model model;
|
Model *model;
|
||||||
|
|
||||||
int button_x;
|
int button_x;
|
||||||
int button_y;
|
int button_y;
|
||||||
@ -1620,270 +1571,96 @@ typedef struct
|
|||||||
int button_height;
|
int button_height;
|
||||||
} MiniInfo;
|
} MiniInfo;
|
||||||
|
|
||||||
static void
|
|
||||||
object_init (Object *object,
|
|
||||||
double position_x, double position_y,
|
|
||||||
double velocity_x, double velocity_y, double mass)
|
|
||||||
{
|
|
||||||
object->position.x = position_x;
|
|
||||||
object->position.y = position_y;
|
|
||||||
|
|
||||||
object->velocity.x = velocity_x;
|
|
||||||
object->velocity.y = velocity_y;
|
|
||||||
|
|
||||||
object->mass = mass;
|
|
||||||
|
|
||||||
object->force.x = 0;
|
|
||||||
object->force.y = 0;
|
|
||||||
|
|
||||||
object->immobile = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
spring_init (Spring *spring,
|
|
||||||
Object *object_a, Object *object_b,
|
|
||||||
double offset_x, double offset_y)
|
|
||||||
{
|
|
||||||
spring->a = object_a;
|
|
||||||
spring->b = object_b;
|
|
||||||
spring->offset.x = offset_x;
|
|
||||||
spring->offset.y = offset_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
model_add_spring (Model *model,
|
|
||||||
Object *object_a, Object *object_b,
|
|
||||||
double offset_x, double offset_y)
|
|
||||||
{
|
|
||||||
Spring *spring;
|
|
||||||
|
|
||||||
g_assert (model->num_springs < MODEL_MAX_SPRINGS);
|
|
||||||
|
|
||||||
spring = &model->springs[model->num_springs];
|
|
||||||
model->num_springs++;
|
|
||||||
|
|
||||||
spring_init (spring, object_a, object_b, offset_x, offset_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
model_init_grid (Model *model, MetaRectangle *rect, gboolean expand)
|
|
||||||
{
|
|
||||||
int x, y, i, v_x, v_y;
|
|
||||||
int hpad, vpad;
|
|
||||||
|
|
||||||
model->num_objects = MODEL_MAX_OBJECTS;
|
|
||||||
|
|
||||||
model->num_springs = 0;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
if (expand) {
|
|
||||||
hpad = rect->width / 3;
|
|
||||||
vpad = rect->height / 3;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hpad = rect->width / 6;
|
|
||||||
vpad = rect->height / 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (y = 0; y < GRID_HEIGHT; y++)
|
|
||||||
for (x = 0; x < GRID_WIDTH; x++) {
|
|
||||||
|
|
||||||
v_x = random() % 40 - 20;
|
|
||||||
v_y = random() % 40 - 20;
|
|
||||||
|
|
||||||
if (expand)
|
|
||||||
object_init (&model->objects[i],
|
|
||||||
rect->x + x * rect->width / 6 + rect->width / 4,
|
|
||||||
rect->y + y * rect->height / 6 + rect->height / 4,
|
|
||||||
v_x, v_y, 20);
|
|
||||||
else
|
|
||||||
object_init (&model->objects[i],
|
|
||||||
rect->x + x * rect->width / 3,
|
|
||||||
rect->y + y * rect->height / 3,
|
|
||||||
v_x, v_y, 20);
|
|
||||||
|
|
||||||
|
|
||||||
if (x > 0)
|
|
||||||
model_add_spring (model,
|
|
||||||
&model->objects[i - 1],
|
|
||||||
&model->objects[i],
|
|
||||||
hpad, 0);
|
|
||||||
|
|
||||||
if (y > 0)
|
|
||||||
model_add_spring (model,
|
|
||||||
&model->objects[i - GRID_WIDTH],
|
|
||||||
&model->objects[i],
|
|
||||||
0, vpad);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
model_init (Model *model, MetaRectangle *rect, gboolean expand)
|
|
||||||
{
|
|
||||||
model->anchor_object = NULL;
|
|
||||||
|
|
||||||
model->k = DEFAULT_SPRING_K;
|
|
||||||
model->friction = DEFAULT_FRICTION;
|
|
||||||
|
|
||||||
model_init_grid (model, rect, expand);
|
|
||||||
model->steps = 0;
|
|
||||||
model->last_time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
object_apply_force (Object *object, double fx, double fy)
|
|
||||||
{
|
|
||||||
object->force.x += fx;
|
|
||||||
object->force.y += fy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The model here can be understood as a rigid body of the spring's
|
|
||||||
* rest shape, centered on the vector between the two object
|
|
||||||
* positions. This rigid body is then connected by linear-force
|
|
||||||
* springs to each object. This model does degnerate into a simple
|
|
||||||
* spring for linear displacements, and does something reasonable for
|
|
||||||
* rotation.
|
|
||||||
*
|
|
||||||
* There are other possibilities for handling the rotation of the
|
|
||||||
* spring, and it might be interesting to explore something which has
|
|
||||||
* better length-preserving properties. For example, with the current
|
|
||||||
* model, an initial 180 degree rotation of the spring results in the
|
|
||||||
* spring collapsing down to 0 size before expanding back to it's
|
|
||||||
* natural size again.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
spring_exert_forces (Spring *spring, double k)
|
|
||||||
{
|
|
||||||
Vector da, db;
|
|
||||||
Vector a, b;
|
|
||||||
|
|
||||||
a = spring->a->position;
|
|
||||||
b = spring->b->position;
|
|
||||||
|
|
||||||
/* A nice vector diagram would likely help here, but my ASCII-art
|
|
||||||
* skills aren't up to the task. Here's how to make your own
|
|
||||||
* diagram:
|
|
||||||
*
|
|
||||||
* Draw a and b, and the vector AB from a to b
|
|
||||||
* Find the center of AB
|
|
||||||
* Draw spring->offset so that its center point is on the center of AB
|
|
||||||
* Draw da from a to the initial point of spring->offset
|
|
||||||
* Draw db from b to the final point of spring->offset
|
|
||||||
*
|
|
||||||
* The math below should be easy to verify from the diagram.
|
|
||||||
*/
|
|
||||||
|
|
||||||
da.x = 0.5 * (b.x - a.x - spring->offset.x);
|
|
||||||
da.y = 0.5 * (b.y - a.y - spring->offset.y);
|
|
||||||
|
|
||||||
db.x = 0.5 * (a.x - b.x + spring->offset.x);
|
|
||||||
db.y = 0.5 * (a.y - b.y + spring->offset.y);
|
|
||||||
|
|
||||||
object_apply_force (spring->a, k *da.x, k * da.y);
|
|
||||||
|
|
||||||
object_apply_force (spring->b, k * db.x, k * db.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
model_step_object (Model *model, Object *object)
|
|
||||||
{
|
|
||||||
Vector acceleration;
|
|
||||||
|
|
||||||
object->theta += 0.05;
|
|
||||||
|
|
||||||
/* Slow down due to friction. */
|
|
||||||
object->force.x -= model->friction * object->velocity.x;
|
|
||||||
object->force.y -= model->friction * object->velocity.y;
|
|
||||||
|
|
||||||
acceleration.x = object->force.x / object->mass;
|
|
||||||
acceleration.y = object->force.y / object->mass;
|
|
||||||
|
|
||||||
if (object->immobile) {
|
|
||||||
object->velocity.x = 0;
|
|
||||||
object->velocity.y = 0;
|
|
||||||
} else {
|
|
||||||
object->velocity.x += acceleration.x;
|
|
||||||
object->velocity.y += acceleration.y;
|
|
||||||
|
|
||||||
object->position.x += object->velocity.x;
|
|
||||||
object->position.y += object->velocity.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
object->force.x = 0.0;
|
|
||||||
object->force.y = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
model_step (Model *model)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < model->num_springs; i++)
|
|
||||||
spring_exert_forces (&model->springs[i], model->k);
|
|
||||||
|
|
||||||
for (i = 0; i < model->num_objects; i++)
|
|
||||||
model_step_object (model, &model->objects[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WOBBLE_TIME 1.0
|
#define WOBBLE_TIME 1.0
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_patch (CmDrawableNode *node,
|
||||||
|
Model *model,
|
||||||
|
gdouble blend,
|
||||||
|
MetaRectangle *target)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
CmPoint points[4][4];
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
double obj_x, obj_y;
|
||||||
|
int p_x, p_y;
|
||||||
|
|
||||||
|
model_get_position (model, i, j, &obj_x, &obj_y);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
target_x = info->node->real_x + i * info->node->real_width / 3;
|
||||||
|
target_y = info->node->real_y + j * info->node->real_height / 3;
|
||||||
|
#endif
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
p_x = target->x + i * target->width / 3;
|
||||||
|
p_y = target->y + j * target->height / 3;
|
||||||
|
|
||||||
|
points[j][i].x = (1 - blend) * obj_x + blend * p_x;
|
||||||
|
points[j][i].y = (1 - blend) * obj_y + blend * p_y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points[j][i].x = obj_x;
|
||||||
|
points[j][i].y = obj_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cm_drawable_node_set_patch (node, points);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
run_animation (gpointer data)
|
run_animation (gpointer data)
|
||||||
{
|
{
|
||||||
MiniInfo *info = data;
|
MiniInfo *info = data;
|
||||||
gdouble t, blend;
|
gdouble t, blend;
|
||||||
CmPoint points[4][4];
|
double n_steps;
|
||||||
int i, j, steps, target_x, target_y;
|
int i;
|
||||||
|
|
||||||
t = g_timer_elapsed (info->timer, NULL);
|
t = g_timer_elapsed (info->timer, NULL);
|
||||||
|
|
||||||
info->model.steps += (t - info->model.last_time) / 0.03;
|
n_steps = floor ((t - info->last_time) * 75);
|
||||||
info->model.last_time = t;
|
|
||||||
steps = floor(info->model.steps);
|
|
||||||
info->model.steps -= steps;
|
|
||||||
|
|
||||||
for (i = 0; i < steps; i++)
|
for (i = 0; i < n_steps; ++i)
|
||||||
model_step (&info->model);
|
model_step (info->model);
|
||||||
|
|
||||||
if (info->expand)
|
if (i > 0)
|
||||||
blend = t / WOBBLE_TIME;
|
info->last_time = t;
|
||||||
else
|
|
||||||
blend = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
blend = t / WOBBLE_TIME;
|
||||||
for (j = 0; j < 4; j++) {
|
|
||||||
target_x = info->node->real_x + i * info->node->real_width / 3;
|
set_patch (info->node, info->model, 0.0, NULL);
|
||||||
target_y = info->node->real_y + j * info->node->real_height / 3;
|
|
||||||
|
|
||||||
points[j][i].x =
|
|
||||||
(1 - blend) * info->model.objects[j * 4 + i].position.x +
|
|
||||||
blend * target_x;
|
|
||||||
points[j][i].y =
|
|
||||||
(1 - blend) * info->model.objects[j * 4 + i].position.y +
|
|
||||||
blend * target_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
cm_drawable_node_set_patch (info->node, points);
|
|
||||||
if (info->expand)
|
if (info->expand)
|
||||||
cm_drawable_node_set_alpha (info->node, t / WOBBLE_TIME);
|
cm_drawable_node_set_alpha (info->node, t / WOBBLE_TIME);
|
||||||
else
|
else
|
||||||
cm_drawable_node_set_alpha (info->node, 1.0 - t / WOBBLE_TIME);
|
cm_drawable_node_set_alpha (info->node, 1.0 - t / WOBBLE_TIME);
|
||||||
|
|
||||||
if (t > WOBBLE_TIME) {
|
if (t > WOBBLE_TIME)
|
||||||
cm_drawable_node_set_viewable (info->node, info->expand);
|
{
|
||||||
cm_drawable_node_unset_geometry (info->node);
|
cm_drawable_node_set_viewable (info->node, info->expand);
|
||||||
cm_drawable_node_set_alpha (info->node, 1.0);
|
cm_drawable_node_unset_geometry (info->node);
|
||||||
|
cm_drawable_node_set_alpha (info->node, 1.0);
|
||||||
if (info->finished_func)
|
|
||||||
info->finished_func (info->finished_data);
|
if (info->finished_func)
|
||||||
return FALSE;
|
{
|
||||||
}
|
info->finished_func (info->finished_data);
|
||||||
else {
|
|
||||||
return TRUE;
|
model_destroy (info->model);
|
||||||
}
|
info->model = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue_repaint (info->node, info->screen);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1909,7 +1686,9 @@ meta_compositor_minimize (MetaCompositor *compositor,
|
|||||||
|
|
||||||
info->rect = window->user_rect;
|
info->rect = window->user_rect;
|
||||||
|
|
||||||
model_init (&info->model, &info->rect, FALSE);
|
info->model = model_new (&info->rect, FALSE);
|
||||||
|
|
||||||
|
info->last_time = 0.0;
|
||||||
|
|
||||||
info->expand = FALSE;
|
info->expand = FALSE;
|
||||||
info->button_x = x;
|
info->button_x = x;
|
||||||
@ -1918,7 +1697,7 @@ meta_compositor_minimize (MetaCompositor *compositor,
|
|||||||
info->button_height = height;
|
info->button_height = height;
|
||||||
|
|
||||||
info->compositor = compositor;
|
info->compositor = compositor;
|
||||||
info->scr_info = screen->compositor_data;
|
info->screen = screen;
|
||||||
|
|
||||||
g_idle_add (run_animation, info);
|
g_idle_add (run_animation, info);
|
||||||
#endif
|
#endif
|
||||||
@ -1947,7 +1726,7 @@ meta_compositor_unminimize (MetaCompositor *compositor,
|
|||||||
|
|
||||||
info->rect = window->user_rect;
|
info->rect = window->user_rect;
|
||||||
|
|
||||||
model_init (&info->model, &info->rect, TRUE);
|
info->model = model_new (&info->rect, TRUE);
|
||||||
|
|
||||||
info->expand = TRUE;
|
info->expand = TRUE;
|
||||||
info->button_x = x;
|
info->button_x = x;
|
||||||
@ -1956,7 +1735,7 @@ meta_compositor_unminimize (MetaCompositor *compositor,
|
|||||||
info->button_height = height;
|
info->button_height = height;
|
||||||
|
|
||||||
info->compositor = compositor;
|
info->compositor = compositor;
|
||||||
info->scr_info = screen->compositor_data;
|
info->screen = screen;
|
||||||
|
|
||||||
g_idle_add (run_animation, info);
|
g_idle_add (run_animation, info);
|
||||||
#endif
|
#endif
|
||||||
@ -2052,7 +1831,9 @@ void
|
|||||||
meta_compositor_destroy (MetaCompositor *compositor)
|
meta_compositor_destroy (MetaCompositor *compositor)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
|
#if 0
|
||||||
GSList *list;
|
GSList *list;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
@ -2064,3 +1845,122 @@ meta_compositor_destroy (MetaCompositor *compositor)
|
|||||||
g_free (compositor);
|
g_free (compositor);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
|
|
||||||
|
struct MoveInfo
|
||||||
|
{
|
||||||
|
GTimer *timer;
|
||||||
|
gboolean finished;
|
||||||
|
Model *model;
|
||||||
|
MetaScreen *screen;
|
||||||
|
CmDrawableNode *node;
|
||||||
|
gdouble last_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wobble (gpointer data)
|
||||||
|
{
|
||||||
|
MoveInfo *info = data;
|
||||||
|
double t = g_timer_elapsed (info->timer, NULL);
|
||||||
|
|
||||||
|
if (info->finished && model_is_calm (info->model))
|
||||||
|
{
|
||||||
|
cm_drawable_node_unset_geometry (info->node);
|
||||||
|
g_free (info);
|
||||||
|
info = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n_steps;
|
||||||
|
n_steps = floor ((t - info->last_time) * 75);
|
||||||
|
|
||||||
|
for (i = 0; i < n_steps; ++i)
|
||||||
|
model_step (info->model);
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
info->last_time = t;
|
||||||
|
|
||||||
|
set_patch (info->node, info->model, 0.0, NULL);
|
||||||
|
|
||||||
|
queue_repaint (info->node, info->screen);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
compute_window_rect (MetaWindow *window,
|
||||||
|
MetaRectangle *rect)
|
||||||
|
{
|
||||||
|
/* FIXME: does metacity include this function somewhere? */
|
||||||
|
|
||||||
|
if (window->frame)
|
||||||
|
{
|
||||||
|
*rect = window->frame->rect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*rect = window->user_rect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_compositor_begin_move (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window,
|
||||||
|
MetaRectangle *initial,
|
||||||
|
int grab_x, int grab_y)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
|
MetaRectangle rect;
|
||||||
|
|
||||||
|
compositor->move_info = g_new0 (MoveInfo, 1);
|
||||||
|
|
||||||
|
compositor->move_info->last_time = 0.0;
|
||||||
|
compositor->move_info->timer = g_timer_new ();
|
||||||
|
|
||||||
|
compute_window_rect (window, &rect);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_print ("init: %d %d\n", initial->x, initial->y);
|
||||||
|
g_print ("window: %d %d\n", window->rect.x, window->rect.y);
|
||||||
|
g_print ("frame: %d %d\n", rect.x, rect.y);
|
||||||
|
g_print ("grab: %d %d\n", grab_x, grab_y);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
compositor->move_info->model = model_new (&rect, TRUE);
|
||||||
|
compositor->move_info->node = window_to_node (window->display->compositor, window);
|
||||||
|
compositor->move_info->screen = window->screen;
|
||||||
|
|
||||||
|
model_begin_move (compositor->move_info->model, grab_x, grab_y);
|
||||||
|
|
||||||
|
g_idle_add (wobble, compositor->move_info);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_compositor_update_move (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
|
model_update_move (compositor->move_info->model, x, y);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_compositor_end_move (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
|
compositor->move_info->finished = TRUE;
|
||||||
|
compositor->move_info = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -70,4 +70,14 @@ meta_compositor_set_updates (MetaCompositor *compositor,
|
|||||||
void
|
void
|
||||||
meta_compositor_destroy (MetaCompositor *compositor);
|
meta_compositor_destroy (MetaCompositor *compositor);
|
||||||
|
|
||||||
|
void meta_compositor_begin_move (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window,
|
||||||
|
MetaRectangle *initial,
|
||||||
|
int grab_x, int grab_y);
|
||||||
|
void meta_compositor_update_move (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window,
|
||||||
|
int x, int y);
|
||||||
|
void meta_compositor_end_move (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window);
|
||||||
|
|
||||||
#endif /* META_COMPOSITOR_H */
|
#endif /* META_COMPOSITOR_H */
|
||||||
|
@ -1835,7 +1835,7 @@ event_callback (XEvent *event,
|
|||||||
XAllowEvents (display->xdisplay,
|
XAllowEvents (display->xdisplay,
|
||||||
mode, event->xbutton.time);
|
mode, event->xbutton.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (begin_move && window->has_move_func)
|
if (begin_move && window->has_move_func)
|
||||||
{
|
{
|
||||||
meta_display_begin_grab_op (display,
|
meta_display_begin_grab_op (display,
|
||||||
@ -3305,6 +3305,16 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
|||||||
{
|
{
|
||||||
Window grab_xwindow;
|
Window grab_xwindow;
|
||||||
|
|
||||||
|
if (grab_op_is_mouse (op) && meta_grab_op_is_moving (op))
|
||||||
|
{
|
||||||
|
if (display->compositor)
|
||||||
|
{
|
||||||
|
meta_compositor_begin_move (display->compositor,
|
||||||
|
window, &window->rect,
|
||||||
|
root_x, root_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
"Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
|
"Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
|
||||||
op, window ? window->desc : "none", button, pointer_already_grabbed,
|
op, window ? window->desc : "none", button, pointer_already_grabbed,
|
||||||
@ -3635,6 +3645,15 @@ meta_display_end_grab_op (MetaDisplay *display,
|
|||||||
meta_window_calc_showing (display->grab_window);
|
meta_window_calc_showing (display->grab_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (display->compositor &&
|
||||||
|
display->grab_window &&
|
||||||
|
grab_op_is_mouse (display->grab_op) &&
|
||||||
|
meta_grab_op_is_moving (display->grab_op))
|
||||||
|
{
|
||||||
|
meta_compositor_end_move (display->compositor,
|
||||||
|
display->grab_window);
|
||||||
|
}
|
||||||
|
|
||||||
if (display->grab_have_pointer)
|
if (display->grab_have_pointer)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
410
src/spring-model.c
Normal file
410
src/spring-model.c
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
#include "spring-model.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
struct XYPair
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GRID_WIDTH 4
|
||||||
|
#define GRID_HEIGHT 4
|
||||||
|
|
||||||
|
#define MODEL_MAX_OBJECTS (GRID_WIDTH * GRID_HEIGHT)
|
||||||
|
#define MODEL_MAX_SPRINGS (MODEL_MAX_OBJECTS * 2)
|
||||||
|
|
||||||
|
#define DEFAULT_SPRING_K 5.0
|
||||||
|
#define DEFAULT_FRICTION 1.4
|
||||||
|
|
||||||
|
struct Spring {
|
||||||
|
Object *a;
|
||||||
|
Object *b;
|
||||||
|
/* Spring position at rest, from a to b:
|
||||||
|
offset = b.position - a.position
|
||||||
|
*/
|
||||||
|
Vector offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Object {
|
||||||
|
Vector force;
|
||||||
|
|
||||||
|
Point position;
|
||||||
|
Vector velocity;
|
||||||
|
|
||||||
|
double mass;
|
||||||
|
double theta;
|
||||||
|
|
||||||
|
int immobile;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
int num_objects;
|
||||||
|
Object objects[MODEL_MAX_OBJECTS];
|
||||||
|
|
||||||
|
int num_springs;
|
||||||
|
Spring springs[MODEL_MAX_SPRINGS];
|
||||||
|
|
||||||
|
Object *anchor_object;
|
||||||
|
Vector anchor_offset;
|
||||||
|
|
||||||
|
double friction;/* Friction constant */
|
||||||
|
double k;/* Spring constant */
|
||||||
|
|
||||||
|
double last_time;
|
||||||
|
double steps;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
object_init (Object *object,
|
||||||
|
double position_x, double position_y,
|
||||||
|
double velocity_x, double velocity_y, double mass)
|
||||||
|
{
|
||||||
|
object->position.x = position_x;
|
||||||
|
object->position.y = position_y;
|
||||||
|
|
||||||
|
object->velocity.x = velocity_x;
|
||||||
|
object->velocity.y = velocity_y;
|
||||||
|
|
||||||
|
object->mass = mass;
|
||||||
|
|
||||||
|
object->force.x = 0;
|
||||||
|
object->force.y = 0;
|
||||||
|
|
||||||
|
object->immobile = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spring_init (Spring *spring,
|
||||||
|
Object *object_a, Object *object_b,
|
||||||
|
double offset_x, double offset_y)
|
||||||
|
{
|
||||||
|
spring->a = object_a;
|
||||||
|
spring->b = object_b;
|
||||||
|
spring->offset.x = offset_x;
|
||||||
|
spring->offset.y = offset_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
model_add_spring (Model *model,
|
||||||
|
Object *object_a, Object *object_b,
|
||||||
|
double offset_x, double offset_y)
|
||||||
|
{
|
||||||
|
Spring *spring;
|
||||||
|
|
||||||
|
g_assert (model->num_springs < MODEL_MAX_SPRINGS);
|
||||||
|
|
||||||
|
spring = &model->springs[model->num_springs];
|
||||||
|
model->num_springs++;
|
||||||
|
|
||||||
|
spring_init (spring, object_a, object_b, offset_x, offset_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
object_apply_force (Object *object, double fx, double fy)
|
||||||
|
{
|
||||||
|
object->force.x += fx;
|
||||||
|
object->force.y += fy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The model here can be understood as a rigid body of the spring's
|
||||||
|
* rest shape, centered on the vector between the two object
|
||||||
|
* positions. This rigid body is then connected by linear-force
|
||||||
|
* springs to each object. This model does degnerate into a simple
|
||||||
|
* spring for linear displacements, and does something reasonable for
|
||||||
|
* rotation.
|
||||||
|
*
|
||||||
|
* There are other possibilities for handling the rotation of the
|
||||||
|
* spring, and it might be interesting to explore something which has
|
||||||
|
* better length-preserving properties. For example, with the current
|
||||||
|
* model, an initial 180 degree rotation of the spring results in the
|
||||||
|
* spring collapsing down to 0 size before expanding back to it's
|
||||||
|
* natural size again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
spring_exert_forces (Spring *spring, double k)
|
||||||
|
{
|
||||||
|
Vector da, db;
|
||||||
|
Vector a, b;
|
||||||
|
|
||||||
|
a = spring->a->position;
|
||||||
|
b = spring->b->position;
|
||||||
|
|
||||||
|
/* A nice vector diagram would likely help here, but my ASCII-art
|
||||||
|
* skills aren't up to the task. Here's how to make your own
|
||||||
|
* diagram:
|
||||||
|
*
|
||||||
|
* Draw a and b, and the vector AB from a to b
|
||||||
|
* Find the center of AB
|
||||||
|
* Draw spring->offset so that its center point is on the center of AB
|
||||||
|
* Draw da from a to the initial point of spring->offset
|
||||||
|
* Draw db from b to the final point of spring->offset
|
||||||
|
*
|
||||||
|
* The math below should be easy to verify from the diagram.
|
||||||
|
*/
|
||||||
|
|
||||||
|
da.x = 0.5 * (b.x - a.x - spring->offset.x);
|
||||||
|
da.y = 0.5 * (b.y - a.y - spring->offset.y);
|
||||||
|
|
||||||
|
db.x = 0.5 * (a.x - b.x + spring->offset.x);
|
||||||
|
db.y = 0.5 * (a.y - b.y + spring->offset.y);
|
||||||
|
|
||||||
|
object_apply_force (spring->a, k * da.x, k * da.y);
|
||||||
|
object_apply_force (spring->b, k * db.x, k * db.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
model_step_object (Model *model, Object *object)
|
||||||
|
{
|
||||||
|
Vector acceleration;
|
||||||
|
|
||||||
|
object->theta += 0.05;
|
||||||
|
|
||||||
|
/* Slow down due to friction. */
|
||||||
|
object->force.x -= model->friction * object->velocity.x;
|
||||||
|
object->force.y -= model->friction * object->velocity.y;
|
||||||
|
|
||||||
|
acceleration.x = object->force.x / object->mass;
|
||||||
|
acceleration.y = object->force.y / object->mass;
|
||||||
|
|
||||||
|
if (object->immobile)
|
||||||
|
{
|
||||||
|
object->velocity.x = 0;
|
||||||
|
object->velocity.y = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object->velocity.x += acceleration.x;
|
||||||
|
object->velocity.y += acceleration.y;
|
||||||
|
|
||||||
|
object->position.x += object->velocity.x;
|
||||||
|
object->position.y += object->velocity.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
object->force.x = 0.0;
|
||||||
|
object->force.y = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
model_init_grid (Model *model, MetaRectangle *rect, gboolean expand)
|
||||||
|
{
|
||||||
|
int x, y, i, v_x, v_y;
|
||||||
|
int hpad, vpad;
|
||||||
|
|
||||||
|
model->num_objects = MODEL_MAX_OBJECTS;
|
||||||
|
|
||||||
|
model->num_springs = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if (expand)
|
||||||
|
{
|
||||||
|
hpad = rect->width / 3;
|
||||||
|
vpad = rect->height / 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hpad = rect->width / 6;
|
||||||
|
vpad = rect->height / 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y = 0; y < GRID_HEIGHT; y++)
|
||||||
|
for (x = 0; x < GRID_WIDTH; x++)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
v_x = 40 * g_random_double() - 20;
|
||||||
|
v_y = 40 * g_random_double() - 20;
|
||||||
|
#endif
|
||||||
|
v_x = v_y = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (expand)
|
||||||
|
object_init (&model->objects[i],
|
||||||
|
rect->x + x * rect->width / 6 + rect->width / 4,
|
||||||
|
rect->y + y * rect->height / 6 + rect->height / 4,
|
||||||
|
v_x, v_y, 20);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
g_print ("obj: %d %d\n", rect->x + x * rect->width / 3,
|
||||||
|
rect->y + y * rect->height / 3);
|
||||||
|
#endif
|
||||||
|
object_init (&model->objects[i],
|
||||||
|
rect->x + x * rect->width / 3,
|
||||||
|
rect->y + y * rect->height / 3,
|
||||||
|
v_x, v_y, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x > 0)
|
||||||
|
model_add_spring (model,
|
||||||
|
&model->objects[i - 1],
|
||||||
|
&model->objects[i],
|
||||||
|
hpad, 0);
|
||||||
|
|
||||||
|
if (y > 0)
|
||||||
|
model_add_spring (model,
|
||||||
|
&model->objects[i - GRID_WIDTH],
|
||||||
|
&model->objects[i],
|
||||||
|
0, vpad);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
model_init (Model *model, MetaRectangle *rect, gboolean expand)
|
||||||
|
{
|
||||||
|
model->anchor_object = NULL;
|
||||||
|
|
||||||
|
model->k = DEFAULT_SPRING_K;
|
||||||
|
model->friction = DEFAULT_FRICTION;
|
||||||
|
|
||||||
|
model_init_grid (model, rect, expand);
|
||||||
|
model->steps = 0;
|
||||||
|
model->last_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Model *
|
||||||
|
model_new (MetaRectangle *rect, gboolean expand)
|
||||||
|
{
|
||||||
|
Model *model = g_new0 (Model, 1);
|
||||||
|
|
||||||
|
model_init (model, rect, expand);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
object_distance (Object *object, double x, double y)
|
||||||
|
{
|
||||||
|
double dx, dy;
|
||||||
|
|
||||||
|
dx = object->position.x - x;
|
||||||
|
dy = object->position.y - y;
|
||||||
|
|
||||||
|
return sqrt (dx*dx + dy*dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object *
|
||||||
|
model_find_nearest (Model *model, double x, double y)
|
||||||
|
{
|
||||||
|
Object *object = &model->objects[0];
|
||||||
|
double distance, min_distance = 0.0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < model->num_objects; i++) {
|
||||||
|
distance = object_distance (&model->objects[i], x, y);
|
||||||
|
if (i == 0 || distance < min_distance) {
|
||||||
|
min_distance = distance;
|
||||||
|
object = &model->objects[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
model_begin_move (Model *model, int x, int y)
|
||||||
|
{
|
||||||
|
if (model->anchor_object)
|
||||||
|
model->anchor_object->immobile = 0;
|
||||||
|
|
||||||
|
model->anchor_object = model_find_nearest (model, x, y);
|
||||||
|
|
||||||
|
model->anchor_offset.x = x - model->anchor_object->position.x;
|
||||||
|
model->anchor_offset.y = y - model->anchor_object->position.y;
|
||||||
|
|
||||||
|
g_print ("ypos: %f %f\n", model->anchor_object->position.y,
|
||||||
|
model->anchor_object->position.x);
|
||||||
|
|
||||||
|
g_print ("anchor offset: %f %f\n",
|
||||||
|
model->anchor_offset.x,
|
||||||
|
model->anchor_offset.y);
|
||||||
|
|
||||||
|
model->anchor_object->immobile = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
model_set_anchor (Model *model,
|
||||||
|
int x,
|
||||||
|
int y)
|
||||||
|
{
|
||||||
|
if (model->anchor_object)
|
||||||
|
model->anchor_object->immobile = 0;
|
||||||
|
|
||||||
|
model->anchor_object = model_find_nearest (model, x, y);
|
||||||
|
model->anchor_offset.x = model->anchor_object->position.x - x;
|
||||||
|
model->anchor_offset.y = model->anchor_object->position.y - y;
|
||||||
|
|
||||||
|
model->anchor_object->immobile = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
model_update_move (Model *model, int x, int y)
|
||||||
|
{
|
||||||
|
model->anchor_object->position.x = x - model->anchor_offset.x;
|
||||||
|
model->anchor_object->position.y = y - model->anchor_offset.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_end_move (Model *model)
|
||||||
|
{
|
||||||
|
if (model->anchor_object)
|
||||||
|
{
|
||||||
|
model->anchor_object->immobile = 0;
|
||||||
|
model->anchor_object = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EPSILON 0.01
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
model_is_calm (Model *model)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
gboolean calm = TRUE;
|
||||||
|
|
||||||
|
for (i = 0; i < model->num_objects; i++)
|
||||||
|
{
|
||||||
|
if (model->objects[i].velocity.x > EPSILON ||
|
||||||
|
model->objects[i].velocity.y > EPSILON ||
|
||||||
|
model->objects[i].velocity.x < - EPSILON ||
|
||||||
|
model->objects[i].velocity.y < - EPSILON)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
model_step (Model *model)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < model->num_springs; i++)
|
||||||
|
spring_exert_forces (&model->springs[i], model->k);
|
||||||
|
|
||||||
|
for (i = 0; i < model->num_objects; i++)
|
||||||
|
model_step_object (model, &model->objects[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
model_destroy (Model *model)
|
||||||
|
{
|
||||||
|
g_free (model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
model_get_position (Model *model,
|
||||||
|
int i,
|
||||||
|
int j,
|
||||||
|
double *x,
|
||||||
|
double *y)
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
*x = model->objects[j * 4 + i].position.x;
|
||||||
|
|
||||||
|
if (y)
|
||||||
|
*y = model->objects[j * 4 + i].position.y;
|
||||||
|
}
|
31
src/spring-model.h
Normal file
31
src/spring-model.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
typedef struct XYPair Point;
|
||||||
|
typedef struct XYPair Vector;
|
||||||
|
typedef struct Spring Spring;
|
||||||
|
typedef struct Object Object;
|
||||||
|
typedef struct Model Model;
|
||||||
|
|
||||||
|
Model *model_new (MetaRectangle *rectangle,
|
||||||
|
gboolean expand);
|
||||||
|
void model_destroy (Model *model);
|
||||||
|
void
|
||||||
|
model_get_position (Model *model,
|
||||||
|
int i,
|
||||||
|
int j,
|
||||||
|
double *x,
|
||||||
|
double *y);
|
||||||
|
void
|
||||||
|
model_step (Model *model);
|
||||||
|
void
|
||||||
|
model_destroy (Model *model);
|
||||||
|
gboolean
|
||||||
|
model_is_calm (Model *model);
|
||||||
|
void
|
||||||
|
model_set_anchor (Model *model,
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
void
|
||||||
|
model_begin_move (Model *model, int x, int y);
|
||||||
|
void
|
||||||
|
model_update_move (Model *model, int x, int y);
|
65
src/window.c
65
src/window.c
@ -39,6 +39,7 @@
|
|||||||
#include "resizepopup.h"
|
#include "resizepopup.h"
|
||||||
#include "xprops.h"
|
#include "xprops.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "window-props.h"
|
#include "window-props.h"
|
||||||
#include "constraints.h"
|
#include "constraints.h"
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
@ -6661,22 +6662,23 @@ update_move (MetaWindow *window,
|
|||||||
int new_x, new_y;
|
int new_x, new_y;
|
||||||
MetaRectangle old;
|
MetaRectangle old;
|
||||||
int shake_threshold;
|
int shake_threshold;
|
||||||
|
MetaDisplay *display = window->display;
|
||||||
|
|
||||||
window->display->grab_latest_motion_x = x;
|
display->grab_latest_motion_x = x;
|
||||||
window->display->grab_latest_motion_y = y;
|
display->grab_latest_motion_y = y;
|
||||||
|
|
||||||
dx = x - window->display->grab_anchor_root_x;
|
dx = x - display->grab_anchor_root_x;
|
||||||
dy = y - window->display->grab_anchor_root_y;
|
dy = y - display->grab_anchor_root_y;
|
||||||
|
|
||||||
new_x = window->display->grab_anchor_window_pos.x + dx;
|
new_x = display->grab_anchor_window_pos.x + dx;
|
||||||
new_y = window->display->grab_anchor_window_pos.y + dy;
|
new_y = 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",
|
meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d\n",
|
||||||
x, y,
|
x, y,
|
||||||
window->display->grab_anchor_root_x,
|
display->grab_anchor_root_x,
|
||||||
window->display->grab_anchor_root_y,
|
display->grab_anchor_root_y,
|
||||||
window->display->grab_anchor_window_pos.x,
|
display->grab_anchor_window_pos.x,
|
||||||
window->display->grab_anchor_window_pos.y,
|
display->grab_anchor_window_pos.y,
|
||||||
dx, dy);
|
dx, dy);
|
||||||
|
|
||||||
/* Don't bother doing anything if no move has been specified. (This
|
/* Don't bother doing anything if no move has been specified. (This
|
||||||
@ -6703,22 +6705,22 @@ update_move (MetaWindow *window,
|
|||||||
|
|
||||||
/* move the unmaximized window to the cursor */
|
/* move the unmaximized window to the cursor */
|
||||||
prop =
|
prop =
|
||||||
((double)(x - window->display->grab_initial_window_pos.x)) /
|
((double)(x - display->grab_initial_window_pos.x)) /
|
||||||
((double)window->display->grab_initial_window_pos.width);
|
((double)display->grab_initial_window_pos.width);
|
||||||
|
|
||||||
window->display->grab_initial_window_pos.x =
|
display->grab_initial_window_pos.x =
|
||||||
x - window->saved_rect.width * prop;
|
x - window->saved_rect.width * prop;
|
||||||
window->display->grab_initial_window_pos.y = y;
|
display->grab_initial_window_pos.y = y;
|
||||||
|
|
||||||
if (window->frame)
|
if (window->frame)
|
||||||
{
|
{
|
||||||
window->display->grab_initial_window_pos.y += window->frame->child_y / 2;
|
display->grab_initial_window_pos.y += window->frame->child_y / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->saved_rect.x = window->display->grab_initial_window_pos.x;
|
window->saved_rect.x = display->grab_initial_window_pos.x;
|
||||||
window->saved_rect.y = window->display->grab_initial_window_pos.y;
|
window->saved_rect.y = display->grab_initial_window_pos.y;
|
||||||
window->display->grab_anchor_root_x = x;
|
display->grab_anchor_root_x = x;
|
||||||
window->display->grab_anchor_root_y = y;
|
display->grab_anchor_root_y = y;
|
||||||
|
|
||||||
meta_window_unmaximize (window,
|
meta_window_unmaximize (window,
|
||||||
META_MAXIMIZE_HORIZONTAL |
|
META_MAXIMIZE_HORIZONTAL |
|
||||||
@ -6766,9 +6768,9 @@ update_move (MetaWindow *window,
|
|||||||
META_MAXIMIZE_VERTICAL);
|
META_MAXIMIZE_VERTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
window->display->grab_initial_window_pos = work_area;
|
display->grab_initial_window_pos = work_area;
|
||||||
window->display->grab_anchor_root_x = x;
|
display->grab_anchor_root_x = x;
|
||||||
window->display->grab_anchor_root_y = y;
|
display->grab_anchor_root_y = y;
|
||||||
window->shaken_loose = FALSE;
|
window->shaken_loose = FALSE;
|
||||||
|
|
||||||
meta_window_maximize (window,
|
meta_window_maximize (window,
|
||||||
@ -6780,8 +6782,8 @@ update_move (MetaWindow *window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->display->grab_wireframe_active)
|
if (display->grab_wireframe_active)
|
||||||
old = window->display->grab_wireframe_rect;
|
old = display->grab_wireframe_rect;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
old = window->rect;
|
old = window->rect;
|
||||||
@ -6804,10 +6806,19 @@ update_move (MetaWindow *window,
|
|||||||
snap,
|
snap,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
if (window->display->grab_wireframe_active)
|
if (display->compositor)
|
||||||
|
{
|
||||||
|
int root_x = new_x - display->grab_anchor_window_pos.x + display->grab_anchor_root_x;
|
||||||
|
int root_y = new_y - display->grab_anchor_window_pos.y + display->grab_anchor_root_y;
|
||||||
|
|
||||||
|
meta_compositor_update_move (display->compositor,
|
||||||
|
window, root_x, root_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display->grab_wireframe_active)
|
||||||
meta_window_update_wireframe (window, new_x, new_y,
|
meta_window_update_wireframe (window, new_x, new_y,
|
||||||
window->display->grab_wireframe_rect.width,
|
display->grab_wireframe_rect.width,
|
||||||
window->display->grab_wireframe_rect.height);
|
display->grab_wireframe_rect.height);
|
||||||
else
|
else
|
||||||
meta_window_move (window, TRUE, new_x, new_y);
|
meta_window_move (window, TRUE, new_x, new_y);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user