~canonical-dx-team/unity/unity.fix-ql-losing-focus

« back to all changes in this revision

Viewing changes to targets/mutter/plugin.vala

  • Committer: Neil Jagdish Patel
  • Date: 2010-11-11 18:51:08 UTC
  • mfrom: (572.1.58 unity-3.0)
  • Revision ID: neil.patel@canonical.com-20101111185108-71923a90txzvxbit
[merge] Unity 3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2009 Canonical Ltd
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License version 3 as
6
 
 * published by the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful,
9
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 * GNU General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 * Authored by Neil Jagdish Patel <neil.patel@canonical.com>
17
 
 *
18
 
 */
19
 
 
20
 
using GConf;
21
 
using Unity;
22
 
using Unity.Testing;
23
 
 
24
 
static string? boot_logging_filename = null;
25
 
 
26
 
namespace Unity
27
 
{
28
 
  public class DragDest: Gtk.Window
29
 
  {
30
 
    public DragDest ()
31
 
      {
32
 
        Object (type:Gtk.WindowType.TOPLEVEL,
33
 
                type_hint:Gdk.WindowTypeHint.DOCK,
34
 
                opacity:0.0);
35
 
      }
36
 
 
37
 
    construct
38
 
    {
39
 
      this.set_accept_focus (false);
40
 
    }
41
 
  }
42
 
 
43
 
  public enum InputState
44
 
  {
45
 
    NONE,
46
 
    FULLSCREEN,
47
 
    UNITY,
48
 
    ZERO,
49
 
  }
50
 
 
51
 
  /*
52
 
  public class ActorBlur : Ctk.Bin
53
 
  {
54
 
    private Clutter.Clone clone;
55
 
    //private Ctk.EffectBlur blur;
56
 
 
57
 
    public ActorBlur (Clutter.Actor actor)
58
 
    {
59
 
      clone = new Clutter.Clone (actor);
60
 
 
61
 
      add_actor (clone);
62
 
      clone.show ();
63
 
 
64
 
      clone.set_position (0, 0);
65
 
      //blur = new Ctk.EffectBlur ();
66
 
      //blur.set_factor (9f);
67
 
      //add_effect (blur);
68
 
    }
69
 
 
70
 
    construct
71
 
    {
72
 
 
73
 
    }
74
 
  }
75
 
 
76
 
  */
77
 
  public class Plugin : Object, Shell
78
 
  {
79
 
    /* Signals */
80
 
    public signal void window_minimized (Plugin plugin, Mutter.Window window);
81
 
    public signal void window_maximized (Plugin        plugin,
82
 
                                         Mutter.Window window,
83
 
                                         int           x,
84
 
                                         int           y,
85
 
                                         int           width,
86
 
                                         int           height);
87
 
    public signal void window_unmaximized (Plugin        plugin,
88
 
                                           Mutter.Window window,
89
 
                                           int           x,
90
 
                                           int           y,
91
 
                                           int           width,
92
 
                                           int           height);
93
 
    public signal void window_mapped (Plugin plugin, Mutter.Window window);
94
 
    public signal void window_destroyed (Plugin plugin, Mutter.Window window);
95
 
    public signal void kill_window_effects (Plugin plugin, Mutter.Window window);
96
 
    public signal void kill_switch_workspace (Plugin plugin);
97
 
 
98
 
    public signal void workspace_switch_event (Plugin plugin,
99
 
                                               int from,
100
 
                                               int to,
101
 
                                               int direction);
102
 
 
103
 
    public signal void restore_input_region (bool fullscreen);
104
 
 
105
 
    /* Properties */
106
 
    private Mutter.Plugin? _plugin;
107
 
    public  Mutter.Plugin? plugin {
108
 
      get { return _plugin; }
109
 
      set { _plugin = value; Idle.add (real_construct); }
110
 
    }
111
 
    private bool _super_key_enable=true;
112
 
    public bool super_key_enable {
113
 
      get { return _super_key_enable; }
114
 
      set { _super_key_enable = value; }
115
 
    }
116
 
 
117
 
    public ExposeManager expose_manager { get; private set; }
118
 
    
119
 
    public bool menus_swallow_events { get { return false; } }
120
 
 
121
 
    private bool _super_key_active = false;
122
 
    public bool super_key_active {
123
 
      get { return _super_key_active; }
124
 
      set { _super_key_active = value; }
125
 
    }
126
 
    public bool is_starting {get; set;}
127
 
 
128
 
    public bool expose_showing { get { return expose_manager.expose_showing; } }
129
 
 
130
 
    private static const int PANEL_HEIGHT        =  24;
131
 
    private static const int QUICKLAUNCHER_WIDTH = 58;
132
 
    private static const string UNDECORATED_HINT = "UNDECORATED_HINT";
133
 
 
134
 
    public Gee.ArrayList<Background> backgrounds;
135
 
    public Gdk.Rectangle primary_monitor;
136
 
 
137
 
    private Clutter.Stage    stage;
138
 
    private Application      app;
139
 
    private WindowManagement wm;
140
 
    private Maximus          maximus;
141
 
 
142
 
    /* Unity Components */
143
 
    private SpacesManager      spaces_manager;
144
 
    private Launcher.Launcher  launcher;
145
 
    private Places.Controller  places_controller;
146
 
    private Places.View        places;
147
 
    private Panel.View         panel;
148
 
    private Clutter.Rectangle  dark_box;
149
 
    private unowned Mutter.MetaWindow?  focus_window = null;
150
 
    private unowned Mutter.MetaDisplay? display = null;
151
 
 
152
 
    private DragDest drag_dest;
153
 
    private bool     places_showing;
154
 
    private bool     _fullscreen_obstruction;
155
 
    private InputState last_input_state = InputState.NONE;
156
 
 
157
 
    private Gee.ArrayList<Object> fullscreen_requests;
158
 
 
159
 
    private bool fullscreen_obstruction
160
 
      {
161
 
        get {
162
 
          return _fullscreen_obstruction;
163
 
        }
164
 
        set {
165
 
          _fullscreen_obstruction = value;
166
 
          ensure_input_region ();
167
 
        }
168
 
      }
169
 
 
170
 
    private bool grab_enabled = false;
171
 
    private DBus.Connection screensaver_conn;
172
 
    private dynamic DBus.Object screensaver;
173
 
 
174
 
    public Gesture.Dispatcher gesture_dispatcher;
175
 
    private Gesture.Type active_gesture_type = Gesture.Type.NONE;
176
 
 
177
 
    /* Pinch info */
178
 
    /* private float start_pinch_radius = 0.0f; */
179
 
    private unowned Mutter.Window? resize_window = null;
180
 
    /*private float   resize_last_x1 = 0.0f;
181
 
    private float   resize_last_y1 = 0.0f;
182
 
    private float   resize_last_x2 = 0.0f;
183
 
    private float   resize_last_y2 = 0.0f;*/
184
 
 
185
 
    /* Pan info */
186
 
    private unowned Mutter.Window? start_pan_window = null;
187
 
    private unowned Clutter.Rectangle? start_frame_rect = null;
188
 
    private float last_pan_x_root = 0.0f;
189
 
    private float last_pan_maximised_x_root = 0.0f;
190
 
    private enum MaximizeType {
191
 
      NONE,
192
 
      FULL,
193
 
      LEFT,
194
 
      RIGHT
195
 
    }
196
 
    private MaximizeType maximize_type = MaximizeType.NONE;
197
 
 
198
 
    private enum ExposeType {
199
 
      NONE,
200
 
      APPLICATION,
201
 
      WINDOWS,
202
 
      WORKSPACE
203
 
    }
204
 
    private ExposeType expose_type = ExposeType.NONE;
205
 
    private unowned Mutter.Window? start_pinch_window = null;
206
 
 
207
 
    /* const */
208
 
    private const string GCONF_DIR = "/desktop/unity/launcher";
209
 
    private const string GCONF_SUPER_KEY_ENABLE_KEY = "super_key_enable";
210
 
 
211
 
    construct
212
 
    {
213
 
      is_starting = true;
214
 
      fullscreen_requests = new Gee.ArrayList<Object> ();
215
 
      Unity.global_shell = this;
216
 
      Unity.TimelineLogger.get_default(); // just inits the timer for logging
217
 
      // attempt to get a boot logging filename
218
 
      boot_logging_filename = Environment.get_variable ("UNITY_BOOTLOG_FILENAME");
219
 
      if (boot_logging_filename != null)
220
 
        {
221
 
          Unity.is_logging = true;
222
 
        }
223
 
      else
224
 
        {
225
 
          Unity.is_logging = false;
226
 
        }
227
 
      START_FUNCTION ();
228
 
      string[] args = { "mutter" };
229
 
 
230
 
      LOGGER_START_PROCESS ("ctk_init");
231
 
      Ctk.init_after (ref args);
232
 
      LOGGER_END_PROCESS ("ctk_init");
233
 
 
234
 
      Gtk.Settings.get_default ().gtk_icon_theme_name = "ubuntu-mono-dark";
235
 
 
236
 
      /* Unique instancing */
237
 
      LOGGER_START_PROCESS ("unity_application_constructor");
238
 
      this.app = new Unity.Application ();
239
 
      this.app.shell = this;
240
 
      LOGGER_END_PROCESS ("unity_application_constructor");
241
 
 
242
 
      try
243
 
        {
244
 
          this.screensaver_conn = DBus.Bus.get (DBus.BusType.SESSION);
245
 
          this.screensaver = this.screensaver_conn.get_object ("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver");
246
 
          this.screensaver.ActiveChanged.connect (got_screensaver_changed);
247
 
        }
248
 
      catch (GLib.Error e)
249
 
        {
250
 
          warning (e.message);
251
 
        }
252
 
 
253
 
      this.wm = new WindowManagement (this);
254
 
      this.maximus = new Maximus ();
255
 
 
256
 
      (Clutter.Stage.get_default () as Clutter.Stage).color = { 0, 0, 0, 255 };
257
 
 
258
 
      END_FUNCTION ();
259
 
    }
260
 
 
261
 
    private bool real_construct ()
262
 
    {
263
 
      START_FUNCTION ();
264
 
 
265
 
      Clutter.set_gl_picking_enabled (false);
266
 
 
267
 
      this.stage = (Clutter.Stage)this.plugin.get_stage ();
268
 
      this.stage.actor_added.connect   ((a) => { ensure_input_region (); });
269
 
      this.stage.actor_removed.connect ((a) => { ensure_input_region (); });
270
 
 
271
 
      this.drag_dest = new DragDest ();
272
 
      this.drag_dest.show ();
273
 
      Gtk.TargetEntry[] target_list =
274
 
        {
275
 
          Gtk.TargetEntry () {target="STRING", flags=0,
276
 
                              info=Unity.dnd_targets.TARGET_STRING },
277
 
          Gtk.TargetEntry () {target="text/plain", flags=0,
278
 
                              info=Unity.dnd_targets.TARGET_STRING },
279
 
          Gtk.TargetEntry () {target="text/uri-list", flags=0,
280
 
                              info=Unity.dnd_targets.TARGET_URL },
281
 
          Gtk.TargetEntry () {target="x-url/http",
282
 
                              flags=0, info=Unity.dnd_targets.TARGET_URL },
283
 
          Gtk.TargetEntry () {target="x-url/ftp",
284
 
                              flags=0, info=Unity.dnd_targets.TARGET_URL },
285
 
          Gtk.TargetEntry () {target="_NETSCAPE_URL", flags=0,
286
 
                              info=Unity.dnd_targets.TARGET_URL }
287
 
        };
288
 
 
289
 
      Ctk.dnd_init ((Gtk.Widget)this.drag_dest, target_list);
290
 
 
291
 
      Clutter.Group window_group = (Clutter.Group) this.plugin.get_window_group ();
292
 
 
293
 
      /* we need to hook into the super key bound by mutter for g-shell.
294
 
         don't ask me why mutter binds things for g-shell explictly...
295
 
         */
296
 
      var gc = GConf.Client.get_default();
297
 
      Mutter.MetaDisplay display = Mutter.MetaScreen.get_display (plugin.get_screen ());
298
 
 
299
 
      try {
300
 
          super_key_enable = gc.get_bool(GCONF_DIR + "/" + GCONF_SUPER_KEY_ENABLE_KEY);
301
 
      } catch (GLib.Error e) {
302
 
          super_key_enable = true;
303
 
          warning("Cannot find super_key_enable gconf key");
304
 
      }
305
 
      try {
306
 
          gc.add_dir(GCONF_DIR, GConf.ClientPreloadType.ONELEVEL);
307
 
          gc.notify_add(GCONF_DIR + "/" + GCONF_SUPER_KEY_ENABLE_KEY, this.gconf_super_key_enable_cb);
308
 
      } catch (GLib.Error e) {
309
 
          warning("Cannot set gconf callback function of super_key_enable");
310
 
      }
311
 
 
312
 
      display.overlay_key_down.connect (() => {
313
 
          if (super_key_enable) {
314
 
              super_key_active = true;
315
 
          }
316
 
      });
317
 
 
318
 
      display.overlay_key.connect (() => {
319
 
          super_key_active = false;
320
 
      });
321
 
 
322
 
      display.overlay_key_with_modifier.connect ((keysym) => {
323
 
        super_key_modifier_release (keysym);
324
 
      });
325
 
 
326
 
      display.overlay_key_with_modifier_down.connect ((keysym) => {
327
 
          if (super_key_enable) {
328
 
            super_key_modifier_press (keysym);
329
 
          }
330
 
      });
331
 
 
332
 
      /* Setup the backgrounds */
333
 
      unowned Gdk.Screen screen = Gdk.Screen.get_default ();
334
 
      backgrounds = new Gee.ArrayList<Background> ();
335
 
 
336
 
      /* Connect to interestng signals */
337
 
      screen.monitors_changed.connect (relayout);
338
 
      screen.size_changed.connect (relayout);
339
 
 
340
 
      this.launcher = new Launcher.Launcher (this);
341
 
      this.launcher.get_view ().opacity = 0;
342
 
 
343
 
      this.spaces_manager = new SpacesManager (this);
344
 
      this.spaces_manager.set_padding (50, 50, get_launcher_width_foobar () + 50, 50);
345
 
      this.launcher.model.add (spaces_manager.button);
346
 
 
347
 
      this.expose_manager = new ExposeManager (this, launcher);
348
 
      this.expose_manager.hovered_opacity = 255;
349
 
      this.expose_manager.unhovered_opacity = 255;
350
 
      this.expose_manager.darken = 25;
351
 
      this.expose_manager.right_buffer = 10;
352
 
      this.expose_manager.top_buffer = this.expose_manager.bottom_buffer = 20;
353
 
 
354
 
      this.expose_manager.coverflow = false;
355
 
 
356
 
      window_group.add_actor (this.launcher.get_container ());
357
 
      (this.launcher.get_container () as Ctk.Bin).add_actor (this.launcher.get_view ());
358
 
      window_group.raise_child (this.launcher.get_container (),
359
 
                                this.plugin.get_normal_window_group ());
360
 
      this.launcher.get_view ().animate (Clutter.AnimationMode.EASE_IN_SINE, 400,
361
 
                                  "opacity", 255);
362
 
 
363
 
      this.places_controller = new Places.Controller (this);
364
 
      this.places = this.places_controller.get_view ();
365
 
 
366
 
      window_group.add_actor (this.places);
367
 
      window_group.raise_child (this.places,
368
 
                                this.launcher.get_container ());
369
 
      this.places.opacity = 0;
370
 
      this.places.reactive = false;
371
 
      this.places.hide ();
372
 
      this.places_showing = false;
373
 
 
374
 
      this.panel = new Panel.View (this);
375
 
      window_group.add_actor (this.panel);
376
 
      window_group.raise_child (this.panel,
377
 
                                this.launcher.get_container ());
378
 
      this.panel.show ();
379
 
 
380
 
      this.stage.notify["width"].connect (this.relayout);
381
 
      this.stage.notify["height"].connect (this.relayout);
382
 
 
383
 
      this.relayout ();
384
 
      END_FUNCTION ();
385
 
 
386
 
      if (boot_logging_filename != null)
387
 
        {
388
 
          Timeout.add_seconds (5, () => {
389
 
            Unity.TimelineLogger.get_default().write_log (boot_logging_filename);
390
 
            return false;
391
 
          });
392
 
        }
393
 
 
394
 
      gesture_dispatcher = new Gesture.XCBDispatcher ();
395
 
      gesture_dispatcher.gesture.connect (on_gesture_received);
396
 
      
397
 
      this.ensure_input_region ();
398
 
      GLib.Idle.add (() => { is_starting = false; return false; });
399
 
      return false;
400
 
      
401
 
    }
402
 
 
403
 
    private void gconf_super_key_enable_cb(GConf.Client gc, uint cxnid, GConf.Entry entry) {
404
 
      bool new_value = true;
405
 
      try {
406
 
          new_value = gc.get_bool(GCONF_DIR + "/" + GCONF_SUPER_KEY_ENABLE_KEY);
407
 
      } catch (GLib.Error e) {
408
 
          new_value = true;
409
 
      }
410
 
      super_key_enable = new_value;
411
 
    }
412
 
 
413
 
    private void on_focus_window_changed ()
414
 
    {
415
 
      check_fullscreen_obstruction ();
416
 
 
417
 
      if (focus_window != null)
418
 
        {
419
 
          focus_window.notify["fullscreen"].disconnect (on_focus_window_fullscreen_changed);
420
 
        }
421
 
 
422
 
      display.get ("focus-window", ref focus_window);
423
 
      focus_window.notify["fullscreen"].connect (on_focus_window_fullscreen_changed);
424
 
    }
425
 
 
426
 
    private void on_focus_window_fullscreen_changed ()
427
 
    {
428
 
      check_fullscreen_obstruction ();
429
 
    }
430
 
 
431
 
    private void got_screensaver_changed (dynamic DBus.Object screensaver, bool changed)
432
 
    {
433
 
      if (changed)
434
 
        {
435
 
          this.launcher.get_container ().hide ();
436
 
          this.panel.hide ();
437
 
          var menu = Unity.Launcher.QuicklistController.get_current_menu ();
438
 
          if (menu.is_menu_open ())
439
 
            menu.state = Unity.Launcher.QuicklistControllerState.CLOSED;
440
 
 
441
 
          fullscreen_obstruction = true;
442
 
        }
443
 
      else
444
 
        {
445
 
          this.launcher.get_container ().show ();
446
 
          this.panel.show ();
447
 
          fullscreen_obstruction = false;
448
 
        }
449
 
    }
450
 
 
451
 
    public uint32 get_current_time ()
452
 
    {
453
 
      return Mutter.MetaDisplay.get_current_time (Mutter.MetaScreen.get_display (plugin.get_screen ()));
454
 
    }
455
 
 
456
 
    void check_fullscreen_obstruction ()
457
 
    {
458
 
      Mutter.Window focus = null;
459
 
      bool fullscreen = false;
460
 
 
461
 
      // prevent segfault when mutter beats us to the initialization punch
462
 
      if (!(launcher is Launcher.Launcher) || !(panel is Clutter.Actor))
463
 
        return;
464
 
 
465
 
      unowned GLib.List<Mutter.Window> mutter_windows = plugin.get_windows ();
466
 
      foreach (Mutter.Window w in mutter_windows)
467
 
        {
468
 
          unowned Mutter.MetaWindow meta = w.get_meta_window ();
469
 
 
470
 
          if (meta != null && Mutter.MetaWindow.has_focus (w.get_meta_window ()))
471
 
            {
472
 
              focus = w;
473
 
              break;
474
 
            }
475
 
        }
476
 
 
477
 
      if (focus == null)
478
 
        return;
479
 
 
480
 
      (focus.get_meta_window () as GLib.Object).get ("fullscreen", ref fullscreen);
481
 
      (this.launcher.get_container () as Launcher.LauncherContainer).cache.invalidate_texture_cache ();
482
 
      this.panel.cache.invalidate_texture_cache ();
483
 
 
484
 
      Clutter.Animation? anim;
485
 
      Clutter.Animation? panim;
486
 
      if (fullscreen)
487
 
        {
488
 
          anim = this.launcher.get_container ().animate (Clutter.AnimationMode.EASE_IN_SINE, 200, "x", -100f);
489
 
          panim = this.panel.animate (Clutter.AnimationMode.EASE_IN_SINE, 200, "opacity", 0);
490
 
          fullscreen_obstruction = true;
491
 
        }
492
 
      else
493
 
        {
494
 
          anim = this.launcher.get_container ().animate (Clutter.AnimationMode.EASE_IN_SINE, 200, "x", 0f);
495
 
          panim = this.panel.animate (Clutter.AnimationMode.EASE_IN_SINE, 200, "opacity", 255);
496
 
          fullscreen_obstruction = false;
497
 
        }
498
 
 
499
 
      if (anim is Clutter.Animation)
500
 
        {
501
 
          anim.completed.connect (()=> {
502
 
            (this.launcher.get_container () as Launcher.LauncherContainer).cache.update_texture_cache ();
503
 
          });
504
 
        }
505
 
 
506
 
      if (panim is Clutter.Animation)
507
 
        {
508
 
          panim.completed.connect (() => { this.panel.cache.update_texture_cache (); });
509
 
        }
510
 
    }
511
 
 
512
 
    private void refresh_n_backgrounds (int n_monitors)
513
 
    {
514
 
      int size = backgrounds.size;
515
 
 
516
 
      if (size == n_monitors)
517
 
        return;
518
 
      else if (size < n_monitors)
519
 
        {
520
 
          for (int i = 0; i < n_monitors - size; i++)
521
 
            {
522
 
              var bg = new Background ();
523
 
              backgrounds.add (bg);
524
 
              stage.add_actor (bg);
525
 
              bg.lower_bottom ();
526
 
              bg.opacity = 0;
527
 
              bg.show ();
528
 
              bg.animate (Clutter.AnimationMode.EASE_IN_QUAD, 2000,
529
 
                          "opacity", 255);
530
 
            }
531
 
        }
532
 
      else
533
 
        {
534
 
          for (int i = 0; i < size - n_monitors; i++)
535
 
            {
536
 
              var bg = backgrounds.get (0);
537
 
              if (bg is Clutter.Actor)
538
 
                {
539
 
                  backgrounds.remove (bg);
540
 
                  stage.remove_actor (bg);
541
 
                }
542
 
            }
543
 
        }
544
 
    }
545
 
    private void relayout ()
546
 
    {
547
 
      START_FUNCTION ();
548
 
 
549
 
      unowned Gdk.Screen screen = Gdk.Screen.get_default ();
550
 
      int x, y, width, height;
551
 
 
552
 
      /* Figure out what should be the right size and location of Unity */
553
 
      /* FIXME: This needs to always be monitor 0 right now as it doesn't
554
 
       * seem possible to have panels on a vertical edge of a monitor unless
555
 
       * it's the first or last monitor :(
556
 
       */
557
 
      screen.get_monitor_geometry (0, // Should be screen.get_primary_monitor()
558
 
                                   out primary_monitor);
559
 
      x = primary_monitor.x;
560
 
      y = primary_monitor.y;
561
 
      width = primary_monitor.width;
562
 
      height = primary_monitor.height;
563
 
 
564
 
      /* The drag-n-drop region */
565
 
      drag_dest.resize (QUICKLAUNCHER_WIDTH,
566
 
                        height - PANEL_HEIGHT);
567
 
      drag_dest.move (x, y + PANEL_HEIGHT);
568
 
 
569
 
      /* We're responsible for painting the backgrounds on all the monitors */
570
 
      refresh_n_backgrounds (screen.get_n_monitors ());
571
 
      for (int i = 0; i < screen.get_n_monitors (); i++)
572
 
        {
573
 
          var bg = backgrounds.get (i);
574
 
          if (bg is Background)
575
 
            {
576
 
              Gdk.Rectangle rect;
577
 
              screen.get_monitor_geometry (i, out rect);
578
 
 
579
 
              bg.set_position (rect.x, rect.y);
580
 
              bg.set_size (rect.width, rect.height);
581
 
            }
582
 
        }   
583
 
 
584
 
      this.launcher.get_container ().set_size (this.QUICKLAUNCHER_WIDTH,
585
 
                                   (height-this.PANEL_HEIGHT));
586
 
      this.launcher.get_container ().set_position (x, y + this.PANEL_HEIGHT);
587
 
      this.launcher.get_container ().set_clip (0, 0,
588
 
                                   this.QUICKLAUNCHER_WIDTH,
589
 
                                   height-this.PANEL_HEIGHT);
590
 
 
591
 
      Utils.set_strut ((Gtk.Window)this.drag_dest,
592
 
                       this.QUICKLAUNCHER_WIDTH, y, (uint32)height,
593
 
                       PANEL_HEIGHT, x, (uint32)width);
594
 
 
595
 
      this.places.set_size (width - this.QUICKLAUNCHER_WIDTH, height);
596
 
      this.places.set_position (x + this.QUICKLAUNCHER_WIDTH, y);
597
 
 
598
 
      this.panel.set_size (width, PANEL_HEIGHT);
599
 
      this.panel.set_position (x, y);
600
 
 
601
 
      ensure_input_region ();
602
 
 
603
 
      END_FUNCTION ();
604
 
    }
605
 
 
606
 
    public void add_fullscreen_request (Object o)
607
 
    {
608
 
      fullscreen_requests.add (o);
609
 
      ensure_input_region ();
610
 
    }
611
 
 
612
 
    public bool remove_fullscreen_request (Object o)
613
 
    {
614
 
      bool result = fullscreen_requests.remove (o);
615
 
      ensure_input_region ();
616
 
      return result;
617
 
    }
618
 
 
619
 
    public void ensure_input_region ()
620
 
    {
621
 
      if (fullscreen_obstruction)
622
 
        {
623
 
          if (last_input_state == InputState.ZERO)
624
 
            return;
625
 
          last_input_state = InputState.ZERO;
626
 
          this.plugin.set_stage_input_area(0, 0, 0, 0);
627
 
 
628
 
          this.grab_keyboard (false, Clutter.get_current_event_time ());
629
 
        }
630
 
      else if (fullscreen_requests.size > 0 || places_showing)
631
 
        {
632
 
          // Fullscreen required
633
 
          if (last_input_state == InputState.FULLSCREEN)
634
 
            return;
635
 
 
636
 
          last_input_state = InputState.FULLSCREEN;
637
 
          this.restore_input_region (true);
638
 
 
639
 
          this.stage.set_key_focus (null as Clutter.Actor);
640
 
          this.grab_keyboard (true, Clutter.get_current_event_time ());
641
 
        }
642
 
      else
643
 
        {
644
 
          // Unity mode requred
645
 
          if (last_input_state == InputState.UNITY)
646
 
            return;
647
 
 
648
 
          last_input_state = InputState.UNITY;
649
 
          this.restore_input_region (false);
650
 
 
651
 
          this.grab_keyboard (false, Clutter.get_current_event_time ());
652
 
        }
653
 
    }
654
 
 
655
 
    /*
656
 
     * SHELL IMPLEMENTATION
657
 
     */
658
 
    public Clutter.Stage get_stage ()
659
 
    {
660
 
      return this.stage;
661
 
    }
662
 
 
663
 
    public void close_xids (Array<uint32> xids)
664
 
    {
665
 
      for (int i = 0; i < xids.length; i++)
666
 
        {
667
 
          uint32 xid = xids.index (i);
668
 
 
669
 
          unowned GLib.List<Mutter.Window> mutter_windows = this.plugin.get_windows ();
670
 
          foreach (Mutter.Window window in mutter_windows)
671
 
            {
672
 
              uint32 wxid = (uint32) Mutter.MetaWindow.get_xwindow (window.get_meta_window ());
673
 
              if (wxid == xid)
674
 
                {
675
 
                  Mutter.MetaWindow.delete (window.get_meta_window (), Clutter.get_current_event_time ());
676
 
                }
677
 
            }
678
 
        }
679
 
    }
680
 
 
681
 
    public void expose_xids (Array<uint32> xids)
682
 
    {
683
 
      spaces_manager.hide_spaces_picker ();
684
 
      SList<Clutter.Actor> windows = new SList<Clutter.Actor> ();
685
 
      for (int i = 0; i < xids.length; i++)
686
 
        {
687
 
          uint32 xid = xids.index (i);
688
 
 
689
 
          unowned GLib.List<Mutter.Window> mutter_windows = plugin.get_windows ();
690
 
          foreach (Mutter.Window w in mutter_windows)
691
 
            {
692
 
              uint32 wxid = (uint32) Mutter.MetaWindow.get_xwindow (w.get_meta_window ());
693
 
              if (wxid == xid)
694
 
                {
695
 
                  windows.append (w);
696
 
                  break;
697
 
                }
698
 
            }
699
 
        }
700
 
 
701
 
      expose_windows (windows,  get_launcher_width_foobar () + 10);
702
 
    }
703
 
 
704
 
    public void stop_expose ()
705
 
    {
706
 
      expose_manager.end_expose ();
707
 
    }
708
 
 
709
 
    public void show_window (uint32 xid)
710
 
    {
711
 
      unowned GLib.List<Mutter.Window> mutter_windows = this.plugin.get_windows ();
712
 
 
713
 
      foreach (Mutter.Window mutter_window in mutter_windows)
714
 
        {
715
 
          ulong window_xid = (ulong) Mutter.MetaWindow.get_xwindow (mutter_window.get_meta_window ());
716
 
          if (window_xid != xid)
717
 
            continue;
718
 
 
719
 
          int type = mutter_window.get_window_type ();
720
 
 
721
 
          if (type != Mutter.MetaWindowType.NORMAL &&
722
 
              type != Mutter.MetaWindowType.DIALOG &&
723
 
              type != Mutter.MetaWindowType.MODAL_DIALOG)
724
 
            continue;
725
 
 
726
 
          uint32 time_;
727
 
          unowned Mutter.MetaWindow meta = mutter_window.get_meta_window ();
728
 
 
729
 
          time_ = Mutter.MetaDisplay.get_current_time (Mutter.MetaWindow.get_display (meta));
730
 
          Mutter.MetaWorkspace.activate (Mutter.MetaWindow.get_workspace (meta), time_);
731
 
          Mutter.MetaWindow.activate (meta, time_);
732
 
        }
733
 
    }
734
 
 
735
 
    public ShellMode get_mode ()
736
 
    {
737
 
      return places_showing ? ShellMode.DASH : ShellMode.MINIMIZED;
738
 
    }
739
 
 
740
 
    public int get_indicators_width ()
741
 
    {
742
 
      return this.panel.get_indicators_width ();
743
 
    }
744
 
 
745
 
    public void expose_windows (GLib.SList<Clutter.Actor> windows,
746
 
                                int left_buffer = 75)
747
 
    {
748
 
      expose_manager.left_buffer = left_buffer;
749
 
      expose_manager.start_expose (windows);
750
 
    }
751
 
 
752
 
 
753
 
    public void hide_unity ()
754
 
    {
755
 
      if (places_showing == false)
756
 
        return;
757
 
 
758
 
      places_showing = false;
759
 
 
760
 
      var anim = dark_box.animate (Clutter.AnimationMode.EASE_IN_QUAD, 100, "opacity", 0);
761
 
      anim.completed.connect ((an) => {
762
 
        (an.get_object () as Clutter.Actor).destroy ();
763
 
      });
764
 
 
765
 
      plugin.get_normal_window_group ().animate (Clutter.AnimationMode.EASE_OUT_QUAD, 100, "opacity", 255);
766
 
 
767
 
      anim = places.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 100,
768
 
                      "opacity", 0);
769
 
      anim.completed.connect ((an) => {
770
 
        (an.get_object () as Clutter.Actor).hide ();
771
 
        });
772
 
 
773
 
      panel.set_indicator_mode (false);
774
 
      ensure_input_region ();
775
 
 
776
 
      while (Gtk.events_pending ())
777
 
        Gtk.main_iteration ();
778
 
 
779
 
      places.hidden ();
780
 
 
781
 
      mode_changed (ShellMode.MINIMIZED);
782
 
    }
783
 
 
784
 
    public void show_unity ()
785
 
    {
786
 
      if (this.places_showing)
787
 
        {
788
 
          hide_unity ();
789
 
        }
790
 
      else
791
 
        {
792
 
          this.places_showing = true;
793
 
 
794
 
          this.places.show ();
795
 
          this.places.opacity = 0;
796
 
          this.dark_box = new Clutter.Rectangle.with_color ({0, 0, 0, 255});
797
 
 
798
 
          (this.plugin.get_window_group () as Clutter.Container).add_actor (this.dark_box);
799
 
          this.dark_box.raise (plugin.get_normal_window_group ());
800
 
 
801
 
          this.dark_box.set_position (primary_monitor.x, primary_monitor.y);
802
 
          this.dark_box.set_size (primary_monitor.width, primary_monitor.height);
803
 
 
804
 
          this.dark_box.show ();
805
 
 
806
 
          this.panel.set_indicator_mode (true);
807
 
 
808
 
          this.ensure_input_region ();
809
 
 
810
 
          new X.Display (null).flush ();
811
 
 
812
 
          this.dark_box.opacity = 0;
813
 
 
814
 
          this.dark_box.animate   (Clutter.AnimationMode.EASE_IN_QUAD, 100, "opacity", 180);
815
 
          plugin.get_normal_window_group ().animate (Clutter.AnimationMode.EASE_OUT_QUAD, 100, "opacity", 0);
816
 
          places.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 100,
817
 
                          "opacity", 255);
818
 
 
819
 
          places.shown ();
820
 
 
821
 
          mode_changed (ShellMode.DASH);
822
 
        }
823
 
    }
824
 
 
825
 
    public void about_to_show_places ()
826
 
    {
827
 
      places.about_to_show ();
828
 
    }
829
 
 
830
 
    public void grab_keyboard (bool grab, uint32 timestamp)
831
 
    {
832
 
      if (this.grab_enabled == grab)
833
 
        return;
834
 
 
835
 
      if (grab)
836
 
        {
837
 
          this.plugin.begin_modal (Utils.get_stage_window (this.stage),
838
 
                                   0,
839
 
                                   0,
840
 
                                   timestamp);
841
 
 
842
 
        }
843
 
      else
844
 
        {
845
 
          this.plugin.end_modal (timestamp);
846
 
        }
847
 
 
848
 
      this.grab_enabled = grab;
849
 
    }
850
 
 
851
 
    private unowned Mutter.MetaWindow? get_window_for_xid (uint32 xid)
852
 
    {
853
 
      unowned GLib.List<Mutter.Window> mutter_windows = this.plugin.get_windows ();
854
 
      foreach (Mutter.Window window in mutter_windows)
855
 
        {
856
 
          uint32 wxid = (uint32) Mutter.MetaWindow.get_xwindow (window.get_meta_window ());
857
 
          if (wxid == xid)
858
 
            {
859
 
              unowned Mutter.MetaWindow win = window.get_meta_window ();
860
 
              return win;
861
 
            }
862
 
        }
863
 
 
864
 
      return null;
865
 
    }
866
 
 
867
 
    public void get_window_details (uint32   xid,
868
 
                                    out bool allows_resize,
869
 
                                    out bool is_maximised)
870
 
    {
871
 
      unowned Mutter.MetaWindow? win = get_window_for_xid (xid);
872
 
 
873
 
      if (win != null)
874
 
        {
875
 
          allows_resize = Mutter.MetaWindow.allows_resize (win);
876
 
          is_maximised = (Mutter.MetaWindow.is_maximized (win) ||
877
 
                          Mutter.MetaWindow.is_maximized_horizontally (win) ||
878
 
                          Mutter.MetaWindow.is_maximized_vertically (win));
879
 
 
880
 
        }
881
 
    }
882
 
 
883
 
    public void do_window_action (uint32 xid, WindowAction action)
884
 
    {
885
 
      unowned Mutter.MetaWindow? win = get_window_for_xid (xid);
886
 
 
887
 
      if (win != null)
888
 
        {
889
 
          switch (action)
890
 
            {
891
 
            case WindowAction.CLOSE:
892
 
              Mutter.MetaWindow.delete (win, get_current_time ());
893
 
              break;
894
 
 
895
 
            case WindowAction.MINIMIZE:
896
 
              Mutter.MetaWindow.minimize (win);
897
 
              break;
898
 
 
899
 
            case WindowAction.MAXIMIZE:
900
 
              Mutter.MetaWindow.maximize (win,
901
 
                                          Mutter.MetaMaximizeFlags.HORIZONTAL |
902
 
                                          Mutter.MetaMaximizeFlags.VERTICAL);
903
 
              break;
904
 
 
905
 
            case WindowAction.UNMAXIMIZE:
906
 
              Mutter.MetaWindow.unmaximize (win,
907
 
                                            Mutter.MetaMaximizeFlags.HORIZONTAL |
908
 
                                            Mutter.MetaMaximizeFlags.VERTICAL);
909
 
              break;
910
 
 
911
 
            default:
912
 
              warning (@"Window action type $action not supported");
913
 
              break;
914
 
            }
915
 
        }
916
 
    }
917
 
 
918
 
    private void on_gesture_received (Gesture.Event event)
919
 
    {
920
 
      if (active_gesture_type != Gesture.Type.NONE
921
 
          && active_gesture_type != event.type
922
 
          && event.state != Gesture.State.ENDED)
923
 
        {
924
 
          /* A new gesture is beginning */
925
 
          if (event.state == Gesture.State.BEGAN)
926
 
            {
927
 
              active_gesture_type = event.type;
928
 
            }
929
 
          else
930
 
            {
931
 
              /* We don't want to handle it */
932
 
              return;
933
 
            }
934
 
        }
935
 
 
936
 
      if (event.type == Gesture.Type.TAP)
937
 
        {
938
 
          if (event.fingers == 4
939
 
              && !expose_manager.expose_showing)
940
 
            {
941
 
              if (places_showing == true)
942
 
                hide_unity ();
943
 
              else
944
 
                show_unity ();
945
 
            }
946
 
              /*
947
 
              if (expose_manager.expose_showing == false)
948
 
                {
949
 
                }
950
 
              else
951
 
                expose_manager.end_expose ();
952
 
              */
953
 
        }
954
 
      else if (event.type == Gesture.Type.PINCH)
955
 
        {
956
 
          if (event.fingers == 3
957
 
              && places_showing == false)
958
 
            {
959
 
              if (event.state == Gesture.State.ENDED)
960
 
                {
961
 
                  if (event.pinch_event.radius_delta < 0)
962
 
                    {
963
 
                      /* Pinch */
964
 
                      if (expose_type == ExposeType.NONE || !expose_manager.expose_showing)
965
 
                        {
966
 
                          Mutter.Window? window = null;
967
 
 
968
 
                          var actor = stage.get_actor_at_pos (Clutter.PickMode.ALL,
969
 
                                                              (int)event.root_x,
970
 
                                                              (int)event.root_y);
971
 
                          if (actor is Mutter.Window == false)
972
 
                            actor = actor.get_parent ();
973
 
 
974
 
                          if (actor is Mutter.Window)
975
 
                            {
976
 
                              window = actor as Mutter.Window;
977
 
 
978
 
                              if (window.get_window_type () != Mutter.MetaCompWindowType.NORMAL &&
979
 
                                  window.get_window_type () != Mutter.MetaCompWindowType.DIALOG &&
980
 
                                  window.get_window_type () != Mutter.MetaCompWindowType.MODAL_DIALOG &&
981
 
                                  window.get_window_type () != Mutter.MetaCompWindowType.UTILITY)
982
 
                                window = null;
983
 
                            }
984
 
 
985
 
                          start_pinch_window = null;
986
 
 
987
 
                          if (window is Mutter.Window)
988
 
                            {
989
 
                              var matcher = Bamf.Matcher.get_default ();
990
 
                              var xwin = (uint32)Mutter.MetaWindow.get_xwindow (window.get_meta_window ());
991
 
 
992
 
                              foreach (Bamf.Application app in matcher.get_running_applications ())
993
 
                                {
994
 
                                  Array<uint32> last_pinch_xids = app.get_xids ();
995
 
                                  for (int i = 0; i < last_pinch_xids.length; i++)
996
 
                                    {
997
 
                                      uint32 xid = last_pinch_xids.index (i);
998
 
                                      if (xwin == xid)
999
 
                                        {
1000
 
                                          // Found the right application, so pick it
1001
 
                                          expose_xids (last_pinch_xids);
1002
 
                                          expose_type = ExposeType.APPLICATION;
1003
 
                                          start_pinch_window = window;
1004
 
                                          return;
1005
 
                                        }
1006
 
                                    }
1007
 
                                }
1008
 
                            }
1009
 
 
1010
 
                          /* If we're here we didnt find window, so lets do window expose */
1011
 
                          SList<Clutter.Actor> windows = new SList<Clutter.Actor> ();
1012
 
                          unowned GLib.List<Mutter.Window> mutter_windows = plugin.get_windows ();
1013
 
                          foreach (Mutter.Window w in mutter_windows)
1014
 
                            {
1015
 
                              windows.append (w);
1016
 
                            }
1017
 
                          expose_windows (windows, get_launcher_width_foobar () + 10);
1018
 
                          
1019
 
                          expose_type = ExposeType.WINDOWS;
1020
 
 
1021
 
                        }
1022
 
                      else if (expose_type == ExposeType.APPLICATION)
1023
 
                        {
1024
 
                          SList<Clutter.Actor> windows = new SList<Clutter.Actor> ();
1025
 
                          unowned GLib.List<Mutter.Window> mutter_windows = plugin.get_windows ();
1026
 
                          foreach (Mutter.Window w in mutter_windows)
1027
 
                            {
1028
 
                              windows.append (w);
1029
 
                            }
1030
 
                          expose_windows (windows, get_launcher_width_foobar () + 10);
1031
 
                          
1032
 
                          expose_type = ExposeType.WINDOWS;
1033
 
                        }
1034
 
                      else if (expose_type == ExposeType.WINDOWS)
1035
 
                        {
1036
 
                          expose_type = ExposeType.WORKSPACE;
1037
 
                        }
1038
 
                    }
1039
 
                  else
1040
 
                    {
1041
 
                      /* Spread */
1042
 
                      if (expose_type == ExposeType.NONE || !expose_manager.expose_showing)
1043
 
                        {
1044
 
                          expose_manager.end_expose ();
1045
 
                          expose_type = ExposeType.NONE;
1046
 
                        }
1047
 
                      else if (expose_type == ExposeType.APPLICATION)
1048
 
                        {
1049
 
                          expose_manager.end_expose ();
1050
 
                          expose_type = ExposeType.NONE;
1051
 
                        }
1052
 
                      else if (expose_type == ExposeType.WINDOWS)
1053
 
                        {
1054
 
                          var matcher = Bamf.Matcher.get_default ();
1055
 
                          var xwin = (uint32)Mutter.MetaWindow.get_xwindow (start_pinch_window.get_meta_window ());
1056
 
 
1057
 
                          foreach (Bamf.Application app in matcher.get_running_applications ())
1058
 
                            {
1059
 
                              Array<uint32> last_pinch_xids = app.get_xids ();
1060
 
                              for (int i = 0; i < last_pinch_xids.length; i++)
1061
 
                                {
1062
 
                                  uint32 xid = last_pinch_xids.index (i);
1063
 
                                  if (xwin == xid)
1064
 
                                    {
1065
 
                                      // Found the right application, so pick it
1066
 
                                      expose_xids (last_pinch_xids);
1067
 
                                      expose_type = ExposeType.APPLICATION;
1068
 
                                      return;
1069
 
                                    }
1070
 
                                }
1071
 
                            }
1072
 
                          expose_manager.end_expose ();
1073
 
                          expose_type = ExposeType.NONE;
1074
 
                        }
1075
 
                      else if (expose_type == ExposeType.WORKSPACE)
1076
 
                        {
1077
 
                          expose_type = ExposeType.WINDOWS;
1078
 
                        }
1079
 
                    }
1080
 
                }
1081
 
            }
1082
 
        }
1083
 
      else if (event.type == Gesture.Type.PAN)
1084
 
        {
1085
 
          if (resize_window is Mutter.Window)
1086
 
            return;
1087
 
 
1088
 
          if (event.fingers == 3)
1089
 
            {
1090
 
              if (event.state == Gesture.State.BEGAN
1091
 
                  && event.pan_event.current_n_fingers == 2)
1092
 
                {
1093
 
                  start_pan_window = null;
1094
 
 
1095
 
                  var actor = stage.get_actor_at_pos (Clutter.PickMode.ALL,
1096
 
                                                      (int)event.root_x,
1097
 
                                                      (int)event.root_y);
1098
 
                  if (actor is Mutter.Window == false)
1099
 
                    actor = actor.get_parent ();
1100
 
 
1101
 
                  if (actor is Mutter.Window)
1102
 
                    {
1103
 
                      start_pan_window = actor as Mutter.Window;
1104
 
 
1105
 
                      if (start_pan_window.get_window_type () != Mutter.MetaCompWindowType.NORMAL &&
1106
 
                          start_pan_window.get_window_type () != Mutter.MetaCompWindowType.DIALOG &&
1107
 
                          start_pan_window.get_window_type () != Mutter.MetaCompWindowType.MODAL_DIALOG &&
1108
 
                          start_pan_window.get_window_type () != Mutter.MetaCompWindowType.UTILITY)
1109
 
                        start_pan_window = null;
1110
 
                    }
1111
 
                }
1112
 
              else if (event.state == Gesture.State.CONTINUED
1113
 
                       && event.pan_event.current_n_fingers == 2)
1114
 
                {
1115
 
                  if (start_pan_window is Mutter.Window == false)
1116
 
                    return;
1117
 
 
1118
 
                  last_pan_x_root = event.root_x;
1119
 
 
1120
 
                  unowned Mutter.MetaWindow win = start_pan_window.get_meta_window ();
1121
 
                  bool fullscreen = false;
1122
 
                  win.get ("fullscreen", out fullscreen);
1123
 
 
1124
 
                  if (!Mutter.MetaWindow.is_maximized (win) && fullscreen == false)
1125
 
                    {
1126
 
                      if (start_pan_window.y == PANEL_HEIGHT
1127
 
                          && event.pan_event.delta_y <= 0.0f)
1128
 
                        {
1129
 
                          if (start_frame_rect is Clutter.Rectangle == false)
1130
 
                            {
1131
 
                              Clutter.Rectangle frame = new Clutter.Rectangle.with_color ({ 0, 0, 0, 10 });
1132
 
                              frame.border_color = { 255, 255, 255, 255 };
1133
 
                              frame.border_width = 3;
1134
 
 
1135
 
                              stage.add_actor (frame);
1136
 
                              frame.set_size (start_pan_window.width,
1137
 
                                              start_pan_window.height);
1138
 
                              frame.set_position (start_pan_window.x,
1139
 
                                                  start_pan_window.y);
1140
 
                              frame.show ();
1141
 
 
1142
 
                              start_frame_rect = frame;
1143
 
 
1144
 
                              last_pan_maximised_x_root = start_pan_window.x;
1145
 
                            }
1146
 
 
1147
 
                          maximize_type = MaximizeType.FULL;
1148
 
                          var MAX_DELTA = 50.0f;
1149
 
                          if (start_pan_window.x < last_pan_maximised_x_root - MAX_DELTA)
1150
 
                            {
1151
 
                              maximize_type = MaximizeType.LEFT;
1152
 
                              start_frame_rect.animate (Clutter.AnimationMode.EASE_OUT_QUAD,
1153
 
                                                        150,
1154
 
                                                        "x", (float)QUICKLAUNCHER_WIDTH,
1155
 
                                                        "y", (float)PANEL_HEIGHT,
1156
 
                                                        "width", (stage.width - QUICKLAUNCHER_WIDTH)/2.0f,
1157
 
                                                        "height", stage.height - PANEL_HEIGHT);
1158
 
 
1159
 
                            }
1160
 
                          else if (start_pan_window.x > last_pan_maximised_x_root + MAX_DELTA)
1161
 
                            {
1162
 
                              maximize_type = MaximizeType.RIGHT;
1163
 
                              start_frame_rect.animate (Clutter.AnimationMode.EASE_OUT_QUAD,
1164
 
                                                        150,
1165
 
                                                        "x", (float)((stage.width - QUICKLAUNCHER_WIDTH)/2.0f) + QUICKLAUNCHER_WIDTH,
1166
 
                                                        "y", (float)PANEL_HEIGHT,
1167
 
                                                        "width", (stage.width - QUICKLAUNCHER_WIDTH)/2.0f,
1168
 
                                                        "height", stage.height - PANEL_HEIGHT);
1169
 
                            }
1170
 
                          else
1171
 
                            {
1172
 
                              start_frame_rect.animate (Clutter.AnimationMode.EASE_OUT_QUAD,
1173
 
                                                        150,
1174
 
                                                        "x", (float)QUICKLAUNCHER_WIDTH,
1175
 
                                                        "y", (float)PANEL_HEIGHT,
1176
 
                                                        "width", stage.width - QUICKLAUNCHER_WIDTH,
1177
 
                                                        "height", stage.height - PANEL_HEIGHT);
1178
 
 
1179
 
                             }
1180
 
                        }
1181
 
                     else
1182
 
                        {
1183
 
                          if (start_frame_rect is Clutter.Rectangle)
1184
 
                            {
1185
 
                              if (start_frame_rect.opacity == 0)
1186
 
                                {
1187
 
                                  stage.remove_actor (start_frame_rect);
1188
 
                                  start_frame_rect = null;
1189
 
                                }
1190
 
                              else if (start_pan_window.y > PANEL_HEIGHT + 5 &&
1191
 
                                (start_frame_rect.get_animation () is Clutter.Animation == false))
1192
 
                                {
1193
 
                                  start_frame_rect.animate (Clutter.AnimationMode.EASE_IN_QUAD,
1194
 
                                                            150,
1195
 
                                                            "x", start_pan_window.x,
1196
 
                                                            "y", start_pan_window.y,
1197
 
                                                            "width", start_pan_window.width,
1198
 
                                                            "height", start_pan_window.height,
1199
 
                                                            "opacity", 0);
1200
 
                                }
1201
 
                            }
1202
 
                        }
1203
 
                      start_pan_window.x += Math.floorf (event.pan_event.delta_x + 0.5f);
1204
 
                      start_pan_window.y += Math.floorf (event.pan_event.delta_y + 0.5f);
1205
 
                      start_pan_window.x = float.max (start_pan_window.x, QUICKLAUNCHER_WIDTH);
1206
 
                      start_pan_window.y = float.max (start_pan_window.y, PANEL_HEIGHT);
1207
 
                    }
1208
 
                  else
1209
 
                    {
1210
 
                      if (event.pan_event.delta_y >= 0.0f && fullscreen == false)
1211
 
                        {
1212
 
                          Mutter.MetaWindow.unmaximize (win,
1213
 
                                                        Mutter.MetaMaximizeFlags.HORIZONTAL | Mutter.MetaMaximizeFlags.VERTICAL);
1214
 
                        }
1215
 
                    }
1216
 
                }
1217
 
              else if (event.state == Gesture.State.ENDED)
1218
 
                {
1219
 
                  if (start_pan_window is Mutter.Window)
1220
 
                    {
1221
 
                      unowned Mutter.MetaWindow win = start_pan_window.get_meta_window ();
1222
 
                      float nx = 0;
1223
 
                      float ny = 0;
1224
 
                      float nwidth = 0;
1225
 
                      float nheight = 0;
1226
 
                      bool  move_resize = false;
1227
 
                      bool fullscreen = false;
1228
 
                      win.get ("fullscreen", out fullscreen);
1229
 
 
1230
 
                      int wx, wy, ww, wh;
1231
 
                      Mutter.MetaWindow.get_geometry (win, out wx, out wy, out ww, out wh);
1232
 
                      Mutter.MetaRectangle rect = Mutter.MetaRectangle ();
1233
 
                      Mutter.MetaWindow.get_outer_rect (win, rect);
1234
 
 
1235
 
                      if (Mutter.MetaWindow.is_maximized (win) || fullscreen)
1236
 
                        {
1237
 
                        }
1238
 
                      else if (start_pan_window.y == PANEL_HEIGHT && event.pan_event.delta_y < 0.0f)
1239
 
                        {
1240
 
                          if (maximize_type == MaximizeType.FULL)
1241
 
                            {
1242
 
                            
1243
 
                              Mutter.MetaWindow.maximize (win,
1244
 
                                                          Mutter.MetaMaximizeFlags.HORIZONTAL | Mutter.MetaMaximizeFlags.VERTICAL);
1245
 
                              move_resize = false;
1246
 
                            }
1247
 
                          else if (maximize_type == MaximizeType.RIGHT)
1248
 
                            {
1249
 
                              nx = (float)QUICKLAUNCHER_WIDTH + (stage.width-QUICKLAUNCHER_WIDTH)/2.0f;
1250
 
                              ny = (float)PANEL_HEIGHT;
1251
 
                              nwidth = (stage.width - QUICKLAUNCHER_WIDTH)/2.0f;
1252
 
                              nheight = stage.height - PANEL_HEIGHT;
1253
 
 
1254
 
                              move_resize = true;
1255
 
                            }
1256
 
                          else if (maximize_type == MaximizeType.LEFT)
1257
 
                            {
1258
 
                              nx = (float)QUICKLAUNCHER_WIDTH;
1259
 
                              ny = (float)PANEL_HEIGHT;
1260
 
                              nwidth = (stage.width - QUICKLAUNCHER_WIDTH)/2.0f;
1261
 
                              nheight = stage.height - PANEL_HEIGHT;
1262
 
 
1263
 
                              move_resize = true;
1264
 
                            }
1265
 
                        }
1266
 
                      else
1267
 
                        {
1268
 
                          nx = start_pan_window.x;
1269
 
                          ny = start_pan_window.y;
1270
 
                          nwidth = 0.0f;
1271
 
                          nheight = 0.0f;
1272
 
                          move_resize = true;
1273
 
                        }
1274
 
 
1275
 
                      if (move_resize)
1276
 
                        {
1277
 
                          X.Window xwin = start_pan_window.get_x_window ();
1278
 
                          if (nwidth > 0.0f && nheight > 0.0f)
1279
 
                            {
1280
 
                              Mutter.MetaWindow.move_resize (win, false, ((int)nx),
1281
 
                                                             ((int)ny),
1282
 
                                                             (int)nwidth, (int)nheight);
1283
 
                            }
1284
 
                          else
1285
 
                            {
1286
 
                              /* We use gdk_window_move because we don't want
1287
 
                               * to send in the width and height if we dont
1288
 
                               * need to, as otherwise we'll cause a resize
1289
 
                               * for no reason, and most likely get it
1290
 
                               * wrong (you need to take into account frame
1291
 
                               * size inside Mutter
1292
 
                               */
1293
 
                              unowned Gdk.Window w = Gdk.Window.foreign_new ((Gdk.NativeWindow)xwin);
1294
 
                              w.move ((int)nx, (int)ny);
1295
 
                            }
1296
 
                        }
1297
 
                    }
1298
 
 
1299
 
                    if (start_frame_rect is Clutter.Rectangle)
1300
 
                      stage.remove_actor (start_frame_rect);
1301
 
                }
1302
 
            }
1303
 
        }
1304
 
    }
1305
 
 
1306
 
    /*
1307
 
     * MUTTER PLUGIN HOOKS
1308
 
     */
1309
 
    public void minimize (Mutter.Window window)
1310
 
    {
1311
 
      this.window_minimized (this, window);
1312
 
    }
1313
 
 
1314
 
    public void maximize (Mutter.Window window,
1315
 
                          int           x,
1316
 
                          int           y,
1317
 
                          int           width,
1318
 
                          int           height)
1319
 
    {
1320
 
      if (window.get_data<string> (UNDECORATED_HINT) == null)
1321
 
        {
1322
 
          Utils.window_set_decorations (Mutter.MetaWindow.get_xwindow (window.get_meta_window ()), 0);
1323
 
        }
1324
 
 
1325
 
      this.window_maximized (this, window, x, y, width, height);
1326
 
 
1327
 
      active_window_state_changed ();
1328
 
    }
1329
 
 
1330
 
    public void unmaximize (Mutter.Window window,
1331
 
                            int           x,
1332
 
                            int           y,
1333
 
                            int           width,
1334
 
                            int           height)
1335
 
    {
1336
 
      if (window.get_data<string> (UNDECORATED_HINT) == null)
1337
 
        {
1338
 
          Utils.window_set_decorations (Mutter.MetaWindow.get_xwindow (window.get_meta_window ()), 1);
1339
 
        }
1340
 
 
1341
 
      this.window_unmaximized (this, window, x, y, width, height);
1342
 
 
1343
 
      active_window_state_changed ();
1344
 
    }
1345
 
 
1346
 
    public void map (Mutter.Window window)
1347
 
    {
1348
 
      unowned Mutter.MetaWindow win = window.get_meta_window ();
1349
 
 
1350
 
      if (window.get_window_type () == Mutter.MetaCompWindowType.NORMAL)
1351
 
        {
1352
 
          Idle.add (() => {
1353
 
            if (win is Object)
1354
 
              {
1355
 
                bool decorated  = Utils.window_is_decorated (Mutter.MetaWindow.get_xwindow (win));
1356
 
                bool maximized  = Mutter.MetaWindow.is_maximized (win);
1357
 
                
1358
 
                bool fullscreen;
1359
 
                win.get ("fullscreen", out fullscreen);
1360
 
                
1361
 
                if (!decorated && !maximized)
1362
 
                  {
1363
 
                    window.set_data (UNDECORATED_HINT, "%s".printf ("true"));
1364
 
                  }
1365
 
                else if (decorated && maximized && !fullscreen)
1366
 
                  {
1367
 
                    Utils.window_set_decorations (Mutter.MetaWindow.get_xwindow (win), 0);
1368
 
                  }
1369
 
              }
1370
 
 
1371
 
            return false;
1372
 
          });
1373
 
        }
1374
 
      else if (window.get_window_type () == Mutter.MetaCompWindowType.DOCK)
1375
 
        {
1376
 
          if (win.get_xwindow (win) == Gdk.x11_drawable_get_xid (drag_dest.window))
1377
 
            {
1378
 
              window.opacity = 0;
1379
 
            }
1380
 
        }
1381
 
 
1382
 
      this.maximus.process_window (window);
1383
 
      this.window_mapped (this, window);
1384
 
 
1385
 
      if (display == null)
1386
 
        {
1387
 
          display = Mutter.MetaWindow.get_display (window.get_meta_window ());
1388
 
          display.notify["focus-window"].connect (on_focus_window_changed);
1389
 
        }
1390
 
    }
1391
 
 
1392
 
    public void destroy (Mutter.Window window)
1393
 
    {
1394
 
      this.window_destroyed (this, window);
1395
 
    }
1396
 
 
1397
 
    public void switch_workspace (int                 from,
1398
 
                                  int                 to,
1399
 
                                  int                 direction)
1400
 
    {
1401
 
      this.workspace_switch_event (this, from, to, direction);
1402
 
    }
1403
 
 
1404
 
    public void on_kill_window_effects (Mutter.Window window)
1405
 
    {
1406
 
      this.kill_window_effects (this, window);
1407
 
    }
1408
 
 
1409
 
    public void on_kill_switch_workspace ()
1410
 
    {
1411
 
      this.kill_switch_workspace (this);
1412
 
    }
1413
 
 
1414
 
    public int get_panel_height ()
1415
 
    {
1416
 
      return this.PANEL_HEIGHT;
1417
 
    }
1418
 
 
1419
 
    public int get_launcher_width ()
1420
 
    {
1421
 
      return this.QUICKLAUNCHER_WIDTH;
1422
 
    }
1423
 
 
1424
 
    /* this is needed to avoid a symbol clash in unity/targets/mutter/main.c */
1425
 
    public int get_panel_height_foobar ()
1426
 
    {
1427
 
      return this.get_panel_height ();
1428
 
    }
1429
 
 
1430
 
    /* this is needed to avoid a symbol clash in unity/targets/mutter/main.c */
1431
 
    public int get_launcher_width_foobar ()
1432
 
    {
1433
 
      return this.get_launcher_width ();
1434
 
    }
1435
 
  }
1436
 
}