~3v1n0/unity/overlay-border-scale

« back to all changes in this revision

Viewing changes to plugins/unityshell/src/BamfLauncherIcon.cpp

  • Committer: Daniel van Vugt
  • Date: 2012-03-14 06:24:18 UTC
  • mfrom: (2108 unity)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: daniel.van.vugt@canonical.com-20120314062418-nprucpbr0m7qky5e
MergedĀ latestĀ lp:unity

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2
2
/*
3
 
 * Copyright (C) 2010 Canonical Ltd
 
3
 * Copyright (C) 2010-2012 Canonical Ltd
4
4
 *
5
5
 * This program is free software: you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License version 3 as
15
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
16
 *
17
17
 * Authored by: Jason Smith <jason.smith@canonical.com>
 
18
 *              Marco Trevisan (TreviƱo) <3v1n0@ubuntu.com>
18
19
 */
19
20
 
20
21
#include <Nux/Nux.h>
21
22
#include <Nux/BaseWindow.h>
 
23
#include <UnityCore/Variant.h>
22
24
 
23
25
#include "BamfLauncherIcon.h"
24
26
#include "FavoriteStore.h"
25
27
#include "Launcher.h"
 
28
#include "MultiMonitor.h"
26
29
#include "WindowManager.h"
27
30
#include "UBusMessages.h"
28
31
#include "ubus-server.h"
29
32
 
30
33
#include <glib/gi18n-lib.h>
31
34
#include <gio/gdesktopappinfo.h>
32
 
#include <libindicator/indicator-desktop-shortcuts.h>
33
35
 
34
36
#include <UnityCore/GLibWrapper.h>
35
37
 
38
40
namespace launcher
39
41
{
40
42
 
41
 
struct _ShortcutData
42
 
{
43
 
  BamfLauncherIcon* self;
44
 
  IndicatorDesktopShortcuts* shortcuts;
45
 
  char* nick;
46
 
};
47
 
typedef struct _ShortcutData ShortcutData;
48
 
static void shortcut_data_destroy(ShortcutData* data)
49
 
{
50
 
  g_object_unref(data->shortcuts);
51
 
  g_free(data->nick);
52
 
  g_slice_free(ShortcutData, data);
53
 
}
54
 
 
55
 
static void shortcut_activated(DbusmenuMenuitem* _sender, guint timestamp, gpointer userdata)
56
 
{
57
 
  ShortcutData* data = (ShortcutData*)userdata;
58
 
  indicator_desktop_shortcuts_nick_exec(data->shortcuts, data->nick);
 
43
NUX_IMPLEMENT_OBJECT_TYPE(BamfLauncherIcon);
 
44
 
 
45
BamfLauncherIcon::BamfLauncherIcon(BamfApplication* app)
 
46
  : SimpleLauncherIcon()
 
47
  , _bamf_app(app, glib::AddRef())
 
48
  , _dnd_hovered(false)
 
49
  , _dnd_hover_timer(0)
 
50
  , _supported_types_filled(false)
 
51
  , _fill_supported_types_id(0)
 
52
  , _window_moved_id(0)
 
53
{
 
54
  auto bamf_view = glib::object_cast<BamfView>(_bamf_app);
 
55
 
 
56
  glib::String icon(bamf_view_get_icon(bamf_view));
 
57
 
 
58
  tooltip_text = BamfName();
 
59
  icon_name = icon.Str();
 
60
  SetIconType(TYPE_APPLICATION);
 
61
 
 
62
  if (IsSticky())
 
63
    SetQuirk(QUIRK_VISIBLE, true);
 
64
  else
 
65
    SetQuirk(QUIRK_VISIBLE, bamf_view_user_visible(bamf_view));
 
66
 
 
67
  SetQuirk(QUIRK_ACTIVE, bamf_view_is_active(bamf_view));
 
68
  SetQuirk(QUIRK_RUNNING, bamf_view_is_running(bamf_view));
 
69
 
 
70
  glib::SignalBase* sig;
 
71
 
 
72
  sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-added",
 
73
                          [&] (BamfView*, BamfView*) {
 
74
                            EnsureWindowState();
 
75
                            UpdateMenus();
 
76
                            UpdateIconGeometries(GetCenters());
 
77
                          });
 
78
  _gsignals.Add(sig);
 
79
 
 
80
  sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",
 
81
                          [&] (BamfView*, BamfView*) { EnsureWindowState(); });
 
82
  _gsignals.Add(sig);
 
83
 
 
84
  sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "urgent-changed",
 
85
                          [&] (BamfView*, gboolean urgent) {
 
86
                            SetQuirk(QUIRK_URGENT, urgent);
 
87
                          });
 
88
  _gsignals.Add(sig);
 
89
 
 
90
  sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "active-changed",
 
91
                          [&] (BamfView*, gboolean active) {
 
92
                            SetQuirk(QUIRK_ACTIVE, active);
 
93
                          });
 
94
  _gsignals.Add(sig);
 
95
 
 
96
  sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "running-changed",
 
97
                          [&] (BamfView*, gboolean running) {
 
98
                            SetQuirk(QUIRK_RUNNING, running);
 
99
                            if (running)
 
100
                            {
 
101
                              EnsureWindowState();
 
102
                              UpdateIconGeometries(GetCenters());
 
103
                            }
 
104
                          });
 
105
  _gsignals.Add(sig);
 
106
 
 
107
  sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view, "user-visible-changed",
 
108
                          [&] (BamfView*, gboolean visible) {
 
109
                            if (!IsSticky())
 
110
                              SetQuirk(QUIRK_VISIBLE, visible);
 
111
                          });
 
112
  _gsignals.Add(sig);
 
113
 
 
114
  sig = new glib::Signal<void, BamfView*>(bamf_view, "closed",
 
115
                          [&] (BamfView*) {
 
116
                            if (!IsSticky())
 
117
                              Remove();
 
118
                          });
 
119
  _gsignals.Add(sig);
 
120
 
 
121
  WindowManager::Default()->window_minimized.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMinimized));
 
122
  WindowManager::Default()->window_moved.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMoved));
 
123
  WindowManager::Default()->compiz_screen_viewport_switch_ended.connect(sigc::mem_fun(this, &BamfLauncherIcon::EnsureWindowState));
 
124
  WindowManager::Default()->terminate_expo.connect(sigc::mem_fun(this, &BamfLauncherIcon::EnsureWindowState));
 
125
 
 
126
  EnsureWindowState();
 
127
  UpdateMenus();
 
128
  UpdateDesktopFile();
 
129
 
 
130
  // hack
 
131
  SetProgress(0.0f);
 
132
 
 
133
  // Calls when there are no higher priority events pending to the default main loop.
 
134
  _fill_supported_types_id = g_idle_add([] (gpointer data) -> gboolean {
 
135
    static_cast<BamfLauncherIcon*>(data)->FillSupportedTypes();
 
136
    return false;
 
137
  }, this);
 
138
}
 
139
 
 
140
BamfLauncherIcon::~BamfLauncherIcon()
 
141
{
 
142
  g_object_set_qdata(G_OBJECT(_bamf_app.RawPtr()),
 
143
                     g_quark_from_static_string("unity-seen"),
 
144
                     GINT_TO_POINTER(0));
 
145
 
 
146
  if (_fill_supported_types_id != 0)
 
147
    g_source_remove(_fill_supported_types_id);
 
148
 
 
149
  if (_window_moved_id != 0)
 
150
    g_source_remove(_window_moved_id);
 
151
 
 
152
  if (_dnd_hover_timer != 0)
 
153
    g_source_remove(_dnd_hover_timer);
 
154
}
 
155
 
 
156
bool BamfLauncherIcon::IsSticky() const
 
157
{
 
158
  return bamf_view_is_sticky(BAMF_VIEW(_bamf_app.RawPtr()));
 
159
}
 
160
 
 
161
bool BamfLauncherIcon::IsVisible() const
 
162
{
 
163
  return GetQuirk(QUIRK_VISIBLE);
 
164
}
 
165
 
 
166
bool BamfLauncherIcon::IsActive() const
 
167
{
 
168
  return GetQuirk(QUIRK_ACTIVE);
 
169
}
 
170
 
 
171
bool BamfLauncherIcon::IsRunning() const
 
172
{
 
173
  return GetQuirk(QUIRK_RUNNING);
 
174
}
 
175
 
 
176
bool BamfLauncherIcon::IsUrgent() const
 
177
{
 
178
  return GetQuirk(QUIRK_URGENT);
59
179
}
60
180
 
61
181
void BamfLauncherIcon::ActivateLauncherIcon(ActionArg arg)
63
183
  SimpleLauncherIcon::ActivateLauncherIcon(arg);
64
184
  bool scaleWasActive = WindowManager::Default()->IsScaleActive();
65
185
  GList    *l;
66
 
  BamfView *view;
67
 
 
68
 
  bool active, running, user_visible;
69
 
  active = bamf_view_is_active(BAMF_VIEW(m_App));
70
 
  running = bamf_view_is_running(BAMF_VIEW(m_App));
71
 
  user_visible = running;
72
 
 
73
 
  if (arg.target && OwnsWindow (arg.target))
 
186
 
 
187
  bool active = IsActive();
 
188
  bool user_visible = IsRunning();
 
189
 
 
190
  if (arg.target && OwnsWindow(arg.target))
74
191
  {
75
192
    WindowManager::Default()->Activate(arg.target);
76
193
    return;
82
199
 
83
200
  if (arg.source != ActionArg::SWITCHER)
84
201
  {
85
 
    user_visible = bamf_view_user_visible(BAMF_VIEW(m_App));
 
202
    auto bamf_view = glib::object_cast<BamfView>(_bamf_app);
 
203
    user_visible = bamf_view_user_visible(bamf_view);
86
204
 
87
205
    bool any_visible = false;
88
 
    for (l = bamf_view_get_children(BAMF_VIEW(m_App)); l; l = l->next)
 
206
    GList *children = bamf_view_get_children(bamf_view);
 
207
 
 
208
    for (l = children; l; l = l->next)
89
209
    {
90
 
      view = static_cast <BamfView*> (l->data);
91
 
 
92
 
      if (BAMF_IS_WINDOW(view))
93
 
      {
94
 
        Window xid = bamf_window_get_xid(BAMF_WINDOW(view));
95
 
 
96
 
        if (!any_visible && WindowManager::Default()->IsWindowOnCurrentDesktop(xid))
97
 
        {
98
 
          any_visible = true;
99
 
        }
100
 
        if (active && !WindowManager::Default()->IsWindowMapped(xid))
101
 
        {
102
 
          active = false;
103
 
        }
 
210
      if (!BAMF_IS_WINDOW(l->data))
 
211
        continue;
 
212
 
 
213
      Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
214
 
 
215
      if (!any_visible && WindowManager::Default()->IsWindowOnCurrentDesktop(xid))
 
216
      {
 
217
        any_visible = true;
 
218
      }
 
219
 
 
220
      if (active && !WindowManager::Default()->IsWindowMapped(xid))
 
221
      {
 
222
        active = false;
104
223
      }
105
224
    }
106
225
 
 
226
    g_list_free(children);
 
227
 
107
228
    if (!any_visible)
108
229
      active = false;
109
230
  }
116
237
   * 5) Spread is active -> Spread de-activated, and fall through
117
238
   */
118
239
 
119
 
  if (!running || (running && !user_visible)) // #1 above
 
240
  if (!IsRunning() || (IsRunning() && !user_visible)) // #1 above
120
241
  {
121
242
    if (GetQuirk(QUIRK_STARTING))
122
243
      return;
163
284
  }
164
285
 
165
286
  if (arg.source != ActionArg::SWITCHER)
166
 
    ubus_server_send_message(ubus_server_get_default(), UBUS_LAUNCHER_ACTION_DONE, NULL);
167
 
}
168
 
 
169
 
BamfLauncherIcon::BamfLauncherIcon(Launcher* IconManager, BamfApplication* app)
170
 
  : SimpleLauncherIcon(IconManager)
171
 
  , _supported_types_filled(false)
172
 
  , _fill_supported_types_id(0)
173
 
{
174
 
  _cached_desktop_file = NULL;
175
 
  _cached_name = NULL;
176
 
  m_App = app;
177
 
  _remote_uri = 0;
178
 
  _dnd_hover_timer = 0;
179
 
  _dnd_hovered = false;
180
 
  _launcher = IconManager;
181
 
  _desktop_file_monitor = NULL;
182
 
  _menu_desktop_shortcuts = NULL;
183
 
  _on_desktop_file_changed_handler_id = 0;
184
 
  _window_moved_id = 0;
185
 
  glib::String icon(bamf_view_get_icon(BAMF_VIEW(m_App)));
186
 
 
187
 
  tooltip_text = BamfName();
188
 
  icon_name = icon.Str();
189
 
  SetIconType(TYPE_APPLICATION);
190
 
 
191
 
  if (bamf_view_is_sticky(BAMF_VIEW(m_App)))
192
 
    SetQuirk(QUIRK_VISIBLE, true);
193
 
  else
194
 
    SetQuirk(QUIRK_VISIBLE, bamf_view_user_visible(BAMF_VIEW(m_App)));
195
 
 
196
 
  SetQuirk(QUIRK_ACTIVE, bamf_view_is_active(BAMF_VIEW(m_App)));
197
 
  SetQuirk(QUIRK_RUNNING, bamf_view_is_running(BAMF_VIEW(m_App)));
198
 
 
199
 
  g_signal_connect(app, "child-removed", (GCallback) &BamfLauncherIcon::OnChildRemoved, this);
200
 
  g_signal_connect(app, "child-added", (GCallback) &BamfLauncherIcon::OnChildAdded, this);
201
 
  g_signal_connect(app, "urgent-changed", (GCallback) &BamfLauncherIcon::OnUrgentChanged, this);
202
 
  g_signal_connect(app, "running-changed", (GCallback) &BamfLauncherIcon::OnRunningChanged, this);
203
 
  g_signal_connect(app, "active-changed", (GCallback) &BamfLauncherIcon::OnActiveChanged, this);
204
 
  g_signal_connect(app, "user-visible-changed", (GCallback) &BamfLauncherIcon::OnUserVisibleChanged, this);
205
 
  g_signal_connect(app, "closed", (GCallback) &BamfLauncherIcon::OnClosed, this);
206
 
 
207
 
  g_object_ref(m_App);
208
 
 
209
 
  EnsureWindowState();
210
 
  UpdateMenus();
211
 
 
212
 
  UpdateDesktopFile();
213
 
 
214
 
  WindowManager::Default()->window_minimized.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMinimized));
215
 
  WindowManager::Default()->window_moved.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMoved));
216
 
  WindowManager::Default()->compiz_screen_viewport_switch_ended.connect(sigc::mem_fun(this, &BamfLauncherIcon::EnsureWindowState));
217
 
  WindowManager::Default()->terminate_expo.connect(sigc::mem_fun(this, &BamfLauncherIcon::EnsureWindowState));
218
 
  IconManager->hidden_changed.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnLauncherHiddenChanged));
219
 
 
220
 
  // hack
221
 
  SetProgress(0.0f);
222
 
 
223
 
  // Calls when there are no higher priority events pending to the default main loop.
224
 
  _fill_supported_types_id = g_idle_add((GSourceFunc)FillSupportedTypes, this);
225
 
 
226
 
}
227
 
 
228
 
BamfLauncherIcon::~BamfLauncherIcon()
229
 
{
230
 
  g_object_set_qdata(G_OBJECT(m_App), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(0));
231
 
 
232
 
  // We might not have created the menu items yet
233
 
  for (auto it = _menu_clients.begin(); it != _menu_clients.end(); it++)
234
 
  {
235
 
    g_object_unref(G_OBJECT(it->second));
236
 
  }
237
 
 
238
 
  if (_menu_items.find("Pin") != _menu_items.end())
239
 
  {
240
 
    g_signal_handler_disconnect(G_OBJECT(_menu_items["Pin"]),
241
 
                                _menu_callbacks["Pin"]);
242
 
  }
243
 
 
244
 
  if (_menu_items.find("Quit") != _menu_items.end())
245
 
  {
246
 
    g_signal_handler_disconnect(G_OBJECT(_menu_items["Quit"]),
247
 
                                _menu_callbacks["Quit"]);
248
 
  }
249
 
 
250
 
  for (auto it = _menu_items.begin(); it != _menu_items.end(); it++)
251
 
  {
252
 
    g_object_unref(G_OBJECT(it->second));
253
 
  }
254
 
 
255
 
  for (auto it = _menu_items_extra.begin(); it != _menu_items_extra.end(); it++)
256
 
  {
257
 
    g_object_unref(G_OBJECT(it->second));
258
 
  }
259
 
 
260
 
  if (G_IS_OBJECT(_menu_desktop_shortcuts))
261
 
    g_object_unref(G_OBJECT(_menu_desktop_shortcuts));
262
 
 
263
 
  if (_on_desktop_file_changed_handler_id != 0)
264
 
    g_signal_handler_disconnect(G_OBJECT(_desktop_file_monitor),
265
 
                                _on_desktop_file_changed_handler_id);
266
 
 
267
 
  if (_fill_supported_types_id != 0)
268
 
    g_source_remove(_fill_supported_types_id);
269
 
  
270
 
  if (_window_moved_id != 0)
271
 
    g_source_remove(_window_moved_id);
272
 
 
273
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnChildRemoved,       this);
274
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnChildAdded,         this);
275
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnUrgentChanged,      this);
276
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnRunningChanged,     this);
277
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnActiveChanged,      this);
278
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnUserVisibleChanged, this);
279
 
  g_signal_handlers_disconnect_by_func(m_App, (void*) &BamfLauncherIcon::OnClosed,             this);
280
 
 
281
 
  g_object_unref(m_App);
282
 
  g_object_unref(_desktop_file_monitor);
283
 
 
284
 
  g_free(_cached_desktop_file);
285
 
  g_free(_cached_name);
286
 
}
287
 
 
288
 
std::vector<Window> BamfLauncherIcon::RelatedXids ()
289
 
{
290
 
  std::vector<Window> results;
291
 
  GList* children, *l;
292
 
  BamfView* view;
293
 
  WindowManager *wm = WindowManager::Default();
294
 
 
295
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
296
 
  for (l = children; l; l = l->next)
297
 
  {
298
 
    view = static_cast <BamfView*> (l->data);
299
 
    if (BAMF_IS_WINDOW(view))
300
 
    {
301
 
      guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
302
 
 
303
 
      if (wm->IsWindowMapped(xid))
304
 
      {
305
 
        results.push_back (xid);
306
 
      }
307
 
    }
308
 
  }
309
 
 
310
 
  g_list_free(children);
311
 
  return results;
312
 
}
313
 
 
314
 
std::string BamfLauncherIcon::NameForWindow (Window window)
 
287
    ubus_server_send_message(ubus_server_get_default(), UBUS_LAUNCHER_ACTION_DONE, nullptr);
 
288
}
 
289
 
 
290
std::vector<Window> BamfLauncherIcon::Windows()
 
291
{
 
292
  std::vector<Window> results;
 
293
  GList* children, *l;
 
294
  WindowManager *wm = WindowManager::Default();
 
295
 
 
296
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
 
297
  for (l = children; l; l = l->next)
 
298
  {
 
299
    if (!BAMF_IS_WINDOW(l->data))
 
300
      continue;
 
301
 
 
302
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
303
 
 
304
    if (wm->IsWindowMapped(xid))
 
305
    {
 
306
      results.push_back(xid);
 
307
    }
 
308
  }
 
309
 
 
310
  g_list_free(children);
 
311
  return results;
 
312
}
 
313
 
 
314
std::vector<Window> BamfLauncherIcon::WindowsForMonitor(int monitor)
 
315
{
 
316
  std::vector<Window> results;
 
317
  GList* children, *l;
 
318
  WindowManager *wm = WindowManager::Default();
 
319
 
 
320
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
 
321
  for (l = children; l; l = l->next)
 
322
  {
 
323
    if (!BAMF_IS_WINDOW(l->data))
 
324
      continue;
 
325
 
 
326
    auto window = static_cast<BamfWindow*>(l->data);
 
327
    if (bamf_window_get_monitor(window) == monitor)
 
328
    {
 
329
      guint32 xid = bamf_window_get_xid(window);
 
330
      bool user_visible = bamf_view_user_visible(reinterpret_cast<BamfView*>(window));
 
331
 
 
332
      if (user_visible && wm->IsWindowMapped(xid) && wm->IsWindowOnCurrentDesktop(xid))
 
333
        results.push_back(xid);
 
334
    }
 
335
  }
 
336
 
 
337
  g_list_free(children);
 
338
  return results;
 
339
}
 
340
 
 
341
std::string BamfLauncherIcon::NameForWindow(Window window)
315
342
{
316
343
  std::string result;
317
344
  GList* children, *l;
318
 
  BamfView* view;
319
345
 
320
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
346
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
321
347
  for (l = children; l; l = l->next)
322
348
  {
323
 
    view = static_cast <BamfView*> (l->data);
324
 
    if (BAMF_IS_WINDOW(view) && (Window) bamf_window_get_xid(BAMF_WINDOW(view)) == window)
 
349
    if (!BAMF_IS_WINDOW(l->data))
 
350
      continue;
 
351
 
 
352
    if (bamf_window_get_xid(static_cast<BamfWindow*>(l->data)) == window)
325
353
    {
326
 
      gchar *name = bamf_view_get_name (view);
327
 
      result = name;
328
 
      g_free (name);
 
354
      auto view = static_cast<BamfView*>(l->data);
 
355
      result = glib::String(bamf_view_get_name(view)).Str();
329
356
      break;
330
357
    }
331
358
  }
334
361
  return result;
335
362
}
336
363
 
337
 
void BamfLauncherIcon::OnLauncherHiddenChanged()
338
 
{
339
 
  UpdateIconGeometries(GetCenter());
340
 
}
341
 
 
342
364
void BamfLauncherIcon::OnWindowMinimized(guint32 xid)
343
365
{
344
366
  if (!OwnsWindow(xid))
350
372
 
351
373
void BamfLauncherIcon::OnWindowMoved(guint32 moved_win)
352
374
{
 
375
  if (!OwnsWindow(moved_win))
 
376
    return;
 
377
 
353
378
  if (_window_moved_id != 0)
354
379
    g_source_remove(_window_moved_id);
355
380
 
356
 
  _window_moved_xid = moved_win;
357
 
 
358
381
  _window_moved_id = g_timeout_add(250, [] (gpointer data) -> gboolean
359
382
  {
360
383
    BamfLauncherIcon* self = static_cast<BamfLauncherIcon*>(data);
361
384
    self->EnsureWindowState();
 
385
    self->UpdateIconGeometries(self->GetCenters());
362
386
    self->_window_moved_id = 0;
363
387
    return FALSE;
364
388
  }, this);
365
389
}
366
390
 
367
 
bool BamfLauncherIcon::IsSticky()
368
 
{
369
 
  return bamf_view_is_sticky(BAMF_VIEW(m_App));
370
 
}
371
 
 
372
391
void BamfLauncherIcon::UpdateDesktopFile()
373
392
{
374
 
  char* filename = NULL;
375
 
  filename = (char*) bamf_application_get_desktop_file(m_App);
 
393
  const char* filename = bamf_application_get_desktop_file(_bamf_app);
376
394
 
377
 
  if (filename != NULL && g_strcmp0(_cached_desktop_file, filename) != 0)
 
395
  if (filename != nullptr && filename[0] != '\0' && _desktop_file != filename)
378
396
  {
379
 
    if (_cached_desktop_file != NULL)
380
 
      g_free(_cached_desktop_file);
381
 
 
382
 
    _cached_desktop_file = g_strdup(filename);
 
397
    _desktop_file = filename;
383
398
 
384
399
    // add a file watch to the desktop file so that if/when the app is removed
385
400
    // we can remove ourself from the launcher and when it's changed
386
401
    // we can update the quicklist.
387
402
    if (_desktop_file_monitor)
388
 
    {
389
 
      if (_on_desktop_file_changed_handler_id != 0)
390
 
        g_signal_handler_disconnect(G_OBJECT(_desktop_file_monitor),
391
 
                                    _on_desktop_file_changed_handler_id);
392
 
      g_object_unref(_desktop_file_monitor);  
393
 
    }
 
403
      _gsignals.Disconnect(_desktop_file_monitor, "changed");
394
404
 
395
 
    GFile* desktop_file = g_file_new_for_path(DesktopFile());
 
405
    glib::Object<GFile> desktop_file(g_file_new_for_path(_desktop_file.c_str()));
396
406
    _desktop_file_monitor = g_file_monitor_file(desktop_file, G_FILE_MONITOR_NONE,
397
 
                                                NULL, NULL);
398
 
    g_file_monitor_set_rate_limit (_desktop_file_monitor, 1000);
399
 
    _on_desktop_file_changed_handler_id = g_signal_connect(_desktop_file_monitor,
400
 
                                                           "changed",
401
 
                                                           G_CALLBACK(&BamfLauncherIcon::OnDesktopFileChanged),
402
 
                                                           this);
 
407
                                                nullptr, nullptr);
 
408
    g_file_monitor_set_rate_limit(_desktop_file_monitor, 1000);
 
409
 
 
410
    auto sig = new glib::Signal<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(_desktop_file_monitor, "changed",
 
411
                                [&] (GFileMonitor*, GFile*, GFile*, GFileMonitorEvent event_type) {
 
412
                                  switch (event_type)
 
413
                                  {
 
414
                                    case G_FILE_MONITOR_EVENT_DELETED:
 
415
                                      UnStick();
 
416
                                      break;
 
417
                                    case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
 
418
                                      UpdateDesktopQuickList();
 
419
                                      break;
 
420
                                    default:
 
421
                                      break;
 
422
                                  }
 
423
                                });
 
424
    _gsignals.Add(sig);
403
425
  }
404
426
}
405
427
 
406
 
const char* BamfLauncherIcon::DesktopFile()
 
428
std::string BamfLauncherIcon::DesktopFile()
407
429
{
408
430
  UpdateDesktopFile();
409
 
  return _cached_desktop_file;
 
431
  return _desktop_file;
410
432
}
411
433
 
412
 
const char* BamfLauncherIcon::BamfName()
 
434
std::string BamfLauncherIcon::BamfName() const
413
435
{
414
 
  gchar* name = bamf_view_get_name(BAMF_VIEW(m_App));
415
 
 
416
 
  if (name == NULL)
417
 
    name = g_strdup("");
418
 
 
419
 
  if (_cached_name != NULL)
420
 
    g_free(_cached_name);
421
 
 
422
 
  _cached_name = name;
423
 
 
424
 
  return _cached_name;
 
436
  glib::String name(bamf_view_get_name(BAMF_VIEW(_bamf_app.RawPtr())));
 
437
  return name.Str();
425
438
}
426
439
 
427
440
void BamfLauncherIcon::AddProperties(GVariantBuilder* builder)
428
441
{
429
442
  LauncherIcon::AddProperties(builder);
430
443
 
431
 
  g_variant_builder_add(builder, "{sv}", "desktop-file", g_variant_new_string(DesktopFile()));
432
 
 
433
444
  GList* children, *l;
434
 
  BamfView* view;
435
 
 
436
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
445
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
437
446
  GVariant* xids[(int) g_list_length(children)];
438
447
 
439
448
  int i = 0;
440
449
  for (l = children; l; l = l->next)
441
450
  {
442
 
    view = static_cast <BamfView*> (l->data);
 
451
    if (!BAMF_IS_WINDOW(l->data))
 
452
      continue;
443
453
 
444
 
    if (BAMF_IS_WINDOW(view))
445
 
    {
446
 
      xids[i++] = g_variant_new_uint32(bamf_window_get_xid(BAMF_WINDOW(view)));
447
 
    }
 
454
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
455
    xids[i++] = g_variant_new_uint32(xid);
448
456
  }
449
457
  g_list_free(children);
450
 
  g_variant_builder_add(builder, "{sv}", "xids", g_variant_new_array(G_VARIANT_TYPE_UINT32, xids, i));
 
458
 
 
459
  variant::BuilderWrapper(builder)
 
460
    .add("desktop-file", DesktopFile())
 
461
    .add("xids", g_variant_new_array(G_VARIANT_TYPE_UINT32, xids, i))
 
462
    .add("sticky", IsSticky());
451
463
}
452
464
 
453
 
bool BamfLauncherIcon::OwnsWindow(Window w)
 
465
bool BamfLauncherIcon::OwnsWindow(Window xid) const
454
466
{
455
467
  GList* children, *l;
456
 
  BamfView* view;
457
468
  bool owns = false;
458
469
 
459
 
  if (!w) return owns;
 
470
  if (!xid)
 
471
    return owns;
460
472
 
461
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
473
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
462
474
 
463
475
  for (l = children; l; l = l->next)
464
476
  {
465
 
    view = static_cast <BamfView*> (l->data);
 
477
    if (!BAMF_IS_WINDOW(l->data))
 
478
      continue;
466
479
 
467
 
    if (BAMF_IS_WINDOW(view))
 
480
    if (bamf_window_get_xid(static_cast<BamfWindow*>(l->data)) == xid)
468
481
    {
469
 
      guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
470
 
 
471
 
      if (xid == w)
472
 
      {
473
 
        owns = true;
474
 
        break;
475
 
      }
 
482
      owns = true;
 
483
      break;
476
484
    }
477
485
  }
478
486
 
482
490
 
483
491
void BamfLauncherIcon::OpenInstanceWithUris(std::set<std::string> uris)
484
492
{
485
 
  GDesktopAppInfo* appInfo;
486
 
  GError* error = NULL;
487
 
 
488
 
  appInfo = g_desktop_app_info_new_from_filename(DesktopFile());
489
 
 
490
 
  if (g_app_info_supports_uris(G_APP_INFO(appInfo)))
 
493
  glib::Error error;
 
494
  glib::Object<GDesktopAppInfo> desktopInfo(g_desktop_app_info_new_from_filename(DesktopFile().c_str()));
 
495
  auto appInfo = glib::object_cast<GAppInfo>(desktopInfo);
 
496
 
 
497
  if (g_app_info_supports_uris(appInfo))
491
498
  {
492
 
    GList* list = NULL;
 
499
    GList* list = nullptr;
493
500
 
494
501
    for (auto  it : uris)
495
502
      list = g_list_prepend(list, g_strdup(it.c_str()));
496
503
 
497
 
    g_app_info_launch_uris(G_APP_INFO(appInfo), list, NULL, &error);
 
504
    g_app_info_launch_uris(appInfo, list, nullptr, &error);
498
505
    g_list_free_full(list, g_free);
499
506
  }
500
 
  else if (g_app_info_supports_files(G_APP_INFO(appInfo)))
 
507
  else if (g_app_info_supports_files(appInfo))
501
508
  {
502
 
    GList* list = NULL, *l;
503
 
    
 
509
    GList* list = nullptr;
 
510
 
504
511
    for (auto it : uris)
505
512
    {
506
513
      GFile* file = g_file_new_for_uri(it.c_str());
507
514
      list = g_list_prepend(list, file);
508
515
    }
509
 
    g_app_info_launch(G_APP_INFO(appInfo), list, NULL, &error);
510
 
 
511
 
    for (l = list; l; l = l->next)
512
 
      g_object_unref(G_FILE(list->data));
513
 
 
514
 
    g_list_free(list);
 
516
 
 
517
    g_app_info_launch(appInfo, list, nullptr, &error);
 
518
    g_list_free_full(list, g_object_unref);
515
519
  }
516
520
  else
517
521
  {
518
 
    g_app_info_launch(G_APP_INFO(appInfo), NULL, NULL, &error);
 
522
    g_app_info_launch(appInfo, nullptr, nullptr, &error);
519
523
  }
520
524
 
521
 
  g_object_unref(appInfo);
522
 
 
523
525
  if (error)
524
 
  {
525
 
    g_warning("%s\n", error->message);
526
 
    g_error_free(error);
527
 
  }
 
526
    g_warning("%s\n", error.Message().c_str());
528
527
 
529
528
  UpdateQuirkTime(QUIRK_STARTING);
530
529
}
533
532
{
534
533
  std::set<std::string> empty;
535
534
  OpenInstanceWithUris(empty);
536
 
  ubus_server_send_message(ubus_server_get_default(), UBUS_LAUNCHER_ACTION_DONE, NULL);
 
535
  ubus_server_send_message(ubus_server_get_default(), UBUS_LAUNCHER_ACTION_DONE, nullptr);
537
536
}
538
537
 
539
538
void BamfLauncherIcon::Focus(ActionArg arg)
540
539
{
541
540
  GList* children, *l;
542
 
  BamfView* view;
543
541
  bool any_urgent = false;
544
542
  bool any_visible = false;
545
543
  bool any_user_visible = false;
546
544
 
547
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
545
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
548
546
 
549
547
  std::vector<Window> windows;
550
548
 
551
549
  /* get the list of windows */
552
550
  for (l = children; l; l = l->next)
553
551
  {
554
 
    view = static_cast <BamfView*> (l->data);
555
 
 
556
 
    if (BAMF_IS_WINDOW(view))
557
 
    {
558
 
      Window xid = bamf_window_get_xid(BAMF_WINDOW(view));
559
 
      bool urgent = bamf_view_is_urgent(view);
560
 
      bool user_visible = bamf_view_user_visible(view);
561
 
 
562
 
      if (any_urgent)
563
 
      {
564
 
        if (urgent)
565
 
          windows.push_back(xid);
566
 
      }
567
 
      else if (any_user_visible && !urgent)
568
 
      {
569
 
        if (user_visible)
570
 
          windows.push_back(xid);
571
 
      }
572
 
      else
573
 
      {
574
 
        if (urgent || user_visible)
575
 
        {
576
 
          windows.clear();
577
 
          any_visible = false;
578
 
          any_urgent = (any_urgent || urgent);
579
 
          any_user_visible = (any_user_visible || user_visible);
580
 
        }
581
 
 
582
 
        windows.push_back(xid);
583
 
      }
584
 
 
585
 
      if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid) &&
586
 
          WindowManager::Default()->IsWindowVisible(xid))
587
 
      {
588
 
        any_visible = true;
589
 
      }
 
552
    if (!BAMF_IS_WINDOW(l->data))
 
553
      continue;
 
554
 
 
555
    auto view = static_cast<BamfView*>(l->data);
 
556
 
 
557
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
558
    bool urgent = bamf_view_is_urgent(view);
 
559
    bool user_visible = bamf_view_user_visible(view);
 
560
 
 
561
    if (any_urgent)
 
562
    {
 
563
      if (urgent)
 
564
        windows.push_back(xid);
 
565
    }
 
566
    else if (any_user_visible && !urgent)
 
567
    {
 
568
      if (user_visible)
 
569
        windows.push_back(xid);
 
570
    }
 
571
    else
 
572
    {
 
573
      if (urgent || user_visible)
 
574
      {
 
575
        windows.clear();
 
576
        any_visible = false;
 
577
        any_urgent = (any_urgent || urgent);
 
578
        any_user_visible = (any_user_visible || user_visible);
 
579
      }
 
580
 
 
581
      windows.push_back(xid);
 
582
    }
 
583
 
 
584
    if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid) &&
 
585
        WindowManager::Default()->IsWindowVisible(xid))
 
586
    {
 
587
      any_visible = true;
590
588
    }
591
589
  }
592
590
  g_list_free(children);
596
594
    if (any_visible)
597
595
    {
598
596
      WindowManager::Default()->FocusWindowGroup(windows,
599
 
       WindowManager::FocusVisibility::ForceUnminimizeInvisible);
 
597
       WindowManager::FocusVisibility::ForceUnminimizeInvisible, arg.monitor);
600
598
    }
601
599
    else
602
600
    {
603
601
      WindowManager::Default()->FocusWindowGroup(windows,
604
 
       WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop);
 
602
       WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop, arg.monitor);
605
603
    }
606
604
  }
607
605
  else
608
606
  {
609
607
    WindowManager::Default()->FocusWindowGroup(windows,
610
 
      WindowManager::FocusVisibility::OnlyVisible);
 
608
      WindowManager::FocusVisibility::OnlyVisible, arg.monitor);
611
609
  }
612
610
}
613
611
 
614
612
bool BamfLauncherIcon::Spread(bool current_desktop, int state, bool force)
615
613
{
616
 
  BamfView* view;
617
614
  GList* children, *l;
618
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
615
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
619
616
  WindowManager* wm = WindowManager::Default();
620
617
 
621
618
  std::vector<Window> windowList;
622
619
  for (l = children; l; l = l->next)
623
620
  {
624
 
    view = static_cast <BamfView*> (l->data);
625
 
 
626
 
    if (BAMF_IS_WINDOW(view))
 
621
    if (!BAMF_IS_WINDOW(l->data))
 
622
      continue;
 
623
 
 
624
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
625
 
 
626
    if (!current_desktop || (current_desktop && wm->IsWindowOnCurrentDesktop(xid)))
627
627
    {
628
 
      guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
629
 
 
630
 
      if (!current_desktop || (current_desktop && wm->IsWindowOnCurrentDesktop(xid)))
631
 
      {
632
 
        windowList.push_back((Window) xid);
633
 
      }
 
628
      windowList.push_back(xid);
634
629
    }
635
630
  }
636
631
 
638
633
  return WindowManager::Default()->ScaleWindowGroup(windowList, state, force);
639
634
}
640
635
 
641
 
void BamfLauncherIcon::OnClosed(BamfView* view, gpointer data)
642
 
{
643
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
644
 
 
645
 
  if (!bamf_view_is_sticky(BAMF_VIEW(self->m_App)))
646
 
    self->Remove();
647
 
}
648
 
 
649
 
void BamfLauncherIcon::OnUserVisibleChanged(BamfView* view, gboolean visible,
650
 
                                            gpointer data)
651
 
{
652
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
653
 
 
654
 
  if (!bamf_view_is_sticky(BAMF_VIEW(self->m_App)))
655
 
    self->SetQuirk(QUIRK_VISIBLE, visible);
656
 
}
657
 
 
658
 
void BamfLauncherIcon::OnRunningChanged(BamfView* view, gboolean running,
659
 
                                        gpointer data)
660
 
{
661
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
662
 
  self->SetQuirk(QUIRK_RUNNING, running);
663
 
 
664
 
  if (running)
665
 
  {
666
 
    self->EnsureWindowState();
667
 
    self->UpdateIconGeometries(self->GetCenter());
668
 
  }
669
 
}
670
 
 
671
 
void BamfLauncherIcon::OnActiveChanged(BamfView* view, gboolean active, gpointer data)
672
 
{
673
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
674
 
  self->SetQuirk(QUIRK_ACTIVE, active);
675
 
}
676
 
 
677
 
void BamfLauncherIcon::OnUrgentChanged(BamfView* view, gboolean urgent, gpointer data)
678
 
{
679
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
680
 
  self->SetQuirk(QUIRK_URGENT, urgent);
681
 
}
682
 
 
683
636
void BamfLauncherIcon::EnsureWindowState()
684
637
{
685
638
  GList* children, *l;
686
 
  bool has_win_on_current_vp = false;
687
 
  unsigned int user_visible_count = 0;
688
 
  unsigned int children_count = 0;
 
639
  std::vector<bool> monitors;
 
640
  monitors.resize(max_num_monitors);
689
641
 
690
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
642
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
691
643
  for (l = children; l; l = l->next)
692
644
  {
693
645
    if (!BAMF_IS_WINDOW(l->data))
694
646
      continue;
695
647
 
696
 
    Window xid = bamf_window_get_xid(BAMF_WINDOW(l->data));
697
 
    if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid))
698
 
    {
699
 
      has_win_on_current_vp = true;
700
 
 
701
 
      if (bamf_view_user_visible (BAMF_VIEW (l->data)))
702
 
      {
703
 
        user_visible_count++;
704
 
      }
705
 
    }
706
 
 
707
 
    children_count++;
708
 
  }
709
 
 
710
 
  if (user_visible_count > 0)
711
 
  {
712
 
    SetRelatedWindows(user_visible_count);
713
 
  }
714
 
  else if (children_count > 0)
715
 
  {
716
 
    SetRelatedWindows(1);
717
 
  }
718
 
 
719
 
  SetHasWindowOnViewport(has_win_on_current_vp);
 
648
    auto window = static_cast<BamfWindow*>(l->data);
 
649
    Window xid = bamf_window_get_xid(window);
 
650
    int monitor = bamf_window_get_monitor(window);
 
651
 
 
652
    if (monitor >= 0 && WindowManager::Default()->IsWindowOnCurrentDesktop(xid))
 
653
      monitors[monitor] = true;
 
654
  }
 
655
 
 
656
  for (int i = 0; i < max_num_monitors; i++)
 
657
    SetWindowVisibleOnMonitor(monitors[i], i);
 
658
 
 
659
  EmitNeedsRedraw();
720
660
 
721
661
  g_list_free(children);
722
662
}
723
663
 
724
 
void BamfLauncherIcon::OnChildAdded(BamfView* view, BamfView* child, gpointer data)
725
 
{
726
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
727
 
  self->EnsureWindowState();
728
 
  self->UpdateMenus();
729
 
  self->UpdateIconGeometries(self->GetCenter());
730
 
}
731
 
 
732
 
void BamfLauncherIcon::OnChildRemoved(BamfView* view, BamfView* child, gpointer data)
733
 
{
734
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
735
 
  self->EnsureWindowState();
736
 
}
737
 
 
738
664
void BamfLauncherIcon::UpdateDesktopQuickList()
739
665
{
740
 
  IndicatorDesktopShortcuts* desktop_shortcuts;
741
 
  GKeyFile* keyfile;
742
 
  GError* error = NULL;
743
 
  const char *desktop_file;
744
 
 
745
 
  desktop_file = DesktopFile();
746
 
 
747
 
  if (!desktop_file || g_strcmp0(desktop_file, "") == 0)
748
 
    return;
749
 
 
750
 
  // check that we have the X-Ayatana-Desktop-Shortcuts flag
751
 
  // not sure if we should do this or if libindicator should shut up
752
 
  // and not report errors when it can't find the key.
753
 
  // so FIXME when ted is around
754
 
  keyfile = g_key_file_new();
755
 
  g_key_file_load_from_file(keyfile, desktop_file, G_KEY_FILE_NONE, &error);
756
 
 
757
 
  if (error != NULL)
758
 
  {
759
 
    g_warning("Could not load desktop file for: %s", desktop_file);
760
 
    g_key_file_free(keyfile);
761
 
    g_error_free(error);
762
 
    return;
763
 
  }
764
 
 
765
 
  if (g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP,
766
 
                         "X-Ayatana-Desktop-Shortcuts", NULL))
767
 
  {
768
 
    DbusmenuMenuitem* root = dbusmenu_menuitem_new();
769
 
    dbusmenu_menuitem_set_root(root, TRUE);
770
 
    desktop_shortcuts = indicator_desktop_shortcuts_new(desktop_file, "Unity");
771
 
    const gchar** nicks = indicator_desktop_shortcuts_get_nicks(desktop_shortcuts);
772
 
 
773
 
    int index = 0;
774
 
    if (nicks)
775
 
    {
776
 
      while (((gpointer*) nicks)[index])
777
 
      {
778
 
        gchar* name;
779
 
        DbusmenuMenuitem* item;
780
 
        name = indicator_desktop_shortcuts_nick_get_name(desktop_shortcuts,
781
 
                                                         nicks[index]);
782
 
        ShortcutData* data = g_slice_new0(ShortcutData);
783
 
        data->self = this;
784
 
        data->shortcuts = INDICATOR_DESKTOP_SHORTCUTS(g_object_ref(desktop_shortcuts));
785
 
        data->nick = g_strdup(nicks[index]);
786
 
 
787
 
        item = dbusmenu_menuitem_new();
788
 
        dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name);
789
 
        dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
790
 
        dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
791
 
        g_signal_connect_data(item, "item-activated",
792
 
                              (GCallback) shortcut_activated, (gpointer) data,
793
 
                              (GClosureNotify) shortcut_data_destroy, (GConnectFlags)0);
794
 
 
795
 
        dbusmenu_menuitem_child_append(root, item);
796
 
 
797
 
        index++;
798
 
 
799
 
        g_free(name);
800
 
      }
801
 
    }
802
 
 
803
 
    if (G_IS_OBJECT(_menu_desktop_shortcuts))
804
 
      g_object_unref(G_OBJECT(_menu_desktop_shortcuts));
805
 
 
806
 
    _menu_desktop_shortcuts = root;
807
 
  }
808
 
 
809
 
  g_key_file_free(keyfile);
 
666
  std::string const& desktop_file = DesktopFile();
 
667
 
 
668
  if (desktop_file.empty())
 
669
    return;
 
670
 
 
671
  for (GList *l = dbusmenu_menuitem_get_children(_menu_desktop_shortcuts); l; l = l->next)
 
672
    _gsignals.Disconnect(l->data, "item-activated");
 
673
 
 
674
  _menu_desktop_shortcuts = dbusmenu_menuitem_new();
 
675
  dbusmenu_menuitem_set_root(_menu_desktop_shortcuts, TRUE);
 
676
 
 
677
  // Build a desktop shortcuts object and tell it that our
 
678
  // environment is Unity to handle the filtering
 
679
  _desktop_shortcuts = indicator_desktop_shortcuts_new(desktop_file.c_str(), "Unity");
 
680
  // This will get us a list of the nicks available, it should
 
681
  // always be at least one entry of NULL if there either aren't
 
682
  // any or they're filtered for the environment we're in
 
683
  const gchar** nicks = indicator_desktop_shortcuts_get_nicks(_desktop_shortcuts);
 
684
 
 
685
  int index = 0;
 
686
  while (nicks[index]) {
 
687
  
 
688
    // Build a dbusmenu item for each nick that is the desktop 
 
689
    // file that is built from it's name and includes a callback
 
690
    // to the desktop shortcuts object to execute the nick
 
691
    glib::String name(indicator_desktop_shortcuts_nick_get_name(_desktop_shortcuts,
 
692
                                                                nicks[index]));
 
693
    glib::Object<DbusmenuMenuitem> item(dbusmenu_menuitem_new());
 
694
    dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name);
 
695
    dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
 
696
    dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
 
697
    dbusmenu_menuitem_property_set(item, "shortcut-nick", nicks[index]);
 
698
 
 
699
    auto sig = new glib::Signal<void, DbusmenuMenuitem*, gint>(item, "item-activated",
 
700
                                [&] (DbusmenuMenuitem* item, gint) {
 
701
                                  const gchar *nick;
 
702
                                  nick = dbusmenu_menuitem_property_get(item, "shortcut-nick");
 
703
                                  indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick);
 
704
                                });
 
705
    _gsignals.Add(sig);
 
706
 
 
707
    dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item);
 
708
    index++;
 
709
  }
810
710
}
811
711
 
812
712
void BamfLauncherIcon::UpdateMenus()
813
713
{
814
714
  GList* children, *l;
815
715
 
816
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
716
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
817
717
  for (l = children; l; l = l->next)
818
718
  {
819
719
    if (!BAMF_IS_INDICATOR(l->data))
820
720
      continue;
821
721
 
822
 
    BamfIndicator* indicator = BAMF_INDICATOR(l->data);
 
722
    auto indicator = static_cast<BamfIndicator*>(l->data);
823
723
    std::string path = bamf_indicator_get_dbus_menu_path(indicator);
824
724
 
825
725
    // we already have this
826
726
    if (_menu_clients.find(path) != _menu_clients.end())
827
727
      continue;
828
728
 
829
 
    DbusmenuClient* client = dbusmenu_client_new(bamf_indicator_get_remote_address(indicator), path.c_str());
830
 
    _menu_clients[path] = client;
 
729
    std::string address = bamf_indicator_get_remote_address(indicator);
 
730
    DbusmenuClient* client = dbusmenu_client_new(address.c_str(), path.c_str());
 
731
    _menu_clients[path] = glib::Object<DbusmenuClient>(client);
831
732
  }
832
733
 
833
734
  g_list_free(children);
834
735
 
835
736
  // add dynamic quicklist
836
 
  if (_menuclient_dynamic_quicklist != NULL)
837
 
  {
838
 
    auto menu_client = DBUSMENU_CLIENT(g_object_ref(_menuclient_dynamic_quicklist));
839
 
    _menu_clients["dynamicquicklist"] = menu_client;
 
737
  if (DBUSMENU_IS_CLIENT(_menuclient_dynamic_quicklist))
 
738
  {
 
739
    if (_menu_clients["dynamicquicklist"] != _menuclient_dynamic_quicklist)
 
740
    {
 
741
      _menu_clients["dynamicquicklist"] = glib::Object<DbusmenuClient>(_menuclient_dynamic_quicklist);
 
742
    }
 
743
  }
 
744
  else if (_menu_clients["dynamicquicklist"])
 
745
  {
 
746
    _menu_clients.erase("dynamicquicklist");
 
747
    _menuclient_dynamic_quicklist = nullptr;
840
748
  }
841
749
 
842
750
  // make a client for desktop file actions
843
 
  if (!DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts))
 
751
  if (!DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts.RawPtr()))
844
752
  {
845
753
    UpdateDesktopQuickList();
846
754
  }
847
 
 
848
 
}
849
 
 
850
 
void BamfLauncherIcon::OnQuit(DbusmenuMenuitem* item, int time, BamfLauncherIcon* self)
851
 
{
852
 
  self->Quit();
853
755
}
854
756
 
855
757
void BamfLauncherIcon::Quit()
856
758
{
857
759
  GList* children, *l;
858
 
  BamfView* view;
859
760
 
860
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
761
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
861
762
 
862
763
  for (l = children; l; l = l->next)
863
764
  {
864
 
    view = static_cast <BamfView*> (l->data);
 
765
    if (!BAMF_IS_WINDOW(l->data))
 
766
      continue;
865
767
 
866
 
    if (BAMF_IS_WINDOW(view))
867
 
    {
868
 
      guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
869
 
      WindowManager::Default()->Close(xid);
870
 
    }
 
768
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
769
    WindowManager::Default()->Close(xid);
871
770
  }
872
771
 
873
772
  g_list_free(children);
874
773
}
875
774
 
876
 
void BamfLauncherIcon::Stick()
 
775
void BamfLauncherIcon::Stick(bool save)
877
776
{
878
 
  BamfView* view = BAMF_VIEW(m_App);
879
 
  
880
 
  if (bamf_view_is_sticky(view))
 
777
  if (IsSticky())
881
778
    return;
882
 
  
883
 
  const gchar* desktop_file = DesktopFile();
884
 
  bamf_view_set_sticky(view, true);
885
 
  
886
 
  if (desktop_file && strlen(desktop_file) > 0)
887
 
    FavoriteStore::GetDefault().AddFavorite(desktop_file, -1);
 
779
 
 
780
  std::string const& desktop_file = DesktopFile();
 
781
  bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), true);
 
782
 
 
783
  if (save && !desktop_file.empty())
 
784
    FavoriteStore::GetDefault().AddFavorite(desktop_file.c_str(), -1);
888
785
}
889
786
 
890
 
void BamfLauncherIcon::UnStick(void)
 
787
void BamfLauncherIcon::UnStick()
891
788
{
892
 
  BamfView* view = BAMF_VIEW(this->m_App);
893
 
 
894
 
  if (!bamf_view_is_sticky(view))
 
789
  if (!IsSticky())
895
790
    return;
896
791
 
897
 
  const gchar* desktop_file = DesktopFile();
 
792
  std::string const& desktop_file = DesktopFile();
 
793
  BamfView* view = BAMF_VIEW(_bamf_app.RawPtr());
898
794
  bamf_view_set_sticky(view, false);
899
795
 
900
796
  if (bamf_view_is_closed(view) || !bamf_view_user_visible(view))
901
 
    this->Remove();
 
797
    Remove();
902
798
 
903
 
  if (desktop_file && desktop_file[0] != '\0')
904
 
    FavoriteStore::GetDefault().RemoveFavorite(desktop_file);
 
799
  if (!desktop_file.empty())
 
800
    FavoriteStore::GetDefault().RemoveFavorite(desktop_file.c_str());
905
801
}
906
802
 
907
 
void BamfLauncherIcon::OnTogglePin(DbusmenuMenuitem* item, int time, BamfLauncherIcon* self)
 
803
void BamfLauncherIcon::ToggleSticky()
908
804
{
909
 
  BamfView* view = BAMF_VIEW(self->m_App);
910
 
  bool sticky = bamf_view_is_sticky(view);
911
 
  const gchar* desktop_file = self->DesktopFile();
912
 
 
913
 
  if (sticky)
 
805
  if (IsSticky())
914
806
  {
915
 
    self->UnStick();
 
807
    UnStick();
916
808
  }
917
809
  else
918
810
  {
919
 
    bamf_view_set_sticky(view, true);
920
 
 
921
 
    if (desktop_file && strlen(desktop_file) > 0)
922
 
      FavoriteStore::GetDefault().AddFavorite(desktop_file, -1);
 
811
    Stick();
923
812
  }
924
813
}
925
814
 
931
820
  if (_menu_items.find("Pin") == _menu_items.end())
932
821
  {
933
822
    menu_item = dbusmenu_menuitem_new();
934
 
 
935
823
    dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
936
824
    dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
937
825
 
938
 
    _menu_callbacks["Pin"] = g_signal_connect(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, (GCallback) &BamfLauncherIcon::OnTogglePin, this);
 
826
    _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
827
                                    [&] (DbusmenuMenuitem*, int) {
 
828
                                      ToggleSticky();
 
829
                                    }));
939
830
 
940
 
    _menu_items["Pin"] = menu_item;
 
831
    _menu_items["Pin"] = glib::Object<DbusmenuMenuitem>(menu_item);
941
832
  }
942
 
  
943
 
  const char* label = !bamf_view_is_sticky(BAMF_VIEW(m_App)) ?
944
 
                      _("Lock to launcher") : _("Unlock from launcher");
 
833
 
 
834
  const char* label = !IsSticky() ? _("Lock to Launcher") : _("Unlock from Launcher");
945
835
 
946
836
  dbusmenu_menuitem_property_set(_menu_items["Pin"], DBUSMENU_MENUITEM_PROP_LABEL, label);
947
837
 
950
840
  if (_menu_items.find("Quit") == _menu_items.end())
951
841
  {
952
842
    menu_item = dbusmenu_menuitem_new();
953
 
 
954
843
    dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Quit"));
955
844
    dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
956
845
    dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
957
846
 
958
 
    _menu_callbacks["Quit"] = g_signal_connect(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, (GCallback) &BamfLauncherIcon::OnQuit, this);
 
847
    _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
848
                                    [&] (DbusmenuMenuitem*, int) {
 
849
                                      Quit();
 
850
                                    }));
959
851
 
960
 
    _menu_items["Quit"] = menu_item;
 
852
    _menu_items["Quit"] = glib::Object<DbusmenuMenuitem>(menu_item);
961
853
  }
962
854
}
963
855
 
964
 
static void OnAppLabelActivated(DbusmenuMenuitem* sender,
965
 
                                guint             timestamp,
966
 
                                gpointer data)
967
 
{
968
 
  BamfLauncherIcon* self = NULL;
969
 
 
970
 
  if (!data)
971
 
    return;
972
 
 
973
 
  self = static_cast <BamfLauncherIcon*> (data);
974
 
  self->ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0));
975
 
}
976
 
 
977
856
std::list<DbusmenuMenuitem*> BamfLauncherIcon::GetMenus()
978
857
{
979
 
  std::map<std::string, DbusmenuClient*>::iterator it;
980
858
  std::list<DbusmenuMenuitem*> result;
981
859
  bool first_separator_needed = false;
982
 
  DbusmenuMenuitem* item = NULL;
 
860
  DbusmenuMenuitem* item = nullptr;
983
861
 
984
862
  // FIXME for O: hack around the wrong abstraction
985
863
  UpdateMenus();
986
864
 
987
 
  for (it = _menu_clients.begin(); it != _menu_clients.end(); it++)
 
865
  for (auto it = _menu_clients.begin(); it != _menu_clients.end(); ++it)
988
866
  {
989
 
    GList* child = NULL;
990
 
    DbusmenuClient* client = (*it).second;
 
867
    GList* child = nullptr;
 
868
    DbusmenuClient* client = it->second;
991
869
    DbusmenuMenuitem* root = dbusmenu_client_get_root(client);
992
870
 
993
871
    if (!root || !dbusmenu_menuitem_property_get_bool(root, DBUSMENU_MENUITEM_PROP_VISIBLE))
994
872
      continue;
995
873
 
996
 
    for (child = dbusmenu_menuitem_get_children(root); child != NULL; child = g_list_next(child))
 
874
    for (child = dbusmenu_menuitem_get_children(root); child; child = child->next)
997
875
    {
998
876
      DbusmenuMenuitem* item = (DbusmenuMenuitem*) child->data;
999
877
 
1011
889
  }
1012
890
 
1013
891
  // FIXME: this should totally be added as a _menu_client
1014
 
  if (DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts))
 
892
  if (DBUSMENU_IS_MENUITEM(_menu_desktop_shortcuts.RawPtr()))
1015
893
  {
1016
 
    GList* child = NULL;
1017
 
    DbusmenuMenuitem* root = _menu_desktop_shortcuts;
 
894
    GList* child = nullptr;
1018
895
 
1019
 
    for (child = dbusmenu_menuitem_get_children(root); child != NULL; child = g_list_next(child))
 
896
    for (child = dbusmenu_menuitem_get_children(_menu_desktop_shortcuts); child; child = child->next)
1020
897
    {
1021
898
      DbusmenuMenuitem* item = (DbusmenuMenuitem*) child->data;
1022
899
 
1042
919
      dbusmenu_menuitem_property_set(item,
1043
920
                                     DBUSMENU_MENUITEM_PROP_TYPE,
1044
921
                                     DBUSMENU_CLIENT_TYPES_SEPARATOR);
1045
 
      _menu_items_extra["FirstSeparator"] = item;
 
922
      _menu_items_extra["FirstSeparator"] = glib::Object<DbusmenuMenuitem>(item);
1046
923
    }
1047
924
    result.push_back(item);
1048
925
  }
1054
931
  }
1055
932
  else
1056
933
  {
1057
 
    glib::String app_name(g_markup_escape_text(BamfName(), -1));
 
934
    glib::String app_name(g_markup_escape_text(BamfName().c_str(), -1));
1058
935
    std::ostringstream bold_app_name;
1059
936
    bold_app_name << "<b>" << app_name << "</b>";
1060
937
 
1068
945
    dbusmenu_menuitem_property_set_bool(item,
1069
946
                                        "unity-use-markup",
1070
947
                                        true);
1071
 
    g_signal_connect(item, "item-activated", (GCallback) OnAppLabelActivated, this);
1072
 
 
1073
 
    _menu_items_extra["AppName"] = item;
 
948
 
 
949
    _gsignals.Add(new glib::Signal<void, DbusmenuMenuitem*, int>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
 
950
                                    [&] (DbusmenuMenuitem*, int) {
 
951
                                      ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0));
 
952
                                    }));
 
953
 
 
954
    _menu_items_extra["AppName"] = glib::Object<DbusmenuMenuitem>(item);
1074
955
  }
1075
956
  result.push_back(item);
1076
957
 
1085
966
    dbusmenu_menuitem_property_set(item,
1086
967
                                   DBUSMENU_MENUITEM_PROP_TYPE,
1087
968
                                   DBUSMENU_CLIENT_TYPES_SEPARATOR);
1088
 
    _menu_items_extra["SecondSeparator"] = item;
 
969
    _menu_items_extra["SecondSeparator"] = glib::Object<DbusmenuMenuitem>(item);
1089
970
  }
1090
971
  result.push_back(item);
1091
972
 
1092
973
  EnsureMenuItemsReady();
1093
974
 
1094
 
  std::map<std::string, DbusmenuMenuitem*>::iterator it_m;
1095
 
  std::list<DbusmenuMenuitem*>::iterator it_l;
1096
 
  bool exists;
1097
 
  for (it_m = _menu_items.begin(); it_m != _menu_items.end(); it_m++)
 
975
  for (auto it_m = _menu_items.begin(); it_m != _menu_items.end(); ++it_m)
1098
976
  {
1099
 
    const char* key = ((*it_m).first).c_str();
1100
 
    if (g_strcmp0(key , "Quit") == 0 && !bamf_view_is_running(BAMF_VIEW(m_App)))
 
977
    if (!IsRunning() && it_m->first == "Quit")
1101
978
      continue;
1102
979
 
1103
 
    exists = false;
1104
 
    std::string label_default = dbusmenu_menuitem_property_get((*it_m).second, DBUSMENU_MENUITEM_PROP_LABEL);
1105
 
    for (it_l = result.begin(); it_l != result.end(); it_l++)
 
980
    bool exists = false;
 
981
    std::string label_default(dbusmenu_menuitem_property_get(it_m->second, DBUSMENU_MENUITEM_PROP_LABEL));
 
982
 
 
983
    for (auto menu_item : result)
1106
984
    {
1107
 
      const gchar* type = dbusmenu_menuitem_property_get(*it_l, DBUSMENU_MENUITEM_PROP_TYPE);
1108
 
      if (type == NULL)//(g_strcmp0 (type, DBUSMENU_MENUITEM_PROP_LABEL) == 0)
 
985
      const gchar* type = dbusmenu_menuitem_property_get(menu_item, DBUSMENU_MENUITEM_PROP_TYPE);
 
986
      if (type == nullptr)//(g_strcmp0 (type, DBUSMENU_MENUITEM_PROP_LABEL) == 0)
1109
987
      {
1110
 
        std::string label_menu = dbusmenu_menuitem_property_get(*it_l, DBUSMENU_MENUITEM_PROP_LABEL);
1111
 
        if (label_menu.compare(label_default) == 0)
 
988
        std::string label_menu(dbusmenu_menuitem_property_get(menu_item, DBUSMENU_MENUITEM_PROP_LABEL));
 
989
        if (label_menu == label_default)
1112
990
        {
1113
991
          exists = true;
1114
992
          break;
1117
995
    }
1118
996
 
1119
997
    if (!exists)
1120
 
      result.push_back((*it_m).second);
 
998
      result.push_back(it_m->second);
1121
999
  }
1122
1000
 
1123
1001
  return result;
1124
1002
}
1125
1003
 
1126
 
 
1127
 
void BamfLauncherIcon::UpdateIconGeometries(nux::Point3 center)
 
1004
void BamfLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> center)
1128
1005
{
1129
1006
  GList* children, *l;
1130
 
  BamfView* view;
1131
1007
  nux::Geometry geo;
1132
1008
 
1133
 
  if (_launcher->Hidden() && !_launcher->ShowOnEdge())
1134
 
  {
1135
 
    geo.x = 0;
1136
 
    geo.y = 0;
1137
 
  }
1138
 
  else
1139
 
  {
1140
 
    geo.x = center.x - 24;
1141
 
    geo.y = center.y - 24;
1142
 
  }
1143
1009
  geo.width = 48;
1144
1010
  geo.height = 48;
1145
1011
 
1146
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
1012
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
1147
1013
 
1148
1014
  for (l = children; l; l = l->next)
1149
1015
  {
1150
 
    view = static_cast <BamfView*> (l->data);
1151
 
 
1152
 
    if (BAMF_IS_WINDOW(view))
1153
 
    {
1154
 
      guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
1155
 
      WindowManager::Default()->SetWindowIconGeometry((Window)xid, geo);
1156
 
    }
 
1016
    if (!BAMF_IS_WINDOW(l->data))
 
1017
      continue;
 
1018
 
 
1019
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
1020
    int monitor = bamf_window_get_monitor(static_cast<BamfWindow*>(l->data));
 
1021
    monitor = std::max<int>(0, std::min<int>(center.size() - 1, monitor));
 
1022
 
 
1023
    geo.x = center[monitor].x - 24;
 
1024
    geo.y = center[monitor].y - 24;
 
1025
    WindowManager::Default()->SetWindowIconGeometry(xid, geo);
1157
1026
  }
1158
1027
 
1159
1028
  g_list_free(children);
1160
1029
}
1161
1030
 
1162
 
void BamfLauncherIcon::OnCenterStabilized(nux::Point3 center)
 
1031
void BamfLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> center)
1163
1032
{
1164
1033
  UpdateIconGeometries(center);
1165
1034
}
1166
1035
 
1167
1036
const gchar* BamfLauncherIcon::GetRemoteUri()
1168
1037
{
1169
 
  if (!_remote_uri)
 
1038
  if (_remote_uri.empty())
1170
1039
  {
1171
 
    const gchar* desktop_file = DesktopFile();
1172
 
    gchar* basename =  g_path_get_basename(desktop_file);
1173
 
 
1174
 
    _remote_uri = g_strdup_printf("application://%s", basename);
1175
 
 
1176
 
    g_free(basename);
 
1040
    const std::string prefix = "application://";
 
1041
    glib::String basename(g_path_get_basename(DesktopFile().c_str()));
 
1042
 
 
1043
    if (!basename.Str().empty())
 
1044
    {
 
1045
      _remote_uri = prefix + basename.Str();
 
1046
    }
1177
1047
  }
1178
1048
 
1179
 
  return _remote_uri;
 
1049
  return _remote_uri.c_str();
1180
1050
}
1181
1051
 
1182
1052
std::set<std::string> BamfLauncherIcon::ValidateUrisForLaunch(unity::DndData& uris)
1183
1053
{
1184
1054
  std::set<std::string> result;
1185
 
  gboolean is_home_launcher = g_str_has_suffix(DesktopFile(), "nautilus-home.desktop");
 
1055
  gboolean is_home_launcher = g_str_has_suffix(DesktopFile().c_str(), "nautilus-home.desktop");
1186
1056
 
1187
1057
  if (is_home_launcher)
1188
1058
  {
1192
1062
  }
1193
1063
 
1194
1064
  for (auto i : uris.Types())
 
1065
  {
1195
1066
    for (auto j : GetSupportedTypes())
 
1067
    {
1196
1068
      if (g_content_type_is_a(i.c_str(), j.c_str()))
1197
1069
      {
1198
1070
        for (auto k : uris.UrisByType(i))
1199
1071
          result.insert(k);
1200
 
          
 
1072
 
1201
1073
        break;
1202
1074
      }
1203
 
    
 
1075
    }
 
1076
  }
 
1077
 
1204
1078
  return result;
1205
1079
}
1206
1080
 
1207
 
gboolean BamfLauncherIcon::OnDndHoveredTimeout(gpointer data)
 
1081
void BamfLauncherIcon::OnDndHovered()
1208
1082
{
1209
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
1210
 
  
1211
1083
  // for now, let's not do this, it turns out to be quite buggy
1212
 
  //if (self->_dnd_hovered && bamf_view_is_running(BAMF_VIEW(self->m_App)))
1213
 
  //  self->Spread(CompAction::StateInitEdgeDnd, true);
1214
 
 
1215
 
  self->_dnd_hover_timer = 0;
1216
 
  return false;
 
1084
  //if (_dnd_hovered && IsRunning())
 
1085
  //  Spread(CompAction::StateInitEdgeDnd, true);
1217
1086
}
1218
1087
 
1219
1088
void BamfLauncherIcon::OnDndEnter()
1220
1089
{
1221
1090
  _dnd_hovered = true;
1222
 
  _dnd_hover_timer = g_timeout_add(1000, &BamfLauncherIcon::OnDndHoveredTimeout, this);
 
1091
  _dnd_hover_timer = g_timeout_add(1000, [] (gpointer data) -> gboolean {
 
1092
    BamfLauncherIcon* self = static_cast<BamfLauncherIcon*>(data);
 
1093
    self->OnDndHovered();
 
1094
    self->_dnd_hover_timer = 0;
 
1095
    return false;
 
1096
  }, this);
1223
1097
}
1224
1098
 
1225
1099
void BamfLauncherIcon::OnDndLeave()
1236
1110
  return ValidateUrisForLaunch(dnd_data).empty() ? nux::DNDACTION_NONE : nux::DNDACTION_COPY;
1237
1111
}
1238
1112
 
1239
 
void  BamfLauncherIcon::OnAcceptDrop(unity::DndData& dnd_data)
 
1113
void BamfLauncherIcon::OnAcceptDrop(unity::DndData& dnd_data)
1240
1114
{
1241
1115
  OpenInstanceWithUris(ValidateUrisForLaunch(dnd_data));
1242
1116
}
1243
1117
 
1244
 
void BamfLauncherIcon::OnDesktopFileChanged(GFileMonitor*        monitor,
1245
 
                                            GFile*               file,
1246
 
                                            GFile*               other_file,
1247
 
                                            GFileMonitorEvent    event_type,
1248
 
                                            gpointer             data)
 
1118
bool BamfLauncherIcon::ShowInSwitcher(bool current)
1249
1119
{
1250
 
  BamfLauncherIcon* self = static_cast<BamfLauncherIcon*>(data);
1251
 
  switch (event_type)
 
1120
  bool result = false;
 
1121
 
 
1122
  if (IsRunning() && IsVisible())
1252
1123
  {
1253
 
    case G_FILE_MONITOR_EVENT_DELETED:
1254
 
      self->UnStick();
1255
 
      break;
1256
 
    case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
1257
 
      self->UpdateDesktopQuickList();
1258
 
      break;
1259
 
    default:
1260
 
      break;
 
1124
    // If current is true, we only want to show the current workspace.
 
1125
    if (!current)
 
1126
    {
 
1127
      result = true;
 
1128
    }
 
1129
    else
 
1130
    {
 
1131
      for (int i = 0; i < max_num_monitors; i++)
 
1132
      {
 
1133
        if (WindowVisibleOnMonitor(i))
 
1134
        {
 
1135
          result = true;
 
1136
          break;
 
1137
        }
 
1138
      }
 
1139
    }
1261
1140
  }
1262
 
}
1263
 
 
1264
 
bool
1265
 
BamfLauncherIcon::ShowInSwitcher()
1266
 
{
1267
 
  return GetQuirk(QUIRK_RUNNING) && GetQuirk(QUIRK_VISIBLE);
1268
 
}
1269
 
 
1270
 
unsigned long long
1271
 
BamfLauncherIcon::SwitcherPriority()
 
1141
 
 
1142
  return result;
 
1143
}
 
1144
 
 
1145
unsigned long long BamfLauncherIcon::SwitcherPriority()
1272
1146
{
1273
1147
  GList* children, *l;
1274
 
  BamfView* view;
1275
1148
  unsigned long long result = 0;
1276
1149
 
1277
 
  children = bamf_view_get_children(BAMF_VIEW(m_App));
 
1150
  children = bamf_view_get_children(BAMF_VIEW(_bamf_app.RawPtr()));
1278
1151
 
1279
1152
  /* get the list of windows */
1280
1153
  for (l = children; l; l = l->next)
1281
1154
  {
1282
 
    view = static_cast <BamfView*> (l->data);
 
1155
    if (!BAMF_IS_WINDOW(l->data))
 
1156
      continue;
1283
1157
 
1284
 
    if (BAMF_IS_WINDOW(view))
1285
 
    {
1286
 
      guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
1287
 
      result = std::max(result, WindowManager::Default()->GetWindowActiveNumber (xid));
1288
 
    }
 
1158
    Window xid = bamf_window_get_xid(static_cast<BamfWindow*>(l->data));
 
1159
    result = std::max(result, WindowManager::Default()->GetWindowActiveNumber(xid));
1289
1160
  }
1290
1161
 
1291
1162
  g_list_free(children);
1292
1163
  return result;
1293
1164
}
1294
1165
 
1295
 
const std::set<std::string>&
1296
 
BamfLauncherIcon::GetSupportedTypes()
 
1166
const std::set<std::string>& BamfLauncherIcon::GetSupportedTypes()
1297
1167
{
1298
1168
  if (!_supported_types_filled)
1299
 
    FillSupportedTypes(this);
1300
 
    
 
1169
    FillSupportedTypes();
 
1170
 
1301
1171
  return _supported_types;
1302
1172
}
1303
1173
 
1304
 
gboolean
1305
 
BamfLauncherIcon::FillSupportedTypes(gpointer data)
 
1174
void BamfLauncherIcon::FillSupportedTypes()
1306
1175
{
1307
 
  BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data);
1308
 
  
1309
 
  if (self->_fill_supported_types_id)
 
1176
  if (_fill_supported_types_id)
1310
1177
  {
1311
 
    g_source_remove(self->_fill_supported_types_id);
1312
 
    self->_fill_supported_types_id = 0;
 
1178
    g_source_remove(_fill_supported_types_id);
 
1179
    _fill_supported_types_id = 0;
1313
1180
  }
1314
 
  
1315
 
  if (!self->_supported_types_filled)
 
1181
 
 
1182
  if (!_supported_types_filled)
1316
1183
  {
1317
 
    self->_supported_types_filled = true;
1318
 
    
1319
 
    self->_supported_types.clear();
1320
 
    
1321
 
    const char* desktop_file = self->DesktopFile();
1322
 
 
1323
 
    if (!desktop_file || strlen(desktop_file) <= 1)
1324
 
      return false;
1325
 
      
 
1184
    _supported_types_filled = true;
 
1185
    _supported_types.clear();
 
1186
 
 
1187
    std::string const& desktop_file = DesktopFile();
 
1188
 
 
1189
    if (desktop_file.empty())
 
1190
      return;
 
1191
 
1326
1192
    GKeyFile* key_file = g_key_file_new();
1327
 
    unity::glib::Error error;
 
1193
    glib::Error error;
1328
1194
 
1329
 
    g_key_file_load_from_file(key_file, desktop_file, (GKeyFileFlags) 0, &error);
 
1195
    g_key_file_load_from_file(key_file, desktop_file.c_str(), (GKeyFileFlags) 0, &error);
1330
1196
 
1331
1197
    if (error)
1332
1198
    {
1333
1199
      g_key_file_free(key_file);
1334
 
      return false;
 
1200
      return;
1335
1201
    }
1336
 
    
1337
 
    char** mimes = g_key_file_get_string_list(key_file, "Desktop Entry", "MimeType", NULL, NULL);
 
1202
 
 
1203
    char** mimes = g_key_file_get_string_list(key_file, "Desktop Entry", "MimeType", nullptr, nullptr);
1338
1204
    if (!mimes)
1339
1205
    {
1340
1206
      g_key_file_free(key_file);
1341
 
      return false;
 
1207
      return;
1342
1208
    }
1343
 
    
1344
 
    for (int i=0; mimes[i]; i++)
 
1209
 
 
1210
    for (int i = 0; mimes[i]; i++)
1345
1211
    {
1346
1212
      unity::glib::String super_type(g_content_type_from_mime_type(mimes[i]));
1347
 
      self->_supported_types.insert(super_type.Str());
 
1213
      _supported_types.insert(super_type.Str());
1348
1214
    }
1349
 
    
 
1215
 
1350
1216
    g_key_file_free(key_file);
1351
1217
    g_strfreev(mimes);
1352
1218
  }
 
1219
}
1353
1220
 
1354
 
  return false;
 
1221
std::string BamfLauncherIcon::GetName() const
 
1222
{
 
1223
  return "BamfLauncherIcon";
1355
1224
}
1356
1225
 
1357
1226
} // namespace launcher