gnome-shell-3.6.3.1/src/gnome-shell-plugin.c

No issues found

  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 
  3 /*
  4  * Copyright (c) 2008 Red Hat, Inc.
  5  * Copyright (c) 2008 Intel Corp.
  6  *
  7  * Based on plugin skeleton by:
  8  * Author: Tomas Frydrych <tf@linux.intel.com>
  9  *
 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.
 14  *
 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.
 19  *
 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
 23  * 02111-1307, USA.
 24  */
 25 
 26 #include "config.h"
 27 
 28 #include <stdlib.h>
 29 #include <string.h>
 30 
 31 #include <clutter/clutter.h>
 32 #include <clutter/x11/clutter-x11.h>
 33 #include <GL/glx.h>
 34 #include <GL/glxext.h>
 35 #include <gjs/gjs.h>
 36 #include <meta/display.h>
 37 #include <meta/meta-plugin.h>
 38 
 39 #include "shell-global-private.h"
 40 #include "shell-perf-log.h"
 41 #include "shell-wm-private.h"
 42 
 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,
 48                                                  gint                 x,
 49                                                  gint                 y,
 50                                                  gint                 width,
 51                                                  gint                 height);
 52 static void gnome_shell_plugin_unmaximize       (MetaPlugin          *plugin,
 53                                                  MetaWindowActor     *actor,
 54                                                  gint                 x,
 55                                                  gint                 y,
 56                                                  gint                 width,
 57                                                  gint                 height);
 58 static void gnome_shell_plugin_map              (MetaPlugin          *plugin,
 59                                                  MetaWindowActor     *actor);
 60 static void gnome_shell_plugin_destroy          (MetaPlugin          *plugin,
 61                                                  MetaWindowActor     *actor);
 62 
 63 static void gnome_shell_plugin_switch_workspace (MetaPlugin          *plugin,
 64                                                  gint                 from,
 65                                                  gint                 to,
 66                                                  MetaMotionDirection  direction);
 67 
 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);
 71 
 72 
 73 static gboolean              gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
 74                                                                XEvent     *event);
 75 static const MetaPluginInfo *gnome_shell_plugin_plugin_info   (MetaPlugin *plugin);
 76 
 77 
 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))
 84 
 85 typedef struct _GnomeShellPlugin        GnomeShellPlugin;
 86 typedef struct _GnomeShellPluginClass   GnomeShellPluginClass;
 87 
 88 struct _GnomeShellPlugin
 89 {
 90   MetaPlugin parent;
 91 
 92   Atom panel_action;
 93   Atom panel_action_run_dialog;
 94   Atom panel_action_main_menu;
 95 
 96   int glx_error_base;
 97   int glx_event_base;
 98   guint have_swap_event : 1;
 99 
100   ShellGlobal *global;
101 };
102 
103 struct _GnomeShellPluginClass
104 {
105   MetaPluginClass parent_class;
106 };
107 
108 GType gnome_shell_plugin_get_type (void);
109 
110 G_DEFINE_TYPE (GnomeShellPlugin, gnome_shell_plugin, META_TYPE_PLUGIN)
111 
112 static void
113 gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
114 {
115   MetaPluginClass *plugin_class  = META_PLUGIN_CLASS (klass);
116 
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;
123 
124   plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
125 
126   plugin_class->kill_window_effects   = gnome_shell_plugin_kill_window_effects;
127   plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
128 
129   plugin_class->xevent_filter    = gnome_shell_plugin_xevent_filter;
130   plugin_class->plugin_info      = gnome_shell_plugin_plugin_info;
131 }
132 
133 static void
134 gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
135 {
136 }
137 
138 static void
139 gnome_shell_plugin_start (MetaPlugin *plugin)
140 {
141   GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
142   MetaScreen *screen;
143   MetaDisplay *display;
144   Display *xdisplay;
145   GError *error = NULL;
146   int status;
147   const char *glx_extensions;
148   GjsContext *gjs_context;
149 
150   screen = meta_plugin_get_screen (plugin);
151   display = meta_screen_get_display (screen);
152 
153   xdisplay = meta_display_get_xdisplay (display);
154 
155   glXQueryExtension (xdisplay,
156                      &shell_plugin->glx_error_base,
157                      &shell_plugin->glx_event_base);
158 
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;
162 
163   shell_perf_log_define_event (shell_perf_log_get_default (),
164                                "glx.swapComplete",
165                                "GL buffer swap complete event received (with timestamp of completion)",
166                                "x");
167 
168   shell_plugin->global = shell_global_get ();
169   _shell_global_set_plugin (shell_plugin->global, META_PLUGIN (shell_plugin));
170 
171   gjs_context = _shell_global_get_gjs_context (shell_plugin->global);
172 
173   if (!gjs_context_eval (gjs_context,
174                          "imports.ui.environment.init();"
175                          "imports.ui.main.start();",
176                          -1,
177                          "<main>",
178                          &status,
179                          &error))
180     {
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.
186        *
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.
190        *
191        * If there was a generic "hook into bug-buddy for non-C crashes"
192        * infrastructure, here would be the place to put it.
193        */
194       exit (1);
195     }
196 }
197 
198 static ShellWM *
199 get_shell_wm (void)
200 {
201   ShellWM *wm;
202 
203   g_object_get (shell_global_get (),
204                 "window-manager", &wm,
205                 NULL);
206   /* drop extra ref added by g_object_get */
207   g_object_unref (wm);
208 
209   return wm;
210 }
211 
212 static void
213 gnome_shell_plugin_minimize (MetaPlugin         *plugin,
214 			     MetaWindowActor    *actor)
215 {
216   _shell_wm_minimize (get_shell_wm (),
217                       actor);
218 
219 }
220 
221 static void
222 gnome_shell_plugin_maximize (MetaPlugin         *plugin,
223                              MetaWindowActor    *actor,
224                              gint                x,
225                              gint                y,
226                              gint                width,
227                              gint                height)
228 {
229   _shell_wm_maximize (get_shell_wm (),
230                       actor, x, y, width, height);
231 }
232 
233 static void
234 gnome_shell_plugin_unmaximize (MetaPlugin         *plugin,
235                                MetaWindowActor    *actor,
236                                gint                x,
237                                gint                y,
238                                gint                width,
239                                gint                height)
240 {
241   _shell_wm_unmaximize (get_shell_wm (),
242                         actor, x, y, width, height);
243 }
244 
245 static void
246 gnome_shell_plugin_map (MetaPlugin         *plugin,
247                         MetaWindowActor    *actor)
248 {
249   _shell_wm_map (get_shell_wm (),
250                  actor);
251 }
252 
253 static void
254 gnome_shell_plugin_destroy (MetaPlugin         *plugin,
255                             MetaWindowActor    *actor)
256 {
257   _shell_wm_destroy (get_shell_wm (),
258                      actor);
259 }
260 
261 static void
262 gnome_shell_plugin_switch_workspace (MetaPlugin         *plugin,
263                                      gint                from,
264                                      gint                to,
265                                      MetaMotionDirection direction)
266 {
267   _shell_wm_switch_workspace (get_shell_wm(), from, to, direction);
268 }
269 
270 static void
271 gnome_shell_plugin_kill_window_effects (MetaPlugin         *plugin,
272                                         MetaWindowActor    *actor)
273 {
274   _shell_wm_kill_window_effects (get_shell_wm(), actor);
275 }
276 
277 static void
278 gnome_shell_plugin_kill_switch_workspace (MetaPlugin         *plugin)
279 {
280   _shell_wm_kill_switch_workspace (get_shell_wm());
281 }
282 
283 static gboolean
284 gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
285                                   XEvent     *xev)
286 {
287   MetaScreen *screen = meta_plugin_get_screen (plugin);
288   ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
289 
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))
294     {
295       GLXBufferSwapComplete *swap_complete_event;
296       swap_complete_event = (GLXBufferSwapComplete *)xev;
297 
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 (),
303                                 "glx.swapComplete",
304                                 swap_complete_event->ust);
305     }
306 #endif
307 
308   if ((xev->xany.type == EnterNotify || xev->xany.type == LeaveNotify)
309       && xev->xcrossing.window == clutter_x11_get_stage_window (stage))
310     {
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.
314        */
315       if (xev->xcrossing.detail == NotifyInferior)
316         return TRUE;
317 
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().)
324        */
325       if (xev->xcrossing.mode == NotifyGrab &&
326           (xev->xcrossing.detail == NotifyNonlinear ||
327            xev->xcrossing.detail == NotifyNonlinearVirtual))
328         return TRUE;
329     }
330 
331   /*
332    * Pass the event to shell-global
333    */
334   if (_shell_global_check_xdnd_event (shell_plugin->global, xev))
335     return TRUE;
336 
337   return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
338 }
339 
340 static const
341 MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
342 {
343   static const MetaPluginInfo info = {
344     .name = "GNOME Shell",
345     .version = "0.1",
346     .author = "Various",
347     .license = "GPLv2+",
348     .description = "Provides GNOME Shell core functionality"
349   };
350 
351   return &info;
352 }
353 
354 #if HAVE_BLUETOOTH
355 /* HACK:
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.
359 */
360 extern GType bluetooth_applet_get_type(void);
361 void _shell_link_to_bluetooth(void);
362 
363 void _shell_link_to_bluetooth(void) {
364   bluetooth_applet_get_type();
365 }
366 #endif