Blame src/gnome-shell-plugin.c

Packit Service ed5168
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
Packit Service ed5168
Packit Service ed5168
/*
Packit Service ed5168
 * Copyright (c) 2008 Red Hat, Inc.
Packit Service ed5168
 * Copyright (c) 2008 Intel Corp.
Packit Service ed5168
 *
Packit Service ed5168
 * Based on plugin skeleton by:
Packit Service ed5168
 * Author: Tomas Frydrych <tf@linux.intel.com>
Packit Service ed5168
 *
Packit Service ed5168
 * This program is free software; you can redistribute it and/or
Packit Service ed5168
 * modify it under the terms of the GNU General Public License as
Packit Service ed5168
 * published by the Free Software Foundation; either version 2 of the
Packit Service ed5168
 * License, or (at your option) any later version.
Packit Service ed5168
 *
Packit Service ed5168
 * This program is distributed in the hope that it will be useful, but
Packit Service ed5168
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service ed5168
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service ed5168
 * General Public License for more details.
Packit Service ed5168
 *
Packit Service ed5168
 * You should have received a copy of the GNU General Public License
Packit Service ed5168
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit Service ed5168
 */
Packit Service ed5168
Packit Service ed5168
/*
Packit Service ed5168
 * GnomeShellPlugin is the entry point for for GNOME Shell into and out of
Packit Service ed5168
 * Mutter. By registering itself into Mutter using
Packit Service ed5168
 * meta_plugin_manager_set_plugin_type(), Mutter will call the vfuncs of the
Packit Service ed5168
 * plugin at the appropriate time.
Packit Service ed5168
 *
Packit Service ed5168
 * The funcions in in GnomeShellPlugin are all just stubs, which just call the
Packit Service ed5168
 * similar methods in GnomeShellWm.
Packit Service ed5168
 */
Packit Service ed5168
Packit Service ed5168
#include "config.h"
Packit Service ed5168
Packit Service ed5168
#include <stdlib.h>
Packit Service ed5168
#include <string.h>
Packit Service ed5168
Packit Service ed5168
#include <clutter/clutter.h>
Packit Service ed5168
#include <clutter/x11/clutter-x11.h>
Packit Service ed5168
#include <gjs/gjs.h>
Packit Service ed5168
#include <meta/display.h>
Packit Service ed5168
#include <meta/meta-plugin.h>
Packit Service ed5168
#include <meta/util.h>
Packit Service ed5168
Packit Service ed5168
#include "shell-global-private.h"
Packit Service ed5168
#include "shell-perf-log.h"
Packit Service ed5168
#include "shell-wm-private.h"
Packit Service ed5168
Packit Service ed5168
#define GNOME_TYPE_SHELL_PLUGIN (gnome_shell_plugin_get_type ())
Packit Service ed5168
G_DECLARE_FINAL_TYPE (GnomeShellPlugin, gnome_shell_plugin,
Packit Service ed5168
                      GNOME, SHELL_PLUGIN,
Packit Service ed5168
                      MetaPlugin)
Packit Service ed5168
Packit Service ed5168
struct _GnomeShellPlugin
Packit Service ed5168
{
Packit Service ed5168
  MetaPlugin parent;
Packit Service ed5168
Packit Service ed5168
  int glx_error_base;
Packit Service ed5168
  int glx_event_base;
Packit Service ed5168
  guint have_swap_event : 1;
Packit Service ed5168
  CoglContext *cogl_context;
Packit Service ed5168
Packit Service ed5168
  ShellGlobal *global;
Packit Service ed5168
};
Packit Service ed5168
Packit Service ed5168
G_DEFINE_TYPE (GnomeShellPlugin, gnome_shell_plugin, META_TYPE_PLUGIN)
Packit Service ed5168
Packit Service ed5168
static gboolean
Packit Service ed5168
gnome_shell_plugin_has_swap_event (GnomeShellPlugin *shell_plugin)
Packit Service ed5168
{
Packit Service ed5168
  CoglDisplay *cogl_display =
Packit Service ed5168
    cogl_context_get_display (shell_plugin->cogl_context);
Packit Service ed5168
  CoglRenderer *renderer = cogl_display_get_renderer (cogl_display);
Packit Service ed5168
  const char * (* query_extensions_string) (Display *dpy, int screen);
Packit Service ed5168
  Bool (* query_extension) (Display *dpy, int *error, int *event);
Packit Service ed5168
  Display *xdisplay;
Packit Service ed5168
  int screen_number;
Packit Service ed5168
  const char *glx_extensions;
Packit Service ed5168
Packit Service ed5168
  /* We will only get swap events if Cogl is using GLX */
Packit Service ed5168
  if (cogl_renderer_get_winsys_id (renderer) != COGL_WINSYS_ID_GLX)
Packit Service ed5168
    return FALSE;
Packit Service ed5168
Packit Service ed5168
  xdisplay = clutter_x11_get_default_display ();
Packit Service ed5168
Packit Service ed5168
  query_extensions_string =
Packit Service ed5168
    (void *) cogl_get_proc_address ("glXQueryExtensionsString");
Packit Service ed5168
  query_extension =
Packit Service ed5168
    (void *) cogl_get_proc_address ("glXQueryExtension");
Packit Service ed5168
Packit Service ed5168
  query_extension (xdisplay,
Packit Service ed5168
                   &shell_plugin->glx_error_base,
Packit Service ed5168
                   &shell_plugin->glx_event_base);
Packit Service ed5168
Packit Service ed5168
  screen_number = XDefaultScreen (xdisplay);
Packit Service ed5168
  glx_extensions = query_extensions_string (xdisplay, screen_number);
Packit Service ed5168
Packit Service ed5168
  return strstr (glx_extensions, "GLX_INTEL_swap_event") != NULL;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_start (MetaPlugin *plugin)
Packit Service ed5168
{
Packit Service ed5168
  GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
Packit Service ed5168
  GError *error = NULL;
Packit Service ed5168
  int status;
Packit Service ed5168
  GjsContext *gjs_context;
Packit Service ed5168
  ClutterBackend *backend;
Packit Service ed5168
Packit Service ed5168
  backend = clutter_get_default_backend ();
Packit Service ed5168
  shell_plugin->cogl_context = clutter_backend_get_cogl_context (backend);
Packit Service ed5168
Packit Service ed5168
  shell_plugin->have_swap_event =
Packit Service ed5168
    gnome_shell_plugin_has_swap_event (shell_plugin);
Packit Service ed5168
Packit Service ed5168
  shell_perf_log_define_event (shell_perf_log_get_default (),
Packit Service ed5168
                               "glx.swapComplete",
Packit Service ed5168
                               "GL buffer swap complete event received (with timestamp of completion)",
Packit Service ed5168
                               "x");
Packit Service ed5168
Packit Service ed5168
  shell_plugin->global = shell_global_get ();
Packit Service ed5168
  _shell_global_set_plugin (shell_plugin->global, META_PLUGIN (shell_plugin));
Packit Service ed5168
Packit Service ed5168
  gjs_context = _shell_global_get_gjs_context (shell_plugin->global);
Packit Service ed5168
Packit Service ed5168
  if (!gjs_context_eval (gjs_context,
Packit Service ed5168
                         "imports.ui.environment.init();"
Packit Service ed5168
                         "imports.ui.main.start();",
Packit Service ed5168
                         -1,
Packit Service ed5168
                         "<main>",
Packit Service ed5168
                         &status,
Packit Service ed5168
                         &error))
Packit Service ed5168
    {
Packit Service ed5168
      g_message ("Execution of main.js threw exception: %s", error->message);
Packit Service ed5168
      g_error_free (error);
Packit Service ed5168
      /* We just exit() here, since in a development environment you'll get the
Packit Service ed5168
       * error in your shell output, and it's way better than a busted WM,
Packit Service ed5168
       * which typically manifests as a white screen.
Packit Service ed5168
       *
Packit Service ed5168
       * In production, we shouldn't crash =)  But if we do, we should get
Packit Service ed5168
       * restarted by the session infrastructure, which is likely going
Packit Service ed5168
       * to be better than some undefined state.
Packit Service ed5168
       *
Packit Service ed5168
       * If there was a generic "hook into bug-buddy for non-C crashes"
Packit Service ed5168
       * infrastructure, here would be the place to put it.
Packit Service ed5168
       */
Packit Service ed5168
      g_object_unref (gjs_context);
Packit Service ed5168
      exit (1);
Packit Service ed5168
    }
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static ShellWM *
Packit Service ed5168
get_shell_wm (void)
Packit Service ed5168
{
Packit Service ed5168
  ShellWM *wm;
Packit Service ed5168
Packit Service ed5168
  g_object_get (shell_global_get (),
Packit Service ed5168
                "window-manager", &wm,
Packit Service ed5168
                NULL);
Packit Service ed5168
  /* drop extra ref added by g_object_get */
Packit Service ed5168
  g_object_unref (wm);
Packit Service ed5168
Packit Service ed5168
  return wm;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_minimize (MetaPlugin         *plugin,
Packit Service ed5168
			     MetaWindowActor    *actor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_minimize (get_shell_wm (),
Packit Service ed5168
                      actor);
Packit Service ed5168
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_unminimize (MetaPlugin         *plugin,
Packit Service ed5168
                               MetaWindowActor    *actor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_unminimize (get_shell_wm (),
Packit Service ed5168
                      actor);
Packit Service ed5168
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_size_changed (MetaPlugin         *plugin,
Packit Service ed5168
                                 MetaWindowActor    *actor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_size_changed (get_shell_wm (), actor);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_size_change (MetaPlugin         *plugin,
Packit Service ed5168
                                MetaWindowActor    *actor,
Packit Service ed5168
                                MetaSizeChange      which_change,
Packit Service ed5168
                                MetaRectangle      *old_frame_rect,
Packit Service ed5168
                                MetaRectangle      *old_buffer_rect)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_size_change (get_shell_wm (), actor, which_change, old_frame_rect, old_buffer_rect);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_map (MetaPlugin         *plugin,
Packit Service ed5168
                        MetaWindowActor    *actor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_map (get_shell_wm (),
Packit Service ed5168
                 actor);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_destroy (MetaPlugin         *plugin,
Packit Service ed5168
                            MetaWindowActor    *actor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_destroy (get_shell_wm (),
Packit Service ed5168
                     actor);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_switch_workspace (MetaPlugin         *plugin,
Packit Service ed5168
                                     gint                from,
Packit Service ed5168
                                     gint                to,
Packit Service ed5168
                                     MetaMotionDirection direction)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_switch_workspace (get_shell_wm(), from, to, direction);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_kill_window_effects (MetaPlugin         *plugin,
Packit Service ed5168
                                        MetaWindowActor    *actor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_kill_window_effects (get_shell_wm(), actor);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_kill_switch_workspace (MetaPlugin         *plugin)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_kill_switch_workspace (get_shell_wm());
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_show_tile_preview (MetaPlugin      *plugin,
Packit Service ed5168
                                      MetaWindow      *window,
Packit Service ed5168
                                      MetaRectangle   *tile_rect,
Packit Service ed5168
                                      int              tile_monitor)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_show_tile_preview (get_shell_wm (), window, tile_rect, tile_monitor);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_hide_tile_preview (MetaPlugin *plugin)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_hide_tile_preview (get_shell_wm ());
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_show_window_menu (MetaPlugin         *plugin,
Packit Service ed5168
                                     MetaWindow         *window,
Packit Service ed5168
                                     MetaWindowMenuType  menu,
Packit Service ed5168
                                     int                 x,
Packit Service ed5168
                                     int                 y)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_show_window_menu (get_shell_wm (), window, menu, x, y);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_show_window_menu_for_rect (MetaPlugin         *plugin,
Packit Service ed5168
                                              MetaWindow         *window,
Packit Service ed5168
                                              MetaWindowMenuType  menu,
Packit Service ed5168
                                              MetaRectangle      *rect)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_show_window_menu_for_rect (get_shell_wm (), window, menu, rect);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static gboolean
Packit Service ed5168
gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
Packit Service ed5168
                                  XEvent     *xev)
Packit Service ed5168
{
Packit Service ed5168
#ifdef GLX_INTEL_swap_event
Packit Service ed5168
  GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
Packit Service ed5168
Packit Service ed5168
  if (shell_plugin->have_swap_event &&
Packit Service ed5168
      xev->type == (shell_plugin->glx_event_base + GLX_BufferSwapComplete))
Packit Service ed5168
    {
Packit Service ed5168
      GLXBufferSwapComplete *swap_complete_event;
Packit Service ed5168
      swap_complete_event = (GLXBufferSwapComplete *)xev;
Packit Service ed5168
Packit Service ed5168
      /* Buggy early versions of the INTEL_swap_event implementation in Mesa
Packit Service ed5168
       * can send this with a ust of 0. Simplify life for consumers
Packit Service ed5168
       * by ignoring such events */
Packit Service ed5168
      if (swap_complete_event->ust != 0)
Packit Service ed5168
        {
Packit Service ed5168
          gboolean frame_timestamps;
Packit Service ed5168
          g_object_get (shell_plugin->global,
Packit Service ed5168
                        "frame-timestamps", &frame_timestamps,
Packit Service ed5168
                        NULL);
Packit Service ed5168
Packit Service ed5168
          if (frame_timestamps)
Packit Service ed5168
            shell_perf_log_event_x (shell_perf_log_get_default (),
Packit Service ed5168
                                    "glx.swapComplete",
Packit Service ed5168
                                    swap_complete_event->ust);
Packit Service ed5168
        }
Packit Service ed5168
    }
Packit Service ed5168
#endif
Packit Service ed5168
Packit Service ed5168
  return FALSE;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static gboolean
Packit Service ed5168
gnome_shell_plugin_keybinding_filter (MetaPlugin     *plugin,
Packit Service ed5168
                                      MetaKeyBinding *binding)
Packit Service ed5168
{
Packit Service ed5168
  return _shell_wm_filter_keybinding (get_shell_wm (), binding);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin)
Packit Service ed5168
{
Packit Service ed5168
  _shell_wm_confirm_display_change (get_shell_wm ());
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static const MetaPluginInfo *
Packit Service ed5168
gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
Packit Service ed5168
{
Packit Service ed5168
  static const MetaPluginInfo info = {
Packit Service ed5168
    .name = "GNOME Shell",
Packit Service ed5168
    .version = "0.1",
Packit Service ed5168
    .author = "Various",
Packit Service ed5168
    .license = "GPLv2+",
Packit Service ed5168
    .description = "Provides GNOME Shell core functionality"
Packit Service ed5168
  };
Packit Service ed5168
Packit Service ed5168
  return &info;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static MetaCloseDialog *
Packit Service ed5168
gnome_shell_plugin_create_close_dialog (MetaPlugin *plugin,
Packit Service ed5168
                                        MetaWindow *window)
Packit Service ed5168
{
Packit Service ed5168
  return _shell_wm_create_close_dialog (get_shell_wm (), window);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static MetaInhibitShortcutsDialog *
Packit Service ed5168
gnome_shell_plugin_create_inhibit_shortcuts_dialog (MetaPlugin *plugin,
Packit Service ed5168
                                                    MetaWindow *window)
Packit Service ed5168
{
Packit Service ed5168
  return _shell_wm_create_inhibit_shortcuts_dialog (get_shell_wm (), window);
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
Packit Service ed5168
{
Packit Service ed5168
  MetaPluginClass *plugin_class  = META_PLUGIN_CLASS (klass);
Packit Service ed5168
Packit Service ed5168
  plugin_class->start            = gnome_shell_plugin_start;
Packit Service ed5168
  plugin_class->map              = gnome_shell_plugin_map;
Packit Service ed5168
  plugin_class->minimize         = gnome_shell_plugin_minimize;
Packit Service ed5168
  plugin_class->unminimize       = gnome_shell_plugin_unminimize;
Packit Service ed5168
  plugin_class->size_changed     = gnome_shell_plugin_size_changed;
Packit Service ed5168
  plugin_class->size_change      = gnome_shell_plugin_size_change;
Packit Service ed5168
  plugin_class->destroy          = gnome_shell_plugin_destroy;
Packit Service ed5168
Packit Service ed5168
  plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
Packit Service ed5168
Packit Service ed5168
  plugin_class->kill_window_effects   = gnome_shell_plugin_kill_window_effects;
Packit Service ed5168
  plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
Packit Service ed5168
Packit Service ed5168
  plugin_class->show_tile_preview = gnome_shell_plugin_show_tile_preview;
Packit Service ed5168
  plugin_class->hide_tile_preview = gnome_shell_plugin_hide_tile_preview;
Packit Service ed5168
  plugin_class->show_window_menu = gnome_shell_plugin_show_window_menu;
Packit Service ed5168
  plugin_class->show_window_menu_for_rect = gnome_shell_plugin_show_window_menu_for_rect;
Packit Service ed5168
Packit Service ed5168
  plugin_class->xevent_filter     = gnome_shell_plugin_xevent_filter;
Packit Service ed5168
  plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
Packit Service ed5168
Packit Service ed5168
  plugin_class->confirm_display_change = gnome_shell_plugin_confirm_display_change;
Packit Service ed5168
Packit Service ed5168
  plugin_class->plugin_info       = gnome_shell_plugin_plugin_info;
Packit Service ed5168
Packit Service ed5168
  plugin_class->create_close_dialog = gnome_shell_plugin_create_close_dialog;
Packit Service ed5168
  plugin_class->create_inhibit_shortcuts_dialog = gnome_shell_plugin_create_inhibit_shortcuts_dialog;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
static void
Packit Service ed5168
gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
Packit Service ed5168
{
Packit Service ed5168
}