2014-01-15 13:28:00 +00:00
|
|
|
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "browser/native_window_gtk.h"
|
|
|
|
|
|
|
|
#include "base/values.h"
|
|
|
|
#include "common/options_switches.h"
|
|
|
|
#include "content/public/browser/web_contents.h"
|
|
|
|
#include "content/public/browser/web_contents_view.h"
|
2014-01-15 14:38:38 +00:00
|
|
|
#include "content/public/common/renderer_preferences.h"
|
2014-01-15 14:31:26 +00:00
|
|
|
#include "ui/gfx/gtk_util.h"
|
2014-01-15 13:28:00 +00:00
|
|
|
#include "ui/gfx/rect.h"
|
2014-01-15 14:38:38 +00:00
|
|
|
#include "ui/gfx/skia_utils_gtk.h"
|
2014-01-15 13:28:00 +00:00
|
|
|
|
|
|
|
namespace atom {
|
|
|
|
|
2014-01-15 14:31:26 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Dividing GTK's cursor blink cycle time (in milliseconds) by this value yields
|
|
|
|
// an appropriate value for content::RendererPreferences::caret_blink_interval.
|
|
|
|
// This matches the logic in the WebKit GTK port.
|
|
|
|
const double kGtkCursorBlinkCycleFactor = 2000.0;
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2014-01-15 13:28:00 +00:00
|
|
|
NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
|
|
|
|
base::DictionaryValue* options)
|
|
|
|
: NativeWindow(web_contents, options),
|
|
|
|
window_(GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL))),
|
|
|
|
fullscreen_(false),
|
|
|
|
is_always_on_top_(false) {
|
|
|
|
gtk_container_add(GTK_CONTAINER(window_),
|
|
|
|
GetWebContents()->GetView()->GetNativeView());
|
|
|
|
|
|
|
|
int width = 800, height = 600;
|
|
|
|
options->GetInteger(switches::kWidth, &width);
|
|
|
|
options->GetInteger(switches::kHeight, &height);
|
|
|
|
gtk_window_set_default_size(window_, width, height);
|
|
|
|
|
|
|
|
if (!has_frame_)
|
|
|
|
gtk_window_set_decorated(window_, false);
|
|
|
|
|
|
|
|
if (!icon_.IsEmpty())
|
|
|
|
gtk_window_set_icon(window_, icon_.ToGdkPixbuf());
|
|
|
|
|
|
|
|
g_signal_connect(window_, "delete-event",
|
|
|
|
G_CALLBACK(OnWindowDeleteEventThunk), this);
|
2014-01-15 14:38:38 +00:00
|
|
|
g_signal_connect(window_, "focus-out-event",
|
|
|
|
G_CALLBACK(OnFocusOutThunk), this);
|
2014-01-15 14:31:26 +00:00
|
|
|
|
|
|
|
SetWebKitColorStyle();
|
2014-01-15 13:28:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NativeWindowGtk::~NativeWindowGtk() {
|
|
|
|
if (window_)
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(window_));
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Close() {
|
|
|
|
CloseWebContents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::CloseImmediately() {
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(window_));
|
|
|
|
window_ = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Move(const gfx::Rect& pos) {
|
|
|
|
gtk_window_move(window_, pos.x(), pos.y());
|
|
|
|
gtk_window_resize(window_, pos.width(), pos.height());
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Focus(bool focus) {
|
|
|
|
if (focus)
|
|
|
|
gtk_window_present(window_);
|
|
|
|
else
|
|
|
|
gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window_)));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::IsFocused() {
|
|
|
|
return gtk_window_is_active(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Show() {
|
|
|
|
gtk_widget_show_all(GTK_WIDGET(window_));
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Hide() {
|
|
|
|
gtk_widget_hide(GTK_WIDGET(window_));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::IsVisible() {
|
|
|
|
return gtk_widget_get_visible(GTK_WIDGET(window_));
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Maximize() {
|
|
|
|
gtk_window_maximize(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Unmaximize() {
|
|
|
|
gtk_window_unmaximize(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Minimize() {
|
|
|
|
gtk_window_iconify(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Restore() {
|
|
|
|
gtk_window_present(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetFullscreen(bool fullscreen) {
|
|
|
|
fullscreen_ = fullscreen;
|
|
|
|
if (fullscreen)
|
|
|
|
gtk_window_fullscreen(window_);
|
|
|
|
else
|
|
|
|
gtk_window_unfullscreen(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::IsFullscreen() {
|
|
|
|
return fullscreen_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetSize(const gfx::Size& size) {
|
|
|
|
gtk_window_resize(window_, size.width(), size.height());
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Size NativeWindowGtk::GetSize() {
|
|
|
|
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
|
|
|
|
|
|
|
|
GdkRectangle frame_extents;
|
|
|
|
gdk_window_get_frame_extents(gdk_window, &frame_extents);
|
|
|
|
|
|
|
|
return gfx::Size(frame_extents.width, frame_extents.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetMinimumSize(const gfx::Size& size) {
|
|
|
|
minimum_size_ = size;
|
|
|
|
|
|
|
|
GdkGeometry geometry = { 0 };
|
|
|
|
geometry.min_width = size.width();
|
|
|
|
geometry.min_height = size.height();
|
|
|
|
int hints = GDK_HINT_POS | GDK_HINT_MIN_SIZE;
|
|
|
|
gtk_window_set_geometry_hints(
|
|
|
|
window_, GTK_WIDGET(window_), &geometry, (GdkWindowHints)hints);
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Size NativeWindowGtk::GetMinimumSize() {
|
|
|
|
return minimum_size_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetMaximumSize(const gfx::Size& size) {
|
|
|
|
maximum_size_ = size;
|
|
|
|
|
|
|
|
GdkGeometry geometry = { 0 };
|
|
|
|
geometry.max_width = size.width();
|
|
|
|
geometry.max_height = size.height();
|
|
|
|
int hints = GDK_HINT_POS | GDK_HINT_MAX_SIZE;
|
|
|
|
gtk_window_set_geometry_hints(
|
|
|
|
window_, GTK_WIDGET(window_), &geometry, (GdkWindowHints)hints);
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Size NativeWindowGtk::GetMaximumSize() {
|
|
|
|
return maximum_size_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetResizable(bool resizable) {
|
|
|
|
// Should request widget size after setting unresizable, otherwise the
|
|
|
|
// window will shrink to a very small size.
|
|
|
|
if (!IsResizable()) {
|
|
|
|
gint width, height;
|
|
|
|
gtk_window_get_size(window_, &width, &height);
|
|
|
|
gtk_widget_set_size_request(GTK_WIDGET(window_), width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_window_set_resizable(window_, resizable);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::IsResizable() {
|
|
|
|
return gtk_window_get_resizable(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetAlwaysOnTop(bool top) {
|
|
|
|
is_always_on_top_ = top;
|
|
|
|
gtk_window_set_keep_above(window_, top ? TRUE : FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::IsAlwaysOnTop() {
|
|
|
|
return is_always_on_top_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::Center() {
|
|
|
|
gtk_window_set_position(window_, GTK_WIN_POS_CENTER);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetPosition(const gfx::Point& position) {
|
|
|
|
gtk_window_move(window_, position.x(), position.y());
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Point NativeWindowGtk::GetPosition() {
|
|
|
|
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window_));
|
|
|
|
|
|
|
|
GdkRectangle frame_extents;
|
|
|
|
gdk_window_get_frame_extents(gdk_window, &frame_extents);
|
|
|
|
|
|
|
|
return gfx::Point(frame_extents.x, frame_extents.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetTitle(const std::string& title) {
|
|
|
|
gtk_window_set_title(window_, title.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string NativeWindowGtk::GetTitle() {
|
|
|
|
return gtk_window_get_title(window_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::FlashFrame(bool flash) {
|
|
|
|
gtk_window_set_urgency_hint(window_, flash);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::SetKiosk(bool kiosk) {
|
|
|
|
SetFullscreen(kiosk);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::IsKiosk() {
|
|
|
|
return IsFullscreen();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NativeWindowGtk::HasModalDialog() {
|
|
|
|
// FIXME(zcbenz): Implement me.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::NativeWindow NativeWindowGtk::GetNativeWindow() {
|
|
|
|
return window_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NativeWindowGtk::UpdateDraggableRegions(
|
|
|
|
const std::vector<DraggableRegion>& regions) {
|
|
|
|
}
|
|
|
|
|
2014-01-15 14:31:26 +00:00
|
|
|
void NativeWindowGtk::SetWebKitColorStyle() {
|
|
|
|
content::RendererPreferences* prefs =
|
|
|
|
GetWebContents()->GetMutableRendererPrefs();
|
|
|
|
GtkStyle* frame_style = gtk_rc_get_style(GTK_WIDGET(window_));
|
|
|
|
prefs->focus_ring_color =
|
|
|
|
gfx::GdkColorToSkColor(frame_style->bg[GTK_STATE_SELECTED]);
|
|
|
|
prefs->thumb_active_color = SkColorSetRGB(244, 244, 244);
|
|
|
|
prefs->thumb_inactive_color = SkColorSetRGB(234, 234, 234);
|
|
|
|
prefs->track_color = SkColorSetRGB(211, 211, 211);
|
|
|
|
|
|
|
|
GtkWidget* url_entry = gtk_entry_new();
|
|
|
|
GtkStyle* entry_style = gtk_rc_get_style(url_entry);
|
|
|
|
prefs->active_selection_bg_color =
|
|
|
|
gfx::GdkColorToSkColor(entry_style->base[GTK_STATE_SELECTED]);
|
|
|
|
prefs->active_selection_fg_color =
|
|
|
|
gfx::GdkColorToSkColor(entry_style->text[GTK_STATE_SELECTED]);
|
|
|
|
prefs->inactive_selection_bg_color =
|
|
|
|
gfx::GdkColorToSkColor(entry_style->base[GTK_STATE_ACTIVE]);
|
|
|
|
prefs->inactive_selection_fg_color =
|
|
|
|
gfx::GdkColorToSkColor(entry_style->text[GTK_STATE_ACTIVE]);
|
|
|
|
gtk_widget_destroy(url_entry);
|
|
|
|
|
|
|
|
const base::TimeDelta cursor_blink_time = gfx::GetCursorBlinkCycle();
|
|
|
|
prefs->caret_blink_interval =
|
|
|
|
cursor_blink_time.InMilliseconds() ?
|
|
|
|
cursor_blink_time.InMilliseconds() / kGtkCursorBlinkCycleFactor :
|
|
|
|
0;
|
|
|
|
}
|
|
|
|
|
2014-01-15 13:28:00 +00:00
|
|
|
gboolean NativeWindowGtk::OnWindowDeleteEvent(GtkWidget* widget,
|
|
|
|
GdkEvent* event) {
|
|
|
|
Close();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-01-15 14:38:38 +00:00
|
|
|
gboolean NativeWindowGtk::OnFocusOut(GtkWidget* window, GdkEventFocus*) {
|
|
|
|
NotifyWindowBlur();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-01-15 13:28:00 +00:00
|
|
|
// static
|
|
|
|
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
|
|
|
|
base::DictionaryValue* options) {
|
|
|
|
return new NativeWindowGtk(web_contents, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace atom
|