Initial commit for real hidpi support

Note: This commit has only been tested on MacOS

Changes:
- Icons now use the native hidpi support from Gtk (through Icon Theme)
- Icons are now directly generated from scalable file (i.e. SVG file)
- Widget sizes are scaled based on DPI and scale factor
- Font size is scaled based on DPI and scale factor
This commit is contained in:
Pandagrapher
2022-08-19 16:47:28 +02:00
parent 1e2dc30738
commit 89d2bdce5b
108 changed files with 1949 additions and 2032 deletions

View File

@@ -34,12 +34,9 @@
#include "filepanel.h"
#include "filmsimulation.h"
float fontScale = 1.f;
Glib::RefPtr<Gtk::CssProvider> cssForced;
Glib::RefPtr<Gtk::CssProvider> cssRT;
extern unsigned char initialGdkScale;
#if defined(__APPLE__)
static gboolean
osx_should_quit_cb (GtkosxApplication *app, gpointer data)
@@ -104,10 +101,6 @@ RTWindow::RTWindow ()
, epanel (nullptr)
, fpanel (nullptr)
{
if (options.is_new_version()) {
RTImage::cleanup(true);
}
cacheMgr->init ();
ProfilePanel::init (this);
@@ -116,9 +109,15 @@ RTWindow::RTWindow ()
Glib::RefPtr<Gdk::Screen> screen = Gdk::Screen::get_default();
if (screen) {
// Setting default theme and icon theme (bases for custom themes)
Gtk::Settings::get_for_screen (screen)->property_gtk_theme_name() = "Adwaita";
Gtk::Settings::get_for_screen (screen)->property_gtk_application_prefer_dark_theme() = true;
Gtk::Settings::get_for_screen (screen)->property_gtk_icon_theme_name() = "RawTherapee";
// Initialize RTScalable for Hi-DPI support
RTScalable::init(this);
// Look for theme and set it
Glib::RefPtr<Glib::Regex> regex = Glib::Regex::create (THEMEREGEXSTR, Glib::RegexCompileFlags::REGEX_CASELESS);
Glib::ustring filename;
Glib::MatchInfo mInfo;
@@ -169,63 +168,84 @@ RTWindow::RTWindow ()
// Set the font face and size
Glib::ustring css;
if (options.fontFamily != "default") {
//GTK318
#if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20
css = Glib::ustring::compose ("* { font-family: %1; font-size: %2px}", options.fontFamily, options.fontSize * (int)initialGdkScale);
#else
css = Glib::ustring::compose ("* { font-family: %1; font-size: %2pt}", options.fontFamily, options.fontSize * (int)initialGdkScale);
#endif
//GTK318
if (options.pseudoHiDPISupport) {
fontScale = options.fontSize / (float)RTScalable::baseFontSize;
}
#ifndef __APPLE__
const double fontScale = static_cast<double>(RTScalable::getDPI())
/ static_cast<double>(RTScalable::pangoDPI)
* RTScalable::getScale(); // Refer to notes in rtscalable.h
#else
// On MacOS, font is already scaled by the System library
// Refer to https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/quartz/gdkscreen-quartz.c
const double fontScale = 1.;
#endif
auto style = get_pango_context();
if (options.fontFamily != "default") { // Set font and size according to user choice
// Scale font size based on DPI and Scale
const int scaledFontSize = static_cast<int>(options.fontSize * fontScale + 0.5);
// Set font and size in css
css = Glib::ustring::compose ("* { font-family: %1; font-size: %2px}", options.fontFamily, scaledFontSize);
if (rtengine::settings->verbose) {
printf("\"Non-Default\" font size(%d) * scale(%d) / fontScale(%.3f)\n", options.fontSize, (int)initialGdkScale, static_cast<double>(fontScale));
printf("\"Non-Default\" font size in pt(%d) * scale(%.3f) = font size in px(%d)\n", options.fontSize, fontScale, scaledFontSize);
}
} else {
} else { // Set font and size according to default values
// Retrieve default style values
Glib::RefPtr<Gtk::StyleContext> style = Gtk::StyleContext::create();
Pango::FontDescription pfd = style->get_font(Gtk::STATE_FLAG_NORMAL);
if (pfd.get_set_fields() & Pango::FONT_MASK_SIZE) {
int pt;
int fontSize = pfd.get_size();
bool isPix = pfd.get_size_is_absolute();
int resolution = (int)style->get_screen()->get_resolution();
if (isPix) {
// HOMBRE: guessing here...
// if resolution is lower than baseHiDPI, we're supposing that it's already expressed in a scale==1 scenario
if (resolution >= int(RTScalable::baseHiDPI)) {
// converting the resolution to a scale==1 scenario
resolution /= 2;
}
// 1pt = 1/72in @ 96 ppi
// HOMBRE: If the font unit is px, is it already scaled up to match the resolution ?
// px >inch >pt >"scaled pt"
pt = (int)(double(fontSize) / RTScalable::baseDPI * 72. * (96. / (double)resolution) + 0.49);
} else {
pt = fontSize / Pango::SCALE;
}
if (options.pseudoHiDPISupport) {
fontScale = (float)pt / (float)RTScalable::baseFontSize;
}
if ((int)initialGdkScale > 1 || pt != RTScalable::baseFontSize) {
css = Glib::ustring::compose ("* { font-size: %1pt}", pt * (int)initialGdkScale);
const int fontSize = pfd.get_size();
const bool isAbsoluteFontSize = pfd.get_size_is_absolute();
int newFontSize;
if (isAbsoluteFontSize) {
// Absolute size is defined in "Pango units" and shall be divided by
// Pango::SCALE to get "px"
newFontSize = fontSize / Pango::SCALE;
// Guessing that pixel size is given for a 96 DPI reference:
#ifndef __APPLE__
const double newFontScale = static_cast<double>(RTScalable::getDPI())
/ static_cast<double>(RTScalable::pangoDPI)
* RTScalable::getScale(); // Refer to notes in rtscalable.h
#else
// On MacOS, font is already scaled by the System library
// Refer to https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/quartz/gdkscreen-quartz.c
const double newFontScale = 1.;
#endif
newFontSize = static_cast<int>(newFontSize * newFontScale + 0.5);
if (rtengine::settings->verbose) {
printf("\"Default\" font size(%d) * scale(%d) / fontScale(%.3f)\n", pt, (int)initialGdkScale, static_cast<double>(fontScale));
printf("\"Default\" absolute font size(%d)\n", newFontSize);
}
} else {
// Non-absolute size is defined in "pt" and shall be converted to "px"
newFontSize = static_cast<int>(fontSize * fontScale + 0.5);
if (rtengine::settings->verbose) {
printf("\"Default\" non-absolute font size in pt(%d) * scale(%.3f) = font size in px(%d)\n", fontSize, fontScale, newFontSize);
}
}
// Set font and size in css
css = Glib::ustring::compose ("* { font-size: %1px}", newFontSize);
printf("newFontSize: %d\n", newFontSize);
}
}
// Load custom CSS for font
if (!css.empty()) {
if (rtengine::settings->verbose) {
printf("CSS:\n%s\n\n", css.c_str());
}
try {
cssForced = Gtk::CssProvider::create();
cssForced->load_from_data (css);
Gtk::StyleContext::add_provider_for_screen (screen, cssForced, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
} catch (Glib::Error &err) {
printf ("Error: \"%s\"\n", err.what().c_str());
} catch (...) {
@@ -236,22 +256,10 @@ RTWindow::RTWindow ()
// ------- end loading theme files
RTScalable::init(this);
RTSurface::init();
RTImage::init();
WhiteBalance::init();
MyExpander::init();
// For UNIX system, set app icon
#ifndef WIN32
const std::vector<Glib::RefPtr<Gdk::Pixbuf>> appIcons = {
RTImage::createPixbufFromFile("rawtherapee-logo-16.png"),
RTImage::createPixbufFromFile("rawtherapee-logo-24.png"),
RTImage::createPixbufFromFile("rawtherapee-logo-48.png"),
RTImage::createPixbufFromFile("rawtherapee-logo-128.png"),
RTImage::createPixbufFromFile("rawtherapee-logo-256.png")
};
try {
set_default_icon_list(appIcons);
set_default_icon_name("rawtherapee");
} catch (Glib::Exception& ex) {
printf ("%s\n", ex.what().c_str());
}
@@ -324,11 +332,11 @@ RTWindow::RTWindow ()
if (options.mainNBVertical) {
mainNB->set_tab_pos (Gtk::POS_LEFT);
fpl->set_angle (90);
RTImage* folderIcon = Gtk::manage (new RTImage ("folder-closed.png"));
RTImage* folderIcon = Gtk::manage (new RTImage ("folder-closed", Gtk::ICON_SIZE_LARGE_TOOLBAR));
fpanelLabelGrid->attach_next_to (*folderIcon, Gtk::POS_TOP, 1, 1);
fpanelLabelGrid->attach_next_to (*fpl, Gtk::POS_TOP, 1, 1);
} else {
RTImage* folderIcon = Gtk::manage (new RTImage ("folder-closed.png"));
RTImage* folderIcon = Gtk::manage (new RTImage ("folder-closed", Gtk::ICON_SIZE_LARGE_TOOLBAR));
fpanelLabelGrid->attach_next_to (*folderIcon, Gtk::POS_RIGHT, 1, 1);
fpanelLabelGrid->attach_next_to (*fpl, Gtk::POS_RIGHT, 1, 1);
}
@@ -361,27 +369,27 @@ RTWindow::RTWindow ()
//mainBox->pack_start (*mainNB);
// filling bottom box
iFullscreen = new RTImage ("fullscreen-enter.png");
iFullscreen_exit = new RTImage ("fullscreen-leave.png");
iFullscreen = new RTImage ("fullscreen-enter", Gtk::ICON_SIZE_LARGE_TOOLBAR);
iFullscreen_exit = new RTImage ("fullscreen-leave", Gtk::ICON_SIZE_LARGE_TOOLBAR);
Gtk::Button* iccProfileCreator = Gtk::manage (new Gtk::Button ());
setExpandAlignProperties (iccProfileCreator, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
iccProfileCreator->set_relief(Gtk::RELIEF_NONE);
iccProfileCreator->set_image (*Gtk::manage (new RTImage ("gamut-plus.png")));
iccProfileCreator->set_image (*Gtk::manage (new RTImage ("gamut-plus", Gtk::ICON_SIZE_LARGE_TOOLBAR)));
iccProfileCreator->set_tooltip_markup (M ("MAIN_BUTTON_ICCPROFCREATOR"));
iccProfileCreator->signal_clicked().connect ( sigc::mem_fun (*this, &RTWindow::showICCProfileCreator) );
Gtk::Button* helpBtn = Gtk::manage (new Gtk::Button ());
setExpandAlignProperties (helpBtn, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
helpBtn->set_relief(Gtk::RELIEF_NONE);
helpBtn->set_image (*Gtk::manage (new RTImage ("questionmark.png")));
helpBtn->set_image (*Gtk::manage (new RTImage("questionmark", Gtk::ICON_SIZE_LARGE_TOOLBAR)));
helpBtn->set_tooltip_markup (M ("GENERAL_HELP"));
helpBtn->signal_clicked().connect (sigc::mem_fun (*this, &RTWindow::showRawPedia));
Gtk::Button* preferences = Gtk::manage (new Gtk::Button ());
setExpandAlignProperties (preferences, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
preferences->set_relief(Gtk::RELIEF_NONE);
preferences->set_image (*Gtk::manage (new RTImage ("preferences.png")));
preferences->set_image (*Gtk::manage (new RTImage ("preferences", Gtk::ICON_SIZE_LARGE_TOOLBAR)));
preferences->set_tooltip_markup (M ("MAIN_BUTTON_PREFERENCES"));
preferences->signal_clicked().connect ( sigc::mem_fun (*this, &RTWindow::showPreferences) );
@@ -454,7 +462,6 @@ RTWindow::~RTWindow()
delete fpanel;
delete iFullscreen;
delete iFullscreen_exit;
RTImage::cleanup();
}
void RTWindow::on_realize ()
@@ -529,8 +536,8 @@ bool RTWindow::on_configure_event (GdkEventConfigure* event)
get_position (options.windowX, options.windowY);
}
RTImage::setDPInScale(RTScalable::getDPI(), RTScalable::getScale()); // will update the RTImage on scale/resolution change
RTSurface::setDPInScale(RTScalable::getDPI(), RTScalable::getScale()); // will update the RTSurface on scale/resolution change
// With update the RTScalable on scale or resolution change
RTScalable::setDPInScale(this);
return Gtk::Widget::on_configure_event (event);
}
@@ -541,7 +548,7 @@ bool RTWindow::on_window_state_event (GdkEventWindowState* event)
options.windowMaximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
is_minimized = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED;
is_fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
return Gtk::Widget::on_window_state_event (event);
}
@@ -592,7 +599,7 @@ void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name)
// construct closeable tab for the image
Gtk::Grid* titleGrid = Gtk::manage (new Gtk::Grid ());
titleGrid->set_tooltip_markup (name);
RTImage *closebimg = Gtk::manage (new RTImage ("cancel-small.png"));
RTImage *closebimg = Gtk::manage (new RTImage ("cancel-small", Gtk::ICON_SIZE_LARGE_TOOLBAR));
Gtk::Button* closeb = Gtk::manage (new Gtk::Button ());
closeb->set_name ("CloseButton");
closeb->add (*closebimg);
@@ -601,7 +608,7 @@ void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name)
closeb->signal_clicked().connect ( sigc::bind (sigc::mem_fun (*this, &RTWindow::remEditorPanel), ep));
if (!EditWindow::isMultiDisplayEnabled()) {
titleGrid->attach_next_to (*Gtk::manage (new RTImage ("aperture.png")), Gtk::POS_RIGHT, 1, 1);
titleGrid->attach_next_to (*Gtk::manage (new RTImage ("aperture", Gtk::ICON_SIZE_LARGE_TOOLBAR)), Gtk::POS_RIGHT, 1, 1);
}
titleGrid->attach_next_to (*Gtk::manage (new Gtk::Label (Glib::path_get_basename (name))), Gtk::POS_RIGHT, 1, 1);
titleGrid->attach_next_to (*closeb, Gtk::POS_RIGHT, 1, 1);
@@ -855,12 +862,8 @@ bool RTWindow::on_delete_event (GdkEventAny* event)
}
cacheMgr->closeCache (); // also makes cleanup if too large
WhiteBalance::cleanup();
ProfilePanel::cleanup();
ClutComboBox::cleanup();
MyExpander::cleanup();
mainWindowCursorManager.cleanup();
editWindowCursorManager.cleanup();
BatchQueueEntry::savedAsIcon.reset();
FileBrowserEntry::editedIcon.reset();
FileBrowserEntry::recentlySavedIcon.reset();
@@ -997,7 +1000,7 @@ void RTWindow::error(const Glib::ustring& descr)
void RTWindow::toggle_fullscreen ()
{
onConfEventConn.block(true); // Avoid getting size and position while window is getting fullscreen
if (is_fullscreen) {
unfullscreen();
@@ -1013,7 +1016,7 @@ void RTWindow::toggle_fullscreen ()
btn_fullscreen->set_image (*iFullscreen_exit);
}
}
onConfEventConn.block(false);
}
@@ -1121,7 +1124,7 @@ bool RTWindow::splashClosed (GdkEventAny* event)
void RTWindow::setWindowSize ()
{
onConfEventConn.block(true); // Avoid getting size and position while window is being moved, maximized, ...
Gdk::Rectangle lMonitorRect;
const auto display = get_screen()->get_display();
display->get_monitor (std::min (options.windowMonitor, display->get_n_monitors() - 1))->get_geometry(lMonitorRect);
@@ -1160,7 +1163,7 @@ void RTWindow::setWindowSize ()
unmaximize();
resize (options.windowWidth, options.windowHeight);
}
onConfEventConn.block(false);
}
@@ -1168,7 +1171,7 @@ void RTWindow::get_position(int& x, int& y) const
{
// Call native function
Gtk::Window::get_position (x, y);
// Retrieve display (concatenation of all monitors) size
int width = 0, height = 0;
const auto display = get_screen()->get_display();
@@ -1253,7 +1256,7 @@ void RTWindow::createSetmEditor()
el->set_angle (90);
}
editorLabelGrid->attach_next_to (*Gtk::manage (new RTImage ("aperture.png")), pos, 1, 1);
editorLabelGrid->attach_next_to (*Gtk::manage (new RTImage ("aperture", Gtk::ICON_SIZE_LARGE_TOOLBAR)), pos, 1, 1);
editorLabelGrid->attach_next_to (*el, pos, 1, 1);
editorLabelGrid->set_tooltip_markup (M ("MAIN_FRAME_EDITOR_TOOLTIP"));