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

« back to all changes in this revision

Viewing changes to .pc/debian-changes-4.8.2-0ubuntu4/plugins/unityshell/src/unityshell.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
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
 
2
/* Compiz unity plugin
 
3
 * unity.cpp
 
4
 *
 
5
 * Copyright (c) 2010-11 Canonical Ltd.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License
 
9
 * as published by the Free Software Foundation; either version 3
 
10
 * of the License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * Your own copyright notice would go above. You are free to choose whatever
 
18
 * licence you want, just take note that some compiz code is GPL and you will
 
19
 * not be able to re-use it if you want to use a different licence.
 
20
 */
 
21
 
 
22
#include <NuxCore/Logger.h>
 
23
#include <Nux/Nux.h>
 
24
#include <Nux/HLayout.h>
 
25
#include <Nux/BaseWindow.h>
 
26
#include <Nux/WindowCompositor.h>
 
27
 
 
28
#include "IconRenderer.h"
 
29
#include "Launcher.h"
 
30
#include "LauncherIcon.h"
 
31
#include "LauncherController.h"
 
32
#include "PlacesSettings.h"
 
33
#include "GeisAdapter.h"
 
34
#include "DevicesSettings.h"
 
35
#include "PluginAdapter.h"
 
36
#include "StartupNotifyService.h"
 
37
#include "Timer.h"
 
38
#include "unityshell.h"
 
39
#include "BackgroundEffectHelper.h"
 
40
 
 
41
#include <dbus/dbus.h>
 
42
#include <dbus/dbus-glib.h>
 
43
#include <glib/gi18n-lib.h>
 
44
#include <gtk/gtk.h>
 
45
#include <gdk/gdk.h>
 
46
#include <libnotify/notify.h>
 
47
 
 
48
#include <sstream>
 
49
 
 
50
#include <core/atoms.h>
 
51
 
 
52
#include "unitya11y.h"
 
53
 
 
54
#include "ubus-server.h"
 
55
#include "UBusMessages.h"
 
56
 
 
57
#include "config.h"
 
58
 
 
59
/* FIXME: once we get a better method to add the toplevel windows to
 
60
   the accessible root object, this include would not be required */
 
61
#include "unity-util-accessible.h"
 
62
 
 
63
using namespace unity::switcher;
 
64
 
 
65
/* Set up vtable symbols */
 
66
COMPIZ_PLUGIN_20090315(unityshell, UnityPluginVTable);
 
67
 
 
68
using ::unity::logger::Timer;
 
69
 
 
70
namespace
 
71
{
 
72
 
 
73
nux::logging::Logger logger("unity.shell");
 
74
 
 
75
UnityScreen* uScreen = 0;
 
76
 
 
77
void configure_logging();
 
78
void capture_g_log_calls(const gchar* log_domain,
 
79
                         GLogLevelFlags log_level,
 
80
                         const gchar* message,
 
81
                         gpointer user_data);
 
82
gboolean is_extension_supported(const gchar* extensions, const gchar* extension);
 
83
gfloat get_opengl_version_f32(const gchar* version_string);
 
84
 
 
85
}
 
86
 
 
87
UnityScreen::UnityScreen(CompScreen* screen)
 
88
  : BaseSwitchScreen (screen)
 
89
  , PluginClassHandler <UnityScreen, CompScreen> (screen)
 
90
  , screen(screen)
 
91
  , cScreen(CompositeScreen::get(screen))
 
92
  , gScreen(GLScreen::get(screen))
 
93
  , launcher(nullptr)
 
94
  , controller(nullptr)
 
95
  , panelController(nullptr)
 
96
  , switcherController(nullptr)
 
97
  , gestureEngine(nullptr)
 
98
  , wt(nullptr)
 
99
  , launcherWindow(nullptr)
 
100
  , panelWindow(nullptr)
 
101
  , debugger(nullptr)
 
102
  , needsRelayout(false)
 
103
  , relayoutSourceId(0)
 
104
  , _edge_trigger_handle(0)
 
105
  , _edge_pointerY(0)
 
106
  , newFocusedWindow(nullptr)
 
107
  , lastFocusedWindow(nullptr)
 
108
  , doShellRepaint(false)
 
109
  , allowWindowPaint(false)
 
110
  , damaged(false)
 
111
  , _key_nav_mode_requested(false)
 
112
  , _last_output(nullptr)
 
113
  , switcher_desktop_icon(nullptr)
 
114
  , mActiveFbo (0)
 
115
{
 
116
  Timer timer;
 
117
  configure_logging();
 
118
  LOG_DEBUG(logger) << __PRETTY_FUNCTION__;
 
119
  int (*old_handler)(Display*, XErrorEvent*);
 
120
  old_handler = XSetErrorHandler(NULL);
 
121
 
 
122
  notify_init("unityshell");
 
123
 
 
124
  g_thread_init(NULL);
 
125
  dbus_g_thread_init();
 
126
 
 
127
  unity_a11y_preset_environment();
 
128
 
 
129
  XSetErrorHandler(old_handler);
 
130
 
 
131
  /* Wrap compiz interfaces */
 
132
  ScreenInterface::setHandler(screen);
 
133
  CompositeScreenInterface::setHandler(cScreen);
 
134
  GLScreenInterface::setHandler(gScreen);
 
135
 
 
136
  PluginAdapter::Initialize(screen);
 
137
  WindowManager::SetDefault(PluginAdapter::Default());
 
138
 
 
139
  StartupNotifyService::Default()->SetSnDisplay(screen->snDisplay(), screen->screenNum());
 
140
 
 
141
  nux::NuxInitialize(0);
 
142
  wt = nux::CreateFromForeignWindow(cScreen->output(),
 
143
                                    glXGetCurrentContext(),
 
144
                                    &UnityScreen::initUnity,
 
145
                                    this);
 
146
 
 
147
  wt->RedrawRequested.connect(sigc::mem_fun(this, &UnityScreen::onRedrawRequested));
 
148
 
 
149
  unity_a11y_init(wt);
 
150
 
 
151
  /* i18n init */
 
152
  bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
 
153
  bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
 
154
 
 
155
  wt->Run(NULL);
 
156
  uScreen = this;
 
157
 
 
158
  debugger = new DebugDBusInterface(this);
 
159
 
 
160
  _edge_timeout = optionGetLauncherRevealEdgeTimeout ();
 
161
 
 
162
  if (GL::fbo)
 
163
  {
 
164
    foreach (CompOutput &o, screen->outputDevs ())
 
165
      uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO (&o));
 
166
    
 
167
    uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO (&(screen->fullscreenOutput ())));
 
168
  }
 
169
 
 
170
  optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
171
  optionSetBacklightModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
172
  optionSetLaunchAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
173
  optionSetUrgentAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
174
  optionSetPanelOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
175
  optionSetLauncherOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
176
  optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
177
  optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
178
  optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
179
  optionSetDevicesOptionNotify(boost::bind (&UnityScreen::optionChanged, this, _1, _2));
 
180
  optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
 
181
  optionSetShowLauncherTerminate(boost::bind(&UnityScreen::showLauncherKeyTerminate, this, _1, _2, _3));
 
182
  optionSetKeyboardFocusInitiate(boost::bind(&UnityScreen::setKeyboardFocusKeyInitiate, this, _1, _2, _3));
 
183
  //optionSetKeyboardFocusTerminate (boost::bind (&UnityScreen::setKeyboardFocusKeyTerminate, this, _1, _2, _3));
 
184
  optionSetExecuteCommandInitiate(boost::bind(&UnityScreen::executeCommand, this, _1, _2, _3));
 
185
  optionSetPanelFirstMenuInitiate(boost::bind(&UnityScreen::showPanelFirstMenuKeyInitiate, this, _1, _2, _3));
 
186
  optionSetPanelFirstMenuTerminate(boost::bind(&UnityScreen::showPanelFirstMenuKeyTerminate, this, _1, _2, _3));
 
187
  optionSetLauncherRevealEdgeInitiate(boost::bind(&UnityScreen::launcherRevealEdgeInitiate, this, _1, _2, _3));
 
188
  optionSetLauncherRevealEdgeTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
189
  optionSetAutomaximizeValueNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
190
  optionSetAltTabTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
191
  
 
192
  optionSetAltTabForwardInitiate(boost::bind(&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
 
193
  optionSetAltTabForwardTerminate(boost::bind(&UnityScreen::altTabForwardTerminate, this, _1, _2, _3));
 
194
  
 
195
  optionSetAltTabPrevInitiate(boost::bind(&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
 
196
  optionSetAltTabPrevTerminate(boost::bind(&UnityScreen::altTabPrevTerminate, this, _1, _2, _3));
 
197
  
 
198
  optionSetAltTabDetailStartInitiate(boost::bind(&UnityScreen::altTabDetailStartInitiate, this, _1, _2, _3));
 
199
  optionSetAltTabDetailStartTerminate(boost::bind(&UnityScreen::altTabDetailStartTerminate, this, _1, _2, _3));
 
200
 
 
201
  optionSetAltTabDetailStopInitiate(boost::bind(&UnityScreen::altTabDetailStopInitiate, this, _1, _2, _3));
 
202
  optionSetAltTabDetailStopTerminate(boost::bind(&UnityScreen::altTabDetailStopTerminate, this, _1, _2, _3));
 
203
 
 
204
  optionSetAltTabNextWindowInitiate(boost::bind(&UnityScreen::altTabNextWindowInitiate, this, _1, _2, _3));
 
205
  optionSetAltTabNextWindowTerminate(boost::bind(&UnityScreen::altTabNextWindowTerminate, this, _1, _2, _3));
 
206
 
 
207
  optionSetAltTabExitInitiate(boost::bind(&UnityScreen::altTabExitInitiate, this, _1, _2, _3));
 
208
  optionSetAltTabExitTerminate(boost::bind(&UnityScreen::altTabExitTerminate, this, _1, _2, _3));
 
209
  
 
210
 
 
211
  for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); i++)
 
212
    _ubus_handles[i] = 0;
 
213
 
 
214
  UBusServer* ubus = ubus_server_get_default();
 
215
  _ubus_handles[0] = ubus_server_register_interest(ubus,
 
216
                                                   UBUS_LAUNCHER_START_KEY_NAV,
 
217
                                                   (UBusCallback)&UnityScreen::OnLauncherStartKeyNav,
 
218
                                                   this);
 
219
 
 
220
  _ubus_handles[1] = ubus_server_register_interest(ubus,
 
221
                                                   UBUS_LAUNCHER_END_KEY_NAV,
 
222
                                                   (UBusCallback)&UnityScreen::OnLauncherEndKeyNav,
 
223
                                                   this);
 
224
 
 
225
  _ubus_handles[2] = ubus_server_register_interest(ubus,
 
226
                                                   UBUS_QUICKLIST_END_KEY_NAV,
 
227
                                                   (UBusCallback)&UnityScreen::OnQuicklistEndKeyNav,
 
228
                                                   this);
 
229
 
 
230
  g_timeout_add(0, &UnityScreen::initPluginActions, this);
 
231
 
 
232
  GeisAdapter::Default(screen)->Run();
 
233
  gestureEngine = new GestureEngine(screen);
 
234
 
 
235
  CompString name(PKGDATADIR"/panel-shadow.png");
 
236
  CompString pname("unityshell");
 
237
  CompSize size(1, 20);
 
238
  _shadow_texture = GLTexture::readImageToTexture(name, pname, size);
 
239
 
 
240
  ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_SHOWN, [&](GVariant* args) { dash_is_open_ = true; });
 
241
  ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_HIDDEN, [&](GVariant* args) { dash_is_open_ = false; });
 
242
 
 
243
  EnsureKeybindings();
 
244
 
 
245
  LOG_INFO(logger) << "UnityScreen constructed: " << timer.ElapsedSeconds() << "s";
 
246
}
 
247
 
 
248
UnityScreen::~UnityScreen()
 
249
{
 
250
  panelController->UnReference();
 
251
  delete controller;
 
252
  launcher->UnReference();
 
253
  launcherWindow->UnReference();
 
254
 
 
255
  notify_uninit();
 
256
 
 
257
  unity_a11y_finalize();
 
258
 
 
259
  UBusServer* ubus = ubus_server_get_default();
 
260
  for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); i++)
 
261
  {
 
262
    if (_ubus_handles[i] != 0)
 
263
      ubus_server_unregister_interest(ubus, _ubus_handles[i]);
 
264
  }
 
265
 
 
266
  if (relayoutSourceId != 0)
 
267
    g_source_remove(relayoutSourceId);
 
268
 
 
269
  // Deleting the windows thread calls XCloseDisplay, which calls XSync, which
 
270
  // sits waiting for a reply.
 
271
  // delete wt;
 
272
 
 
273
  ::unity::ui::IconRenderer::DestroyTextures();
 
274
}
 
275
 
 
276
void UnityScreen::EnsureKeybindings()
 
277
{
 
278
  for (auto action : _shortcut_actions)
 
279
    screen->removeAction(action.get());
 
280
 
 
281
  _shortcut_actions.clear ();
 
282
 
 
283
  for (auto icon : *(launcher->GetModel()))
 
284
  {
 
285
    guint64 shortcut = icon->GetShortcut();
 
286
    if (shortcut == 0)
 
287
      continue;
 
288
 
 
289
    CompActionPtr action(new CompAction());
 
290
 
 
291
    CompAction::KeyBinding binding;
 
292
    std::ostringstream sout;
 
293
    sout << "<Super>" << static_cast<char>(shortcut);
 
294
    binding.fromString(sout.str());
 
295
 
 
296
    action->setKey(binding);
 
297
 
 
298
    screen->addAction(action.get());
 
299
    _shortcut_actions.push_back(action);
 
300
  }
 
301
}
 
302
 
 
303
void UnityScreen::nuxPrologue()
 
304
{
 
305
  /* Vertex lighting isn't used in Unity, we disable that state as it could have
 
306
   * been leaked by another plugin. That should theoretically be switched off
 
307
   * right after PushAttrib since ENABLE_BIT is meant to restore the LIGHTING
 
308
   * bit, but we do that here in order to workaround a bug (?) in the NVIDIA
 
309
   * drivers (lp:703140). */
 
310
  glDisable(GL_LIGHTING);
 
311
 
 
312
  /* reset matrices */
 
313
  glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT |
 
314
               GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
 
315
 
 
316
  glMatrixMode(GL_PROJECTION);
 
317
  glPushMatrix();
 
318
 
 
319
  glMatrixMode(GL_MODELVIEW);
 
320
  glPushMatrix();
 
321
 
 
322
  glGetError();
 
323
}
 
324
 
 
325
void UnityScreen::nuxEpilogue()
 
326
{
 
327
  (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, mActiveFbo);
 
328
 
 
329
  glMatrixMode(GL_PROJECTION);
 
330
  glLoadIdentity();
 
331
  glMatrixMode(GL_MODELVIEW);
 
332
  glLoadIdentity();
 
333
  glDepthRange(0, 1);
 
334
  glViewport(-1, -1, 2, 2);
 
335
  glRasterPos2f(0, 0);
 
336
 
 
337
  gScreen->resetRasterPos();
 
338
 
 
339
  glMatrixMode(GL_PROJECTION);
 
340
  glPopMatrix();
 
341
  glMatrixMode(GL_MODELVIEW);
 
342
  glPopMatrix();
 
343
 
 
344
  glDrawBuffer(GL_BACK);
 
345
  glReadBuffer(GL_BACK);
 
346
 
 
347
  glPopAttrib();
 
348
 
 
349
  glDisable(GL_SCISSOR_TEST);
 
350
}
 
351
 
 
352
void UnityScreen::OnLauncherHiddenChanged()
 
353
{
 
354
  if (launcher->Hidden())
 
355
    screen->addAction(&optionGetLauncherRevealEdge());
 
356
  else
 
357
    screen->removeAction(&optionGetLauncherRevealEdge());
 
358
}
 
359
 
 
360
void UnityScreen::paintPanelShadow(const GLMatrix& matrix)
 
361
{
 
362
  if (relayoutSourceId > 0)
 
363
    return;
 
364
 
 
365
  if (PluginAdapter::Default()->IsExpoActive())
 
366
    return;
 
367
 
 
368
  nuxPrologue();
 
369
 
 
370
  CompOutput* output = _last_output;
 
371
  float vc[4];
 
372
  float h = 20.0f;
 
373
  float w = 1.0f;
 
374
  float panel_h = 24.0f;
 
375
 
 
376
  float x1 = output->x();
 
377
  float y1 = panel_h;
 
378
  float x2 = x1 + output->width();
 
379
  float y2 = y1 + h;
 
380
 
 
381
  vc[0] = x1;
 
382
  vc[1] = x2;
 
383
  vc[2] = y1;
 
384
  vc[3] = y2;
 
385
 
 
386
  if (!dash_is_open_)
 
387
  {
 
388
    foreach(GLTexture * tex, _shadow_texture)
 
389
    {
 
390
      glEnable(GL_BLEND);
 
391
      glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 
392
 
 
393
      GL::activeTexture(GL_TEXTURE0_ARB);
 
394
      tex->enable(GLTexture::Fast);
 
395
 
 
396
      glTexParameteri(tex->target(), GL_TEXTURE_WRAP_S, GL_REPEAT);
 
397
 
 
398
      glBegin(GL_QUADS);
 
399
      {
 
400
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), 0));
 
401
        glVertex2f(vc[0], vc[2]);
 
402
 
 
403
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), h));
 
404
        glVertex2f(vc[0], vc[3]);
 
405
 
 
406
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), h));
 
407
        glVertex2f(vc[1], vc[3]);
 
408
 
 
409
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), 0));
 
410
        glVertex2f(vc[1], vc[2]);
 
411
      }
 
412
      glEnd();
 
413
 
 
414
      tex->disable();
 
415
      glDisable(GL_BLEND);
 
416
    }
 
417
  }
 
418
  nuxEpilogue();
 
419
}
 
420
 
 
421
void
 
422
UnityWindow::updateIconPos (int   &wx,
 
423
                            int   &wy,
 
424
                            int   x,
 
425
                            int   y,
 
426
                            float width,
 
427
                            float height)
 
428
{
 
429
  wx = x + (last_bound.width - width) / 2;
 
430
  wy = y + (last_bound.height - height) / 2;
 
431
}
 
432
 
 
433
void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask)
 
434
{
 
435
  CompOutput *output = _last_output;
 
436
 
 
437
  mFbos[output]->unbind ();
 
438
 
 
439
  /* Draw the bit of the relevant framebuffer for each output */
 
440
  mFbos[output]->paint ();
 
441
 
 
442
  nuxPrologue();
 
443
  nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture = 
 
444
  nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(mFbos[output]->texture(), 
 
445
  output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
 
446
 
 
447
  nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
 
448
 
 
449
  nux::Geometry geo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
 
450
 
 
451
  wt->RenderInterfaceFromForeignCmd (&geo);
 
452
  nuxEpilogue();
 
453
 
 
454
if (switcherController->Visible ())
 
455
  {
 
456
    LayoutWindowList targets = switcherController->ExternalRenderTargets ();
 
457
 
 
458
    for (LayoutWindow::Ptr target : targets)
 
459
    {
 
460
      CompWindow* window = screen->findWindow(target->xid);
 
461
      UnityWindow *unity_window = UnityWindow::get (window);
 
462
 
 
463
      unity_window->paintThumbnail (target->result, target->alpha);
 
464
    }
 
465
  }
 
466
 
 
467
  doShellRepaint = false;
 
468
  damaged = false;
 
469
  BackgroundEffectHelper::updates_enabled = true;
 
470
}
 
471
 
 
472
void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha)
 
473
{
 
474
  GLMatrix matrix;
 
475
  matrix.toScreenSpace (UnityScreen::get (screen)->_last_output, -DEFAULT_Z_CAMERA);
 
476
 
 
477
  nux::Geometry geo = bounding;
 
478
  geo.x += 3;
 
479
  geo.width -= 6;
 
480
 
 
481
  geo.y += 3;
 
482
  geo.height -= 6;
 
483
 
 
484
  last_bound = geo;
 
485
 
 
486
  GLWindowPaintAttrib attrib = gWindow->lastPaintAttrib ();
 
487
  attrib.opacity = (GLushort) (alpha * G_MAXUSHORT);
 
488
 
 
489
  paintThumb (attrib,
 
490
              matrix,
 
491
              0,
 
492
              geo.x,
 
493
              geo.y,
 
494
              geo.width,
 
495
              geo.height,
 
496
              geo.width,
 
497
              geo.height);
 
498
}
 
499
 
 
500
/* called whenever we need to repaint parts of the screen */
 
501
bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
 
502
                                const GLMatrix& transform,
 
503
                                const CompRegion& region,
 
504
                                CompOutput* output,
 
505
                                unsigned int mask)
 
506
{
 
507
  bool ret;
 
508
 
 
509
  /* bind the framebuffer here */
 
510
  mFbos[output]->bind ();
 
511
 
 
512
  doShellRepaint = true;
 
513
  allowWindowPaint = true;
 
514
  _last_output = output;
 
515
 
 
516
  /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
 
517
  ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
 
518
 
 
519
  if (doShellRepaint)
 
520
    paintDisplay(region, transform, mask);
 
521
 
 
522
  return ret;
 
523
}
 
524
 
 
525
/* called whenever a plugin needs to paint the entire scene
 
526
 * transformed */
 
527
 
 
528
void UnityScreen::glPaintTransformedOutput(const GLScreenPaintAttrib& attrib,
 
529
                                           const GLMatrix& transform,
 
530
                                           const CompRegion& region,
 
531
                                           CompOutput* output,
 
532
                                           unsigned int mask)
 
533
{
 
534
  /* bind the framebuffer here */
 
535
  mFbos[output]->bind ();
 
536
  allowWindowPaint = false;
 
537
  /* urgh */
 
538
  gScreen->glPaintOutput(attrib, transform, region, output, mask);
 
539
}
 
540
 
 
541
void UnityScreen::preparePaint(int ms)
 
542
{
 
543
  if (BackgroundEffectHelper::blur_type == unity::BLUR_ACTIVE)
 
544
  {
 
545
    // this causes queue draws to be called, we obviously dont want to disable updates
 
546
    // because we are updating the blur, so ignore them.
 
547
    bool tmp = BackgroundEffectHelper::updates_enabled;
 
548
    BackgroundEffectHelper::QueueDrawOnOwners();
 
549
    BackgroundEffectHelper::updates_enabled = tmp;
 
550
  }
 
551
 
 
552
  cScreen->preparePaint(ms);
 
553
 
 
554
  if (damaged)
 
555
  {
 
556
    damaged = false;
 
557
    damageNuxRegions();
 
558
  }
 
559
 
 
560
}
 
561
 
 
562
/* Grab changed nux regions and add damage rects for them */
 
563
void UnityScreen::damageNuxRegions()
 
564
{
 
565
  if (damaged)
 
566
    return;
 
567
 
 
568
  std::vector<nux::Geometry> dirty = wt->GetDrawList();
 
569
  damaged = true;
 
570
 
 
571
  for (std::vector<nux::Geometry>::iterator it = dirty.begin(), end = dirty.end();
 
572
       it != end; ++it)
 
573
  {
 
574
    nux::Geometry const& geo = *it;
 
575
    cScreen->damageRegion(CompRegion(geo.x, geo.y, geo.width, geo.height));
 
576
  }
 
577
 
 
578
  nux::Geometry geo = wt->GetWindowCompositor().GetTooltipMainWindowGeometry();
 
579
  cScreen->damageRegion(CompRegion(geo.x, geo.y, geo.width, geo.height));
 
580
  cScreen->damageRegion(CompRegion(lastTooltipArea.x, lastTooltipArea.y,
 
581
                                   lastTooltipArea.width, lastTooltipArea.height));
 
582
 
 
583
  lastTooltipArea = geo;
 
584
 
 
585
  wt->ClearDrawList();
 
586
}
 
587
 
 
588
/* handle X Events */
 
589
void UnityScreen::handleEvent(XEvent* event)
 
590
{
 
591
  bool skip_other_plugins = false;
 
592
 
 
593
  switch (event->type)
 
594
  {
 
595
    case FocusIn:
 
596
    case FocusOut:
 
597
      if (event->xfocus.mode == NotifyGrab)
 
598
        PluginAdapter::Default()->OnScreenGrabbed();
 
599
      else if (event->xfocus.mode == NotifyUngrab)
 
600
        PluginAdapter::Default()->OnScreenUngrabbed();
 
601
      cScreen->damageScreen();  // evil hack
 
602
      if (_key_nav_mode_requested)
 
603
        launcher->startKeyNavMode();
 
604
      _key_nav_mode_requested = false;
 
605
      break;
 
606
    case KeyPress:
 
607
      KeySym key_sym;
 
608
      char key_string[2];
 
609
      int result;
 
610
      if ((result = XLookupString(&(event->xkey), key_string, 2, &key_sym, 0)) > 0)
 
611
      {
 
612
        key_string[result] = 0;
 
613
        skip_other_plugins = launcher->CheckSuperShortcutPressed(key_sym, event->xkey.keycode, event->xkey.state, key_string);
 
614
      }
 
615
      break;
 
616
  }
 
617
 
 
618
  // avoid further propagation (key conflict for instance)
 
619
  if (!skip_other_plugins)
 
620
    screen->handleEvent(event);
 
621
 
 
622
  if (!skip_other_plugins && screen->otherGrabExist("deco", "move", "switcher", "resize", NULL))
 
623
  {
 
624
    wt->ProcessForeignEvent(event, NULL);
 
625
  }
 
626
}
 
627
 
 
628
void UnityScreen::handleCompizEvent(const char* plugin,
 
629
                                    const char* event,
 
630
                                    CompOption::Vector& option)
 
631
{
 
632
  /*
 
633
   *  don't take into account window over launcher state during
 
634
   *  the ws switch as we can get false positives
 
635
   *  (like switching to an empty viewport while grabbing a fullscreen window)
 
636
   */
 
637
  if (strcmp(event, "start_viewport_switch") == 0)
 
638
    launcher->EnableCheckWindowOverLauncher(false);
 
639
  else if (strcmp(event, "end_viewport_switch") == 0)
 
640
  {
 
641
    // compute again the list of all window on the new viewport
 
642
    // to decide if we should or not hide the launcher
 
643
    launcher->EnableCheckWindowOverLauncher(true);
 
644
    launcher->CheckWindowOverLauncher();
 
645
  }
 
646
  screen->handleCompizEvent(plugin, event, option);
 
647
}
 
648
 
 
649
bool UnityScreen::showLauncherKeyInitiate(CompAction* action,
 
650
                                          CompAction::State state,
 
651
                                          CompOption::Vector& options)
 
652
{
 
653
  // to receive the Terminate event
 
654
  if (state & CompAction::StateInitKey)
 
655
    action->setState(action->state() | CompAction::StateTermKey);
 
656
 
 
657
  launcher->StartKeyShowLauncher();
 
658
  EnsureKeybindings ();
 
659
  return false;
 
660
}
 
661
 
 
662
bool UnityScreen::showLauncherKeyTerminate(CompAction* action,
 
663
                                           CompAction::State state,
 
664
                                           CompOption::Vector& options)
 
665
{
 
666
  launcher->EndKeyShowLauncher();
 
667
  return false;
 
668
}
 
669
 
 
670
bool UnityScreen::showPanelFirstMenuKeyInitiate(CompAction* action,
 
671
                                                CompAction::State state,
 
672
                                                CompOption::Vector& options)
 
673
{
 
674
  // to receive the Terminate event
 
675
  if (state & CompAction::StateInitKey)
 
676
    action->setState(action->state() | CompAction::StateTermKey);
 
677
 
 
678
  panelController->StartFirstMenuShow();
 
679
  return false;
 
680
}
 
681
 
 
682
bool UnityScreen::showPanelFirstMenuKeyTerminate(CompAction* action,
 
683
                                                 CompAction::State state,
 
684
                                                 CompOption::Vector& options)
 
685
{
 
686
  panelController->EndFirstMenuShow();
 
687
  return false;
 
688
}
 
689
 
 
690
gboolean UnityScreen::OnEdgeTriggerTimeout(gpointer data)
 
691
{
 
692
  UnityScreen* self = reinterpret_cast<UnityScreen*>(data);
 
693
 
 
694
  if (pointerX == 0)
 
695
  {
 
696
    if (abs(pointerY-self->_edge_pointerY) <= 5)
 
697
    {
 
698
      self->launcher->EdgeRevealTriggered();
 
699
    }
 
700
    else
 
701
    {
 
702
      /* We are still in the edge, but moving in Y, maybe we need another chance */
 
703
 
 
704
      if (abs(pointerY-self->_edge_pointerY) > 20)
 
705
      {
 
706
        /* We're quite far from the first hit spot, let's wait again */
 
707
        self->_edge_pointerY = pointerY;
 
708
        return true;
 
709
      }
 
710
      else
 
711
      {
 
712
        /* We're quite near to the first hit spot, so we can reduce our timeout */
 
713
        self->_edge_pointerY = pointerY;
 
714
        g_source_remove(self->_edge_trigger_handle);
 
715
        self->_edge_trigger_handle = g_timeout_add(self->_edge_timeout/2,
 
716
                                                   &UnityScreen::OnEdgeTriggerTimeout,
 
717
                                                   self);
 
718
        return false;
 
719
      }
 
720
    }
 
721
  }
 
722
 
 
723
  self->_edge_trigger_handle = 0;
 
724
  return false;
 
725
}
 
726
 
 
727
bool UnityScreen::launcherRevealEdgeInitiate(CompAction* action,
 
728
                                             CompAction::State state,
 
729
                                             CompOption::Vector& options)
 
730
{
 
731
  if (screen->grabbed())
 
732
    return false;
 
733
 
 
734
  if (_edge_trigger_handle)
 
735
    g_source_remove(_edge_trigger_handle);
 
736
 
 
737
  if (pointerX == 0)
 
738
  {
 
739
    _edge_pointerY = pointerY;
 
740
    _edge_trigger_handle = g_timeout_add(_edge_timeout,
 
741
                                         &UnityScreen::OnEdgeTriggerTimeout,
 
742
                                         this);
 
743
  }
 
744
 
 
745
  return false;
 
746
}
 
747
 
 
748
void UnityScreen::SendExecuteCommand()
 
749
{
 
750
  ubus_server_send_message(ubus_server_get_default(),
 
751
                           UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
 
752
                           g_variant_new("(sus)",
 
753
                                         "commands.lens",
 
754
                                         0,
 
755
                                         ""));
 
756
}
 
757
 
 
758
bool UnityScreen::executeCommand(CompAction* action,
 
759
                                 CompAction::State state,
 
760
                                 CompOption::Vector& options)
 
761
{
 
762
  SendExecuteCommand();
 
763
  return false;
 
764
}
 
765
 
 
766
void UnityScreen::restartLauncherKeyNav()
 
767
{
 
768
  // set input-focus on launcher-window and start key-nav mode
 
769
  if (newFocusedWindow != NULL)
 
770
  {
 
771
    newFocusedWindow->moveInputFocusTo();
 
772
    launcher->startKeyNavMode();
 
773
  }
 
774
}
 
775
 
 
776
void UnityScreen::startLauncherKeyNav()
 
777
{
 
778
  // get CompWindow* of launcher-window
 
779
  newFocusedWindow = screen->findWindow(launcherWindow->GetInputWindowId());
 
780
 
 
781
  // check if currently focused window isn't the launcher-window
 
782
  if (newFocusedWindow != screen->findWindow(screen->activeWindow()))
 
783
    lastFocusedWindow = screen->findWindow(screen->activeWindow());
 
784
 
 
785
  // set input-focus on launcher-window and start key-nav mode
 
786
  if (newFocusedWindow != NULL)
 
787
  {
 
788
    // Put the launcher BaseWindow at the top of the BaseWindow stack. The
 
789
    // input focus coming from the XinputWindow will be processed by the
 
790
    // launcher BaseWindow only. Then the Launcher BaseWindow will decide
 
791
    // which View will get the input focus.
 
792
    launcherWindow->PushToFront();
 
793
    newFocusedWindow->moveInputFocusTo();
 
794
  }
 
795
}
 
796
 
 
797
bool UnityScreen::setKeyboardFocusKeyInitiate(CompAction* action,
 
798
                                              CompAction::State state,
 
799
                                              CompOption::Vector& options)
 
800
{
 
801
  _key_nav_mode_requested = true;
 
802
  return false;
 
803
}
 
804
 
 
805
bool UnityScreen::altTabForwardInitiate(CompAction* action,
 
806
                                        CompAction::State state,
 
807
                                        CompOption::Vector& options)
 
808
{
 
809
  if (switcherController->Visible())
 
810
  {
 
811
    switcherController->Next();
 
812
  }
 
813
  else
 
814
  {
 
815
    std::vector<AbstractLauncherIcon*> results;
 
816
 
 
817
    if (!switcher_desktop_icon)
 
818
    {
 
819
      switcher_desktop_icon = new DesktopLauncherIcon(launcher);
 
820
      switcher_desktop_icon->SinkReference();
 
821
    }
 
822
 
 
823
    results.push_back(switcher_desktop_icon);
 
824
 
 
825
    LauncherModel::iterator it;
 
826
    for (it = launcher->GetModel()->begin(); it != launcher->GetModel()->end(); it++)
 
827
      if ((*it)->ShowInSwitcher())
 
828
        results.push_back(*it);
 
829
 
 
830
    // maybe check launcher position/hide state?
 
831
    switcherController->SetWorkspace(nux::Geometry(_primary_monitor.x + 100,
 
832
                                                   _primary_monitor.y + 100,
 
833
                                                   _primary_monitor.width - 200,
 
834
                                                   _primary_monitor.height - 200));
 
835
    switcherController->Show(SwitcherController::ALL, SwitcherController::FOCUS_ORDER, false, results);
 
836
  }
 
837
 
 
838
  action->setState(action->state() | CompAction::StateTermKey);
 
839
  return false;
 
840
}
 
841
 
 
842
bool UnityScreen::altTabForwardTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
843
{
 
844
  action->setState(action->state() & (unsigned)~(CompAction::StateTermKey));
 
845
  bool accept_state = (state & CompAction::StateCancel) == 0;
 
846
  switcherController->Hide(accept_state);
 
847
  return false;
 
848
}
 
849
 
 
850
bool UnityScreen::altTabPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
851
{
 
852
  if (switcherController->Visible())
 
853
    switcherController->Prev();
 
854
 
 
855
  action->setState(action->state() | CompAction::StateTermKey);
 
856
  return false;
 
857
}
 
858
 
 
859
bool UnityScreen::altTabPrevTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
860
{
 
861
  action->setState(action->state() & (unsigned)~(CompAction::StateTermKey));
 
862
  return false;
 
863
}
 
864
 
 
865
bool UnityScreen::altTabDetailStartInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
866
{
 
867
  if (switcherController->Visible())
 
868
    switcherController->SetDetail(true);
 
869
 
 
870
  action->setState(action->state() | CompAction::StateTermKey);
 
871
  return false;
 
872
}
 
873
 
 
874
bool UnityScreen::altTabDetailStartTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
875
{
 
876
  action->setState(action->state() & (unsigned)~(CompAction::StateTermKey));
 
877
  return false;
 
878
}
 
879
 
 
880
bool UnityScreen::altTabDetailStopInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
881
{
 
882
  if (switcherController->Visible())
 
883
    switcherController->SetDetail(false);
 
884
 
 
885
  action->setState(action->state() | CompAction::StateTermKey);
 
886
  return false;
 
887
}
 
888
 
 
889
bool UnityScreen::altTabDetailStopTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
890
{
 
891
  action->setState(action->state() & (unsigned)~(CompAction::StateTermKey));
 
892
  return false;
 
893
}
 
894
 
 
895
bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
896
{
 
897
  if (switcherController->Visible())
 
898
    switcherController->NextDetail();
 
899
 
 
900
  action->setState(action->state() | CompAction::StateTermKey);
 
901
  return false;
 
902
}
 
903
 
 
904
bool UnityScreen::altTabNextWindowTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
905
{
 
906
  action->setState(action->state() & (unsigned)~(CompAction::StateTermKey));
 
907
  return false;
 
908
}
 
909
 
 
910
bool UnityScreen::altTabExitInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
911
{
 
912
  switcherController->Hide(false);
 
913
  action->setState(action->state() | CompAction::StateTermKey);
 
914
  return false;
 
915
}
 
916
 
 
917
bool UnityScreen::altTabExitTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
918
{
 
919
  action->setState(action->state() & (unsigned)~(CompAction::StateTermKey));
 
920
  return false;
 
921
}
 
922
 
 
923
void UnityScreen::OnLauncherStartKeyNav(GVariant* data, void* value)
 
924
{
 
925
  UnityScreen* self = reinterpret_cast<UnityScreen*>(value);
 
926
  self->startLauncherKeyNav();
 
927
}
 
928
 
 
929
void UnityScreen::OnLauncherEndKeyNav(GVariant* data, void* value)
 
930
{
 
931
  UnityScreen* self = reinterpret_cast<UnityScreen*>(value);
 
932
  bool preserve_focus = false;
 
933
 
 
934
  if (data)
 
935
  {
 
936
    preserve_focus = g_variant_get_boolean(data);
 
937
  }
 
938
 
 
939
  // Return input-focus to previously focused window (before key-nav-mode was
 
940
  // entered)
 
941
  if (preserve_focus && (self->lastFocusedWindow != NULL))
 
942
  {
 
943
    self->lastFocusedWindow->moveInputFocusTo();
 
944
  }
 
945
}
 
946
 
 
947
void UnityScreen::OnQuicklistEndKeyNav(GVariant* data, void* value)
 
948
{
 
949
  UnityScreen* self = reinterpret_cast<UnityScreen*>(value);
 
950
  self->restartLauncherKeyNav();
 
951
}
 
952
 
 
953
gboolean UnityScreen::initPluginActions(gpointer data)
 
954
{
 
955
  CompPlugin* p = CompPlugin::find("expo");
 
956
 
 
957
  if (p)
 
958
  {
 
959
    MultiActionList expoActions(0);
 
960
 
 
961
    foreach(CompOption & option, p->vTable->getOptions())
 
962
    {
 
963
      if (option.name() == "expo_key" ||
 
964
          option.name() == "expo_button" ||
 
965
          option.name() == "expo_edge")
 
966
      {
 
967
        CompAction* action = &option.value().action();
 
968
        expoActions.AddNewAction(action, false);
 
969
        break;
 
970
      }
 
971
    }
 
972
 
 
973
    PluginAdapter::Default()->SetExpoAction(expoActions);
 
974
  }
 
975
 
 
976
  p = CompPlugin::find("scale");
 
977
 
 
978
  if (p)
 
979
  {
 
980
    MultiActionList scaleActions(0);
 
981
 
 
982
    foreach(CompOption & option, p->vTable->getOptions())
 
983
    {
 
984
      if (option.name() == "initiate_all_key" ||
 
985
          option.name() == "initiate_all_edge" ||
 
986
          option.name() == "initiate_key" ||
 
987
          option.name() == "initiate_button" ||
 
988
          option.name() == "initiate_edge" ||
 
989
          option.name() == "initiate_group_key" ||
 
990
          option.name() == "initiate_group_button" ||
 
991
          option.name() == "initiate_group_edge" ||
 
992
          option.name() == "initiate_output_key" ||
 
993
          option.name() == "initiate_output_button" ||
 
994
          option.name() == "initiate_output_edge")
 
995
      {
 
996
        CompAction* action = &option.value().action();
 
997
        scaleActions.AddNewAction(action, false);
 
998
      }
 
999
      else if (option.name() == "initiate_all_button")
 
1000
      {
 
1001
        CompAction* action = &option.value().action();
 
1002
        scaleActions.AddNewAction(action, true);
 
1003
      }
 
1004
    }
 
1005
 
 
1006
    PluginAdapter::Default()->SetScaleAction(scaleActions);
 
1007
  }
 
1008
 
 
1009
  p = CompPlugin::find("unitymtgrabhandles");
 
1010
 
 
1011
  if (p)
 
1012
  {
 
1013
    foreach(CompOption & option, p->vTable->getOptions())
 
1014
    {
 
1015
      if (option.name() == "show_handles_key")
 
1016
        PluginAdapter::Default()->SetShowHandlesAction(&option.value().action());
 
1017
      else if (option.name() == "hide_handles_key")
 
1018
        PluginAdapter::Default()->SetHideHandlesAction(&option.value().action());
 
1019
      else if (option.name() == "toggle_handles_key")
 
1020
        PluginAdapter::Default()->SetToggleHandlesAction(&option.value().action());
 
1021
    }
 
1022
  }
 
1023
 
 
1024
  return FALSE;
 
1025
}
 
1026
 
 
1027
/* Set up expo and scale actions on the launcher */
 
1028
bool UnityScreen::initPluginForScreen(CompPlugin* p)
 
1029
{
 
1030
  if (p->vTable->name() == "expo" ||
 
1031
      p->vTable->name() == "scale")
 
1032
  {
 
1033
    initPluginActions(this);
 
1034
  }
 
1035
 
 
1036
  return screen->initPluginForScreen(p);
 
1037
}
 
1038
 
 
1039
void UnityScreen::AddProperties(GVariantBuilder* builder)
 
1040
{
 
1041
}
 
1042
 
 
1043
const gchar* UnityScreen::GetName()
 
1044
{
 
1045
  return "Unity";
 
1046
}
 
1047
 
 
1048
const CompWindowList& UnityScreen::getWindowPaintList()
 
1049
{
 
1050
  CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList();
 
1051
  CompWindowList::reverse_iterator it = pl.rbegin();
 
1052
  CompWindowList::reverse_iterator end = pl.rend();
 
1053
  std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
 
1054
 
 
1055
  unsigned int size = xwns.size();
 
1056
 
 
1057
  while (it != end)
 
1058
  {
 
1059
    bool erased = false;
 
1060
    auto id = (*it)->id();
 
1061
    for (unsigned int i = 0; i < size; ++i)
 
1062
    {
 
1063
      if (xwns[i] == id)
 
1064
      {
 
1065
        /* Increment the reverse_iterator to ensure
 
1066
               * it is valid, then it++ returns the old
 
1067
         * position */
 
1068
        CompWindowList::reverse_iterator oit = it++;
 
1069
        /* Get the base and offset by -1 since
 
1070
         * &*(reverse_iterator(i)) == &*(i - 1)) */
 
1071
        CompWindowList::iterator eit = --(oit.base ());
 
1072
 
 
1073
        erased = true;
 
1074
 
 
1075
        /* Remove that from the list */
 
1076
        pl.erase(eit);
 
1077
        break;
 
1078
      }
 
1079
    }
 
1080
 
 
1081
    if (!erased)
 
1082
      it++;
 
1083
  }
 
1084
 
 
1085
  return pl;
 
1086
}
 
1087
 
 
1088
/* handle window painting in an opengl context
 
1089
 *
 
1090
 * we want to paint underneath other windows here,
 
1091
 * so we need to find if this window is actually
 
1092
 * stacked on top of one of the nux input windows
 
1093
 * and if so paint nux and stop us from painting
 
1094
 * other windows or on top of the whole screen */
 
1095
bool UnityWindow::glDraw(const GLMatrix& matrix,
 
1096
                         GLFragment::Attrib& attrib,
 
1097
                         const CompRegion& region,
 
1098
                         unsigned int mask)
 
1099
{
 
1100
  if (uScreen->doShellRepaint && uScreen->allowWindowPaint)
 
1101
  {
 
1102
    std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
 
1103
    unsigned int size = xwns.size();
 
1104
 
 
1105
    for (CompWindow* w = window; w && uScreen->doShellRepaint; w = w->prev)
 
1106
    {
 
1107
      auto id = w->id();
 
1108
      for (unsigned int i = 0; i < size; ++i)
 
1109
      {
 
1110
        if (xwns[i] == id)
 
1111
        {
 
1112
          uScreen->paintDisplay(region, matrix, mask);
 
1113
          break;
 
1114
        }
 
1115
      }
 
1116
    }
 
1117
  }
 
1118
 
 
1119
  bool ret = gWindow->glDraw(matrix, attrib, region, mask);
 
1120
 
 
1121
  if (window->type() == CompWindowTypeDesktopMask)
 
1122
  {
 
1123
    uScreen->paintPanelShadow(matrix);
 
1124
  }
 
1125
 
 
1126
  return ret;
 
1127
}
 
1128
 
 
1129
/* Called whenever a window is mapped, unmapped, minimized etc */
 
1130
void UnityWindow::windowNotify(CompWindowNotify n)
 
1131
{
 
1132
  PluginAdapter::Default()->Notify(window, n);
 
1133
  window->windowNotify(n);
 
1134
}
 
1135
 
 
1136
void UnityWindow::stateChangeNotify(unsigned int lastState)
 
1137
{
 
1138
  PluginAdapter::Default()->NotifyStateChange(window, window->state(), lastState);
 
1139
  window->stateChangeNotify(lastState);
 
1140
}
 
1141
 
 
1142
void UnityWindow::moveNotify(int x, int y, bool immediate)
 
1143
{
 
1144
  PluginAdapter::Default()->NotifyMoved(window, x, y);
 
1145
  window->moveNotify(x, y, immediate);
 
1146
}
 
1147
 
 
1148
void UnityWindow::resizeNotify(int x, int y, int w, int h)
 
1149
{
 
1150
  PluginAdapter::Default()->NotifyResized(window, x, y, w, h);
 
1151
  window->resizeNotify(x, y, w, h);
 
1152
}
 
1153
 
 
1154
CompPoint UnityWindow::tryNotIntersectLauncher(CompPoint& pos)
 
1155
{
 
1156
  UnityScreen* us = UnityScreen::get(screen);
 
1157
  nux::Geometry geo = us->launcher->GetAbsoluteGeometry();
 
1158
  CompRect launcherGeo(geo.x, geo.y, geo.width, geo.height);
 
1159
 
 
1160
  if (launcherGeo.contains(pos))
 
1161
  {
 
1162
    if (screen->workArea().contains(CompRect(launcherGeo.right() + 1, pos.y(), window->width(), window->height())))
 
1163
      pos.setX(launcherGeo.right() + 1);
 
1164
  }
 
1165
 
 
1166
  return pos;
 
1167
}
 
1168
 
 
1169
bool UnityWindow::place(CompPoint& pos)
 
1170
{
 
1171
  UnityScreen* us = UnityScreen::get(screen);
 
1172
  Launcher::LauncherHideMode hideMode = us->launcher->GetHideMode();
 
1173
 
 
1174
  bool result = window->place(pos);
 
1175
 
 
1176
  switch (hideMode)
 
1177
  {
 
1178
    case Launcher::LAUNCHER_HIDE_DODGE_WINDOWS:
 
1179
    case Launcher::LAUNCHER_HIDE_DODGE_ACTIVE_WINDOW:
 
1180
      pos = tryNotIntersectLauncher(pos);
 
1181
      break;
 
1182
 
 
1183
    default:
 
1184
      break;
 
1185
  }
 
1186
 
 
1187
  return result;
 
1188
}
 
1189
 
 
1190
/* Configure callback for the launcher window */
 
1191
void UnityScreen::launcherWindowConfigureCallback(int WindowWidth, int WindowHeight,
 
1192
                                                  nux::Geometry& geo, void* user_data)
 
1193
{
 
1194
  UnityScreen* self = reinterpret_cast<UnityScreen*>(user_data);
 
1195
  geo = nux::Geometry(self->_primary_monitor.x, self->_primary_monitor.y + 24,
 
1196
                      geo.width, self->_primary_monitor.height - 24);
 
1197
}
 
1198
 
 
1199
/* Start up nux after OpenGL is initialized */
 
1200
void UnityScreen::initUnity(nux::NThread* thread, void* InitData)
 
1201
{
 
1202
  Timer timer;
 
1203
  initLauncher(thread, InitData);
 
1204
 
 
1205
  nux::ColorLayer background(nux::color::Transparent);
 
1206
  static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
 
1207
  LOG_INFO(logger) << "UnityScreen::initUnity: " << timer.ElapsedSeconds() << "s";
 
1208
}
 
1209
 
 
1210
void UnityScreen::onRedrawRequested()
 
1211
{
 
1212
  // disable blur updates so we dont waste perf. This can stall the blur during animations
 
1213
  // but ensures a smooth animation.
 
1214
  BackgroundEffectHelper::updates_enabled = false;
 
1215
  damageNuxRegions();
 
1216
}
 
1217
 
 
1218
/* Handle option changes and plug that into nux windows */
 
1219
void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num)
 
1220
{
 
1221
  switch (num)
 
1222
  {
 
1223
    case UnityshellOptions::LauncherHideMode:
 
1224
      launcher->SetHideMode((Launcher::LauncherHideMode) optionGetLauncherHideMode());
 
1225
      break;
 
1226
    case UnityshellOptions::BacklightMode:
 
1227
      launcher->SetBacklightMode((Launcher::BacklightMode) optionGetBacklightMode());
 
1228
      break;
 
1229
    case UnityshellOptions::LaunchAnimation:
 
1230
      launcher->SetLaunchAnimation((Launcher::LaunchAnimation) optionGetLaunchAnimation());
 
1231
      break;
 
1232
    case UnityshellOptions::UrgentAnimation:
 
1233
      launcher->SetUrgentAnimation((Launcher::UrgentAnimation) optionGetUrgentAnimation());
 
1234
      break;
 
1235
    case UnityshellOptions::PanelOpacity:
 
1236
      panelController->SetOpacity(optionGetPanelOpacity());
 
1237
      break;
 
1238
    case UnityshellOptions::LauncherOpacity:
 
1239
      launcher->SetBackgroundAlpha(optionGetLauncherOpacity());
 
1240
      break;
 
1241
    case UnityshellOptions::IconSize:
 
1242
      panelController->SetBFBSize(optionGetIconSize() + 18);
 
1243
      launcher->SetIconSize(optionGetIconSize() + 6, optionGetIconSize());
 
1244
      dashController->launcher_width = optionGetIconSize() + 18;
 
1245
      break;
 
1246
    case UnityshellOptions::AutohideAnimation:
 
1247
      launcher->SetAutoHideAnimation((Launcher::AutoHideAnimation) optionGetAutohideAnimation());
 
1248
      break;
 
1249
    case UnityshellOptions::DashBlurExperimental:
 
1250
      BackgroundEffectHelper::blur_type = (unity::BlurType)optionGetDashBlurExperimental();
 
1251
      break;
 
1252
    case UnityshellOptions::AutomaximizeValue:
 
1253
      PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);
 
1254
      break;
 
1255
    case UnityshellOptions::DevicesOption:
 
1256
      unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption());
 
1257
      break;
 
1258
    case UnityshellOptions::LauncherRevealEdgeTimeout:
 
1259
      _edge_timeout = optionGetLauncherRevealEdgeTimeout();
 
1260
      break;
 
1261
    case UnityshellOptions::AltTabTimeout:
 
1262
      switcherController->detail_on_timeout = optionGetAltTabTimeout();
 
1263
      break;
 
1264
    default:
 
1265
      break;
 
1266
  }
 
1267
}
 
1268
 
 
1269
void UnityScreen::NeedsRelayout()
 
1270
{
 
1271
  needsRelayout = true;
 
1272
}
 
1273
 
 
1274
void UnityScreen::ScheduleRelayout(guint timeout)
 
1275
{
 
1276
  if (relayoutSourceId == 0)
 
1277
    relayoutSourceId = g_timeout_add(timeout, &UnityScreen::RelayoutTimeout, this);
 
1278
}
 
1279
 
 
1280
void UnityScreen::Relayout()
 
1281
{
 
1282
  GdkScreen* scr;
 
1283
  GdkRectangle rect;
 
1284
  nux::Geometry lCurGeom;
 
1285
  gint primary_monitor;
 
1286
  int panel_height = 24;
 
1287
 
 
1288
  if (!needsRelayout)
 
1289
    return;
 
1290
 
 
1291
  if (GL::fbo)
 
1292
  {
 
1293
    foreach (CompOutput &o, screen->outputDevs ())
 
1294
      uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO (&o));
 
1295
    
 
1296
    uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO (&(screen->fullscreenOutput ())));
 
1297
  }
 
1298
 
 
1299
  scr = gdk_screen_get_default ();
 
1300
  primary_monitor = gdk_screen_get_primary_monitor (scr);
 
1301
  gdk_screen_get_monitor_geometry (scr, primary_monitor, &rect);
 
1302
  _primary_monitor = rect;
 
1303
 
 
1304
  wt->SetWindowSize(rect.width, rect.height);
 
1305
 
 
1306
  lCurGeom = launcherWindow->GetGeometry();
 
1307
  launcher->SetMaximumHeight(rect.height - panel_height);
 
1308
 
 
1309
  g_debug("Setting to primary screen rect: x=%d y=%d w=%d h=%d",
 
1310
          rect.x,
 
1311
          rect.y,
 
1312
          rect.width,
 
1313
          rect.height);
 
1314
 
 
1315
  launcherWindow->SetGeometry(nux::Geometry(rect.x,
 
1316
                                            rect.y + panel_height,
 
1317
                                            lCurGeom.width,
 
1318
                                            rect.height - panel_height));
 
1319
  launcher->SetGeometry(nux::Geometry(rect.x,
 
1320
                                      rect.y + panel_height,
 
1321
                                      lCurGeom.width,
 
1322
                                      rect.height - panel_height));
 
1323
  needsRelayout = false;
 
1324
}
 
1325
 
 
1326
gboolean UnityScreen::RelayoutTimeout(gpointer data)
 
1327
{
 
1328
  UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);
 
1329
 
 
1330
  uScreen->mFbos.clear ();
 
1331
 
 
1332
  uScr->NeedsRelayout ();
 
1333
  uScr->Relayout();
 
1334
  uScr->relayoutSourceId = 0;
 
1335
 
 
1336
  uScr->cScreen->damageScreen();
 
1337
 
 
1338
  return FALSE;
 
1339
}
 
1340
 
 
1341
/* Handle changes in the number of workspaces by showing the switcher
 
1342
 * or not showing the switcher */
 
1343
bool UnityScreen::setOptionForPlugin(const char* plugin, const char* name,
 
1344
                                     CompOption::Value& v)
 
1345
{
 
1346
  bool status = screen->setOptionForPlugin(plugin, name, v);
 
1347
  if (status)
 
1348
  {
 
1349
    if (strcmp(plugin, "core") == 0 && strcmp(name, "hsize") == 0)
 
1350
    {
 
1351
      controller->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
 
1352
    }
 
1353
  }
 
1354
  return status;
 
1355
}
 
1356
 
 
1357
void UnityScreen::outputChangeNotify()
 
1358
{
 
1359
  ScheduleRelayout(500);
 
1360
}
 
1361
 
 
1362
void UnityFBO::paint ()
 
1363
{
 
1364
  //CompositeScreen *cScreen = CompositeScreen::get (screen);
 
1365
  //unsigned int    mask = cScreen->damageMask ();
 
1366
  float texx, texy, texwidth, texheight;
 
1367
 
 
1368
  /* Draw the bit of the relevant framebuffer for each output */
 
1369
  GLMatrix transform;
 
1370
 
 
1371
  glViewport (output->x (), screen->height () - output->y2 (), output->width (), output->height ());
 
1372
 
 
1373
  transform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
 
1374
  glPushMatrix ();
 
1375
  glLoadMatrixf (transform.getMatrix ());
 
1376
 
 
1377
  /* Note that texcoords here are normalized, so it's just (0,0)-(1,1) */
 
1378
  texx = 0.0;
 
1379
  texy = 0.0;
 
1380
  texwidth = 1.0f;
 
1381
  texheight = 1.0f;
 
1382
 
 
1383
  if (mFBTexture)
 
1384
  {
 
1385
    glEnable (GL_TEXTURE_2D);
 
1386
    GL::activeTexture (GL_TEXTURE0_ARB);
 
1387
    glBindTexture (GL_TEXTURE_2D, mFBTexture);
 
1388
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
1389
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
1390
    
 
1391
    glPushAttrib (GL_SCISSOR_BIT);
 
1392
    glEnable (GL_SCISSOR_TEST);
 
1393
 
 
1394
    glScissor (output->x1 (), screen->height () - output->y2 (),
 
1395
                output->width (), output->height ());
 
1396
    
 
1397
    /* FIXME: This needs to be GL_TRIANGLE_STRIP */
 
1398
    glBegin (GL_QUADS);
 
1399
    glTexCoord2f (texx, texy + texheight);
 
1400
    glVertex2i   (output->x1 (), output->y1 ());
 
1401
    glTexCoord2f (texx, texy);
 
1402
    glVertex2i   (output->x1 (),        output->y2 ());
 
1403
    glTexCoord2f (texx + texwidth, texy);
 
1404
    glVertex2i   (output->x2 (), output->y2 ());
 
1405
    glTexCoord2f (texx + texwidth, texy + texheight);
 
1406
    glVertex2i   (output->x2 (),        output->y1 ());
 
1407
    glEnd ();
 
1408
    
 
1409
    GL::activeTexture (GL_TEXTURE0_ARB);
 
1410
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
1411
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
1412
    glBindTexture (GL_TEXTURE_2D, 0);
 
1413
    glEnable (GL_TEXTURE_2D);
 
1414
    
 
1415
    glDisable (GL_SCISSOR_TEST);
 
1416
    glPopAttrib ();
 
1417
  }
 
1418
 
 
1419
  glPopMatrix();
 
1420
}
 
1421
 
 
1422
void UnityFBO::unbind ()
 
1423
{
 
1424
  uScreen->setActiveFbo (0);
 
1425
  (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
 
1426
 
 
1427
  glDrawBuffer (GL_BACK);
 
1428
  glReadBuffer (GL_BACK);
 
1429
 
 
1430
}
 
1431
 
 
1432
bool UnityFBO::status ()
 
1433
{
 
1434
  return mFboStatus;
 
1435
}
 
1436
 
 
1437
void UnityFBO::bind ()
 
1438
{
 
1439
  if (!mFBTexture)
 
1440
  {
 
1441
    glGenTextures (1, &mFBTexture);
 
1442
 
 
1443
    glBindTexture (GL_TEXTURE_2D, mFBTexture);
 
1444
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
1445
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
1446
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
1447
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
1448
    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, output->width (), output->height (), 0, GL_BGRA,
 
1449
#if IMAGE_BYTE_ORDER == MSBFirst
 
1450
                  GL_UNSIGNED_INT_8_8_8_8_REV,
 
1451
#else
 
1452
                  GL_UNSIGNED_BYTE,
 
1453
#endif
 
1454
                  NULL);
 
1455
 
 
1456
    glBindTexture (GL_TEXTURE_2D, 0);
 
1457
  }
 
1458
 
 
1459
  glGetError ();
 
1460
 
 
1461
  (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
 
1462
 
 
1463
  (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 
1464
                               GL_TEXTURE_2D, mFBTexture, 0);
 
1465
 
 
1466
  /* Ensure that a framebuffer is actually available */
 
1467
  if (!mFboStatus)
 
1468
  {
 
1469
    GLint status = (*GL::checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
 
1470
 
 
1471
    if (status != GL_FRAMEBUFFER_COMPLETE)
 
1472
    {
 
1473
       switch (status)
 
1474
       {
 
1475
          case GL_FRAMEBUFFER_UNDEFINED:
 
1476
            compLogMessage ("unity", CompLogLevelWarn, "no window"); break;
 
1477
          case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
 
1478
            compLogMessage ("unity", CompLogLevelWarn, "attachment incomplete"); break;
 
1479
          case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
 
1480
            compLogMessage ("unity", CompLogLevelWarn, "no buffers attached to fbo"); break;
 
1481
          case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
 
1482
            compLogMessage ("unity", CompLogLevelWarn, "some attachment in glDrawBuffers doesn't exist in FBO"); break;
 
1483
          case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
 
1484
            compLogMessage ("unity", CompLogLevelWarn, "some attachment in glReadBuffers doesn't exist in FBO"); break;
 
1485
          case GL_FRAMEBUFFER_UNSUPPORTED:
 
1486
            compLogMessage ("unity", CompLogLevelWarn, "unsupported internal format"); break;
 
1487
          case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
 
1488
            compLogMessage ("unity", CompLogLevelWarn, "different levels of sampling for each attachment"); break;
 
1489
          case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
 
1490
            compLogMessage ("unity", CompLogLevelWarn, "number of layers is different"); break;
 
1491
          default:
 
1492
            compLogMessage ("unity", CompLogLevelWarn, "unable to bind the framebuffer for an unknown reason"); break;
 
1493
       }
 
1494
 
 
1495
       GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
 
1496
       GL::deleteFramebuffers (1, &mFboHandle);
 
1497
 
 
1498
       glDrawBuffer (GL_BACK);
 
1499
       glReadBuffer (GL_BACK);
 
1500
 
 
1501
       mFboHandle = 0;
 
1502
 
 
1503
       mFboStatus = false;
 
1504
       uScreen->setActiveFbo (0);
 
1505
     }
 
1506
     else
 
1507
       mFboStatus = true;
 
1508
   }
 
1509
 
 
1510
  if (mFboStatus)
 
1511
  {
 
1512
    uScreen->setActiveFbo (mFboHandle);
 
1513
 
 
1514
    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
 
1515
    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
 
1516
 
 
1517
    glViewport (0,
 
1518
                0,
 
1519
                output->width (),
 
1520
                output->height ());
 
1521
 
 
1522
  }
 
1523
}
 
1524
 
 
1525
UnityFBO::UnityFBO (CompOutput *o)
 
1526
 : mFboStatus (false)
 
1527
 , mFBTexture (0)
 
1528
 , output (o)
 
1529
{
 
1530
  (*GL::genFramebuffers) (1, &mFboHandle);
 
1531
}
 
1532
 
 
1533
UnityFBO::~UnityFBO ()
 
1534
{
 
1535
  (*GL::deleteFramebuffers) (1, &mFboHandle);
 
1536
 
 
1537
  if (mFBTexture)
 
1538
    glDeleteTextures (1, &mFBTexture);
 
1539
}
 
1540
 
 
1541
/* Start up the launcher */
 
1542
void UnityScreen::initLauncher(nux::NThread* thread, void* InitData)
 
1543
{
 
1544
  Timer timer;
 
1545
  UnityScreen* self = reinterpret_cast<UnityScreen*>(InitData);
 
1546
 
 
1547
  self->launcherWindow = new nux::BaseWindow(TEXT("LauncherWindow"));
 
1548
  self->launcherWindow->SinkReference();
 
1549
 
 
1550
  self->launcher = new Launcher(self->launcherWindow, self->screen);
 
1551
  self->launcher->SinkReference();
 
1552
  self->launcher->hidden_changed.connect(sigc::mem_fun(self, &UnityScreen::OnLauncherHiddenChanged));
 
1553
 
 
1554
  self->AddChild(self->launcher);
 
1555
 
 
1556
  nux::HLayout* layout = new nux::HLayout();
 
1557
  layout->AddView(self->launcher, 1);
 
1558
  layout->SetContentDistribution(nux::eStackLeft);
 
1559
  layout->SetVerticalExternalMargin(0);
 
1560
  layout->SetHorizontalExternalMargin(0);
 
1561
 
 
1562
  self->controller = new LauncherController(self->launcher, self->screen);
 
1563
 
 
1564
  self->launcherWindow->SetConfigureNotifyCallback(&UnityScreen::launcherWindowConfigureCallback, self);
 
1565
  self->launcherWindow->SetLayout(layout);
 
1566
  self->launcherWindow->SetBackgroundColor(nux::Color(0x00000000));
 
1567
  self->launcherWindow->ShowWindow(true);
 
1568
  self->launcherWindow->EnableInputWindow(true, "launcher", false, false);
 
1569
  self->launcherWindow->InputWindowEnableStruts(true);
 
1570
  self->launcherWindow->SetEnterFocusInputArea(self->launcher);
 
1571
 
 
1572
  self->switcherController = new SwitcherController();
 
1573
  /* FIXME: this should not be manual, should be managed with a
 
1574
     show/hide callback like in GAIL*/
 
1575
  if (unity_a11y_initialized () == TRUE)
 
1576
    {
 
1577
      AtkObject *atk_obj = NULL;
 
1578
 
 
1579
      atk_obj = unity_util_accessible_add_window (self->launcherWindow);
 
1580
 
 
1581
      atk_object_set_name (atk_obj, _("Launcher"));
 
1582
    }
 
1583
 
 
1584
  self->launcher->SetIconSize(54, 48);
 
1585
  self->launcher->SetBacklightMode(Launcher::BACKLIGHT_ALWAYS_ON);
 
1586
 
 
1587
  LOG_INFO(logger) << "initLauncher-Launcher " << timer.ElapsedSeconds() << "s";
 
1588
 
 
1589
  /* Setup panel */
 
1590
  timer.Reset();
 
1591
  self->panelController = new PanelController();
 
1592
  self->AddChild(self->panelController);
 
1593
  LOG_INFO(logger) << "initLauncher-Panel " << timer.ElapsedSeconds() << "s";
 
1594
 
 
1595
  /* Setup Places */
 
1596
  self->dashController = DashController::Ptr(new DashController());
 
1597
 
 
1598
  /* FIXME: this should not be manual, should be managed with a
 
1599
     show/hide callback like in GAIL
 
1600
  if (unity_a11y_initialized() == TRUE)
 
1601
  {
 
1602
    AtkObject* atk_obj = NULL;
 
1603
 
 
1604
    atk_obj = unity_util_accessible_add_window(self->placesController->GetWindow());
 
1605
 
 
1606
    atk_object_set_name(atk_obj, _("Places"));
 
1607
  }
 
1608
  */
 
1609
 
 
1610
  self->launcher->SetHideMode(Launcher::LAUNCHER_HIDE_DODGE_WINDOWS);
 
1611
  self->launcher->SetLaunchAnimation(Launcher::LAUNCH_ANIMATION_PULSE);
 
1612
  self->launcher->SetUrgentAnimation(Launcher::URGENT_ANIMATION_WIGGLE);
 
1613
  self->ScheduleRelayout(0);
 
1614
 
 
1615
  self->OnLauncherHiddenChanged();
 
1616
}
 
1617
 
 
1618
/* Window init */
 
1619
UnityWindow::UnityWindow(CompWindow* window)
 
1620
  : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
 
1621
  , PluginClassHandler<UnityWindow, CompWindow>(window)
 
1622
  , window(window)
 
1623
  , gWindow(GLWindow::get(window))
 
1624
{
 
1625
  WindowInterface::setHandler(window);
 
1626
  GLWindowInterface::setHandler(gWindow);
 
1627
}
 
1628
 
 
1629
UnityWindow::~UnityWindow()
 
1630
{
 
1631
  UnityScreen* us = UnityScreen::get(screen);
 
1632
  if (us->newFocusedWindow && (UnityWindow::get(us->newFocusedWindow) == this))
 
1633
    us->newFocusedWindow = NULL;
 
1634
  if (us->lastFocusedWindow && (UnityWindow::get(us->lastFocusedWindow) == this))
 
1635
    us->lastFocusedWindow = NULL;
 
1636
}
 
1637
 
 
1638
/* vtable init */
 
1639
bool UnityPluginVTable::init()
 
1640
{
 
1641
  gfloat version;
 
1642
  gchar* extensions;
 
1643
 
 
1644
  if (!CompPlugin::checkPluginABI("core", CORE_ABIVERSION))
 
1645
    return false;
 
1646
  if (!CompPlugin::checkPluginABI("composite", COMPIZ_COMPOSITE_ABI))
 
1647
    return false;
 
1648
  if (!CompPlugin::checkPluginABI("opengl", COMPIZ_OPENGL_ABI))
 
1649
    return false;
 
1650
 
 
1651
  /* Ensure OpenGL version is 1.4+. */
 
1652
  version = get_opengl_version_f32((const gchar*) glGetString(GL_VERSION));
 
1653
  if (version < 1.4f)
 
1654
  {
 
1655
    compLogMessage("unityshell", CompLogLevelError,
 
1656
                   "OpenGL 1.4+ not supported\n");
 
1657
    return false;
 
1658
  }
 
1659
 
 
1660
  /* Ensure OpenGL extensions required by the Unity plugin are available. */
 
1661
  extensions = (gchar*) glGetString(GL_EXTENSIONS);
 
1662
  if (!is_extension_supported(extensions, "GL_ARB_vertex_program"))
 
1663
  {
 
1664
    compLogMessage("unityshell", CompLogLevelError,
 
1665
                   "GL_ARB_vertex_program not supported\n");
 
1666
    return false;
 
1667
  }
 
1668
  if (!is_extension_supported(extensions, "GL_ARB_fragment_program"))
 
1669
  {
 
1670
    compLogMessage("unityshell", CompLogLevelError,
 
1671
                   "GL_ARB_fragment_program not supported\n");
 
1672
    return false;
 
1673
  }
 
1674
  if (!is_extension_supported(extensions, "GL_ARB_vertex_buffer_object"))
 
1675
  {
 
1676
    compLogMessage("unityshell", CompLogLevelError,
 
1677
                   "GL_ARB_vertex_buffer_object not supported\n");
 
1678
    return false;
 
1679
  }
 
1680
  if (!is_extension_supported(extensions, "GL_ARB_framebuffer_object"))
 
1681
  {
 
1682
    if (!is_extension_supported(extensions, "GL_EXT_framebuffer_object"))
 
1683
    {
 
1684
      compLogMessage("unityshell", CompLogLevelError,
 
1685
                     "GL_ARB_framebuffer_object or GL_EXT_framebuffer_object "
 
1686
                     "not supported\n");
 
1687
      return false;
 
1688
    }
 
1689
  }
 
1690
  if (!is_extension_supported(extensions, "GL_ARB_texture_non_power_of_two"))
 
1691
  {
 
1692
    if (!is_extension_supported(extensions, "GL_ARB_texture_rectangle"))
 
1693
    {
 
1694
      compLogMessage("unityshell", CompLogLevelError,
 
1695
                     "GL_ARB_texture_non_power_of_two or "
 
1696
                     "GL_ARB_texture_rectangle not supported\n");
 
1697
      return false;
 
1698
    }
 
1699
  }
 
1700
 
 
1701
  return true;
 
1702
}
 
1703
 
 
1704
 
 
1705
namespace
 
1706
{
 
1707
 
 
1708
void configure_logging()
 
1709
{
 
1710
  // The default behaviour of the logging infrastructure is to send all output
 
1711
  // to std::cout for warning or above.
 
1712
 
 
1713
  // TODO: write a file output handler that keeps track of backups.
 
1714
  nux::logging::configure_logging(::getenv("UNITY_LOG_SEVERITY"));
 
1715
  g_log_set_default_handler(capture_g_log_calls, NULL);
 
1716
}
 
1717
 
 
1718
/* Checks whether an extension is supported by the GLX or OpenGL implementation
 
1719
 * given the extension name and the list of supported extensions. */
 
1720
gboolean is_extension_supported(const gchar* extensions, const gchar* extension)
 
1721
{
 
1722
  if (extensions != NULL && extension != NULL)
 
1723
  {
 
1724
    const gsize len = strlen(extension);
 
1725
    gchar* p = (gchar*) extensions;
 
1726
    gchar* end = p + strlen(p);
 
1727
 
 
1728
    while (p < end)
 
1729
    {
 
1730
      const gsize size = strcspn(p, " ");
 
1731
      if (len == size && strncmp(extension, p, size) == 0)
 
1732
        return TRUE;
 
1733
      p += size + 1;
 
1734
    }
 
1735
  }
 
1736
 
 
1737
  return FALSE;
 
1738
}
 
1739
 
 
1740
/* Gets the OpenGL version as a floating-point number given the string. */
 
1741
gfloat get_opengl_version_f32(const gchar* version_string)
 
1742
{
 
1743
  gfloat version = 0.0f;
 
1744
  gint32 i;
 
1745
 
 
1746
  for (i = 0; isdigit(version_string[i]); i++)
 
1747
    version = version * 10.0f + (version_string[i] - 48);
 
1748
 
 
1749
  if ((version_string[i] == '.' || version_string[i] == ',') &&
 
1750
      isdigit(version_string[i + 1]))
 
1751
  {
 
1752
    version = version * 10.0f + (version_string[i + 1] - 48);
 
1753
    return (version + 0.1f) * 0.1f;
 
1754
  }
 
1755
  else
 
1756
    return 0.0f;
 
1757
}
 
1758
 
 
1759
nux::logging::Level glog_level_to_nux(GLogLevelFlags log_level)
 
1760
{
 
1761
  // For some weird reason, ERROR is more critical than CRITICAL in gnome.
 
1762
  if (log_level & G_LOG_LEVEL_ERROR)
 
1763
    return nux::logging::Critical;
 
1764
  if (log_level & G_LOG_LEVEL_CRITICAL)
 
1765
    return nux::logging::Error;
 
1766
  if (log_level & G_LOG_LEVEL_WARNING)
 
1767
    return nux::logging::Warning;
 
1768
  if (log_level & G_LOG_LEVEL_MESSAGE ||
 
1769
      log_level & G_LOG_LEVEL_INFO)
 
1770
    return nux::logging::Info;
 
1771
  // default to debug.
 
1772
  return nux::logging::Debug;
 
1773
}
 
1774
 
 
1775
void capture_g_log_calls(const gchar* log_domain,
 
1776
                         GLogLevelFlags log_level,
 
1777
                         const gchar* message,
 
1778
                         gpointer user_data)
 
1779
{
 
1780
  // Since we aren't entirely sure if log_domain contains anything, lets have
 
1781
  // a glib prefix.
 
1782
  std::string module("glib");
 
1783
  if (log_domain)
 
1784
  {
 
1785
    module += std::string(".") + log_domain;
 
1786
  }
 
1787
  nux::logging::Logger logger(module);
 
1788
  nux::logging::Level level = glog_level_to_nux(log_level);
 
1789
  if (logger.GetEffectiveLogLevel() >= level)
 
1790
  {
 
1791
    nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
 
1792
        << message;
 
1793
  }
 
1794
}
 
1795
 
 
1796
} // anonymous namespace