mirror of
https://github.com/elementary/gala.git
synced 2024-12-19 07:11:56 +03:00
e26d4274a0
plugin info allowing plugins to replace built-in componenets, allow them to delay their load.
191 lines
7.3 KiB
Vala
191 lines
7.3 KiB
Vala
//
|
|
// Copyright (C) 2014 Tom Beckmann
|
|
//
|
|
// 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 3 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/>.
|
|
//
|
|
|
|
// note on compilation: If you want your own plugin within this source tree
|
|
// don't forget to add the new subdirectory to the plugins' Makefile.am
|
|
// SUBDIRS list and add your Makefile to the list of Makefiles found at
|
|
// about the end of the configure.ac file AC_CONFIG_FILES.
|
|
// The API is currently internal until the API is finalized, so you have
|
|
// to build it in this source tree.
|
|
|
|
/*
|
|
This is a template class showing some of the things that can be done
|
|
with a gala plugin and how to do them.
|
|
*/
|
|
|
|
namespace Gala.Plugins.Template
|
|
{
|
|
public class Main : Gala.Plugin
|
|
{
|
|
Gala.WindowManager? wm = null;
|
|
const int PADDING = 50;
|
|
|
|
Clutter.Actor red_box;
|
|
|
|
// This function is called as soon as Gala has started and gives you
|
|
// an instance of the GalaWindowManager class.
|
|
public override void initialize (Gala.WindowManager wm)
|
|
{
|
|
// we will save the instance to our wm property so we can use it later again
|
|
// especially helpful when you have larger plugins with more functions,
|
|
// we won't need it here
|
|
this.wm = wm;
|
|
|
|
// for demonstration purposes we'll add a red quad to the stage which will
|
|
// turn green when clicked
|
|
red_box = new Clutter.Actor ();
|
|
red_box.set_size (100, 100);
|
|
red_box.background_color = { 255, 0, 0, 255 };
|
|
red_box.reactive = true;
|
|
red_box.button_press_event.connect (turn_green);
|
|
|
|
// we want to place it in the lower right of the primary monitor with a bit
|
|
// of padding. refer to vapi/libmutter.vapi in gala's source for something
|
|
// remotely similar to a documentation
|
|
var screen = wm.get_screen ();
|
|
var rect = screen.get_monitor_geometry (screen.get_primary_monitor ());
|
|
|
|
red_box.x = rect.x + rect.width - red_box.width - PADDING;
|
|
red_box.y = rect.y + rect.height - red_box.height - PADDING;
|
|
|
|
// to order Gala to deliver mouse events to our box instead of the underlying
|
|
// windows, we need to mark the region where the quad is located.
|
|
// The plugin class offers an utility function for this purpose, the track_actor
|
|
// function. It will update the region with the allocation of the actor
|
|
// whenever its allocation changes. Make sure to set freeze_track to
|
|
// true while animating the actor to not make gala update the region
|
|
// every single frame.
|
|
// You can also handle the region manually by setting the custom_region
|
|
// property. The tracked actors and custom regions will be merged by
|
|
// the plugin.
|
|
track_actor (red_box);
|
|
|
|
// now we'll add our box into the ui_group. This is where all the shell
|
|
// elements and also the windows and backgrouds are located.
|
|
wm.ui_group.add_child (red_box);
|
|
}
|
|
|
|
bool turn_green (Clutter.ButtonEvent event)
|
|
{
|
|
red_box.background_color = { 0, 255, 0, 255 };
|
|
return true;
|
|
}
|
|
|
|
// This function is actually not even called by Gala at the moment,
|
|
// still it might be a good idea to implement it anyway to make sure
|
|
// your plugin is compatible in case we'd add disabling specific plugins
|
|
// in the future
|
|
public override void destroy ()
|
|
{
|
|
// here you would destroy actors you added to the stage or remove
|
|
// keybindings
|
|
|
|
red_box.destroy ();
|
|
}
|
|
}
|
|
}
|
|
|
|
// this little function just tells Gala which class of those you may have in
|
|
// your plugin is the one you want to start with and delivers some additional
|
|
// details about your plugin. It also gives you the option to choose a specific
|
|
// function which your plugin fulfils. Gala will then make sure that there is
|
|
// no duplicate functionality.
|
|
public Gala.PluginInfo register_plugin ()
|
|
{
|
|
return {
|
|
"template-plugin", // the plugin's name
|
|
"Tom Beckmann <tomjonabc@gmail.com>", // you, the author
|
|
typeof (Gala.Plugins.Template.Main), // the type of your plugin class
|
|
|
|
Gala.PluginFunction.ADDITION, // the function which your plugin
|
|
// fulfils, ADDITION means nothing
|
|
// specific
|
|
|
|
false // indicates whether your plugin's
|
|
// start can be delayed until gala
|
|
// has loaded the important stuff or
|
|
// if you want your plugin to start
|
|
// right away. False means wait.
|
|
};
|
|
}
|
|
|
|
/*
|
|
|
|
Some more useful stuff:
|
|
|
|
Modal Mode
|
|
----------
|
|
If you want to display large elements that can be toggled instead of small overlays,
|
|
you can use wm.begin_modal() to make Gala enter modal mode. In this mode, you'll be
|
|
able to receive key events and all mouse events will be delivered regardless of the
|
|
region you have set. Don't forget to call wm.end_modal() and provide an obvious way
|
|
to exit modal mode for the user, otherwise he will be stuck and can only restart
|
|
Gala.
|
|
|
|
Keybindings
|
|
-----------
|
|
To add keybindings, you'll need a gsettings schema. You can take a look at Gala's
|
|
schema in data/org.pantheon.desktop.gschema.xml for an example. You'll also find
|
|
how to correctly declare shortcut keys in that file. Once you got this file ready
|
|
it's pretty easy. Just enable its installation in cmake, the relevant is commented
|
|
out in this template, and call wm.get_screen().get_display().add_keybinding().
|
|
The keybinding function takes the name of the shortcut key in your
|
|
schema, then a GSettings instance for that schema, which can be obtained with
|
|
'new GLib.Settings("org.pantheon.gala.plugins.my-plugin")', then some flags, for
|
|
which you can almost always use 0, refer to the vapi for more details, and finally
|
|
your function as arguments. Its delegate is:
|
|
|
|
public delegate void KeyHandlerFunc (Meta.Display display, Meta.Screen screen,
|
|
Meta.Window? window, X.Event event, Meta.KeyBinding binding);
|
|
|
|
So it'd be something like
|
|
|
|
void initialize (Gala.WindowManager wm)
|
|
{
|
|
[...]
|
|
var display = wm.get_screen ().get_display ();
|
|
var schema = new GLib.Settings ("org.pantheon.desktop.gala.plugins");
|
|
display.add_keybinding ("my-shortcut", schema, 0, my_handler);
|
|
[...]
|
|
}
|
|
void my_handler (Meta.Display display, Meta.Screen screen, Meta.Window? window,
|
|
X.Event event, Meta.KeyBinding binding)
|
|
{
|
|
print ("Shortcut hit! D:");
|
|
}
|
|
void destroy ()
|
|
{
|
|
wm.get_screen ().get_display ().remove_keybinding ("my-shortcut");
|
|
}
|
|
|
|
Overriding default keybindings
|
|
------------------------------
|
|
Libmutter allows you to override exisiting shortcuts, which is a lot easier than
|
|
adding new ones. All you have to do is:
|
|
|
|
Keybinding.set_custom_handler ("shortcut-name", my_handler);
|
|
|
|
The signature for my_handler is the same as above.
|
|
|
|
More info
|
|
---------
|
|
A great source for exploring the possibilities of mutter's API is scrolling through
|
|
the mentioned mutter vapi. In some cases you can find documentation on particular
|
|
functions in the mutter source code. Just grep for their C names.
|
|
|
|
*/
|