~unity-team/unity/panel-fixes-2011-03-17

« back to all changes in this revision

Viewing changes to src/Launcher.cpp

  • Committer: Didier Roche
  • Date: 2011-03-16 16:29:02 UTC
  • mfrom: (945.10.8 launcher-changes)
  • Revision ID: didier.roche@canonical.com-20110316162902-a9m48xz7q26oyj0t
This branch:
* Fix some false-positive when the check call isn't refresh on ws change (LP:
#730679)
* enable adding a new desktop file with the dbus call (LP: #670403)
* add another drag icon action: pressing for 500ms on a launcher icon would
decouple it from the Launcher. Clean some other code as well (LP: #727922)
* increase the dead zone size on th bfb (lp: #736034)
* do some cleanup on the launcher code as well

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
 
52
52
#define BACKLIGHT_STRENGTH  0.9f
53
53
 
 
54
#define S_DBUS_NAME  "com.canonical.Unity.Launcher"
 
55
#define S_DBUS_PATH  "/com/canonical/Unity/Launcher"
 
56
#define S_DBUS_IFACE "com.canonical.Unity.Launcher"
 
57
 
54
58
NUX_IMPLEMENT_OBJECT_TYPE (Launcher);
55
59
 
56
60
int
72
76
  timeref->tv_nsec -= remove * 1000000;
73
77
}
74
78
 
 
79
const gchar Launcher::introspection_xml[] =
 
80
  "<node>"
 
81
  "  <interface name='com.canonical.Unity.Launcher'>"
 
82
  ""
 
83
  "    <method name='AddLauncherItemFromPosition'>"
 
84
  "      <arg type='s' name='icon' direction='in'/>"
 
85
  "      <arg type='s' name='title' direction='in'/>"
 
86
  "      <arg type='i' name='icon_x' direction='in'/>"
 
87
  "      <arg type='i' name='icon_y' direction='in'/>"
 
88
  "      <arg type='i' name='icon_size' direction='in'/>"
 
89
  "      <arg type='s' name='desktop_file' direction='in'/>"
 
90
  "      <arg type='s' name='aptdaemon_task' direction='in'/>"
 
91
  "    </method>"
 
92
  ""
 
93
  "  </interface>"
 
94
  "</node>";
 
95
  
 
96
GDBusInterfaceVTable Launcher::interface_vtable =
 
97
{
 
98
  Launcher::handle_dbus_method_call,
 
99
  NULL,
 
100
  NULL
 
101
};
 
102
 
75
103
 
76
104
/*
77
105
                Use this shader to pass vertices in screen coordinates in the C++ code and compute use
303
331
    _autohide_handle        = 0;
304
332
    _autoscroll_handle      = 0;
305
333
    _redraw_handle          = 0;
 
334
    _start_dragicon_handle  = 0;
306
335
    _focus_keynav_handle    = 0;
307
 
    _single_finger_hold_handle = 0;
308
 
    _single_finger_hold_timer  = NULL;
309
336
    _floating               = false;
310
337
    _hovered                = false;
311
338
    _hidden                 = false;
355
382
    ubus_server_register_interest (ubus, UBUS_LAUNCHER_ACTION_DONE,
356
383
                                   (UBusCallback)&Launcher::OnActionDone,
357
384
                                   this);
 
385
    
 
386
    _dbus_owner = g_bus_own_name (G_BUS_TYPE_SESSION,
 
387
                                  S_DBUS_NAME,
 
388
                                  (GBusNameOwnerFlags) (G_BUS_NAME_OWNER_FLAGS_REPLACE | G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT),
 
389
                                  OnBusAcquired,
 
390
                                  OnNameAcquired,
 
391
                                  OnNameLost,
 
392
                                  this,
 
393
                                  NULL);
358
394
 
359
395
    SetDndEnabled (false, true);
360
396
}
366
402
    if (_superkey_labels[i])
367
403
      _superkey_labels[i]->UnReference ();
368
404
  }
 
405
  g_bus_unown_name (_dbus_owner);
369
406
}
370
407
 
371
408
/* Introspection */
608
645
    return pow (1.0f - CLAMP ((float) (TimeDelta (&current, &_times[TIME_DRAG_END])) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f), 2);
609
646
}
610
647
 
611
 
float Launcher::DnDStartProgress (struct timespec const &current)
612
 
{
613
 
  return CLAMP ((float) (TimeDelta (&current, &_times[TIME_DRAG_START])) / (float) ANIM_DURATION, 0.0f, 1.0f);
614
 
}
615
 
 
616
648
float Launcher::AutohideProgress (struct timespec const &current)
617
649
{
618
650
    
624
656
          return 0.0f;
625
657
          
626
658
        // "dead" zone
627
 
        if ((_trigger_mouse_position.x < 2) && (_trigger_mouse_position.y < 2))
 
659
        if ((_trigger_mouse_position.x < 3) && (_trigger_mouse_position.y < 3))
628
660
            return GetAutohidePositionMin ();
629
661
        
630
662
       /* 
749
781
    // hover out animation
750
782
    if (TimeDelta (&current, &_times[TIME_LEAVE]) < ANIM_DURATION)
751
783
        return true;
752
 
  
753
 
    // drag start animation
754
 
    if (TimeDelta (&current, &_times[TIME_DRAG_START]) < ANIM_DURATION)
755
 
        return true;
756
784
    
757
785
    // drag end animation
758
786
    if (TimeDelta (&current, &_times[TIME_DRAG_END]) < ANIM_DURATION_LONG)
1442
1470
{
1443
1471
    if (hidden == _hidden)
1444
1472
        return;
1445
 
    
 
1473
        
1446
1474
    // auto lock/unlock the launcher depending on the state switch
1447
1475
    if (hidden)
1448
1476
    {
1487
1515
  return _mouse_position.y;
1488
1516
}
1489
1517
 
1490
 
gboolean
1491
 
Launcher::SingleFingerHoldTimeout (gpointer data)
1492
 
{
1493
 
  Launcher*     self          = NULL;
1494
 
  LauncherIcon* launcher_icon = NULL;
1495
 
 
1496
 
  self = (Launcher*) data;
1497
 
  launcher_icon = self->MouseIconIntersection (self->GetMouseX (),
1498
 
                                               self->GetMouseY ());
1499
 
  if (launcher_icon)
1500
 
    launcher_icon->OpenQuicklist ();
1501
 
 
1502
 
  return false;
1503
 
}
1504
 
 
1505
1518
gboolean Launcher::DrawLauncherTimeout (gpointer data)
1506
1519
{
1507
1520
    Launcher *self = (Launcher*) data;
1542
1555
  if (!window || !(window->type () & intersect_types) || !window->isMapped () || !window->isViewable ())
1543
1556
    return false;
1544
1557
 
1545
 
  if (CompRegion (window->serverInputRect ()).intersects (CompRect (geo.x, geo.y, geo.width, geo.height)))
 
1558
  if (CompRegion (window->inputRect ()).intersects (CompRect (geo.x, geo.y, geo.width, geo.height)))
1546
1559
    return true;
1547
1560
 
1548
1561
  return false;
2337
2350
    guint64 shortcut = arg.icon->GetShortcut ();
2338
2351
 
2339
2352
    /* deal with dynamic labels for places, which can be set via the locale */
2340
 
    if (shortcut != 0 && !g_ascii_isdigit ((gchar) shortcut))
2341
 
    {
2342
 
      RenderIcon (GfxContext,
2343
 
                  arg,
2344
 
                  arg.icon->GetSuperkeyLabel ()->GetDeviceTexture (),
2345
 
                  nux::Color (0xFFFFFFFF),
2346
 
                  arg.alpha,
2347
 
                  arg.icon->_xform_coords["Tile"]);
2348
 
    }
2349
 
    else
2350
 
    {
2351
 
      /* deal with the hardcoded labels used for the first 10 icons on the launcher */
2352
 
      gchar key   = (gchar) shortcut;
2353
 
      int   index = -1;
2354
 
 
2355
 
      switch (key)
 
2353
    if (shortcut != 0)
 
2354
    {
 
2355
      if (!g_ascii_isdigit ((gchar) shortcut))
2356
2356
      {
2357
 
        case '1': index = 0; break;
2358
 
        case '2': index = 1; break;
2359
 
        case '3': index = 2; break;
2360
 
        case '4': index = 3; break;
2361
 
        case '5': index = 4; break;
2362
 
        case '6': index = 5; break;
2363
 
        case '7': index = 6; break;
2364
 
        case '8': index = 7; break;
2365
 
        case '9': index = 8; break;
2366
 
        case '0': index = 9; break;
 
2357
        RenderIcon (GfxContext,
 
2358
                    arg,
 
2359
                    arg.icon->GetSuperkeyLabel ()->GetDeviceTexture (),
 
2360
                    nux::Color (0xFFFFFFFF),
 
2361
                    arg.alpha,
 
2362
                    arg.icon->_xform_coords["Tile"]);
2367
2363
      }
2368
 
 
2369
 
      if (index != -1)
 
2364
      else
 
2365
      {
 
2366
        /* deal with the hardcoded labels used for the first 10 icons on the launcher */
 
2367
        gchar *shortcut_str = g_strdup_printf ("%c", (gchar)shortcut);
 
2368
        int index = (atoi (shortcut_str) + 9) % 10; // Not -1 as -1 % 10 = -1…
 
2369
        g_free (shortcut_str);
 
2370
        
2370
2371
        RenderIcon (GfxContext,
2371
2372
                    arg,
2372
2373
                    _superkey_labels[index]->GetDeviceTexture (),
2373
2374
                    nux::Color (0xFFFFFFFF),
2374
2375
                    arg.alpha,
2375
2376
                    arg.icon->_xform_coords["Tile"]);
 
2377
      }
2376
2378
    }
2377
2379
  }
2378
2380
}
2499
2501
  EnsureAnimation ();
2500
2502
}
2501
2503
 
 
2504
 
 
2505
gboolean Launcher::StartIconDragTimeout (gpointer data)
 
2506
{
 
2507
    Launcher *self = (Launcher*) data;
 
2508
    
 
2509
    // if we are still waiting…
 
2510
    if (self->GetActionState () == ACTION_NONE)
 
2511
      self->StartIconDragRequest (self->GetMouseX (), self->GetMouseY ());
 
2512
    return false;    
 
2513
}
 
2514
 
 
2515
void Launcher::StartIconDragRequest (int x, int y)
 
2516
{
 
2517
  LauncherIcon *drag_icon = MouseIconIntersection ((int) (GetGeometry ().x / 2.0f), y);
 
2518
  
 
2519
  // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
 
2520
  // on an internal Launcher property then
 
2521
  if (drag_icon && (_last_button_press == 1) && _model->IconHasSister (drag_icon))
 
2522
  {
 
2523
    StartIconDrag (drag_icon);
 
2524
    SetActionState (ACTION_DRAG_ICON);
 
2525
    UpdateDragWindowPosition (x, y);
 
2526
  } 
 
2527
}
 
2528
 
2502
2529
void Launcher::StartIconDrag (LauncherIcon *icon)
2503
2530
{
2504
2531
  if (!icon)
2612
2639
 
2613
2640
  if (GetActionState () == ACTION_NONE)
2614
2641
  {
2615
 
    SetTimeStruct (&_times[TIME_DRAG_START]);
2616
 
    
2617
2642
    if (nux::Abs (_dnd_delta_y) >= nux::Abs (_dnd_delta_x))
2618
2643
    {
2619
2644
      _launcher_drag_delta += _dnd_delta_y;
2621
2646
    }
2622
2647
    else
2623
2648
    {
2624
 
      LauncherIcon *drag_icon = MouseIconIntersection ((int) (GetGeometry ().x / 2.0f), y);
2625
 
      
2626
 
      // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
2627
 
      // on an internal Launcher property then
2628
 
      if (drag_icon && (_last_button_press == 1) && _model->IconHasSister (drag_icon))
2629
 
      {
2630
 
        StartIconDrag (drag_icon);
2631
 
        SetActionState (ACTION_DRAG_ICON);
2632
 
        UpdateDragWindowPosition (x, y);
2633
 
      }
2634
 
 
 
2649
      StartIconDragRequest (x, y);
2635
2650
    }
2636
2651
  }
2637
2652
  else if (GetActionState () == ACTION_DRAG_LAUNCHER)
2899
2914
  LauncherIcon* launcher_icon = 0;
2900
2915
  launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
2901
2916
 
2902
 
  // this takes care of the one-finger-hold "event" on a launcher-icon
2903
 
  if (_single_finger_hold_handle == 0)
2904
 
  {
2905
 
    _single_finger_hold_handle = g_timeout_add (SINGLE_FINGER_HOLD_DURATION,
2906
 
                                                &Launcher::SingleFingerHoldTimeout,
2907
 
                                                this);
2908
 
    if (_single_finger_hold_timer)
2909
 
      g_timer_destroy (_single_finger_hold_timer);
2910
 
 
2911
 
    _single_finger_hold_timer = g_timer_new ();
2912
 
  }
2913
 
 
2914
2917
  if (launcher_icon)
2915
2918
  {
2916
2919
    _icon_mouse_down = launcher_icon;
 
2920
    // if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app
 
2921
    if (_start_dragicon_handle > 0)
 
2922
      g_source_remove (_start_dragicon_handle);
 
2923
    _start_dragicon_handle = g_timeout_add (START_DRAGICON_DURATION, &Launcher::StartIconDragTimeout, this);
 
2924
    
2917
2925
    launcher_icon->MouseDown.emit (nux::GetEventButton (button_flags));
2918
2926
  }
2919
2927
}
2921
2929
void Launcher::MouseUpLogic (int x, int y, unsigned long button_flags, unsigned long key_flags)
2922
2930
{
2923
2931
  LauncherIcon* launcher_icon = 0;
 
2932
  
2924
2933
  launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
2925
 
 
2926
 
  // this takes care of the one-finger-hold "event" on a launcher-icon
2927
 
  if (_single_finger_hold_timer)
2928
 
  {
2929
 
    // user "released" before single-finger-hold threshold
2930
 
    if (g_timer_elapsed (_single_finger_hold_timer, NULL) < (float) SINGLE_FINGER_HOLD_DURATION / 1000.0)
2931
 
    {
2932
 
 
2933
 
      // remove callback
2934
 
      if (_single_finger_hold_handle > 0)
2935
 
      {
2936
 
        g_source_remove (_single_finger_hold_handle);
2937
 
        _single_finger_hold_handle = 0;
2938
 
      }
2939
 
    }
2940
 
    // user "released" after single-finger-hold threshold...
2941
 
    else
2942
 
    {
2943
 
      // remove timer
2944
 
      g_timer_destroy (_single_finger_hold_timer);
2945
 
      _single_finger_hold_timer = NULL;
2946
 
 
2947
 
      // remove callback
2948
 
      if (_single_finger_hold_handle > 0)
2949
 
      {
2950
 
        g_source_remove (_single_finger_hold_handle);
2951
 
        _single_finger_hold_handle = 0;
2952
 
      }
2953
 
 
2954
 
      // ... don't start app, just return
2955
 
      _icon_mouse_down = 0;
2956
 
      return;
2957
 
    }
2958
 
 
2959
 
    // remove timer
2960
 
    g_timer_destroy (_single_finger_hold_timer);
2961
 
    _single_finger_hold_timer = NULL;
2962
 
 
2963
 
    // remove callback
2964
 
    if (_single_finger_hold_handle > 0)
2965
 
    {
2966
 
      g_source_remove (_single_finger_hold_handle);
2967
 
      _single_finger_hold_handle = 0;
2968
 
    }
2969
 
  }
 
2934
  
 
2935
  if (_start_dragicon_handle > 0)
 
2936
      g_source_remove (_start_dragicon_handle);
 
2937
  _start_dragicon_handle = 0;
2970
2938
 
2971
2939
  if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
2972
2940
  {
2973
2941
    _icon_mouse_down->MouseUp.emit (nux::GetEventButton (button_flags));
2974
2942
 
2975
 
    if (GetActionState () == ACTION_NONE)
 
2943
    if (GetActionState () == ACTION_NONE) {
2976
2944
      _icon_mouse_down->MouseClick.emit (nux::GetEventButton (button_flags));
 
2945
    }
2977
2946
  }
2978
2947
 
2979
2948
  if (launcher_icon && (_icon_mouse_down != launcher_icon))
3674
3643
    
3675
3644
    if (path)
3676
3645
    {
3677
 
      launcher_dropped.emit (path, _dnd_hovered_icon);
 
3646
      launcher_addrequest.emit (path, _dnd_hovered_icon);
3678
3647
      g_free (path);
3679
3648
    }
3680
3649
  }
3712
3681
  else
3713
3682
    return NULL;
3714
3683
}
 
3684
 
 
3685
/* dbus handlers */
 
3686
 
 
3687
void
 
3688
Launcher::handle_dbus_method_call (GDBusConnection       *connection,
 
3689
                                   const gchar           *sender,
 
3690
                                   const gchar           *object_path,
 
3691
                                   const gchar           *interface_name,
 
3692
                                   const gchar           *method_name,
 
3693
                                   GVariant              *parameters,
 
3694
                                   GDBusMethodInvocation *invocation,
 
3695
                                   gpointer               user_data)
 
3696
{
 
3697
 
 
3698
  if (g_strcmp0 (method_name, "AddLauncherItemFromPosition") == 0)
 
3699
  {
 
3700
    gchar  *icon;
 
3701
    gchar  *title;
 
3702
    gint32  icon_x;
 
3703
    gint32  icon_y;
 
3704
    gint32  icon_size;
 
3705
    gchar  *desktop_file;   
 
3706
    gchar  *aptdaemon_task;
 
3707
    
 
3708
    g_variant_get (parameters, "(ssiiiss)", &icon, &title, &icon_x, &icon_y, &icon_size, &desktop_file, &aptdaemon_task, NULL);
 
3709
    
 
3710
    Launcher *self = (Launcher*)user_data;
 
3711
    self->launcher_addrequest.emit (desktop_file, NULL);
 
3712
    
 
3713
    g_dbus_method_invocation_return_value (invocation, NULL);
 
3714
    g_free (icon);
 
3715
    g_free (title);
 
3716
    g_free (desktop_file);
 
3717
    g_free (aptdaemon_task);
 
3718
  }
 
3719
  
 
3720
}
 
3721
 
 
3722
void
 
3723
Launcher::OnBusAcquired (GDBusConnection *connection,
 
3724
                         const gchar     *name,
 
3725
                         gpointer         user_data)
 
3726
{
 
3727
  GDBusNodeInfo *introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
 
3728
  guint registration_id;
 
3729
  
 
3730
  if (!introspection_data) {
 
3731
    g_warning ("No introspection data loaded. Won't get dynamic launcher addition.");
 
3732
    return;
 
3733
  }
 
3734
  
 
3735
  
 
3736
  
 
3737
  registration_id = g_dbus_connection_register_object (connection,
 
3738
                                                       S_DBUS_PATH,
 
3739
                                                       introspection_data->interfaces[0],
 
3740
                                                       &interface_vtable,
 
3741
                                                       user_data,
 
3742
                                                       NULL,
 
3743
                                                       NULL);
 
3744
  if (!registration_id)
 
3745
    g_warning ("Object registration failed. Won't get dynamic launcher addition.");
 
3746
  
 
3747
}
 
3748
 
 
3749
void
 
3750
Launcher::OnNameAcquired (GDBusConnection *connection,
 
3751
                          const gchar     *name,
 
3752
                          gpointer         user_data)
 
3753
{
 
3754
  g_debug ("Acquired the name %s on the session bus\n", name);
 
3755
}
 
3756
 
 
3757
void
 
3758
Launcher::OnNameLost (GDBusConnection *connection,
 
3759
                       const gchar     *name,
 
3760
                       gpointer         user_data)
 
3761
{
 
3762
  g_debug ("Lost the name %s on the session bus\n", name);
 
3763
}