1 /*
2  * Copyright (C) 2018 Red Hat
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17  * 02111-1307, USA.
18  *
19  * Author: Carlos Garnacho <carlosg@gnome.org>
20  */
21 
22 #include "clutter-build-config.h"
23 
24 #include "clutter-keymap-private.h"
25 #include "clutter-private.h"
26 
27 enum
28 {
29   PROP_0,
30 
31   PROP_CAPS_LOCK_STATE,
32   PROP_NUM_LOCK_STATE,
33 
34   N_PROPS
35 };
36 
37 static GParamSpec *obj_props[N_PROPS];
38 
39 typedef struct _ClutterKeymapPrivate
40 {
41   gboolean caps_lock_state;
42   gboolean num_lock_state;
43 } ClutterKeymapPrivate;
44 
45 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterKeymap, clutter_keymap,
46                                      G_TYPE_OBJECT)
47 
48 enum
49 {
50   STATE_CHANGED,
51   N_SIGNALS
52 };
53 
54 static guint signals[N_SIGNALS] = { 0, };
55 
56 static void
clutter_keymap_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)57 clutter_keymap_get_property (GObject    *object,
58                              guint       prop_id,
59                              GValue     *value,
60                              GParamSpec *pspec)
61 {
62   ClutterKeymap *keymap = CLUTTER_KEYMAP (object);
63   ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
64 
65   switch (prop_id)
66     {
67     case PROP_CAPS_LOCK_STATE:
68       g_value_set_boolean (value, priv->caps_lock_state);
69       break;
70     case PROP_NUM_LOCK_STATE:
71       g_value_set_boolean (value, priv->num_lock_state);
72       break;
73     default:
74       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
75       break;
76     }
77 }
78 
79 static void
clutter_keymap_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)80 clutter_keymap_set_property (GObject      *object,
81                              guint         prop_id,
82                              const GValue *value,
83                              GParamSpec   *pspec)
84 {
85   ClutterKeymap *keymap = CLUTTER_KEYMAP (object);
86   ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
87 
88   switch (prop_id)
89     {
90     case PROP_CAPS_LOCK_STATE:
91       priv->caps_lock_state = g_value_get_boolean (value);
92       break;
93     case PROP_NUM_LOCK_STATE:
94       priv->num_lock_state = g_value_get_boolean (value);
95       break;
96     default:
97       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
98       break;
99     }
100 }
101 
102 static void
clutter_keymap_class_init(ClutterKeymapClass * klass)103 clutter_keymap_class_init (ClutterKeymapClass *klass)
104 {
105   GObjectClass *object_class = G_OBJECT_CLASS (klass);
106 
107   object_class->get_property = clutter_keymap_get_property;
108   object_class->set_property = clutter_keymap_set_property;
109 
110   obj_props[PROP_CAPS_LOCK_STATE] =
111     g_param_spec_boolean ("caps-lock-state",
112                           "Caps lock state",
113                           "Caps lock state",
114                           FALSE,
115                           G_PARAM_READABLE |
116                           G_PARAM_STATIC_STRINGS);
117   obj_props[PROP_NUM_LOCK_STATE] =
118     g_param_spec_boolean ("num-lock-state",
119                           "Num lock state",
120                           "Num lock state",
121                           FALSE,
122                           G_PARAM_READABLE |
123                           G_PARAM_STATIC_STRINGS);
124   g_object_class_install_properties (object_class, N_PROPS, obj_props);
125 
126   signals[STATE_CHANGED] =
127     g_signal_new (I_("state-changed"),
128 		  G_TYPE_FROM_CLASS (klass),
129 		  G_SIGNAL_RUN_FIRST,
130 		  0, NULL, NULL,
131                   g_cclosure_marshal_VOID__VOID,
132 		  G_TYPE_NONE, 0);
133 }
134 
135 static void
clutter_keymap_init(ClutterKeymap * keymap)136 clutter_keymap_init (ClutterKeymap *keymap)
137 {
138 }
139 
140 gboolean
clutter_keymap_get_num_lock_state(ClutterKeymap * keymap)141 clutter_keymap_get_num_lock_state (ClutterKeymap *keymap)
142 {
143   ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
144 
145   return priv->num_lock_state;
146 }
147 
148 gboolean
clutter_keymap_get_caps_lock_state(ClutterKeymap * keymap)149 clutter_keymap_get_caps_lock_state (ClutterKeymap *keymap)
150 {
151   ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
152 
153   return priv->caps_lock_state;
154 }
155 
156 PangoDirection
clutter_keymap_get_direction(ClutterKeymap * keymap)157 clutter_keymap_get_direction (ClutterKeymap *keymap)
158 {
159   return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_direction (keymap);
160 }
161 
162 void
clutter_keymap_set_lock_modifier_state(ClutterKeymap * keymap,gboolean caps_lock_state,gboolean num_lock_state)163 clutter_keymap_set_lock_modifier_state (ClutterKeymap *keymap,
164                                         gboolean       caps_lock_state,
165                                         gboolean       num_lock_state)
166 {
167   ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
168 
169   if (priv->caps_lock_state == caps_lock_state &&
170       priv->num_lock_state == num_lock_state)
171     return;
172 
173   if (priv->caps_lock_state != caps_lock_state)
174     {
175       priv->caps_lock_state = caps_lock_state;
176       g_object_notify_by_pspec (G_OBJECT (keymap),
177                                 obj_props[PROP_CAPS_LOCK_STATE]);
178     }
179 
180   if (priv->num_lock_state != num_lock_state)
181     {
182       priv->num_lock_state = num_lock_state;
183       g_object_notify_by_pspec (G_OBJECT (keymap),
184                                 obj_props[PROP_NUM_LOCK_STATE]);
185     }
186 
187   g_debug ("Locks state changed - Num: %s, Caps: %s",
188            priv->num_lock_state ? "set" : "unset",
189            priv->caps_lock_state ? "set" : "unset");
190 
191   g_signal_emit (keymap, signals[STATE_CHANGED], 0);
192 }
193