1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
4
* Copyright (c) 2008 Red Hat, Inc.
5
* Copyright (c) 2008 Intel Corp.
7
* Based on plugin skeleton by:
8
* Author: Tomas Frydrych <tf@linux.intel.com>
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License as
12
* published by the Free Software Foundation; either version 2 of the
13
* License, or (at your option) any later version.
15
* This program is distributed in the hope that it will be useful, but
16
* WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31
#include <clutter/clutter.h>
32
#include <clutter/x11/clutter-x11.h>
34
#include <GL/glxext.h>
36
#include <meta/display.h>
37
#include <meta/meta-plugin.h>
39
#include "shell-global-private.h"
40
#include "shell-perf-log.h"
41
#include "shell-wm-private.h"
43
static void gnome_shell_plugin_start (MetaPlugin *plugin);
44
static void gnome_shell_plugin_minimize (MetaPlugin *plugin,
45
MetaWindowActor *actor);
46
static void gnome_shell_plugin_maximize (MetaPlugin *plugin,
47
MetaWindowActor *actor,
52
static void gnome_shell_plugin_unmaximize (MetaPlugin *plugin,
53
MetaWindowActor *actor,
58
static void gnome_shell_plugin_map (MetaPlugin *plugin,
59
MetaWindowActor *actor);
60
static void gnome_shell_plugin_destroy (MetaPlugin *plugin,
61
MetaWindowActor *actor);
63
static void gnome_shell_plugin_switch_workspace (MetaPlugin *plugin,
66
MetaMotionDirection direction);
68
static void gnome_shell_plugin_kill_window_effects (MetaPlugin *plugin,
69
MetaWindowActor *actor);
70
static void gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin);
73
static gboolean gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
75
static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin);
78
#define GNOME_TYPE_SHELL_PLUGIN (gnome_shell_plugin_get_type ())
79
#define GNOME_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPlugin))
80
#define GNOME_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
81
#define GNOME_IS_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_SHELL_PLUGIN_TYPE))
82
#define GNOME_IS_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_SHELL_PLUGIN))
83
#define GNOME_SHELL_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
85
typedef struct _GnomeShellPlugin GnomeShellPlugin;
86
typedef struct _GnomeShellPluginClass GnomeShellPluginClass;
88
struct _GnomeShellPlugin
93
Atom panel_action_run_dialog;
94
Atom panel_action_main_menu;
98
guint have_swap_event : 1;
103
struct _GnomeShellPluginClass
105
MetaPluginClass parent_class;
108
GType gnome_shell_plugin_get_type (void);
110
G_DEFINE_TYPE (GnomeShellPlugin, gnome_shell_plugin, META_TYPE_PLUGIN)
113
gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
115
MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass);
117
plugin_class->start = gnome_shell_plugin_start;
118
plugin_class->map = gnome_shell_plugin_map;
119
plugin_class->minimize = gnome_shell_plugin_minimize;
120
plugin_class->maximize = gnome_shell_plugin_maximize;
121
plugin_class->unmaximize = gnome_shell_plugin_unmaximize;
122
plugin_class->destroy = gnome_shell_plugin_destroy;
124
plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
126
plugin_class->kill_window_effects = gnome_shell_plugin_kill_window_effects;
127
plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
129
plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter;
130
plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
134
gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
139
gnome_shell_plugin_start (MetaPlugin *plugin)
141
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
143
MetaDisplay *display;
145
GError *error = NULL;
147
const char *glx_extensions;
148
GjsContext *gjs_context;
150
screen = meta_plugin_get_screen (plugin);
151
display = meta_screen_get_display (screen);
153
xdisplay = meta_display_get_xdisplay (display);
155
glXQueryExtension (xdisplay,
156
&shell_plugin->glx_error_base,
157
&shell_plugin->glx_event_base);
159
glx_extensions = glXQueryExtensionsString (xdisplay,
160
meta_screen_get_screen_number (screen));
161
shell_plugin->have_swap_event = strstr (glx_extensions, "GLX_INTEL_swap_event") != NULL;
163
shell_perf_log_define_event (shell_perf_log_get_default (),
165
"GL buffer swap complete event received (with timestamp of completion)",
168
shell_plugin->global = shell_global_get ();
169
_shell_global_set_plugin (shell_plugin->global, META_PLUGIN (shell_plugin));
171
gjs_context = _shell_global_get_gjs_context (shell_plugin->global);
173
if (!gjs_context_eval (gjs_context,
174
"imports.ui.environment.init();"
175
"imports.ui.main.start();",
181
g_message ("Execution of main.js threw exception: %s", error->message);
182
g_error_free (error);
183
/* We just exit() here, since in a development environment you'll get the
184
* error in your shell output, and it's way better than a busted WM,
185
* which typically manifests as a white screen.
187
* In production, we shouldn't crash =) But if we do, we should get
188
* restarted by the session infrastructure, which is likely going
189
* to be better than some undefined state.
191
* If there was a generic "hook into bug-buddy for non-C crashes"
192
* infrastructure, here would be the place to put it.
203
g_object_get (shell_global_get (),
204
"window-manager", &wm,
206
/* drop extra ref added by g_object_get */
213
gnome_shell_plugin_minimize (MetaPlugin *plugin,
214
MetaWindowActor *actor)
216
_shell_wm_minimize (get_shell_wm (),
222
gnome_shell_plugin_maximize (MetaPlugin *plugin,
223
MetaWindowActor *actor,
229
_shell_wm_maximize (get_shell_wm (),
230
actor, x, y, width, height);
234
gnome_shell_plugin_unmaximize (MetaPlugin *plugin,
235
MetaWindowActor *actor,
241
_shell_wm_unmaximize (get_shell_wm (),
242
actor, x, y, width, height);
246
gnome_shell_plugin_map (MetaPlugin *plugin,
247
MetaWindowActor *actor)
249
_shell_wm_map (get_shell_wm (),
254
gnome_shell_plugin_destroy (MetaPlugin *plugin,
255
MetaWindowActor *actor)
257
_shell_wm_destroy (get_shell_wm (),
262
gnome_shell_plugin_switch_workspace (MetaPlugin *plugin,
265
MetaMotionDirection direction)
267
_shell_wm_switch_workspace (get_shell_wm(), from, to, direction);
271
gnome_shell_plugin_kill_window_effects (MetaPlugin *plugin,
272
MetaWindowActor *actor)
274
_shell_wm_kill_window_effects (get_shell_wm(), actor);
278
gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin)
280
_shell_wm_kill_switch_workspace (get_shell_wm());
284
gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
287
MetaScreen *screen = meta_plugin_get_screen (plugin);
288
ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
290
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
291
#ifdef GLX_INTEL_swap_event
292
if (shell_plugin->have_swap_event &&
293
xev->type == (shell_plugin->glx_event_base + GLX_BufferSwapComplete))
295
GLXBufferSwapComplete *swap_complete_event;
296
swap_complete_event = (GLXBufferSwapComplete *)xev;
298
/* Buggy early versions of the INTEL_swap_event implementation in Mesa
299
* can send this with a ust of 0. Simplify life for consumers
300
* by ignoring such events */
301
if (swap_complete_event->ust != 0)
302
shell_perf_log_event_x (shell_perf_log_get_default (),
304
swap_complete_event->ust);
308
if ((xev->xany.type == EnterNotify || xev->xany.type == LeaveNotify)
309
&& xev->xcrossing.window == clutter_x11_get_stage_window (stage))
311
/* If the pointer enters a child of the stage window (eg, a
312
* trayicon), we want to consider it to still be in the stage,
313
* so don't let Clutter see the event.
315
if (xev->xcrossing.detail == NotifyInferior)
318
/* If the pointer is grabbed by a window it is not currently in,
319
* filter that out as well. In particular, if a trayicon grabs
320
* the pointer after a click on its label, we don't want to hide
321
* the message tray. Filtering out this event will leave Clutter
322
* out of sync, but that happens fairly often with grabs, and we
323
* can work around it. (Eg, shell_global_sync_pointer().)
325
if (xev->xcrossing.mode == NotifyGrab &&
326
(xev->xcrossing.detail == NotifyNonlinear ||
327
xev->xcrossing.detail == NotifyNonlinearVirtual))
332
* Pass the event to shell-global
334
if (_shell_global_check_xdnd_event (shell_plugin->global, xev))
337
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
341
MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
343
static const MetaPluginInfo info = {
344
.name = "GNOME Shell",
348
.description = "Provides GNOME Shell core functionality"
356
Add a non-static function that calls into libgnome-bluetooth-applet.so,
357
to avoid the linker being too smart and removing the dependency.
358
This function is never actually called.
360
extern GType bluetooth_applet_get_type(void);
361
void _shell_link_to_bluetooth(void);
363
void _shell_link_to_bluetooth(void) {
364
bluetooth_applet_get_type();