~ubuntu-branches/ubuntu/natty/mutter/natty

1 by Didier Roche
Import upstream version 2.27.1
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3
/*
4
 * Copyright (c) 2008 Intel Corp.
5
 *
6
 * Author: Tomas Frydrych <tf@linux.intel.com>
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License as
10
 * published by the Free Software Foundation; either version 2 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21
 * 02111-1307, USA.
22
 */
23
22 by Rico Tzschichholz
* New upstream release
24
#include <meta/meta-plugin.h>
25
#include <meta/window.h>
1 by Didier Roche
Import upstream version 2.27.1
26
27
#include <libintl.h>
28
#define _(x) dgettext (GETTEXT_PACKAGE, x)
29
#define N_(x) x
30
31
#include <clutter/clutter.h>
32
#include <gmodule.h>
33
#include <string.h>
34
35
#define DESTROY_TIMEOUT   250
36
#define MINIMIZE_TIMEOUT  250
37
#define MAXIMIZE_TIMEOUT  250
38
#define MAP_TIMEOUT       250
39
#define SWITCH_TIMEOUT    500
40
41
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
42
12 by Robert Ancell
* New upstream release
43
#define META_TYPE_DEFAULT_PLUGIN            (meta_default_plugin_get_type ())
44
#define META_DEFAULT_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
45
#define META_DEFAULT_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
46
#define META_IS_DEFAULT_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_DEFAULT_PLUGIN_TYPE))
47
#define META_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_DEFAULT_PLUGIN))
48
#define META_DEFAULT_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
49
50
#define META_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
51
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginPrivate))
52
53
typedef struct _MetaDefaultPlugin        MetaDefaultPlugin;
54
typedef struct _MetaDefaultPluginClass   MetaDefaultPluginClass;
55
typedef struct _MetaDefaultPluginPrivate MetaDefaultPluginPrivate;
56
57
struct _MetaDefaultPlugin
1 by Didier Roche
Import upstream version 2.27.1
58
{
12 by Robert Ancell
* New upstream release
59
  MetaPlugin parent;
1 by Didier Roche
Import upstream version 2.27.1
60
12 by Robert Ancell
* New upstream release
61
  MetaDefaultPluginPrivate *priv;
1 by Didier Roche
Import upstream version 2.27.1
62
};
63
12 by Robert Ancell
* New upstream release
64
struct _MetaDefaultPluginClass
1 by Didier Roche
Import upstream version 2.27.1
65
{
12 by Robert Ancell
* New upstream release
66
  MetaPluginClass parent_class;
1 by Didier Roche
Import upstream version 2.27.1
67
};
68
69
static GQuark actor_data_quark = 0;
70
12 by Robert Ancell
* New upstream release
71
static void minimize   (MetaPlugin      *plugin,
72
                        MetaWindowActor *actor);
73
static void map        (MetaPlugin      *plugin,
74
                        MetaWindowActor *actor);
75
static void destroy    (MetaPlugin      *plugin,
76
                        MetaWindowActor *actor);
77
static void maximize   (MetaPlugin      *plugin,
78
                        MetaWindowActor *actor,
79
                        gint             x,
80
                        gint             y,
81
                        gint             width,
82
                        gint             height);
83
static void unmaximize (MetaPlugin      *plugin,
84
                        MetaWindowActor *actor,
85
                        gint             x,
86
                        gint             y,
87
                        gint             width,
88
                        gint             height);
89
90
static void switch_workspace (MetaPlugin          *plugin,
91
                              gint                 from,
92
                              gint                 to,
93
                              MetaMotionDirection  direction);
94
95
static void kill_window_effects   (MetaPlugin      *plugin,
96
                                   MetaWindowActor *actor);
97
static void kill_switch_workspace (MetaPlugin      *plugin);
98
99
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
100
101
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
1 by Didier Roche
Import upstream version 2.27.1
102
103
/*
104
 * Plugin private data that we store in the .plugin_private member.
105
 */
12 by Robert Ancell
* New upstream release
106
struct _MetaDefaultPluginPrivate
1 by Didier Roche
Import upstream version 2.27.1
107
{
108
  /* Valid only when switch_workspace effect is in progress */
109
  ClutterTimeline       *tml_switch_workspace1;
110
  ClutterTimeline       *tml_switch_workspace2;
111
  ClutterActor          *desktop1;
112
  ClutterActor          *desktop2;
113
12 by Robert Ancell
* New upstream release
114
  MetaPluginInfo         info;
1 by Didier Roche
Import upstream version 2.27.1
115
116
  gboolean               debug_mode : 1;
117
};
118
119
/*
120
 * Per actor private data we attach to each actor.
121
 */
122
typedef struct _ActorPrivate
123
{
124
  ClutterActor *orig_parent;
125
126
  ClutterTimeline *tml_minimize;
127
  ClutterTimeline *tml_maximize;
128
  ClutterTimeline *tml_destroy;
129
  ClutterTimeline *tml_map;
130
131
  gboolean      is_minimized : 1;
132
  gboolean      is_maximized : 1;
133
} ActorPrivate;
134
135
/* callback data for when animations complete */
136
typedef struct
137
{
138
  ClutterActor *actor;
12 by Robert Ancell
* New upstream release
139
  MetaPlugin *plugin;
1 by Didier Roche
Import upstream version 2.27.1
140
} EffectCompleteData;
141
142
143
static void
12 by Robert Ancell
* New upstream release
144
meta_default_plugin_dispose (GObject *object)
1 by Didier Roche
Import upstream version 2.27.1
145
{
12 by Robert Ancell
* New upstream release
146
  /* MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (object)->priv;
1 by Didier Roche
Import upstream version 2.27.1
147
  */
12 by Robert Ancell
* New upstream release
148
  G_OBJECT_CLASS (meta_default_plugin_parent_class)->dispose (object);
1 by Didier Roche
Import upstream version 2.27.1
149
}
150
151
static void
12 by Robert Ancell
* New upstream release
152
meta_default_plugin_finalize (GObject *object)
1 by Didier Roche
Import upstream version 2.27.1
153
{
12 by Robert Ancell
* New upstream release
154
  G_OBJECT_CLASS (meta_default_plugin_parent_class)->finalize (object);
1 by Didier Roche
Import upstream version 2.27.1
155
}
156
157
static void
12 by Robert Ancell
* New upstream release
158
meta_default_plugin_set_property (GObject      *object,
1 by Didier Roche
Import upstream version 2.27.1
159
			    guint         prop_id,
160
			    const GValue *value,
161
			    GParamSpec   *pspec)
162
{
163
  switch (prop_id)
164
    {
165
    default:
166
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167
      break;
168
    }
169
}
170
171
static void
12 by Robert Ancell
* New upstream release
172
meta_default_plugin_get_property (GObject    *object,
1 by Didier Roche
Import upstream version 2.27.1
173
			    guint       prop_id,
174
			    GValue     *value,
175
			    GParamSpec *pspec)
176
{
177
  switch (prop_id)
178
    {
179
    default:
180
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
181
      break;
182
    }
183
}
184
185
static void
12 by Robert Ancell
* New upstream release
186
start (MetaPlugin *plugin)
1 by Didier Roche
Import upstream version 2.27.1
187
{
12 by Robert Ancell
* New upstream release
188
  MetaDefaultPluginPrivate *priv   = META_DEFAULT_PLUGIN (plugin)->priv;
1 by Didier Roche
Import upstream version 2.27.1
189
190
  guint destroy_timeout  = DESTROY_TIMEOUT;
191
  guint minimize_timeout = MINIMIZE_TIMEOUT;
192
  guint maximize_timeout = MAXIMIZE_TIMEOUT;
193
  guint map_timeout      = MAP_TIMEOUT;
194
  guint switch_timeout   = SWITCH_TIMEOUT;
195
12 by Robert Ancell
* New upstream release
196
  if (meta_plugin_debug_mode (plugin))
1 by Didier Roche
Import upstream version 2.27.1
197
    {
198
      g_debug ("Plugin %s: Entering debug mode.", priv->info.name);
199
200
      priv->debug_mode = TRUE;
201
202
      /*
203
       * Double the effect duration to make them easier to observe.
204
       */
205
      destroy_timeout  *= 2;
206
      minimize_timeout *= 2;
207
      maximize_timeout *= 2;
208
      map_timeout      *= 2;
209
      switch_timeout   *= 2;
210
    }
211
}
212
213
static void
12 by Robert Ancell
* New upstream release
214
meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
1 by Didier Roche
Import upstream version 2.27.1
215
{
216
  GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
12 by Robert Ancell
* New upstream release
217
  MetaPluginClass *plugin_class  = META_PLUGIN_CLASS (klass);
1 by Didier Roche
Import upstream version 2.27.1
218
12 by Robert Ancell
* New upstream release
219
  gobject_class->finalize        = meta_default_plugin_finalize;
220
  gobject_class->dispose         = meta_default_plugin_dispose;
221
  gobject_class->set_property    = meta_default_plugin_set_property;
222
  gobject_class->get_property    = meta_default_plugin_get_property;
1 by Didier Roche
Import upstream version 2.27.1
223
1.1.7 by Didier Roche
Import upstream version 2.31.2
224
  plugin_class->start            = start;
1 by Didier Roche
Import upstream version 2.27.1
225
  plugin_class->map              = map;
226
  plugin_class->minimize         = minimize;
227
  plugin_class->maximize         = maximize;
228
  plugin_class->unmaximize       = unmaximize;
229
  plugin_class->destroy          = destroy;
230
  plugin_class->switch_workspace = switch_workspace;
231
  plugin_class->plugin_info      = plugin_info;
10.1.11 by Didier Roche
* New upstream release:
232
  plugin_class->kill_window_effects   = kill_window_effects;
233
  plugin_class->kill_switch_workspace = kill_switch_workspace;
1 by Didier Roche
Import upstream version 2.27.1
234
12 by Robert Ancell
* New upstream release
235
  g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
1 by Didier Roche
Import upstream version 2.27.1
236
}
237
238
static void
12 by Robert Ancell
* New upstream release
239
meta_default_plugin_init (MetaDefaultPlugin *self)
1 by Didier Roche
Import upstream version 2.27.1
240
{
12 by Robert Ancell
* New upstream release
241
  MetaDefaultPluginPrivate *priv;
1 by Didier Roche
Import upstream version 2.27.1
242
12 by Robert Ancell
* New upstream release
243
  self->priv = priv = META_DEFAULT_PLUGIN_GET_PRIVATE (self);
1 by Didier Roche
Import upstream version 2.27.1
244
245
  priv->info.name        = "Default Effects";
246
  priv->info.version     = "0.1";
247
  priv->info.author      = "Intel Corp.";
248
  priv->info.license     = "GPL";
249
  priv->info.description = "This is an example of a plugin implementation.";
250
}
251
252
/*
253
 * Actor private data accessor
254
 */
255
static void
256
free_actor_private (gpointer data)
257
{
258
  if (G_LIKELY (data != NULL))
259
    g_slice_free (ActorPrivate, data);
260
}
261
262
static ActorPrivate *
12 by Robert Ancell
* New upstream release
263
get_actor_private (MetaWindowActor *actor)
1 by Didier Roche
Import upstream version 2.27.1
264
{
265
  ActorPrivate *priv = g_object_get_qdata (G_OBJECT (actor), actor_data_quark);
266
267
  if (G_UNLIKELY (actor_data_quark == 0))
268
    actor_data_quark = g_quark_from_static_string (ACTOR_DATA_KEY);
269
270
  if (G_UNLIKELY (!priv))
271
    {
272
      priv = g_slice_new0 (ActorPrivate);
273
274
      g_object_set_qdata_full (G_OBJECT (actor),
275
                               actor_data_quark, priv,
276
                               free_actor_private);
277
    }
278
279
  return priv;
280
}
281
282
static void
283
on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
284
{
12 by Robert Ancell
* New upstream release
285
  MetaPlugin               *plugin  = META_PLUGIN (data);
286
  MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
287
  GList        *l     = meta_plugin_get_window_actors (plugin);
1 by Didier Roche
Import upstream version 2.27.1
288
289
  while (l)
290
    {
291
      ClutterActor *a = l->data;
12 by Robert Ancell
* New upstream release
292
      MetaWindowActor *window_actor = META_WINDOW_ACTOR (a);
293
      ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
294
295
      if (apriv->orig_parent)
296
        {
297
          clutter_actor_reparent (a, apriv->orig_parent);
298
          apriv->orig_parent = NULL;
299
        }
300
301
      l = l->next;
302
    }
303
304
  clutter_actor_destroy (priv->desktop1);
305
  clutter_actor_destroy (priv->desktop2);
306
307
  priv->tml_switch_workspace1 = NULL;
308
  priv->tml_switch_workspace2 = NULL;
309
  priv->desktop1 = NULL;
310
  priv->desktop2 = NULL;
311
12 by Robert Ancell
* New upstream release
312
  meta_plugin_switch_workspace_completed (plugin);
1 by Didier Roche
Import upstream version 2.27.1
313
}
314
315
static void
12 by Robert Ancell
* New upstream release
316
switch_workspace (MetaPlugin *plugin,
10.1.11 by Didier Roche
* New upstream release:
317
                  gint from, gint to,
1 by Didier Roche
Import upstream version 2.27.1
318
                  MetaMotionDirection direction)
319
{
12 by Robert Ancell
* New upstream release
320
  MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
1 by Didier Roche
Import upstream version 2.27.1
321
  GList        *l;
322
  ClutterActor *workspace0  = clutter_group_new ();
323
  ClutterActor *workspace1  = clutter_group_new ();
324
  ClutterActor *stage;
325
  int           screen_width, screen_height;
326
  ClutterAnimation *animation;
327
12 by Robert Ancell
* New upstream release
328
  stage = meta_plugin_get_stage (plugin);
1 by Didier Roche
Import upstream version 2.27.1
329
12 by Robert Ancell
* New upstream release
330
  meta_plugin_query_screen_size (plugin,
1 by Didier Roche
Import upstream version 2.27.1
331
					      &screen_width,
332
					      &screen_height);
333
  clutter_actor_set_anchor_point (workspace1,
334
                                  screen_width,
335
                                  screen_height);
336
  clutter_actor_set_position (workspace1,
337
                              screen_width,
338
                              screen_height);
339
340
  clutter_actor_set_scale (workspace1, 0.0, 0.0);
341
342
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace1);
343
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace0);
344
345
  if (from == to)
346
    {
12 by Robert Ancell
* New upstream release
347
      meta_plugin_switch_workspace_completed (plugin);
1 by Didier Roche
Import upstream version 2.27.1
348
      return;
349
    }
350
12 by Robert Ancell
* New upstream release
351
  l = g_list_last (meta_plugin_get_window_actors (plugin));
1 by Didier Roche
Import upstream version 2.27.1
352
353
  while (l)
354
    {
12 by Robert Ancell
* New upstream release
355
      MetaWindowActor *window_actor = l->data;
356
      ActorPrivate    *apriv	    = get_actor_private (window_actor);
357
      ClutterActor    *actor	    = CLUTTER_ACTOR (window_actor);
358
      gint             win_workspace;
1 by Didier Roche
Import upstream version 2.27.1
359
12 by Robert Ancell
* New upstream release
360
      win_workspace = meta_window_actor_get_workspace (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
361
362
      if (win_workspace == to || win_workspace == from)
363
        {
12 by Robert Ancell
* New upstream release
364
          apriv->orig_parent = clutter_actor_get_parent (actor);
1 by Didier Roche
Import upstream version 2.27.1
365
12 by Robert Ancell
* New upstream release
366
          clutter_actor_reparent (actor,
1 by Didier Roche
Import upstream version 2.27.1
367
				  win_workspace == to ? workspace1 : workspace0);
12 by Robert Ancell
* New upstream release
368
          clutter_actor_show_all (actor);
369
          clutter_actor_raise_top (actor);
1 by Didier Roche
Import upstream version 2.27.1
370
        }
371
      else if (win_workspace < 0)
372
        {
373
          /* Sticky window */
374
          apriv->orig_parent = NULL;
375
        }
376
      else
377
        {
378
          /* Window on some other desktop */
12 by Robert Ancell
* New upstream release
379
          clutter_actor_hide (actor);
1 by Didier Roche
Import upstream version 2.27.1
380
          apriv->orig_parent = NULL;
381
        }
382
383
      l = l->prev;
384
    }
385
386
  priv->desktop1 = workspace0;
387
  priv->desktop2 = workspace1;
388
389
  animation = clutter_actor_animate (workspace0, CLUTTER_EASE_IN_SINE,
390
                                     SWITCH_TIMEOUT,
391
                                     "scale-x", 1.0,
392
                                     "scale-y", 1.0,
393
                                     NULL);
394
  priv->tml_switch_workspace1 = clutter_animation_get_timeline (animation);
395
  g_signal_connect (priv->tml_switch_workspace1,
396
                    "completed",
397
                    G_CALLBACK (on_switch_workspace_effect_complete),
10.1.11 by Didier Roche
* New upstream release:
398
                    plugin);
1 by Didier Roche
Import upstream version 2.27.1
399
400
  animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
401
                                     SWITCH_TIMEOUT,
402
                                     "scale-x", 0.0,
403
                                     "scale-y", 0.0,
404
                                     NULL);
405
  priv->tml_switch_workspace2 = clutter_animation_get_timeline (animation);
406
}
407
408
409
/*
410
 * Minimize effect completion callback; this function restores actor state, and
411
 * calls the manager callback function.
412
 */
413
static void
414
on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
415
{
416
  /*
417
   * Must reverse the effect of the effect; must hide it first to ensure
418
   * that the restoration will not be visible.
419
   */
12 by Robert Ancell
* New upstream release
420
  MetaPlugin *plugin = data->plugin;
1 by Didier Roche
Import upstream version 2.27.1
421
  ActorPrivate *apriv;
12 by Robert Ancell
* New upstream release
422
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
1 by Didier Roche
Import upstream version 2.27.1
423
12 by Robert Ancell
* New upstream release
424
  apriv = get_actor_private (META_WINDOW_ACTOR (data->actor));
1 by Didier Roche
Import upstream version 2.27.1
425
  apriv->tml_minimize = NULL;
426
427
  clutter_actor_hide (data->actor);
428
429
  /* FIXME - we shouldn't assume the original scale, it should be saved
430
   * at the start of the effect */
431
  clutter_actor_set_scale (data->actor, 1.0, 1.0);
432
  clutter_actor_move_anchor_point_from_gravity (data->actor,
433
                                                CLUTTER_GRAVITY_NORTH_WEST);
434
435
  /* Now notify the manager that we are done with this effect */
12 by Robert Ancell
* New upstream release
436
  meta_plugin_minimize_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
437
438
  g_free (data);
439
}
440
441
/*
442
 * Simple minimize handler: it applies a scale effect (which must be reversed on
443
 * completion).
444
 */
445
static void
12 by Robert Ancell
* New upstream release
446
minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
1 by Didier Roche
Import upstream version 2.27.1
447
{
12 by Robert Ancell
* New upstream release
448
  MetaWindowType type;
449
  MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
450
  ClutterActor *actor  = CLUTTER_ACTOR (window_actor);
451
452
453
  type = meta_window_get_window_type (meta_window);
454
455
  if (type == META_WINDOW_NORMAL)
1 by Didier Roche
Import upstream version 2.27.1
456
    {
457
      ClutterAnimation *animation;
458
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
12 by Robert Ancell
* New upstream release
459
      ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
460
461
      apriv->is_minimized = TRUE;
462
463
      clutter_actor_move_anchor_point_from_gravity (actor,
464
                                                    CLUTTER_GRAVITY_CENTER);
465
466
      animation = clutter_actor_animate (actor,
467
                                         CLUTTER_EASE_IN_SINE,
468
                                         MINIMIZE_TIMEOUT,
469
                                         "scale-x", 0.0,
470
                                         "scale-y", 0.0,
471
                                         NULL);
472
      apriv->tml_minimize = clutter_animation_get_timeline (animation);
473
      data->plugin = plugin;
474
      data->actor = actor;
475
      g_signal_connect (apriv->tml_minimize, "completed",
476
                        G_CALLBACK (on_minimize_effect_complete),
477
                        data);
478
479
    }
480
  else
12 by Robert Ancell
* New upstream release
481
    meta_plugin_minimize_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
482
}
483
484
/*
485
 * Minimize effect completion callback; this function restores actor state, and
486
 * calls the manager callback function.
487
 */
488
static void
489
on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
490
{
491
  /*
492
   * Must reverse the effect of the effect.
493
   */
12 by Robert Ancell
* New upstream release
494
  MetaPlugin *plugin = data->plugin;
495
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
496
  ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
497
498
  apriv->tml_maximize = NULL;
499
500
  /* FIXME - don't assume the original scale was 1.0 */
501
  clutter_actor_set_scale (data->actor, 1.0, 1.0);
502
  clutter_actor_move_anchor_point_from_gravity (data->actor,
503
                                                CLUTTER_GRAVITY_NORTH_WEST);
504
505
  /* Now notify the manager that we are done with this effect */
12 by Robert Ancell
* New upstream release
506
  meta_plugin_maximize_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
507
508
  g_free (data);
509
}
510
511
/*
512
 * The Nature of Maximize operation is such that it is difficult to do a visual
513
 * effect that would work well. Scaling, the obvious effect, does not work that
514
 * well, because at the end of the effect we end up with window content bigger
515
 * and differently laid out than in the real window; this is a proof concept.
516
 *
517
 * (Something like a sound would be more appropriate.)
518
 */
519
static void
12 by Robert Ancell
* New upstream release
520
maximize (MetaPlugin *plugin,
521
          MetaWindowActor *window_actor,
1 by Didier Roche
Import upstream version 2.27.1
522
          gint end_x, gint end_y, gint end_width, gint end_height)
523
{
12 by Robert Ancell
* New upstream release
524
  MetaWindowType type;
525
  ClutterActor *actor = CLUTTER_ACTOR (window_actor);
526
  MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
527
528
  gdouble  scale_x    = 1.0;
529
  gdouble  scale_y    = 1.0;
530
  gfloat   anchor_x   = 0;
531
  gfloat   anchor_y   = 0;
532
12 by Robert Ancell
* New upstream release
533
  type = meta_window_get_window_type (meta_window);
1 by Didier Roche
Import upstream version 2.27.1
534
12 by Robert Ancell
* New upstream release
535
  if (type == META_WINDOW_NORMAL)
1 by Didier Roche
Import upstream version 2.27.1
536
    {
537
      ClutterAnimation *animation;
538
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
12 by Robert Ancell
* New upstream release
539
      ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
540
      gfloat width, height;
541
      gfloat x, y;
542
543
      apriv->is_maximized = TRUE;
544
545
      clutter_actor_get_size (actor, &width, &height);
546
      clutter_actor_get_position (actor, &x, &y);
547
548
      /*
549
       * Work out the scale and anchor point so that the window is expanding
550
       * smoothly into the target size.
551
       */
552
      scale_x = (gdouble)end_width / (gdouble) width;
553
      scale_y = (gdouble)end_height / (gdouble) height;
554
555
      anchor_x = (gdouble)(x - end_x)*(gdouble)width /
556
        ((gdouble)(end_width - width));
557
      anchor_y = (gdouble)(y - end_y)*(gdouble)height /
558
        ((gdouble)(end_height - height));
559
560
      clutter_actor_move_anchor_point (actor, anchor_x, anchor_y);
561
562
      animation = clutter_actor_animate (actor,
563
                                         CLUTTER_EASE_IN_SINE,
564
                                         MAXIMIZE_TIMEOUT,
565
                                         "scale-x", scale_x,
566
                                         "scale-y", scale_y,
567
                                         NULL);
568
      apriv->tml_maximize = clutter_animation_get_timeline (animation);
569
      data->plugin = plugin;
570
      data->actor = actor;
571
      g_signal_connect (apriv->tml_maximize, "completed",
572
                        G_CALLBACK (on_maximize_effect_complete),
573
                        data);
574
      return;
575
    }
576
12 by Robert Ancell
* New upstream release
577
  meta_plugin_maximize_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
578
}
579
580
/*
581
 * See comments on the maximize() function.
582
 *
583
 * (Just a skeleton code.)
584
 */
585
static void
12 by Robert Ancell
* New upstream release
586
unmaximize (MetaPlugin *plugin,
587
            MetaWindowActor *window_actor,
1 by Didier Roche
Import upstream version 2.27.1
588
            gint end_x, gint end_y, gint end_width, gint end_height)
589
{
12 by Robert Ancell
* New upstream release
590
  MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
591
  MetaWindowType type = meta_window_get_window_type (meta_window);
1 by Didier Roche
Import upstream version 2.27.1
592
12 by Robert Ancell
* New upstream release
593
  if (type == META_WINDOW_NORMAL)
1 by Didier Roche
Import upstream version 2.27.1
594
    {
12 by Robert Ancell
* New upstream release
595
      ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
596
597
      apriv->is_maximized = FALSE;
598
    }
599
600
  /* Do this conditionally, if the effect requires completion callback. */
12 by Robert Ancell
* New upstream release
601
  meta_plugin_unmaximize_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
602
}
603
604
static void
605
on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
606
{
607
  /*
608
   * Must reverse the effect of the effect.
609
   */
12 by Robert Ancell
* New upstream release
610
  MetaPlugin *plugin = data->plugin;
611
  MetaWindowActor  *window_actor = META_WINDOW_ACTOR (data->actor);
612
  ActorPrivate  *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
613
614
  apriv->tml_map = NULL;
615
616
  clutter_actor_move_anchor_point_from_gravity (data->actor,
617
                                                CLUTTER_GRAVITY_NORTH_WEST);
618
619
  /* Now notify the manager that we are done with this effect */
12 by Robert Ancell
* New upstream release
620
  meta_plugin_map_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
621
622
  g_free (data);
623
}
624
625
/*
626
 * Simple map handler: it applies a scale effect which must be reversed on
627
 * completion).
628
 */
629
static void
12 by Robert Ancell
* New upstream release
630
map (MetaPlugin *plugin, MetaWindowActor *window_actor)
1 by Didier Roche
Import upstream version 2.27.1
631
{
12 by Robert Ancell
* New upstream release
632
  MetaWindowType type;
633
  ClutterActor *actor = CLUTTER_ACTOR (window_actor);
634
  MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
635
636
  type = meta_window_get_window_type (meta_window);
637
638
  if (type == META_WINDOW_NORMAL)
1 by Didier Roche
Import upstream version 2.27.1
639
    {
640
      ClutterAnimation *animation;
641
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
12 by Robert Ancell
* New upstream release
642
      ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
643
644
      clutter_actor_move_anchor_point_from_gravity (actor,
645
                                                    CLUTTER_GRAVITY_CENTER);
646
647
      clutter_actor_set_scale (actor, 0.0, 0.0);
648
      clutter_actor_show (actor);
649
650
      animation = clutter_actor_animate (actor,
651
                                         CLUTTER_EASE_IN_SINE,
652
                                         MAP_TIMEOUT,
653
                                         "scale-x", 1.0,
654
                                         "scale-y", 1.0,
655
                                         NULL);
656
      apriv->tml_map = clutter_animation_get_timeline (animation);
657
      data->actor = actor;
658
      data->plugin = plugin;
659
      g_signal_connect (apriv->tml_map, "completed",
660
                        G_CALLBACK (on_map_effect_complete),
661
                        data);
662
663
      apriv->is_minimized = FALSE;
664
665
    }
666
  else
12 by Robert Ancell
* New upstream release
667
    meta_plugin_map_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
668
}
669
670
/*
671
 * Destroy effect completion callback; this is a simple effect that requires no
672
 * further action than notifying the manager that the effect is completed.
673
 */
674
static void
675
on_destroy_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
676
{
12 by Robert Ancell
* New upstream release
677
  MetaPlugin *plugin = data->plugin;
678
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
679
  ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
680
681
  apriv->tml_destroy = NULL;
682
12 by Robert Ancell
* New upstream release
683
  meta_plugin_destroy_completed (plugin, window_actor);
1 by Didier Roche
Import upstream version 2.27.1
684
}
685
686
/*
687
 * Simple TV-out like effect.
688
 */
689
static void
12 by Robert Ancell
* New upstream release
690
destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
1 by Didier Roche
Import upstream version 2.27.1
691
{
12 by Robert Ancell
* New upstream release
692
  MetaWindowType type;
693
  ClutterActor *actor = CLUTTER_ACTOR (window_actor);
694
  MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
695
696
  type = meta_window_get_window_type (meta_window);
697
698
  if (type == META_WINDOW_NORMAL)
1 by Didier Roche
Import upstream version 2.27.1
699
    {
700
      ClutterAnimation *animation;
701
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
12 by Robert Ancell
* New upstream release
702
      ActorPrivate *apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
703
704
      clutter_actor_move_anchor_point_from_gravity (actor,
705
                                                    CLUTTER_GRAVITY_CENTER);
706
707
      animation = clutter_actor_animate (actor,
708
                                         CLUTTER_EASE_IN_SINE,
709
                                         DESTROY_TIMEOUT,
710
                                         "scale-x", 0.0,
711
                                         "scale-y", 1.0,
712
                                         NULL);
713
      apriv->tml_destroy = clutter_animation_get_timeline (animation);
714
      data->plugin = plugin;
715
      data->actor = actor;
716
      g_signal_connect (apriv->tml_destroy, "completed",
717
                        G_CALLBACK (on_destroy_effect_complete),
718
                        data);
719
    }
720
  else
12 by Robert Ancell
* New upstream release
721
    meta_plugin_destroy_completed (plugin, window_actor);
10.1.11 by Didier Roche
* New upstream release:
722
}
723
724
static void
12 by Robert Ancell
* New upstream release
725
kill_switch_workspace (MetaPlugin     *plugin)
10.1.11 by Didier Roche
* New upstream release:
726
{
12 by Robert Ancell
* New upstream release
727
  MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
10.1.11 by Didier Roche
* New upstream release:
728
729
  if (priv->tml_switch_workspace1)
730
    {
731
      clutter_timeline_stop (priv->tml_switch_workspace1);
732
      clutter_timeline_stop (priv->tml_switch_workspace2);
733
      g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
734
    }
735
}
736
737
static void
12 by Robert Ancell
* New upstream release
738
kill_window_effects (MetaPlugin      *plugin,
739
                     MetaWindowActor *window_actor)
1 by Didier Roche
Import upstream version 2.27.1
740
{
741
  ActorPrivate *apriv;
742
12 by Robert Ancell
* New upstream release
743
  apriv = get_actor_private (window_actor);
1 by Didier Roche
Import upstream version 2.27.1
744
10.1.11 by Didier Roche
* New upstream release:
745
  if (apriv->tml_minimize)
1 by Didier Roche
Import upstream version 2.27.1
746
    {
747
      clutter_timeline_stop (apriv->tml_minimize);
748
      g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
749
    }
750
10.1.11 by Didier Roche
* New upstream release:
751
  if (apriv->tml_maximize)
1 by Didier Roche
Import upstream version 2.27.1
752
    {
753
      clutter_timeline_stop (apriv->tml_maximize);
754
      g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
755
    }
756
10.1.11 by Didier Roche
* New upstream release:
757
  if (apriv->tml_map)
1 by Didier Roche
Import upstream version 2.27.1
758
    {
759
      clutter_timeline_stop (apriv->tml_map);
760
      g_signal_emit_by_name (apriv->tml_map, "completed", NULL);
761
    }
762
10.1.11 by Didier Roche
* New upstream release:
763
  if (apriv->tml_destroy)
1 by Didier Roche
Import upstream version 2.27.1
764
    {
765
      clutter_timeline_stop (apriv->tml_destroy);
766
      g_signal_emit_by_name (apriv->tml_destroy, "completed", NULL);
767
    }
768
}
769
12 by Robert Ancell
* New upstream release
770
static const MetaPluginInfo *
771
plugin_info (MetaPlugin *plugin)
1 by Didier Roche
Import upstream version 2.27.1
772
{
12 by Robert Ancell
* New upstream release
773
  MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
1 by Didier Roche
Import upstream version 2.27.1
774
775
  return &priv->info;
776
}