root/chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. container_
  2. UpdateContent
  3. InitWidgets
  4. GetMessage
  5. GetPopupRect
  6. GetCursorScreenPoint
  7. WindowContainsPoint
  8. IsWindowActive
  9. Hide
  10. Show
  11. IsAnimating
  12. CanMouseTriggerSlideIn
  13. StartWatchingMouseIfNecessary
  14. OnSetFloatingPosition
  15. OnLinkClicked
  16. OnAllowClicked
  17. OnDenyClicked
  18. Observe

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h"

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "chrome/browser/ui/gtk/rounded_window.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_widget_host_view.h"
#include "grit/generated_resources.h"
#include "grit/ui_strings.h"
#include "ui/base/gtk/gtk_floating_container.h"
#include "ui/base/gtk/gtk_hig_constants.h"
#include "ui/base/l10n/l10n_util.h"

namespace {

const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff);
const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63);

}  // namespace

FullscreenExitBubbleGtk::FullscreenExitBubbleGtk(
    GtkFloatingContainer* container,
    Browser* browser,
    const GURL& url,
    FullscreenExitBubbleType bubble_type)
    : FullscreenExitBubble(browser, url, bubble_type),
      theme_service_(NULL),
      bubble_(NULL),
      container_(container) {
  InitWidgets();
}

FullscreenExitBubbleGtk::~FullscreenExitBubbleGtk() {
}

void FullscreenExitBubbleGtk::UpdateContent(
    const GURL& url,
    FullscreenExitBubbleType bubble_type) {
  if (bubble_type == FEB_TYPE_NONE) {
    NOTREACHED();
    bubble_type = FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION;
  }

  url_ = url;
  bubble_type_ = bubble_type;

  gtk_label_set_text(GTK_LABEL(message_label_),
                     base::UTF16ToUTF8(GetCurrentMessageText()).c_str());
  if (fullscreen_bubble::ShowButtonsForType(bubble_type)) {
    gtk_widget_hide(link_);
    gtk_widget_hide(instruction_label_);
    gtk_widget_show(allow_button_);
    gtk_button_set_label(GTK_BUTTON(deny_button_),
                         base::UTF16ToUTF8(GetCurrentDenyButtonText()).c_str());
    gtk_widget_show(deny_button_);
  } else {
    bool link_visible = true;
    base::string16 accelerator;
    if (bubble_type == FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION ||
        bubble_type ==
            FEB_TYPE_BROWSER_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION) {
      accelerator = l10n_util::GetStringUTF16(IDS_APP_F11_KEY);
    } else if (bubble_type == FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION) {
      accelerator = l10n_util::GetStringUTF16(IDS_APP_ESC_KEY);
    } else {
      link_visible = false;
    }
    if (link_visible) {
      std::string exit_link_text(
          l10n_util::GetStringUTF8(IDS_EXIT_FULLSCREEN_MODE) + " " +
          l10n_util::GetStringFUTF8(IDS_EXIT_FULLSCREEN_MODE_ACCELERATOR,
              accelerator));
      gtk_chrome_link_button_set_label(GTK_CHROME_LINK_BUTTON(link_),
          exit_link_text.c_str());
      gtk_widget_show(link_);
      gtk_widget_hide(instruction_label_);
    } else {
      gtk_widget_hide(link_);
      gtk_widget_show(instruction_label_);
    }
    gtk_widget_hide(allow_button_);
    gtk_widget_hide(deny_button_);
  }

  Show();
  StopWatchingMouse();
  StartWatchingMouseIfNecessary();
}

void FullscreenExitBubbleGtk::InitWidgets() {
  theme_service_ = GtkThemeService::GetFrom(browser_->profile());

  hbox_ = gtk_hbox_new(false, ui::kControlSpacing);

  message_label_ = theme_service_->BuildLabel(GetMessage(url_).c_str(),
                                              ui::kGdkBlack);
  gtk_box_pack_start(GTK_BOX(hbox_), message_label_, FALSE, FALSE, 0);

  allow_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_FULLSCREEN_ALLOW).c_str());
  gtk_widget_set_can_focus(allow_button_, FALSE);
  gtk_widget_set_no_show_all(allow_button_, FALSE);
  gtk_box_pack_start(GTK_BOX(hbox_), allow_button_, FALSE, FALSE, 0);

  deny_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_FULLSCREEN_DENY).c_str());
  gtk_widget_set_can_focus(deny_button_, FALSE);
  gtk_widget_set_no_show_all(deny_button_, FALSE);
  gtk_box_pack_start(GTK_BOX(hbox_), deny_button_, FALSE, FALSE, 0);

  link_ = gtk_chrome_link_button_new("");
  gtk_widget_set_can_focus(link_, FALSE);
  gtk_widget_set_no_show_all(link_, FALSE);
  gtk_chrome_link_button_set_use_gtk_theme(GTK_CHROME_LINK_BUTTON(link_),
                                           FALSE);
  gtk_box_pack_start(GTK_BOX(hbox_), link_, FALSE, FALSE, 0);

  instruction_label_ =
      gtk_label_new(base::UTF16ToUTF8(GetInstructionText()).c_str());
  gtk_widget_set_no_show_all(instruction_label_, FALSE);
  gtk_box_pack_start(GTK_BOX(hbox_), instruction_label_, FALSE, FALSE, 0);

  bubble_ = gtk_util::CreateGtkBorderBin(
      hbox_, &ui::kGdkWhite,
      kPaddingPx, kPaddingPx, kPaddingPx, kPaddingPx);
  gtk_util::ActAsRoundedWindow(bubble_, kFrameColor, 3,
      gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
  gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 0, 0, 0);
  gtk_container_add(GTK_CONTAINER(alignment), bubble_);
  ui_container_.Own(alignment);

  slide_widget_.reset(new SlideAnimatorGtk(ui_container_.get(),
      SlideAnimatorGtk::DOWN, kSlideOutDurationMs, false, false, NULL));
  gtk_widget_set_name(widget(), "exit-fullscreen-bubble");
  gtk_widget_show_all(ui_container_.get());
  gtk_widget_show(widget());
  slide_widget_->OpenWithoutAnimation();

  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(container_),
                                      widget());

  signals_.Connect(container_, "set-floating-position",
                   G_CALLBACK(OnSetFloatingPositionThunk), this);
  signals_.Connect(link_, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
  signals_.Connect(allow_button_, "clicked",
                   G_CALLBACK(&OnAllowClickedThunk), this);
  signals_.Connect(deny_button_, "clicked",
                   G_CALLBACK(&OnDenyClickedThunk), this);

  UpdateContent(url_, bubble_type_);

  theme_service_->InitThemesFor(this);
  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
                 content::Source<ThemeService>(theme_service_));
}

std::string FullscreenExitBubbleGtk::GetMessage(const GURL& url) {
  if (url.is_empty())
    return l10n_util::GetStringUTF8(IDS_FULLSCREEN_USER_ENTERED_FULLSCREEN);

  if (url.SchemeIsFile())
    return l10n_util::GetStringUTF8(IDS_FULLSCREEN_ENTERED_FULLSCREEN);
  return l10n_util::GetStringFUTF8(IDS_FULLSCREEN_SITE_ENTERED_FULLSCREEN,
      base::UTF8ToUTF16(url.host()));
}

gfx::Rect FullscreenExitBubbleGtk::GetPopupRect(
    bool ignore_animation_state) const {
  GtkRequisition bubble_size;
  if (ignore_animation_state) {
    gtk_widget_size_request(ui_container_.get(), &bubble_size);
  } else {
    gtk_widget_size_request(widget(), &bubble_size);
  }
  return gfx::Rect(bubble_size.width, bubble_size.height);
}

gfx::Point FullscreenExitBubbleGtk::GetCursorScreenPoint() {
  GdkDisplay* display = gtk_widget_get_display(widget());

  // Get cursor position.
  // TODO: this hits the X server, so we may want to consider decreasing
  // kPositionCheckHz if we detect that we're running remotely.
  int x, y;
  gdk_display_get_pointer(display, NULL, &x, &y, NULL);

  return gfx::Point(x, y);
}

bool FullscreenExitBubbleGtk::WindowContainsPoint(gfx::Point pos) {
  GtkWindow* window = GTK_WINDOW(
      gtk_widget_get_ancestor(widget(), GTK_TYPE_WINDOW));
  int width, height, x, y;
  gtk_window_get_size(window, &width, &height);
  gtk_window_get_position(window, &x, &y);
  return gfx::Rect(x, y, width, height).Contains(pos);
}

bool FullscreenExitBubbleGtk::IsWindowActive() {
  if (!gtk_widget_get_parent(widget()))
    return false;
  GtkWindow* window = GTK_WINDOW(
      gtk_widget_get_ancestor(widget(), GTK_TYPE_WINDOW));
  return gtk_window_is_active(window);
}

void FullscreenExitBubbleGtk::Hide() {
  slide_widget_->Close();
}

void FullscreenExitBubbleGtk::Show() {
  slide_widget_->Open();
}

bool FullscreenExitBubbleGtk::IsAnimating() {
  return slide_widget_->IsAnimating();
}

bool FullscreenExitBubbleGtk::CanMouseTriggerSlideIn() const {
  return true;
}

void FullscreenExitBubbleGtk::StartWatchingMouseIfNecessary() {
  if (!fullscreen_bubble::ShowButtonsForType(bubble_type_))
    StartWatchingMouse();
}

void FullscreenExitBubbleGtk::OnSetFloatingPosition(
    GtkWidget* floating_container,
    GtkAllocation* allocation) {
  GtkRequisition bubble_size;
  gtk_widget_size_request(widget(), &bubble_size);

  // Position the bubble at the top center of the screen.
  GValue value = { 0, };
  g_value_init(&value, G_TYPE_INT);
  g_value_set_int(&value, (allocation->width - bubble_size.width) / 2);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget(), "x", &value);

  g_value_set_int(&value, 0);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget(), "y", &value);
  g_value_unset(&value);
}

void FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link) {
  ToggleFullscreen();
}

void FullscreenExitBubbleGtk::OnAllowClicked(GtkWidget* button) {
  Accept();
}

void FullscreenExitBubbleGtk::OnDenyClicked(GtkWidget* button) {
  Cancel();
}

void FullscreenExitBubbleGtk::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED);
  if (theme_service_->UsingNativeTheme())
    gtk_widget_modify_bg(bubble_, GTK_STATE_NORMAL, NULL);
  else
    gtk_widget_modify_bg(bubble_, GTK_STATE_NORMAL, &kBackgroundColor);
}

/* [<][>][^][v][top][bottom][index][help] */