diff --git a/wxGTK3-3.0.2-check-radio-button-rendering.patch b/wxGTK3-3.0.2-check-radio-button-rendering.patch new file mode 100644 index 0000000..8367ae9 --- /dev/null +++ b/wxGTK3-3.0.2-check-radio-button-rendering.patch @@ -0,0 +1,256 @@ +From ec023e99774d90e3ac16a3a5b4e55c6cdf9fb3c1 Mon Sep 17 00:00:00 2001 +From: Paul Cornett +Date: Sat, 10 Dec 2016 21:49:06 -0800 +Subject: [PATCH] Fix rendering of check and radio buttons with GTK+ >= 3.20 + +(cherry picked from commit e627970ba6126113fdf09db69c50582b369d0d8a) +--- + src/gtk/renderer.cpp | 184 ++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 153 insertions(+), 31 deletions(-) + +diff --git a/src/gtk/renderer.cpp b/src/gtk/renderer.cpp +index 965d5fe..c89b0d3 100644 +--- a/src/gtk/renderer.cpp ++++ b/src/gtk/renderer.cpp +@@ -503,6 +503,49 @@ wxRendererGTK::DrawComboBoxDropButton(wxWindow *win, + wxSize + wxRendererGTK::GetCheckBoxSize(wxWindow *WXUNUSED(win)) + { ++#ifdef __WXGTK3__ ++ int min_width, min_height; ++ GtkWidgetPath* path = gtk_widget_path_new(); ++ GtkStyleContext* sc = gtk_style_context_new(); ++ GtkStyleContext* sc1 = NULL; ++ gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON); ++#if GTK_CHECK_VERSION(3,20,0) ++ if (gtk_check_version(3,20,0) == NULL) ++ { ++ gtk_widget_path_iter_set_object_name(path, -1, "checkbutton"); ++ sc1 = gtk_style_context_new(); ++ gtk_style_context_set_path(sc1, path); ++ gtk_widget_path_append_type(path, G_TYPE_NONE); ++ gtk_widget_path_iter_set_object_name(path, -1, "check"); ++ gtk_style_context_set_path(sc, path); ++ gtk_style_context_set_parent(sc, sc1); ++ gtk_style_context_get(sc, GTK_STATE_FLAG_NORMAL, ++ "min-width", &min_width, "min-height", &min_height, NULL); ++ GtkBorder margin; ++ gtk_style_context_get_margin(sc, GTK_STATE_FLAG_NORMAL, &margin); ++ min_width += margin.left + margin.right; ++ min_height += margin.top + margin.bottom; ++ } ++ else ++#endif ++ { ++ gtk_style_context_set_path(sc, path); ++ GValue value = G_VALUE_INIT; ++ g_value_init(&value, G_TYPE_INT); ++ gtk_style_context_get_style_property(sc, "indicator-size", &value); ++ min_width = g_value_get_int(&value); ++ gtk_style_context_get_style_property(sc, "indicator-spacing", &value); ++ min_width += 2 * g_value_get_int(&value); ++ min_height = min_width; ++ g_value_unset(&value); ++ } ++ gtk_widget_path_unref(path); ++ g_object_unref(sc); ++ if (sc1) ++ g_object_unref(sc1); ++ ++ return wxSize(min_width, min_height); ++#else // !__WXGTK3__ + gint indicator_size, indicator_spacing; + gtk_widget_style_get(wxGTKPrivate::GetCheckButtonWidget(), + "indicator_size", &indicator_size, +@@ -511,6 +554,7 @@ wxRendererGTK::GetCheckBoxSize(wxWindow *WXUNUSED(win)) + + int size = indicator_size + indicator_spacing * 2; + return wxSize(size, size); ++#endif // !__WXGTK3__ + } + + void +@@ -519,6 +563,7 @@ wxRendererGTK::DrawCheckBox(wxWindow* win, + const wxRect& rect, + int flags ) + { ++#ifndef __WXGTK3__ + GtkWidget *button = wxGTKPrivate::GetCheckButtonWidget(); + + gint indicator_size, indicator_spacing; +@@ -527,7 +572,6 @@ wxRendererGTK::DrawCheckBox(wxWindow* win, + "indicator_spacing", &indicator_spacing, + NULL); + +-#ifndef __WXGTK3__ + GtkStateType state; + + if ( flags & wxCONTROL_PRESSED ) +@@ -551,31 +595,68 @@ wxRendererGTK::DrawCheckBox(wxWindow* win, + + #ifdef __WXGTK3__ + cairo_t* cr = wxGetGTKDrawable(win, dc); +- if (cr) ++ if (cr == NULL) ++ return; ++ ++ int state = GTK_STATE_FLAG_NORMAL; ++ if (flags & wxCONTROL_CHECKED) + { +- int stateFlags = GTK_STATE_FLAG_NORMAL; +- if (flags & wxCONTROL_CHECKED) +- { +- stateFlags = GTK_STATE_FLAG_ACTIVE; +- if (gtk_check_version(3,14,0) == NULL) +- stateFlags = GTK_STATE_FLAG_CHECKED; +- } +- if (flags & wxCONTROL_DISABLED) +- stateFlags |= GTK_STATE_FLAG_INSENSITIVE; +- if (flags & wxCONTROL_UNDETERMINED) +- stateFlags |= GTK_STATE_FLAG_INCONSISTENT; +- if (flags & wxCONTROL_CURRENT) +- stateFlags |= GTK_STATE_FLAG_PRELIGHT; +- GtkStyleContext* sc = gtk_widget_get_style_context(button); +- gtk_style_context_save(sc); +- gtk_style_context_set_state(sc, GtkStateFlags(stateFlags)); +- gtk_style_context_add_class(sc, GTK_STYLE_CLASS_CHECK); +- gtk_render_check(sc, cr, +- rect.x + (rect.width - indicator_size) / 2, +- rect.y + (rect.height - indicator_size) / 2, +- indicator_size, indicator_size); +- gtk_style_context_restore(sc); ++ state = GTK_STATE_FLAG_ACTIVE; ++ if (gtk_check_version(3,14,0) == NULL) ++ state = GTK_STATE_FLAG_CHECKED; ++ } ++ if (flags & wxCONTROL_DISABLED) ++ state |= GTK_STATE_FLAG_INSENSITIVE; ++ if (flags & wxCONTROL_UNDETERMINED) ++ state |= GTK_STATE_FLAG_INCONSISTENT; ++ if (flags & wxCONTROL_CURRENT) ++ state |= GTK_STATE_FLAG_PRELIGHT; ++ ++ int min_width, min_height; ++ GtkWidgetPath* path = gtk_widget_path_new(); ++ GtkStyleContext* sc = gtk_style_context_new(); ++ GtkStyleContext* sc1 = NULL; ++ gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON); ++#if GTK_CHECK_VERSION(3,20,0) ++ if (gtk_check_version(3,20,0) == NULL) ++ { ++ gtk_widget_path_iter_set_object_name(path, -1, "checkbutton"); ++ sc1 = gtk_style_context_new(); ++ gtk_style_context_set_path(sc1, path); ++ gtk_widget_path_append_type(path, G_TYPE_NONE); ++ gtk_widget_path_iter_set_object_name(path, -1, "check"); ++ gtk_style_context_set_path(sc, path); ++ gtk_style_context_set_parent(sc, sc1); ++ gtk_style_context_get(sc, GTK_STATE_FLAG_NORMAL, ++ "min-width", &min_width, "min-height", &min_height, NULL); ++ } ++ else ++#endif ++ { ++ gtk_style_context_set_path(sc, path); ++ GValue value = G_VALUE_INIT; ++ g_value_init(&value, G_TYPE_INT); ++ gtk_style_context_get_style_property(sc, "indicator-size", &value); ++ min_width = g_value_get_int(&value); ++ min_height = min_width; ++ g_value_unset(&value); + } ++ ++ // need save/restore for GTK+ 3.6 & 3.8 ++ gtk_style_context_save(sc); ++ gtk_style_context_set_state(sc, GtkStateFlags(state)); ++ const int x = rect.x + (rect.width - min_width) / 2; ++ const int y = rect.y + (rect.height - min_height) / 2; ++ gtk_render_background(sc, cr, x, y, min_width, min_height); ++ gtk_render_frame(sc, cr, x, y, min_width, min_height); ++ gtk_style_context_add_class(sc, "check"); ++ gtk_render_check(sc, cr, x, y, min_width, min_height); ++ gtk_style_context_restore(sc); ++ ++ gtk_widget_path_unref(path); ++ g_object_unref(sc); ++ if (sc1) ++ g_object_unref(sc1); + #else + GdkWindow* gdk_window = wxGetGTKDrawable(win, dc); + if (gdk_window == NULL) +@@ -869,8 +950,6 @@ void wxRendererGTK::DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, + if (drawable == NULL) + return; + +- GtkWidget* button = wxGTKPrivate::GetRadioButtonWidget(); +- + #ifdef __WXGTK3__ + int state = GTK_STATE_FLAG_NORMAL; + if (flags & wxCONTROL_CHECKED) +@@ -879,18 +958,61 @@ void wxRendererGTK::DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, + if (gtk_check_version(3,14,0) == NULL) + state = GTK_STATE_FLAG_CHECKED; + } +- else if (flags & wxCONTROL_UNDETERMINED) +- state = GTK_STATE_FLAG_INCONSISTENT; + if (flags & wxCONTROL_DISABLED) + state |= GTK_STATE_FLAG_INSENSITIVE; ++ if (flags & wxCONTROL_UNDETERMINED) ++ state |= GTK_STATE_FLAG_INCONSISTENT; ++ if (flags & wxCONTROL_CURRENT) ++ state |= GTK_STATE_FLAG_PRELIGHT; ++ ++ int min_width, min_height; ++ GtkWidgetPath* path = gtk_widget_path_new(); ++ GtkStyleContext* sc = gtk_style_context_new(); ++ GtkStyleContext* sc1 = NULL; ++ gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON); ++#if GTK_CHECK_VERSION(3,20,0) ++ if (gtk_check_version(3,20,0) == NULL) ++ { ++ gtk_widget_path_iter_set_object_name(path, -1, "radiobutton"); ++ sc1 = gtk_style_context_new(); ++ gtk_style_context_set_path(sc1, path); ++ gtk_widget_path_append_type(path, G_TYPE_NONE); ++ gtk_widget_path_iter_set_object_name(path, -1, "radio"); ++ gtk_style_context_set_path(sc, path); ++ gtk_style_context_set_parent(sc, sc1); ++ gtk_style_context_get(sc, GTK_STATE_FLAG_NORMAL, ++ "min-width", &min_width, "min-height", &min_height, NULL); ++ } ++ else ++#endif ++ { ++ gtk_style_context_set_path(sc, path); ++ GValue value = G_VALUE_INIT; ++ g_value_init(&value, G_TYPE_INT); ++ gtk_style_context_get_style_property(sc, "indicator-size", &value); ++ min_width = g_value_get_int(&value); ++ min_height = min_width; ++ g_value_unset(&value); ++ } + +- GtkStyleContext* sc = gtk_widget_get_style_context(button); ++ // need save/restore for GTK+ 3.6 & 3.8 + gtk_style_context_save(sc); +- gtk_style_context_add_class(sc, GTK_STYLE_CLASS_RADIO); + gtk_style_context_set_state(sc, GtkStateFlags(state)); +- gtk_render_option(sc, drawable, rect.x, rect.y, rect.width, rect.height); ++ const int x = rect.x + (rect.width - min_width) / 2; ++ const int y = rect.y + (rect.height - min_height) / 2; ++ gtk_render_background(sc, drawable, x, y, min_width, min_height); ++ gtk_render_frame(sc, drawable, x, y, min_width, min_height); ++ gtk_style_context_add_class(sc, "radio"); ++ gtk_render_option(sc, drawable, x, y, min_width, min_height); + gtk_style_context_restore(sc); ++ ++ gtk_widget_path_unref(path); ++ g_object_unref(sc); ++ if (sc1) ++ g_object_unref(sc1); + #else ++ GtkWidget* button = wxGTKPrivate::GetRadioButtonWidget(); ++ + GtkShadowType shadow_type = GTK_SHADOW_OUT; + if ( flags & wxCONTROL_CHECKED ) + shadow_type = GTK_SHADOW_IN; diff --git a/wxGTK3-3.0.2-unresizable-windows-hidpi.patch b/wxGTK3-3.0.2-unresizable-windows-hidpi.patch new file mode 100644 index 0000000..71cecac --- /dev/null +++ b/wxGTK3-3.0.2-unresizable-windows-hidpi.patch @@ -0,0 +1,29 @@ +From a97553a939b76df1564ffbfe9c919d1da5a34c5a Mon Sep 17 00:00:00 2001 +From: Paul Cornett +Date: Mon, 21 Mar 2016 09:46:46 -0700 +Subject: [PATCH] Avoid unresizable windows on HiDPI displays when using + SetSizeHints() + +see #17456 + +(cherry picked from commit 4793e5b0a4e189e492287305859b278fed780080) +--- + src/gtk/toplevel.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp +index 464fb3f..69fca2a 100644 +--- a/src/gtk/toplevel.cpp ++++ b/src/gtk/toplevel.cpp +@@ -1273,8 +1273,9 @@ void wxTopLevelWindowGTK::DoSetSizeHints( int minW, int minH, + int hints_mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE; + hints.min_width = 1; + hints.min_height = 1; +- hints.max_width = INT_MAX; +- hints.max_height = INT_MAX; ++ // using INT_MAX for size will lead to integer overflow with HiDPI scaling ++ hints.max_width = INT_MAX / 16; ++ hints.max_height = INT_MAX / 16; + int decorSize_x; + int decorSize_y; + #ifdef HAS_CLIENT_DECOR diff --git a/wxGTK3.spec b/wxGTK3.spec index 8a1f065..b10f4ae 100644 --- a/wxGTK3.spec +++ b/wxGTK3.spec @@ -11,7 +11,7 @@ Name: %{wxgtkname} Version: 3.0.2 -Release: 30%{?dist} +Release: 31%{?dist} Summary: GTK port of the wxWidgets GUI library License: wxWidgets Group: System Environment/Libraries @@ -113,6 +113,14 @@ Patch23: %{name}-%{version}-paint-clipping-region.patch # For more details, see the upstream commit: # https://github.com/wxWidgets/wxWidgets/commit/dcc23ceba8e1dba828e8b3e4633ac77acaad7562 Patch24: %{name}-%{version}-wxpgchoicesdata-protected-destructor.patch +# Fixes unresizable windows on HiDPI displays +# For more details, see the upstream commit: +# https://github.com/wxWidgets/wxWidgets/commit/a97553a939b76df1564ffbfe9c919d1da5a34c5a +Patch25: %{name}-%{version}-unresizable-windows-hidpi.patch +# Fixes rendering of check and radio buttons with GTK+ >= 3.20 +# For more details, see the upstream commit: +# https://github.com/wxWidgets/wxWidgets/commit/ec023e99774d90e3ac16a3a5b4e55c6cdf9fb3c1 +Patch26: %{name}-%{version}-check-radio-button-rendering.patch BuildRequires: gtk%{gtkver}-devel #Note webkitgtk (GTK2) does not appear to be supported @@ -414,6 +422,10 @@ fi %doc docs/doxygen/out/xml/* %changelog +* Wed Dec 28 2016 Scott Talbert - 3.0.2-31 +- Fix unresizable windows on HiDPI displays (#1402630) +- Fix rendering of check and radio buttons on GTK+ 3.20+ (#1405841) + * Mon Nov 21 2016 Scott Talbert - 3.0.2-30 - Fix poedit regression in -29 - add paint clipping region patch (#1396747) - Add patch to change ~wxPGChoicesData from private to protected