Skip to content

Improves usability on Linux. No more double title bar#12600

Merged
SoftFever merged 6 commits into
mainfrom
feature/fix-double-title-bar-in-Linux
Mar 4, 2026
Merged

Improves usability on Linux. No more double title bar#12600
SoftFever merged 6 commits into
mainfrom
feature/fix-double-title-bar-in-Linux

Conversation

@SoftFever

Copy link
Copy Markdown
Collaborator

Description

This PR improves usability on Linux. No more double title bar on Linux now.
We now have the same sleek look on Linux as on Windows and macOS.

Screenshots/Recordings/Graphs

Before:
Screenshot 2026-03-04 at 19 08 27

Now:
Screenshot from 2026-03-04 19-02-21

Tests

Copilot AI review requested due to automatic review settings March 4, 2026 11:10
@SoftFever SoftFever added the 2.3.2 label Mar 4, 2026
@SoftFever SoftFever self-assigned this Mar 4, 2026
@SoftFever SoftFever added the Community testers wanted Looking for community testers and feedback label Mar 4, 2026
@SoftFever SoftFever added this to the 2.3.2 milestone Mar 4, 2026
@SoftFever SoftFever changed the title Feature/fix double title bar in linux Improves usability on Linux. No more double title bar Mar 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the double title bar issue on Linux by suppressing the window manager's native title bar (via m_gdkDecor = 0) and implementing a custom WM-integrated resize border handler (GtkResizeBorderHandler) and drag/maximize interactions using native GTK APIs. It also removes a stray task.md developer-notes file.

Changes:

  • Adds a GtkResizeBorderHandler wxEventFilter class to provide resize cursor and gtk_window_begin_resize_drag()-based window resizing for the borderless GTK window.
  • Implements GTK-specific window drag (gtk_window_begin_move_drag) and maximize/unmaximize (gtk_window_maximize/gtk_window_unmaximize) in the topbar.
  • Removes the task.md developer scratch file from the repo.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
task.md Removes an accidentally committed developer scratch/notes file unrelated to the PR
src/slic3r/GUI/MainFrame.hpp Declares the nested GtkResizeBorderHandler class and its pointer member for GTK builds
src/slic3r/GUI/MainFrame.cpp Implements GtkResizeBorderHandler, sets m_gdkDecor = 0 to remove WM title bar, installs/cleans up the handler
src/slic3r/GUI/BBLTopbar.cpp Adds GTK-native window move drag and maximize/restore in the topbar event handlers

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/slic3r/GUI/MainFrame.cpp Outdated
Comment on lines +206 to +227
GdkCursorType cursor_type;
switch (edge) {
case GDK_WINDOW_EDGE_NORTH: cursor_type = GDK_TOP_SIDE; break;
case GDK_WINDOW_EDGE_SOUTH: cursor_type = GDK_BOTTOM_SIDE; break;
case GDK_WINDOW_EDGE_WEST: cursor_type = GDK_LEFT_SIDE; break;
case GDK_WINDOW_EDGE_EAST: cursor_type = GDK_RIGHT_SIDE; break;
case GDK_WINDOW_EDGE_NORTH_WEST: cursor_type = GDK_TOP_LEFT_CORNER; break;
case GDK_WINDOW_EDGE_NORTH_EAST: cursor_type = GDK_TOP_RIGHT_CORNER; break;
case GDK_WINDOW_EDGE_SOUTH_WEST: cursor_type = GDK_BOTTOM_LEFT_CORNER; break;
case GDK_WINDOW_EDGE_SOUTH_EAST: cursor_type = GDK_BOTTOM_RIGHT_CORNER;break;
default: return;
}

GdkDisplay* display = gtk_widget_get_display(m_frame->m_widget);
GdkCursor* cursor = gdk_cursor_new_for_display(display, cursor_type);
gdk_window_set_cursor(gtk_widget_get_window(m_frame->m_widget), cursor);
g_object_unref(cursor);
m_cursor_set = true;
}

MainFrame* m_frame;
bool m_cursor_set{false};

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The set_cursor_for_edge() method is called unconditionally on every wxEVT_MOTION event when the cursor is near a border edge. It creates and destroys a new GdkCursor object each time via gdk_cursor_new_for_display() + g_object_unref(). Since mouse motion events can fire many times per second, this causes frequent GDK cursor object allocation and deallocation.

Additionally, gdk_cursor_new_for_display() with a GdkCursorType argument has been deprecated since GTK 3.16. The recommended replacement is gdk_cursor_new_from_name().

To fix the performance issue, track the last edge that was set (e.g., add a GdkWindowEdge m_last_edge member and a sentinel value like -1 or an std::optional<GdkWindowEdge>) and skip recreating the cursor when the edge hasn't changed. To fix the deprecation, use gdk_cursor_new_from_name() with CSS cursor names (e.g., "n-resize", "s-resize", "w-resize", "e-resize", "nw-resize", "ne-resize", "sw-resize", "se-resize").

Suggested change
GdkCursorType cursor_type;
switch (edge) {
case GDK_WINDOW_EDGE_NORTH: cursor_type = GDK_TOP_SIDE; break;
case GDK_WINDOW_EDGE_SOUTH: cursor_type = GDK_BOTTOM_SIDE; break;
case GDK_WINDOW_EDGE_WEST: cursor_type = GDK_LEFT_SIDE; break;
case GDK_WINDOW_EDGE_EAST: cursor_type = GDK_RIGHT_SIDE; break;
case GDK_WINDOW_EDGE_NORTH_WEST: cursor_type = GDK_TOP_LEFT_CORNER; break;
case GDK_WINDOW_EDGE_NORTH_EAST: cursor_type = GDK_TOP_RIGHT_CORNER; break;
case GDK_WINDOW_EDGE_SOUTH_WEST: cursor_type = GDK_BOTTOM_LEFT_CORNER; break;
case GDK_WINDOW_EDGE_SOUTH_EAST: cursor_type = GDK_BOTTOM_RIGHT_CORNER;break;
default: return;
}
GdkDisplay* display = gtk_widget_get_display(m_frame->m_widget);
GdkCursor* cursor = gdk_cursor_new_for_display(display, cursor_type);
gdk_window_set_cursor(gtk_widget_get_window(m_frame->m_widget), cursor);
g_object_unref(cursor);
m_cursor_set = true;
}
MainFrame* m_frame;
bool m_cursor_set{false};
// Avoid recreating the cursor if the edge (and thus cursor shape) has not changed.
if (m_last_edge_valid && m_cursor_set && edge == m_last_edge)
return;
const char *cursor_name = nullptr;
switch (edge) {
case GDK_WINDOW_EDGE_NORTH: cursor_name = "n-resize"; break;
case GDK_WINDOW_EDGE_SOUTH: cursor_name = "s-resize"; break;
case GDK_WINDOW_EDGE_WEST: cursor_name = "w-resize"; break;
case GDK_WINDOW_EDGE_EAST: cursor_name = "e-resize"; break;
case GDK_WINDOW_EDGE_NORTH_WEST: cursor_name = "nw-resize"; break;
case GDK_WINDOW_EDGE_NORTH_EAST: cursor_name = "ne-resize"; break;
case GDK_WINDOW_EDGE_SOUTH_WEST: cursor_name = "sw-resize"; break;
case GDK_WINDOW_EDGE_SOUTH_EAST: cursor_name = "se-resize"; break;
default:
return;
}
GdkDisplay* display = gtk_widget_get_display(m_frame->m_widget);
GdkCursor* cursor = gdk_cursor_new_from_name(display, cursor_name);
if (!cursor)
return;
gdk_window_set_cursor(gtk_widget_get_window(m_frame->m_widget), cursor);
g_object_unref(cursor);
m_cursor_set = true;
m_last_edge = edge;
m_last_edge_valid = true;
}
MainFrame* m_frame;
bool m_cursor_set{false};
GdkWindowEdge m_last_edge;
bool m_last_edge_valid{false};

Copilot uses AI. Check for mistakes.
Comment thread src/slic3r/GUI/BBLTopbar.cpp
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown

Test Results

0 tests   0 ✅  0s ⏱️
1 suites  0 💤
1 files    0 ❌

Results for commit aa631b0.

@SoftFever SoftFever requested a review from Copilot March 4, 2026 14:20
@SoftFever SoftFever merged commit d50b4cb into main Mar 4, 2026
16 checks passed
@SoftFever SoftFever deleted the feature/fix-double-title-bar-in-Linux branch March 4, 2026 14:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +169 to +176
if (t == wxEVT_LEFT_DOWN) {
gtk_window_begin_resize_drag(
GTK_WINDOW(m_frame->m_widget),
edge,
1, // left mouse button
mouse.x, mouse.y,
gtk_get_current_event_time());
return Event_Processed;

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GtkResizeBorderHandler::FilterEvent intercepts all wxEVT_LEFT_DOWN events application-wide without checking whether the event's target window is the main frame or one of its direct children. If any widget (e.g., a popup menu, dropdown, or child panel) is positioned within the 8-pixel border zone at the frame's edge, a left-click on it will be intercepted and transformed into a resize drag operation instead, eating the click entirely (since Event_Processed is returned).

To fix this, the filter should check that the event's target window (event.GetEventObject()) is either the main frame itself or that no other top-level window is active/focused (e.g., using wxWindow::FindFocus() or checking wxGetTopLevelParent of the event object). Alternatively, set the cursor only on the root GDK window but only begin the drag when the event source is the main GDK window.

Copilot uses AI. Check for mistakes.
SoftFever added a commit that referenced this pull request Mar 4, 2026
* Fix double title bar on Linux by removing WM decorations for GTK

* wip

* fix

* finish

* address review comment
SoftFever added a commit that referenced this pull request Mar 4, 2026
…variables (#12602)

* Linux: prefer discrete GPU on dual-GPU systems via PRIME environment variables

  Set DRI_PRIME=1 for AMD/nouveau PRIME setups and __NV_PRIME_RENDER_OFFLOAD/__GLX_VENDOR_LIBRARY_NAME for NVIDIA proprietary driver, only when the NVIDIA kernel module is detected. Uses replace=false to respect user overrides.

* Improves usability on Linux. No more double title bar (#12600)

* Fix double title bar on Linux by removing WM decorations for GTK

* wip

* fix

* finish

* address review comment
@timnolte

timnolte commented Mar 6, 2026

Copy link
Copy Markdown

This work is not good for Linux users. The result of this is that now the file name and the file change state is no longer in the Title Bar. Removing the native Title Bar breaks functionality. This needs to be reverted or changed so the built-in Title Bar contains the file name.

image

Xipit pushed a commit to Xipit/OrcaSlicer that referenced this pull request Mar 16, 2026
* Fix double title bar on Linux by removing WM decorations for GTK

* wip

* fix

* finish

* address review comment
Xipit pushed a commit to Xipit/OrcaSlicer that referenced this pull request Mar 16, 2026
…variables (OrcaSlicer#12602)

* Linux: prefer discrete GPU on dual-GPU systems via PRIME environment variables

  Set DRI_PRIME=1 for AMD/nouveau PRIME setups and __NV_PRIME_RENDER_OFFLOAD/__GLX_VENDOR_LIBRARY_NAME for NVIDIA proprietary driver, only when the NVIDIA kernel module is detected. Uses replace=false to respect user overrides.

* Improves usability on Linux. No more double title bar (OrcaSlicer#12600)

* Fix double title bar on Linux by removing WM decorations for GTK

* wip

* fix

* finish

* address review comment
davidjdixon pushed a commit to davidjdixon/OrcaSlicer that referenced this pull request Mar 21, 2026
* Fix double title bar on Linux by removing WM decorations for GTK

* wip

* fix

* finish

* address review comment
davidjdixon pushed a commit to davidjdixon/OrcaSlicer that referenced this pull request Mar 21, 2026
…variables (OrcaSlicer#12602)

* Linux: prefer discrete GPU on dual-GPU systems via PRIME environment variables

  Set DRI_PRIME=1 for AMD/nouveau PRIME setups and __NV_PRIME_RENDER_OFFLOAD/__GLX_VENDOR_LIBRARY_NAME for NVIDIA proprietary driver, only when the NVIDIA kernel module is detected. Uses replace=false to respect user overrides.

* Improves usability on Linux. No more double title bar (OrcaSlicer#12600)

* Fix double title bar on Linux by removing WM decorations for GTK

* wip

* fix

* finish

* address review comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Community testers wanted Looking for community testers and feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants