summaryrefslogtreecommitdiff
path: root/gui/greeter/greeter_item_capslock.c
blob: a0297ad6d2f1e5fb6b631f848c5ed8c9c4d473ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "config.h"

#include <gtk/gtk.h>
#include <libgnome/libgnome.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <gdk/gdkx.h>
#include <X11/XKBlib.h>

#include "greeter_parser.h"
#include "greeter_item_capslock.h"


static gboolean caps_lock_state = FALSE;

static Display *
get_parent_display (void)
{
  static gboolean tested = FALSE;
  static Display *dsp = NULL;

  if (tested)
    return dsp;

  tested = TRUE;

  if (g_getenv ("GDM_PARENT_DISPLAY") != NULL)
    {
      char *old_xauth = g_strdup (g_getenv ("XAUTHORITY"));
      if (g_getenv ("GDM_PARENT_XAUTHORITY") != NULL)
        {
	  gnome_setenv ("XAUTHORITY",
			g_getenv ("GDM_PARENT_XAUTHORITY"), TRUE);
	}
      dsp = XOpenDisplay (g_getenv ("GDM_PARENT_DISPLAY"));
      if (old_xauth != NULL)
        gnome_setenv ("XAUTHORITY", old_xauth, TRUE);
      else
        gnome_unsetenv ("XAUTHORITY");
      g_free (old_xauth);
    }

  return dsp;
}

static gboolean
is_caps_lock_on (void)
{
  unsigned int states;
  Display *dsp;

  /* HACK! incredible hack, if this is set we get
   * indicator state from the parent display, since we must be inside an
   * Xnest */
  dsp = get_parent_display ();
  if (dsp == NULL)
    dsp = GDK_DISPLAY ();

  if (XkbGetIndicatorState (dsp, XkbUseCoreKbd, &states) != Success)
      return FALSE;

  return (states & ShiftMask) != 0;
}


static void
capslock_update (gboolean new_state)
{
  GreeterItemInfo *info;
  GnomeCanvasItem *item;

  caps_lock_state = new_state;
  
  info = greeter_lookup_id ("caps-lock-warning");

  if (info)
    {
      if (info->group_item != NULL)
	item = GNOME_CANVAS_ITEM (info->group_item);
      else
	item = info->item;

      if (caps_lock_state)
        {
	  gnome_canvas_item_show (item);
	}
      else
        {
	  gnome_canvas_item_hide (item);
	}
    }
}

static gboolean
cl_key_press_event (GtkWidget *widget, GdkEventKey *key, gpointer data)
{
  gboolean new_state;

  new_state = is_caps_lock_on ();
  if (new_state != caps_lock_state)
    capslock_update (new_state);
  
  return FALSE;
}


gboolean
greeter_item_capslock_setup (GtkWidget *window)
{
  capslock_update (is_caps_lock_on ());
  
  g_signal_connect (G_OBJECT (window), "key_press_event",
		    G_CALLBACK (cl_key_press_event), NULL);
  return TRUE;
}