<commit_before>// Copyright (c) 2009 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/gtk/browser_window_gtk.h"

#include <gdk/gdkkeysyms.h>

#include "base/base_paths_linux.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/find_bar_controller.h"
#include "chrome/browser/gtk/browser_toolbar_gtk.h"
#include "chrome/browser/gtk/find_bar_gtk.h"
#include "chrome/browser/gtk/nine_box.h"
#include "chrome/browser/gtk/status_bubble_gtk.h"
#include "chrome/browser/gtk/tab_contents_container_gtk.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/controls/button/text_button.h"
#include "grit/theme_resources.h"

namespace {

static GdkPixbuf* LoadThemeImage(int resource_id) {
  // TODO(mmoss) refactor -- stolen from custom_button.cc
  if (0 == resource_id)
    return NULL;

  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  std::vector<unsigned char> data;
  rb.LoadImageResourceBytes(resource_id, &data);

  GdkPixbufLoader* loader = gdk_pixbuf_loader_new();
  bool ok = gdk_pixbuf_loader_write(loader, static_cast<guint8*>(data.data()),
      data.size(), NULL);
  DCHECK(ok) << "failed to write " << resource_id;
  // Calling gdk_pixbuf_loader_close forces the data to be parsed by the
  // loader.  We must do this before calling gdk_pixbuf_loader_get_pixbuf.
  ok = gdk_pixbuf_loader_close(loader, NULL);
  DCHECK(ok) << "close failed " << resource_id;
  GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
  DCHECK(pixbuf) << "failed to load " << resource_id << " " << data.size();

  // The pixbuf is owned by the loader, so add a ref so when we delete the
  // loader, the pixbuf still exists.
  g_object_ref(pixbuf);
  g_object_unref(loader);

  return pixbuf;
}

gboolean MainWindowConfigured(GtkWindow* window, GdkEventConfigure* event,
                              BrowserWindowGtk* browser_win) {
  gfx::Rect bounds = gfx::Rect(event->x, event->y, event->width, event->height);
  browser_win->OnBoundsChanged(bounds);
  return FALSE;
}

gboolean MainWindowStateChanged(GtkWindow* window, GdkEventWindowState* event,
                                BrowserWindowGtk* browser_win) {
  browser_win->OnStateChanged(event->new_window_state);
  return FALSE;
}

// Using gtk_window_get_position/size creates a race condition, so only use
// this to get the initial bounds.  After window creation, we pick up the
// normal bounds by connecting to the configure-event signal.
gfx::Rect GetInitialWindowBounds(GtkWindow* window) {
  gint x, y, width, height;
  gtk_window_get_position(window, &x, &y);
  gtk_window_get_size(window, &width, &height);
  return gfx::Rect(x, y, width, height);
}

const struct AcceleratorMapping {
  guint keyval;
  int command_id;
} kAcceleratorMap[] = {
  { GDK_k, IDC_FOCUS_SEARCH },
  { GDK_l, IDC_FOCUS_LOCATION },
  { GDK_o, IDC_OPEN_FILE },
  { GDK_w, IDC_CLOSE_TAB },
};

int GetCommandFromKeyval(guint accel_key) {
  for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) {
    if (kAcceleratorMap[i].keyval == accel_key)
      return kAcceleratorMap[i].command_id;
  }
  NOTREACHED();
  return 0;
}

// Usually accelerators are checked before propagating the key event, but in our
// case we want to reverse the order of things to allow webkit to handle key
// events like ctrl-l. If the window's children can handle the key event, this
// will return TRUE and the signal won't be propagated further. If the window's
// children cannot handle the key event then this will return FALSE and the
// default GtkWindow key press handler will be invoked.
gboolean OnKeyPress(GtkWindow* window, GdkEventKey* event, gpointer userdata) {
  return gtk_window_propagate_key_event(window, event);
}

}  // namespace

// TODO(estade): Break up this constructor into helper functions to improve
// readability.
BrowserWindowGtk::BrowserWindowGtk(Browser* browser)
    :  browser_(browser),
       // TODO(port): make this a pref.
       custom_frame_(false),
       method_factory_(this) {
  window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
  gtk_window_set_default_size(window_, 640, 480);
  g_signal_connect(window_, "destroy",
                   G_CALLBACK(OnWindowDestroyed), this);
  g_signal_connect(window_, "configure-event",
                   G_CALLBACK(MainWindowConfigured), this);
  g_signal_connect(window_, "window-state-event",
                   G_CALLBACK(MainWindowStateChanged), this);
  g_signal_connect(window_, "key-press-event",
                   G_CALLBACK(OnKeyPress), NULL);
  ConnectAccelerators();
  bounds_ = GetInitialWindowBounds(window_);

  GdkPixbuf* images[9] = {
    LoadThemeImage(IDR_CONTENT_TOP_LEFT_CORNER),
    LoadThemeImage(IDR_CONTENT_TOP_CENTER),
    LoadThemeImage(IDR_CONTENT_TOP_RIGHT_CORNER),
    LoadThemeImage(IDR_CONTENT_LEFT_SIDE),
    NULL,
    LoadThemeImage(IDR_CONTENT_RIGHT_SIDE),
    LoadThemeImage(IDR_CONTENT_BOTTOM_LEFT_CORNER),
    LoadThemeImage(IDR_CONTENT_BOTTOM_CENTER),
    LoadThemeImage(IDR_CONTENT_BOTTOM_RIGHT_CORNER)
  };
  content_area_ninebox_.reset(new NineBox(images));<commit_msg>Linux: Restore normal event handling for key events that are not to be sent to webkit.<commit_after>// Copyright (c) 2009 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/gtk/browser_window_gtk.h"

#include <gdk/gdkkeysyms.h>

#include "base/base_paths_linux.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/find_bar_controller.h"
#include "chrome/browser/gtk/browser_toolbar_gtk.h"
#include "chrome/browser/gtk/find_bar_gtk.h"
#include "chrome/browser/gtk/nine_box.h"
#include "chrome/browser/gtk/status_bubble_gtk.h"
#include "chrome/browser/gtk/tab_contents_container_gtk.h"
#include "chrome/browser/location_bar.h"
#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
#include "chrome/browser/tab_contents/web_contents.h"
#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/controls/button/text_button.h"
#include "grit/theme_resources.h"

namespace {

static GdkPixbuf* LoadThemeImage(int resource_id) {
  // TODO(mmoss) refactor -- stolen from custom_button.cc
  if (0 == resource_id)
    return NULL;

  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  std::vector<unsigned char> data;
  rb.LoadImageResourceBytes(resource_id, &data);

  GdkPixbufLoader* loader = gdk_pixbuf_loader_new();
  bool ok = gdk_pixbuf_loader_write(loader, static_cast<guint8*>(data.data()),
      data.size(), NULL);
  DCHECK(ok) << "failed to write " << resource_id;
  // Calling gdk_pixbuf_loader_close forces the data to be parsed by the
  // loader.  We must do this before calling gdk_pixbuf_loader_get_pixbuf.
  ok = gdk_pixbuf_loader_close(loader, NULL);
  DCHECK(ok) << "close failed " << resource_id;
  GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
  DCHECK(pixbuf) << "failed to load " << resource_id << " " << data.size();

  // The pixbuf is owned by the loader, so add a ref so when we delete the
  // loader, the pixbuf still exists.
  g_object_ref(pixbuf);
  g_object_unref(loader);

  return pixbuf;
}

gboolean MainWindowConfigured(GtkWindow* window, GdkEventConfigure* event,
                              BrowserWindowGtk* browser_win) {
  gfx::Rect bounds = gfx::Rect(event->x, event->y, event->width, event->height);
  browser_win->OnBoundsChanged(bounds);
  return FALSE;
}

gboolean MainWindowStateChanged(GtkWindow* window, GdkEventWindowState* event,
                                BrowserWindowGtk* browser_win) {
  browser_win->OnStateChanged(event->new_window_state);
  return FALSE;
}

// Using gtk_window_get_position/size creates a race condition, so only use
// this to get the initial bounds.  After window creation, we pick up the
// normal bounds by connecting to the configure-event signal.
gfx::Rect GetInitialWindowBounds(GtkWindow* window) {
  gint x, y, width, height;
  gtk_window_get_position(window, &x, &y);
  gtk_window_get_size(window, &width, &height);
  return gfx::Rect(x, y, width, height);
}

const struct AcceleratorMapping {
  guint keyval;
  int command_id;
} kAcceleratorMap[] = {
  { GDK_k, IDC_FOCUS_SEARCH },
  { GDK_l, IDC_FOCUS_LOCATION },
  { GDK_o, IDC_OPEN_FILE },
  { GDK_w, IDC_CLOSE_TAB },
  { GDK_Page_Down, IDC_FOCUS_SEARCH },
};

int GetCommandFromKeyval(guint accel_key) {
  for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) {
    if (kAcceleratorMap[i].keyval == accel_key)
      return kAcceleratorMap[i].command_id;
  }
  NOTREACHED();
  return 0;
}

// Usually accelerators are checked before propagating the key event, but if the
// focus is on the render area we want to reverse the order of things to allow
// webkit to handle key events like ctrl-l.
gboolean OnKeyPress(GtkWindow* window, GdkEventKey* event, Browser* browser) {
  TabContents* current_tab_contents =
      browser->tabstrip_model()->GetSelectedTabContents();
  // If there is no current tab contents or it is not focused then let the
  // default GtkWindow key handler run.
  if (!current_tab_contents)
    return FALSE;
  if (!gtk_widget_is_focus(current_tab_contents->GetContentNativeView()))
    return FALSE;

  // If the content area is focused, let it handle the key event.
  DCHECK(gtk_window_propagate_key_event(window, event));
  return TRUE;
}

}  // namespace

// TODO(estade): Break up this constructor into helper functions to improve
// readability.
BrowserWindowGtk::BrowserWindowGtk(Browser* browser)
    :  browser_(browser),
       // TODO(port): make this a pref.
       custom_frame_(false),
       method_factory_(this) {
  window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
  gtk_window_set_default_size(window_, 640, 480);
  g_signal_connect(window_, "destroy",
                   G_CALLBACK(OnWindowDestroyed), this);
  g_signal_connect(window_, "configure-event",
                   G_CALLBACK(MainWindowConfigured), this);
  g_signal_connect(window_, "window-state-event",
                   G_CALLBACK(MainWindowStateChanged), this);
  g_signal_connect(window_, "key-press-event",
                   G_CALLBACK(OnKeyPress), browser_.get());
  ConnectAccelerators();
  bounds_ = GetInitialWindowBounds(window_);

  GdkPixbuf* images[9] = {
    LoadThemeImage(IDR_CONTENT_TOP_LEFT_CORNER),
    LoadThemeImage(IDR_CONTENT_TOP_CENTER),
    LoadThemeImage(IDR_CONTENT_TOP_RIGHT_CORNER),
    LoadThemeImage(IDR_CONTENT_LEFT_SIDE),
    NULL,
    LoadThemeImage(IDR_CONTENT_RIGHT_SIDE),
    LoadThemeImage(IDR_CONTENT_BOTTOM_LEFT_CORNER),
    LoadThemeImage(IDR_CONTENT_BOTTOM_CENTER),
    LoadThemeImage(IDR_CONTENT_BOTTOM_RIGHT_CORNER)
  };
  content_area_ninebox_.reset(new NineBox(images));
{'fraction_non_alphanumeric': 0.10748146871229099, 'fraction_numerical': 0.0025857610756766076, 'mean_word_length': 4.616166505324298, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3419719', 'n_tokens_mistral': 3965, 'n_tokens_neox': 3844, 'n_words': 872}