~didrocks/unity/launcher-bug-fix-fest

« back to all changes in this revision

Viewing changes to src/IndicatorObjectFactoryRemote.cpp

Import the work done so far with Compiz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Canonical Ltd
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
 
17
 */
 
18
 
 
19
#include "IndicatorObjectFactoryRemote.h"
 
20
 
 
21
#include "IndicatorObjectProxyRemote.h"
 
22
#include "IndicatorObjectEntryProxyRemote.h"
 
23
#include "IndicatorObjectEntryProxy.h"
 
24
 
 
25
#define S_NAME  "com.canonical.Unity.Panel.Service"
 
26
#define S_PATH  "/com/canonical/Unity/Panel/Service"
 
27
#define S_IFACE "com.canonical.Unity.Panel.Service"
 
28
#define D_NAME  "com.canonical.Unity.Panel.Service.Indicators"
 
29
 
 
30
// Enums
 
31
 
 
32
enum
 
33
{
 
34
  COL_NAME = 0,
 
35
  COL_MODEL_NAME,
 
36
  COL_EXPAND
 
37
};
 
38
 
 
39
// Forwards
 
40
static void on_proxy_ready_cb (GObject      *source,
 
41
                               GAsyncResult *res,
 
42
                               gpointer      data);
 
43
 
 
44
static void on_row_added   (DeeModel                     *model,
 
45
                            DeeModelIter                 *iter,
 
46
                            IndicatorObjectFactoryRemote *remote);
 
47
 
 
48
static void on_row_changed (DeeModel                     *model,
 
49
                            DeeModelIter                 *iter,
 
50
                            IndicatorObjectFactoryRemote *remote);
 
51
 
 
52
static void on_row_removed (DeeModel                     *model,
 
53
                            DeeModelIter                 *iter,
 
54
                            IndicatorObjectFactoryRemote *remote);
 
55
 
 
56
static void on_proxy_signal_received (GDBusProxy *proxy,
 
57
                                      gchar      *sender_name,
 
58
                                      gchar      *signal_name,
 
59
                                      GVariant   *parameters,
 
60
                                      IndicatorObjectFactoryRemote *remote);
 
61
 
 
62
// Public Methods
 
63
IndicatorObjectFactoryRemote::IndicatorObjectFactoryRemote ()
 
64
{
 
65
  // We want to grab the Panel Service object. This is async, which is fine
 
66
  g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
 
67
                            G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
 
68
                            NULL,
 
69
                            S_NAME,
 
70
                            S_PATH,
 
71
                            S_IFACE,
 
72
                            NULL,
 
73
                            on_proxy_ready_cb,
 
74
                            this);
 
75
 
 
76
  // Connect to the main DeeSharedModel, which gives us info about the
 
77
  // indicators that the service has
 
78
  _model = dee_shared_model_new_with_name (D_NAME);
 
79
  g_signal_connect (_model, "row-added",
 
80
                    G_CALLBACK (on_row_added), this);
 
81
  g_signal_connect (_model, "row-changed",
 
82
                    G_CALLBACK (on_row_changed), this);
 
83
  g_signal_connect (_model, "row-removed",
 
84
                    G_CALLBACK (on_row_removed), this);
 
85
 
 
86
  dee_shared_model_connect (DEE_SHARED_MODEL (_model));
 
87
}
 
88
 
 
89
IndicatorObjectFactoryRemote::~IndicatorObjectFactoryRemote ()
 
90
{
 
91
  if (G_IS_OBJECT (_proxy))
 
92
    g_object_unref (_proxy);
 
93
  _proxy = NULL;
 
94
 
 
95
  if (DEE_IS_SHARED_MODEL (_model))
 
96
    g_object_unref (_model);
 
97
  _model = NULL;
 
98
 
 
99
  std::vector<IndicatorObjectProxy*>::iterator it;
 
100
  
 
101
  for (it = _indicators.begin(); it != _indicators.end(); it++)
 
102
  {
 
103
    IndicatorObjectProxyRemote *remote = static_cast<IndicatorObjectProxyRemote *> (*it);
 
104
    delete remote;
 
105
  }
 
106
 
 
107
  _indicators.erase (_indicators.begin (), _indicators.end ());
 
108
}
 
109
 
 
110
std::vector<IndicatorObjectProxy *>&
 
111
IndicatorObjectFactoryRemote::GetIndicatorObjects ()
 
112
{
 
113
  return _indicators;
 
114
}
 
115
 
 
116
void
 
117
IndicatorObjectFactoryRemote::ForceRefresh ()
 
118
{
 
119
}
 
120
 
 
121
void
 
122
IndicatorObjectFactoryRemote::OnRemoteProxyReady (GDBusProxy *proxy)
 
123
{
 
124
  _proxy = proxy;
 
125
 
 
126
  // Connect to interesting signals
 
127
  // FIXME: Add autorestarting bits here
 
128
 g_signal_connect (_proxy, "g-signal",
 
129
                   G_CALLBACK (on_proxy_signal_received), this);
 
130
}
 
131
 
 
132
void
 
133
IndicatorObjectFactoryRemote::OnShowMenuRequestReceived (const char *id, int x, int y, guint timestamp)
 
134
{
 
135
  // FIXME: Why doesn't this work if timestamp is valid?
 
136
  timestamp = 0;
 
137
 
 
138
  g_dbus_proxy_call (_proxy,
 
139
                     "ShowEntry",
 
140
                     g_variant_new ("(suii)",
 
141
                                    id,
 
142
                                    timestamp,
 
143
                                    x,
 
144
                                    y),
 
145
                     G_DBUS_CALL_FLAGS_NONE,
 
146
                     -1,
 
147
                     NULL,
 
148
                     NULL,
 
149
                     NULL);
 
150
}
 
151
 
 
152
void
 
153
IndicatorObjectFactoryRemote::OnRowAdded (DeeModelIter *iter)
 
154
{
 
155
  IndicatorObjectProxyRemote *remote;
 
156
  const gchar *name;
 
157
  const gchar *model_name;
 
158
 
 
159
  name = dee_model_get_string (_model, iter, COL_NAME);
 
160
  model_name = dee_model_get_string (_model, iter, COL_MODEL_NAME);
 
161
 
 
162
  remote = new IndicatorObjectProxyRemote (name, model_name);
 
163
  remote->OnShowMenuRequest.connect (sigc::mem_fun (this, &IndicatorObjectFactoryRemote::OnShowMenuRequestReceived));
 
164
 
 
165
  _indicators.push_back (remote);
 
166
 
 
167
  OnObjectAdded.emit (remote);
 
168
}
 
169
 
 
170
void
 
171
IndicatorObjectFactoryRemote::OnRowChanged (DeeModelIter *iter)
 
172
{
 
173
  printf ("HELLO %s\n", G_STRFUNC);
 
174
}
 
175
 
 
176
void
 
177
IndicatorObjectFactoryRemote::OnRowRemoved (DeeModelIter *iter)
 
178
{
 
179
  printf ("HELLO%s\n", G_STRFUNC);
 
180
}
 
181
 
 
182
// We need to unset the last active entry and set the new one as active
 
183
void
 
184
IndicatorObjectFactoryRemote::OnEntryActivated (const char *entry_id)
 
185
{
 
186
  std::vector<IndicatorObjectProxy*>::iterator it;
 
187
  
 
188
  for (it = _indicators.begin(); it != _indicators.end(); it++)
 
189
  {
 
190
    IndicatorObjectProxyRemote *object = static_cast<IndicatorObjectProxyRemote *> (*it);
 
191
    std::vector<IndicatorObjectEntryProxy*>::iterator it;
 
192
  
 
193
    for (it = object->GetEntries ().begin(); it != object->GetEntries ().end(); it++)
 
194
    {
 
195
      IndicatorObjectEntryProxyRemote *entry = static_cast<IndicatorObjectEntryProxyRemote *> (*it);
 
196
 
 
197
      entry->SetActive (g_strcmp0 (entry_id, entry->GetId ()) == 0);
 
198
    }
 
199
  } 
 
200
}
 
201
 
 
202
//
 
203
// C callbacks, they just link to class methods and aren't interesting
 
204
//
 
205
 
 
206
static bool
 
207
reconnect_to_service (gpointer data)
 
208
{
 
209
  g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
 
210
                            G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
 
211
                            NULL,
 
212
                            S_NAME,
 
213
                            S_PATH,
 
214
                            S_IFACE,
 
215
                            NULL,
 
216
                            on_proxy_ready_cb,
 
217
                            data);
 
218
 
 
219
  return false;
 
220
}
 
221
 
 
222
static void
 
223
on_proxy_ready_cb (GObject      *source,
 
224
                   GAsyncResult *res,
 
225
                   gpointer      data)
 
226
{
 
227
  IndicatorObjectFactoryRemote *remote = static_cast<IndicatorObjectFactoryRemote *> (data);
 
228
  GDBusProxy *proxy;
 
229
  GError     *error = NULL;
 
230
  static bool force_tried = false;
 
231
  char       *name_owner;
 
232
 
 
233
  proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
 
234
  name_owner = g_dbus_proxy_get_name_owner (proxy);
 
235
 
 
236
  if (G_IS_DBUS_PROXY (proxy) && name_owner)
 
237
  {
 
238
    remote->OnRemoteProxyReady (G_DBUS_PROXY (proxy));
 
239
    g_free (name_owner);
 
240
    return;
 
241
  }
 
242
  else
 
243
  {
 
244
    if (force_tried)
 
245
    {
 
246
      printf ("\nWARNING: Unable to connect to the unity-panel-service %s\n",
 
247
              error ? error->message : "Unknown");
 
248
      if (error)
 
249
        g_error_free (error);
 
250
    }
 
251
    else
 
252
    {
 
253
      force_tried = true;
 
254
      GError *error = NULL;
 
255
      
 
256
      // Let's attempt to run it from where we expect it to be
 
257
      char *cmd = g_strdup_printf ("%s/lib/unity/unity-panel-service", PREFIX);
 
258
      printf ("\nWARNING: Couldn't load panel from installed services, so trying to load panel from known location: %s\n", cmd);
 
259
 
 
260
      g_spawn_command_line_async (cmd, &error);
 
261
      if (error)
 
262
      {
 
263
        printf ("\nWARNING: Unable to launch remote service manually: %s\n", error->message);
 
264
        g_error_free (error);
 
265
        return;
 
266
      }
 
267
 
 
268
      // This is obviously hackish, but this part of the code is mostly hackish...
 
269
      g_timeout_add_seconds (2, (GSourceFunc)reconnect_to_service, remote);
 
270
      g_free (cmd);
 
271
    }
 
272
  }
 
273
 
 
274
  g_object_unref (proxy);
 
275
}
 
276
 
 
277
static void
 
278
on_row_added (DeeModel *model, DeeModelIter *iter, IndicatorObjectFactoryRemote *remote)
 
279
{
 
280
  remote->OnRowAdded (iter);
 
281
}
 
282
 
 
283
static void
 
284
on_row_changed (DeeModel *model, DeeModelIter *iter, IndicatorObjectFactoryRemote *remote)
 
285
{
 
286
  remote->OnRowChanged (iter);
 
287
}
 
288
 
 
289
static void
 
290
on_row_removed (DeeModel *model, DeeModelIter *iter, IndicatorObjectFactoryRemote *remote)
 
291
{
 
292
  remote->OnRowRemoved (iter);
 
293
}
 
294
 
 
295
static void
 
296
on_proxy_signal_received (GDBusProxy *proxy,
 
297
                          gchar      *sender_name,
 
298
                          gchar      *signal_name,
 
299
                          GVariant   *parameters,
 
300
                          IndicatorObjectFactoryRemote *remote)
 
301
{
 
302
  if (g_strcmp0 (signal_name, "EntryActivated") == 0)
 
303
  {
 
304
    remote->OnEntryActivated (g_variant_get_string (g_variant_get_child_value (parameters, 0), NULL));
 
305
  }
 
306
}