Fix some problems with moving and resizing child frames
(1) Provide new option 'x-gtk-resize-child-frames' which allows to either hide a child frame during resizing or asks GTK to resize it "immediately". This is needed because desktops like GNOME shell otherwise won't allow resizing child frames at all. (2) Do not try to synchronize the position of a child frame after moving it. Needed because the present implementation introduces a 0.5 secs delay which makes dragging child frames virtually impossible with Lucid and Motif toolkits on desktops like GNOME shell that use invisible outer frame borders. For further information see the thread starting with https://lists.gnu.org/archive/html/emacs-devel/2020-01/msg00343.html * src/frame.c (syms_of_frame): New symbol Qxg_frame_set_char_size_4. * src/gtkutil.c (xg_frame_set_char_size): Hide child frame during resizing when 'x-gtk-resize-child-frames' equals 'hide'. * src/xfns.c (x_set_parent_frame, Fx_create_frame): Set gtk_container_resize_mode to GTK_RESIZE_IMMEDIATE for child frames when'x-gtk-resize-child-frames' equals 'resize-mode'. (Fx_gtk_debug): New function to toggle interactive GTK debugging from within Emacs. (syms_of_xfns): New symbols Qhide and Qresize_mode. (x-gtk-resize-child-frames): New option that allows to resize child frames on desktops like GNOME shell (with the mutter WM) that otherwise refuse to resize them. * src/xterm.c (x_set_offset): Don't x_sync_with_move for child frames, it makes moving child frames virtually impossible with the Lucid and Motif toolkits.
This commit is contained in:
parent
6de20c7eab
commit
c49d379f17
4 changed files with 105 additions and 22 deletions
|
@ -5943,6 +5943,7 @@ syms_of_frame (void)
|
|||
DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
|
||||
DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
|
||||
DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
|
||||
DEFSYM (Qxg_frame_set_char_size_4, "xg-frame-set-char-size-4");
|
||||
DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
|
||||
DEFSYM (Qx_set_window_size_2, "x-set-window-size-2");
|
||||
DEFSYM (Qx_set_window_size_3, "x-set-window-size-3");
|
||||
|
|
|
@ -941,9 +941,8 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
|
|||
}
|
||||
}
|
||||
|
||||
/* Resize the outer window of frame F after changing the height.
|
||||
COLUMNS/ROWS is the size the edit area shall have after the resize. */
|
||||
|
||||
/** Resize the outer window of frame F. WIDTH and HEIGHT are the new
|
||||
pixel sizes of F's text area. */
|
||||
void
|
||||
xg_frame_set_char_size (struct frame *f, int width, int height)
|
||||
{
|
||||
|
@ -954,6 +953,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
|
|||
int totalheight
|
||||
= pixelheight + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
|
||||
int totalwidth = pixelwidth + FRAME_TOOLBAR_WIDTH (f);
|
||||
bool was_visible = false;
|
||||
|
||||
if (FRAME_PIXEL_HEIGHT (f) == 0)
|
||||
return;
|
||||
|
@ -996,12 +996,35 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
|
|||
gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
|
||||
totalwidth, gheight);
|
||||
}
|
||||
else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f)
|
||||
&& EQ (x_gtk_resize_child_frames, Qhide))
|
||||
{
|
||||
was_visible = true;
|
||||
|
||||
if (totalwidth != gwidth || totalheight != gheight)
|
||||
{
|
||||
frame_size_history_add
|
||||
(f, Qxg_frame_set_char_size_4, width, height,
|
||||
list2i (totalwidth, totalheight));
|
||||
block_input ();
|
||||
gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
|
||||
unblock_input ();
|
||||
|
||||
gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
|
||||
totalwidth, totalheight);
|
||||
|
||||
block_input ();
|
||||
gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
|
||||
unblock_input ();
|
||||
|
||||
fullscreen = Qnil;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_size_history_add
|
||||
(f, Qxg_frame_set_char_size_3, width, height,
|
||||
list2i (totalwidth, totalheight));
|
||||
|
||||
gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
|
||||
totalwidth, totalheight);
|
||||
fullscreen = Qnil;
|
||||
|
@ -1017,7 +1040,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
|
|||
size as fast as possible.
|
||||
For unmapped windows, we can set rows/cols. When
|
||||
the frame is mapped again we will (hopefully) get the correct size. */
|
||||
if (FRAME_VISIBLE_P (f))
|
||||
if (FRAME_VISIBLE_P (f) && !was_visible)
|
||||
{
|
||||
/* Must call this to flush out events */
|
||||
(void)gtk_events_pending ();
|
||||
|
|
56
src/xfns.c
56
src/xfns.c
|
@ -861,6 +861,12 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
|
|||
(FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
|
||||
f->left_pos, f->top_pos);
|
||||
#ifdef USE_GTK
|
||||
if (EQ (x_gtk_resize_child_frames, Qresize_mode))
|
||||
gtk_container_set_resize_mode
|
||||
(GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)),
|
||||
p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE);
|
||||
#endif
|
||||
unblock_input ();
|
||||
|
||||
fset_parent_frame (f, new_value);
|
||||
|
@ -4084,6 +4090,11 @@ This function is an internal primitive--use `make-frame' instead. */)
|
|||
block_input ();
|
||||
XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
|
||||
FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
|
||||
#ifdef USE_GTK
|
||||
if (EQ (x_gtk_resize_child_frames, Qresize_mode))
|
||||
gtk_container_set_resize_mode
|
||||
(GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), GTK_RESIZE_IMMEDIATE);
|
||||
#endif
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
|
@ -7742,6 +7753,22 @@ Note: Text drawn with the `x' font backend is shown with hollow boxes. */)
|
|||
#endif /* USE_GTK */
|
||||
#endif /* USE_CAIRO */
|
||||
|
||||
#ifdef USE_GTK
|
||||
#ifdef HAVE_GTK3
|
||||
DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0,
|
||||
doc: /* Toggle interactive GTK debugging. */)
|
||||
(Lisp_Object enable)
|
||||
{
|
||||
gboolean enable_debug = !NILP (enable);
|
||||
|
||||
block_input ();
|
||||
gtk_window_set_interactive_debugging (enable_debug);
|
||||
unblock_input ();
|
||||
|
||||
return NILP (enable) ? Qnil : Qt;
|
||||
}
|
||||
#endif /* HAVE_GTK3 */
|
||||
#endif /* USE_GTK */
|
||||
|
||||
/***********************************************************************
|
||||
Initialization
|
||||
|
@ -7810,6 +7837,8 @@ syms_of_xfns (void)
|
|||
DEFSYM (Qfont_parameter, "font-parameter");
|
||||
DEFSYM (Qmono, "mono");
|
||||
DEFSYM (Qassq_delete_all, "assq-delete-all");
|
||||
DEFSYM (Qhide, "hide");
|
||||
DEFSYM (Qresize_mode, "resize-mode");
|
||||
|
||||
#ifdef USE_CAIRO
|
||||
DEFSYM (Qpdf, "pdf");
|
||||
|
@ -7986,6 +8015,28 @@ Otherwise use Emacs own tooltip implementation.
|
|||
When using Gtk+ tooltips, the tooltip face is not used. */);
|
||||
x_gtk_use_system_tooltips = true;
|
||||
|
||||
DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames,
|
||||
doc: /* If non-nil, resize child frames specially with GTK builds.
|
||||
If this is nil, resize child frames like any other frames. This is the
|
||||
default and usually works with most desktops. Some desktop environments
|
||||
(GNOME shell in particular when using the mutter window manager),
|
||||
however, may refuse to resize a child frame when Emacs is built with
|
||||
GTK3. For those environments, the two settings below are provided.
|
||||
|
||||
If this equals the symbol 'hide', Emacs temporarily hides the child
|
||||
frame during resizing. This approach seems to work reliably, may
|
||||
however induce some flicker when the frame is made visible again.
|
||||
|
||||
If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to
|
||||
always trigger an immediate resize of the child frame. This method is
|
||||
deprecated by GTK and may not work in future versions of that toolkit.
|
||||
It also may freeze Emacs when used with other desktop environments. It
|
||||
avoids, however, the unpleasent flicker induced by the hiding approach.
|
||||
|
||||
This variable is considered a temporary workaround and will be hopefully
|
||||
eliminated in future versions of Emacs. */);
|
||||
x_gtk_resize_child_frames = Qnil;
|
||||
|
||||
/* Tell Emacs about this window system. */
|
||||
Fprovide (Qx, Qnil);
|
||||
|
||||
|
@ -8101,4 +8152,9 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
|
|||
defsubr (&Sx_print_frames_dialog);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_GTK
|
||||
#ifdef HAVE_GTK3
|
||||
defsubr (&Sx_gtk_debug);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
37
src/xterm.c
37
src/xterm.c
|
@ -10608,26 +10608,29 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
|
|||
modified_left, modified_top);
|
||||
#endif
|
||||
|
||||
x_sync_with_move (f, f->left_pos, f->top_pos,
|
||||
FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
|
||||
/* 'x_sync_with_move' is too costly for dragging child frames. */
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
{
|
||||
x_sync_with_move (f, f->left_pos, f->top_pos,
|
||||
FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
|
||||
|
||||
/* change_gravity is non-zero when this function is called from Lisp to
|
||||
programmatically move a frame. In that case, we call
|
||||
x_check_expected_move to discover if we have a "Type A" or "Type B"
|
||||
window manager, and, for a "Type A" window manager, adjust the position
|
||||
of the frame.
|
||||
/* change_gravity is non-zero when this function is called from Lisp to
|
||||
programmatically move a frame. In that case, we call
|
||||
x_check_expected_move to discover if we have a "Type A" or "Type B"
|
||||
window manager, and, for a "Type A" window manager, adjust the position
|
||||
of the frame.
|
||||
|
||||
We call x_check_expected_move if a programmatic move occurred, and
|
||||
either the window manager type (A/B) is unknown or it is Type A but we
|
||||
need to compute the top/left offset adjustment for this frame. */
|
||||
We call x_check_expected_move if a programmatic move occurred, and
|
||||
either the window manager type (A/B) is unknown or it is Type A but we
|
||||
need to compute the top/left offset adjustment for this frame. */
|
||||
|
||||
if (change_gravity != 0
|
||||
&& !FRAME_PARENT_FRAME (f)
|
||||
&& (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
|
||||
|| (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
|
||||
&& (FRAME_X_OUTPUT (f)->move_offset_left == 0
|
||||
&& FRAME_X_OUTPUT (f)->move_offset_top == 0))))
|
||||
x_check_expected_move (f, modified_left, modified_top);
|
||||
if (change_gravity != 0
|
||||
&& (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
|
||||
|| (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
|
||||
&& (FRAME_X_OUTPUT (f)->move_offset_left == 0
|
||||
&& FRAME_X_OUTPUT (f)->move_offset_top == 0))))
|
||||
x_check_expected_move (f, modified_left, modified_top);
|
||||
}
|
||||
|
||||
unblock_input ();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue