diff --git a/src/gtkutil.c b/src/gtkutil.c index 3a00e36..63f0143 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -783,33 +783,55 @@ struct xg_frame_tb_info { if (f->size_hint_flags & (USPosition | PPosition)) { - int left = f->left_pos; - int xneg = f->size_hint_flags & XNegative; - int top = f->top_pos; - int yneg = f->size_hint_flags & YNegative; - char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)]; - guint id; - - if (xneg) - left = -left; - if (yneg) - top = -top; - - sprintf (geom_str, "=%dx%d%c%d%c%d", - FRAME_PIXEL_WIDTH (f), - FRAME_PIXEL_HEIGHT (f), - (xneg ? '-' : '+'), left, - (yneg ? '-' : '+'), top); - - /* Silence warning about visible children. */ - id = g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL - | G_LOG_FLAG_RECURSION, my_log_handler, NULL); - - if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - geom_str)) - fprintf (stderr, "Failed to parse: '%s'\n", geom_str); - - g_log_remove_handler ("Gtk", id); + if (x_gtk_use_window_move) + { + /* Handle negative positions without consulting + gtk_window_parse_geometry (Bug#25851). The position will + be off by scrollbar width + window manager decorations. */ + if (f->size_hint_flags & XNegative) + f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) + - FRAME_PIXEL_WIDTH (f) + f->left_pos); + + if (f->size_hint_flags & YNegative) + f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) + - FRAME_PIXEL_HEIGHT (f) + f->top_pos); + + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + + /* Reset size hint flags. */ + f->size_hint_flags &= ~ (XNegative | YNegative); + } + else + { + int left = f->left_pos; + int xneg = f->size_hint_flags & XNegative; + int top = f->top_pos; + int yneg = f->size_hint_flags & YNegative; + char geom_str[sizeof "=x--" + 4 * INT_STRLEN_BOUND (int)]; + guint id; + + if (xneg) + left = -left; + if (yneg) + top = -top; + + sprintf (geom_str, "=%dx%d%c%d%c%d", + FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f), + (xneg ? '-' : '+'), left, + (yneg ? '-' : '+'), top); + + /* Silence warning about visible children. */ + id = g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL + | G_LOG_FLAG_RECURSION, my_log_handler, NULL); + + if (!gtk_window_parse_geometry (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + geom_str)) + fprintf (stderr, "Failed to parse: '%s'\n", geom_str); + + g_log_remove_handler ("Gtk", id); + } } } @@ -1406,6 +1428,13 @@ struct xg_frame_tb_info else if (win_gravity == StaticGravity) size_hints.win_gravity = GDK_GRAVITY_STATIC; + if (x_gtk_use_window_move) + { + if (flags & PPosition) hint_flags |= GDK_HINT_POS; + if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS; + if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE; + } + if (user_position) { hint_flags &= ~GDK_HINT_POS; diff --git a/src/xterm.c b/src/xterm.c index 7856793..4f9eff6 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10056,11 +10056,26 @@ struct x_error_message_stack { f->size_hint_flags |= YNegative; f->win_gravity = NorthWestGravity; } + x_calc_absolute_position (f); block_input (); x_wm_set_size_hint (f, 0, false); +#ifdef USE_GTK + if (x_gtk_use_window_move) + { + /* When a position change was requested and the outer GTK widget + has been realized already, leave it to gtk_window_move to DTRT + and return. Used for Bug#25851 and Bug#25943. */ + if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + unblock_input (); + return; + } +#endif /* USE_GTK */ + modified_left = f->left_pos; modified_top = f->top_pos; @@ -12905,4 +12920,11 @@ click on a frame to select it (give it focus). In that case, a value Set this variable only if your window manager cannot handle the transition between the various maximization states. */); x_frame_normalize_before_maximize = false; + + DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move, + doc: /* Non-nil means rely on gtk_window_move to set frame positions. +If this variable is t, the GTK build uses the function gtk_window_move +to set or store frame positions and disables some time consuming frame +position adjustments. */); + x_gtk_use_window_move = false; }