~mial/ubuntu/oneiric/unity/bug-791810

« back to all changes in this revision

Viewing changes to src/BamfLauncherIcon.cpp

Import the work done so far with Compiz

Show diffs side-by-side

added added

removed removed

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