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

« back to all changes in this revision

Viewing changes to src/unity.cpp

Import the work done so far with Compiz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Compiz unity plugin
 
2
 * unity.cpp
 
3
 *
 
4
 * Copyright (c) 2010 Sam Spilsbury <smspillaz@gmail.com>
 
5
 *                    Jason Smith <jason.smith@canonical.com>
 
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 2
 
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
 
 
23
#include <Nux/Nux.h>
 
24
#include <Nux/HLayout.h>
 
25
#include <Nux/BaseWindow.h>
 
26
#include <Nux/WindowCompositor.h>
 
27
 
 
28
#include "Launcher.h"
 
29
#include "LauncherIcon.h"
 
30
#include "LauncherController.h"
 
31
#include "PluginAdapter.h"
 
32
#include "unity.h"
 
33
 
 
34
#include <dbus/dbus.h>
 
35
#include <dbus/dbus-glib.h>
 
36
#include <gtk/gtk.h>
 
37
 
 
38
#include <core/atoms.h>
 
39
 
 
40
/* You must also call this. This creates a proper vTable for a plugin name in the 
 
41
 * first argument (it's a macro, so you don't need a string). This changes from
 
42
 * time to time as the vTable changes, so it is a good way of ensure plugins keep
 
43
 * current */
 
44
 
 
45
COMPIZ_PLUGIN_20090315 (unity, UnityPluginVTable);
 
46
 
 
47
/* This is the function that is called before the screen is 're-painted'. It is used for animation
 
48
 * and such because it gives you a time difference between when the last time the screen was repainted
 
49
 * and the current time of the execution of the functions in milliseconds). It's part of the composite
 
50
 * plugin's interface
 
51
 */
 
52
 
 
53
static bool paint_required = false;
 
54
static UnityScreen *uScreen = 0;
 
55
 
 
56
void
 
57
UnityScreen::preparePaint (int ms)
 
58
{
 
59
    /* At the end of every function, you must call BaseClass->functionName (args) in order to pass on
 
60
     * the call chain */
 
61
    cScreen->preparePaint (ms);
 
62
    paint_required = true;
 
63
}
 
64
 
 
65
void
 
66
UnityScreen::nuxPrologue ()
 
67
{
 
68
    glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
 
69
    
 
70
    glMatrixMode (GL_PROJECTION);
 
71
    glPushMatrix ();
 
72
    
 
73
    glMatrixMode (GL_MODELVIEW);
 
74
    glPushMatrix ();
 
75
 
 
76
    glGetError();
 
77
}
 
78
 
 
79
void
 
80
UnityScreen::nuxEpilogue ()
 
81
{
 
82
    (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
 
83
 
 
84
    glMatrixMode (GL_PROJECTION);
 
85
    glLoadIdentity ();
 
86
    glMatrixMode (GL_MODELVIEW);
 
87
    glLoadIdentity ();
 
88
    glDepthRange (0, 1);
 
89
    glViewport (-1, -1, 2, 2);
 
90
    glRasterPos2f (0, 0);
 
91
 
 
92
    gScreen->resetRasterPos ();
 
93
 
 
94
    glMatrixMode (GL_PROJECTION);
 
95
    glPopMatrix ();
 
96
    glMatrixMode (GL_MODELVIEW);
 
97
    glPopMatrix ();
 
98
 
 
99
    glDrawBuffer (GL_BACK);
 
100
    glReadBuffer (GL_BACK);
 
101
 
 
102
    glPopAttrib ();
 
103
}
 
104
 
 
105
void
 
106
UnityScreen::paintDisplay (const CompRegion &region)
 
107
{
 
108
    nuxPrologue ();
 
109
    wt->RenderInterfaceFromForeignCmd ();
 
110
    nuxEpilogue ();
 
111
}
 
112
 
 
113
/* This is the guts of the paint function. You can transform the way the entire output is painted
 
114
 * or you can just draw things on screen with openGL. The unsigned int here is a mask for painting
 
115
 * the screen, see opengl/opengl.h on how you can change it */
 
116
 
 
117
bool
 
118
UnityScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, // Some basic attribs on how the screen should be painted
 
119
                              const GLMatrix            &transform, // Screen transformation matrix
 
120
                              const CompRegion          &region, // Region of screen being painted
 
121
                              CompOutput                *output, // Output properties. Use this to the get output width and height for the output being painted
 
122
                              unsigned int              mask /* Some other paint properties, see opengl.h */)
 
123
{
 
124
    bool ret;
 
125
 
 
126
    /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
 
127
    ret = gScreen->glPaintOutput (attrib, transform, region, output, mask);
 
128
    
 
129
    if (paint_required)
 
130
    {
 
131
        paintDisplay (region);
 
132
        paint_required = false;
 
133
    }
 
134
    
 
135
    return ret;
 
136
}
 
137
 
 
138
/* This is called when the output is transformed by a matrix. Basically the same, but core has
 
139
 * done a few things for us like clip planes etc */
 
140
 
 
141
void
 
142
UnityScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &attrib, // Some basic attribs on how the screen should be painted
 
143
                                         const GLMatrix         &transform, // Screen transformation matrix
 
144
                                         const CompRegion       &region, // Region of screen being painted
 
145
                                         CompOutput             *output, // Output properties. Use this to the get output width and height for the output being painted
 
146
                                         unsigned int           mask /* Some other paint properties, see opengl.h */)
 
147
{
 
148
    /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
 
149
    gScreen->glPaintOutput (attrib, transform, region, output, mask);
 
150
}
 
151
 
 
152
/* This is called after screen painting is finished. It gives you a chance to do any cleanup and or
 
153
 * call another repaint with screen->damageScreen (). It's also part of the composite plugin's
 
154
 * interface.
 
155
 */
 
156
 
 
157
void
 
158
UnityScreen::donePaint ()
 
159
{
 
160
    cScreen->donePaint ();
 
161
}
 
162
 
 
163
void
 
164
UnityScreen::damageNuxRegions ()
 
165
{
 
166
    CompRegion region;
 
167
    std::vector<nux::Geometry>::iterator it;
 
168
    std::vector<nux::Geometry> dirty = wt->GetDrawList ();
 
169
    nux::Geometry geo;
 
170
            
 
171
    for (it = dirty.begin (); it != dirty.end (); it++)
 
172
    {
 
173
        geo = *it;
 
174
        cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
 
175
    }
 
176
            
 
177
    geo = wt->GetWindowCompositor ().GetTooltipMainWindowGeometry();
 
178
    cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
 
179
    cScreen->damageRegion (CompRegion (lastTooltipArea.x, lastTooltipArea.y, lastTooltipArea.width, lastTooltipArea.height));
 
180
            
 
181
    lastTooltipArea = geo;
 
182
    
 
183
    wt->ClearDrawList ();
 
184
}
 
185
 
 
186
/* This is our event handler. It directly hooks into the screen's X Event handler and allows us to handle
 
187
 * our raw X Events
 
188
 */
 
189
 
 
190
void
 
191
UnityScreen::handleEvent (XEvent *event)
 
192
{
 
193
    screen->handleEvent (event);
 
194
}
 
195
 
 
196
bool
 
197
UnityScreen::initPluginForScreen (CompPlugin *p)
 
198
{
 
199
    if (g_strcmp0 (p->vTable->name ().c_str (), "expo") == 0)
 
200
    {
 
201
        CompOption::Vector &options = p->vTable->getOptions ();
 
202
        
 
203
        foreach (CompOption& option, options)
 
204
        {
 
205
          if (g_strcmp0 (option.name ().c_str () , "expo_key") == 0)
 
206
          {
 
207
              CompAction *expoAction = &option.value ().action ();
 
208
              
 
209
              PluginAdapter::Default ()->SetExpoAction (expoAction);
 
210
              break;
 
211
          }
 
212
        }
 
213
    }
 
214
    
 
215
    if (g_strcmp0 (p->vTable->name ().c_str (), "scale") == 0)
 
216
    {
 
217
        CompOption::Vector &options = p->vTable->getOptions ();
 
218
        
 
219
        foreach (CompOption& option, options)
 
220
        {
 
221
          if (g_strcmp0 (option.name ().c_str () , "initiate_all_key") == 0)
 
222
          {
 
223
              CompAction *scaleAction = &option.value ().action ();
 
224
              
 
225
              PluginAdapter::Default ()->SetScaleAction (scaleAction);
 
226
              break;
 
227
          }
 
228
        }
 
229
    }
 
230
 
 
231
    screen->initPluginForScreen (p);
 
232
    return true;
 
233
}
 
234
 
 
235
/* This gets called whenever the window needs to be repainted. WindowPaintAttrib gives you some
 
236
 * attributes like brightness/saturation etc to play around with. GLMatrix is the window's
 
237
 * transformation matrix. the unsigned int is the mask, have a look at opengl.h on what you can do
 
238
 * with it */
 
239
 
 
240
bool
 
241
UnityWindow::glPaint (const GLWindowPaintAttrib &attrib, // Brightness, Saturation, Opacity etc
 
242
      const GLMatrix &transform, // Transformation Matrix
 
243
      const CompRegion &region, // Repaint region
 
244
      unsigned int mask) // Other flags. See opengl.h
 
245
{
 
246
    bool ret;
 
247
    ret = gWindow->glPaint (attrib, transform, region, mask);
 
248
    return ret;
 
249
}
 
250
 
 
251
bool 
 
252
UnityWindow::glDraw (const GLMatrix     &matrix,
 
253
                             GLFragment::Attrib &attrib,
 
254
                             const CompRegion   &region,
 
255
                             unsigned int       mask)
 
256
{
 
257
    bool ret;
 
258
    
 
259
    if (paint_required && uScreen && window->type () & (CompWindowTypeMenuMask | 
 
260
                                                        CompWindowTypeDropdownMenuMask | 
 
261
                                                        CompWindowTypePopupMenuMask |
 
262
                                                        CompWindowTypeComboMask |
 
263
                                                        CompWindowTypeTooltipMask |
 
264
                                                        CompWindowTypeDndMask
 
265
                                                        ))
 
266
    {
 
267
        uScreen->paintDisplay (region);
 
268
        paint_required = false;
 
269
    }
 
270
 
 
271
    ret = gWindow->glDraw (matrix, attrib, region, mask);
 
272
 
 
273
    return ret;
 
274
}
 
275
/* This get's called whenever a window's rect is damaged. You can do stuff here or you can adjust the damage
 
276
 * rectangle so that the window will update properly. Part of the CompositeWindowInterface.
 
277
 */
 
278
 
 
279
bool
 
280
UnityWindow::damageRect (bool initial, // initial damage?
 
281
    const CompRect &rect) // The actual rect. Modifyable.
 
282
{
 
283
    bool ret;
 
284
 
 
285
    ret = cWindow->damageRect (initial, rect);
 
286
 
 
287
    return ret;
 
288
}
 
289
 
 
290
/* This is called whenever the window is focussed */
 
291
 
 
292
bool
 
293
UnityWindow::focus ()
 
294
{
 
295
    bool ret;
 
296
 
 
297
    ret = window->focus ();
 
298
 
 
299
    return ret;
 
300
}
 
301
 
 
302
/* This is called whenever the window is activated */
 
303
 
 
304
void
 
305
UnityWindow::activate ()
 
306
{
 
307
    window->activate ();
 
308
}
 
309
 
 
310
/* This is called whenever the window must be placed. You can alter the placement position by altering
 
311
 * the CompPoint & */
 
312
 
 
313
bool
 
314
UnityWindow::place (CompPoint &point)
 
315
{
 
316
    bool ret;
 
317
 
 
318
    ret = window->place (point);
 
319
    return ret;
 
320
}
 
321
 
 
322
/* This is called whenever the window is moved. It tells you how far it's been moved and whether that
 
323
 * move should be immediate or animated. (Immediate is usually for a sudden move, false for that
 
324
 * usually means the user moved the window */
 
325
 
 
326
void
 
327
UnityWindow::moveNotify (int dx,
 
328
            int dy,
 
329
            bool immediate)
 
330
{
 
331
    window->moveNotify (dx, dy, immediate);
 
332
}
 
333
 
 
334
/* This is called whenever the window is resized. It tells you how much the window has been resized */
 
335
 
 
336
void
 
337
UnityWindow::resizeNotify (int dx,
 
338
              int dy,
 
339
              int dwidth,
 
340
              int dheight)
 
341
{
 
342
    window->resizeNotify (dx, dy, dwidth, dheight);
 
343
}
 
344
 
 
345
/* This is called when another plugin deems a window to be 'grabbed'. You can't actually 'grab' a
 
346
 * window in X, but it is useful in case you need to know when a user has grabbed a window for some reason */
 
347
 
 
348
void
 
349
UnityWindow::grabNotify (int x,
 
350
            int y,
 
351
            unsigned int state,
 
352
            unsigned int mask)
 
353
{
 
354
    window->grabNotify (x, y, state, mask);
 
355
}
 
356
 
 
357
/* This is called when a window in released from a grab. See above */
 
358
 
 
359
void
 
360
UnityWindow::ungrabNotify ()
 
361
{
 
362
    window->ungrabNotify ();
 
363
}
 
364
 
 
365
/* This is called when another misc notification arises, such as Map/Unmap etc */
 
366
 
 
367
void
 
368
UnityWindow::windowNotify (CompWindowNotify n)
 
369
{
 
370
    window->windowNotify (n);
 
371
}
 
372
 
 
373
/* This is an action. It is called on a keybinding as set in the options. It is binded when
 
374
 *  the class is constructed
 
375
 */
 
376
 
 
377
bool
 
378
UnityScreen::unityInitiate (CompAction         *action,
 
379
                CompAction::State  state,
 
380
                CompOption::Vector &options)
 
381
{
 
382
    return false;
 
383
}
 
384
 
 
385
void 
 
386
UnityScreen::launcherWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
 
387
{
 
388
    int OurWindowHeight = WindowHeight - 24;
 
389
    geo = nux::Geometry(0, 24, geo.width, OurWindowHeight);
 
390
}
 
391
 
 
392
void 
 
393
UnityScreen::panelWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
 
394
{
 
395
    geo = nux::Geometry(0, 0, WindowWidth, 24);
 
396
}
 
397
 
 
398
 
 
399
void 
 
400
UnityScreen::initUnity(nux::NThread* thread, void* InitData)
 
401
{
 
402
    initLauncher(thread, InitData);
 
403
      
 
404
    nux::ColorLayer background(nux::Color(0x00000000));
 
405
    static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
 
406
}
 
407
 
 
408
void 
 
409
UnityScreen::onRedrawRequested ()
 
410
{
 
411
  damageNuxRegions ();
 
412
}
 
413
 
 
414
UnityScreen::UnityScreen (CompScreen *screen) :// The constructor takes a CompScreen *,
 
415
    PluginClassHandler <UnityScreen, CompScreen> (screen), // Initiate PluginClassHandler class template
 
416
    screen (screen),
 
417
    cScreen (CompositeScreen::get (screen)),
 
418
    gScreen (GLScreen::get (screen))
 
419
{
 
420
    int (*old_handler) (Display *, XErrorEvent *);
 
421
    old_handler = XSetErrorHandler (NULL);
 
422
    
 
423
    g_thread_init (NULL);
 
424
    dbus_g_thread_init ();
 
425
    gtk_init (NULL, NULL);
 
426
    
 
427
    XSetErrorHandler (old_handler);
 
428
    
 
429
    ScreenInterface::setHandler (screen); // Sets the screen function hook handler
 
430
    CompositeScreenInterface::setHandler (cScreen); // Ditto for cScreen
 
431
    GLScreenInterface::setHandler (gScreen); // Ditto for gScreen
 
432
 
 
433
    optionSetUnityInitiate (unityInitiate); // Initiate handler for 'unity' action
 
434
 
 
435
    nux::NuxInitialize (0);
 
436
    wt = nux::CreateFromForeignWindow (cScreen->output (), 
 
437
                                       glXGetCurrentContext (), 
 
438
                                       &UnityScreen::initUnity,
 
439
                                       this);
 
440
    
 
441
    wt->RedrawRequested.connect (sigc::mem_fun (this, &UnityScreen::onRedrawRequested));
 
442
    
 
443
    wt->Run (NULL);
 
444
    uScreen = this;
 
445
    
 
446
    PluginAdapter::Initialize (screen);
 
447
}
 
448
 
 
449
/* This is the destructor. It is called when the class is destroyed. If you allocated any
 
450
 * memory or need to do some cleanup, here is where you do it. Note the tilde (~)?
 
451
 */
 
452
 
 
453
UnityScreen::~UnityScreen ()
 
454
{
 
455
}
 
456
 
 
457
gboolean UnityScreen::strutHackTimeout (gpointer data)
 
458
{
 
459
    UnityScreen *self = (UnityScreen*) data;  
 
460
    
 
461
    self->launcherWindow->InputWindowEnableStruts(false);
 
462
    self->launcherWindow->InputWindowEnableStruts(true);
 
463
    
 
464
    self->panelWindow->InputWindowEnableStruts(false);
 
465
    self->panelWindow->InputWindowEnableStruts(true);
 
466
    
 
467
    return FALSE;
 
468
}
 
469
 
 
470
void UnityScreen::initLauncher (nux::NThread* thread, void* InitData)
 
471
{
 
472
  UnityScreen *self = (UnityScreen*) InitData;
 
473
  
 
474
  self->launcher = new Launcher();
 
475
 
 
476
  nux::HLayout* layout = new nux::HLayout();
 
477
 
 
478
  layout->AddView(self->launcher, 1);
 
479
  layout->SetContentDistribution(nux::eStackLeft);
 
480
  layout->SetVerticalExternalMargin(0);
 
481
  layout->SetHorizontalExternalMargin(0);
 
482
 
 
483
  self->launcherWindow = new nux::BaseWindow(TEXT(""));
 
484
  self->controller = new LauncherController (self->launcher, self->screen, self->launcherWindow);
 
485
 
 
486
  self->launcherWindow->SetConfigureNotifyCallback(&UnityScreen::launcherWindowConfigureCallback, self);
 
487
  self->launcherWindow->SetLayout(layout);
 
488
  self->launcherWindow->SetBackgroundColor(nux::Color(0x00000000));
 
489
  self->launcherWindow->SetBlurredBackground(false);
 
490
  self->launcherWindow->ShowWindow(true);
 
491
  self->launcherWindow->EnableInputWindow(true);
 
492
  self->launcherWindow->InputWindowEnableStruts(true);
 
493
 
 
494
  self->launcher->SetIconSize (54, 48, self->launcherWindow);
 
495
 
 
496
  /* Setup panel */
 
497
  self->panelView = new PanelView ();
 
498
 
 
499
  layout = new nux::HLayout();
 
500
 
 
501
  self->panelView->SetMaximumHeight(24);
 
502
  layout->AddView(self->panelView, 1);
 
503
  layout->SetContentDistribution(nux::eStackLeft);
 
504
  layout->SetVerticalExternalMargin(0);
 
505
  layout->SetHorizontalExternalMargin(0);
 
506
 
 
507
  self->panelWindow = new nux::BaseWindow("");
 
508
 
 
509
  self->panelWindow->SetConfigureNotifyCallback(&UnityScreen::panelWindowConfigureCallback, self);
 
510
  self->panelWindow->SetLayout(layout);
 
511
  self->panelWindow->SetBackgroundColor(nux::Color(0x00000000));
 
512
  self->panelWindow->SetBlurredBackground(false);
 
513
  self->panelWindow->ShowWindow(true);
 
514
  self->panelWindow->EnableInputWindow(true);  
 
515
  self->panelWindow->InputWindowEnableStruts(true);
 
516
  
 
517
  g_timeout_add (2000, &UnityScreen::strutHackTimeout, self);
 
518
}
 
519
 
 
520
UnityWindow::UnityWindow (CompWindow *window) :
 
521
    PluginClassHandler <UnityWindow, CompWindow> (window), // Initiate our PrivateHandler class template
 
522
    window (window), 
 
523
    cWindow (CompositeWindow::get (window)),
 
524
    gWindow (GLWindow::get (window))
 
525
{
 
526
    WindowInterface::setHandler (window); // Sets the window function hook handler
 
527
    CompositeWindowInterface::setHandler (cWindow); // Ditto for cWindow
 
528
    GLWindowInterface::setHandler (gWindow); // Ditto for gWindow
 
529
}
 
530
 
 
531
UnityWindow::~UnityWindow ()
 
532
{
 
533
}
 
534
 
 
535
/* This is the very first function compiz calls. It kicks off plugin initialization */
 
536
 
 
537
bool
 
538
UnityPluginVTable::init ()
 
539
{
 
540
    /* Calls to checkPluginABI check the ABI of a particular plugin to see if it is loaded
 
541
     * and in sync with your current build. If it fails the plugin will not load otherwise
 
542
     * compiz will crash.
 
543
     */
 
544
 
 
545
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
546
         return false;
 
547
    if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
 
548
         return false;
 
549
    if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
 
550
         return false;
 
551
 
 
552
    return true;
 
553
}
 
554