diff --git a/BUILD.gn b/BUILD.gn index 6ec657d9c..184769437 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2035,18 +2035,12 @@ if (is_mac) { pkg_config("gtk") { packages = [ "gmodule-2.0", - "gtk+-2.0", + "gtk+-3.0", "gthread-2.0", - "gtk+-unix-print-2.0", + "gtk+-unix-print-3.0", "xi", ] } - - pkg_config("gtkglext") { - packages = [ - "gtkglext-1.0", - ] - } } if (is_linux) { @@ -2127,13 +2121,13 @@ if (is_mac) { ] libs = [ + "GL", "X11", ] if (cef_use_gtk) { configs += [ ":gtk", - ":gtkglext", ] } diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in index 0eb3e7de4..5c7fd65e1 100644 --- a/CMakeLists.txt.in +++ b/CMakeLists.txt.in @@ -44,8 +44,7 @@ # work but may not have been tested. # Required packages include: # build-essential -# libgtk2.0-dev (required by the cefclient target only) -# libgtkglext1-dev (required by the cefclient target only) +# libgtk3.0-dev (required by the cefclient target only) # # - MacOS requirements: # Xcode 8 or newer building on MacOS 10.11 (El Capitan) or newer for x86_64. diff --git a/cmake/cef_variables.cmake.in b/cmake/cef_variables.cmake.in index 6e418cc70..8e7c18544 100644 --- a/cmake/cef_variables.cmake.in +++ b/cmake/cef_variables.cmake.in @@ -95,6 +95,7 @@ if(OS_LINUX) -Wno-unused-parameter # Don't warn about unused parameters -Wno-error=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 -std=c99 # Use the C99 language standard diff --git a/tests/cefclient/CMakeLists.txt.in b/tests/cefclient/CMakeLists.txt.in index 51de5b671..84396999a 100644 --- a/tests/cefclient/CMakeLists.txt.in +++ b/tests/cefclient/CMakeLists.txt.in @@ -122,13 +122,13 @@ if(OS_LINUX) ) # 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. add_executable(${CEF_TARGET} ${CEFCLIENT_SRCS}) SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET}) 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_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN") diff --git a/tests/cefclient/browser/browser_window_osr_gtk.cc b/tests/cefclient/browser/browser_window_osr_gtk.cc index bb5918337..3b73f0c77 100644 --- a/tests/cefclient/browser/browser_window_osr_gtk.cc +++ b/tests/cefclient/browser/browser_window_osr_gtk.cc @@ -6,16 +6,14 @@ #include #include -#include +#include #include #include #include -#include #define XK_3270 // for XK_3270_BackTab #include #include -#include #include #include "include/base/cef_logging.h" @@ -29,17 +27,10 @@ namespace client { 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 // to correct browser, so we maintain a vector of all windows. std::vector g_browser_windows; -bool IsTouchAvailable() { - return g_xinput_extension != -1; -} - int GetCefStateModifiers(guint state) { int modifiers = 0; if (state & GDK_SHIFT_MASK) @@ -59,20 +50,6 @@ int GetCefStateModifiers(guint state) { 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. enum KeyboardCode { VKEY_BACK = 0x08, @@ -894,17 +871,20 @@ void GetWidgetRectInScreen(GtkWidget* widget, GdkRectangle* r) { // Get parent's left-top screen coordinates. gdk_window_get_root_origin(window, &x, &y); // 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. gdk_window_get_frame_extents(window, &extents); // X and Y calculations assume that left, right and bottom border sizes are // all the same. const gint border = (extents.width - w) / 2; - r->x = x + border + widget->allocation.x; - r->y = y + (extents.height - h) - border + widget->allocation.y; - r->width = widget->allocation.width; - r->height = widget->allocation.height; + GtkAllocation allocation; + gtk_widget_get_allocation(widget, &allocation); + r->x = x + border + allocation.x; + r->y = y + (extents.height - h) - border + allocation.y; + r->width = allocation.width; + r->height = allocation.height; } CefBrowserHost::DragOperationsMask GetDragOperationsMask( @@ -925,30 +905,25 @@ CefBrowserHost::DragOperationsMask GetDragOperationsMask( class ScopedGLContext { public: ScopedGLContext(GtkWidget* widget, bool swap_buffers) - : swap_buffers_(swap_buffers) { - GdkGLContext* glcontext = gtk_widget_get_gl_context(widget); - gldrawable_ = gtk_widget_get_gl_drawable(widget); - is_valid_ = gdk_gl_drawable_gl_begin(gldrawable_, glcontext); + : swap_buffers_(swap_buffers), widget_(widget) { + gtk_gl_area_make_current(GTK_GL_AREA(widget)); + is_valid_ = gtk_gl_area_get_error(GTK_GL_AREA(widget)) == NULL; + 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() { - if (is_valid_) { - gdk_gl_drawable_gl_end(gldrawable_); - - if (swap_buffers_) { - if (gdk_gl_drawable_is_double_buffered(gldrawable_)) - gdk_gl_drawable_swap_buffers(gldrawable_); - else - glFlush(); - } - } + if (swap_buffers_ && is_valid_) + glFlush(); } bool IsValid() const { return is_valid_; } private: bool swap_buffers_; - GdkGLDrawable* gldrawable_; + GtkWidget* const widget_; bool is_valid_; ScopedGdkThreadsEnter scoped_gdk_threads_; }; @@ -1013,11 +988,11 @@ void BrowserWindowOsrGtk::CreateBrowser( // Retrieve the X11 Window ID for the GTK parent window. GtkWidget* window = gtk_widget_get_ancestor(GTK_WIDGET(parent_handle), GTK_TYPE_WINDOW); - ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(window)); - DCHECK(xwindow); + CefWindowHandle handle = GDK_WINDOW_XID(gtk_widget_get_window(window)); + DCHECK(handle); CefWindowInfo window_info; - window_info.SetAsWindowless(xwindow); + window_info.SetAsWindowless(handle); // Create the browser asynchronously. CefBrowserHost::CreateBrowser(window_info, client_handler_, @@ -1172,11 +1147,12 @@ void BrowserWindowOsrGtk::GetViewRect(CefRefPtr browser, // The simulated screen and view rectangle are the same. This is necessary // 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) rect.width = 1; - rect.height = - DeviceToLogical(glarea_->allocation.height, device_scale_factor); + rect.height = DeviceToLogical(allocation.height, device_scale_factor); if (rect.height == 0) rect.height = 1; } @@ -1373,18 +1349,13 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) { ScopedGdkThreadsEnter scoped_gdk_threads; - glarea_ = gtk_drawing_area_new(); + glarea_ = gtk_gl_area_new(); DCHECK(glarea_); - GdkGLConfig* glconfig = - gdk_gl_config_new_by_mode(static_cast( - 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_gl_area_set_auto_render(GTK_GL_AREA(glarea_), FALSE); + g_signal_connect(G_OBJECT(glarea_), "size_allocate", G_CALLBACK(&BrowserWindowOsrGtk::SizeAllocation), this); @@ -1414,18 +1385,16 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) { G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this); g_signal_connect(G_OBJECT(glarea_), "focus_out_event", G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this); + g_signal_connect(G_OBJECT(glarea_), "touch-event", + G_CALLBACK(&BrowserWindowOsrGtk::TouchEvent), this); 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. gtk_widget_show_all(parent_handle); - - InitializeXinput(xdisplay_); - - if (IsTouchAvailable()) - RegisterTouch(); } // static @@ -1661,6 +1630,9 @@ gint BrowserWindowOsrGtk::ScrollEvent(GtkWidget* widget, case GDK_SCROLL_RIGHT: deltaX = -scrollbarPixelsPerGtkTick; break; + case GDK_SCROLL_SMOOTH: + NOTIMPLEMENTED(); + break; } host->SendMouseWheelEvent(mouse_event, deltaX, deltaY); @@ -1677,106 +1649,49 @@ gint BrowserWindowOsrGtk::FocusEvent(GtkWidget* widget, return TRUE; } -void BrowserWindowOsrGtk::TouchEvent(CefXIDeviceEvent event) { - if (!browser_.get()) - return; +// static +gboolean BrowserWindowOsrGtk::TouchEvent(GtkWidget* widget, + GdkEventTouch* event, + BrowserWindowOsrGtk* self) { + REQUIRE_MAIN_THREAD(); - XIDeviceEvent* ev = static_cast(event); - CefTouchEvent cef_event; - switch (ev->evtype) { - case XI_TouchBegin: - cef_event.type = CEF_TET_PRESSED; + if (!self->browser_.get()) + return TRUE; + + CefRefPtr host = self->browser_->GetHost(); + + 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; - case XI_TouchUpdate: - cef_event.type = CEF_TET_MOVED; + case GDK_TOUCH_UPDATE: + touch_event.type = CEF_TET_MOVED; break; - case XI_TouchEnd: - cef_event.type = CEF_TET_RELEASED; + case GDK_TOUCH_END: + touch_event.type = CEF_TET_RELEASED; break; default: - return; + return TRUE; } - cef_event.id = ev->detail; - cef_event.x = ev->event_x; - cef_event.y = ev->event_y; - cef_event.radius_x = 0; - cef_event.radius_y = 0; - cef_event.rotation_angle = 0; - cef_event.pressure = 0; - cef_event.modifiers = GetCefStateModifiers(ev->mods, ev->buttons); + touch_event.x = event->x; + touch_event.y = event->y; + touch_event.radius_x = 0; + touch_event.radius_y = 0; + touch_event.rotation_angle = 0; + touch_event.pressure = 0; + DeviceToLogical(touch_event, device_scale_factor); + touch_event.modifiers = GetCefStateModifiers(event->state); - browser_->GetHost()->SendTouchEvent(cef_event); -} - -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(&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(gdk_xevent); - if (xevent->type == GenericEvent && - xevent->xgeneric.extension == g_xinput_extension) { - XGetEventData(xevent->xcookie.display, &xevent->xcookie); - XIDeviceEvent* ev = static_cast(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; - } - } + host->SendTouchEvent(touch_event); + return TRUE; } bool BrowserWindowOsrGtk::IsOverPopupWidget(int x, int y) const { diff --git a/tests/cefclient/browser/browser_window_osr_gtk.h b/tests/cefclient/browser/browser_window_osr_gtk.h index 0847e37ff..fa99c00f8 100644 --- a/tests/cefclient/browser/browser_window_osr_gtk.h +++ b/tests/cefclient/browser/browser_window_osr_gtk.h @@ -117,8 +117,10 @@ class BrowserWindowOsrGtk : public BrowserWindow, static gint FocusEvent(GtkWidget* widget, GdkEventFocus* event, BrowserWindowOsrGtk* self); + static gboolean TouchEvent(GtkWidget* widget, + GdkEventTouch* event, + BrowserWindowOsrGtk* self); - void TouchEvent(CefXIDeviceEvent event); void RegisterTouch(); bool IsOverPopupWidget(int x, int y) const; @@ -176,7 +178,6 @@ class BrowserWindowOsrGtk : public BrowserWindow, static GdkFilterReturn EventFilter(GdkXEvent* gdk_xevent, GdkEvent* event, gpointer data); - static void InitializeXinput(XDisplay* xdisplay); XDisplay* xdisplay_; diff --git a/tests/cefclient/browser/dialog_handler_gtk.cc b/tests/cefclient/browser/dialog_handler_gtk.cc index 5daa52d7f..2522ffb66 100644 --- a/tests/cefclient/browser/dialog_handler_gtk.cc +++ b/tests/cefclient/browser/dialog_handler_gtk.cc @@ -135,10 +135,10 @@ GtkWindow* GetWindow(CefRefPtr browser) { scoped_refptr root_window = RootWindow::GetForBrowser(browser->GetIdentifier()); if (root_window) { - GtkWindow* window = GTK_WINDOW(root_window->GetWindowHandle()); + GtkWidget* window = root_window->GetWindowHandle(); if (!window) LOG(ERROR) << "No GtkWindow for browser"; - return window; + return GTK_WINDOW(window); } return nullptr; } @@ -238,13 +238,13 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params, if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) { action = GTK_FILE_CHOOSER_ACTION_OPEN; - accept_button = GTK_STOCK_OPEN; + accept_button = "_Open"; } else if (mode_type == FILE_DIALOG_OPEN_FOLDER) { action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - accept_button = GTK_STOCK_OPEN; + accept_button = "_Open"; } else if (mode_type == FILE_DIALOG_SAVE) { action = GTK_FILE_CHOOSER_ACTION_SAVE; - accept_button = GTK_STOCK_SAVE; + accept_button = "_Save"; } else { NOTREACHED(); params.callback->Cancel(); @@ -274,7 +274,7 @@ void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params, } 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); 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()); - GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), - GTK_STOCK_OK, GTK_RESPONSE_OK); + GtkWidget* ok_button = + gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), "_OK", GTK_RESPONSE_OK); if (params.dialog_type != JSDIALOGTYPE_PROMPT) gtk_widget_grab_focus(ok_button); diff --git a/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc b/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc index f05074e2e..36e4b5ab3 100644 --- a/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc +++ b/tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc @@ -5,7 +5,7 @@ #include "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h" #include -#include +#include #include "include/base/cef_bind.h" #include "include/base/cef_logging.h" diff --git a/tests/cefclient/browser/print_handler_gtk.cc b/tests/cefclient/browser/print_handler_gtk.cc index 922c85b96..2dc7b4732 100644 --- a/tests/cefclient/browser/print_handler_gtk.cc +++ b/tests/cefclient/browser/print_handler_gtk.cc @@ -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 // which deletes |this|. Execute it asnychronously so the call stack has a // chance to unwind. @@ -556,7 +556,7 @@ struct ClientPrintHandlerGtk::PrintHandler { static void OnJobCompletedThunk(GtkPrintJob* print_job, void* handler, - GError* error) { + const GError* error) { static_cast(handler)->OnJobCompleted(print_job, error); } diff --git a/tests/cefclient/browser/root_window_gtk.cc b/tests/cefclient/browser/root_window_gtk.cc index 964e222a5..51d85d9ba 100644 --- a/tests/cefclient/browser/root_window_gtk.cc +++ b/tests/cefclient/browser/root_window_gtk.cc @@ -29,6 +29,36 @@ namespace { 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) { GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window)); gint state = gdk_window_get_state(gdk_window); @@ -143,6 +173,7 @@ void RootWindowGtk::Show(ShowMode mode) { ScopedGdkThreadsEnter scoped_gdk_threads; // Show the GTK window. + UseDefaultX11VisualForGtk(GTK_WIDGET(window_)); gtk_widget_show_all(window_); if (mode == ShowMinimized) @@ -290,23 +321,34 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings, G_CALLBACK(&RootWindowGtk::WindowDelete), this); const cef_color_t background_color = MainContext::Get()->GetBackgroundColor(); - GdkColor color = {0}; - color.red = CefColorGetR(background_color) * 65535 / 255; - color.green = CefColorGetG(background_color) * 65535 / 255; - color.blue = CefColorGetB(background_color) * 65535 / 255; - gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &color); + GdkRGBA rgba = {0}; + rgba.red = CefColorGetR(background_color) * 65535 / 255; + rgba.green = CefColorGetG(background_color) * 65535 / 255; + rgba.blue = CefColorGetB(background_color) * 65535 / 255; + rgba.alpha = 1; - GtkWidget* vbox = gtk_vbox_new(FALSE, 0); - g_signal_connect(vbox, "size-allocate", - G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this); - gtk_container_add(GTK_CONTAINER(window_), vbox); + gchar* css = g_strdup_printf("#* { background-color: %s; }", + gdk_rgba_to_string(&rgba)); + GtkCssProvider* provider = gtk_css_provider_new(); + 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_) { GtkWidget* menu_bar = CreateMenuBar(); g_signal_connect(menu_bar, "size-allocate", 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(); // 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_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_CALLBACK(&RootWindowGtk::BackButtonClicked), this); 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_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this); 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_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this); 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_CALLBACK(&RootWindowGtk::StopButtonClicked), this); 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_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 @@ -360,8 +407,8 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings, // 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 - // added to the Vbox container for automatic layout-based sizing. - GtkWidget* parent = with_osr_ ? vbox : window_; + // added to the grid container for automatic layout-based sizing. + GtkWidget* parent = with_osr_ ? grid : window_; // Set the Display associated with the browser. ::Display* xdisplay = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(window_)); @@ -746,7 +793,7 @@ gboolean RootWindowGtk::WindowDelete(GtkWidget* widget, } // static -void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget, +void RootWindowGtk::GridSizeAllocated(GtkWidget* widget, GtkAllocation* allocation, RootWindowGtk* self) { // May be called on the main thread and the UI thread. diff --git a/tests/cefclient/browser/root_window_gtk.h b/tests/cefclient/browser/root_window_gtk.h index 9982c1474..5c0aab4e2 100644 --- a/tests/cefclient/browser/root_window_gtk.h +++ b/tests/cefclient/browser/root_window_gtk.h @@ -97,7 +97,7 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate { RootWindowGtk* self); // Signal handlers for the GTK Vbox containing all UX elements. - static void VboxSizeAllocated(GtkWidget* widget, + static void GridSizeAllocated(GtkWidget* widget, GtkAllocation* allocation, RootWindowGtk* self); diff --git a/tests/cefclient/cefclient_gtk.cc b/tests/cefclient/cefclient_gtk.cc index 02ae57154..4e81c1903 100644 --- a/tests/cefclient/cefclient_gtk.cc +++ b/tests/cefclient/cefclient_gtk.cc @@ -3,7 +3,6 @@ // can be found in the LICENSE file. #include -#include #include #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. 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. scoped_ptr message_loop; if (settings.multi_threaded_message_loop) @@ -110,13 +116,13 @@ int RunMain(int argc, char* argv[]) { // Initialize CEF. 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 // initialization. Therefore initialize GTK after CEF. 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 // on non-fatal errors. Must be done after initializing GTK. XSetErrorHandler(XErrorHandlerImpl); diff --git a/tests/shared/browser/geometry_util.cc b/tests/shared/browser/geometry_util.cc index 206edbc80..f7c3210b9 100644 --- a/tests/shared/browser/geometry_util.cc +++ b/tests/shared/browser/geometry_util.cc @@ -30,4 +30,9 @@ void DeviceToLogical(CefMouseEvent& value, float 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 diff --git a/tests/shared/browser/geometry_util.h b/tests/shared/browser/geometry_util.h index 1f1e188a6..fc2c476aa 100644 --- a/tests/shared/browser/geometry_util.h +++ b/tests/shared/browser/geometry_util.h @@ -17,6 +17,7 @@ CefRect LogicalToDevice(const CefRect& value, float device_scale_factor); // Convert |value| from device coordinates to logical coordinates. int DeviceToLogical(int value, float device_scale_factor); void DeviceToLogical(CefMouseEvent& value, float device_scale_factor); +void DeviceToLogical(CefTouchEvent& value, float device_scale_factor); } // namespace client