~jamespharaoh/ubuntu/oneiric/unity/fix-for-880672

« back to all changes in this revision

Viewing changes to .pc/debian-changes-4.8.2-0ubuntu3/plugins/unityshell/src/SwitcherController.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-08-19 18:53:28 UTC
  • Revision ID: james.westby@ubuntu.com-20110819185328-qaxk9eepjaghewu9
Tags: 4.8.2-0ubuntu4
Backport another trunk commit to fix an alt-tab segfault

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2011 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: Jason Smith <jason.smith@canonical.com>
17
 
 */
18
 
 
19
 
#include <math.h>
20
 
 
21
 
#include <Nux/Nux.h>
22
 
#include <Nux/HLayout.h>
23
 
 
24
 
#include "UBusMessages.h"
25
 
#include "ubus-server.h"
26
 
 
27
 
#include "SwitcherController.h"
28
 
 
29
 
namespace unity
30
 
{
31
 
namespace switcher
32
 
{
33
 
 
34
 
SwitcherController::SwitcherController()
35
 
  :  view_(0)
36
 
  ,  view_window_(0)
37
 
  ,  visible_(false)
38
 
  ,  show_timer_(0)
39
 
  ,  detail_timer_(0)
40
 
{
41
 
  timeout_length = 150;
42
 
  detail_on_timeout = false;
43
 
  detail_timeout_length = 1500;
44
 
 
45
 
  UBusServer *ubus = ubus_server_get_default();
46
 
  ubus_server_register_interest(ubus, UBUS_BACKGROUND_COLOR_CHANGED,
47
 
                                (UBusCallback)&SwitcherController::OnBackgroundUpdate,
48
 
                                this);
49
 
}
50
 
 
51
 
SwitcherController::~SwitcherController()
52
 
{
53
 
}
54
 
 
55
 
void SwitcherController::OnBackgroundUpdate (GVariant *data, SwitcherController *self)
56
 
{
57
 
  gdouble red, green, blue, alpha;
58
 
  g_variant_get(data, "(dddd)", &red, &green, &blue, &alpha);
59
 
  self->bg_color_ = nux::Color (red, green, blue, alpha);
60
 
 
61
 
  if (self->view_)
62
 
    self->view_->background_color = self->bg_color_;
63
 
}
64
 
 
65
 
void SwitcherController::Show(SwitcherController::ShowMode show, SwitcherController::SortMode sort, bool reverse, std::vector<AbstractLauncherIcon*> results)
66
 
{
67
 
  if (sort == FOCUS_ORDER)
68
 
    std::sort(results.begin(), results.end(), CompareSwitcherItemsPriority);
69
 
 
70
 
  model_ = SwitcherModel::Ptr(new SwitcherModel(results));
71
 
  model_->selection_changed.connect (sigc::mem_fun(this, &SwitcherController::OnModelSelectionChanged));
72
 
  
73
 
  SelectFirstItem();
74
 
 
75
 
  visible_ = true;
76
 
 
77
 
  if (timeout_length > 0)
78
 
  {
79
 
    show_timer_ = g_timeout_add(timeout_length, &SwitcherController::OnShowTimer, this);
80
 
  }
81
 
  else
82
 
  {
83
 
    ConstructView ();
84
 
  }
85
 
 
86
 
  if (detail_on_timeout)
87
 
  {
88
 
    detail_timer_ = g_timeout_add(detail_timeout_length, &SwitcherController::OnDetailTimer, this);
89
 
  }
90
 
}
91
 
 
92
 
gboolean SwitcherController::OnShowTimer(gpointer data)
93
 
{
94
 
  SwitcherController* self = static_cast<SwitcherController*>(data);
95
 
 
96
 
  if (self->visible_)
97
 
    self->ConstructView();
98
 
 
99
 
  self->show_timer_ = 0;
100
 
  return FALSE;
101
 
}
102
 
 
103
 
gboolean SwitcherController::OnDetailTimer(gpointer data)
104
 
{
105
 
  SwitcherController* self = static_cast<SwitcherController*>(data);
106
 
 
107
 
  if (!self->visible_ || self->model_->detail_selection)
108
 
    return FALSE;
109
 
  
110
 
  self->SetDetail(true);
111
 
  self->detail_mode_ = TAB_NEXT_WINDOW;
112
 
  self->detail_timer_ = 0;
113
 
  return FALSE;
114
 
}
115
 
 
116
 
void SwitcherController::OnModelSelectionChanged(AbstractLauncherIcon *icon)
117
 
{
118
 
  if (detail_on_timeout)
119
 
  {
120
 
    if (detail_timer_)
121
 
      g_source_remove(detail_timer_);
122
 
    
123
 
    detail_timer_ = g_timeout_add(detail_timeout_length, &SwitcherController::OnDetailTimer, this);
124
 
  }
125
 
}
126
 
 
127
 
void SwitcherController::ConstructView()
128
 
{
129
 
  nux::HLayout* layout;
130
 
 
131
 
  layout = new nux::HLayout();
132
 
 
133
 
  view_ = new SwitcherView();
134
 
  view_->SetModel(model_);
135
 
  view_->background_color = bg_color_;
136
 
 
137
 
  layout->AddView(view_, 1);
138
 
  layout->SetVerticalExternalMargin(0);
139
 
  layout->SetHorizontalExternalMargin(0);
140
 
 
141
 
  view_window_ = new nux::BaseWindow("Switcher");
142
 
  view_window_->SinkReference();
143
 
  view_window_->SetLayout(layout);
144
 
  view_window_->SetBackgroundColor(nux::Color(0x00000000));
145
 
  view_window_->SetGeometry(workarea_);
146
 
 
147
 
  view_window_->ShowWindow(true);
148
 
}
149
 
 
150
 
void SwitcherController::SetWorkspace(nux::Geometry geo)
151
 
{
152
 
  workarea_ = geo;
153
 
}
154
 
 
155
 
void SwitcherController::Hide(bool accept_state)
156
 
{
157
 
  if (!visible_)
158
 
    return;
159
 
 
160
 
  if (accept_state)
161
 
  {
162
 
    AbstractLauncherIcon* selection = model_->Selection();
163
 
    if (selection)
164
 
    {
165
 
      if (model_->detail_selection)
166
 
      {
167
 
        selection->Activate(ActionArg(ActionArg::SWITCHER, 0, model_->DetailSelectionWindow ()));
168
 
      }
169
 
      else
170
 
      {
171
 
        if (selection->GetQuirk (AbstractLauncherIcon::QUIRK_ACTIVE))
172
 
        {
173
 
          selection->Activate(ActionArg (ActionArg::SWITCHER, 0, model_->DetailXids()[0]));
174
 
        } 
175
 
        else
176
 
        {
177
 
          selection->Activate(ActionArg(ActionArg::SWITCHER, 0));
178
 
        }     
179
 
      }
180
 
    }
181
 
  }
182
 
 
183
 
  model_.reset();
184
 
  visible_ = false;
185
 
 
186
 
  if (view_window_)
187
 
  {
188
 
    view_window_->ShowWindow(false);
189
 
    view_window_->UnReference();
190
 
    view_window_ = 0;
191
 
  }
192
 
 
193
 
  if (show_timer_)
194
 
    g_source_remove(show_timer_);
195
 
  show_timer_ = 0;
196
 
 
197
 
  view_ = 0;
198
 
}
199
 
 
200
 
bool SwitcherController::Visible()
201
 
{
202
 
  return visible_;
203
 
}
204
 
 
205
 
int SwitcherController::WindowsRelatedToSelection()
206
 
{
207
 
  if (model_->Selection())
208
 
    return model_->Selection()->RelatedWindows ();
209
 
  return 0;
210
 
}
211
 
 
212
 
void SwitcherController::Next()
213
 
{
214
 
  if (!model_)
215
 
    return;
216
 
 
217
 
  if (model_->detail_selection)
218
 
  {
219
 
    switch (detail_mode_)
220
 
    {
221
 
      case TAB_NEXT_WINDOW:
222
 
        if (model_->detail_selection_index < WindowsRelatedToSelection() - 1)
223
 
          model_->NextDetail();
224
 
        else
225
 
          model_->Next();
226
 
        break;
227
 
      case TAB_NEXT_TILE:
228
 
        model_->Next();
229
 
        break;
230
 
      case TAB_NEXT_WINDOW_LOOP:
231
 
        model_->NextDetail(); //looping automatic
232
 
        break;
233
 
    }
234
 
  }
235
 
  else
236
 
  {
237
 
    model_->Next();
238
 
  }
239
 
}
240
 
 
241
 
void SwitcherController::Prev()
242
 
{
243
 
  if (!model_)
244
 
    return;
245
 
 
246
 
  if (model_->detail_selection)
247
 
  {
248
 
    switch (detail_mode_)
249
 
    {
250
 
      case TAB_NEXT_WINDOW:
251
 
        if (model_->detail_selection_index > 0)
252
 
          model_->PrevDetail();
253
 
        else
254
 
          model_->Prev();
255
 
        break;
256
 
      case TAB_NEXT_TILE:
257
 
        model_->Prev();
258
 
        break;
259
 
      case TAB_NEXT_WINDOW_LOOP:
260
 
        model_->PrevDetail(); //looping automatic
261
 
        break;
262
 
    }
263
 
  }
264
 
  else
265
 
  {
266
 
    model_->Prev();
267
 
  }
268
 
}
269
 
 
270
 
SwitcherView * SwitcherController::GetView()
271
 
{
272
 
  return view_;
273
 
}
274
 
 
275
 
void SwitcherController::SetDetail(bool value)
276
 
{
277
 
  if (value && model_->Selection()->RelatedWindows() > 0)
278
 
  {
279
 
    model_->detail_selection = true;
280
 
    detail_mode_ = TAB_NEXT_WINDOW_LOOP;
281
 
  }
282
 
  else
283
 
  {
284
 
    model_->detail_selection = false;
285
 
  }
286
 
}
287
 
 
288
 
void SwitcherController::NextDetail()
289
 
{
290
 
  if (!model_->detail_selection)
291
 
  {
292
 
    SetDetail(true);
293
 
    detail_mode_ = TAB_NEXT_TILE;
294
 
  }
295
 
  else
296
 
  {
297
 
    model_->NextDetail();
298
 
  }
299
 
}
300
 
 
301
 
void SwitcherController::PrevDetail()
302
 
{
303
 
  model_->PrevDetail();
304
 
}
305
 
 
306
 
LayoutWindowList SwitcherController::ExternalRenderTargets ()
307
 
{
308
 
  if (!view_)
309
 
  {
310
 
    LayoutWindowList result;
311
 
    return result;
312
 
  }
313
 
  return view_->ExternalTargets ();
314
 
}
315
 
 
316
 
bool SwitcherController::CompareSwitcherItemsPriority(AbstractLauncherIcon* first, AbstractLauncherIcon* second)
317
 
{
318
 
  if (first->Type() == second->Type())
319
 
    return first->SwitcherPriority() > second->SwitcherPriority();
320
 
  return first->Type() < second->Type();
321
 
}
322
 
 
323
 
void SwitcherController::SelectFirstItem()
324
 
{
325
 
  if (!model_)
326
 
    return;
327
 
 
328
 
  AbstractLauncherIcon *first  = model_->at (1);
329
 
  AbstractLauncherIcon *second = model_->at (2);
330
 
 
331
 
  if (!first)
332
 
  {
333
 
    model_->Select (0);
334
 
    return;
335
 
  }
336
 
  else if (!second)
337
 
  {
338
 
    model_->Select (1);
339
 
    return;
340
 
  }
341
 
 
342
 
  unsigned int first_highest = 0;
343
 
  unsigned int first_second = 0; // first icons second highest active
344
 
  unsigned int second_first = 0; // second icons first highest active
345
 
 
346
 
  for (guint32 xid : first->RelatedXids ())
347
 
  {
348
 
    unsigned int num = WindowManager::Default ()->GetWindowActiveNumber (xid);
349
 
 
350
 
    if (num > first_highest)
351
 
    {
352
 
      first_second = first_highest;
353
 
      first_highest = num;
354
 
    }
355
 
    else if (num > first_second)
356
 
    {
357
 
      first_second = num;
358
 
    }
359
 
  }
360
 
 
361
 
  for (guint32 xid : second->RelatedXids ())
362
 
  {
363
 
    second_first = MAX (WindowManager::Default ()->GetWindowActiveNumber (xid), second_first);
364
 
  }
365
 
 
366
 
  if (first_second > second_first)
367
 
    model_->Select (first);
368
 
  else
369
 
    model_->Select (second);
370
 
}
371
 
 
372
 
}
373
 
}