macos: introduce ugly packing hack to attempt to reduce the size of the residual...
authorThomas Debesse <dev@illwieckz.net>
Fri, 19 Feb 2021 20:17:08 +0000 (21:17 +0100)
committerThomas Debesse <dev@illwieckz.net>
Sat, 20 Feb 2021 19:11:29 +0000 (20:11 +0100)
HACK: The OpenGL viewport is reduced to one line on the bottom of the window when other tabs are displayed,
so the rectangle is not drawn over the window but a non-bostructing bottom line instead.

CMakeLists.txt
libs/uilib/uilib.cpp
libs/uilib/uilib.h
radiant/groupdialog.cpp
radiant/texwindow.cpp
radiant/texwindow.h

index 5ff959dcf2b72a26790b9cb53f61e38d430d1a84..94136b8c870eb2c78ef6bf65cec76533c9b5a6e4 100644 (file)
@@ -245,6 +245,7 @@ if (BUILD_RADIANT)
     if (APPLE)
         if (GTK_TARGET EQUAL 2)
             add_definitions(-DWORKAROUND_MACOS_GTK2_DESTROY=1)
+            add_definitions(-DWORKAROUND_MACOS_GTK2_GLWIDGET=1)
         endif ()
     endif ()
 endif ()
index 8812911ed1e2bed878e6ad212aae77080ed5c08d..5caf150d2c9bb16c2218235610c1bce346725f89 100644 (file)
@@ -270,6 +270,11 @@ namespace ui {
         gtk_box_pack_end(this, child, expand, fill, padding);
     }
 
+    void IBox::set_child_packing(ui::Widget child, bool expand, bool fill, unsigned int padding, ui::Packing packing)
+    {
+        gtk_box_set_child_packing(this, child, expand, fill, padding, (GtkPackType) packing);
+    }
+
     IMPL(VBox, GTK_VBOX);
 
     VBox::VBox(bool homogenous, int spacing) : VBox(GTK_VBOX(gtk_vbox_new(homogenous, spacing)))
index e6c5ff6a91d68b8fbc583123590d5391ea7650d0..d8f41c85d88559371a36f86c2ed90a33235537c3 100644 (file)
@@ -103,6 +103,11 @@ namespace ui {
         NEVER
     };
 
+       enum class Packing {
+               START,
+               END
+       };
+
     namespace details {
 
         enum class Convert {
@@ -376,6 +381,7 @@ namespace ui {
     ,
          void pack_start(ui::Widget child, bool expand, bool fill, unsigned int padding);
          void pack_end(ui::Widget child, bool expand, bool fill, unsigned int padding);
+         void set_child_packing(ui::Widget child, bool expand, bool fill, unsigned int padding, ui::Packing packing);
     );
 
     WRAP(VBox, Box, _GtkVBox, (),
index f6d9c4be8080d5137fb589d537a9c37d2da541ad..dbad5b89680b43f9f5d74a9bee220d0f0be845ae 100644 (file)
 #include "multimon.h"
 #include "console.h"
 #include "commands.h"
-
-
 #include "gtkutil/window.h"
 
+#if defined(WORKAROUND_WINDOWS_GTK2_GLWIDGET) || defined(WORKAROUND_MACOS_GTK2_GLWIDGET)
+#include "texwindow.h"
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET || WORKAROUND_MACOS_GTK2_GLWIDGET
+
 class GroupDlg
 {
 public:
@@ -74,16 +76,30 @@ std::size_t g_current_page;
 std::vector<Callback<void(const Callback<void(const char *)> &)>> g_pages;
 }
 
+static void workaround_macos_show_hide(){
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+       if ( g_current_page == 2 )
+       {
+               TextureBrowser_showGLWidget();
+       }
+       else
+       {
+               TextureBrowser_hideGLWidget();
+       }
+#endif // WORKAROUND_MACOS_GTK2_GLWIDGET
+}
+
 void GroupDialog_updatePageTitle( ui::Window window, std::size_t pageIndex ){
        if ( pageIndex < g_pages.size() ) {
                g_pages[pageIndex]( PointerCaller<GtkWindow, void(const char*), gtk_window_set_title>( window ) );
        }
+
+       workaround_macos_show_hide();
 }
 
 static gboolean switch_page( GtkNotebook *notebook, gpointer page, guint page_num, gpointer data ){
-       GroupDialog_updatePageTitle( ui::Window::from(data), page_num );
        g_current_page = page_num;
-
+       GroupDialog_updatePageTitle( ui::Window::from(data), page_num );
        return FALSE;
 }
 
@@ -122,7 +138,6 @@ void GroupDlg::Create( ui::Window parent ){
        }
 }
 
-
 ui::Widget GroupDialog_addPage( const char* tabLabel, ui::Widget widget, const Callback<void(const Callback<void(const char *)> &)>& title ){
        ui::Widget w = ui::Label( tabLabel );
        w.show();
@@ -132,7 +147,6 @@ ui::Widget GroupDialog_addPage( const char* tabLabel, ui::Widget widget, const C
        return page;
 }
 
-
 bool GroupDialog_isShown(){
        return g_GroupDlg.m_window.visible();
 }
@@ -152,7 +166,6 @@ void GroupDialog_destroyWindow(){
        g_GroupDlg.m_window = ui::Window{ui::null};
 }
 
-
 ui::Window GroupDialog_getWindow(){
        return ui::Window(g_GroupDlg.m_window);
 }
@@ -161,12 +174,14 @@ void GroupDialog_show(){
 }
 
 ui::Widget GroupDialog_getPage(){
-       return ui::Widget::from(gtk_notebook_get_nth_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) ));
+       return ui::Widget::from(gtk_notebook_get_nth_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) ) );
 }
 
 void GroupDialog_setPage( ui::Widget page ){
        g_current_page = gtk_notebook_page_num( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), page );
        gtk_notebook_set_current_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) );
+
+       workaround_macos_show_hide();
 }
 
 #ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
@@ -174,6 +189,7 @@ void GroupDialog_cycle();
 #endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
 
 void GroupDialog_showPage( ui::Widget page ){
+
        if ( GroupDialog_getPage() == page ) {
                GroupDialog_ToggleShow();
 
@@ -193,6 +209,8 @@ void GroupDialog_showPage( ui::Widget page ){
                g_GroupDlg.m_window.show();
                GroupDialog_setPage( page );
        }
+
+       workaround_macos_show_hide();
 }
 
 void GroupDialog_cycle(){
@@ -206,7 +224,6 @@ void GroupDialog_updatePageTitle( ui::Widget page ){
        }
 }
 
-
 #include "preferencesystem.h"
 
 void GroupDialog_Construct(){
index 75d3788d607f55a0f3e34de14d917f82f0f2b976..9870d2a0c10a6590b088b6722c23af4a121cd622 100644 (file)
@@ -266,6 +266,14 @@ int m_nTotalHeight;
 CopiedString shader;
 
 ui::Window m_parent{ui::null};
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+ui::VBox m_vframe{ui::null};
+ui::VBox m_vfiller{ui::null};
+ui::HBox m_hframe{ui::null};
+ui::HBox m_hfiller{ui::null};
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+ui::VBox m_frame{ui::null};
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
 ui::GLArea m_gl_widget{ui::null};
 ui::Widget m_texture_scroll{ui::null};
 ui::TreeView m_treeViewTree{ui::New};
@@ -1143,6 +1151,7 @@ void Texture_Draw( TextureBrowser& textureBrowser ){
                                  textureBrowser.color_textureback[1],
                                  textureBrowser.color_textureback[2],
                                  0 );
+
        glViewport( 0, 0, textureBrowser.width, textureBrowser.height );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
@@ -1519,7 +1528,6 @@ gboolean TextureBrowser_expose( ui::Widget widget, GdkEventExpose* event, Textur
        return FALSE;
 }
 
-
 TextureBrowser g_TextureBrowser;
 
 TextureBrowser& GlobalTextureBrowser(){
@@ -2056,12 +2064,42 @@ void TextureBrowser_SetNotex(){
        IShader* shadernotex = QERApp_Shader_ForName( DEFAULT_SHADERNOTEX_NAME );
 
        g_notex = notex->getTexture()->name;
+
        g_shadernotex = shadernotex->getTexture()->name;
 
        notex->DecRef();
        shadernotex->DecRef();
 }
 
+static bool isGLWidgetConstructed = false;
+static bool isWindowConstructed = false;
+
+void TextureBrowser_constructGLWidget(){
+       g_TextureBrowser.m_gl_widget = glwidget_new( FALSE );
+       g_object_ref( g_TextureBrowser.m_gl_widget._handle );
+
+       gtk_widget_set_events( g_TextureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK );
+       gtk_widget_set_can_focus( g_TextureBrowser.m_gl_widget, true );
+
+       g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect( "size_allocate", G_CALLBACK( TextureBrowser_size_allocate ), &g_TextureBrowser );
+       g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render( G_CALLBACK( TextureBrowser_expose ), &g_TextureBrowser );
+
+       g_TextureBrowser.m_gl_widget.connect( "button_press_event", G_CALLBACK( TextureBrowser_button_press ), &g_TextureBrowser );
+       g_TextureBrowser.m_gl_widget.connect( "button_release_event", G_CALLBACK( TextureBrowser_button_release ), &g_TextureBrowser );
+       g_TextureBrowser.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( TextureBrowser_motion ), &g_TextureBrowser );
+       g_TextureBrowser.m_gl_widget.connect( "scroll_event", G_CALLBACK( TextureBrowser_scroll ), &g_TextureBrowser );
+
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+       g_TextureBrowser.m_hframe.pack_start( g_TextureBrowser.m_gl_widget, TRUE, TRUE, 0 );
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+       g_TextureBrowser.m_frame.pack_start( g_TextureBrowser.m_gl_widget, TRUE, TRUE, 0 );
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
+
+       g_TextureBrowser.m_gl_widget.show();
+
+       isGLWidgetConstructed = true;
+}
+
 ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
        // The gl_widget and the tag assignment frame should be packed into a GtkVPaned with the slider
        // position stored in local.pref. gtk_paned_get_position() and gtk_paned_set_position() don't
@@ -2123,22 +2161,30 @@ ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
                g_TextureBrowser.m_texture_scroll.visible(g_TextureBrowser.m_showTextureScrollbar);
        }
        { // gl_widget
-               g_TextureBrowser.m_gl_widget = glwidget_new( FALSE );
-               g_object_ref( g_TextureBrowser.m_gl_widget._handle );
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+               g_TextureBrowser.m_vframe = ui::VBox( FALSE, 0 );
+               table.attach(g_TextureBrowser.m_vframe, {1, 2, 1, 2});
+
+               g_TextureBrowser.m_vfiller = ui::VBox( FALSE, 0 );
+               g_TextureBrowser.m_vframe.pack_start( g_TextureBrowser.m_vfiller, FALSE, FALSE, 0 );
 
-               gtk_widget_set_events( g_TextureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK );
-               gtk_widget_set_can_focus( g_TextureBrowser.m_gl_widget, true );
+               g_TextureBrowser.m_hframe = ui::HBox( FALSE, 0 );
+               g_TextureBrowser.m_vframe.pack_start( g_TextureBrowser.m_hframe, TRUE, TRUE, 0 );
 
-               table.attach(g_TextureBrowser.m_gl_widget, {1, 2, 1, 2});
-               g_TextureBrowser.m_gl_widget.show();
+               g_TextureBrowser.m_hfiller = ui::HBox( FALSE, 0 );
+               g_TextureBrowser.m_hframe.pack_start( g_TextureBrowser.m_hfiller, FALSE, FALSE, 0 );
 
-               g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect( "size_allocate", G_CALLBACK( TextureBrowser_size_allocate ), &g_TextureBrowser );
-               g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render( G_CALLBACK( TextureBrowser_expose ), &g_TextureBrowser );
+               g_TextureBrowser.m_vframe.show();
+               g_TextureBrowser.m_vfiller.show();
+               g_TextureBrowser.m_hframe.show(),
+               g_TextureBrowser.m_hfiller.show();
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+               g_TextureBrowser.m_frame = ui::VBox( FALSE, 0 );
+               table.attach(g_TextureBrowser.m_frame, {1, 2, 1, 2});
+               g_TextureBrowser.m_frame.show();
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
 
-               g_TextureBrowser.m_gl_widget.connect( "button_press_event", G_CALLBACK( TextureBrowser_button_press ), &g_TextureBrowser );
-               g_TextureBrowser.m_gl_widget.connect( "button_release_event", G_CALLBACK( TextureBrowser_button_release ), &g_TextureBrowser );
-               g_TextureBrowser.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( TextureBrowser_motion ), &g_TextureBrowser );
-               g_TextureBrowser.m_gl_widget.connect( "scroll_event", G_CALLBACK( TextureBrowser_scroll ), &g_TextureBrowser );
+               TextureBrowser_constructGLWidget();
        }
 
        // tag stuff
@@ -2291,17 +2337,65 @@ ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
        // TODO do we need this?
        //gtk_container_set_focus_chain(GTK_CONTAINER(hbox_table), NULL);
 
+       isWindowConstructed = true;
+
        return table;
 }
 
+void TextureBrowser_destroyGLWidget(){
+       if ( isGLWidgetConstructed )
+       {
+               g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_sizeHandler );
+               g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_exposeHandler );
+
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+               g_TextureBrowser.m_hframe.remove( g_TextureBrowser.m_gl_widget );
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+               g_TextureBrowser.m_frame.remove( g_TextureBrowser.m_gl_widget );
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
+
+               g_TextureBrowser.m_gl_widget.unref();
+
+               isGLWidgetConstructed = false;
+       }
+}
+
 void TextureBrowser_destroyWindow(){
        GlobalShaderSystem().setActiveShadersChangedNotify( Callback<void()>() );
 
-       g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_sizeHandler );
-       g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_exposeHandler );
+       TextureBrowser_destroyGLWidget();
+}
 
-       g_TextureBrowser.m_gl_widget.unref();
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+/* workaround for gtkglext on gtk 2 issue: OpenGL texture viewport being drawn over the other pages */
+/* this is very ugly: force the resizing of the viewport to a single bottom line by forcing the
+ * resizing of the gl widget by expanding some empty boxes, so the widget area size is reduced
+ * while covered by another page, so the texture viewport is still rendered over the other page
+ * but does not annoy the user that much because it's just a line on the bottom that may even
+ * be printed over existing bottom frame or very close to it. */
+void TextureBrowser_showGLWidget(){
+       if ( isWindowConstructed && isGLWidgetConstructed )
+       {
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_vfiller, FALSE, FALSE, 0, ui::Packing::START );
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_hframe, TRUE, TRUE, 0, ui::Packing::START );
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_hfiller, FALSE, FALSE, 0, ui::Packing::START );
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_gl_widget, TRUE, TRUE, 0, ui::Packing::START );
+               GlobalTextureBrowser().m_gl_widget.show();
+       }
+}
+
+void TextureBrowser_hideGLWidget(){
+       if ( isWindowConstructed && isGLWidgetConstructed )
+       {
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_vfiller, TRUE, TRUE, 0, ui::Packing::START);
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_hframe, FALSE, FALSE, 0, ui::Packing::END );
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_hfiller, TRUE, TRUE, 0, ui::Packing::START);
+               GlobalTextureBrowser().m_vframe.set_child_packing( GlobalTextureBrowser().m_gl_widget, FALSE, FALSE, 0, ui::Packing::END );
+               GdkEventExpose event = {};
+               TextureBrowser_expose( GlobalTextureBrowser().m_gl_widget, &event, &GlobalTextureBrowser() );
+       }
 }
+#endif // WORKAROUND_MACOS_GTK2_GLWIDGET
 
 const Vector3& TextureBrowser_getBackgroundColour( TextureBrowser& textureBrowser ){
        return textureBrowser.color_textureback;
index 80aa5e4d0bb9a5aa41e558112e046b92ad04c815..f17a980d73b224aadece0e9e313ad13911456f2f 100644 (file)
@@ -60,4 +60,9 @@ void TextureBrowser_RefreshShaders();
 ui::GLArea TextureBrowser_getGLWidget();
 #endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
 
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+void TextureBrowser_showGLWidget();
+void TextureBrowser_hideGLWidget();
+#endif // WORKAROUND_MACOS_GTK2_GLWIDGET
+
 #endif