172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_floating_container.h"
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/rounded_window.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_strings.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Padding around the link text.
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kPaddingPixels = 8;
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Time before the link slides away. This is a bit longer than the Windows
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// timeout because we don't yet support reshowing when the mouse moves to the
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of the screen.
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kInitialDelayMs = 3000;
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How long the slide up animation takes when hiding the bubble.
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kSlideOutDurationMs = 700;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFullscreenExitBubbleGtk::FullscreenExitBubbleGtk(
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkFloatingContainer* container)
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : container_(container) {
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitWidgets();
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFullscreenExitBubbleGtk::~FullscreenExitBubbleGtk() {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FullscreenExitBubbleGtk::InitWidgets() {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The exit bubble is a gtk_chrome_link_button inside a gtk event box and gtk
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // alignment (these provide the background color).  This is then made rounded
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and put into a slide widget.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The Windows code actually looks up the accelerator key in the accelerator
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // table and then converts the key to a string (in a switch statement).
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string exit_text_utf8("<span color=\"white\" size=\"large\">");
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exit_text_utf8.append(l10n_util::GetStringFUTF8(
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDS_EXIT_FULLSCREEN_MODE, l10n_util::GetStringUTF16(IDS_APP_F11_KEY)));
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exit_text_utf8.append("</span>");
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* link = gtk_chrome_link_button_new_with_markup(
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exit_text_utf8.c_str());
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_chrome_link_button_set_use_gtk_theme(GTK_CHROME_LINK_BUTTON(link),
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           FALSE);
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  signals_.Connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  GtkWidget* container = gtk_util::CreateGtkBorderBin(
57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      link, &gtk_util::kGdkBlack,
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kPaddingPixels, kPaddingPixels, kPaddingPixels, kPaddingPixels);
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  gtk_util::ActAsRoundedWindow(container, gtk_util::kGdkGreen, kPaddingPixels,
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_util::ROUNDED_BOTTOM_LEFT | gtk_util::ROUNDED_BOTTOM_RIGHT,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_util::BORDER_NONE);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  slide_widget_.reset(new SlideAnimatorGtk(container,
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SlideAnimatorGtk::DOWN, kSlideOutDurationMs, false, false, NULL));
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_name(widget(), "exit-fullscreen-bubble");
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(container);
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show(widget());
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  slide_widget_->OpenWithoutAnimation();
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(tc): Implement the more complex logic in the windows version for
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when to show/hide the exit bubble.
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  initial_delay_.Start(base::TimeDelta::FromMilliseconds(kInitialDelayMs), this,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       &FullscreenExitBubbleGtk::Hide);
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(container_),
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      widget());
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  signals_.Connect(container_, "set-floating-position",
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnSetFloatingPositionThunk), this);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FullscreenExitBubbleGtk::Hide() {
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  slide_widget_->Close();
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FullscreenExitBubbleGtk::OnSetFloatingPosition(
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* floating_container,
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkAllocation* allocation) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition bubble_size;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_size_request(widget(), &bubble_size);
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Position the bubble at the top center of the screen.
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GValue value = { 0, };
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_init(&value, G_TYPE_INT);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_set_int(&value, (allocation->width - bubble_size.width) / 2);
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   widget(), "x", &value);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_set_int(&value, 0);
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   widget(), "y", &value);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_value_unset(&value);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(widget()));
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_unfullscreen(window);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
108