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