~ubuntu-branches/ubuntu/oneiric/unity/oneiric

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-10-07 09:03:50 UTC
  • Revision ID: james.westby@ubuntu.com-20111007090350-56xw1pt9tdlpc2fg
Tags: 4.22.0-0ubuntu3
* Cherry-pick upstream:
  - Resize the _gradient_texture (in PanelMenuView::Draw) if needed
    (LP: #863068, #868293, #869028)

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 "GeisAdapter.h"
 
33
#include "DevicesSettings.h"
 
34
#include "PluginAdapter.h"
 
35
#include "QuicklistManager.h"
 
36
#include "StartupNotifyService.h"
 
37
#include "Timer.h"
 
38
#include "KeyboardUtil.h"
 
39
#include "unityshell.h"
 
40
#include "BackgroundEffectHelper.h"
 
41
 
 
42
#include <dbus/dbus.h>
 
43
#include <dbus/dbus-glib.h>
 
44
#include <glib/gi18n-lib.h>
 
45
#include <gtk/gtk.h>
 
46
#include <gdk/gdk.h>
 
47
#include <libnotify/notify.h>
 
48
 
 
49
#include <sstream>
 
50
 
 
51
#include <core/atoms.h>
 
52
 
 
53
#include "unitya11y.h"
 
54
 
 
55
#include "ubus-server.h"
 
56
#include "UBusMessages.h"
 
57
#include "UScreen.h"
 
58
 
 
59
#include "config.h"
 
60
 
 
61
/* FIXME: once we get a better method to add the toplevel windows to
 
62
   the accessible root object, this include would not be required */
 
63
#include "unity-util-accessible.h"
 
64
 
 
65
using namespace unity::switcher;
 
66
 
 
67
/* Set up vtable symbols */
 
68
COMPIZ_PLUGIN_20090315(unityshell, UnityPluginVTable);
 
69
 
 
70
using ::unity::util::Timer;
 
71
 
 
72
namespace
 
73
{
 
74
 
 
75
nux::logging::Logger logger("unity.shell");
 
76
 
 
77
UnityScreen* uScreen = 0;
 
78
 
 
79
void configure_logging();
 
80
void capture_g_log_calls(const gchar* log_domain,
 
81
                         GLogLevelFlags log_level,
 
82
                         const gchar* message,
 
83
                         gpointer user_data);
 
84
gboolean is_extension_supported(const gchar* extensions, const gchar* extension);
 
85
gfloat get_opengl_version_f32(const gchar* version_string);
 
86
 
 
87
}
 
88
 
 
89
UnityScreen::UnityScreen(CompScreen* screen)
 
90
  : BaseSwitchScreen (screen)
 
91
  , PluginClassHandler <UnityScreen, CompScreen> (screen)
 
92
  , screen(screen)
 
93
  , cScreen(CompositeScreen::get(screen))
 
94
  , gScreen(GLScreen::get(screen))
 
95
  , launcher(nullptr)
 
96
  , controller(nullptr)
 
97
  , panelController(nullptr)
 
98
  , switcherController(nullptr)
 
99
  , gestureEngine(nullptr)
 
100
  , wt(nullptr)
 
101
  , launcherWindow(nullptr)
 
102
  , panelWindow(nullptr)
 
103
  , debugger(nullptr)
 
104
  , needsRelayout(false)
 
105
  , relayoutSourceId(0)
 
106
  , _edge_trigger_handle(0)
 
107
  , _edge_pointerY(0)
 
108
  , newFocusedWindow(nullptr)
 
109
  , doShellRepaint(false)
 
110
  , allowWindowPaint(false)
 
111
  , damaged(false)
 
112
  , _key_nav_mode_requested(false)
 
113
  , _last_output(nullptr)
 
114
  , switcher_desktop_icon(nullptr)
 
115
  , mActiveFbo (0)
 
116
  , dash_is_open_ (false)
 
117
  , grab_index_ (0)
 
118
  , painting_tray_ (false)
 
119
{
 
120
  Timer timer;
 
121
  gfloat version;
 
122
  gchar* extensions;
 
123
  bool  failed = false;
 
124
  configure_logging();
 
125
  LOG_DEBUG(logger) << __PRETTY_FUNCTION__;
 
126
  int (*old_handler)(Display*, XErrorEvent*);
 
127
  old_handler = XSetErrorHandler(NULL);
 
128
 
 
129
  /* Ensure OpenGL version is 1.4+. */
 
130
  version = get_opengl_version_f32((const gchar*) glGetString(GL_VERSION));
 
131
  if (version < 1.4f)
 
132
  {
 
133
    compLogMessage("unityshell", CompLogLevelError,
 
134
                   "OpenGL 1.4+ not supported\n");
 
135
    setFailed ();
 
136
    failed = true;
 
137
  }
 
138
 
 
139
  /* Ensure OpenGL extensions required by the Unity plugin are available. */
 
140
  extensions = (gchar*) glGetString(GL_EXTENSIONS);
 
141
  if (!is_extension_supported(extensions, "GL_ARB_vertex_program"))
 
142
  {
 
143
    compLogMessage("unityshell", CompLogLevelError,
 
144
                   "GL_ARB_vertex_program not supported\n");
 
145
    setFailed ();
 
146
    failed = true;
 
147
  }
 
148
  if (!is_extension_supported(extensions, "GL_ARB_fragment_program"))
 
149
  {
 
150
    compLogMessage("unityshell", CompLogLevelError,
 
151
                   "GL_ARB_fragment_program not supported\n");
 
152
    setFailed ();
 
153
    failed = true;
 
154
  }
 
155
  if (!is_extension_supported(extensions, "GL_ARB_vertex_buffer_object"))
 
156
  {
 
157
    compLogMessage("unityshell", CompLogLevelError,
 
158
                   "GL_ARB_vertex_buffer_object not supported\n");
 
159
    setFailed ();
 
160
    failed = true;
 
161
  }
 
162
  if (!is_extension_supported(extensions, "GL_ARB_framebuffer_object"))
 
163
  {
 
164
    if (!is_extension_supported(extensions, "GL_EXT_framebuffer_object"))
 
165
    {
 
166
      compLogMessage("unityshell", CompLogLevelError,
 
167
                     "GL_ARB_framebuffer_object or GL_EXT_framebuffer_object "
 
168
                     "not supported\n");
 
169
      setFailed();
 
170
      failed = true;
 
171
    }
 
172
  }
 
173
  if (!is_extension_supported(extensions, "GL_ARB_texture_non_power_of_two"))
 
174
  {
 
175
    if (!is_extension_supported(extensions, "GL_ARB_texture_rectangle"))
 
176
    {
 
177
      compLogMessage("unityshell", CompLogLevelError,
 
178
                     "GL_ARB_texture_non_power_of_two or "
 
179
                     "GL_ARB_texture_rectangle not supported\n");
 
180
      setFailed ();
 
181
      failed = true;
 
182
    }
 
183
  }
 
184
 
 
185
  if (!failed)
 
186
  {
 
187
     notify_init("unityshell");
 
188
 
 
189
     g_thread_init(NULL);
 
190
     dbus_g_thread_init();
 
191
 
 
192
     unity_a11y_preset_environment();
 
193
 
 
194
     XSetErrorHandler(old_handler);
 
195
 
 
196
     /* Wrap compiz interfaces */
 
197
     ScreenInterface::setHandler(screen);
 
198
     CompositeScreenInterface::setHandler(cScreen);
 
199
     GLScreenInterface::setHandler(gScreen);
 
200
 
 
201
     PluginAdapter::Initialize(screen);
 
202
     WindowManager::SetDefault(PluginAdapter::Default());
 
203
 
 
204
     StartupNotifyService::Default()->SetSnDisplay(screen->snDisplay(), screen->screenNum());
 
205
 
 
206
     nux::NuxInitialize(0);
 
207
     wt = nux::CreateFromForeignWindow(cScreen->output(),
 
208
                                       glXGetCurrentContext(),
 
209
                                       &UnityScreen::initUnity,
 
210
                                       this);
 
211
 
 
212
     wt->RedrawRequested.connect(sigc::mem_fun(this, &UnityScreen::onRedrawRequested));
 
213
 
 
214
     unity_a11y_init(wt);
 
215
 
 
216
     /* i18n init */
 
217
     bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
 
218
     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
 
219
 
 
220
     wt->Run(NULL);
 
221
     uScreen = this;
 
222
 
 
223
     debugger = new DebugDBusInterface(this);
 
224
 
 
225
     _edge_timeout = optionGetLauncherRevealEdgeTimeout ();
 
226
     _in_paint = false;
 
227
 
 
228
     if (GL::fbo)
 
229
     {
 
230
       foreach (CompOutput & o, screen->outputDevs())
 
231
             uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO(&o));
 
232
 
 
233
       uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO(&(screen->fullscreenOutput ())));
 
234
     }
 
235
 
 
236
     optionSetLauncherHideModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
237
     optionSetBacklightModeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
238
     optionSetLaunchAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
239
     optionSetUrgentAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
240
     optionSetPanelOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
241
     optionSetLauncherOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
242
     optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
243
     optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
244
     optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
245
     optionSetDevicesOptionNotify(boost::bind (&UnityScreen::optionChanged, this, _1, _2));
 
246
     optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
 
247
     optionSetShowLauncherTerminate(boost::bind(&UnityScreen::showLauncherKeyTerminate, this, _1, _2, _3));
 
248
     optionSetKeyboardFocusInitiate(boost::bind(&UnityScreen::setKeyboardFocusKeyInitiate, this, _1, _2, _3));
 
249
     //optionSetKeyboardFocusTerminate (boost::bind (&UnityScreen::setKeyboardFocusKeyTerminate, this, _1, _2, _3));
 
250
     optionSetExecuteCommandInitiate(boost::bind(&UnityScreen::executeCommand, this, _1, _2, _3));
 
251
     optionSetPanelFirstMenuInitiate(boost::bind(&UnityScreen::showPanelFirstMenuKeyInitiate, this, _1, _2, _3));
 
252
     optionSetPanelFirstMenuTerminate(boost::bind(&UnityScreen::showPanelFirstMenuKeyTerminate, this, _1, _2, _3));
 
253
     optionSetLauncherRevealEdgeInitiate(boost::bind(&UnityScreen::launcherRevealEdgeInitiate, this, _1, _2, _3));
 
254
     optionSetLauncherRevealEdgeTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
255
     optionSetAutomaximizeValueNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
256
     optionSetAltTabTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
257
     optionSetAltTabBiasViewportNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
 
258
 
 
259
     optionSetAltTabForwardInitiate(boost::bind(&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
 
260
     optionSetAltTabForwardTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
 
261
     optionSetAltTabPrevInitiate(boost::bind(&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
 
262
 
 
263
     optionSetAltTabDetailStartInitiate(boost::bind(&UnityScreen::altTabDetailStartInitiate, this, _1, _2, _3));
 
264
     optionSetAltTabDetailStopInitiate(boost::bind(&UnityScreen::altTabDetailStopInitiate, this, _1, _2, _3));
 
265
 
 
266
     optionSetAltTabNextWindowInitiate(boost::bind(&UnityScreen::altTabNextWindowInitiate, this, _1, _2, _3));
 
267
     optionSetAltTabNextWindowTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
 
268
 
 
269
     optionSetAltTabPrevWindowInitiate(boost::bind(&UnityScreen::altTabPrevWindowInitiate, this, _1, _2, _3));
 
270
 
 
271
     optionSetAltTabLeftInitiate (boost::bind (&UnityScreen::altTabPrevInitiate, this, _1, _2, _3));
 
272
     optionSetAltTabRightInitiate (boost::bind (&UnityScreen::altTabForwardInitiate, this, _1, _2, _3));
 
273
     optionSetShowMinimizedWindowsNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
 
274
 
 
275
     for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); i++)
 
276
       _ubus_handles[i] = 0;
 
277
 
 
278
     UBusServer* ubus = ubus_server_get_default();
 
279
     _ubus_handles[0] = ubus_server_register_interest(ubus,
 
280
                                                      UBUS_LAUNCHER_START_KEY_NAV,
 
281
                                                      (UBusCallback)&UnityScreen::OnLauncherStartKeyNav,
 
282
                                                      this);
 
283
 
 
284
     _ubus_handles[1] = ubus_server_register_interest(ubus,
 
285
                                                      UBUS_LAUNCHER_END_KEY_NAV,
 
286
                                                      (UBusCallback)&UnityScreen::OnLauncherEndKeyNav,
 
287
                                                      this);
 
288
 
 
289
     _ubus_handles[2] = ubus_server_register_interest(ubus,
 
290
                                                      UBUS_QUICKLIST_END_KEY_NAV,
 
291
                                                      (UBusCallback)&UnityScreen::OnQuicklistEndKeyNav,
 
292
                                                      this);
 
293
 
 
294
     g_timeout_add(0, &UnityScreen::initPluginActions, this);
 
295
     super_keypressed_ = false;
 
296
 
 
297
     GeisAdapter::Default()->Run();
 
298
     gestureEngine = new GestureEngine(screen);
 
299
 
 
300
     CompString name(PKGDATADIR"/panel-shadow.png");
 
301
     CompString pname("unityshell");
 
302
     CompSize size(1, 20);
 
303
     _shadow_texture = GLTexture::readImageToTexture(name, pname, size);
 
304
 
 
305
     BackgroundEffectHelper::updates_enabled = true;
 
306
 
 
307
     ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_SHOWN, [&](GVariant * args) { dash_is_open_ = true; });
 
308
     ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_HIDDEN, [&](GVariant * args) { dash_is_open_ = false; });
 
309
      LOG_INFO(logger) << "UnityScreen constructed: " << timer.ElapsedSeconds() << "s";
 
310
  }
 
311
}
 
312
 
 
313
UnityScreen::~UnityScreen()
 
314
{
 
315
  if (switcher_desktop_icon)
 
316
    switcher_desktop_icon->UnReference();
 
317
  panelController->UnReference();
 
318
  delete controller;
 
319
  delete switcherController;
 
320
  launcherWindow->UnReference();
 
321
 
 
322
  notify_uninit();
 
323
 
 
324
  unity_a11y_finalize();
 
325
 
 
326
  UBusServer* ubus = ubus_server_get_default();
 
327
  for (unsigned int i = 0; i < G_N_ELEMENTS(_ubus_handles); i++)
 
328
  {
 
329
    if (_ubus_handles[i] != 0)
 
330
      ubus_server_unregister_interest(ubus, _ubus_handles[i]);
 
331
  }
 
332
 
 
333
  if (relayoutSourceId != 0)
 
334
    g_source_remove(relayoutSourceId);
 
335
 
 
336
  ::unity::ui::IconRenderer::DestroyTextures();
 
337
  QuicklistManager::Destroy();
 
338
 
 
339
  delete wt;
 
340
}
 
341
 
 
342
void UnityScreen::initAltTabNextWindow()
 
343
{
 
344
  KeyboardUtil key_util (screen->dpy());
 
345
  guint above_tab_keycode = key_util.GetKeycodeAboveKeySymbol (XStringToKeysym("Tab"));
 
346
  KeySym above_tab_keysym = XKeycodeToKeysym (screen->dpy(), above_tab_keycode, 0);
 
347
 
 
348
  if (above_tab_keysym != NoSymbol)
 
349
  {
 
350
    {
 
351
      std::ostringstream sout;
 
352
      sout << "<Alt>" << XKeysymToString(above_tab_keysym);
 
353
 
 
354
      screen->removeAction(&optionGetAltTabNextWindow());
 
355
      
 
356
      CompAction action = CompAction();
 
357
      action.keyFromString(sout.str());
 
358
      action.setState (CompAction::StateInitKey | CompAction::StateAutoGrab);
 
359
      mOptions[UnityshellOptions::AltTabNextWindow].value().set (action);
 
360
      screen->addAction (&mOptions[UnityshellOptions::AltTabNextWindow].value ().action ());
 
361
 
 
362
      optionSetAltTabNextWindowInitiate(boost::bind(&UnityScreen::altTabNextWindowInitiate, this, _1, _2, _3));
 
363
      optionSetAltTabNextWindowTerminate(boost::bind(&UnityScreen::altTabTerminateCommon, this, _1, _2, _3));
 
364
    }
 
365
    {
 
366
      std::ostringstream sout;
 
367
      sout << "<Alt><Shift>" << XKeysymToString(above_tab_keysym);
 
368
 
 
369
      screen->removeAction(&optionGetAltTabPrevWindow());
 
370
      
 
371
      CompAction action = CompAction();
 
372
      action.keyFromString(sout.str());
 
373
      action.setState (CompAction::StateInitKey | CompAction::StateAutoGrab);
 
374
      mOptions[UnityshellOptions::AltTabPrevWindow].value().set (action);
 
375
      screen->addAction (&mOptions[UnityshellOptions::AltTabPrevWindow].value ().action ());
 
376
 
 
377
      optionSetAltTabPrevWindowInitiate(boost::bind(&UnityScreen::altTabPrevWindowInitiate, this, _1, _2, _3));
 
378
    }
 
379
  }
 
380
  else
 
381
  {
 
382
    printf ("Could not find key above tab!\n");
 
383
  }
 
384
 
 
385
}
 
386
 
 
387
void UnityScreen::EnsureSuperKeybindings()
 
388
{
 
389
  for (auto action : _shortcut_actions)
 
390
    screen->removeAction(action.get());
 
391
 
 
392
  _shortcut_actions.clear ();
 
393
 
 
394
  for (auto icon : *(launcher->GetModel()))
 
395
  {
 
396
    guint64 shortcut = icon->GetShortcut();
 
397
    if (shortcut == 0)
 
398
      continue;
 
399
    CreateSuperNewAction(static_cast<char>(shortcut));
 
400
    CreateSuperNewAction(static_cast<char>(shortcut), true);
 
401
    CreateSuperNewAction(static_cast<char>(shortcut), false, true);
 
402
  }
 
403
 
 
404
  for (auto shortcut : dashController->GetAllShortcuts())
 
405
    CreateSuperNewAction(shortcut);
 
406
}
 
407
 
 
408
void UnityScreen::CreateSuperNewAction(char shortcut, bool use_shift, bool use_numpad)
 
409
{
 
410
    CompActionPtr action(new CompAction());
 
411
 
 
412
    CompAction::KeyBinding binding;
 
413
    std::ostringstream sout;
 
414
    if (use_shift)
 
415
      sout << "<Shift><Super>"  << shortcut;
 
416
    else
 
417
      sout << "<Super>" << ((use_numpad) ? "KP_" : "") << shortcut;
 
418
 
 
419
    binding.fromString(sout.str());
 
420
 
 
421
    action->setKey(binding);
 
422
 
 
423
    screen->addAction(action.get());
 
424
    _shortcut_actions.push_back(action);
 
425
}
 
426
 
 
427
void UnityScreen::nuxPrologue()
 
428
{
 
429
  /* Vertex lighting isn't used in Unity, we disable that state as it could have
 
430
   * been leaked by another plugin. That should theoretically be switched off
 
431
   * right after PushAttrib since ENABLE_BIT is meant to restore the LIGHTING
 
432
   * bit, but we do that here in order to workaround a bug (?) in the NVIDIA
 
433
   * drivers (lp:703140). */
 
434
  glDisable(GL_LIGHTING);
 
435
 
 
436
  /* reset matrices */
 
437
  glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT |
 
438
               GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_SCISSOR_BIT);
 
439
 
 
440
  glMatrixMode(GL_PROJECTION);
 
441
  glPushMatrix();
 
442
 
 
443
  glMatrixMode(GL_MODELVIEW);
 
444
  glPushMatrix();
 
445
 
 
446
  glGetError();
 
447
}
 
448
 
 
449
void UnityScreen::nuxEpilogue()
 
450
{
 
451
  (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, mActiveFbo);
 
452
 
 
453
  glMatrixMode(GL_PROJECTION);
 
454
  glLoadIdentity();
 
455
  glMatrixMode(GL_MODELVIEW);
 
456
  glLoadIdentity();
 
457
  glDepthRange(0, 1);
 
458
  glViewport(-1, -1, 2, 2);
 
459
  glRasterPos2f(0, 0);
 
460
 
 
461
  gScreen->resetRasterPos();
 
462
 
 
463
  glMatrixMode(GL_PROJECTION);
 
464
  glPopMatrix();
 
465
  glMatrixMode(GL_MODELVIEW);
 
466
  glPopMatrix();
 
467
 
 
468
  glDrawBuffer(GL_BACK);
 
469
  glReadBuffer(GL_BACK);
 
470
 
 
471
  glPopAttrib();
 
472
 
 
473
  glDisable(GL_SCISSOR_TEST);
 
474
}
 
475
 
 
476
void UnityScreen::OnLauncherHiddenChanged()
 
477
{
 
478
  if (launcher->Hidden())
 
479
    screen->addAction(&optionGetLauncherRevealEdge());
 
480
  else
 
481
    screen->removeAction(&optionGetLauncherRevealEdge());
 
482
}
 
483
 
 
484
void UnityScreen::paintPanelShadow(const GLMatrix& matrix)
 
485
{
 
486
  if (relayoutSourceId > 0)
 
487
    return;
 
488
 
 
489
  if (PluginAdapter::Default()->IsExpoActive())
 
490
    return;
 
491
 
 
492
  nuxPrologue();
 
493
 
 
494
  CompOutput* output = _last_output;
 
495
  float vc[4];
 
496
  float h = 20.0f;
 
497
  float w = 1.0f;
 
498
  float panel_h = 24.0f;
 
499
 
 
500
  float x1 = output->x();
 
501
  float y1 = output->y() + panel_h;
 
502
  float x2 = x1 + output->width();
 
503
  float y2 = y1 + h;
 
504
 
 
505
  vc[0] = x1;
 
506
  vc[1] = x2;
 
507
  vc[2] = y1;
 
508
  vc[3] = y2;
 
509
 
 
510
  if (!dash_is_open_ && panelController->opacity() > 0.0f)
 
511
  {
 
512
    foreach(GLTexture * tex, _shadow_texture)
 
513
    {
 
514
      glEnable(GL_BLEND);
 
515
      glColor4f(1.0f, 1.0f, 1.0f, panelController->opacity());
 
516
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
517
 
 
518
      GL::activeTexture(GL_TEXTURE0_ARB);
 
519
      tex->enable(GLTexture::Fast);
 
520
 
 
521
      glTexParameteri(tex->target(), GL_TEXTURE_WRAP_S, GL_REPEAT);
 
522
 
 
523
      glBegin(GL_QUADS);
 
524
      {
 
525
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), 0));
 
526
        glVertex2f(vc[0], vc[2]);
 
527
 
 
528
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), h));
 
529
        glVertex2f(vc[0], vc[3]);
 
530
 
 
531
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), h));
 
532
        glVertex2f(vc[1], vc[3]);
 
533
 
 
534
        glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), 0));
 
535
        glVertex2f(vc[1], vc[2]);
 
536
      }
 
537
      glEnd();
 
538
 
 
539
      tex->disable();
 
540
      glDisable(GL_BLEND);
 
541
    }
 
542
  }
 
543
  nuxEpilogue();
 
544
}
 
545
 
 
546
void
 
547
UnityWindow::updateIconPos (int   &wx,
 
548
                            int   &wy,
 
549
                            int   x,
 
550
                            int   y,
 
551
                            float width,
 
552
                            float height)
 
553
{
 
554
  wx = x + (last_bound.width - width) / 2;
 
555
  wy = y + (last_bound.height - height) / 2;
 
556
}
 
557
 
 
558
void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask)
 
559
{
 
560
  CompOutput *output = _last_output;
 
561
  Window     tray_xid = panelController->GetTrayXid ();
 
562
  bool       bound = mFbos[output]->bound ();
 
563
 
 
564
 
 
565
  if (bound)
 
566
  {
 
567
    mFbos[output]->unbind ();
 
568
 
 
569
    /* Draw the bit of the relevant framebuffer for each output */
 
570
    mFbos[output]->paint ();
 
571
  }
 
572
 
 
573
  nuxPrologue();
 
574
 
 
575
  nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
 
576
  nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(mFbos[output]->texture(),
 
577
  output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
 
578
 
 
579
  nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
 
580
 
 
581
  nux::Geometry geo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
 
582
  BackgroundEffectHelper::monitor_rect_ = geo;
 
583
 
 
584
  _in_paint = true;
 
585
  wt->RenderInterfaceFromForeignCmd (&geo);
 
586
  _in_paint = false;
 
587
  nuxEpilogue();
 
588
 
 
589
  if (tray_xid && !allowWindowPaint)
 
590
  {
 
591
    CompWindow *tray = screen->findWindow (tray_xid);
 
592
 
 
593
    if (tray)
 
594
    {
 
595
      GLMatrix oTransform;
 
596
      UnityWindow  *uTrayWindow = UnityWindow::get (tray);
 
597
      GLFragment::Attrib attrib (uTrayWindow->gWindow->lastPaintAttrib());
 
598
      unsigned int oldGlAddGeometryIndex = uTrayWindow->gWindow->glAddGeometryGetCurrentIndex ();
 
599
      unsigned int oldGlDrawIndex = uTrayWindow->gWindow->glDrawGetCurrentIndex ();
 
600
      unsigned int oldGlDrawGeometryIndex = uTrayWindow->gWindow->glDrawGeometryGetCurrentIndex ();
 
601
 
 
602
      attrib.setOpacity (OPAQUE);
 
603
      attrib.setBrightness (BRIGHT);
 
604
      attrib.setSaturation (COLOR);
 
605
 
 
606
      oTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
 
607
 
 
608
      glPushMatrix ();
 
609
      glLoadMatrixf (oTransform.getMatrix ());
 
610
 
 
611
      painting_tray_ = true;
 
612
 
 
613
      /* force the use of the core functions */
 
614
      uTrayWindow->gWindow->glDrawSetCurrentIndex (MAXSHORT);
 
615
      uTrayWindow->gWindow->glAddGeometrySetCurrentIndex ( MAXSHORT);
 
616
      uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (MAXSHORT);
 
617
      uTrayWindow->gWindow->glDraw (oTransform, attrib, infiniteRegion,
 
618
                                     PAINT_WINDOW_TRANSFORMED_MASK |
 
619
                                     PAINT_WINDOW_BLEND_MASK |
 
620
                                     PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
 
621
      uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (oldGlDrawGeometryIndex);
 
622
      uTrayWindow->gWindow->glAddGeometrySetCurrentIndex (oldGlAddGeometryIndex);
 
623
      uTrayWindow->gWindow->glDrawSetCurrentIndex (oldGlDrawIndex);
 
624
      painting_tray_ = false;
 
625
 
 
626
      glPopMatrix ();
 
627
    }
 
628
  }
 
629
 
 
630
 if (switcherController->Visible ())
 
631
  {
 
632
    LayoutWindowList targets = switcherController->ExternalRenderTargets ();
 
633
 
 
634
    for (LayoutWindow::Ptr target : targets)
 
635
    {
 
636
      CompWindow* window = screen->findWindow(target->xid);
 
637
      if (window)
 
638
      {
 
639
        UnityWindow *unity_window = UnityWindow::get (window);
 
640
 
 
641
        unity_window->paintThumbnail (target->result, target->alpha);
 
642
      }
 
643
    }
 
644
  }
 
645
 
 
646
  doShellRepaint = false;
 
647
  damaged = false;
 
648
}
 
649
 
 
650
bool UnityScreen::forcePaintOnTop ()
 
651
{
 
652
    return !allowWindowPaint ||
 
653
            ((switcherController->Visible() ||
 
654
              dash_is_open_) && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));
 
655
}
 
656
 
 
657
void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha)
 
658
{
 
659
  GLMatrix matrix;
 
660
  matrix.toScreenSpace (UnityScreen::get (screen)->_last_output, -DEFAULT_Z_CAMERA);
 
661
 
 
662
  nux::Geometry geo = bounding;
 
663
  last_bound = geo;
 
664
 
 
665
  GLWindowPaintAttrib attrib = gWindow->lastPaintAttrib ();
 
666
  attrib.opacity = (GLushort) (alpha * G_MAXUSHORT);
 
667
 
 
668
  paintThumb (attrib,
 
669
              matrix,
 
670
              0,
 
671
              geo.x,
 
672
              geo.y,
 
673
              geo.width,
 
674
              geo.height,
 
675
              geo.width,
 
676
              geo.height);
 
677
}
 
678
 
 
679
void UnityScreen::enterShowDesktopMode ()
 
680
{
 
681
  for (CompWindow *w : screen->windows ())
 
682
  {
 
683
    if (UnityShowdesktopHandler::shouldHide (w))
 
684
      UnityWindow::get (w)->enterShowDesktop ();
 
685
    if (w->type() & CompWindowTypeDesktopMask)
 
686
      w->moveInputFocusTo();
 
687
  }
 
688
 
 
689
  PluginAdapter::Default()->OnShowDesktop();
 
690
 
 
691
  screen->enterShowDesktopMode ();
 
692
}
 
693
 
 
694
void UnityScreen::leaveShowDesktopMode (CompWindow *w)
 
695
{
 
696
  for (CompWindow *cw : screen->windows ())
 
697
    UnityWindow::get (cw)->leaveShowDesktop ();
 
698
 
 
699
  PluginAdapter::Default()->OnLeaveDesktop();
 
700
 
 
701
  screen->leaveShowDesktopMode (w);
 
702
}
 
703
 
 
704
void UnityWindow::enterShowDesktop ()
 
705
{
 
706
  if (!mShowdesktopHandler)
 
707
    mShowdesktopHandler = new UnityShowdesktopHandler (window);
 
708
 
 
709
  window->setShowDesktopMode (true);
 
710
  mShowdesktopHandler->fadeOut ();
 
711
}
 
712
 
 
713
void UnityWindow::leaveShowDesktop ()
 
714
{
 
715
  if (mShowdesktopHandler)
 
716
  {
 
717
    mShowdesktopHandler->fadeIn ();
 
718
    window->setShowDesktopMode (false);
 
719
  }
 
720
}
 
721
 
 
722
bool UnityWindow::handleAnimations (unsigned int ms)
 
723
{
 
724
  if (mShowdesktopHandler)
 
725
    if (mShowdesktopHandler->animate (ms))
 
726
    { 
 
727
      delete mShowdesktopHandler;
 
728
      mShowdesktopHandler = NULL;
 
729
      return true;
 
730
    }
 
731
 
 
732
  return false;
 
733
}
 
734
 
 
735
/* 300 ms */
 
736
const unsigned int UnityShowdesktopHandler::fade_time = 300;
 
737
CompWindowList UnityShowdesktopHandler::animating_windows (0);
 
738
 
 
739
bool UnityShowdesktopHandler::shouldHide (CompWindow *w)
 
740
{
 
741
  if (!w->managed ())
 
742
    return false;
 
743
 
 
744
  if (w->grabbed ())
 
745
    return false;
 
746
 
 
747
  if (w->wmType () & (CompWindowTypeDesktopMask |
 
748
                      CompWindowTypeDockMask))
 
749
   return false;
 
750
 
 
751
  if (w->state () & CompWindowStateSkipPagerMask)
 
752
    return false;
 
753
 
 
754
  return true;
 
755
}
 
756
 
 
757
UnityShowdesktopHandler::UnityShowdesktopHandler (CompWindow *w) :
 
758
  mWindow (w),
 
759
  mRemover (new compiz::WindowInputRemover (screen->dpy (), w->id ())),
 
760
  mState (Visible),
 
761
  mProgress (0.0f)
 
762
{
 
763
}
 
764
 
 
765
UnityShowdesktopHandler::~UnityShowdesktopHandler ()
 
766
{
 
767
  if (mRemover)
 
768
    delete mRemover;
 
769
}
 
770
 
 
771
void UnityShowdesktopHandler::fadeOut ()
 
772
{
 
773
  mState = UnityShowdesktopHandler::FadeOut;
 
774
  mProgress = 1.0f;
 
775
 
 
776
  mWasHidden = mWindow->state () & CompWindowStateHiddenMask;
 
777
 
 
778
  if (!mWasHidden)
 
779
  {
 
780
    mWindow->changeState (mWindow->state () | CompWindowStateHiddenMask);
 
781
    mWindow->windowNotify (CompWindowNotifyHide);
 
782
    mRemover->save ();
 
783
    mRemover->remove ();
 
784
  }
 
785
 
 
786
  CompositeWindow::get (mWindow)->addDamage ();
 
787
 
 
788
  if (std::find (animating_windows.begin(),
 
789
                 animating_windows.end(),
 
790
                 mWindow) == animating_windows.end())
 
791
    animating_windows.push_back(mWindow);
 
792
}
 
793
 
 
794
void UnityShowdesktopHandler::fadeIn ()
 
795
{
 
796
  mState = UnityShowdesktopHandler::FadeIn;
 
797
 
 
798
  if (!mWasHidden)
 
799
  {
 
800
    mWindow->changeState (mWindow->state () & ~CompWindowStateHiddenMask);
 
801
    mWindow->windowNotify (CompWindowNotifyShow);
 
802
    mRemover->restore ();
 
803
  }
 
804
 
 
805
  CompositeWindow::get (mWindow)->addDamage ();
 
806
}
 
807
 
 
808
bool UnityShowdesktopHandler::animate (unsigned int ms)
 
809
{
 
810
  float inc = fade_time / (float) ms;
 
811
 
 
812
  if (mState == UnityShowdesktopHandler::FadeOut)
 
813
  {
 
814
    mProgress -= inc;
 
815
    if (mProgress <= 0.0f)
 
816
    {
 
817
      mProgress = 0.0f;
 
818
      mState = Invisible;
 
819
    }
 
820
    else
 
821
      CompositeWindow::get (mWindow)->addDamage ();
 
822
  }
 
823
  else if (mState == FadeIn)
 
824
  {
 
825
    mProgress += inc;
 
826
    if (mProgress >= 1.0f)
 
827
    {
 
828
      mProgress = 1.0f;
 
829
      mState = Visible;
 
830
 
 
831
      return true;
 
832
    }
 
833
    else
 
834
      CompositeWindow::get (mWindow)->addDamage ();
 
835
  }
 
836
 
 
837
  return false;
 
838
}
 
839
 
 
840
void UnityShowdesktopHandler::paintAttrib (GLWindowPaintAttrib &attrib)
 
841
{
 
842
  attrib.opacity = static_cast <int> (static_cast <float> (attrib.opacity) * mProgress);
 
843
}
 
844
 
 
845
unsigned int UnityShowdesktopHandler::getPaintMask ()
 
846
{
 
847
    return 0;
 
848
}
 
849
 
 
850
void UnityShowdesktopHandler::handleEvent (XEvent *event)
 
851
{
 
852
  /* Ignore sent events from the InputRemover */
 
853
  if (screen->XShape () && event->type ==
 
854
      screen->shapeEvent () + ShapeNotify &&
 
855
      !event->xany.send_event)
 
856
  {
 
857
    if (mRemover)
 
858
    {
 
859
      mRemover->save ();
 
860
      mRemover->remove ();
 
861
    }
 
862
  }
 
863
}
 
864
 
 
865
void UnityShowdesktopHandler::windowNotify (CompWindowNotify n)
 
866
{
 
867
  if (n == CompWindowNotifyFocusChange && mWindow->minimized ())
 
868
  {
 
869
    for (CompWindow *w : animating_windows)
 
870
      w->focusSetEnabled (UnityWindow::get (w), false);
 
871
 
 
872
    mWindow->moveInputFocusToOtherWindow ();
 
873
 
 
874
    for (CompWindow *w : animating_windows)
 
875
      w->focusSetEnabled (UnityWindow::get (w), true);
 
876
  }
 
877
}
 
878
 
 
879
void UnityShowdesktopHandler::updateFrameRegion (CompRegion &r)
 
880
{
 
881
  unsigned int oldUpdateFrameRegionIndex;
 
882
  r = CompRegion ();
 
883
 
 
884
  /* Ensure no other plugins can touch this frame region */
 
885
  oldUpdateFrameRegionIndex = mWindow->updateFrameRegionGetCurrentIndex ();
 
886
  mWindow->updateFrameRegionSetCurrentIndex (MAXSHORT);
 
887
  mWindow->updateFrameRegion (r);
 
888
  mWindow->updateFrameRegionSetCurrentIndex (oldUpdateFrameRegionIndex);
 
889
}
 
890
 
 
891
/* called whenever we need to repaint parts of the screen */
 
892
bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
 
893
                                const GLMatrix& transform,
 
894
                                const CompRegion& region,
 
895
                                CompOutput* output,
 
896
                                unsigned int mask)
 
897
{
 
898
  bool ret;
 
899
 
 
900
  /* bind the framebuffer here
 
901
   * - it will be unbound and flushed
 
902
   *   to the backbuffer when some
 
903
   *   plugin requests to draw a
 
904
   *   a transformed screen or when
 
905
   *   we have finished this draw cycle.
 
906
   *   once an fbo is bound any further
 
907
   *   attempts to bind it will only increment
 
908
   *   its bind reference so make sure that
 
909
   *   you always unbind as much as you bind */
 
910
  mFbos[output]->bind ();
 
911
 
 
912
  doShellRepaint = true;
 
913
  allowWindowPaint = true;
 
914
  _last_output = output;
 
915
 
 
916
  /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
 
917
  ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
 
918
 
 
919
  if (doShellRepaint)
 
920
    paintDisplay(region, transform, mask);
 
921
 
 
922
  return ret;
 
923
}
 
924
 
 
925
/* called whenever a plugin needs to paint the entire scene
 
926
 * transformed */
 
927
 
 
928
void UnityScreen::glPaintTransformedOutput(const GLScreenPaintAttrib& attrib,
 
929
                                           const GLMatrix& transform,
 
930
                                           const CompRegion& region,
 
931
                                           CompOutput* output,
 
932
                                           unsigned int mask)
 
933
{
 
934
  allowWindowPaint = false;
 
935
  gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask);
 
936
 
 
937
}
 
938
 
 
939
void UnityScreen::preparePaint(int ms)
 
940
{
 
941
  CompWindowList remove_windows;
 
942
 
 
943
  cScreen->preparePaint(ms);
 
944
 
 
945
  for (CompWindow *w : UnityShowdesktopHandler::animating_windows)
 
946
    if (UnityWindow::get (w)->handleAnimations (ms))
 
947
      remove_windows.push_back(w);
 
948
 
 
949
  for (CompWindow *w : remove_windows)
 
950
    UnityShowdesktopHandler::animating_windows.remove (w);
 
951
 
 
952
  if (damaged)
 
953
  {
 
954
    damaged = false;
 
955
    damageNuxRegions();
 
956
  }
 
957
 
 
958
}
 
959
 
 
960
/* Grab changed nux regions and add damage rects for them */
 
961
void UnityScreen::damageNuxRegions()
 
962
{
 
963
  CompRegion nux_damage;
 
964
 
 
965
  if (damaged)
 
966
    return;
 
967
 
 
968
  std::vector<nux::Geometry> dirty = wt->GetDrawList();
 
969
  damaged = true;
 
970
 
 
971
  for (std::vector<nux::Geometry>::iterator it = dirty.begin(), end = dirty.end();
 
972
       it != end; ++it)
 
973
  {
 
974
    nux::Geometry const& geo = *it;
 
975
    nux_damage = CompRegion(geo.x, geo.y, geo.width, geo.height);
 
976
    cScreen->damageRegion(nux_damage);
 
977
  }
 
978
 
 
979
  nux::Geometry geo = wt->GetWindowCompositor().GetTooltipMainWindowGeometry();
 
980
  nux_damage = CompRegion(geo.x, geo.y, geo.width, geo.height);
 
981
  cScreen->damageRegion(nux_damage);
 
982
 
 
983
  geo = lastTooltipArea;
 
984
  nux_damage = CompRegion(lastTooltipArea.x, lastTooltipArea.y,
 
985
                          lastTooltipArea.width, lastTooltipArea.height);
 
986
  cScreen->damageRegion(nux_damage);
 
987
 
 
988
  wt->ClearDrawList();
 
989
 
 
990
  lastTooltipArea = geo;
 
991
}
 
992
 
 
993
/* handle X Events */
 
994
void UnityScreen::handleEvent(XEvent* event)
 
995
{
 
996
  bool skip_other_plugins = false;
 
997
 
 
998
  switch (event->type)
 
999
  {
 
1000
    case FocusIn:
 
1001
    case FocusOut:
 
1002
      if (event->xfocus.mode == NotifyGrab)
 
1003
        PluginAdapter::Default()->OnScreenGrabbed();
 
1004
      else if (event->xfocus.mode == NotifyUngrab)
 
1005
        PluginAdapter::Default()->OnScreenUngrabbed();
 
1006
      cScreen->damageScreen();  // evil hack
 
1007
      if (_key_nav_mode_requested)
 
1008
        launcher->startKeyNavMode();
 
1009
      _key_nav_mode_requested = false;
 
1010
      break;
 
1011
    case KeyPress:
 
1012
      KeySym key_sym;
 
1013
      char key_string[2];
 
1014
      int result;
 
1015
      if ((result = XLookupString(&(event->xkey), key_string, 2, &key_sym, 0)) > 0)
 
1016
      {
 
1017
        key_string[result] = 0;
 
1018
        if (super_keypressed_) {
 
1019
          skip_other_plugins = launcher->CheckSuperShortcutPressed(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string);
 
1020
          if (!skip_other_plugins) {
 
1021
            skip_other_plugins = dashController->CheckShortcutActivation(key_string);
 
1022
            if (skip_other_plugins)
 
1023
              launcher->SetLatestShortcut(key_string[0]);
 
1024
          }
 
1025
        }
 
1026
      }
 
1027
      default:
 
1028
        if (screen->shapeEvent () + ShapeNotify == event->type)
 
1029
        {
 
1030
          Window xid = event->xany.window;
 
1031
          CompWindow *w = screen->findWindow(xid);
 
1032
 
 
1033
          if (w)
 
1034
          {
 
1035
            UnityWindow *uw = UnityWindow::get (w);
 
1036
 
 
1037
            if (uw->mShowdesktopHandler)
 
1038
              uw->mShowdesktopHandler->handleEvent(event);
 
1039
          }
 
1040
        }
 
1041
      break;
 
1042
  }
 
1043
 
 
1044
  compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::handleEvent (event);
 
1045
 
 
1046
  // avoid further propagation (key conflict for instance)
 
1047
  if (!skip_other_plugins)
 
1048
    screen->handleEvent(event);
 
1049
 
 
1050
  if (event->type == PropertyNotify)
 
1051
  {
 
1052
    if (event->xproperty.atom == Atoms::mwmHints)
 
1053
    {
 
1054
      PluginAdapter::Default ()->NotifyNewDecorationState(event->xproperty.window);
 
1055
    }
 
1056
  }
 
1057
 
 
1058
  if (!skip_other_plugins &&
 
1059
      screen->otherGrabExist("deco", "move", "switcher", "resize", NULL) &&
 
1060
      !switcherController->Visible())
 
1061
  {
 
1062
    wt->ProcessForeignEvent(event, NULL);
 
1063
  }
 
1064
 
 
1065
  if (event->type == cScreen->damageEvent() + XDamageNotify)
 
1066
  {
 
1067
    XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
 
1068
    CompWindow* w = screen->findWindow (de->drawable);
 
1069
 
 
1070
    if (w)
 
1071
    {
 
1072
      nux::Geometry damage (de->area.x, de->area.y, de->area.width, de->area.height);
 
1073
 
 
1074
      CompWindow::Geometry geom = w->geometry ();
 
1075
      damage.x += geom.x () + geom.border ();
 
1076
      damage.y += geom.y () + geom.border ();
 
1077
 
 
1078
      BackgroundEffectHelper::ProcessDamage(damage);
 
1079
    }
 
1080
  }
 
1081
}
 
1082
 
 
1083
void UnityScreen::handleCompizEvent(const char* plugin,
 
1084
                                    const char* event,
 
1085
                                    CompOption::Vector& option)
 
1086
{
 
1087
  PluginAdapter::Default()->NotifyCompizEvent(plugin, event, option);
 
1088
  compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::handleCompizEvent (plugin, event, option);
 
1089
 
 
1090
  if (dash_is_open_ && 
 
1091
      strcmp(event, "start_viewport_switch") == 0)
 
1092
  {
 
1093
    ubus_server_send_message(ubus_server_get_default(), UBUS_PLACE_VIEW_CLOSE_REQUEST, NULL);
 
1094
  }
 
1095
 
 
1096
  screen->handleCompizEvent(plugin, event, option);
 
1097
}
 
1098
 
 
1099
bool UnityScreen::showLauncherKeyInitiate(CompAction* action,
 
1100
                                          CompAction::State state,
 
1101
                                          CompOption::Vector& options)
 
1102
{
 
1103
  // to receive the Terminate event
 
1104
  if (state & CompAction::StateInitKey)
 
1105
    action->setState(action->state() | CompAction::StateTermKey);
 
1106
 
 
1107
  super_keypressed_ = true;
 
1108
  launcher->StartKeyShowLauncher();
 
1109
  EnsureSuperKeybindings ();
 
1110
  return false;
 
1111
}
 
1112
 
 
1113
bool UnityScreen::showLauncherKeyTerminate(CompAction* action,
 
1114
                                           CompAction::State state,
 
1115
                                           CompOption::Vector& options)
 
1116
{
 
1117
  super_keypressed_ = false;
 
1118
  launcher->EndKeyShowLauncher();
 
1119
  return false;
 
1120
}
 
1121
 
 
1122
bool UnityScreen::showPanelFirstMenuKeyInitiate(CompAction* action,
 
1123
                                                CompAction::State state,
 
1124
                                                CompOption::Vector& options)
 
1125
{
 
1126
  grab_index_ = screen->pushGrab (None, "unityshell");
 
1127
  // to receive the Terminate event
 
1128
  action->setState(action->state() | CompAction::StateTermKey);
 
1129
  panelController->StartFirstMenuShow();
 
1130
  return false;
 
1131
}
 
1132
 
 
1133
bool UnityScreen::showPanelFirstMenuKeyTerminate(CompAction* action,
 
1134
                                                 CompAction::State state,
 
1135
                                                 CompOption::Vector& options)
 
1136
{
 
1137
  screen->removeGrab(grab_index_, NULL);
 
1138
  action->setState (action->state() & (unsigned)~(CompAction::StateTermKey));
 
1139
  panelController->EndFirstMenuShow();
 
1140
  return false;
 
1141
}
 
1142
 
 
1143
gboolean UnityScreen::OnEdgeTriggerTimeout(gpointer data)
 
1144
{
 
1145
  UnityScreen* self = reinterpret_cast<UnityScreen*>(data);
 
1146
 
 
1147
  if (pointerX <= 1)
 
1148
  {
 
1149
    if (pointerY <= 24)
 
1150
      return true;
 
1151
 
 
1152
    if (abs(pointerY - self->_edge_pointerY) <= 5)
 
1153
    {
 
1154
      self->launcher->EdgeRevealTriggered(pointerX, pointerY);
 
1155
    }
 
1156
    else
 
1157
    {
 
1158
      /* We are still in the edge, but moving in Y, maybe we need another chance */
 
1159
 
 
1160
      if (abs(pointerY - self->_edge_pointerY) > 20)
 
1161
      {
 
1162
        /* We're quite far from the first hit spot, let's wait again */
 
1163
        self->_edge_pointerY = pointerY;
 
1164
        return true;
 
1165
      }
 
1166
      else
 
1167
      {
 
1168
        /* We're quite near to the first hit spot, so we can reduce our timeout */
 
1169
        self->_edge_pointerY = pointerY;
 
1170
        g_source_remove(self->_edge_trigger_handle);
 
1171
        self->_edge_trigger_handle = g_timeout_add(self->_edge_timeout/2,
 
1172
                                                   &UnityScreen::OnEdgeTriggerTimeout,
 
1173
                                                   self);
 
1174
        return false;
 
1175
      }
 
1176
    }
 
1177
  }
 
1178
 
 
1179
  self->_edge_trigger_handle = 0;
 
1180
  return false;
 
1181
}
 
1182
 
 
1183
bool UnityScreen::launcherRevealEdgeInitiate(CompAction* action,
 
1184
                                             CompAction::State state,
 
1185
                                             CompOption::Vector& options)
 
1186
{
 
1187
  if (screen->grabbed())
 
1188
    return false;
 
1189
 
 
1190
  if (_edge_trigger_handle)
 
1191
    g_source_remove(_edge_trigger_handle);
 
1192
 
 
1193
  if (pointerX <= 1)
 
1194
  {
 
1195
    _edge_pointerY = pointerY;
 
1196
    _edge_trigger_handle = g_timeout_add(_edge_timeout,
 
1197
                                         &UnityScreen::OnEdgeTriggerTimeout,
 
1198
                                         this);
 
1199
  }
 
1200
 
 
1201
  return false;
 
1202
}
 
1203
 
 
1204
void UnityScreen::SendExecuteCommand()
 
1205
{
 
1206
  ubus_server_send_message(ubus_server_get_default(),
 
1207
                           UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
 
1208
                           g_variant_new("(sus)",
 
1209
                                         "commands.lens",
 
1210
                                         0,
 
1211
                                         ""));
 
1212
}
 
1213
 
 
1214
bool UnityScreen::executeCommand(CompAction* action,
 
1215
                                 CompAction::State state,
 
1216
                                 CompOption::Vector& options)
 
1217
{
 
1218
  SendExecuteCommand();
 
1219
  return false;
 
1220
}
 
1221
 
 
1222
void UnityScreen::restartLauncherKeyNav()
 
1223
{
 
1224
  // set input-focus on launcher-window and start key-nav mode
 
1225
  if (newFocusedWindow != NULL)
 
1226
  {
 
1227
    newFocusedWindow->moveInputFocusTo();
 
1228
    launcher->startKeyNavMode();
 
1229
  }
 
1230
}
 
1231
 
 
1232
void UnityScreen::startLauncherKeyNav()
 
1233
{
 
1234
  // get CompWindow* of launcher-window
 
1235
  newFocusedWindow = screen->findWindow(launcherWindow->GetInputWindowId());
 
1236
 
 
1237
  // check if currently focused window isn't the launcher-window
 
1238
  if (newFocusedWindow != screen->findWindow(screen->activeWindow()))
 
1239
    PluginAdapter::Default ()->saveInputFocus ();
 
1240
 
 
1241
  // set input-focus on launcher-window and start key-nav mode
 
1242
  if (newFocusedWindow != NULL)
 
1243
  {
 
1244
    // Put the launcher BaseWindow at the top of the BaseWindow stack. The
 
1245
    // input focus coming from the XinputWindow will be processed by the
 
1246
    // launcher BaseWindow only. Then the Launcher BaseWindow will decide
 
1247
    // which View will get the input focus.
 
1248
    launcherWindow->PushToFront();
 
1249
    newFocusedWindow->moveInputFocusTo();
 
1250
  }
 
1251
}
 
1252
 
 
1253
bool UnityScreen::setKeyboardFocusKeyInitiate(CompAction* action,
 
1254
                                              CompAction::State state,
 
1255
                                              CompOption::Vector& options)
 
1256
{
 
1257
  _key_nav_mode_requested = true;
 
1258
  return false;
 
1259
}
 
1260
 
 
1261
bool UnityScreen::altTabInitiateCommon(CompAction *action,
 
1262
                                      CompAction::State state,
 
1263
                                      CompOption::Vector& options)
 
1264
{
 
1265
  std::vector<AbstractLauncherIcon*> results;
 
1266
 
 
1267
  if (!grab_index_)
 
1268
    grab_index_ = screen->pushGrab (screen->invisibleCursor(), "unity-switcher");
 
1269
  if (!grab_index_)
 
1270
    return false;
 
1271
 
 
1272
  if (!switcher_desktop_icon)
 
1273
  {
 
1274
    switcher_desktop_icon = new DesktopLauncherIcon(launcher);
 
1275
    switcher_desktop_icon->SinkReference();
 
1276
  }
 
1277
 
 
1278
  results.push_back(switcher_desktop_icon);
 
1279
 
 
1280
  LauncherModel::iterator it;
 
1281
  for (it = launcher->GetModel()->begin(); it != launcher->GetModel()->end(); it++)
 
1282
    if ((*it)->ShowInSwitcher())
 
1283
      results.push_back(*it);
 
1284
 
 
1285
  screen->addAction (&optionGetAltTabRight ());
 
1286
  screen->addAction (&optionGetAltTabDetailStart ());
 
1287
  screen->addAction (&optionGetAltTabDetailStop ());
 
1288
  screen->addAction (&optionGetAltTabLeft ());
 
1289
 
 
1290
  // maybe check launcher position/hide state?
 
1291
 
 
1292
  int device = screen->outputDeviceForPoint (pointerX, pointerY);
 
1293
  switcherController->SetWorkspace(nux::Geometry(screen->outputDevs()[device].x1() + 100,
 
1294
                                                 screen->outputDevs()[device].y1() + 100,
 
1295
                                                 screen->outputDevs()[device].width() - 200,
 
1296
                                                 screen->outputDevs()[device].height() - 200));
 
1297
  switcherController->Show(SwitcherController::ALL, SwitcherController::FOCUS_ORDER, false, results);
 
1298
  return true;
 
1299
}
 
1300
 
 
1301
bool UnityScreen::altTabTerminateCommon(CompAction* action,
 
1302
                                       CompAction::State state,
 
1303
                                       CompOption::Vector& options)
 
1304
{
 
1305
  if (grab_index_)
 
1306
  {
 
1307
    // remove grab before calling hide so workspace switcher doesn't fail
 
1308
    screen->removeGrab(grab_index_, NULL);
 
1309
    grab_index_ = 0;
 
1310
 
 
1311
    screen->removeAction (&optionGetAltTabRight ());
 
1312
    screen->removeAction (&optionGetAltTabDetailStart ());
 
1313
    screen->removeAction (&optionGetAltTabDetailStop ());
 
1314
    screen->removeAction (&optionGetAltTabLeft ());
 
1315
 
 
1316
    bool accept_state = (state & CompAction::StateCancel) == 0;
 
1317
    switcherController->Hide(accept_state);
 
1318
  }
 
1319
 
 
1320
  action->setState (action->state() & (unsigned)~(CompAction::StateTermKey));
 
1321
  return true;
 
1322
}
 
1323
 
 
1324
bool UnityScreen::altTabForwardInitiate(CompAction* action,
 
1325
                                        CompAction::State state,
 
1326
                                        CompOption::Vector& options)
 
1327
{
 
1328
  if (switcherController->Visible())
 
1329
    switcherController->Next();
 
1330
  else
 
1331
    altTabInitiateCommon(action, state, options);
 
1332
 
 
1333
  action->setState(action->state() | CompAction::StateTermKey);
 
1334
  return false;
 
1335
}
 
1336
 
 
1337
 
 
1338
bool UnityScreen::altTabPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
1339
{
 
1340
  if (switcherController->Visible())
 
1341
    switcherController->Prev();
 
1342
 
 
1343
  return false;
 
1344
}
 
1345
 
 
1346
bool UnityScreen::altTabDetailStartInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
1347
{
 
1348
  if (switcherController->Visible())
 
1349
    switcherController->SetDetail(true);
 
1350
 
 
1351
  return false;
 
1352
}
 
1353
 
 
1354
bool UnityScreen::altTabDetailStopInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
1355
{
 
1356
  if (switcherController->Visible())
 
1357
    switcherController->SetDetail(false);
 
1358
 
 
1359
  return false;
 
1360
}
 
1361
 
 
1362
bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
1363
{
 
1364
  if (!switcherController->Visible())
 
1365
  {
 
1366
    altTabInitiateCommon(action, state, options);
 
1367
    switcherController->Select(1); // always select the current application
 
1368
  }
 
1369
  
 
1370
  switcherController->NextDetail();
 
1371
 
 
1372
  action->setState(action->state() | CompAction::StateTermKey);
 
1373
  return false;
 
1374
}
 
1375
 
 
1376
bool UnityScreen::altTabPrevWindowInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options)
 
1377
{
 
1378
  if (switcherController->Visible())
 
1379
    switcherController->PrevDetail();
 
1380
  
 
1381
  return false;
 
1382
}
 
1383
 
 
1384
void UnityScreen::OnLauncherStartKeyNav(GVariant* data, void* value)
 
1385
{
 
1386
  UnityScreen* self = reinterpret_cast<UnityScreen*>(value);
 
1387
  self->startLauncherKeyNav();
 
1388
}
 
1389
 
 
1390
void UnityScreen::OnLauncherEndKeyNav(GVariant* data, void* value)
 
1391
{
 
1392
  bool preserve_focus = false;
 
1393
 
 
1394
  if (data)
 
1395
  {
 
1396
    preserve_focus = g_variant_get_boolean(data);
 
1397
  }
 
1398
 
 
1399
  // Return input-focus to previously focused window (before key-nav-mode was
 
1400
  // entered)
 
1401
  if (preserve_focus)
 
1402
    PluginAdapter::Default ()->restoreInputFocus ();
 
1403
}
 
1404
 
 
1405
void UnityScreen::OnQuicklistEndKeyNav(GVariant* data, void* value)
 
1406
{
 
1407
  UnityScreen* self = reinterpret_cast<UnityScreen*>(value);
 
1408
  self->restartLauncherKeyNav();
 
1409
}
 
1410
 
 
1411
gboolean UnityScreen::initPluginActions(gpointer data)
 
1412
{
 
1413
  CompPlugin* p = CompPlugin::find("expo");
 
1414
 
 
1415
  if (p)
 
1416
  {
 
1417
    MultiActionList expoActions(0);
 
1418
 
 
1419
    foreach(CompOption & option, p->vTable->getOptions())
 
1420
    {
 
1421
      if (option.name() == "expo_key" ||
 
1422
          option.name() == "expo_button" ||
 
1423
          option.name() == "expo_edge")
 
1424
      {
 
1425
        CompAction* action = &option.value().action();
 
1426
        expoActions.AddNewAction(action, false);
 
1427
        break;
 
1428
      }
 
1429
    }
 
1430
 
 
1431
    PluginAdapter::Default()->SetExpoAction(expoActions);
 
1432
  }
 
1433
 
 
1434
  p = CompPlugin::find("scale");
 
1435
 
 
1436
  if (p)
 
1437
  {
 
1438
    MultiActionList scaleActions(0);
 
1439
 
 
1440
    foreach(CompOption & option, p->vTable->getOptions())
 
1441
    {
 
1442
      if (option.name() == "initiate_all_key" ||
 
1443
          option.name() == "initiate_all_edge" ||
 
1444
          option.name() == "initiate_key" ||
 
1445
          option.name() == "initiate_button" ||
 
1446
          option.name() == "initiate_edge" ||
 
1447
          option.name() == "initiate_group_key" ||
 
1448
          option.name() == "initiate_group_button" ||
 
1449
          option.name() == "initiate_group_edge" ||
 
1450
          option.name() == "initiate_output_key" ||
 
1451
          option.name() == "initiate_output_button" ||
 
1452
          option.name() == "initiate_output_edge")
 
1453
      {
 
1454
        CompAction* action = &option.value().action();
 
1455
        scaleActions.AddNewAction(action, false);
 
1456
      }
 
1457
      else if (option.name() == "initiate_all_button")
 
1458
      {
 
1459
        CompAction* action = &option.value().action();
 
1460
        scaleActions.AddNewAction(action, true);
 
1461
      }
 
1462
    }
 
1463
 
 
1464
    PluginAdapter::Default()->SetScaleAction(scaleActions);
 
1465
  }
 
1466
 
 
1467
  p = CompPlugin::find("unitymtgrabhandles");
 
1468
 
 
1469
  if (p)
 
1470
  {
 
1471
    foreach(CompOption & option, p->vTable->getOptions())
 
1472
    {
 
1473
      if (option.name() == "show_handles_key")
 
1474
        PluginAdapter::Default()->SetShowHandlesAction(&option.value().action());
 
1475
      else if (option.name() == "hide_handles_key")
 
1476
        PluginAdapter::Default()->SetHideHandlesAction(&option.value().action());
 
1477
      else if (option.name() == "toggle_handles_key")
 
1478
        PluginAdapter::Default()->SetToggleHandlesAction(&option.value().action());
 
1479
    }
 
1480
  }
 
1481
 
 
1482
  return FALSE;
 
1483
}
 
1484
 
 
1485
/* Set up expo and scale actions on the launcher */
 
1486
bool UnityScreen::initPluginForScreen(CompPlugin* p)
 
1487
{
 
1488
  if (p->vTable->name() == "expo" ||
 
1489
      p->vTable->name() == "scale")
 
1490
  {
 
1491
    initPluginActions(this);
 
1492
  }
 
1493
 
 
1494
  bool result = screen->initPluginForScreen(p);
 
1495
  if (p->vTable->name() == "unityshell")
 
1496
    initAltTabNextWindow();
 
1497
    
 
1498
  return result;
 
1499
}
 
1500
 
 
1501
void UnityScreen::AddProperties(GVariantBuilder* builder)
 
1502
{
 
1503
}
 
1504
 
 
1505
const gchar* UnityScreen::GetName()
 
1506
{
 
1507
  return "Unity";
 
1508
}
 
1509
 
 
1510
bool isNuxWindow (CompWindow* value) 
 
1511
 
1512
  std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
 
1513
  auto id = value->id();
 
1514
 
 
1515
  // iterate loop by hand rather than use std::find as this is considerably faster
 
1516
  // we care about performance here becuase of the high frequency in which this function is
 
1517
  // called (nearly every frame)
 
1518
  unsigned int size = xwns.size();
 
1519
  for (unsigned int i = 0; i < size; ++i)
 
1520
  {
 
1521
    if (xwns[i] == id)
 
1522
      return true;
 
1523
  }
 
1524
  return false;
 
1525
}
 
1526
 
 
1527
const CompWindowList& UnityScreen::getWindowPaintList()
 
1528
{
 
1529
  CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList();
 
1530
  pl.remove_if(isNuxWindow);
 
1531
 
 
1532
  return pl;
 
1533
}
 
1534
 
 
1535
/* detect occlusions
 
1536
 *
 
1537
 * core passes down the PAINT_WINDOW_OCCLUSION_DETECTION
 
1538
 * mask when it is doing occlusion detection, so use that
 
1539
 * order to fill our occlusion buffer which we'll flip
 
1540
 * to nux later
 
1541
 */
 
1542
bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,
 
1543
                          const GLMatrix& matrix,
 
1544
                          const CompRegion& region,
 
1545
                          unsigned int mask)
 
1546
{
 
1547
  GLWindowPaintAttrib wAttrib = attrib;
 
1548
 
 
1549
  if (mMinimizeHandler)
 
1550
  {
 
1551
    typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow> minimized_window_handler_unity;
 
1552
 
 
1553
    compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::Ptr compizMinimizeHandler =
 
1554
        boost::dynamic_pointer_cast <minimized_window_handler_unity> (mMinimizeHandler);
 
1555
    mask |= compizMinimizeHandler->getPaintMask ();
 
1556
  }
 
1557
  else if (mShowdesktopHandler)
 
1558
  {
 
1559
    mShowdesktopHandler->paintAttrib (wAttrib);
 
1560
    mask |= mShowdesktopHandler->getPaintMask ();
 
1561
  }
 
1562
 
 
1563
  if (uScreen->panelController->GetTrayXid () == window->id () && !uScreen->allowWindowPaint)
 
1564
  {
 
1565
    if (!uScreen->painting_tray_)
 
1566
    {
 
1567
      uScreen->tray_paint_mask_ = mask;
 
1568
      mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
 
1569
    }
 
1570
  }
 
1571
 
 
1572
  return gWindow->glPaint(wAttrib, matrix, region, mask);
 
1573
}
 
1574
 
 
1575
/* handle window painting in an opengl context
 
1576
 *
 
1577
 * we want to paint underneath other windows here,
 
1578
 * so we need to find if this window is actually
 
1579
 * stacked on top of one of the nux input windows
 
1580
 * and if so paint nux and stop us from painting
 
1581
 * other windows or on top of the whole screen */
 
1582
bool UnityWindow::glDraw(const GLMatrix& matrix,
 
1583
                         GLFragment::Attrib& attrib,
 
1584
                         const CompRegion& region,
 
1585
                         unsigned int mask)
 
1586
{
 
1587
  if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ())
 
1588
  {
 
1589
    std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
 
1590
    unsigned int size = xwns.size();
 
1591
 
 
1592
    for (CompWindow* w = window; w && uScreen->doShellRepaint; w = w->prev)
 
1593
    {
 
1594
      auto id = w->id();
 
1595
      for (unsigned int i = 0; i < size; ++i)
 
1596
      {
 
1597
        if (xwns[i] == id)
 
1598
        {
 
1599
          uScreen->paintDisplay(region, matrix, mask);
 
1600
          break;
 
1601
        }
 
1602
      }
 
1603
    }
 
1604
  }
 
1605
 
 
1606
  bool ret = gWindow->glDraw(matrix, attrib, region, mask);
 
1607
 
 
1608
  if (window->type() == CompWindowTypeDesktopMask)
 
1609
  {
 
1610
    uScreen->paintPanelShadow(matrix);
 
1611
  }
 
1612
 
 
1613
  return ret;
 
1614
}
 
1615
 
 
1616
void
 
1617
UnityWindow::minimize ()
 
1618
{
 
1619
  if (!window->managed ())
 
1620
    return;
 
1621
 
 
1622
  if (!mMinimizeHandler)
 
1623
  {
 
1624
    mMinimizeHandler = compiz::MinimizedWindowHandler::Ptr (new compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow> (window));
 
1625
    mMinimizeHandler->minimize ();
 
1626
  }
 
1627
}
 
1628
 
 
1629
void
 
1630
UnityWindow::unminimize ()
 
1631
{
 
1632
  if (mMinimizeHandler)
 
1633
  {
 
1634
    mMinimizeHandler->unminimize ();
 
1635
    mMinimizeHandler.reset ();
 
1636
  }
 
1637
}
 
1638
 
 
1639
bool
 
1640
UnityWindow::focus ()
 
1641
{
 
1642
  if (!mMinimizeHandler.get ())
 
1643
    return window->focus ();
 
1644
 
 
1645
  if (window->overrideRedirect ())
 
1646
    return false;
 
1647
 
 
1648
  if (!window->managed ())
 
1649
    return false;
 
1650
 
 
1651
  if (!window->onCurrentDesktop ())
 
1652
    return false;
 
1653
 
 
1654
  /* Only withdrawn windows 
 
1655
   * which are marked hidden
 
1656
   * are excluded */
 
1657
  if (!window->shaded () &&
 
1658
      !window->minimized () &&
 
1659
      (window->state () & CompWindowStateHiddenMask))
 
1660
    return false;
 
1661
 
 
1662
  if (window->geometry ().x () + window->geometry ().width ()  <= 0     ||
 
1663
      window->geometry ().y () + window->geometry ().height () <= 0     ||
 
1664
      window->geometry ().x () >= (int) screen->width ()||
 
1665
      window->geometry ().y () >= (int) screen->height ())
 
1666
    return false;
 
1667
 
 
1668
  return true;
 
1669
}
 
1670
 
 
1671
bool
 
1672
UnityWindow::minimized ()
 
1673
{
 
1674
  return mMinimizeHandler.get () != NULL;
 
1675
}
 
1676
 
 
1677
gboolean
 
1678
UnityWindow::FocusDesktopTimeout(gpointer data)
 
1679
{
 
1680
  UnityWindow *self = reinterpret_cast<UnityWindow*>(data);
 
1681
 
 
1682
  self->focusdesktop_handle_ = 0;
 
1683
 
 
1684
  for (CompWindow *w : screen->clientList ())
 
1685
  {
 
1686
    if (!(w->type() & NO_FOCUS_MASK) && w->focus ())
 
1687
      return FALSE;
 
1688
  }
 
1689
  self->window->moveInputFocusTo();
 
1690
 
 
1691
  return FALSE;
 
1692
}
 
1693
 
 
1694
/* Called whenever a window is mapped, unmapped, minimized etc */
 
1695
void UnityWindow::windowNotify(CompWindowNotify n)
 
1696
{
 
1697
  PluginAdapter::Default()->Notify(window, n);
 
1698
 
 
1699
  switch (n)
 
1700
  {
 
1701
    case CompWindowNotifyMap:
 
1702
      if (window->type() == CompWindowTypeDesktopMask) {
 
1703
        if (!focusdesktop_handle_)
 
1704
           focusdesktop_handle_ = g_timeout_add (1000, &UnityWindow::FocusDesktopTimeout, this);
 
1705
      }
 
1706
      break;
 
1707
    case CompWindowNotifyUnmap:
 
1708
      if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
 
1709
          window->mapNum ())
 
1710
      {
 
1711
        bool wasMinimized = window->minimized ();
 
1712
        if (wasMinimized)
 
1713
          window->unminimize ();
 
1714
        window->focusSetEnabled (this, true);
 
1715
        window->minimizeSetEnabled (this, true);
 
1716
        window->unminimizeSetEnabled (this, true);
 
1717
        window->minimizedSetEnabled (this, true);
 
1718
 
 
1719
        if (wasMinimized)
 
1720
          window->minimize ();
 
1721
      }
 
1722
      else
 
1723
      {
 
1724
        window->focusSetEnabled (this, false);
 
1725
        window->minimizeSetEnabled (this, false);
 
1726
        window->unminimizeSetEnabled (this, false);
 
1727
        window->minimizedSetEnabled (this, false);
 
1728
      }
 
1729
        break;
 
1730
      default:
 
1731
        break;
 
1732
  }
 
1733
 
 
1734
 
 
1735
  window->windowNotify(n);
 
1736
 
 
1737
  if (mMinimizeHandler.get () != NULL)
 
1738
  {
 
1739
    /* The minimize handler will short circuit the frame
 
1740
     * region update func and ensure that the frame
 
1741
     * does not have a region */
 
1742
    typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow> minimized_window_handler_unity;
 
1743
 
 
1744
    compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::Ptr compizMinimizeHandler =
 
1745
        boost::dynamic_pointer_cast <minimized_window_handler_unity> (mMinimizeHandler);
 
1746
    compizMinimizeHandler->windowNotify (n);
 
1747
  }
 
1748
  else if (mShowdesktopHandler)
 
1749
  {
 
1750
    mShowdesktopHandler->windowNotify (n);
 
1751
  }
 
1752
 
 
1753
  // We do this after the notify to ensure input focus has actually been moved.
 
1754
  if (n == CompWindowNotifyFocusChange)
 
1755
  {
 
1756
    UnityScreen* us = UnityScreen::get(screen);
 
1757
    CompWindow *lw;
 
1758
    
 
1759
    if (us->dash_is_open_)
 
1760
    {
 
1761
      lw = screen->findWindow(us->launcherWindow->GetInputWindowId());
 
1762
      lw->moveInputFocusTo();
 
1763
    }
 
1764
  }
 
1765
}
 
1766
 
 
1767
void UnityWindow::stateChangeNotify(unsigned int lastState)
 
1768
{
 
1769
  if (window->state () & CompWindowStateFullscreenMask &&
 
1770
      !(lastState & CompWindowStateFullscreenMask))
 
1771
    UnityScreen::get (screen)->fullscreen_windows_.push_back(window);
 
1772
  else if (lastState & CompWindowStateFullscreenMask &&
 
1773
           !(window->state () & CompWindowStateFullscreenMask))
 
1774
    UnityScreen::get (screen)->fullscreen_windows_.remove(window);
 
1775
 
 
1776
  PluginAdapter::Default()->NotifyStateChange(window, window->state(), lastState);
 
1777
  window->stateChangeNotify(lastState);
 
1778
}
 
1779
 
 
1780
void UnityWindow::updateFrameRegion(CompRegion &region)
 
1781
{
 
1782
  /* The minimize handler will short circuit the frame
 
1783
   * region update func and ensure that the frame
 
1784
   * does not have a region */
 
1785
  typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow> minimized_window_handler_unity;
 
1786
 
 
1787
  compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::Ptr compizMinimizeHandler =
 
1788
      boost::dynamic_pointer_cast <minimized_window_handler_unity> (mMinimizeHandler);
 
1789
 
 
1790
  if (compizMinimizeHandler)
 
1791
    compizMinimizeHandler->updateFrameRegion (region);
 
1792
  else if (mShowdesktopHandler)
 
1793
    mShowdesktopHandler->updateFrameRegion (region);
 
1794
  else
 
1795
    window->updateFrameRegion (region);
 
1796
}
 
1797
 
 
1798
void UnityWindow::moveNotify(int x, int y, bool immediate)
 
1799
{
 
1800
  PluginAdapter::Default()->NotifyMoved(window, x, y);
 
1801
  window->moveNotify(x, y, immediate);
 
1802
}
 
1803
 
 
1804
void UnityWindow::resizeNotify(int x, int y, int w, int h)
 
1805
{
 
1806
  PluginAdapter::Default()->NotifyResized(window, x, y, w, h);
 
1807
  window->resizeNotify(x, y, w, h);
 
1808
}
 
1809
 
 
1810
CompPoint UnityWindow::tryNotIntersectUI(CompPoint& pos)
 
1811
{
 
1812
  UnityScreen* us = UnityScreen::get(screen);
 
1813
  Launcher::LauncherHideMode hideMode = us->launcher->GetHideMode();
 
1814
  nux::Geometry geo = us->launcher->GetAbsoluteGeometry();
 
1815
  CompRegion allowedWorkArea (screen->workArea ());
 
1816
  CompRect launcherGeo(geo.x, geo.y, geo.width, geo.height);
 
1817
  CompRegion wRegion (window->borderRect ());
 
1818
  CompRegion intRegion;
 
1819
 
 
1820
  wRegion.translate (pos.x () - wRegion.boundingRect ().x (),
 
1821
                     pos.y () - wRegion.boundingRect ().y ());
 
1822
 
 
1823
  /* subtract launcher and panel geometries from allowed workarea */
 
1824
  if (!us->launcher->Hidden ())
 
1825
  {
 
1826
    switch (hideMode)
 
1827
    {
 
1828
      case Launcher::LAUNCHER_HIDE_DODGE_WINDOWS:
 
1829
      case Launcher::LAUNCHER_HIDE_DODGE_ACTIVE_WINDOW:
 
1830
        allowedWorkArea -= launcherGeo;
 
1831
        break;
 
1832
 
 
1833
      default:
 
1834
        break;
 
1835
    }
 
1836
  }
 
1837
 
 
1838
  for (nux::Geometry &g : us->panelController->GetGeometries ())
 
1839
  {
 
1840
    CompRect pg (g.x, g.y, g.width, g.height);
 
1841
    allowedWorkArea -= pg;
 
1842
  }
 
1843
 
 
1844
  /* Invert allowed work area */
 
1845
  allowedWorkArea = CompRegion (screen->workArea ()) - allowedWorkArea;
 
1846
 
 
1847
  /* Now intersect the window region with the allowed work area
 
1848
   * region, such that it splits up into a number of rects */
 
1849
  intRegion = wRegion.intersected (allowedWorkArea);
 
1850
 
 
1851
  if (intRegion.rects ().size () > 1)
 
1852
  {
 
1853
    /* Now find the largest rect, this will be the area that we want to move to */
 
1854
    CompRect largest;
 
1855
 
 
1856
    for (CompRect &r : intRegion.rects ())
 
1857
    {
 
1858
      if (r.area () > largest.area ())
 
1859
        largest = r;
 
1860
    }
 
1861
 
 
1862
    /* Now pad the largest rect with the other rectangles that
 
1863
     * were intersecting, padding the opposite side to the one
 
1864
     * that they are currently on on the large rect
 
1865
     */
 
1866
 
 
1867
    intRegion -= largest;
 
1868
 
 
1869
    for (CompRect &r : intRegion.rects ())
 
1870
    {
 
1871
      if (r.x1 () > largest.x2 ())
 
1872
        largest.setX (largest.x () - r.width ());
 
1873
      else if (r.x2 () < largest.x ())
 
1874
        largest.setWidth (largest.width () + r.width ());
 
1875
 
 
1876
      if (r.y1 () > largest.y2 ())
 
1877
        largest.setY (largest.y () - r.height ());
 
1878
      else if (r.y2 () < largest.y ())
 
1879
        largest.setWidth (largest.height () + r.height ());
 
1880
    }
 
1881
 
 
1882
    pos = largest.pos ();
 
1883
  }
 
1884
 
 
1885
  if (launcherGeo.contains(pos))
 
1886
    pos.setX(launcherGeo.x() + launcherGeo.width() + 1);
 
1887
 
 
1888
  return pos;
 
1889
}
 
1890
 
 
1891
bool UnityWindow::place(CompPoint& pos)
 
1892
{
 
1893
  bool result = window->place(pos);
 
1894
 
 
1895
  if (window->type() & NO_FOCUS_MASK)
 
1896
    return result;
 
1897
 
 
1898
  pos = tryNotIntersectUI(pos);
 
1899
  return result;
 
1900
}
 
1901
 
 
1902
/* Configure callback for the launcher window */
 
1903
void UnityScreen::launcherWindowConfigureCallback(int WindowWidth, int WindowHeight,
 
1904
                                                  nux::Geometry& geo, void* user_data)
 
1905
{
 
1906
  UnityScreen* self = reinterpret_cast<UnityScreen*>(user_data);
 
1907
  geo = nux::Geometry(self->_primary_monitor.x, self->_primary_monitor.y + 24,
 
1908
                      geo.width, self->_primary_monitor.height - 24);
 
1909
}
 
1910
 
 
1911
/* Start up nux after OpenGL is initialized */
 
1912
void UnityScreen::initUnity(nux::NThread* thread, void* InitData)
 
1913
{
 
1914
  Timer timer;
 
1915
  initLauncher(thread, InitData);
 
1916
 
 
1917
  nux::ColorLayer background(nux::color::Transparent);
 
1918
  static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
 
1919
  LOG_INFO(logger) << "UnityScreen::initUnity: " << timer.ElapsedSeconds() << "s";
 
1920
}
 
1921
 
 
1922
gboolean UnityScreen::OnRedrawTimeout(gpointer data)
 
1923
{
 
1924
  UnityScreen *self = reinterpret_cast<UnityScreen*>(data);
 
1925
 
 
1926
  self->_redraw_handle = 0;
 
1927
  self->onRedrawRequested();
 
1928
 
 
1929
  return FALSE;
 
1930
}
 
1931
 
 
1932
void UnityScreen::onRedrawRequested()
 
1933
{
 
1934
  // disable blur updates so we dont waste perf. This can stall the blur during animations
 
1935
  // but ensures a smooth animation.
 
1936
  if (_in_paint)
 
1937
  {
 
1938
    if (!_redraw_handle)
 
1939
      _redraw_handle = g_timeout_add (0, &UnityScreen::OnRedrawTimeout, this);
 
1940
  }
 
1941
  else
 
1942
  {
 
1943
    damageNuxRegions();
 
1944
  }
 
1945
}
 
1946
 
 
1947
/* Handle option changes and plug that into nux windows */
 
1948
void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num)
 
1949
{
 
1950
  switch (num)
 
1951
  {
 
1952
    case UnityshellOptions::LauncherHideMode:
 
1953
      launcher->SetHideMode((Launcher::LauncherHideMode) optionGetLauncherHideMode());
 
1954
      break;
 
1955
    case UnityshellOptions::BacklightMode:
 
1956
      launcher->SetBacklightMode((Launcher::BacklightMode) optionGetBacklightMode());
 
1957
      break;
 
1958
    case UnityshellOptions::LaunchAnimation:
 
1959
      launcher->SetLaunchAnimation((Launcher::LaunchAnimation) optionGetLaunchAnimation());
 
1960
      break;
 
1961
    case UnityshellOptions::UrgentAnimation:
 
1962
      launcher->SetUrgentAnimation((Launcher::UrgentAnimation) optionGetUrgentAnimation());
 
1963
      break;
 
1964
    case UnityshellOptions::PanelOpacity:
 
1965
      panelController->SetOpacity(optionGetPanelOpacity());
 
1966
      break;
 
1967
    case UnityshellOptions::LauncherOpacity:
 
1968
      launcher->SetBackgroundAlpha(optionGetLauncherOpacity());
 
1969
      break;
 
1970
    case UnityshellOptions::IconSize:
 
1971
    {
 
1972
      CompPlugin         *p = CompPlugin::find ("expo");
 
1973
 
 
1974
      launcher->SetIconSize(optionGetIconSize() + 6, optionGetIconSize());
 
1975
      dashController->launcher_width = optionGetIconSize() + 18;
 
1976
 
 
1977
      if (p)
 
1978
      {
 
1979
        CompOption::Vector &opts = p->vTable->getOptions ();
 
1980
 
 
1981
        for (CompOption &o : opts)
 
1982
        {
 
1983
          if (o.name () == std::string ("x_offset"))
 
1984
          {
 
1985
            CompOption::Value v;
 
1986
            v.set (static_cast <int> (optionGetIconSize() + 18));
 
1987
 
 
1988
            screen->setOptionForPlugin (p->vTable->name ().c_str (), o.name ().c_str (), v);
 
1989
            break;
 
1990
          }
 
1991
        }
 
1992
      }
 
1993
      break;
 
1994
    }
 
1995
    case UnityshellOptions::AutohideAnimation:
 
1996
      launcher->SetAutoHideAnimation((Launcher::AutoHideAnimation) optionGetAutohideAnimation());
 
1997
      break;
 
1998
    case UnityshellOptions::DashBlurExperimental:
 
1999
      BackgroundEffectHelper::blur_type = (unity::BlurType)optionGetDashBlurExperimental();
 
2000
      break;
 
2001
    case UnityshellOptions::AutomaximizeValue:
 
2002
      PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);
 
2003
      break;
 
2004
    case UnityshellOptions::DevicesOption:
 
2005
      unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption());
 
2006
      break;
 
2007
    case UnityshellOptions::LauncherRevealEdgeTimeout:
 
2008
      _edge_timeout = optionGetLauncherRevealEdgeTimeout();
 
2009
      break;
 
2010
    case UnityshellOptions::AltTabTimeout:
 
2011
      switcherController->detail_on_timeout = optionGetAltTabTimeout();
 
2012
    case UnityshellOptions::AltTabBiasViewport:
 
2013
      PluginAdapter::Default()->bias_active_to_viewport = optionGetAltTabBiasViewport();
 
2014
      break;
 
2015
    case UnityshellOptions::ShowMinimizedWindows:
 
2016
      compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::setFunctions (optionGetShowMinimizedWindows ());
 
2017
      screen->enterShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
 
2018
      screen->leaveShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
 
2019
      break;
 
2020
    default:
 
2021
      break;
 
2022
  }
 
2023
}
 
2024
 
 
2025
void UnityScreen::NeedsRelayout()
 
2026
{
 
2027
  needsRelayout = true;
 
2028
}
 
2029
 
 
2030
void UnityScreen::ScheduleRelayout(guint timeout)
 
2031
{
 
2032
  if (relayoutSourceId == 0)
 
2033
    relayoutSourceId = g_timeout_add(timeout, &UnityScreen::RelayoutTimeout, this);
 
2034
}
 
2035
 
 
2036
void UnityScreen::Relayout()
 
2037
{
 
2038
  GdkRectangle rect;
 
2039
  nux::Geometry lCurGeom;
 
2040
  int panel_height = 24;
 
2041
 
 
2042
  if (!needsRelayout)
 
2043
    return;
 
2044
 
 
2045
  if (GL::fbo)
 
2046
  {
 
2047
    foreach (CompOutput &o, screen->outputDevs ())
 
2048
      uScreen->mFbos[&o] = UnityFBO::Ptr (new UnityFBO (&o));
 
2049
 
 
2050
    uScreen->mFbos[&(screen->fullscreenOutput ())] = UnityFBO::Ptr (new UnityFBO (&(screen->fullscreenOutput ())));
 
2051
  }
 
2052
 
 
2053
  UScreen *uscreen = UScreen::GetDefault();
 
2054
  int primary_monitor = uscreen->GetPrimaryMonitor();
 
2055
  auto geo = uscreen->GetMonitorGeometry(primary_monitor);
 
2056
 
 
2057
  rect.x = geo.x;
 
2058
  rect.y = geo.y;
 
2059
  rect.width = geo.width;
 
2060
  rect.height = geo.height;
 
2061
  _primary_monitor = rect;
 
2062
 
 
2063
  wt->SetWindowSize(rect.width, rect.height);
 
2064
 
 
2065
  lCurGeom = launcherWindow->GetGeometry();
 
2066
  launcher->SetMaximumHeight(rect.height - panel_height);
 
2067
 
 
2068
  g_debug("Setting to primary screen rect: x=%d y=%d w=%d h=%d",
 
2069
          rect.x,
 
2070
          rect.y,
 
2071
          rect.width,
 
2072
          rect.height);
 
2073
 
 
2074
  launcherWindow->SetGeometry(nux::Geometry(rect.x,
 
2075
                                            rect.y + panel_height,
 
2076
                                            lCurGeom.width,
 
2077
                                            rect.height - panel_height));
 
2078
  launcher->SetGeometry(nux::Geometry(rect.x,
 
2079
                                      rect.y + panel_height,
 
2080
                                      lCurGeom.width,
 
2081
                                      rect.height - panel_height));
 
2082
  needsRelayout = false;
 
2083
}
 
2084
 
 
2085
gboolean UnityScreen::RelayoutTimeout(gpointer data)
 
2086
{
 
2087
  UnityScreen* uScr = reinterpret_cast<UnityScreen*>(data);
 
2088
 
 
2089
  uScreen->mFbos.clear ();
 
2090
 
 
2091
  uScr->NeedsRelayout ();
 
2092
  uScr->Relayout();
 
2093
  uScr->relayoutSourceId = 0;
 
2094
 
 
2095
  uScr->cScreen->damageScreen();
 
2096
 
 
2097
  return FALSE;
 
2098
}
 
2099
 
 
2100
/* Handle changes in the number of workspaces by showing the switcher
 
2101
 * or not showing the switcher */
 
2102
bool UnityScreen::setOptionForPlugin(const char* plugin, const char* name,
 
2103
                                     CompOption::Value& v)
 
2104
{
 
2105
  bool status = screen->setOptionForPlugin(plugin, name, v);
 
2106
  if (status)
 
2107
  {
 
2108
    if (strcmp(plugin, "core") == 0 && strcmp(name, "hsize") == 0)
 
2109
    {
 
2110
      controller->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
 
2111
    }
 
2112
  }
 
2113
  return status;
 
2114
}
 
2115
 
 
2116
void UnityScreen::outputChangeNotify()
 
2117
{
 
2118
  screen->outputChangeNotify ();
 
2119
 
 
2120
  ScheduleRelayout(500);
 
2121
}
 
2122
 
 
2123
void UnityFBO::paint ()
 
2124
{
 
2125
  //CompositeScreen *cScreen = CompositeScreen::get (screen);
 
2126
  //unsigned int    mask = cScreen->damageMask ();
 
2127
  float texx, texy, texwidth, texheight;
 
2128
 
 
2129
  /* Must be completely unbound before painting */
 
2130
  if (mBoundCnt)
 
2131
    return;
 
2132
 
 
2133
  /* Draw the bit of the relevant framebuffer for each output */
 
2134
  GLMatrix transform;
 
2135
 
 
2136
  glViewport (output->x (), screen->height () - output->y2 (), output->width (), output->height ());
 
2137
  GLScreen::get (screen)->clearOutput (output, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
2138
 
 
2139
  transform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
 
2140
  glPushMatrix ();
 
2141
  glLoadMatrixf (transform.getMatrix ());
 
2142
 
 
2143
  /* Note that texcoords here are normalized, so it's just (0,0)-(1,1) */
 
2144
  texx = 0.0;
 
2145
  texy = 0.0;
 
2146
  texwidth = 1.0f;
 
2147
  texheight = 1.0f;
 
2148
 
 
2149
  if (mFBTexture)
 
2150
  {
 
2151
    glEnable (GL_TEXTURE_2D);
 
2152
    GL::activeTexture (GL_TEXTURE0_ARB);
 
2153
    glBindTexture (GL_TEXTURE_2D, mFBTexture);
 
2154
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
2155
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
2156
 
 
2157
    glPushAttrib (GL_SCISSOR_BIT);
 
2158
    glEnable (GL_SCISSOR_TEST);
 
2159
 
 
2160
    glScissor (output->x1 (), screen->height () - output->y2 (),
 
2161
               output->width (), output->height ());
 
2162
 
 
2163
    /* FIXME: This needs to be GL_TRIANGLE_STRIP */
 
2164
    glBegin (GL_QUADS);
 
2165
    glTexCoord2f (texx, texy + texheight);
 
2166
    glVertex2i   (output->x1 (), output->y1 ());
 
2167
    glTexCoord2f (texx, texy);
 
2168
    glVertex2i   (output->x1 (), output->y2 ());
 
2169
    glTexCoord2f (texx + texwidth, texy);
 
2170
    glVertex2i   (output->x2 (), output->y2 ());
 
2171
    glTexCoord2f (texx + texwidth, texy + texheight);
 
2172
    glVertex2i   (output->x2 (),  output->y1 ());
 
2173
    glEnd ();
 
2174
 
 
2175
    GL::activeTexture (GL_TEXTURE0_ARB);
 
2176
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
2177
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
2178
    glBindTexture (GL_TEXTURE_2D, 0);
 
2179
    glEnable (GL_TEXTURE_2D);
 
2180
 
 
2181
    glDisable (GL_SCISSOR_TEST);
 
2182
    glPopAttrib ();
 
2183
  }
 
2184
 
 
2185
  glPopMatrix();
 
2186
}
 
2187
 
 
2188
void UnityFBO::unbind ()
 
2189
{
 
2190
  mBoundCnt--;
 
2191
 
 
2192
  if (mBoundCnt)
 
2193
    return;
 
2194
 
 
2195
  uScreen->setActiveFbo (0);
 
2196
  (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
 
2197
 
 
2198
  glDrawBuffer (GL_BACK);
 
2199
  glReadBuffer (GL_BACK);
 
2200
 
 
2201
}
 
2202
 
 
2203
bool UnityFBO::bound ()
 
2204
{
 
2205
  return mBoundCnt > 0;
 
2206
}
 
2207
 
 
2208
bool UnityFBO::status ()
 
2209
{
 
2210
  return mFboStatus;
 
2211
}
 
2212
 
 
2213
void UnityFBO::bind ()
 
2214
{
 
2215
  if (mBoundCnt)
 
2216
  {
 
2217
    mBoundCnt++;
 
2218
    return;
 
2219
  }
 
2220
 
 
2221
  if (!mFBTexture)
 
2222
  {
 
2223
    glGenTextures (1, &mFBTexture);
 
2224
 
 
2225
    glBindTexture (GL_TEXTURE_2D, mFBTexture);
 
2226
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
2227
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
2228
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
2229
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
2230
    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, output->width(), output->height(), 0, GL_BGRA,
 
2231
#if IMAGE_BYTE_ORDER == MSBFirst
 
2232
                 GL_UNSIGNED_INT_8_8_8_8_REV,
 
2233
#else
 
2234
                 GL_UNSIGNED_BYTE,
 
2235
#endif
 
2236
                 NULL);
 
2237
 
 
2238
    glBindTexture (GL_TEXTURE_2D, 0);
 
2239
  }
 
2240
 
 
2241
  glGetError ();
 
2242
 
 
2243
  (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
 
2244
 
 
2245
  (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 
2246
                               GL_TEXTURE_2D, mFBTexture, 0);
 
2247
 
 
2248
  (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
 
2249
                               GL_TEXTURE_2D, 0, 0);
 
2250
 
 
2251
  /* Ensure that a framebuffer is actually available */
 
2252
  if (!mFboStatus)
 
2253
  {
 
2254
    GLint status = (*GL::checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
 
2255
 
 
2256
    if (status != GL_FRAMEBUFFER_COMPLETE)
 
2257
    {
 
2258
      switch (status)
 
2259
      {
 
2260
        case GL_FRAMEBUFFER_UNDEFINED:
 
2261
          compLogMessage ("unity", CompLogLevelWarn, "no window");
 
2262
          break;
 
2263
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
 
2264
          compLogMessage ("unity", CompLogLevelWarn, "attachment incomplete");
 
2265
          break;
 
2266
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
 
2267
          compLogMessage ("unity", CompLogLevelWarn, "no buffers attached to fbo");
 
2268
          break;
 
2269
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
 
2270
          compLogMessage ("unity", CompLogLevelWarn, "some attachment in glDrawBuffers doesn't exist in FBO");
 
2271
          break;
 
2272
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
 
2273
          compLogMessage ("unity", CompLogLevelWarn, "some attachment in glReadBuffers doesn't exist in FBO");
 
2274
          break;
 
2275
        case GL_FRAMEBUFFER_UNSUPPORTED:
 
2276
          compLogMessage ("unity", CompLogLevelWarn, "unsupported internal format");
 
2277
          break;
 
2278
        case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
 
2279
          compLogMessage ("unity", CompLogLevelWarn, "different levels of sampling for each attachment");
 
2280
          break;
 
2281
        case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
 
2282
          compLogMessage ("unity", CompLogLevelWarn, "number of layers is different");
 
2283
          break;
 
2284
        default:
 
2285
          compLogMessage ("unity", CompLogLevelWarn, "unable to bind the framebuffer for an unknown reason");
 
2286
          break;
 
2287
      }
 
2288
 
 
2289
      GL::bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
 
2290
      GL::deleteFramebuffers (1, &mFboHandle);
 
2291
 
 
2292
      glDrawBuffer (GL_BACK);
 
2293
      glReadBuffer (GL_BACK);
 
2294
 
 
2295
      mFboHandle = 0;
 
2296
 
 
2297
      mFboStatus = false;
 
2298
      uScreen->setActiveFbo (0);
 
2299
    }
 
2300
    else
 
2301
      mFboStatus = true;
 
2302
  }
 
2303
 
 
2304
  if (mFboStatus)
 
2305
  {
 
2306
    uScreen->setActiveFbo (mFboHandle);
 
2307
 
 
2308
    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
 
2309
    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
 
2310
 
 
2311
    glViewport (0,
 
2312
               0,
 
2313
               output->width(),
 
2314
               output->height());
 
2315
 
 
2316
    mBoundCnt++;
 
2317
  }
 
2318
}
 
2319
 
 
2320
UnityFBO::UnityFBO (CompOutput *o)
 
2321
 : mFboStatus (false)
 
2322
 , mFBTexture (0)
 
2323
 , output (o)
 
2324
 , mBoundCnt (0)
 
2325
{
 
2326
  (*GL::genFramebuffers) (1, &mFboHandle);
 
2327
}
 
2328
 
 
2329
UnityFBO::~UnityFBO ()
 
2330
{
 
2331
  (*GL::deleteFramebuffers) (1, &mFboHandle);
 
2332
 
 
2333
  if (mFBTexture)
 
2334
    glDeleteTextures (1, &mFBTexture);
 
2335
}
 
2336
 
 
2337
/* Start up the launcher */
 
2338
void UnityScreen::initLauncher(nux::NThread* thread, void* InitData)
 
2339
{
 
2340
  Timer timer;
 
2341
  UnityScreen* self = reinterpret_cast<UnityScreen*>(InitData);
 
2342
 
 
2343
  self->launcherWindow = new nux::BaseWindow(TEXT("LauncherWindow"));
 
2344
  self->launcherWindow->SinkReference();
 
2345
 
 
2346
  self->launcher = new Launcher(self->launcherWindow);
 
2347
  self->launcher->display = self->screen->dpy();
 
2348
  self->launcher->hidden_changed.connect(sigc::mem_fun(self, &UnityScreen::OnLauncherHiddenChanged));
 
2349
 
 
2350
  self->AddChild(self->launcher);
 
2351
 
 
2352
  nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
 
2353
  layout->AddView(self->launcher, 1);
 
2354
  layout->SetContentDistribution(nux::eStackLeft);
 
2355
  layout->SetVerticalExternalMargin(0);
 
2356
  layout->SetHorizontalExternalMargin(0);
 
2357
 
 
2358
  self->controller = new LauncherController(self->launcher);
 
2359
 
 
2360
  self->launcherWindow->SetConfigureNotifyCallback(&UnityScreen::launcherWindowConfigureCallback, self);
 
2361
  self->launcherWindow->SetLayout(layout);
 
2362
  self->launcherWindow->SetBackgroundColor(nux::Color(0x00000000));
 
2363
  self->launcherWindow->ShowWindow(true);
 
2364
  self->launcherWindow->EnableInputWindow(true, "launcher", false, false);
 
2365
  self->launcherWindow->InputWindowEnableStruts(true);
 
2366
  self->launcherWindow->SetEnterFocusInputArea(self->launcher);
 
2367
 
 
2368
  self->switcherController = new SwitcherController();
 
2369
  /* FIXME: this should not be manual, should be managed with a
 
2370
     show/hide callback like in GAIL*/
 
2371
  if (unity_a11y_initialized () == TRUE)
 
2372
    {
 
2373
      AtkObject *atk_obj = NULL;
 
2374
 
 
2375
      atk_obj = unity_util_accessible_add_window (self->launcherWindow);
 
2376
 
 
2377
      atk_object_set_name (atk_obj, _("Launcher"));
 
2378
    }
 
2379
 
 
2380
  self->launcher->SetIconSize(54, 48);
 
2381
  self->launcher->SetBacklightMode(Launcher::BACKLIGHT_ALWAYS_ON);
 
2382
 
 
2383
  LOG_INFO(logger) << "initLauncher-Launcher " << timer.ElapsedSeconds() << "s";
 
2384
 
 
2385
  /* Setup panel */
 
2386
  timer.Reset();
 
2387
  self->panelController = new PanelController();
 
2388
  self->AddChild(self->panelController);
 
2389
  LOG_INFO(logger) << "initLauncher-Panel " << timer.ElapsedSeconds() << "s";
 
2390
 
 
2391
  /* Setup Places */
 
2392
  self->dashController = DashController::Ptr(new DashController());
 
2393
 
 
2394
  /* FIXME: this should not be manual, should be managed with a
 
2395
     show/hide callback like in GAIL
 
2396
  if (unity_a11y_initialized() == TRUE)
 
2397
  {
 
2398
    AtkObject* atk_obj = NULL;
 
2399
 
 
2400
    atk_obj = unity_util_accessible_add_window(self->placesController->GetWindow());
 
2401
 
 
2402
    atk_object_set_name(atk_obj, _("Places"));
 
2403
  }
 
2404
  */
 
2405
 
 
2406
  self->launcher->SetHideMode(Launcher::LAUNCHER_HIDE_DODGE_WINDOWS);
 
2407
  self->launcher->SetLaunchAnimation(Launcher::LAUNCH_ANIMATION_PULSE);
 
2408
  self->launcher->SetUrgentAnimation(Launcher::URGENT_ANIMATION_WIGGLE);
 
2409
  self->ScheduleRelayout(0);
 
2410
 
 
2411
  self->OnLauncherHiddenChanged();
 
2412
}
 
2413
 
 
2414
/* Window init */
 
2415
UnityWindow::UnityWindow(CompWindow* window)
 
2416
  : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
 
2417
  , PluginClassHandler<UnityWindow, CompWindow>(window)
 
2418
  , window(window)
 
2419
  , gWindow(GLWindow::get(window))
 
2420
  , mShowdesktopHandler(nullptr)
 
2421
  , focusdesktop_handle_(0)
 
2422
{
 
2423
  WindowInterface::setHandler(window);
 
2424
  GLWindowInterface::setHandler(gWindow);
 
2425
 
 
2426
  if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
 
2427
      window->mapNum ())
 
2428
  {
 
2429
    bool wasMinimized = window->minimized ();
 
2430
    if (wasMinimized)
 
2431
      window->unminimize ();
 
2432
    window->minimizeSetEnabled (this, true);
 
2433
    window->unminimizeSetEnabled (this, true);
 
2434
    window->minimizedSetEnabled (this, true);
 
2435
 
 
2436
    if (wasMinimized)
 
2437
      window->minimize ();
 
2438
  }
 
2439
  else
 
2440
  {
 
2441
    window->minimizeSetEnabled (this, false);
 
2442
    window->unminimizeSetEnabled (this, false);
 
2443
    window->minimizedSetEnabled (this, false);
 
2444
  }
 
2445
 
 
2446
  if (window->state () & CompWindowStateFullscreenMask)
 
2447
    UnityScreen::get (screen)->fullscreen_windows_.push_back(window);
 
2448
  
 
2449
  if (window->resName() == "onboard")
 
2450
  {
 
2451
    Window xid = UnityScreen::get (screen)->dashController->window()->GetInputWindowId();
 
2452
    XSetTransientForHint (screen->dpy(), window->id(), xid);
 
2453
  }
 
2454
}
 
2455
 
 
2456
UnityWindow::~UnityWindow()
 
2457
{
 
2458
  UnityScreen* us = UnityScreen::get(screen);
 
2459
  if (us->newFocusedWindow && (UnityWindow::get(us->newFocusedWindow) == this))
 
2460
    us->newFocusedWindow = NULL;
 
2461
 
 
2462
  UnityShowdesktopHandler::animating_windows.remove (window);
 
2463
 
 
2464
  if (mMinimizeHandler)
 
2465
  {
 
2466
    unminimize ();
 
2467
    window->focusSetEnabled (this, false);
 
2468
    window->minimizeSetEnabled (this, false);
 
2469
    window->unminimizeSetEnabled (this, false);
 
2470
    window->minimizedSetEnabled (this, false);
 
2471
    window->minimize ();
 
2472
 
 
2473
    mMinimizeHandler.reset ();
 
2474
  }
 
2475
  if (mShowdesktopHandler)
 
2476
    delete mShowdesktopHandler;
 
2477
    
 
2478
  if (focusdesktop_handle_)
 
2479
    g_source_remove(focusdesktop_handle_);
 
2480
 
 
2481
  if (window->state () & CompWindowStateFullscreenMask)
 
2482
    UnityScreen::get (screen)->fullscreen_windows_.remove(window);
 
2483
 
 
2484
  PluginAdapter::Default ()->OnWindowClosed (window);
 
2485
}
 
2486
 
 
2487
/* vtable init */
 
2488
bool UnityPluginVTable::init()
 
2489
{
 
2490
  if (!CompPlugin::checkPluginABI("core", CORE_ABIVERSION))
 
2491
    return false;
 
2492
  if (!CompPlugin::checkPluginABI("composite", COMPIZ_COMPOSITE_ABI))
 
2493
    return false;
 
2494
  if (!CompPlugin::checkPluginABI("opengl", COMPIZ_OPENGL_ABI))
 
2495
    return false;
 
2496
 
 
2497
  return true;
 
2498
}
 
2499
 
 
2500
 
 
2501
namespace
 
2502
{
 
2503
 
 
2504
void configure_logging()
 
2505
{
 
2506
  // The default behaviour of the logging infrastructure is to send all output
 
2507
  // to std::cout for warning or above.
 
2508
 
 
2509
  // TODO: write a file output handler that keeps track of backups.
 
2510
  nux::logging::configure_logging(::getenv("UNITY_LOG_SEVERITY"));
 
2511
  g_log_set_default_handler(capture_g_log_calls, NULL);
 
2512
}
 
2513
 
 
2514
/* Checks whether an extension is supported by the GLX or OpenGL implementation
 
2515
 * given the extension name and the list of supported extensions. */
 
2516
gboolean is_extension_supported(const gchar* extensions, const gchar* extension)
 
2517
{
 
2518
  if (extensions != NULL && extension != NULL)
 
2519
  {
 
2520
    const gsize len = strlen(extension);
 
2521
    gchar* p = (gchar*) extensions;
 
2522
    gchar* end = p + strlen(p);
 
2523
 
 
2524
    while (p < end)
 
2525
    {
 
2526
      const gsize size = strcspn(p, " ");
 
2527
      if (len == size && strncmp(extension, p, size) == 0)
 
2528
        return TRUE;
 
2529
      p += size + 1;
 
2530
    }
 
2531
  }
 
2532
 
 
2533
  return FALSE;
 
2534
}
 
2535
 
 
2536
/* Gets the OpenGL version as a floating-point number given the string. */
 
2537
gfloat get_opengl_version_f32(const gchar* version_string)
 
2538
{
 
2539
  gfloat version = 0.0f;
 
2540
  gint32 i;
 
2541
 
 
2542
  for (i = 0; isdigit(version_string[i]); i++)
 
2543
    version = version * 10.0f + (version_string[i] - 48);
 
2544
 
 
2545
  if ((version_string[i] == '.' || version_string[i] == ',') &&
 
2546
      isdigit(version_string[i + 1]))
 
2547
  {
 
2548
    version = version * 10.0f + (version_string[i + 1] - 48);
 
2549
    return (version + 0.1f) * 0.1f;
 
2550
  }
 
2551
  else
 
2552
    return 0.0f;
 
2553
}
 
2554
 
 
2555
nux::logging::Level glog_level_to_nux(GLogLevelFlags log_level)
 
2556
{
 
2557
  // For some weird reason, ERROR is more critical than CRITICAL in gnome.
 
2558
  if (log_level & G_LOG_LEVEL_ERROR)
 
2559
    return nux::logging::Critical;
 
2560
  if (log_level & G_LOG_LEVEL_CRITICAL)
 
2561
    return nux::logging::Error;
 
2562
  if (log_level & G_LOG_LEVEL_WARNING)
 
2563
    return nux::logging::Warning;
 
2564
  if (log_level & G_LOG_LEVEL_MESSAGE ||
 
2565
      log_level & G_LOG_LEVEL_INFO)
 
2566
    return nux::logging::Info;
 
2567
  // default to debug.
 
2568
  return nux::logging::Debug;
 
2569
}
 
2570
 
 
2571
void capture_g_log_calls(const gchar* log_domain,
 
2572
                         GLogLevelFlags log_level,
 
2573
                         const gchar* message,
 
2574
                         gpointer user_data)
 
2575
{
 
2576
  // Since we aren't entirely sure if log_domain contains anything, lets have
 
2577
  // a glib prefix.
 
2578
  std::string module("glib");
 
2579
  if (log_domain)
 
2580
  {
 
2581
    module += std::string(".") + log_domain;
 
2582
  }
 
2583
  nux::logging::Logger logger(module);
 
2584
  nux::logging::Level level = glog_level_to_nux(log_level);
 
2585
  if (logger.GetEffectiveLogLevel() >= level)
 
2586
  {
 
2587
    nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
 
2588
        << message;
 
2589
  }
 
2590
}
 
2591
 
 
2592
} // anonymous namespace