/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
*
* Copyright (C) 2011,2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* 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 .
*
* Authors: Robert Ancell
* Michael Terry
*/
public class MainWindow : Gtk.Window
{
public UserList user_list;
public MenuBar menubar;
private List monitors;
private Background background;
private Gtk.Box login_box;
private uint change_background_timeout = 0;
construct
{
events |= Gdk.EventMask.POINTER_MOTION_MASK;
var accel_group = new Gtk.AccelGroup ();
add_accel_group (accel_group);
var bg_color = Gdk.RGBA ();
bg_color.parse (UGSettings.get_string (UGSettings.KEY_BACKGROUND_COLOR));
override_background_color (Gtk.StateFlags.NORMAL, bg_color);
get_accessible ().set_name (_("Login Screen"));
has_resize_grip = false;
UnityGreeter.add_style_class (this);
realize ();
background = new Background (Gdk.cairo_create (get_window ()).get_target ());
background.draw_grid = UGSettings.get_boolean (UGSettings.KEY_DRAW_GRID);
background.default_background = UGSettings.get_string (UGSettings.KEY_BACKGROUND);
background.set_logo (UGSettings.get_string (UGSettings.KEY_LOGO), UGSettings.get_string (UGSettings.KEY_BACKGROUND_LOGO));
background.show ();
add (background);
UnityGreeter.add_style_class (background);
login_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
login_box.show ();
background.add (login_box);
menubar = new MenuBar (background, accel_group);
menubar.notify["high-contrast"].connect (() => {change_background ();});
menubar.show ();
login_box.add (menubar);
UnityGreeter.add_style_class (menubar);
user_list = new UserList (background, menubar);
user_list.expand = true;
user_list.user_displayed_start.connect (() => {
change_background ();
});
user_list.user_displayed_done.connect (() => {
menubar.set_layouts (user_list.selected_entry.keyboard_layouts);
change_background ();
});
user_list.show ();
login_box.add (user_list);
UnityGreeter.add_style_class (user_list);
if (UnityGreeter.test_mode)
{
/* Simulate an 800x600 monitor to the left of a 640x480 monitor */
monitors = new List ();
monitors.append (new Monitor (0, 0, 800, 600));
monitors.append (new Monitor (800, 120, 640, 480));
background.set_monitors (monitors);
move_to_monitor (monitors.nth_data (0));
resize (800 + 640, 600);
}
else
{
var screen = get_screen ();
screen.monitors_changed.connect (monitors_changed_cb);
monitors_changed_cb (screen);
}
}
private void monitors_changed_cb (Gdk.Screen screen)
{
debug ("Screen is %dx%d pixels", screen.get_width (), screen.get_height ());
monitors = new List ();
for (var i = 0; i < screen.get_n_monitors (); i++)
{
Gdk.Rectangle geometry;
screen.get_monitor_geometry (i, out geometry);
debug ("Monitor %d is %dx%d pixels at %d,%d", i, geometry.width, geometry.height, geometry.x, geometry.y);
if (monitor_is_unique_position (screen, i))
monitors.append (new Monitor (geometry.x, geometry.y, geometry.width, geometry.height));
}
background.set_monitors (monitors);
resize (screen.get_width (), screen.get_height ());
move (0, 0);
move_to_monitor (monitors.nth_data (0));
}
/* Check if a monitor has a unique position */
private bool monitor_is_unique_position (Gdk.Screen screen, int n)
{
Gdk.Rectangle g0;
screen.get_monitor_geometry (n, out g0);
for (var i = n + 1; i < screen.get_n_monitors (); i++)
{
Gdk.Rectangle g1;
screen.get_monitor_geometry (i, out g1);
if (g0.x == g1.x && g0.y == g1.y)
return false;
}
return true;
}
private bool change_background_timeout_cb ()
{
string new_background_file;
if (menubar.high_contrast ||
!UGSettings.get_boolean (UGSettings.KEY_DRAW_USER_BACKGROUNDS))
new_background_file = null;
else
new_background_file = user_list.selected_entry.background;
background.current_background = new_background_file;
change_background_timeout = 0;
return false;
}
private void change_background ()
{
if (background.current_background != null)
{
if (change_background_timeout == 0)
change_background_timeout = Idle.add (change_background_timeout_cb);
}
else
change_background_timeout_cb ();
}
public override bool motion_notify_event (Gdk.EventMotion event)
{
var x = (int) (event.x + 0.5);
var y = (int) (event.y + 0.5);
/* Get motion event relative to this widget */
if (event.window != get_window ())
{
int w_x, w_y;
get_window ().get_origin (out w_x, out w_y);
x -= w_x;
y -= w_y;
event.window.get_origin (out w_x, out w_y);
x += w_x;
y += w_y;
}
foreach (var m in monitors)
{
if (x >= m.x && x <= m.x + m.width && y >= m.y && y <= m.y + m.height)
{
move_to_monitor (m);
break;
}
}
return false;
}
private void move_to_monitor (Monitor monitor)
{
login_box.set_size_request (monitor.width, monitor.height);
background.set_active_monitor (monitor);
background.move (login_box, monitor.x, monitor.y);
}
public override bool key_press_event (Gdk.EventKey event)
{
switch (event.keyval)
{
case Gdk.KEY_Escape:
user_list.cancel_authentication ();
break;
case Gdk.KEY_Page_Up:
case Gdk.KEY_KP_Page_Up:
user_list.scroll (UserList.ScrollTarget.START);
break;
case Gdk.KEY_Page_Down:
case Gdk.KEY_KP_Page_Down:
user_list.scroll (UserList.ScrollTarget.END);
break;
case Gdk.KEY_Up:
case Gdk.KEY_KP_Up:
user_list.scroll (UserList.ScrollTarget.UP);
break;
case Gdk.KEY_Down:
case Gdk.KEY_KP_Down:
user_list.scroll (UserList.ScrollTarget.DOWN);
break;
case Gdk.KEY_F10:
menubar.select_first (false);
break;
default:
return base.key_press_event (event);
}
return true;
}
}