Linux: cefclient: Port to GTK3 (see issue #2969)
GTK3 is required by the Chrome runtime. The cefclient off-screen rendering example no longer works with Ubuntu 16.04. With end-of-life in April 2021 we are dropping support for 16.04 in the near future in any case.
This commit is contained in:
parent
8424f166cc
commit
020ac1b509
12
BUILD.gn
12
BUILD.gn
|
@ -2035,18 +2035,12 @@ if (is_mac) {
|
||||||
pkg_config("gtk") {
|
pkg_config("gtk") {
|
||||||
packages = [
|
packages = [
|
||||||
"gmodule-2.0",
|
"gmodule-2.0",
|
||||||
"gtk+-2.0",
|
"gtk+-3.0",
|
||||||
"gthread-2.0",
|
"gthread-2.0",
|
||||||
"gtk+-unix-print-2.0",
|
"gtk+-unix-print-3.0",
|
||||||
"xi",
|
"xi",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg_config("gtkglext") {
|
|
||||||
packages = [
|
|
||||||
"gtkglext-1.0",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_linux) {
|
if (is_linux) {
|
||||||
|
@ -2127,13 +2121,13 @@ if (is_mac) {
|
||||||
]
|
]
|
||||||
|
|
||||||
libs = [
|
libs = [
|
||||||
|
"GL",
|
||||||
"X11",
|
"X11",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (cef_use_gtk) {
|
if (cef_use_gtk) {
|
||||||
configs += [
|
configs += [
|
||||||
":gtk",
|
":gtk",
|
||||||
":gtkglext",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,7 @@
|
||||||
# work but may not have been tested.
|
# work but may not have been tested.
|
||||||
# Required packages include:
|
# Required packages include:
|
||||||
# build-essential
|
# build-essential
|
||||||
# libgtk2.0-dev (required by the cefclient target only)
|
# libgtk3.0-dev (required by the cefclient target only)
|
||||||
# libgtkglext1-dev (required by the cefclient target only)
|
|
||||||
#
|
#
|
||||||
# - MacOS requirements:
|
# - MacOS requirements:
|
||||||
# Xcode 8 or newer building on MacOS 10.11 (El Capitan) or newer for x86_64.
|
# Xcode 8 or newer building on MacOS 10.11 (El Capitan) or newer for x86_64.
|
||||||
|
|
|
@ -95,6 +95,7 @@ if(OS_LINUX)
|
||||||
-Wno-unused-parameter # Don't warn about unused parameters
|
-Wno-unused-parameter # Don't warn about unused parameters
|
||||||
-Wno-error=comment # Don't warn about code in comments
|
-Wno-error=comment # Don't warn about code in comments
|
||||||
-Wno-comment # Don't warn about code in comments
|
-Wno-comment # Don't warn about code in comments
|
||||||
|
-Wno-deprecated-declarations # Don't warn about using deprecated methods
|
||||||
)
|
)
|
||||||
list(APPEND CEF_C_COMPILER_FLAGS
|
list(APPEND CEF_C_COMPILER_FLAGS
|
||||||
-std=c99 # Use the C99 language standard
|
-std=c99 # Use the C99 language standard
|
||||||
|
|
|
@ -122,13 +122,13 @@ if(OS_LINUX)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find required libraries and update compiler/linker variables.
|
# Find required libraries and update compiler/linker variables.
|
||||||
FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-2.0 gthread-2.0 gtk+-unix-print-2.0 gtkglext-1.0 xi")
|
FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-3.0 gthread-2.0 gtk+-unix-print-3.0 xi")
|
||||||
|
|
||||||
# Executable target.
|
# Executable target.
|
||||||
add_executable(${CEF_TARGET} ${CEFCLIENT_SRCS})
|
add_executable(${CEF_TARGET} ${CEFCLIENT_SRCS})
|
||||||
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
|
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
|
||||||
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
|
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
|
||||||
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
|
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper "GL" ${CEF_STANDARD_LIBS})
|
||||||
|
|
||||||
# Set rpath so that libraries can be placed next to the executable.
|
# Set rpath so that libraries can be placed next to the executable.
|
||||||
set_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN")
|
set_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN")
|
||||||
|
|
|
@ -6,16 +6,14 @@
|
||||||
|
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
#include <gdk/gdkkeysyms.h>
|
#include <gdk/gdkkeysyms-compat.h>
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <gtk/gtkgl.h>
|
|
||||||
|
|
||||||
#define XK_3270 // for XK_3270_BackTab
|
#define XK_3270 // for XK_3270_BackTab
|
||||||
#include <X11/XF86keysym.h>
|
#include <X11/XF86keysym.h>
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
#include <X11/extensions/XInput2.h>
|
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
#include "include/base/cef_logging.h"
|
#include "include/base/cef_logging.h"
|
||||||
|
@ -29,17 +27,10 @@ namespace client {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Major opcode of XInputExtension, or -1 if XInput 2.2 is not available.
|
|
||||||
int g_xinput_extension = -1;
|
|
||||||
|
|
||||||
// Static BrowserWindowOsrGtk::EventFilter needs to forward touch events
|
// Static BrowserWindowOsrGtk::EventFilter needs to forward touch events
|
||||||
// to correct browser, so we maintain a vector of all windows.
|
// to correct browser, so we maintain a vector of all windows.
|
||||||
std::vector<BrowserWindowOsrGtk*> g_browser_windows;
|
std::vector<BrowserWindowOsrGtk*> g_browser_windows;
|
||||||
|
|
||||||
bool IsTouchAvailable() {
|
|
||||||
return g_xinput_extension != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetCefStateModifiers(guint state) {
|
int GetCefStateModifiers(guint state) {
|
||||||
int modifiers = 0;
|
int modifiers = 0;
|
||||||
if (state & GDK_SHIFT_MASK)
|
if (state & GDK_SHIFT_MASK)
|
||||||
|
@ -59,20 +50,6 @@ int GetCefStateModifiers(guint state) {
|
||||||
return modifiers;
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetCefStateModifiers(XIModifierState mods, XIButtonState buttons) {
|
|
||||||
guint state = mods.effective;
|
|
||||||
if (buttons.mask_len >= 1) {
|
|
||||||
if (XIMaskIsSet(buttons.mask, 1))
|
|
||||||
state |= GDK_BUTTON1_MASK;
|
|
||||||
if (XIMaskIsSet(buttons.mask, 2))
|
|
||||||
state |= GDK_BUTTON2_MASK;
|
|
||||||
if (XIMaskIsSet(buttons.mask, 3))
|
|
||||||
state |= GDK_BUTTON3_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetCefStateModifiers(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// From ui/events/keycodes/keyboard_codes_posix.h.
|
// From ui/events/keycodes/keyboard_codes_posix.h.
|
||||||
enum KeyboardCode {
|
enum KeyboardCode {
|
||||||
VKEY_BACK = 0x08,
|
VKEY_BACK = 0x08,
|
||||||
|
@ -894,17 +871,20 @@ void GetWidgetRectInScreen(GtkWidget* widget, GdkRectangle* r) {
|
||||||
// Get parent's left-top screen coordinates.
|
// Get parent's left-top screen coordinates.
|
||||||
gdk_window_get_root_origin(window, &x, &y);
|
gdk_window_get_root_origin(window, &x, &y);
|
||||||
// Get parent's width and height.
|
// Get parent's width and height.
|
||||||
gdk_drawable_get_size(window, &w, &h);
|
w = gdk_window_get_width(window);
|
||||||
|
h = gdk_window_get_height(window);
|
||||||
// Get parent's extents including decorations.
|
// Get parent's extents including decorations.
|
||||||
gdk_window_get_frame_extents(window, &extents);
|
gdk_window_get_frame_extents(window, &extents);
|
||||||
|
|
||||||
// X and Y calculations assume that left, right and bottom border sizes are
|
// X and Y calculations assume that left, right and bottom border sizes are
|
||||||
// all the same.
|
// all the same.
|
||||||
const gint border = (extents.width - w) / 2;
|
const gint border = (extents.width - w) / 2;
|
||||||
r->x = x + border + widget->allocation.x;
|
GtkAllocation allocation;
|
||||||
r->y = y + (extents.height - h) - border + widget->allocation.y;
|
gtk_widget_get_allocation(widget, &allocation);
|
||||||
r->width = widget->allocation.width;
|
r->x = x + border + allocation.x;
|
||||||
r->height = widget->allocation.height;
|
r->y = y + (extents.height - h) - border + allocation.y;
|
||||||
|
r->width = allocation.width;
|
||||||
|
r->height = allocation.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefBrowserHost::DragOperationsMask GetDragOperationsMask(
|
CefBrowserHost::DragOperationsMask GetDragOperationsMask(
|
||||||
|
@ -925,30 +905,25 @@ CefBrowserHost::DragOperationsMask GetDragOperationsMask(
|
||||||
class ScopedGLContext {
|
class ScopedGLContext {
|
||||||
public:
|
public:
|
||||||
ScopedGLContext(GtkWidget* widget, bool swap_buffers)
|
ScopedGLContext(GtkWidget* widget, bool swap_buffers)
|
||||||
: swap_buffers_(swap_buffers) {
|
: swap_buffers_(swap_buffers), widget_(widget) {
|
||||||
GdkGLContext* glcontext = gtk_widget_get_gl_context(widget);
|
gtk_gl_area_make_current(GTK_GL_AREA(widget));
|
||||||
gldrawable_ = gtk_widget_get_gl_drawable(widget);
|
is_valid_ = gtk_gl_area_get_error(GTK_GL_AREA(widget)) == NULL;
|
||||||
is_valid_ = gdk_gl_drawable_gl_begin(gldrawable_, glcontext);
|
if (swap_buffers_ && is_valid_) {
|
||||||
|
gtk_gl_area_queue_render(GTK_GL_AREA(widget_));
|
||||||
|
gtk_gl_area_attach_buffers(GTK_GL_AREA(widget));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ScopedGLContext() {
|
virtual ~ScopedGLContext() {
|
||||||
if (is_valid_) {
|
if (swap_buffers_ && is_valid_)
|
||||||
gdk_gl_drawable_gl_end(gldrawable_);
|
glFlush();
|
||||||
|
|
||||||
if (swap_buffers_) {
|
|
||||||
if (gdk_gl_drawable_is_double_buffered(gldrawable_))
|
|
||||||
gdk_gl_drawable_swap_buffers(gldrawable_);
|
|
||||||
else
|
|
||||||
glFlush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid() const { return is_valid_; }
|
bool IsValid() const { return is_valid_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool swap_buffers_;
|
bool swap_buffers_;
|
||||||
GdkGLDrawable* gldrawable_;
|
GtkWidget* const widget_;
|
||||||
bool is_valid_;
|
bool is_valid_;
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads_;
|
ScopedGdkThreadsEnter scoped_gdk_threads_;
|
||||||
};
|
};
|
||||||
|
@ -1013,11 +988,11 @@ void BrowserWindowOsrGtk::CreateBrowser(
|
||||||
// Retrieve the X11 Window ID for the GTK parent window.
|
// Retrieve the X11 Window ID for the GTK parent window.
|
||||||
GtkWidget* window =
|
GtkWidget* window =
|
||||||
gtk_widget_get_ancestor(GTK_WIDGET(parent_handle), GTK_TYPE_WINDOW);
|
gtk_widget_get_ancestor(GTK_WIDGET(parent_handle), GTK_TYPE_WINDOW);
|
||||||
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(window));
|
CefWindowHandle handle = GDK_WINDOW_XID(gtk_widget_get_window(window));
|
||||||
DCHECK(xwindow);
|
DCHECK(handle);
|
||||||
|
|
||||||
CefWindowInfo window_info;
|
CefWindowInfo window_info;
|
||||||
window_info.SetAsWindowless(xwindow);
|
window_info.SetAsWindowless(handle);
|
||||||
|
|
||||||
// Create the browser asynchronously.
|
// Create the browser asynchronously.
|
||||||
CefBrowserHost::CreateBrowser(window_info, client_handler_,
|
CefBrowserHost::CreateBrowser(window_info, client_handler_,
|
||||||
|
@ -1172,11 +1147,12 @@ void BrowserWindowOsrGtk::GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||||
|
|
||||||
// The simulated screen and view rectangle are the same. This is necessary
|
// The simulated screen and view rectangle are the same. This is necessary
|
||||||
// for popup menus to be located and sized inside the view.
|
// for popup menus to be located and sized inside the view.
|
||||||
rect.width = DeviceToLogical(glarea_->allocation.width, device_scale_factor);
|
GtkAllocation allocation;
|
||||||
|
gtk_widget_get_allocation(glarea_, &allocation);
|
||||||
|
rect.width = DeviceToLogical(allocation.width, device_scale_factor);
|
||||||
if (rect.width == 0)
|
if (rect.width == 0)
|
||||||
rect.width = 1;
|
rect.width = 1;
|
||||||
rect.height =
|
rect.height = DeviceToLogical(allocation.height, device_scale_factor);
|
||||||
DeviceToLogical(glarea_->allocation.height, device_scale_factor);
|
|
||||||
if (rect.height == 0)
|
if (rect.height == 0)
|
||||||
rect.height = 1;
|
rect.height = 1;
|
||||||
}
|
}
|
||||||
|
@ -1373,18 +1349,13 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
|
||||||
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
|
||||||
glarea_ = gtk_drawing_area_new();
|
glarea_ = gtk_gl_area_new();
|
||||||
DCHECK(glarea_);
|
DCHECK(glarea_);
|
||||||
|
|
||||||
GdkGLConfig* glconfig =
|
|
||||||
gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>(
|
|
||||||
GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
|
|
||||||
DCHECK(glconfig);
|
|
||||||
|
|
||||||
gtk_widget_set_gl_capability(glarea_, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
|
|
||||||
|
|
||||||
gtk_widget_set_can_focus(glarea_, TRUE);
|
gtk_widget_set_can_focus(glarea_, TRUE);
|
||||||
|
|
||||||
|
gtk_gl_area_set_auto_render(GTK_GL_AREA(glarea_), FALSE);
|
||||||
|
|
||||||
g_signal_connect(G_OBJECT(glarea_), "size_allocate",
|
g_signal_connect(G_OBJECT(glarea_), "size_allocate",
|
||||||
G_CALLBACK(&BrowserWindowOsrGtk::SizeAllocation), this);
|
G_CALLBACK(&BrowserWindowOsrGtk::SizeAllocation), this);
|
||||||
|
|
||||||
|
@ -1414,18 +1385,16 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
|
||||||
G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
|
G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
|
||||||
g_signal_connect(G_OBJECT(glarea_), "focus_out_event",
|
g_signal_connect(G_OBJECT(glarea_), "focus_out_event",
|
||||||
G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
|
G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
|
||||||
|
g_signal_connect(G_OBJECT(glarea_), "touch-event",
|
||||||
|
G_CALLBACK(&BrowserWindowOsrGtk::TouchEvent), this);
|
||||||
|
|
||||||
RegisterDragDrop();
|
RegisterDragDrop();
|
||||||
|
|
||||||
gtk_container_add(GTK_CONTAINER(parent_handle), glarea_);
|
gtk_widget_set_vexpand(glarea_, TRUE);
|
||||||
|
gtk_grid_attach(GTK_GRID(parent_handle), glarea_, 0, 3, 1, 1);
|
||||||
|
|
||||||
// Make the GlArea visible in the parent container.
|
// Make the GlArea visible in the parent container.
|
||||||
gtk_widget_show_all(parent_handle);
|
gtk_widget_show_all(parent_handle);
|
||||||
|
|
||||||
InitializeXinput(xdisplay_);
|
|
||||||
|
|
||||||
if (IsTouchAvailable())
|
|
||||||
RegisterTouch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -1661,6 +1630,9 @@ gint BrowserWindowOsrGtk::ScrollEvent(GtkWidget* widget,
|
||||||
case GDK_SCROLL_RIGHT:
|
case GDK_SCROLL_RIGHT:
|
||||||
deltaX = -scrollbarPixelsPerGtkTick;
|
deltaX = -scrollbarPixelsPerGtkTick;
|
||||||
break;
|
break;
|
||||||
|
case GDK_SCROLL_SMOOTH:
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
host->SendMouseWheelEvent(mouse_event, deltaX, deltaY);
|
host->SendMouseWheelEvent(mouse_event, deltaX, deltaY);
|
||||||
|
@ -1677,106 +1649,49 @@ gint BrowserWindowOsrGtk::FocusEvent(GtkWidget* widget,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWindowOsrGtk::TouchEvent(CefXIDeviceEvent event) {
|
// static
|
||||||
if (!browser_.get())
|
gboolean BrowserWindowOsrGtk::TouchEvent(GtkWidget* widget,
|
||||||
return;
|
GdkEventTouch* event,
|
||||||
|
BrowserWindowOsrGtk* self) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
XIDeviceEvent* ev = static_cast<XIDeviceEvent*>(event);
|
if (!self->browser_.get())
|
||||||
CefTouchEvent cef_event;
|
return TRUE;
|
||||||
switch (ev->evtype) {
|
|
||||||
case XI_TouchBegin:
|
CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
|
||||||
cef_event.type = CEF_TET_PRESSED;
|
|
||||||
|
float device_scale_factor;
|
||||||
|
{
|
||||||
|
base::AutoLock lock_scope(self->lock_);
|
||||||
|
device_scale_factor = self->device_scale_factor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefTouchEvent touch_event;
|
||||||
|
switch (event->type) {
|
||||||
|
case GDK_TOUCH_BEGIN:
|
||||||
|
touch_event.type = CEF_TET_PRESSED;
|
||||||
break;
|
break;
|
||||||
case XI_TouchUpdate:
|
case GDK_TOUCH_UPDATE:
|
||||||
cef_event.type = CEF_TET_MOVED;
|
touch_event.type = CEF_TET_MOVED;
|
||||||
break;
|
break;
|
||||||
case XI_TouchEnd:
|
case GDK_TOUCH_END:
|
||||||
cef_event.type = CEF_TET_RELEASED;
|
touch_event.type = CEF_TET_RELEASED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cef_event.id = ev->detail;
|
touch_event.x = event->x;
|
||||||
cef_event.x = ev->event_x;
|
touch_event.y = event->y;
|
||||||
cef_event.y = ev->event_y;
|
touch_event.radius_x = 0;
|
||||||
cef_event.radius_x = 0;
|
touch_event.radius_y = 0;
|
||||||
cef_event.radius_y = 0;
|
touch_event.rotation_angle = 0;
|
||||||
cef_event.rotation_angle = 0;
|
touch_event.pressure = 0;
|
||||||
cef_event.pressure = 0;
|
DeviceToLogical(touch_event, device_scale_factor);
|
||||||
cef_event.modifiers = GetCefStateModifiers(ev->mods, ev->buttons);
|
touch_event.modifiers = GetCefStateModifiers(event->state);
|
||||||
|
|
||||||
browser_->GetHost()->SendTouchEvent(cef_event);
|
host->SendTouchEvent(touch_event);
|
||||||
}
|
return TRUE;
|
||||||
|
|
||||||
void BrowserWindowOsrGtk::RegisterTouch() {
|
|
||||||
GdkWindow* glwindow = gtk_widget_get_window(glarea_);
|
|
||||||
::Window xwindow = GDK_WINDOW_XID(glwindow);
|
|
||||||
uint32_t bitMask = XI_TouchBeginMask | XI_TouchUpdateMask | XI_TouchEndMask;
|
|
||||||
|
|
||||||
XIEventMask mask;
|
|
||||||
mask.deviceid = XIAllMasterDevices;
|
|
||||||
mask.mask = reinterpret_cast<unsigned char*>(&bitMask);
|
|
||||||
mask.mask_len = sizeof(bitMask);
|
|
||||||
XISelectEvents(xdisplay_, xwindow, &mask, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
GdkFilterReturn BrowserWindowOsrGtk::EventFilter(GdkXEvent* gdk_xevent,
|
|
||||||
GdkEvent* event,
|
|
||||||
gpointer data) {
|
|
||||||
XEvent* xevent = static_cast<XEvent*>(gdk_xevent);
|
|
||||||
if (xevent->type == GenericEvent &&
|
|
||||||
xevent->xgeneric.extension == g_xinput_extension) {
|
|
||||||
XGetEventData(xevent->xcookie.display, &xevent->xcookie);
|
|
||||||
XIDeviceEvent* ev = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
|
|
||||||
|
|
||||||
if (!ev)
|
|
||||||
return GDK_FILTER_REMOVE;
|
|
||||||
|
|
||||||
for (BrowserWindowOsrGtk* browser_window : g_browser_windows) {
|
|
||||||
GtkWidget* widget = browser_window->GetWindowHandle();
|
|
||||||
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
|
|
||||||
if (xwindow == ev->event) {
|
|
||||||
browser_window->TouchEvent(ev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFreeEventData(xevent->xcookie.display, &xevent->xcookie);
|
|
||||||
// Even if we didn't find a consumer for this event, we will make sure Gdk
|
|
||||||
// doesn't attempt to process the event, since it can't parse GenericEvents
|
|
||||||
return GDK_FILTER_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GDK_FILTER_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void BrowserWindowOsrGtk::InitializeXinput(XDisplay* xdisplay) {
|
|
||||||
static bool initialized = false;
|
|
||||||
if (initialized)
|
|
||||||
return;
|
|
||||||
initialized = true;
|
|
||||||
|
|
||||||
int firstEvent, firstError;
|
|
||||||
if (XQueryExtension(xdisplay, "XInputExtension", &g_xinput_extension,
|
|
||||||
&firstEvent, &firstError)) {
|
|
||||||
int major = 2, minor = 2;
|
|
||||||
// X Input Extension 2.2 is needed for multitouch events.
|
|
||||||
if (XIQueryVersion(xdisplay, &major, &minor) == Success) {
|
|
||||||
// Ideally we would add an event filter for each glarea_ window
|
|
||||||
// separately, but unfortunately GDK can't parse X GenericEvents
|
|
||||||
// which have the target window stored in different way compared
|
|
||||||
// to other X events. That is why we add this global event filter
|
|
||||||
// just once, and dispatch the event to correct BrowserWindowOsrGtk
|
|
||||||
// manually.
|
|
||||||
gdk_window_add_filter(nullptr, &BrowserWindowOsrGtk::EventFilter,
|
|
||||||
nullptr);
|
|
||||||
} else {
|
|
||||||
g_xinput_extension = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserWindowOsrGtk::IsOverPopupWidget(int x, int y) const {
|
bool BrowserWindowOsrGtk::IsOverPopupWidget(int x, int y) const {
|
||||||
|
|
|
@ -117,8 +117,10 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||||
static gint FocusEvent(GtkWidget* widget,
|
static gint FocusEvent(GtkWidget* widget,
|
||||||
GdkEventFocus* event,
|
GdkEventFocus* event,
|
||||||
BrowserWindowOsrGtk* self);
|
BrowserWindowOsrGtk* self);
|
||||||
|
static gboolean TouchEvent(GtkWidget* widget,
|
||||||
|
GdkEventTouch* event,
|
||||||
|
BrowserWindowOsrGtk* self);
|
||||||
|
|
||||||
void TouchEvent(CefXIDeviceEvent event);
|
|
||||||
void RegisterTouch();
|
void RegisterTouch();
|
||||||
|
|
||||||
bool IsOverPopupWidget(int x, int y) const;
|
bool IsOverPopupWidget(int x, int y) const;
|
||||||
|
@ -176,7 +178,6 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||||
static GdkFilterReturn EventFilter(GdkXEvent* gdk_xevent,
|
static GdkFilterReturn EventFilter(GdkXEvent* gdk_xevent,
|
||||||
GdkEvent* event,
|
GdkEvent* event,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
static void InitializeXinput(XDisplay* xdisplay);
|
|
||||||
|
|
||||||
XDisplay* xdisplay_;
|
XDisplay* xdisplay_;
|
||||||
|
|
||||||
|
|
|
@ -135,10 +135,10 @@ GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
||||||
scoped_refptr<RootWindow> root_window =
|
scoped_refptr<RootWindow> root_window =
|
||||||
RootWindow::GetForBrowser(browser->GetIdentifier());
|
RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||||
if (root_window) {
|
if (root_window) {
|
||||||
GtkWindow* window = GTK_WINDOW(root_window->GetWindowHandle());
|
GtkWidget* window = root_window->GetWindowHandle();
|
||||||
if (!window)
|
if (!window)
|
||||||
LOG(ERROR) << "No GtkWindow for browser";
|
LOG(ERROR) << "No GtkWindow for browser";
|
||||||
return window;
|
return GTK_WINDOW(window);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -238,13 +238,13 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
||||||
|
|
||||||
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||||
accept_button = GTK_STOCK_OPEN;
|
accept_button = "_Open";
|
||||||
} else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
|
} else if (mode_type == FILE_DIALOG_OPEN_FOLDER) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||||
accept_button = GTK_STOCK_OPEN;
|
accept_button = "_Open";
|
||||||
} else if (mode_type == FILE_DIALOG_SAVE) {
|
} else if (mode_type == FILE_DIALOG_SAVE) {
|
||||||
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||||
accept_button = GTK_STOCK_SAVE;
|
accept_button = "_Save";
|
||||||
} else {
|
} else {
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
params.callback->Cancel();
|
params.callback->Cancel();
|
||||||
|
@ -274,7 +274,7 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* dialog = gtk_file_chooser_dialog_new(
|
GtkWidget* dialog = gtk_file_chooser_dialog_new(
|
||||||
title_str.c_str(), GTK_WINDOW(window), action, GTK_STOCK_CANCEL,
|
title_str.c_str(), GTK_WINDOW(window), action, "_Cancel",
|
||||||
GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, NULL);
|
GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, NULL);
|
||||||
|
|
||||||
if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
|
if (mode_type == FILE_DIALOG_OPEN_MULTIPLE)
|
||||||
|
@ -406,8 +406,8 @@ void ClientDialogHandlerGtk::OnJSDialogContinue(OnJSDialogParams params,
|
||||||
|
|
||||||
gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str());
|
gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str());
|
||||||
|
|
||||||
GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
|
GtkWidget* ok_button =
|
||||||
GTK_STOCK_OK, GTK_RESPONSE_OK);
|
gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), "_OK", GTK_RESPONSE_OK);
|
||||||
|
|
||||||
if (params.dialog_type != JSDIALOGTYPE_PROMPT)
|
if (params.dialog_type != JSDIALOGTYPE_PROMPT)
|
||||||
gtk_widget_grab_focus(ok_button);
|
gtk_widget_grab_focus(ok_button);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h"
|
#include "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <gtk/gtkmain.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#include "include/base/cef_bind.h"
|
#include "include/base/cef_bind.h"
|
||||||
#include "include/base/cef_logging.h"
|
#include "include/base/cef_logging.h"
|
||||||
|
|
|
@ -539,7 +539,7 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnJobCompleted(GtkPrintJob* print_job, GError* error) {
|
void OnJobCompleted(GtkPrintJob* print_job, const GError* error) {
|
||||||
// Continue() will result in a call to ClientPrintHandlerGtk::OnPrintReset
|
// Continue() will result in a call to ClientPrintHandlerGtk::OnPrintReset
|
||||||
// which deletes |this|. Execute it asnychronously so the call stack has a
|
// which deletes |this|. Execute it asnychronously so the call stack has a
|
||||||
// chance to unwind.
|
// chance to unwind.
|
||||||
|
@ -556,7 +556,7 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||||
|
|
||||||
static void OnJobCompletedThunk(GtkPrintJob* print_job,
|
static void OnJobCompletedThunk(GtkPrintJob* print_job,
|
||||||
void* handler,
|
void* handler,
|
||||||
GError* error) {
|
const GError* error) {
|
||||||
static_cast<PrintHandler*>(handler)->OnJobCompleted(print_job, error);
|
static_cast<PrintHandler*>(handler)->OnJobCompleted(print_job, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,36 @@ namespace {
|
||||||
|
|
||||||
const char kMenuIdKey[] = "menu_id";
|
const char kMenuIdKey[] = "menu_id";
|
||||||
|
|
||||||
|
void UseDefaultX11VisualForGtk(GtkWidget* widget) {
|
||||||
|
#if GTK_CHECK_VERSION(3, 15, 1)
|
||||||
|
// GTK+ > 3.15.1 uses an X11 visual optimized for GTK+'s OpenGL stuff
|
||||||
|
// since revid dae447728d: https://github.com/GNOME/gtk/commit/dae447728d
|
||||||
|
// However, it breaks CEF: https://github.com/cztomczak/cefcapi/issues/9
|
||||||
|
// Let's use the default X11 visual instead of the GTK's blessed one.
|
||||||
|
// Copied from: https://github.com/cztomczak/cefcapi.
|
||||||
|
GdkScreen* screen = gdk_screen_get_default();
|
||||||
|
GList* visuals = gdk_screen_list_visuals(screen);
|
||||||
|
|
||||||
|
GdkX11Screen* x11_screen = GDK_X11_SCREEN(screen);
|
||||||
|
if (x11_screen == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Visual* default_xvisual = DefaultVisual(GDK_SCREEN_XDISPLAY(x11_screen),
|
||||||
|
GDK_SCREEN_XNUMBER(x11_screen));
|
||||||
|
GList* cursor = visuals;
|
||||||
|
while (cursor != NULL) {
|
||||||
|
GdkVisual* visual = GDK_X11_VISUAL(cursor->data);
|
||||||
|
if (default_xvisual->visualid ==
|
||||||
|
gdk_x11_visual_get_xvisual(visual)->visualid) {
|
||||||
|
gtk_widget_set_visual(widget, visual);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor = cursor->next;
|
||||||
|
}
|
||||||
|
g_list_free(visuals);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool IsWindowMaximized(GtkWindow* window) {
|
bool IsWindowMaximized(GtkWindow* window) {
|
||||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
||||||
gint state = gdk_window_get_state(gdk_window);
|
gint state = gdk_window_get_state(gdk_window);
|
||||||
|
@ -143,6 +173,7 @@ void RootWindowGtk::Show(ShowMode mode) {
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
|
||||||
// Show the GTK window.
|
// Show the GTK window.
|
||||||
|
UseDefaultX11VisualForGtk(GTK_WIDGET(window_));
|
||||||
gtk_widget_show_all(window_);
|
gtk_widget_show_all(window_);
|
||||||
|
|
||||||
if (mode == ShowMinimized)
|
if (mode == ShowMinimized)
|
||||||
|
@ -290,23 +321,34 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||||
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
|
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
|
||||||
|
|
||||||
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
|
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
|
||||||
GdkColor color = {0};
|
GdkRGBA rgba = {0};
|
||||||
color.red = CefColorGetR(background_color) * 65535 / 255;
|
rgba.red = CefColorGetR(background_color) * 65535 / 255;
|
||||||
color.green = CefColorGetG(background_color) * 65535 / 255;
|
rgba.green = CefColorGetG(background_color) * 65535 / 255;
|
||||||
color.blue = CefColorGetB(background_color) * 65535 / 255;
|
rgba.blue = CefColorGetB(background_color) * 65535 / 255;
|
||||||
gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &color);
|
rgba.alpha = 1;
|
||||||
|
|
||||||
GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
|
gchar* css = g_strdup_printf("#* { background-color: %s; }",
|
||||||
g_signal_connect(vbox, "size-allocate",
|
gdk_rgba_to_string(&rgba));
|
||||||
G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this);
|
GtkCssProvider* provider = gtk_css_provider_new();
|
||||||
gtk_container_add(GTK_CONTAINER(window_), vbox);
|
gtk_css_provider_load_from_data(provider, css, -1, nullptr);
|
||||||
|
g_free(css);
|
||||||
|
gtk_style_context_add_provider(gtk_widget_get_style_context(window_),
|
||||||
|
GTK_STYLE_PROVIDER(provider),
|
||||||
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||||
|
g_object_unref(provider);
|
||||||
|
|
||||||
|
GtkWidget* grid = gtk_grid_new();
|
||||||
|
gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
|
||||||
|
g_signal_connect(grid, "size-allocate",
|
||||||
|
G_CALLBACK(&RootWindowGtk::GridSizeAllocated), this);
|
||||||
|
gtk_container_add(GTK_CONTAINER(window_), grid);
|
||||||
|
|
||||||
if (with_controls_) {
|
if (with_controls_) {
|
||||||
GtkWidget* menu_bar = CreateMenuBar();
|
GtkWidget* menu_bar = CreateMenuBar();
|
||||||
g_signal_connect(menu_bar, "size-allocate",
|
g_signal_connect(menu_bar, "size-allocate",
|
||||||
G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this);
|
G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this);
|
||||||
|
|
||||||
gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
|
gtk_grid_attach(GTK_GRID(grid), menu_bar, 0, 0, 1, 1);
|
||||||
|
|
||||||
GtkWidget* toolbar = gtk_toolbar_new();
|
GtkWidget* toolbar = gtk_toolbar_new();
|
||||||
// Turn off the labels on the toolbar buttons.
|
// Turn off the labels on the toolbar buttons.
|
||||||
|
@ -314,22 +356,26 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||||
g_signal_connect(toolbar, "size-allocate",
|
g_signal_connect(toolbar, "size-allocate",
|
||||||
G_CALLBACK(&RootWindowGtk::ToolbarSizeAllocated), this);
|
G_CALLBACK(&RootWindowGtk::ToolbarSizeAllocated), this);
|
||||||
|
|
||||||
back_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
|
back_button_ = gtk_tool_button_new(
|
||||||
|
gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_MENU), NULL);
|
||||||
g_signal_connect(back_button_, "clicked",
|
g_signal_connect(back_button_, "clicked",
|
||||||
G_CALLBACK(&RootWindowGtk::BackButtonClicked), this);
|
G_CALLBACK(&RootWindowGtk::BackButtonClicked), this);
|
||||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
|
||||||
|
|
||||||
forward_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
|
forward_button_ = gtk_tool_button_new(
|
||||||
|
gtk_image_new_from_icon_name("go-next", GTK_ICON_SIZE_MENU), NULL);
|
||||||
g_signal_connect(forward_button_, "clicked",
|
g_signal_connect(forward_button_, "clicked",
|
||||||
G_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this);
|
G_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this);
|
||||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
|
||||||
|
|
||||||
reload_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
|
reload_button_ = gtk_tool_button_new(
|
||||||
|
gtk_image_new_from_icon_name("view-refresh", GTK_ICON_SIZE_MENU), NULL);
|
||||||
g_signal_connect(reload_button_, "clicked",
|
g_signal_connect(reload_button_, "clicked",
|
||||||
G_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this);
|
G_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this);
|
||||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
|
||||||
|
|
||||||
stop_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
|
stop_button_ = gtk_tool_button_new(
|
||||||
|
gtk_image_new_from_icon_name("process-stop", GTK_ICON_SIZE_MENU), NULL);
|
||||||
g_signal_connect(stop_button_, "clicked",
|
g_signal_connect(stop_button_, "clicked",
|
||||||
G_CALLBACK(&RootWindowGtk::StopButtonClicked), this);
|
G_CALLBACK(&RootWindowGtk::StopButtonClicked), this);
|
||||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
|
||||||
|
@ -345,7 +391,8 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||||
gtk_tool_item_set_expand(tool_item, TRUE);
|
gtk_tool_item_set_expand(tool_item, TRUE);
|
||||||
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append
|
||||||
|
|
||||||
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
|
gtk_grid_attach_next_to(GTK_GRID(grid), toolbar, menu_bar, GTK_POS_BOTTOM,
|
||||||
|
1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Realize (show) the GTK widget. This must be done before the browser is
|
// Realize (show) the GTK widget. This must be done before the browser is
|
||||||
|
@ -360,8 +407,8 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||||
|
|
||||||
// Windowed browsers are parented to the X11 Window underlying the GtkWindow*
|
// Windowed browsers are parented to the X11 Window underlying the GtkWindow*
|
||||||
// and must be sized manually. The OSR GTK widget, on the other hand, can be
|
// and must be sized manually. The OSR GTK widget, on the other hand, can be
|
||||||
// added to the Vbox container for automatic layout-based sizing.
|
// added to the grid container for automatic layout-based sizing.
|
||||||
GtkWidget* parent = with_osr_ ? vbox : window_;
|
GtkWidget* parent = with_osr_ ? grid : window_;
|
||||||
|
|
||||||
// Set the Display associated with the browser.
|
// Set the Display associated with the browser.
|
||||||
::Display* xdisplay = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(window_));
|
::Display* xdisplay = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(window_));
|
||||||
|
@ -746,7 +793,7 @@ gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget,
|
void RootWindowGtk::GridSizeAllocated(GtkWidget* widget,
|
||||||
GtkAllocation* allocation,
|
GtkAllocation* allocation,
|
||||||
RootWindowGtk* self) {
|
RootWindowGtk* self) {
|
||||||
// May be called on the main thread and the UI thread.
|
// May be called on the main thread and the UI thread.
|
||||||
|
|
|
@ -97,7 +97,7 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||||
RootWindowGtk* self);
|
RootWindowGtk* self);
|
||||||
|
|
||||||
// Signal handlers for the GTK Vbox containing all UX elements.
|
// Signal handlers for the GTK Vbox containing all UX elements.
|
||||||
static void VboxSizeAllocated(GtkWidget* widget,
|
static void GridSizeAllocated(GtkWidget* widget,
|
||||||
GtkAllocation* allocation,
|
GtkAllocation* allocation,
|
||||||
RootWindowGtk* self);
|
RootWindowGtk* self);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
// can be found in the LICENSE file.
|
// can be found in the LICENSE file.
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <gtk/gtkgl.h>
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#undef Success // Definition conflicts with cef_message_router.h
|
#undef Success // Definition conflicts with cef_message_router.h
|
||||||
|
@ -98,6 +97,13 @@ int RunMain(int argc, char* argv[]) {
|
||||||
// Populate the settings based on command line arguments.
|
// Populate the settings based on command line arguments.
|
||||||
context->PopulateSettings(&settings);
|
context->PopulateSettings(&settings);
|
||||||
|
|
||||||
|
if (settings.windowless_rendering_enabled) {
|
||||||
|
// Force the app to use OpenGL <= 3.1 when off-screen rendering is enabled.
|
||||||
|
// TODO(cefclient): Rewrite OSRRenderer to use shaders instead of the
|
||||||
|
// fixed-function pipeline which was removed in OpenGL 3.2 (back in 2009).
|
||||||
|
setenv("MESA_GL_VERSION_OVERRIDE", "3.1", /*overwrite=*/0);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the main message loop object.
|
// Create the main message loop object.
|
||||||
scoped_ptr<MainMessageLoop> message_loop;
|
scoped_ptr<MainMessageLoop> message_loop;
|
||||||
if (settings.multi_threaded_message_loop)
|
if (settings.multi_threaded_message_loop)
|
||||||
|
@ -110,13 +116,13 @@ int RunMain(int argc, char* argv[]) {
|
||||||
// Initialize CEF.
|
// Initialize CEF.
|
||||||
context->Initialize(main_args, settings, app, nullptr);
|
context->Initialize(main_args, settings, app, nullptr);
|
||||||
|
|
||||||
|
// Force Gtk to use Xwayland (in case a Wayland compositor is being used).
|
||||||
|
gdk_set_allowed_backends("x11");
|
||||||
|
|
||||||
// The Chromium sandbox requires that there only be a single thread during
|
// The Chromium sandbox requires that there only be a single thread during
|
||||||
// initialization. Therefore initialize GTK after CEF.
|
// initialization. Therefore initialize GTK after CEF.
|
||||||
gtk_init(&argc, &argv_copy);
|
gtk_init(&argc, &argv_copy);
|
||||||
|
|
||||||
// Perform gtkglext initialization required by the OSR example.
|
|
||||||
gtk_gl_init(&argc, &argv_copy);
|
|
||||||
|
|
||||||
// Install xlib error handlers so that the application won't be terminated
|
// Install xlib error handlers so that the application won't be terminated
|
||||||
// on non-fatal errors. Must be done after initializing GTK.
|
// on non-fatal errors. Must be done after initializing GTK.
|
||||||
XSetErrorHandler(XErrorHandlerImpl);
|
XSetErrorHandler(XErrorHandlerImpl);
|
||||||
|
|
|
@ -30,4 +30,9 @@ void DeviceToLogical(CefMouseEvent& value, float device_scale_factor) {
|
||||||
value.y = DeviceToLogical(value.y, device_scale_factor);
|
value.y = DeviceToLogical(value.y, device_scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceToLogical(CefTouchEvent& value, float device_scale_factor) {
|
||||||
|
value.x = DeviceToLogical(value.x, device_scale_factor);
|
||||||
|
value.y = DeviceToLogical(value.y, device_scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -17,6 +17,7 @@ CefRect LogicalToDevice(const CefRect& value, float device_scale_factor);
|
||||||
// Convert |value| from device coordinates to logical coordinates.
|
// Convert |value| from device coordinates to logical coordinates.
|
||||||
int DeviceToLogical(int value, float device_scale_factor);
|
int DeviceToLogical(int value, float device_scale_factor);
|
||||||
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
|
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
|
||||||
|
void DeviceToLogical(CefTouchEvent& value, float device_scale_factor);
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue