From 7dbbd75969b5f7c26e97ffe3e8f9da67fb3cfca4 Mon Sep 17 00:00:00 2001
From: whitequark <whitequark@whitequark.org>
Date: Mon, 2 Jan 2017 15:47:34 +0000
Subject: [PATCH] Drop support for GTK 2.

It's a deprecated platform that has weird OpenGL-related bugs and
is incompatible with using EGL anyway. It was clear we're going
to drop it, the only question was when. Answer: now.
---
 .travis/install-debian.sh |  2 +-
 CMakeLists.txt            | 16 +--------
 README.md                 |  7 ++--
 src/CMakeLists.txt        |  2 +-
 src/config.h.in           |  3 --
 src/platform/gtkmain.cpp  | 74 ++-------------------------------------
 6 files changed, 7 insertions(+), 97 deletions(-)

diff --git a/.travis/install-debian.sh b/.travis/install-debian.sh
index 73f91a3..a4c29bb 100755
--- a/.travis/install-debian.sh
+++ b/.travis/install-debian.sh
@@ -6,5 +6,5 @@ sudo add-apt-repository -y 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trust
 sudo apt-get update -qq
 sudo apt-get install -q -y \
   cmake cmake-data libpng12-dev zlib1g-dev libjson0-dev libfontconfig1-dev \
-  libgtkmm-2.4-dev libpangomm-1.4-dev libcairo2-dev libgl1-mesa-dev libglu-dev \
+  libgtkmm-3.0-dev libpangomm-1.4-dev libcairo2-dev libgl1-mesa-dev libglu-dev \
   libfreetype6-dev dpkg-dev libstdc++-5-dev clang-3.9 clang++-3.9 lcov
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8837fb5..f72ba25 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,10 +43,6 @@ set(ENABLE_SANITIZERS OFF CACHE BOOL
 
 set(OPENGL 2 CACHE STRING "OpenGL version to use (one of: 1 2)")
 
-if(NOT WIN32 AND NOT APPLE)
-    set(GUI gtk2 CACHE STRING "GUI toolkit to use (one of: gtk2 gtk3)")
-endif()
-
 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
 set(LIBRARY_OUTPUT_PATH    ${CMAKE_BINARY_DIR}/bin)
 
@@ -186,19 +182,9 @@ else() # Linux and compatible systems
     find_package(OpenGL REQUIRED)
 
     pkg_check_modules(CAIRO REQUIRED cairo)
-
     pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
     pkg_check_modules(JSONC REQUIRED json-c)
-
-    if(GUI STREQUAL "gtk3")
-        set(HAVE_GTK3 TRUE)
-        pkg_check_modules(GTKMM REQUIRED gtkmm-3.0 pangomm-1.4 x11)
-    elseif(GUI STREQUAL "gtk2")
-        set(HAVE_GTK2 TRUE)
-        pkg_check_modules(GTKMM REQUIRED gtkmm-2.4 pangomm-1.4 x11)
-    else()
-        message(FATAL_ERROR "GUI unrecognized: ${GUI}")
-    endif()
+    pkg_check_modules(GTKMM REQUIRED gtkmm-3.0 pangomm-1.4 x11)
 endif()
 
 if(ENABLE_COVERAGE)
diff --git a/README.md b/README.md
index e905cb3..1abd785 100644
--- a/README.md
+++ b/README.md
@@ -25,12 +25,12 @@ Building on Linux
 
 ### Building for Linux
 
-You will need CMake, zlib, json-c, libpng, cairo, freetype, fontconfig, gtkmm 2.4, pangomm 1.4,
+You will need CMake, zlib, json-c, libpng, cairo, freetype, fontconfig, gtkmm 3.0, pangomm 1.4,
 OpenGL and OpenGL GLU, and optionally, the Space Navigator client library.
 On a Debian derivative (e.g. Ubuntu) these can be installed with:
 
     apt-get install cmake libjson-c-dev libpng-dev libcairo2-dev libfreetype6-dev \
-                    libfontconfig1-dev libgtkmm-2.4-dev libpangomm-1.4-dev \
+                    libfontconfig1-dev libgtkmm-3.0-dev libpangomm-1.4-dev \
                     libgl-dev libglu-dev libspnav-dev
 
 Before building, check out the necessary submodules:
@@ -47,9 +47,6 @@ After that, build SolveSpace as following:
 
 The application is built as `build/bin/solvespace`.
 
-A fully functional port to GTK3 is available, but not recommended
-for use due to bugs in this toolkit.
-
 ### Building for Windows
 
 You will need CMake and a Windows cross-compiler.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a1ef081..3f57bae 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -109,7 +109,7 @@ elseif(APPLE)
     set(platform_BUNDLED_LIBS
         ${PNG_LIBRARIES}
         ${FREETYPE_LIBRARIES})
-elseif(HAVE_GTK2 OR HAVE_GTK3)
+else()
     set(platform_SOURCES
         platform/gtkmain.cpp
         render/rendergl.cpp
diff --git a/src/config.h.in b/src/config.h.in
index a3802d1..5c680c6 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -9,9 +9,6 @@
 /* Do we have the si library on win32, or libspnav on *nix? */
 #cmakedefine HAVE_SPACEWARE
 
-#cmakedefine HAVE_GTK2
-#cmakedefine HAVE_GTK3
-
 #define HAVE_OPENGL @OPENGL@
 
 #endif
diff --git a/src/platform/gtkmain.cpp b/src/platform/gtkmain.cpp
index 5f0707f..4337ce7 100644
--- a/src/platform/gtkmain.cpp
+++ b/src/platform/gtkmain.cpp
@@ -23,6 +23,7 @@
 #include <gtkmm/scrollbar.h>
 #include <gtkmm/entry.h>
 #include <gtkmm/eventbox.h>
+#include <gtkmm/hvbox.h>
 #include <gtkmm/fixed.h>
 #include <gtkmm/adjustment.h>
 #include <gtkmm/separatormenuitem.h>
@@ -37,12 +38,6 @@
 #include <gtkmm/messagedialog.h>
 #include <gtkmm/main.h>
 
-#if HAVE_GTK3
-#include <gtkmm/hvbox.h>
-#else
-#include <gtkmm/box.h>
-#endif
-
 #include <cairomm/xlib_surface.h>
 #include <pangomm/fontdescription.h>
 #include <gdk/gdkx.h>
@@ -301,12 +296,7 @@ public:
 protected:
     /* Draw on a GLX framebuffer object, then read pixels out and draw them on
        the Cairo context. Slower, but you get to overlay nice widgets. */
-#ifdef HAVE_GTK3
     bool on_draw(const Cairo::RefPtr<Cairo::Context> &cr) override {
-#else
-    bool on_expose_event(GdkEventExpose *) override {
-        const Cairo::RefPtr<Cairo::Context> &cr = get_window()->create_cairo_context();
-#endif
         ssassert(glXMakeCurrent(_xdisplay, _xwindow, _glcontext),
                  "Cannot make OpenGL context current");
 
@@ -360,18 +350,7 @@ public:
         Pango::FontDescription font_desc;
         font_desc.set_family(is_monospace ? "monospace" : "normal");
         font_desc.set_absolute_size(font_height * Pango::SCALE);
-
-#ifdef HAVE_GTK3
-        /* For some reason override_font doesn't take screen DPI into
-           account on GTK3 when working with font descriptors specified
-           in absolute sizes; modify_font does on GTK2. */
-        Pango::FontDescription override_font_desc(font_desc);
-        double dpi = get_screen()->get_resolution();
-        override_font_desc.set_size(font_height * 72.0 / dpi * Pango::SCALE);
-        _entry.override_font(override_font_desc);
-#else
-        _entry.modify_font(font_desc);
-#endif
+        _entry.override_font(font_desc);
 
         /* y coordinate denotes baseline */
         Pango::FontMetrics font_metrics = get_pango_context()->get_metrics(font_desc);
@@ -382,40 +361,22 @@ public:
         layout->set_text(val + " "); /* avoid scrolling */
         int width = layout->get_logical_extents().get_width();
 
-#ifdef HAVE_GTK3
         Gtk::Border border = _entry.get_style_context()->get_padding();
         move(_entry, x - border.get_left(), y - border.get_top());
         _entry.set_width_chars(minWidthChars);
         _entry.set_size_request(width / Pango::SCALE, -1);
-#else
-        /* We need _gtk_entry_effective_inner_border, but it's not
-           in the public API, so emulate its logic. */
-        Gtk::Border border = { 2, 2, 2, 2 }, *style_border;
-        gtk_widget_style_get(GTK_WIDGET(_entry.gobj()), "inner-border",
-                             &style_border, NULL);
-        if(style_border) border = *style_border;
-        move(_entry, x - border.left, y - border.top);
-        /* This is what set_width_chars does. */
-        int minWidth = minWidthChars * std::max(font_metrics.get_approximate_digit_width(),
-                                                font_metrics.get_approximate_char_width());
-        _entry.set_size_request(std::max(width, minWidth) / Pango::SCALE, -1);
-#endif
 
         _entry.set_text(val);
         if(!_entry.is_visible()) {
             _entry.show();
             _entry.grab_focus();
-#ifndef HAVE_GTK3
             _entry.add_modal_grab();
-#endif
         }
     }
 
     void stop_editing() {
-#ifndef HAVE_GTK3
         if(_entry.is_visible())
             _entry.remove_modal_grab();
-#endif
         _entry.hide();
     }
 
@@ -460,11 +421,7 @@ private:
 /* Graphics window */
 
 double DeltaYOfScrollEvent(GdkEventScroll *event) {
-#ifdef HAVE_GTK3
     double delta_y = event->delta_y;
-#else
-    double delta_y = 0;
-#endif
     if(delta_y == 0) {
         switch(event->direction) {
             case GDK_SCROLL_UP:
@@ -1056,11 +1013,7 @@ void RefreshRecentMenus(void) {
 static std::string ConvertFilters(std::string active, const FileFilter ssFilters[],
                                   Gtk::FileChooser *chooser) {
     for(const FileFilter *ssFilter = ssFilters; ssFilter->name; ssFilter++) {
-#ifdef HAVE_GTK3
         Glib::RefPtr<Gtk::FileFilter> filter = Gtk::FileFilter::create();
-#else
-        Gtk::FileFilter *filter = new Gtk::FileFilter;
-#endif
         filter->set_name(ssFilter->name);
 
         bool is_active = false;
@@ -1080,15 +1033,9 @@ static std::string ConvertFilters(std::string active, const FileFilter ssFilters
         }
         filter->set_name(filter->get_name() + " (" + desc + ")");
 
-#ifdef HAVE_GTK3
         chooser->add_filter(filter);
         if(is_active)
             chooser->set_filter(filter);
-#else
-        chooser->add_filter(*filter);
-        if(is_active)
-            chooser->set_filter(*filter);
-#endif
     }
 
     return active;
@@ -1251,11 +1198,7 @@ DialogChoice LocateImportedFileYesNoCancel(const std::string &filename,
 
 class TextWidget : public GlWidget {
 public:
-#ifdef HAVE_GTK3
     TextWidget(Glib::RefPtr<Gtk::Adjustment> adjustment) : _adjustment(adjustment) {
-#else
-    TextWidget(Gtk::Adjustment* adjustment) : _adjustment(adjustment) {
-#endif
         set_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::SCROLL_MASK |
                    Gdk::LEAVE_NOTIFY_MASK);
     }
@@ -1264,11 +1207,7 @@ public:
         Glib::RefPtr<Gdk::Window> gdkwin = get_window();
         if(gdkwin) { // returns NULL if not realized
             Gdk::CursorType type = is_hand ? Gdk::HAND1 : Gdk::ARROW;
-#ifdef HAVE_GTK3
             gdkwin->set_cursor(Gdk::Cursor::create(type));
-#else
-            gdkwin->set_cursor(Gdk::Cursor(type));
-#endif
         }
     }
 
@@ -1307,11 +1246,7 @@ protected:
     }
 
 private:
-#ifdef HAVE_GTK3
     Glib::RefPtr<Gtk::Adjustment> _adjustment;
-#else
-    Gtk::Adjustment *_adjustment;
-#endif
 };
 
 class TextWindowGtk : public Gtk::Window {
@@ -1571,14 +1506,9 @@ int main(int argc, char** argv) {
     GW->show_all();
 
 #ifdef HAVE_SPACEWARE
-#ifdef HAVE_GTK3
     // We don't care if it can't be opened; just continue without.
     spnav_x11_open(gdk_x11_get_default_xdisplay(),
                    gdk_x11_window_get_xid(GW->get_window()->gobj()));
-#else
-    spnav_x11_open(gdk_x11_get_default_xdisplay(),
-                   GDK_WINDOW_XWINDOW(GW->get_window()->gobj()));
-#endif
 #endif
 
     SS.Init();