Merge pull request #1898 from Technius/cursor-highlight

Add options to customize cursor highlight color and radius
presentation
Bryan Tan 6 years ago committed by GitHub
commit 3acdd07259
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 60
      src/control/settings/Settings.cpp
  2. 36
      src/control/settings/Settings.h
  3. 12
      src/gui/XournalppCursor.cpp
  4. 21
      src/gui/dialog/SettingsDialog.cpp
  5. 13
      src/util/Util.cpp
  6. 1
      src/util/Util.h
  7. 229
      ui/settings.glade

@ -16,6 +16,7 @@
#define WRITE_BOOL_PROP(var) xmlNode = saveProperty((const char*)#var, (var) ? "true" : "false", root)
#define WRITE_STRING_PROP(var) xmlNode = saveProperty((const char*)#var, (var).empty() ? "" : (var).c_str(), root)
#define WRITE_INT_PROP(var) xmlNode = saveProperty((const char*)#var, var, root)
#define WRITE_UINT_PROP(var) xmlNode = savePropertyUnsigned((const char*)#var, var, root)
#define WRITE_DOUBLE_PROP(var) xmlNode = savePropertyDouble((const char*)#var, var, root)
#define WRITE_COMMENT(var) \
com = xmlNewComment((const xmlChar*)(var)); \
@ -72,6 +73,10 @@ void Settings::loadDefault() {
this->autoloadPdfXoj = true;
this->showBigCursor = false;
this->highlightPosition = false;
this->cursorHighlightColor = 0x80FFFF00; // Yellow with 50% opacity
this->cursorHighlightRadius = 30.0;
this->cursorHighlightBorderColor = 0x800000FF; // Blue with 50% opacity
this->cursorHighlightBorderWidth = 0.0;
this->darkTheme = false;
this->scrollbarHideType = SCROLLBAR_HIDE_NONE;
this->disableScrollbarFadeout = false;
@ -332,6 +337,14 @@ void Settings::parseItem(xmlDocPtr doc, xmlNodePtr cur) {
this->showBigCursor = xmlStrcmp(value, reinterpret_cast<const xmlChar*>("true")) == 0;
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("highlightPosition")) == 0) {
this->highlightPosition = xmlStrcmp(value, reinterpret_cast<const xmlChar*>("true")) == 0;
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("cursorHighlightColor")) == 0) {
this->cursorHighlightColor = g_ascii_strtoull(reinterpret_cast<const char*>(value), nullptr, 10);
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("cursorHighlightRadius")) == 0) {
this->cursorHighlightRadius = g_ascii_strtod(reinterpret_cast<const char*>(value), nullptr);
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("cursorHighlightBorderColor")) == 0) {
this->cursorHighlightBorderColor = g_ascii_strtoull(reinterpret_cast<const char*>(value), nullptr, 10);
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("cursorHighlightBorderWidth")) == 0) {
this->cursorHighlightBorderWidth = g_ascii_strtod(reinterpret_cast<const char*>(value), nullptr);
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("darkTheme")) == 0) {
this->darkTheme = xmlStrcmp(value, reinterpret_cast<const xmlChar*>("true")) == 0;
} else if (xmlStrcmp(name, reinterpret_cast<const xmlChar*>("defaultSaveName")) == 0) {
@ -570,6 +583,13 @@ auto Settings::saveProperty(const gchar* key, int value, xmlNodePtr parent) -> x
return xmlNode;
}
auto Settings::savePropertyUnsigned(const gchar* key, unsigned int value, xmlNodePtr parent) -> xmlNodePtr {
char* text = g_strdup_printf("%u", value);
xmlNodePtr xmlNode = saveProperty(key, text, parent);
g_free(text);
return xmlNode;
}
auto Settings::saveProperty(const gchar* key, const gchar* value, xmlNodePtr parent) -> xmlNodePtr {
xmlNodePtr xmlNode = xmlNewChild(parent, nullptr, reinterpret_cast<const xmlChar*>("property"), nullptr);
@ -710,6 +730,10 @@ void Settings::save() {
WRITE_BOOL_PROP(showBigCursor);
WRITE_BOOL_PROP(highlightPosition);
WRITE_UINT_PROP(cursorHighlightColor);
WRITE_UINT_PROP(cursorHighlightBorderColor);
WRITE_DOUBLE_PROP(cursorHighlightRadius);
WRITE_DOUBLE_PROP(cursorHighlightBorderWidth);
WRITE_BOOL_PROP(darkTheme);
WRITE_BOOL_PROP(disableScrollbarFadeout);
@ -1003,6 +1027,42 @@ void Settings::setHighlightPosition(bool highlight) {
save();
}
auto Settings::getCursorHighlightColor() const -> uint32_t { return this->cursorHighlightColor; }
void Settings::setCursorHighlightColor(uint32_t color) {
if (this->cursorHighlightColor != color) {
this->cursorHighlightColor = color;
save();
}
}
auto Settings::getCursorHighlightRadius() const -> double { return this->cursorHighlightRadius; }
void Settings::setCursorHighlightRadius(double radius) {
if (this->cursorHighlightRadius != radius) {
this->cursorHighlightRadius = radius;
save();
}
}
auto Settings::getCursorHighlightBorderColor() const -> uint32_t { return this->cursorHighlightBorderColor; }
void Settings::setCursorHighlightBorderColor(uint32_t color) {
if (this->cursorHighlightBorderColor != color) {
this->cursorHighlightBorderColor = color;
save();
}
}
auto Settings::getCursorHighlightBorderWidth() const -> double { return this->cursorHighlightBorderWidth; }
void Settings::setCursorHighlightBorderWidth(double radius) {
if (this->cursorHighlightBorderWidth != radius) {
this->cursorHighlightBorderWidth = radius;
save();
}
}
auto Settings::isSnapRotation() const -> bool { return this->snapRotation; }
void Settings::setSnapRotation(bool b) {

@ -130,6 +130,7 @@ private:
static xmlNodePtr savePropertyDouble(const gchar* key, double value, xmlNodePtr parent);
static xmlNodePtr saveProperty(const gchar* key, int value, xmlNodePtr parent);
static xmlNodePtr savePropertyUnsigned(const gchar* key, unsigned int value, xmlNodePtr parent);
static xmlNodePtr saveProperty(const gchar* key, const gchar* value, xmlNodePtr parent);
void saveData(xmlNodePtr root, const string& name, SElement& elem);
@ -290,6 +291,18 @@ public:
bool isHighlightPosition() const;
void setHighlightPosition(bool highlight);
uint32_t getCursorHighlightColor() const;
void setCursorHighlightColor(uint32_t color);
double getCursorHighlightRadius() const;
void setCursorHighlightRadius(double radius);
uint32_t getCursorHighlightBorderColor() const;
void setCursorHighlightBorderColor(uint32_t color);
double getCursorHighlightBorderWidth() const;
void setCursorHighlightBorderWidth(double width);
ScrollbarHideType getScrollbarHideType() const;
void setScrollbarHideType(ScrollbarHideType type);
@ -496,10 +509,31 @@ private:
bool showBigCursor{};
/**
* Show a yellow circle around the cursor
* Show a colored circle around the cursor
*/
bool highlightPosition{};
/**
* Cursor highlight color (ARGB format)
*/
uint32_t cursorHighlightColor{};
/**
* Radius of cursor highlight circle. Note that this is limited by the size
* of the cursor in the display server (default is probably 30 pixels).
*/
double cursorHighlightRadius{};
/**
* Cursor highlight border color (ARGB format)
*/
uint32_t cursorHighlightBorderColor{};
/**
* Width of cursor highlight border, in pixels.
*/
double cursorHighlightBorderWidth{};
/**
* If the user uses a dark-themed DE, he should enable this
* (white icons)

@ -410,12 +410,14 @@ auto XournalppCursor::createHighlighterOrPenCursor(int size, double alpha) -> Gd
}
if (bright) {
// A yellow transparent circle with no border
cairo_set_line_width(cr, 0);
cairo_set_source_rgba(cr, 255, 255, 0, 0.5);
cairo_arc(cr, centerX, centerY, 30, 0, 2 * 3.1415);
// Highlight cursor with a circle
auto&& color = Util::argb_to_GdkRGBA(control->getSettings()->getCursorHighlightColor());
cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha);
cairo_arc(cr, centerX, centerY, control->getSettings()->getCursorHighlightRadius(), 0, 2 * 3.1415);
cairo_fill_preserve(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
auto&& borderColor = Util::argb_to_GdkRGBA(control->getSettings()->getCursorHighlightBorderColor());
cairo_set_source_rgba(cr, borderColor.red, borderColor.green, borderColor.blue, borderColor.alpha);
cairo_set_line_width(cr, control->getSettings()->getCursorHighlightBorderWidth());
cairo_stroke(cr);
}

@ -196,7 +196,6 @@ void SettingsDialog::load() {
loadCheckbox("cbDoActionOnStrokeFiltered", settings->getDoActionOnStrokeFiltered());
loadCheckbox("cbTrySelectOnStrokeFiltered", settings->getTrySelectOnStrokeFiltered());
loadCheckbox("cbBigCursor", settings->isShowBigCursor());
loadCheckbox("cbHighlightPosition", settings->isHighlightPosition());
loadCheckbox("cbDarkTheme", settings->isDarkTheme());
loadCheckbox("cbHideHorizontalScrollbar", settings->getScrollbarHideType() & SCROLLBAR_HIDE_HORIZONTAL);
loadCheckbox("cbHideVerticalScrollbar", settings->getScrollbarHideType() & SCROLLBAR_HIDE_VERTICAL);
@ -266,6 +265,14 @@ void SettingsDialog::load() {
color = Util::rgb_to_GdkRGBA(settings->getSelectionColor());
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(get("colorSelection")), &color);
loadCheckbox("cbHighlightPosition", settings->isHighlightPosition());
color = Util::argb_to_GdkRGBA(settings->getCursorHighlightColor());
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(get("cursorHighlightColor")), &color);
color = Util::argb_to_GdkRGBA(settings->getCursorHighlightBorderColor());
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(get("cursorHighlightBorderColor")), &color);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(get("cursorHighlightRadius")), settings->getCursorHighlightRadius());
gtk_spin_button_set_value(GTK_SPIN_BUTTON(get("cursorHighlightBorderWidth")),
settings->getCursorHighlightBorderWidth());
bool hideFullscreenMenubar = false;
bool hideFullscreenSidebar = false;
@ -438,7 +445,6 @@ void SettingsDialog::save() {
settings->setDoActionOnStrokeFiltered(getCheckbox("cbDoActionOnStrokeFiltered"));
settings->setTrySelectOnStrokeFiltered(getCheckbox("cbTrySelectOnStrokeFiltered"));
settings->setShowBigCursor(getCheckbox("cbBigCursor"));
settings->setHighlightPosition(getCheckbox("cbHighlightPosition"));
settings->setDarkTheme(getCheckbox("cbDarkTheme"));
settings->setTouchWorkaround(getCheckbox("cbTouchWorkaround"));
settings->setExperimentalInputSystemEnabled(getCheckbox("cbNewInputSystem"));
@ -467,6 +473,17 @@ void SettingsDialog::save() {
settings->setSelectionColor(Util::gdkrgba_to_hex(color));
settings->setHighlightPosition(getCheckbox("cbHighlightPosition"));
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(get("cursorHighlightColor")), &color);
settings->setCursorHighlightColor(Util::gdkrgba_to_hex(color));
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(get("cursorHighlightBorderColor")), &color);
settings->setCursorHighlightBorderColor(Util::gdkrgba_to_hex(color));
GtkWidget* spCursorHighlightRadius = get("cursorHighlightRadius");
settings->setCursorHighlightRadius(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spCursorHighlightRadius)));
GtkWidget* spCursorHighlightBorderWidth = get("cursorHighlightBorderWidth");
settings->setCursorHighlightBorderWidth(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spCursorHighlightBorderWidth)));
bool hideFullscreenMenubar = getCheckbox("cbHideFullscreenMenubar");
bool hideFullscreenSidebar = getCheckbox("cbHideFullscreenSidebar");
settings->setFullscreenHideElements(

@ -38,11 +38,14 @@ void Util::execInUiThread(std::function<void()>&& callback) {
new CallbackUiData(std::move(callback)));
}
auto Util::rgb_to_GdkRGBA(const uint32_t color) -> GdkRGBA { // clang-format off
return {((color >> 16U) & 0xFFU) / 255.0,
((color >> 8U) & 0xFFU) / 255.0,
(color & 0xFFU) / 255.0,
1.0};
auto Util::rgb_to_GdkRGBA(const uint32_t color) -> GdkRGBA { return Util::argb_to_GdkRGBA(0xFF000000U | color); }
auto Util::argb_to_GdkRGBA(const uint32_t color) -> GdkRGBA {
// clang-format off
return {((color >> 16U) & 0xFFU) / 255.0,
((color >> 8U) & 0xFFU) / 255.0,
(color & 0xFFU) / 255.0,
((color >> 24U) & 0xFFU) / 255.0};
// clang-format on
}

@ -28,6 +28,7 @@ namespace Util {
void cairo_set_source_rgbi(cairo_t* cr, int color);
GdkRGBA rgb_to_GdkRGBA(uint32_t color);
GdkRGBA argb_to_GdkRGBA(uint32_t color);
uint32_t gdkrgba_to_hex(const GdkRGBA& color);
Path getAutosaveFilename();

@ -1,12 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<requires lib="gtk+" version="3.18"/>
<object class="GtkAdjustment" id="adjustmentAudioGain">
<property name="upper">10</property>
<property name="value">1</property>
<property name="step_increment">0.10000000000000001</property>
</object>
<object class="GtkAdjustment" id="adjustmentCursorHighlightBorderWidth">
<property name="upper">30</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="adjustmentCursorHighlightRadius">
<property name="upper">30</property>
<property name="value">30</property>
<property name="step_increment">1</property>
<property name="page_increment">5</property>
</object>
<object class="GtkAdjustment" id="adjustmentDrawDirModRadius">
<property name="lower">2</property>
<property name="upper">1000</property>
@ -115,7 +126,7 @@
<property name="type_hint">normal</property>
<property name="gravity">center</property>
<signal name="close" handler="gtk_widget_hide" swapped="no"/>
<child>
<child type="titlebar">
<placeholder/>
</child>
<child internal-child="vbox">
@ -2140,14 +2151,211 @@ This also enables touch drawing.&lt;/i&gt;</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="cbHighlightPosition">
<property name="label" translatable="yes">Highlight cursor position</property>
<property name="name">cbHighlightPosition</property>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
<property name="can_focus">False</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkCheckButton" id="cbHighlightPosition">
<property name="label" translatable="yes">Highlight cursor position</property>
<property name="name">cbHighlightPosition</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Draw a transparent circle around the cursor</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkColorButton" id="cursorHighlightColor">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_alpha">True</property>
<property name="title" translatable="yes">Choose the color to use for "Highlight cursor position"</property>
<property name="show_editor">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Circle Color</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">10</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">pixels</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="cursorHighlightRadius">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="input_purpose">number</property>
<property name="adjustment">adjustmentCursorHighlightRadius</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Radius</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">pixels</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="cursorHighlightBorderWidth">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="text" translatable="yes">30</property>
<property name="input_purpose">number</property>
<property name="adjustment">adjustmentCursorHighlightBorderWidth</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Border Width</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkColorButton" id="cursorHighlightBorderColor">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_alpha">True</property>
<property name="title" translatable="yes">Choose the color to use for "Highlight cursor position"</property>
<property name="show_editor">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Border Color</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">10</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -2162,7 +2370,6 @@ This also enables touch drawing.&lt;/i&gt;</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>

Loading…
Cancel
Save