[ShellGlobal] add SHELL_STAGE_INPUT_MODE_FOCUSED

Add SHELL_STAGE_INPUT_MODE_FOCUSED, to move the keyboard focus to the
shell without grabbing the keyboard or mouse, and make
stage_input_mode into a GObject property so that (among other things),
callers can tell when MODE_FOCUSED reverts back to MODE_NORMAL.

https://bugzilla.gnome.org/show_bug.cgi?id=623429
This commit is contained in:
Dan Winship 2010-07-02 13:36:13 -04:00
parent 6259513b0f
commit adbf3b1c37
2 changed files with 68 additions and 1 deletions

View File

@ -3,7 +3,9 @@
#include "config.h"
#include "shell-global-private.h"
#include "shell-enum-types.h"
#include "shell-perf-log.h"
#include "shell-window-tracker.h"
#include "shell-wm.h"
#include "display.h"
@ -74,6 +76,7 @@ enum {
PROP_SCREEN_WIDTH,
PROP_SCREEN_HEIGHT,
PROP_STAGE,
PROP_STAGE_INPUT_MODE,
PROP_WINDOW_GROUP,
PROP_WINDOW_MANAGER,
PROP_SETTINGS,
@ -90,8 +93,14 @@ shell_global_set_property(GObject *object,
const GValue *value,
GParamSpec *pspec)
{
ShellGlobal *global = SHELL_GLOBAL (object);
switch (prop_id)
{
case PROP_STAGE_INPUT_MODE:
shell_global_set_stage_input_mode (global, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -136,6 +145,9 @@ shell_global_get_property(GObject *object,
case PROP_STAGE:
g_value_set_object (value, mutter_plugin_get_stage (global->plugin));
break;
case PROP_STAGE_INPUT_MODE:
g_value_set_enum (value, global->input_mode);
break;
case PROP_WINDOW_GROUP:
g_value_set_object (value, mutter_plugin_get_window_group (global->plugin));
break;
@ -254,6 +266,14 @@ shell_global_class_init (ShellGlobalClass *klass)
"Stage holding the desktop scene graph",
CLUTTER_TYPE_ACTOR,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_STAGE_INPUT_MODE,
g_param_spec_enum ("stage-input-mode",
"Stage input mode",
"The stage input mode",
SHELL_TYPE_STAGE_INPUT_MODE,
SHELL_STAGE_INPUT_MODE_NORMAL,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_WINDOW_GROUP,
g_param_spec_object ("window-group",
@ -341,6 +361,32 @@ shell_global_get (void)
return the_object;
}
static void
focus_window_changed (MetaDisplay *display,
GParamSpec *param,
gpointer user_data)
{
ShellGlobal *global = user_data;
if (global->input_mode == SHELL_STAGE_INPUT_MODE_FOCUSED &&
meta_display_get_focus_window (display) != NULL)
shell_global_set_stage_input_mode (global, SHELL_STAGE_INPUT_MODE_NORMAL);
}
static void
shell_global_focus_stage (ShellGlobal *global)
{
Display *xdpy;
ClutterActor *stage;
Window xstage;
stage = mutter_plugin_get_stage (global->plugin);
xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
xdpy = mutter_plugin_get_xdisplay (global->plugin);
XSetInputFocus (xdpy, xstage, RevertToPointerRoot,
shell_global_get_current_time (global));
}
/**
* shell_global_set_stage_input_mode:
* @global: the #ShellGlobal
@ -355,6 +401,12 @@ shell_global_get (void)
* outside that region. When it is %SHELL_STAGE_INPUT_MODE_FULLSCREEN,
* the stage absorbs all input.
*
* When the input mode is %SHELL_STAGE_INPUT_MODE_FOCUSED, the pointer
* is handled as with %SHELL_STAGE_INPUT_MODE_NORMAL, but additionally
* the stage window has the keyboard focus. If the stage loses the
* focus (eg, because the user clicked into a window) the input mode
* will revert to %SHELL_STAGE_INPUT_MODE_NORMAL.
*
* Note that whenever a mutter-internal Gtk widget has a pointer grab,
* the shell behaves as though it was in
* %SHELL_STAGE_INPUT_MODE_NONREACTIVE, to ensure that the widget gets
@ -373,7 +425,14 @@ shell_global_set_stage_input_mode (ShellGlobal *global,
else
mutter_plugin_set_stage_input_region (global->plugin, global->input_region);
if (mode == SHELL_STAGE_INPUT_MODE_FOCUSED)
shell_global_focus_stage (global);
if (mode != global->input_mode)
{
global->input_mode = mode;
g_object_notify (G_OBJECT (global), "stage-input-mode");
}
}
/**
@ -535,6 +594,8 @@ _shell_global_set_plugin (ShellGlobal *global,
MutterPlugin *plugin)
{
ClutterActor *stage;
MetaScreen *screen;
MetaDisplay *display;
g_return_if_fail (SHELL_IS_GLOBAL (global));
g_return_if_fail (global->plugin == NULL);
@ -563,6 +624,11 @@ _shell_global_set_plugin (ShellGlobal *global,
"clutter.stagePaintDone",
"End of stage page repaint",
"");
screen = mutter_plugin_get_screen (global->plugin);
display = meta_screen_get_display (screen);
g_signal_connect (display, "notify::focus-window",
G_CALLBACK (focus_window_changed), global);
}
void

View File

@ -51,6 +51,7 @@ void shell_global_grab_dbus_service (ShellGlobal *global);
typedef enum {
SHELL_STAGE_INPUT_MODE_NONREACTIVE,
SHELL_STAGE_INPUT_MODE_NORMAL,
SHELL_STAGE_INPUT_MODE_FOCUSED,
SHELL_STAGE_INPUT_MODE_FULLSCREEN
} ShellStageInputMode;