From 85d63c31503b55ec9256c6cddc763e4fd1bed674 Mon Sep 17 00:00:00 2001 From: Paul Cornett Date: Tue, 15 Sep 2020 11:52:03 -0700 Subject: [PATCH] Add a class derived from GtkImage to support HiDPI bitmaps And use it to get HiDPI support wherever we use GtkImage. This extends and consolidates support for custom drawing of images which has already been added somewhat redundantly in several places. --- Makefile.in | 60 ++++++++++++ build/bakefiles/files.bkl | 1 + build/cmake/files.cmake | 1 + build/files | 1 + include/wx/gtk/private/image.h | 33 +++++++ src/gtk/anybutton.cpp | 5 +- src/gtk/button.cpp | 3 +- src/gtk/dataview.cpp | 7 +- src/gtk/image_gtk.cpp | 169 +++++++++++++++++++++++++++++++++ src/gtk/menu.cpp | 6 +- src/gtk/notebook.cpp | 17 ++-- src/gtk/statbmp.cpp | 54 +---------- src/gtk/tglbtn.cpp | 3 +- src/gtk/toolbar.cpp | 88 +++++------------ 14 files changed, 314 insertions(+), 134 deletions(-) create mode 100644 include/wx/gtk/private/image.h create mode 100644 src/gtk/image_gtk.cpp diff --git a/Makefile.in b/Makefile.in index 54fbec3abd..62beaa8482 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4995,6 +4995,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS = \ monodll_filectrl.o \ monodll_filehistory.o \ monodll_gtk_font.o \ + monodll_image_gtk.o \ monodll_gtk_sockgtk.o \ monodll_gtk_minifram.o \ monodll_gtk_nonownedwnd.o \ @@ -5035,6 +5036,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS = \ monodll_filectrl.o \ monodll_filehistory.o \ monodll_gtk_font.o \ + monodll_image_gtk.o \ monodll_gtk_sockgtk.o \ monodll_gtk_minifram.o \ monodll_gtk_nonownedwnd.o \ @@ -5072,6 +5074,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS = \ monodll_filectrl.o \ monodll_filehistory.o \ monodll_gtk_font.o \ + monodll_image_gtk.o \ monodll_gtk_sockgtk.o \ monodll_gtk_minifram.o \ monodll_gtk_nonownedwnd.o \ @@ -5899,6 +5902,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_1 = \ monodll_filectrl.o \ monodll_filehistory.o \ monodll_gtk_font.o \ + monodll_image_gtk.o \ monodll_gtk_sockgtk.o \ monodll_gtk_minifram.o \ monodll_gtk_nonownedwnd.o \ @@ -5939,6 +5943,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_1 = \ monodll_filectrl.o \ monodll_filehistory.o \ monodll_gtk_font.o \ + monodll_image_gtk.o \ monodll_gtk_sockgtk.o \ monodll_gtk_minifram.o \ monodll_gtk_nonownedwnd.o \ @@ -5976,6 +5981,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_1 = \ monodll_filectrl.o \ monodll_filehistory.o \ monodll_gtk_font.o \ + monodll_image_gtk.o \ monodll_gtk_sockgtk.o \ monodll_gtk_minifram.o \ monodll_gtk_nonownedwnd.o \ @@ -6976,6 +6982,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_2 = \ monolib_filectrl.o \ monolib_filehistory.o \ monolib_gtk_font.o \ + monolib_image_gtk.o \ monolib_gtk_sockgtk.o \ monolib_gtk_minifram.o \ monolib_gtk_nonownedwnd.o \ @@ -7016,6 +7023,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_2 = \ monolib_filectrl.o \ monolib_filehistory.o \ monolib_gtk_font.o \ + monolib_image_gtk.o \ monolib_gtk_sockgtk.o \ monolib_gtk_minifram.o \ monolib_gtk_nonownedwnd.o \ @@ -7053,6 +7061,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_2 = \ monolib_filectrl.o \ monolib_filehistory.o \ monolib_gtk_font.o \ + monolib_image_gtk.o \ monolib_gtk_sockgtk.o \ monolib_gtk_minifram.o \ monolib_gtk_nonownedwnd.o \ @@ -7880,6 +7889,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_3 = \ monolib_filectrl.o \ monolib_filehistory.o \ monolib_gtk_font.o \ + monolib_image_gtk.o \ monolib_gtk_sockgtk.o \ monolib_gtk_minifram.o \ monolib_gtk_nonownedwnd.o \ @@ -7920,6 +7930,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_3 = \ monolib_filectrl.o \ monolib_filehistory.o \ monolib_gtk_font.o \ + monolib_image_gtk.o \ monolib_gtk_sockgtk.o \ monolib_gtk_minifram.o \ monolib_gtk_nonownedwnd.o \ @@ -7957,6 +7968,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_3 = \ monolib_filectrl.o \ monolib_filehistory.o \ monolib_gtk_font.o \ + monolib_image_gtk.o \ monolib_gtk_sockgtk.o \ monolib_gtk_minifram.o \ monolib_gtk_nonownedwnd.o \ @@ -9103,6 +9115,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_4 = \ coredll_filectrl.o \ coredll_filehistory.o \ coredll_gtk_font.o \ + coredll_image_gtk.o \ coredll_gtk_sockgtk.o \ coredll_gtk_minifram.o \ coredll_gtk_nonownedwnd.o \ @@ -9143,6 +9156,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_4 = \ coredll_filectrl.o \ coredll_filehistory.o \ coredll_gtk_font.o \ + coredll_image_gtk.o \ coredll_gtk_sockgtk.o \ coredll_gtk_minifram.o \ coredll_gtk_nonownedwnd.o \ @@ -9180,6 +9194,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_4 = \ coredll_filectrl.o \ coredll_filehistory.o \ coredll_gtk_font.o \ + coredll_image_gtk.o \ coredll_gtk_sockgtk.o \ coredll_gtk_minifram.o \ coredll_gtk_nonownedwnd.o \ @@ -10007,6 +10022,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_5 = \ coredll_filectrl.o \ coredll_filehistory.o \ coredll_gtk_font.o \ + coredll_image_gtk.o \ coredll_gtk_sockgtk.o \ coredll_gtk_minifram.o \ coredll_gtk_nonownedwnd.o \ @@ -10047,6 +10063,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_5 = \ coredll_filectrl.o \ coredll_filehistory.o \ coredll_gtk_font.o \ + coredll_image_gtk.o \ coredll_gtk_sockgtk.o \ coredll_gtk_minifram.o \ coredll_gtk_nonownedwnd.o \ @@ -10084,6 +10101,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_5 = \ coredll_filectrl.o \ coredll_filehistory.o \ coredll_gtk_font.o \ + coredll_image_gtk.o \ coredll_gtk_sockgtk.o \ coredll_gtk_minifram.o \ coredll_gtk_nonownedwnd.o \ @@ -10820,6 +10838,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_6 = \ corelib_filectrl.o \ corelib_filehistory.o \ corelib_gtk_font.o \ + corelib_image_gtk.o \ corelib_gtk_sockgtk.o \ corelib_gtk_minifram.o \ corelib_gtk_nonownedwnd.o \ @@ -10860,6 +10879,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_6 = \ corelib_filectrl.o \ corelib_filehistory.o \ corelib_gtk_font.o \ + corelib_image_gtk.o \ corelib_gtk_sockgtk.o \ corelib_gtk_minifram.o \ corelib_gtk_nonownedwnd.o \ @@ -10897,6 +10917,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_6 = \ corelib_filectrl.o \ corelib_filehistory.o \ corelib_gtk_font.o \ + corelib_image_gtk.o \ corelib_gtk_sockgtk.o \ corelib_gtk_minifram.o \ corelib_gtk_nonownedwnd.o \ @@ -11724,6 +11745,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___LOWLEVEL_SRC_OBJECTS_7 = \ corelib_filectrl.o \ corelib_filehistory.o \ corelib_gtk_font.o \ + corelib_image_gtk.o \ corelib_gtk_sockgtk.o \ corelib_gtk_minifram.o \ corelib_gtk_nonownedwnd.o \ @@ -11764,6 +11786,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_3___LOWLEVEL_SRC_OBJECTS_7 = \ corelib_filectrl.o \ corelib_filehistory.o \ corelib_gtk_font.o \ + corelib_image_gtk.o \ corelib_gtk_sockgtk.o \ corelib_gtk_minifram.o \ corelib_gtk_nonownedwnd.o \ @@ -11801,6 +11824,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_4___LOWLEVEL_SRC_OBJECTS_7 = \ corelib_filectrl.o \ corelib_filehistory.o \ corelib_gtk_font.o \ + corelib_image_gtk.o \ corelib_gtk_sockgtk.o \ corelib_gtk_minifram.o \ corelib_gtk_nonownedwnd.o \ @@ -18333,6 +18357,15 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@monodll_gtk_font.o: $(srcdir)/src/gtk/font.cpp $(MONODLL_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/font.cpp +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@monodll_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(MONODLL_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@monodll_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(MONODLL_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@monodll_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(MONODLL_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@monodll_gtk_sockgtk.o: $(srcdir)/src/gtk/sockgtk.cpp $(MONODLL_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/sockgtk.cpp @@ -23592,6 +23625,15 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@monolib_gtk_font.o: $(srcdir)/src/gtk/font.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/font.cpp +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@monolib_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(MONOLIB_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@monolib_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(MONOLIB_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@monolib_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(MONOLIB_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@monolib_gtk_sockgtk.o: $(srcdir)/src/gtk/sockgtk.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/sockgtk.cpp @@ -28932,6 +28974,15 @@ coredll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(COREDLL_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@coredll_gtk_font.o: $(srcdir)/src/gtk/font.cpp $(COREDLL_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/font.cpp +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@coredll_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(COREDLL_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@coredll_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(COREDLL_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@coredll_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(COREDLL_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@coredll_gtk_sockgtk.o: $(srcdir)/src/gtk/sockgtk.cpp $(COREDLL_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/sockgtk.cpp @@ -33180,6 +33231,15 @@ corelib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(CORELIB_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@corelib_gtk_font.o: $(srcdir)/src/gtk/font.cpp $(CORELIB_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/font.cpp +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@corelib_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(CORELIB_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@corelib_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(CORELIB_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@corelib_image_gtk.o: $(srcdir)/src/gtk/image_gtk.cpp $(CORELIB_ODEP) +@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/image_gtk.cpp + @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@corelib_gtk_sockgtk.o: $(srcdir)/src/gtk/sockgtk.cpp $(CORELIB_ODEP) @COND_TOOLKIT_GTK_TOOLKIT_VERSION_4_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/sockgtk.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 983df6483b..6b906206a4 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -1397,6 +1397,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/gtk/filectrl.cpp src/gtk/filehistory.cpp src/gtk/font.cpp + src/gtk/image_gtk.cpp src/gtk/sockgtk.cpp src/gtk/minifram.cpp src/gtk/nonownedwnd.cpp diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index e60edd09fa..8165d51792 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -1281,6 +1281,7 @@ set(GTK_LOWLEVEL_SRC src/gtk/filectrl.cpp src/gtk/filehistory.cpp src/gtk/font.cpp + src/gtk/image_gtk.cpp src/gtk/sockgtk.cpp src/gtk/mimetype.cpp src/gtk/minifram.cpp diff --git a/build/files b/build/files index 490e4dfb7f..39a49b19c6 100644 --- a/build/files +++ b/build/files @@ -1293,6 +1293,7 @@ GTK_LOWLEVEL_SRC = src/gtk/filectrl.cpp src/gtk/filehistory.cpp src/gtk/font.cpp + src/gtk/image_gtk.cpp src/gtk/sockgtk.cpp src/gtk/mimetype.cpp src/gtk/minifram.cpp diff --git a/include/wx/gtk/private/image.h b/include/wx/gtk/private/image.h new file mode 100644 index 0000000000..ed5e7091bc --- /dev/null +++ b/include/wx/gtk/private/image.h @@ -0,0 +1,33 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/gtk/private/image.h +// Author: Paul Cornett +// Copyright: (c) 2020 Paul Cornett +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// Class that can be used in place of GtkImage, to allow drawing of alternate +// bitmaps, such as HiDPI or disabled. + +class wxGtkImage: GtkImage +{ +public: + struct BitmapProvider + { + virtual ~BitmapProvider() { } + virtual wxBitmap Get() const = 0; + virtual void Set(const wxBitmap&) { } + }; + + static GType Type(); + static GtkWidget* New(BitmapProvider* provider); + static GtkWidget* New(wxWindow* win = NULL); + void Set(const wxBitmap& bitmap); + + BitmapProvider* m_provider; + + wxDECLARE_NO_COPY_CLASS(wxGtkImage); + wxGtkImage() wxMEMBER_DELETE; + ~wxGtkImage() wxMEMBER_DELETE; +}; + +#define WX_GTK_IMAGE(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, wxGtkImage::Type(), wxGtkImage) diff --git a/src/gtk/anybutton.cpp b/src/gtk/anybutton.cpp index 34908936a8..1b57953fb9 100644 --- a/src/gtk/anybutton.cpp +++ b/src/gtk/anybutton.cpp @@ -19,6 +19,7 @@ #include "wx/stockitem.h" #include "wx/gtk/private/wrapgtk.h" +#include "wx/gtk/private/image.h" // ---------------------------------------------------------------------------- // GTK callbacks @@ -191,7 +192,7 @@ void wxAnyButton::GTKDoShowBitmap(const wxBitmap& bitmap) wxCHECK_RET(GTK_IS_IMAGE(image), "must have image widget"); - gtk_image_set_from_pixbuf(GTK_IMAGE(image), bitmap.GetPixbuf()); + WX_GTK_IMAGE(image)->Set(bitmap); } wxBitmap wxAnyButton::DoGetBitmap(State which) const @@ -222,7 +223,7 @@ void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which) } else if ( !image && bitmap.IsOk() ) { - image = gtk_image_new(); + image = wxGtkImage::New(this); gtk_button_set_image(GTK_BUTTON(m_widget), image); // Setting the image recreates the label, so we need to diff --git a/src/gtk/button.cpp b/src/gtk/button.cpp index f97c90da2a..188b31d0a3 100644 --- a/src/gtk/button.cpp +++ b/src/gtk/button.cpp @@ -19,6 +19,7 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/list.h" +#include "wx/gtk/private/image.h" // ---------------------------------------------------------------------------- // GTK callbacks @@ -98,7 +99,7 @@ bool wxButton::Create(wxWindow *parent, { m_widget = gtk_button_new(); - GtkWidget *image = gtk_image_new(); + GtkWidget* image = wxGtkImage::New(this); gtk_widget_show(image); gtk_container_add(GTK_CONTAINER(m_widget), image); } diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index b8ed3c8f3d..0e8cabd13d 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -35,6 +35,7 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/event.h" #include "wx/gtk/private/gdkconv.h" +#include "wx/gtk/private/image.h" #include "wx/gtk/private/list.h" #include "wx/gtk/private/treeview.h" using namespace wxGTKImpl; @@ -3202,7 +3203,7 @@ void wxDataViewColumn::Init(wxAlignment align, int flags, int width) GtkWidget* box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1); gtk_widget_show( box ); // gtk_container_set_border_width((GtkContainer*)box, 2); - m_image = gtk_image_new(); + m_image = wxGtkImage::New(); gtk_box_pack_start(GTK_BOX(box), m_image, FALSE, FALSE, 1); m_label = gtk_label_new(""); gtk_box_pack_end( GTK_BOX(box), GTK_WIDGET(m_label), FALSE, FALSE, 1 ); @@ -3273,9 +3274,7 @@ void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap ) if (bitmap.IsOk()) { - GtkImage *gtk_image = GTK_IMAGE(m_image); - - gtk_image_set_from_pixbuf(GTK_IMAGE(gtk_image), bitmap.GetPixbuf()); + WX_GTK_IMAGE(m_image)->Set(bitmap); gtk_widget_show( m_image ); } else diff --git a/src/gtk/image_gtk.cpp b/src/gtk/image_gtk.cpp new file mode 100644 index 0000000000..348637df82 --- /dev/null +++ b/src/gtk/image_gtk.cpp @@ -0,0 +1,169 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/gtk/image_gtk.cpp +// Author: Paul Cornett +// Copyright: (c) 2020 Paul Cornett +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#include "wx/wxprec.h" + +#include "wx/bitmap.h" +#include "wx/window.h" + +#include "wx/gtk/private/wrapgtk.h" +#include "wx/gtk/private/image.h" + +namespace +{ +// Default provider for HiDPI common case +struct BitmapProviderDefault: wxGtkImage::BitmapProvider +{ +#ifdef __WXGTK3__ + BitmapProviderDefault(wxWindow* win) : m_win(win) { } + virtual wxBitmap Get() const wxOVERRIDE; + virtual void Set(const wxBitmap& bitmap) wxOVERRIDE; + wxWindow* const m_win; + wxBitmap m_bitmap; + wxBitmap m_bitmapDisabled; +#else + BitmapProviderDefault(wxWindow*) { } + virtual wxBitmap Get() const wxOVERRIDE { return wxBitmap(); } +#endif +}; + +#ifdef __WXGTK3__ +wxBitmap BitmapProviderDefault::Get() const +{ + return (m_win == NULL || m_win->IsEnabled()) ? m_bitmap : m_bitmapDisabled; +} + +void BitmapProviderDefault::Set(const wxBitmap& bitmap) +{ + m_bitmap.UnRef(); + m_bitmapDisabled.UnRef(); + if (bitmap.IsOk() && bitmap.GetScaleFactor() > 1) + { + m_bitmap = bitmap; + if (m_win) + m_bitmapDisabled = bitmap.CreateDisabled(); + } +} +#endif // __WXGTK3__ +} // namespace + +extern "C" { +static void wxGtkImageClassInit(void* g_class, void* class_data); +} + +GType wxGtkImage::Type() +{ + static GType type; + if (type == 0) + { + const GTypeInfo info = { + sizeof(GtkImageClass), + NULL, NULL, + wxGtkImageClassInit, NULL, NULL, + sizeof(wxGtkImage), 0, NULL, + NULL + }; + type = g_type_register_static( + GTK_TYPE_IMAGE, "wxGtkImage", &info, GTypeFlags(0)); + } + return type; +} + +GtkWidget* wxGtkImage::New(BitmapProvider* provider) +{ + wxGtkImage* image = WX_GTK_IMAGE(g_object_new(Type(), NULL)); + image->m_provider = provider; + return GTK_WIDGET(image); +} + +GtkWidget* wxGtkImage::New(wxWindow* win) +{ + return New(new BitmapProviderDefault(win)); +} + +void wxGtkImage::Set(const wxBitmap& bitmap) +{ + m_provider->Set(bitmap); + + GdkPixbuf* pixbuf = NULL; + GdkPixbuf* pixbufNew = NULL; + if (bitmap.IsOk()) + { + if (bitmap.GetScaleFactor() <= 1) + pixbuf = bitmap.GetPixbuf(); + else + { + // Placeholder pixbuf for correct size + pixbufNew = + pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, + int(bitmap.GetScaledWidth()), int(bitmap.GetScaledHeight())); + } + } + gtk_image_set_from_pixbuf(GTK_IMAGE(this), pixbuf); + if (pixbufNew) + g_object_unref(pixbufNew); +} + +static GtkWidgetClass* wxGtkImageParentClass; + +extern "C" +{ +#ifdef __WXGTK3__ +static gboolean wxGtkImageDraw(GtkWidget* widget, cairo_t* cr) +#else +static gboolean wxGtkImageDraw(GtkWidget* widget, GdkEventExpose* event) +#endif +{ + wxGtkImage* image = WX_GTK_IMAGE(widget); + const wxBitmap bitmap(image->m_provider->Get()); + if (!bitmap.IsOk()) + { +#ifdef __WXGTK3__ + return wxGtkImageParentClass->draw(widget, cr); +#else + return wxGtkImageParentClass->expose_event(widget, event); +#endif + } + + GtkAllocation alloc; + gtk_widget_get_allocation(widget, &alloc); + int x = (alloc.width - int(bitmap.GetScaledWidth() )) / 2; + int y = (alloc.height - int(bitmap.GetScaledHeight())) / 2; +#ifdef __WXGTK3__ + gtk_render_background(gtk_widget_get_style_context(widget), + cr, 0, 0, alloc.width, alloc.height); + bitmap.Draw(cr, x, y); +#else + x += alloc.x; + y += alloc.y; + gdk_draw_pixbuf( + gtk_widget_get_window(widget), gtk_widget_get_style(widget)->black_gc, bitmap.GetPixbuf(), + 0, 0, x, y, + -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); +#endif + return false; +} + +static void wxGtkImageFinalize(GObject* object) +{ + wxGtkImage* image = WX_GTK_IMAGE(object); + delete image->m_provider; + image->m_provider = NULL; + G_OBJECT_CLASS(wxGtkImageParentClass)->finalize(object); +} + +static void wxGtkImageClassInit(void* g_class, void* /*class_data*/) +{ +#ifdef __WXGTK3__ + GTK_WIDGET_CLASS(g_class)->draw = wxGtkImageDraw; +#else + GTK_WIDGET_CLASS(g_class)->expose_event = wxGtkImageDraw; +#endif + G_OBJECT_CLASS(g_class)->finalize = wxGtkImageFinalize; + wxGtkImageParentClass = GTK_WIDGET_CLASS(g_type_class_peek_parent(g_class)); +} +} // extern "C" diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index 7fa4a4eee9..8b21013b7d 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -26,6 +26,7 @@ #include "wx/stockitem.h" #include "wx/gtk/private.h" +#include "wx/gtk/private/image.h" #include "wx/gtk/private/mnemonics.h" // Number of currently open modal dialogs, defined in src/gtk/toplevel.cpp. @@ -911,9 +912,8 @@ void wxMenu::GtkAppend(wxMenuItem* mitem, int pos) const wxBitmap& bitmap = mitem->GetBitmap(); if (bitmap.IsOk()) { - // always use pixbuf, because pixmap mask does not - // work with disabled images in some themes - GtkWidget* image = gtk_image_new_from_pixbuf(bitmap.GetPixbuf()); + GtkWidget* image = wxGtkImage::New(); + WX_GTK_IMAGE(image)->Set(bitmap); menuItem = gtk_image_menu_item_new_with_label(""); gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuItem), image); diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp index e70fd01e4e..218e26279f 100644 --- a/src/gtk/notebook.cpp +++ b/src/gtk/notebook.cpp @@ -25,6 +25,7 @@ #include "wx/fontutil.h" #include "wx/gtk/private.h" +#include "wx/gtk/private/image.h" #include "wx/gtk/private/stylecontext.h" //----------------------------------------------------------------------------- @@ -285,23 +286,18 @@ bool wxNotebook::SetPageImage( size_t page, int image ) if (image >= 0) { wxCHECK_MSG(HasImageList(), false, "invalid notebook imagelist"); - const wxBitmap bitmap = GetImageList()->GetBitmap(image); - if (pageData->m_image) + if (pageData->m_image == NULL) { - gtk_image_set_from_pixbuf( - GTK_IMAGE(pageData->m_image), bitmap.GetPixbuf()); - } - else - { - pageData->m_image = gtk_image_new_from_pixbuf(bitmap.GetPixbuf()); + pageData->m_image = wxGtkImage::New(); gtk_widget_show(pageData->m_image); gtk_box_pack_start(GTK_BOX(pageData->m_box), pageData->m_image, false, false, m_padding); } + WX_GTK_IMAGE(pageData->m_image)->Set(GetImageList()->GetBitmap(image)); } else if (pageData->m_image) { - gtk_widget_destroy(pageData->m_image); + gtk_container_remove(GTK_CONTAINER(pageData->m_box), pageData->m_image); pageData->m_image = NULL; } pageData->m_imageIndex = image; @@ -491,7 +487,8 @@ bool wxNotebook::InsertPage( size_t position, if (HasImageList()) { const wxBitmap bitmap = GetImageList()->GetBitmap(imageId); - pageData->m_image = gtk_image_new_from_pixbuf(bitmap.GetPixbuf()); + pageData->m_image = wxGtkImage::New(); + WX_GTK_IMAGE(pageData->m_image)->Set(bitmap); gtk_box_pack_start(GTK_BOX(pageData->m_box), pageData->m_image, false, false, m_padding); } diff --git a/src/gtk/statbmp.cpp b/src/gtk/statbmp.cpp index e137f10f49..6ab16b6a41 100644 --- a/src/gtk/statbmp.cpp +++ b/src/gtk/statbmp.cpp @@ -14,29 +14,7 @@ #include "wx/statbmp.h" #include "wx/gtk/private/wrapgtk.h" - -#ifdef __WXGTK3__ -extern "C" { -static gboolean image_draw(GtkWidget* widget, cairo_t* cr, wxStaticBitmap* win) -{ - wxBitmap bitmap(win->GetBitmap()); - if (!bitmap.IsOk() || bitmap.GetScaleFactor() <= 1) - return false; - - GtkAllocation alloc; - gtk_widget_get_allocation(widget, &alloc); - gtk_render_background(gtk_widget_get_style_context(widget), - cr, 0, 0, alloc.width, alloc.height); - const wxSize size(bitmap.GetScaledSize()); - int x = (alloc.width - size.x) / 2; - int y = (alloc.height - size.y) / 2; - if (!win->IsEnabled()) - bitmap = bitmap.CreateDisabled(); - bitmap.Draw(cr, x, y); - return true; -} -} -#endif +#include "wx/gtk/private/image.h" //----------------------------------------------------------------------------- // wxStaticBitmap @@ -64,7 +42,7 @@ bool wxStaticBitmap::Create( wxWindow *parent, wxWindowID id, const wxBitmap &bi return false; } - m_widget = gtk_image_new(); + m_widget = wxGtkImage::New(this); g_object_ref(m_widget); if (bitmap.IsOk()) @@ -72,9 +50,6 @@ bool wxStaticBitmap::Create( wxWindow *parent, wxWindowID id, const wxBitmap &bi PostCreation(size); m_parent->DoAddChild( this ); -#ifdef __WXGTK3__ - g_signal_connect(m_widget, "draw", G_CALLBACK(image_draw), this); -#endif return true; } @@ -82,30 +57,7 @@ bool wxStaticBitmap::Create( wxWindow *parent, wxWindowID id, const wxBitmap &bi void wxStaticBitmap::SetBitmap( const wxBitmap &bitmap ) { m_bitmap = bitmap; - - // always use pixbuf, because pixmap mask does not - // work with disabled images in some themes - if (m_bitmap.IsOk()) - { -#ifdef __WXGTK3__ - if (bitmap.GetScaleFactor() > 1) - { - // Use a placeholder pixbuf with the correct size. - // The original will be used by our "draw" signal handler. - const wxSize size(bitmap.GetScaledSize()); - GdkPixbuf* pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, size.x, size.y); - gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget), pixbuf); - g_object_unref(pixbuf); - } - else -#endif - { - gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget), m_bitmap.GetPixbuf()); - } - } - else - gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget), NULL); + WX_GTK_IMAGE(m_widget)->Set(bitmap); InvalidateBestSize(); SetSize(GetBestSize()); diff --git a/src/gtk/tglbtn.cpp b/src/gtk/tglbtn.cpp index f386dfc9a6..ed17ae5129 100644 --- a/src/gtk/tglbtn.cpp +++ b/src/gtk/tglbtn.cpp @@ -22,6 +22,7 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/eventsdisabler.h" +#include "wx/gtk/private/image.h" #include "wx/gtk/private/list.h" extern bool g_blockEventsOnDrag; @@ -103,7 +104,7 @@ bool wxToggleButton::Create(wxWindow *parent, wxWindowID id, { m_widget = gtk_toggle_button_new(); - GtkWidget *image = gtk_image_new(); + GtkWidget* image = wxGtkImage::New(this); gtk_widget_show(image); gtk_container_add(GTK_CONTAINER(m_widget), image); } diff --git a/src/gtk/toolbar.cpp b/src/gtk/toolbar.cpp index f58958f8ce..99be10ff57 100644 --- a/src/gtk/toolbar.cpp +++ b/src/gtk/toolbar.cpp @@ -15,6 +15,7 @@ #include "wx/toolbar.h" #include "wx/gtk/private.h" +#include "wx/gtk/private/image.h" #include "wx/gtk/private/gtk3-compat.h" // ---------------------------------------------------------------------------- @@ -168,23 +169,29 @@ enter_notify_event(GtkWidget*, GdkEventCrossing* event, wxToolBarTool* tool) } } -//----------------------------------------------------------------------------- -// "expose_event" from GtkImage inside m_item //----------------------------------------------------------------------------- -extern "C" { -static gboolean -#ifdef __WXGTK3__ -image_draw(GtkWidget* widget, cairo_t* cr, wxToolBarTool* tool) -#else -image_expose_event(GtkWidget* widget, GdkEventExpose*, wxToolBarTool* tool) -#endif +namespace +{ +struct BitmapProvider: wxGtkImage::BitmapProvider +{ + BitmapProvider(wxToolBarTool* tool) : m_tool(tool) { } + virtual wxBitmap Get() const wxOVERRIDE; + wxToolBarTool* const m_tool; +}; + +wxBitmap BitmapProvider::Get() const { #ifdef __WXGTK3__ - wxBitmap bitmap(tool->GetNormalBitmap()); - if (!tool->IsEnabled()) + wxBitmap bitmap(m_tool->GetNormalBitmap()); + if (m_tool->IsEnabled()) { - wxBitmap disabled(tool->GetDisabledBitmap()); + if (bitmap.IsOk() && bitmap.GetScaleFactor() <= 1) + bitmap.UnRef(); + } + else + { + wxBitmap disabled(m_tool->GetDisabledBitmap()); // if no disabled bitmap and normal bitmap is scaled if (!disabled.IsOk() && bitmap.IsOk() && bitmap.GetScaleFactor() > 1) { @@ -193,33 +200,14 @@ image_expose_event(GtkWidget* widget, GdkEventExpose*, wxToolBarTool* tool) } bitmap = disabled; } - if (!bitmap.IsOk() || (tool->IsEnabled() && bitmap.GetScaleFactor() <= 1)) - return false; #else - const wxBitmap& bitmap = tool->GetDisabledBitmap(); - if (tool->IsEnabled() || !bitmap.IsOk()) - return false; + wxBitmap bitmap; + if (!m_tool->IsEnabled()) + bitmap = m_tool->GetDisabledBitmap(); #endif - - GtkAllocation alloc; - gtk_widget_get_allocation(widget, &alloc); - int x = (alloc.width - bitmap.GetScaledWidth()) / 2; - int y = (alloc.height - bitmap.GetScaledHeight()) / 2; -#ifdef __WXGTK3__ - gtk_render_background(gtk_widget_get_style_context(widget), - cr, 0, 0, alloc.width, alloc.height); - bitmap.Draw(cr, x, y); -#else - x += alloc.x; - y += alloc.y; - gdk_draw_pixbuf( - gtk_widget_get_window(widget), gtk_widget_get_style(widget)->black_gc, bitmap.GetPixbuf(), - 0, 0, x, y, - -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); -#endif - return true; -} + return bitmap; } +} // namespace //----------------------------------------------------------------------------- // "toggled" from dropdown menu button @@ -281,26 +269,9 @@ void wxToolBar::AddChildGTK(wxWindowGTK* child) void wxToolBarTool::SetImage() { const wxBitmap& bitmap = GetNormalBitmap(); - wxCHECK_RET(bitmap.IsOk(), "invalid bitmap for wxToolBar icon"); GtkWidget* image = gtk_tool_button_get_icon_widget(GTK_TOOL_BUTTON(m_item)); -#ifdef __WXGTK3__ - if (bitmap.GetScaleFactor() > 1) - { - // Use a placeholder pixbuf with the correct size. - // The original will be used by our "draw" signal handler. - GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, - bitmap.GetScaledWidth(), bitmap.GetScaledHeight()); - gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); - g_object_unref(pixbuf); - } - else -#endif - { - // always use pixbuf, because pixmap mask does not - // work with disabled images in some themes - gtk_image_set_from_pixbuf(GTK_IMAGE(image), bitmap.GetPixbuf()); - } + WX_GTK_IMAGE(image)->Set(bitmap); } // helper to create a dropdown menu item @@ -611,18 +582,11 @@ bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase) } if (!HasFlag(wxTB_NOICONS)) { - GtkWidget* image = gtk_image_new(); + GtkWidget* image = wxGtkImage::New(new BitmapProvider(tool)); gtk_tool_button_set_icon_widget( GTK_TOOL_BUTTON(tool->m_item), image); tool->SetImage(); gtk_widget_show(image); -#ifdef __WXGTK3__ - g_signal_connect(image, "draw", - G_CALLBACK(image_draw), tool); -#else - g_signal_connect(image, "expose_event", - G_CALLBACK(image_expose_event), tool); -#endif } if (!tool->GetLabel().empty()) {