diff --git a/src/control/Control.cpp b/src/control/Control.cpp index d9063d26..6c76526e 100644 --- a/src/control/Control.cpp +++ b/src/control/Control.cpp @@ -1,5 +1,6 @@ #include "Control.h" +#include "FullscreenHandler.h" #include "PrintHandler.h" #include "LatexController.h" #include "layer/LayerController.h" @@ -83,7 +84,6 @@ Control::Control(GladeSearchpath* gladeSearchPath) this->lastAction = ACTION_NONE; this->lastGroup = GROUP_NOGROUP; this->lastEnabled = false; - this->fullscreen = false; Path name = Path(g_get_home_dir()); name /= CONFIG_DIR; @@ -105,8 +105,6 @@ Control::Control(GladeSearchpath* gladeSearchPath) this->scheduler = new XournalScheduler(); - this->hiddenFullscreenWidgets = NULL; - this->sidebarHidden = false; this->autosaveTimeout = 0; this->statusbar = NULL; @@ -138,6 +136,8 @@ Control::Control(GladeSearchpath* gladeSearchPath) this->layerController = new LayerController(this); this->layerController->registerListener(this); + + this->fullscreenHandler = new FullscreenHandler(settings); } Control::~Control() @@ -194,6 +194,8 @@ Control::~Control() this->pageBackgroundChangeController = NULL; delete this->layerController; this->layerController = NULL; + delete this->fullscreenHandler; + this->fullscreenHandler = NULL; XOJ_RELEASE_TYPE(Control); } @@ -1176,59 +1178,9 @@ void Control::enableFullscreen(bool enabled, bool presentation) { XOJ_CHECK_TYPE(Control); - if (enabled) - { - gtk_window_fullscreen((GtkWindow*) *win); - - string str = presentation ? settings->getPresentationHideElements() : settings->getFullscreenHideElements(); - - for (string s : StringUtils::split(str, ',')) - { - if ("sidebarContents" == s && settings->isSidebarVisible()) - { - this->sidebarHidden = true; - win->setSidebarVisible(false); - } - else - { - GtkWidget* w = win->get(s.c_str()); - if (w == NULL) - { - g_warning("Fullscreen: Try to hide \"%s\", but coulden't find it. Wrong entry in ~/" - CONFIG_DIR "/" SETTINGS_XML_FILE "?", s.c_str()); - } - else - { - if (gtk_widget_get_visible(w)) - { - gtk_widget_hide(w); - this->hiddenFullscreenWidgets = g_list_append(this->hiddenFullscreenWidgets, w); - } - } - } - } - } - else - { - gtk_window_unfullscreen((GtkWindow*) *win); - - for (GList* l = this->hiddenFullscreenWidgets; l != NULL; l = l->next) - { - gtk_widget_show(GTK_WIDGET(l->data)); - } - - if (this->sidebarHidden) - { - this->sidebarHidden = false; - win->setSidebarVisible(true); - } - - g_list_free(this->hiddenFullscreenWidgets); - this->hiddenFullscreenWidgets = NULL; - } + fullscreenHandler->enableFullscreen(win, enabled, presentation); fireActionSelected(GROUP_FULLSCREEN, enabled ? ACTION_FULLSCREEN : ACTION_NONE); - this->fullscreen = enabled; } void Control::disableSidebarTmp(bool disabled) @@ -3133,7 +3085,7 @@ GtkWindow* Control::getGtkWindow() bool Control::isFullscreen() { XOJ_CHECK_TYPE(Control); - return this->fullscreen; + return this->fullscreenHandler->isFullscreen(); } void Control::rotationSnappingToggle() diff --git a/src/control/Control.h b/src/control/Control.h index 704713d5..bd426d8e 100644 --- a/src/control/Control.h +++ b/src/control/Control.h @@ -35,6 +35,7 @@ #include "../gui/dialog/LatexDialog.h" class AudioController; +class FullscreenHandler; class Sidebar; class XojPageView; class SaveHandler; @@ -294,7 +295,6 @@ private: RecentManager* recent; UndoRedoHandler* undoRedo; ZoomControl* zoom; - bool fullscreen = false; Settings* settings; MainWindow* win; @@ -310,9 +310,6 @@ private: ActionGroup lastGroup; bool lastEnabled; - GList* hiddenFullscreenWidgets; - bool sidebarHidden; - ScrollHandler* scrollHandler; AudioController* audioController; @@ -366,4 +363,9 @@ private: PageBackgroundChangeController* pageBackgroundChangeController; LayerController* layerController; + + /** + * Fullscreen handler + */ + FullscreenHandler* fullscreenHandler; }; diff --git a/src/control/FullscreenHandler.cpp b/src/control/FullscreenHandler.cpp new file mode 100644 index 00000000..a76dd5df --- /dev/null +++ b/src/control/FullscreenHandler.cpp @@ -0,0 +1,245 @@ +#include "FullscreenHandler.h" + +#include "Control.h" +#include "gui/MainWindow.h" + +#include + +GtkWidget* gtk_invisible_new(); + +FullscreenHandler::FullscreenHandler(Settings* settings) + : settings(settings) +{ + XOJ_INIT_TYPE(FullscreenHandler); +} + +FullscreenHandler::~FullscreenHandler() +{ + XOJ_CHECK_TYPE(FullscreenHandler); + + XOJ_RELEASE_TYPE(FullscreenHandler); +} + +bool FullscreenHandler::isFullscreen() +{ + XOJ_CHECK_TYPE(FullscreenHandler); + + return this->fullscreen; +} + +void FullscreenHandler::hideWidget(MainWindow* win, string widgetName) +{ + XOJ_CHECK_TYPE(FullscreenHandler); + + if ("sidebarContents" == widgetName && settings->isSidebarVisible()) + { + this->sidebarHidden = true; + win->setSidebarVisible(false); + + return; + } + + if ("mainMenubar" == widgetName) + { + // If the menu is hidden, shortcuts are not working anymore + // therefore the menu is not hidden, it's displayed, but invisible + // this costs 1px at the bottom, even if the preferred size is 0px, + // 1px is used by GTK + + GtkWidget* mainMenubar = win->get("mainMenubar"); + GtkWidget* mainBox = win->get("mainBox"); + + if (mainMenubar == NULL || !gtk_widget_is_visible(mainMenubar)) + { + // Menu not visible (global menu or something like this) + return; + } + + // Remove menu from parent + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(mainMenubar)), mainMenubar); + + GtkWidget* fix = gtk_invisible_new(); + + gtk_widget_set_size_request(fix, 0, 0); + gtk_fixed_put(GTK_FIXED(fix), mainMenubar, 0, 0); + + gtk_widget_show(fix); + + gtk_box_pack_end(GTK_BOX(mainBox), fix, false, false, 0); + + menubarHidden = true; + + return; + } + + return; + + GtkWidget* w = win->get(widgetName); + if (w == NULL) + { + g_warning("Fullscreen: Try to hide \"%s\", but coulden't find it. Wrong entry in ~/" + CONFIG_DIR "/" SETTINGS_XML_FILE "?", widgetName.c_str()); + return; + } + + if (gtk_widget_get_visible(w)) + { + gtk_widget_hide(w); + hiddenFullscreenWidgets.push_back(w); + } +} + +void FullscreenHandler::enableFullscreen(MainWindow* win, string hideWidgets) +{ + XOJ_CHECK_TYPE(FullscreenHandler); + + gtk_window_fullscreen((GtkWindow*) *win); + + for (string s : StringUtils::split(hideWidgets, ',')) + { + hideWidget(win, s); + } +} + +void FullscreenHandler::disableFullscreen(MainWindow* win) +{ + XOJ_CHECK_TYPE(FullscreenHandler); + + gtk_window_unfullscreen((GtkWindow*) *win); + + for (GtkWidget* w : hiddenFullscreenWidgets) + { + gtk_widget_show(w); + } + hiddenFullscreenWidgets.clear(); + + if (this->sidebarHidden) + { + this->sidebarHidden = false; + win->setSidebarVisible(true); + } + + if (this->menubarHidden) + { + GtkWidget* mainMenubar = win->get("mainMenubar"); + GtkWidget* mainBox = win->get("mainBox"); + + GtkWidget* parent = gtk_widget_get_parent(mainMenubar); + + // Remove menu from parent + gtk_container_remove(GTK_CONTAINER(parent), mainMenubar); + gtk_box_pack_start(GTK_BOX(mainBox), mainMenubar, false, true, 0); + + + GValue value = G_VALUE_INIT; + g_value_init(&value, G_TYPE_INT); + g_value_set_int(&value, 0); + gtk_container_child_set_property(GTK_CONTAINER(mainBox), mainMenubar, "position", &value); + + // not needed, will be recreated next time + gtk_widget_destroy(parent); + + menubarHidden = false; + } +} + +void FullscreenHandler::enableFullscreen(MainWindow* win, bool enabled, bool presentation) +{ + XOJ_CHECK_TYPE(FullscreenHandler); + + if (enabled) + { + enableFullscreen(win, presentation ? settings->getPresentationHideElements() : settings->getFullscreenHideElements()); + } + else + { + disableFullscreen(win); + } + + this->fullscreen = enabled; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Widget which allow to hide the menu, but let the shortcuts active +/////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + GtkFixedClass parent_class; +} GtkInvisibleMenuClass; + +typedef struct +{ + GtkFixed widget; +} GtkInvisibleMenu; + +static void gtk_invisible_menu_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural) +{ + *minimum = 0; + *natural = 0; +} + +static void gtk_invisible_menu_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural) +{ + *minimum = 0; + *natural = 0; +} + +static gboolean gtk_invisible_menu_draw(GtkWidget *widget, cairo_t *cr) +{ + return FALSE; +} + +static void gtk_invisible_menu_class_init(GtkInvisibleMenuClass* klass) +{ + GtkWidgetClass* widget_class; + + widget_class = (GtkWidgetClass*) klass; + widget_class->get_preferred_width = gtk_invisible_menu_get_preferred_width; + widget_class->get_preferred_height = gtk_invisible_menu_get_preferred_height; + widget_class->draw = gtk_invisible_menu_draw; +} + +GType gtk_invisible_get_type() +{ + static GType gtk_invisible_menu_type = 0; + + if (!gtk_invisible_menu_type) + { + static const GTypeInfo gtk_inivisible_menu_info = + { + sizeof(GtkInvisibleMenuClass), + // base initialize + NULL, + // base finalize + NULL, + // class initialize + (GClassInitFunc) gtk_invisible_menu_class_init, + // class finalize + NULL, + // class data, + NULL, + // instance size + sizeof(GtkInvisibleMenu), + // n_preallocs + 0, + // instance init + NULL, + // value table + (const GTypeValueTable*) NULL + }; + + gtk_invisible_menu_type = g_type_register_static(GTK_TYPE_FIXED, + "GtkInvisibleMenu", + >k_inivisible_menu_info, + (GTypeFlags) 0); + } + + return gtk_invisible_menu_type; +} + +GtkWidget* gtk_invisible_new() +{ + return GTK_WIDGET(g_object_new(gtk_invisible_get_type(), NULL)); +} diff --git a/src/control/FullscreenHandler.h b/src/control/FullscreenHandler.h new file mode 100644 index 00000000..df8ac8f0 --- /dev/null +++ b/src/control/FullscreenHandler.h @@ -0,0 +1,64 @@ +/* + * Xournal++ + * + * Fullscreen handler + * + * @author Xournal++ Team + * https://github.com/xournalpp/xournalpp + * + * @license GNU GPLv2 or later + */ + +#pragma once + +#include + +#include + +class Settings; +class MainWindow; + +class FullscreenHandler +{ +public: + FullscreenHandler(Settings* settings); + virtual ~FullscreenHandler(); + +public: + bool isFullscreen(); + + void enableFullscreen(MainWindow* win, bool enabled, bool presentation = false); + +private: + void enableFullscreen(MainWindow* win, string hideWidgets); + void hideWidget(MainWindow* win, string widgetName); + void disableFullscreen(MainWindow* win); + +private: + XOJ_TYPE_ATTRIB; + + /** + * Settings + */ + Settings* settings; + + /** + * Fullscreen enabled + */ + bool fullscreen = false; + + /** + * If the sidebar was hidden + */ + bool sidebarHidden = false; + + /** + * The menubar was hidden + */ + bool menubarHidden = false; + + /** + * Currently hidden widgets + */ + vector hiddenFullscreenWidgets; +}; diff --git a/src/util/XournalTypeList.h b/src/util/XournalTypeList.h index f2c7ffa3..78ebf3ac 100644 --- a/src/util/XournalTypeList.h +++ b/src/util/XournalTypeList.h @@ -273,3 +273,5 @@ XOJ_DECLARE_TYPE(SoxConsumer, 263); XOJ_DECLARE_TYPE(AudioRecorder, 264); XOJ_DECLARE_TYPE(AudioQueue, 265); XOJ_DECLARE_TYPE(DeviceInfo, 266); +XOJ_DECLARE_TYPE(FullscreenHandler, 267); +