diff options
| author | Martin Rudalics | 2025-12-22 11:01:53 +0100 |
|---|---|---|
| committer | Martin Rudalics | 2025-12-22 11:01:53 +0100 |
| commit | f3d9371a890699fe4047f693adfcd4d8dbe2fb7d (patch) | |
| tree | d37fd603addf836483df8ebcf78c53cd0407d991 | |
| parent | 5cf8af22900d359c18a75d9efed44f7c1d8fc06c (diff) | |
| download | emacs-f3d9371a890699fe4047f693adfcd4d8dbe2fb7d.tar.gz emacs-f3d9371a890699fe4047f693adfcd4d8dbe2fb7d.zip | |
Add functions to set frame size and position in one compound step
* lisp/frame.el (set-frame-size-and-position): New function.
* src/frame.c (adjust_frame_size): Handle requests to set size
and position.
(Fset_frame_size_and_position_pixelwise): New function.
* src/gtkutil.c (xg_frame_set_size_and_position): New function.
(xg_wm_set_size_hint): Handle any non-NorthWestGravity values
for child frames only. Some GTK implementations don't like
them.
* src/gtkutil.h (xg_frame_set_size_and_position.): Add external
declaration.
* src/termhooks.h (set_window_size_and_position_hook): New hook.
* src/w32term.c (w32_set_window_size_and_position): New
function.
(w32_create_terminal): Make it the Microsoft Windows API
set_window_size_and_position_hook.
* src/xterm.c (x_set_window_size_and_position_1)
(x_set_window_size_and_position): New functions.
(x_create_terminal): Make x_set_window_size_and_position the
set_window_size_and_position_hook for the X protocol.
* src/xterm.h (x_set_window_size_and_position): Add external
declaration.
* etc/NEWS: Announce new functions.
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/frame.el | 194 | ||||
| -rw-r--r-- | src/frame.c | 77 | ||||
| -rw-r--r-- | src/gtkutil.c | 108 | ||||
| -rw-r--r-- | src/gtkutil.h | 2 | ||||
| -rw-r--r-- | src/termhooks.h | 5 | ||||
| -rw-r--r-- | src/w32term.c | 80 | ||||
| -rw-r--r-- | src/xterm.c | 54 | ||||
| -rw-r--r-- | src/xterm.h | 1 |
9 files changed, 505 insertions, 23 deletions
| @@ -465,6 +465,13 @@ either resize the frame and change the fullscreen status accordingly or | |||
| 465 | keep the frame size unchanged. The value t means to first reset the | 465 | keep the frame size unchanged. The value t means to first reset the |
| 466 | fullscreen status and then resize the frame. | 466 | fullscreen status and then resize the frame. |
| 467 | 467 | ||
| 468 | *** New commands to set frame size and position in one compound step. | ||
| 469 | 'set-frame-size-and-position' sets the new size and position of a frame | ||
| 470 | in one compound step. Both, size and position, can be specified as with | ||
| 471 | the corresponding frame parameters 'width', 'height', 'left' and 'top'. | ||
| 472 | 'set-frame-size-and-position-pixelwise' is similar but has a more | ||
| 473 | restricted set of values for specifying size and position. | ||
| 474 | |||
| 468 | *** New commands 'split-frame' and 'merge-frames'. | 475 | *** New commands 'split-frame' and 'merge-frames'. |
| 469 | 'split-frame' moves a specified number of windows from an existing frame | 476 | 'split-frame' moves a specified number of windows from an existing frame |
| 470 | to a newly-created frame. 'merge-frames' merges all windows from two | 477 | to a newly-created frame. 'merge-frames' merges all windows from two |
diff --git a/lisp/frame.el b/lisp/frame.el index 307312ef71a..d521d49c175 100644 --- a/lisp/frame.el +++ b/lisp/frame.el | |||
| @@ -1535,6 +1535,200 @@ Functions on this hook are called with the theme name as a symbol: | |||
| 1535 | already be set to one of these values as well.") | 1535 | already be set to one of these values as well.") |
| 1536 | 1536 | ||
| 1537 | 1537 | ||
| 1538 | (defun set-frame-size-and-position (&optional frame width height left top) | ||
| 1539 | "Set size and position of specified FRAME in one compound step. | ||
| 1540 | WIDTH and HEIGHT stand for the new width and height of FRAME. They can | ||
| 1541 | be specified as follows where \"display area\" stands for the entire | ||
| 1542 | display area of FRAME's dominating monitor, \"work area\" stands for the | ||
| 1543 | work area (the usable space) of FRAME's display area and \"parent area\" | ||
| 1544 | stands for the area occupied by the native rectangle of FRAME's parent | ||
| 1545 | provided FRAME is a child frame. | ||
| 1546 | |||
| 1547 | - An integer specifies the size of FRAME's text area in characters. | ||
| 1548 | |||
| 1549 | - A cons cell with the symbol `text-pixels' in its car specifies in its | ||
| 1550 | cdr the size of FRAME's text area in pixels. | ||
| 1551 | |||
| 1552 | - A floating-point number between 0.0 and 1.0 specifies the ratio of | ||
| 1553 | FRAME's outer size to the size of its work or parent area. | ||
| 1554 | |||
| 1555 | Unless you use a plain integer value, you may have to set | ||
| 1556 | `frame-resize-pixelwise' to a non-nil value in order to get the exact | ||
| 1557 | size in pixels. A value of nil means to leave the width or height | ||
| 1558 | unaltered. Any other value will signal an error. | ||
| 1559 | |||
| 1560 | LEFT and TOP stand for FRAME's outer position relative to coordinates of | ||
| 1561 | its display, work or parent area. They can be specified as follows: | ||
| 1562 | |||
| 1563 | - An integer where a positive value relates the left or top edge of | ||
| 1564 | FRAME to the origin of its display or parent area. A negative value | ||
| 1565 | relates the right or bottom edge of FRAME to the right or bottom edge | ||
| 1566 | of its display or parent area. | ||
| 1567 | |||
| 1568 | - The symbol `-' means to place the right or bottom edge of FRAME at the | ||
| 1569 | right or bottom edge of its display or parent area. | ||
| 1570 | |||
| 1571 | - A list with `+' as its first and an integer as its second element | ||
| 1572 | specifies the position of the left or top edge of FRAME relative to | ||
| 1573 | the left or top edge of its display or parent area. If the second | ||
| 1574 | element is negative, this means a position outside FRAME's display or | ||
| 1575 | parent area. | ||
| 1576 | |||
| 1577 | - A list with `-' as its first and an integer as its second element | ||
| 1578 | specifies the position of the right or bottom edge of FRAME relative | ||
| 1579 | to the right or bottom edge of its display or parent area. If the | ||
| 1580 | second element is negative, this means a position outside the area of | ||
| 1581 | its display or parent area. | ||
| 1582 | |||
| 1583 | - A floating-point number between 0.0 and 1.0 specifies the ratio of | ||
| 1584 | FRAME's outer position to the size of its work or parent area. Thus, | ||
| 1585 | a value of 0.0 flushes FRAME to the left or top, a value of 0.5 | ||
| 1586 | centers it and a ratio of 1.0 flushes it to the right or bottom of its | ||
| 1587 | work or parent area. | ||
| 1588 | |||
| 1589 | Calculating a position relative to the right or bottom edge of FRAME's | ||
| 1590 | display, work or parent area proceeds by calculating the new size of | ||
| 1591 | FRAME first and then relate the new prospective outer edges of FRAME to | ||
| 1592 | the respective edges of its display, work or parent area. | ||
| 1593 | |||
| 1594 | A value of nil means to leave the position in this direction unchanged. | ||
| 1595 | Any other value will signal an error. | ||
| 1596 | |||
| 1597 | This function calls `set-frame-size-and-position-pixelwise' to actually | ||
| 1598 | resize and move FRAME." | ||
| 1599 | (let* ((frame (window-normalize-frame frame)) | ||
| 1600 | (parent (frame-parent frame)) | ||
| 1601 | (monitor-attributes | ||
| 1602 | (unless parent | ||
| 1603 | (frame-monitor-attributes frame))) | ||
| 1604 | (geometry | ||
| 1605 | (unless parent | ||
| 1606 | (cdr (assq 'geometry monitor-attributes)))) | ||
| 1607 | (parent-or-display-width | ||
| 1608 | (if parent | ||
| 1609 | (frame-native-width parent) | ||
| 1610 | (nth 2 geometry))) | ||
| 1611 | (parent-or-display-height | ||
| 1612 | (if parent | ||
| 1613 | (frame-native-height parent) | ||
| 1614 | (nth 3 geometry))) | ||
| 1615 | (parent-or-workarea | ||
| 1616 | (if parent | ||
| 1617 | `(0 0 ,parent-or-display-width ,parent-or-display-height) | ||
| 1618 | (cdr (assq 'workarea monitor-attributes)))) | ||
| 1619 | (outer-edges (frame-edges frame 'outer-edges)) | ||
| 1620 | (outer-left (nth 0 outer-edges)) | ||
| 1621 | (outer-top (nth 1 outer-edges)) | ||
| 1622 | (outer-width (if outer-edges | ||
| 1623 | (- (nth 2 outer-edges) outer-left) | ||
| 1624 | (frame-pixel-width frame))) | ||
| 1625 | (outer-minus-text-width | ||
| 1626 | (- outer-width (frame-text-width frame))) | ||
| 1627 | (outer-height (if outer-edges | ||
| 1628 | (- (nth 3 outer-edges) outer-top) | ||
| 1629 | (frame-pixel-height frame))) | ||
| 1630 | (outer-minus-text-height | ||
| 1631 | (- outer-height (frame-text-height frame))) | ||
| 1632 | (old-text-width (frame-text-width frame)) | ||
| 1633 | (old-text-height (frame-text-height frame)) | ||
| 1634 | (text-width old-text-width) | ||
| 1635 | (text-height old-text-height) | ||
| 1636 | (char-width (frame-char-width frame)) | ||
| 1637 | (char-height (frame-char-height frame)) | ||
| 1638 | (gravity 1) | ||
| 1639 | negative) | ||
| 1640 | |||
| 1641 | (cond | ||
| 1642 | ((and (integerp width) (> width 0)) | ||
| 1643 | (setq text-width (* width char-width))) | ||
| 1644 | ((and (consp width) (eq (car width) 'text-pixels) | ||
| 1645 | (integerp (cdr width)) (> (cdr width) 0)) | ||
| 1646 | (setq text-width (cdr width))) | ||
| 1647 | ((and (floatp width) (> width 0.0) (<= width 1.0)) | ||
| 1648 | (setq text-width | ||
| 1649 | (- (round (* width (- (nth 2 parent-or-workarea) | ||
| 1650 | (nth 0 parent-or-workarea)))) | ||
| 1651 | outer-minus-text-width))) | ||
| 1652 | (width | ||
| 1653 | (user-error "Invalid width specification"))) | ||
| 1654 | |||
| 1655 | (cond | ||
| 1656 | ((and (integerp height) (> height 0)) | ||
| 1657 | (setq text-height (* height char-height))) | ||
| 1658 | ((and (consp height) (eq (car height) 'text-pixels) | ||
| 1659 | (integerp (cdr height)) (> (cdr height) 0)) | ||
| 1660 | (setq text-height (cdr height))) | ||
| 1661 | ((and (floatp height) (> height 0.0) (<= height 1.0)) | ||
| 1662 | (setq text-height | ||
| 1663 | (- (round (* height (- (nth 3 parent-or-workarea) | ||
| 1664 | (nth 1 parent-or-workarea)))) | ||
| 1665 | outer-minus-text-height))) | ||
| 1666 | (width | ||
| 1667 | (user-error "Invalid height specification"))) | ||
| 1668 | |||
| 1669 | (cond | ||
| 1670 | ((eq left '-) | ||
| 1671 | (setq left 0) | ||
| 1672 | (setq negative t)) | ||
| 1673 | ((integerp left) | ||
| 1674 | (setq negative (< left 0))) | ||
| 1675 | ((consp left) | ||
| 1676 | (cond | ||
| 1677 | ((and (eq (car left) '-) (integerp (cadr left))) | ||
| 1678 | (setq left (- (cadr left))) | ||
| 1679 | (setq negative t)) | ||
| 1680 | ((and (eq (car left) '+) (integerp (cadr left))) | ||
| 1681 | (setq left (cadr left))) | ||
| 1682 | (t | ||
| 1683 | (user-error "Invalid position specification")))) | ||
| 1684 | ((floatp left) | ||
| 1685 | (setq left | ||
| 1686 | (round (* left (- (nth 2 parent-or-workarea) | ||
| 1687 | (nth 0 parent-or-workarea)))))) | ||
| 1688 | (t (setq left outer-left))) | ||
| 1689 | |||
| 1690 | (when negative | ||
| 1691 | (setq gravity 3) | ||
| 1692 | (setq left (- parent-or-display-width (- left) | ||
| 1693 | (+ text-width | ||
| 1694 | (frame-scroll-bar-width frame) | ||
| 1695 | (frame-fringe-width frame) | ||
| 1696 | (* 2 (frame-internal-border-width frame)) | ||
| 1697 | outer-minus-text-width)))) | ||
| 1698 | |||
| 1699 | (setq negative nil) | ||
| 1700 | (cond | ||
| 1701 | ((eq top '-) | ||
| 1702 | (setq top 0) | ||
| 1703 | (setq negative t)) | ||
| 1704 | ((integerp top) | ||
| 1705 | (setq negative (< top 0))) | ||
| 1706 | ((consp top) | ||
| 1707 | (cond | ||
| 1708 | ((and (eq (car top) '-) (integerp (cadr top))) | ||
| 1709 | (setq top (- (cadr top))) | ||
| 1710 | (setq negative t)) | ||
| 1711 | ((and (eq (car top) '+) (integerp (cadr top))) | ||
| 1712 | (setq top (cadr top))) | ||
| 1713 | (t | ||
| 1714 | (user-error "Invalid position specification")))) | ||
| 1715 | ((floatp top) | ||
| 1716 | (setq top | ||
| 1717 | (round (* top (- (nth 3 parent-or-workarea) | ||
| 1718 | (nth 1 parent-or-workarea)))))) | ||
| 1719 | (t (setq top outer-top))) | ||
| 1720 | |||
| 1721 | (when negative | ||
| 1722 | ;; This should get us 7 or 9. | ||
| 1723 | (setq gravity (+ gravity 6)) | ||
| 1724 | (setq top (- parent-or-display-height (- top) | ||
| 1725 | (+ text-height | ||
| 1726 | (* 2 (frame-internal-border-width frame))) | ||
| 1727 | outer-minus-text-height))) | ||
| 1728 | |||
| 1729 | (set-frame-size-and-position-pixelwise | ||
| 1730 | frame text-width text-height left top gravity))) | ||
| 1731 | |||
| 1538 | ;;;; Frame configurations | 1732 | ;;;; Frame configurations |
| 1539 | 1733 | ||
| 1540 | (defun current-frame-configuration () | 1734 | (defun current-frame-configuration () |
diff --git a/src/frame.c b/src/frame.c index 49317379354..c226852bc09 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -777,6 +777,7 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, | |||
| 777 | int old_text_width = FRAME_TEXT_WIDTH (f); | 777 | int old_text_width = FRAME_TEXT_WIDTH (f); |
| 778 | int old_text_height = FRAME_TEXT_HEIGHT (f); | 778 | int old_text_height = FRAME_TEXT_HEIGHT (f); |
| 779 | bool inhibit_horizontal, inhibit_vertical; | 779 | bool inhibit_horizontal, inhibit_vertical; |
| 780 | bool size_and_position = EQ (parameter, Qsize_and_position); | ||
| 780 | Lisp_Object frame; | 781 | Lisp_Object frame; |
| 781 | 782 | ||
| 782 | XSETFRAME (frame, f); | 783 | XSETFRAME (frame, f); |
| @@ -855,7 +856,8 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, | |||
| 855 | /* For inhibit == 1 call the window_size_hook only if a native | 856 | /* For inhibit == 1 call the window_size_hook only if a native |
| 856 | size changes. For inhibit == 0 or inhibit == 2 always call | 857 | size changes. For inhibit == 0 or inhibit == 2 always call |
| 857 | it. */ | 858 | it. */ |
| 858 | && ((!inhibit_horizontal | 859 | && (size_and_position |
| 860 | || (!inhibit_horizontal | ||
| 859 | && (new_native_width != old_native_width | 861 | && (new_native_width != old_native_width |
| 860 | || inhibit == 0 || inhibit == 2)) | 862 | || inhibit == 0 || inhibit == 2)) |
| 861 | || (!inhibit_vertical | 863 | || (!inhibit_vertical |
| @@ -907,7 +909,13 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, | |||
| 907 | f->new_size_p = false; | 909 | f->new_size_p = false; |
| 908 | } | 910 | } |
| 909 | 911 | ||
| 910 | if (FRAME_TERMINAL (f)->set_window_size_hook) | 912 | if (size_and_position) |
| 913 | /* The caller must have set the new position and gravity and | ||
| 914 | made sure that set_window_size_and_position_hook has been | ||
| 915 | defined. */ | ||
| 916 | FRAME_TERMINAL (f)->set_window_size_and_position_hook | ||
| 917 | (f, new_native_width, new_native_height); | ||
| 918 | else if (FRAME_TERMINAL (f)->set_window_size_hook) | ||
| 911 | FRAME_TERMINAL (f)->set_window_size_hook | 919 | FRAME_TERMINAL (f)->set_window_size_hook |
| 912 | (f, 0, new_native_width, new_native_height); | 920 | (f, 0, new_native_width, new_native_height); |
| 913 | f->resized_p = true; | 921 | f->resized_p = true; |
| @@ -4545,6 +4553,69 @@ bottom edge of FRAME's display. */) | |||
| 4545 | return Qt; | 4553 | return Qt; |
| 4546 | } | 4554 | } |
| 4547 | 4555 | ||
| 4556 | DEFUN ("set-frame-size-and-position-pixelwise", Fset_frame_size_and_position_pixelwise, | ||
| 4557 | Sset_frame_size_and_position_pixelwise, 5, 6, 0, | ||
| 4558 | doc: /* Set FRAME's size to WIDTH and HEIGHT and its position to (X, Y). | ||
| 4559 | FRAME must be a live frame and defaults to the selected one. | ||
| 4560 | |||
| 4561 | WIDTH and HEIGHT must be positive integers and specify the new pixel | ||
| 4562 | width and height of FRAME's text area in pixels. If WIDTH or HEIGHT do | ||
| 4563 | not secify a value that is a multiple of FRAME's character sizes, you | ||
| 4564 | may have to set `frame-resize-pixelwise' to a non-nil value in order to | ||
| 4565 | get the exact size in pixels. | ||
| 4566 | |||
| 4567 | X and Y specify the coordinates of the left and top edge of FRAME's | ||
| 4568 | outer frame in pixels relative to an origin (0, 0) of FRAME's display or | ||
| 4569 | parent frame. Negative values mean the top or left edge may be outside | ||
| 4570 | the display or parent frame. | ||
| 4571 | |||
| 4572 | GRAVITY specifies the new gravity of FRAME and must be a value in the | ||
| 4573 | range 0..10. It defaults to 1. | ||
| 4574 | |||
| 4575 | This function uses any existing backend of the toolkit to resize and | ||
| 4576 | move FRAME in one compound step. If the backend does not provide such a | ||
| 4577 | function, it calls `set-frame-size' followed by `set-frame-position' | ||
| 4578 | instead. See 'set-frame-size-and-position'. */) | ||
| 4579 | (Lisp_Object frame, Lisp_Object width, Lisp_Object height, | ||
| 4580 | Lisp_Object x, Lisp_Object y, Lisp_Object gravity) | ||
| 4581 | { | ||
| 4582 | struct frame *f = decode_live_frame (frame); | ||
| 4583 | |||
| 4584 | if (NILP (gravity)) | ||
| 4585 | f->win_gravity = 1; | ||
| 4586 | else | ||
| 4587 | f->win_gravity = check_integer_range (gravity, 0, 10); | ||
| 4588 | |||
| 4589 | if (FRAME_WINDOW_P (f) | ||
| 4590 | && FRAME_TERMINAL (f)->set_window_size_and_position_hook) | ||
| 4591 | { | ||
| 4592 | int text_width = check_integer_range (width, 1, INT_MAX); | ||
| 4593 | int text_height = check_integer_range (height, 1, INT_MAX); | ||
| 4594 | |||
| 4595 | f->left_pos = check_integer_range (x, INT_MIN, INT_MAX); | ||
| 4596 | f->top_pos = check_integer_range (y, INT_MIN, INT_MAX); | ||
| 4597 | |||
| 4598 | adjust_frame_size (f, text_width, text_height, 1, false, | ||
| 4599 | Qsize_and_position); | ||
| 4600 | } | ||
| 4601 | else | ||
| 4602 | { | ||
| 4603 | Fset_frame_size (frame, width, height, Qt); | ||
| 4604 | |||
| 4605 | int left_pos = check_integer_range (x, INT_MIN, INT_MAX); | ||
| 4606 | int top_pos = check_integer_range (y, INT_MIN, INT_MAX); | ||
| 4607 | |||
| 4608 | Lisp_Object left | ||
| 4609 | = Fcons (Qleft, left_pos < 0 ? list2 (Qplus, x) : x); | ||
| 4610 | Lisp_Object top | ||
| 4611 | = Fcons (Qtop, top_pos < 0 ? list2 (Qplus, y) : y); | ||
| 4612 | |||
| 4613 | Fmodify_frame_parameters (frame, list2 (left, top)); | ||
| 4614 | } | ||
| 4615 | |||
| 4616 | return Qnil; | ||
| 4617 | } | ||
| 4618 | |||
| 4548 | DEFUN ("frame-window-state-change", Fframe_window_state_change, | 4619 | DEFUN ("frame-window-state-change", Fframe_window_state_change, |
| 4549 | Sframe_window_state_change, 0, 1, 0, | 4620 | Sframe_window_state_change, 0, 1, 0, |
| 4550 | doc: /* Return t if FRAME's window state change flag is set, nil otherwise. | 4621 | doc: /* Return t if FRAME's window state change flag is set, nil otherwise. |
| @@ -7113,6 +7184,7 @@ syms_of_frame (void) | |||
| 7113 | DEFSYM (Qmin_height, "min-height"); | 7184 | DEFSYM (Qmin_height, "min-height"); |
| 7114 | DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame"); | 7185 | DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame"); |
| 7115 | DEFSYM (Qkeep_ratio, "keep-ratio"); | 7186 | DEFSYM (Qkeep_ratio, "keep-ratio"); |
| 7187 | DEFSYM (Qsize_and_position, "size-and-position"); | ||
| 7116 | DEFSYM (Qwidth_only, "width-only"); | 7188 | DEFSYM (Qwidth_only, "width-only"); |
| 7117 | DEFSYM (Qheight_only, "height-only"); | 7189 | DEFSYM (Qheight_only, "height-only"); |
| 7118 | DEFSYM (Qleft_only, "left-only"); | 7190 | DEFSYM (Qleft_only, "left-only"); |
| @@ -7593,6 +7665,7 @@ The default is \\+`inhibit' in NS builds and nil everywhere else. */); | |||
| 7593 | defsubr (&Sset_frame_size); | 7665 | defsubr (&Sset_frame_size); |
| 7594 | defsubr (&Sframe_position); | 7666 | defsubr (&Sframe_position); |
| 7595 | defsubr (&Sset_frame_position); | 7667 | defsubr (&Sset_frame_position); |
| 7668 | defsubr (&Sset_frame_size_and_position_pixelwise); | ||
| 7596 | defsubr (&Sframe_pointer_visible_p); | 7669 | defsubr (&Sframe_pointer_visible_p); |
| 7597 | defsubr (&Smouse_position_in_root_frame); | 7670 | defsubr (&Smouse_position_in_root_frame); |
| 7598 | defsubr (&Sframe__set_was_invisible); | 7671 | defsubr (&Sframe__set_was_invisible); |
diff --git a/src/gtkutil.c b/src/gtkutil.c index 7ad6c7ce8c4..9eaf4723bb0 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c | |||
| @@ -1384,6 +1384,67 @@ xg_height_or_width_changed (struct frame *f) | |||
| 1384 | } | 1384 | } |
| 1385 | #endif | 1385 | #endif |
| 1386 | 1386 | ||
| 1387 | /** Move and resize the outer window of frame F. WIDTH and HEIGHT are | ||
| 1388 | the new native pixel sizes of F. */ | ||
| 1389 | void | ||
| 1390 | xg_frame_set_size_and_position (struct frame *f, int width, int height) | ||
| 1391 | { | ||
| 1392 | int outer_height | ||
| 1393 | = height + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); | ||
| 1394 | int outer_width = width + FRAME_TOOLBAR_WIDTH (f); | ||
| 1395 | int scale = xg_get_scale (f); | ||
| 1396 | int x = f->left_pos; | ||
| 1397 | int y = f->top_pos; | ||
| 1398 | GdkWindow *gwin = NULL; | ||
| 1399 | int flags = 0; | ||
| 1400 | |||
| 1401 | if (FRAME_GTK_OUTER_WIDGET (f)) | ||
| 1402 | gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)); | ||
| 1403 | else | ||
| 1404 | gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); | ||
| 1405 | |||
| 1406 | outer_height /= scale; | ||
| 1407 | outer_width /= scale; | ||
| 1408 | |||
| 1409 | /* Full force ahead. For top-level frames the gravity will get reset | ||
| 1410 | to NorthWestGravity anyway. */ | ||
| 1411 | flags |= USSize; | ||
| 1412 | if (f->win_gravity == 3 || f->win_gravity == 9) | ||
| 1413 | flags |= XNegative; | ||
| 1414 | if (f->win_gravity == 6 || f->win_gravity == 9) | ||
| 1415 | flags |= YNegative; | ||
| 1416 | flags |= USPosition; | ||
| 1417 | |||
| 1418 | xg_wm_set_size_hint (f, flags, true); | ||
| 1419 | |||
| 1420 | #ifndef HAVE_PGTK | ||
| 1421 | gdk_window_move_resize (gwin, x, y, outer_width, outer_height); | ||
| 1422 | #else | ||
| 1423 | if (FRAME_GTK_OUTER_WIDGET (f)) | ||
| 1424 | gdk_window_move_resize (gwin, x, y, outer_width, outer_height); | ||
| 1425 | else | ||
| 1426 | gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), | ||
| 1427 | outer_width, outer_height); | ||
| 1428 | #endif | ||
| 1429 | |||
| 1430 | SET_FRAME_GARBAGED (f); | ||
| 1431 | cancel_mouse_face (f); | ||
| 1432 | |||
| 1433 | if (FRAME_VISIBLE_P (f)) | ||
| 1434 | { | ||
| 1435 | /* Must call this to flush out events */ | ||
| 1436 | (void)gtk_events_pending (); | ||
| 1437 | gdk_flush (); | ||
| 1438 | #ifndef HAVE_PGTK | ||
| 1439 | x_wait_for_event (f, ConfigureNotify); | ||
| 1440 | #endif | ||
| 1441 | } | ||
| 1442 | else | ||
| 1443 | adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), | ||
| 1444 | FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), | ||
| 1445 | 5, 0, Qxg_frame_set_char_size); | ||
| 1446 | } | ||
| 1447 | |||
| 1387 | #ifndef HAVE_PGTK | 1448 | #ifndef HAVE_PGTK |
| 1388 | /* Convert an X Window WSESC on display DPY to its corresponding GtkWidget. | 1449 | /* Convert an X Window WSESC on display DPY to its corresponding GtkWidget. |
| 1389 | Must be done like this, because GtkWidget:s can have "hidden" | 1450 | Must be done like this, because GtkWidget:s can have "hidden" |
| @@ -2041,28 +2102,33 @@ xg_wm_set_size_hint (struct frame *f, long int flags, bool user_position) | |||
| 2041 | 2102 | ||
| 2042 | /* These currently have a one to one mapping with the X values, but I | 2103 | /* These currently have a one to one mapping with the X values, but I |
| 2043 | don't think we should rely on that. */ | 2104 | don't think we should rely on that. */ |
| 2044 | hint_flags |= GDK_HINT_WIN_GRAVITY; | 2105 | if (FRAME_PARENT_FRAME (f)) |
| 2045 | size_hints.win_gravity = 0; | 2106 | { |
| 2046 | if (win_gravity == NorthWestGravity) | 2107 | hint_flags |= GDK_HINT_WIN_GRAVITY; |
| 2108 | size_hints.win_gravity = 0; | ||
| 2109 | if (win_gravity == NorthWestGravity) | ||
| 2110 | size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST; | ||
| 2111 | else if (win_gravity == NorthGravity) | ||
| 2112 | size_hints.win_gravity = GDK_GRAVITY_NORTH; | ||
| 2113 | else if (win_gravity == NorthEastGravity) | ||
| 2114 | size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST; | ||
| 2115 | else if (win_gravity == WestGravity) | ||
| 2116 | size_hints.win_gravity = GDK_GRAVITY_WEST; | ||
| 2117 | else if (win_gravity == CenterGravity) | ||
| 2118 | size_hints.win_gravity = GDK_GRAVITY_CENTER; | ||
| 2119 | else if (win_gravity == EastGravity) | ||
| 2120 | size_hints.win_gravity = GDK_GRAVITY_EAST; | ||
| 2121 | else if (win_gravity == SouthWestGravity) | ||
| 2122 | size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST; | ||
| 2123 | else if (win_gravity == SouthGravity) | ||
| 2124 | size_hints.win_gravity = GDK_GRAVITY_SOUTH; | ||
| 2125 | else if (win_gravity == SouthEastGravity) | ||
| 2126 | size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST; | ||
| 2127 | else if (win_gravity == StaticGravity) | ||
| 2128 | size_hints.win_gravity = GDK_GRAVITY_STATIC; | ||
| 2129 | } | ||
| 2130 | else | ||
| 2047 | size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST; | 2131 | size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST; |
| 2048 | else if (win_gravity == NorthGravity) | ||
| 2049 | size_hints.win_gravity = GDK_GRAVITY_NORTH; | ||
| 2050 | else if (win_gravity == NorthEastGravity) | ||
| 2051 | size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST; | ||
| 2052 | else if (win_gravity == WestGravity) | ||
| 2053 | size_hints.win_gravity = GDK_GRAVITY_WEST; | ||
| 2054 | else if (win_gravity == CenterGravity) | ||
| 2055 | size_hints.win_gravity = GDK_GRAVITY_CENTER; | ||
| 2056 | else if (win_gravity == EastGravity) | ||
| 2057 | size_hints.win_gravity = GDK_GRAVITY_EAST; | ||
| 2058 | else if (win_gravity == SouthWestGravity) | ||
| 2059 | size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST; | ||
| 2060 | else if (win_gravity == SouthGravity) | ||
| 2061 | size_hints.win_gravity = GDK_GRAVITY_SOUTH; | ||
| 2062 | else if (win_gravity == SouthEastGravity) | ||
| 2063 | size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST; | ||
| 2064 | else if (win_gravity == StaticGravity) | ||
| 2065 | size_hints.win_gravity = GDK_GRAVITY_STATIC; | ||
| 2066 | 2132 | ||
| 2067 | if (flags & PPosition) | 2133 | if (flags & PPosition) |
| 2068 | hint_flags |= GDK_HINT_POS; | 2134 | hint_flags |= GDK_HINT_POS; |
diff --git a/src/gtkutil.h b/src/gtkutil.h index e6c1e19c765..849315a826a 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h | |||
| @@ -163,6 +163,8 @@ extern void xg_frame_resized (struct frame *f, | |||
| 163 | int pixelwidth, | 163 | int pixelwidth, |
| 164 | int pixelheight); | 164 | int pixelheight); |
| 165 | extern void xg_frame_set_char_size (struct frame *f, int width, int height); | 165 | extern void xg_frame_set_char_size (struct frame *f, int width, int height); |
| 166 | extern void xg_frame_set_size_and_position (struct frame *f, int width, | ||
| 167 | int height); | ||
| 166 | extern GtkWidget * xg_win_to_widget (Display *dpy, Window wdesc); | 168 | extern GtkWidget * xg_win_to_widget (Display *dpy, Window wdesc); |
| 167 | 169 | ||
| 168 | extern int xg_get_scale (struct frame *f); | 170 | extern int xg_get_scale (struct frame *f); |
diff --git a/src/termhooks.h b/src/termhooks.h index e688ed40c0f..5e861051498 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -684,6 +684,11 @@ struct terminal | |||
| 684 | void (*set_window_size_hook) (struct frame *f, bool change_gravity, | 684 | void (*set_window_size_hook) (struct frame *f, bool change_gravity, |
| 685 | int width, int height); | 685 | int width, int height); |
| 686 | 686 | ||
| 687 | /* This hook is called to change the size and position of frame F's | ||
| 688 | native (underlying) window. */ | ||
| 689 | void (*set_window_size_and_position_hook) (struct frame *f, int width, | ||
| 690 | int height); | ||
| 691 | |||
| 687 | /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, | 692 | /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, |
| 688 | to really change the position, and 0 when calling from | 693 | to really change the position, and 0 when calling from |
| 689 | *_make_frame_visible (in that case, XOFF and YOFF are the current | 694 | *_make_frame_visible (in that case, XOFF and YOFF are the current |
diff --git a/src/w32term.c b/src/w32term.c index 9387cc3e7b7..80b072d6b5d 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -7237,6 +7237,85 @@ w32_set_window_size (struct frame *f, bool change_gravity, | |||
| 7237 | 7237 | ||
| 7238 | do_pending_window_change (false); | 7238 | do_pending_window_change (false); |
| 7239 | } | 7239 | } |
| 7240 | |||
| 7241 | /* Change the size of frame F's Windows window to WIDTH and HEIGHT | ||
| 7242 | pixels and its position to those stored in f->left_pos and | ||
| 7243 | f->top_pos. */ | ||
| 7244 | static void | ||
| 7245 | w32_set_window_size_and_position (struct frame *f, int width, int height) | ||
| 7246 | { | ||
| 7247 | RECT rect; | ||
| 7248 | MENUBARINFO info; | ||
| 7249 | int menu_bar_height; | ||
| 7250 | |||
| 7251 | block_input (); | ||
| 7252 | |||
| 7253 | /* Get the height of the menu bar here. It's used below to detect | ||
| 7254 | whether the menu bar is wrapped. It's also used to specify the | ||
| 7255 | third argument for AdjustWindowRect. See bug#22105. */ | ||
| 7256 | info.cbSize = sizeof (info); | ||
| 7257 | info.rcBar.top = info.rcBar.bottom = 0; | ||
| 7258 | GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info); | ||
| 7259 | menu_bar_height = info.rcBar.bottom - info.rcBar.top; | ||
| 7260 | |||
| 7261 | if (w32_add_wrapped_menu_bar_lines) | ||
| 7262 | { | ||
| 7263 | /* When the menu bar wraps sending a SetWindowPos shrinks the | ||
| 7264 | height of the frame then the wrapped menu bar lines are not | ||
| 7265 | accounted for (Bug#15174 and Bug#18720). Here we add these | ||
| 7266 | extra lines to the frame height. */ | ||
| 7267 | int default_menu_bar_height; | ||
| 7268 | |||
| 7269 | /* Why is (apparently) SM_CYMENUSIZE needed here instead of | ||
| 7270 | SM_CYMENU ?? */ | ||
| 7271 | default_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE); | ||
| 7272 | |||
| 7273 | if ((default_menu_bar_height > 0) | ||
| 7274 | && (menu_bar_height > default_menu_bar_height) | ||
| 7275 | && ((menu_bar_height % default_menu_bar_height) == 0)) | ||
| 7276 | height = height + menu_bar_height - default_menu_bar_height; | ||
| 7277 | } | ||
| 7278 | |||
| 7279 | f->win_gravity = NorthWestGravity; | ||
| 7280 | w32_wm_set_size_hint (f, (long) 0, false); | ||
| 7281 | |||
| 7282 | rect.left = f->left_pos; | ||
| 7283 | rect.top = f->top_pos; | ||
| 7284 | rect.right = rect.left + width; | ||
| 7285 | rect.bottom = rect.top + height; | ||
| 7286 | |||
| 7287 | AdjustWindowRect (&rect, f->output_data.w32->dwStyle, menu_bar_height > 0); | ||
| 7288 | |||
| 7289 | if (!FRAME_PARENT_FRAME (f)) | ||
| 7290 | my_set_window_pos (FRAME_W32_WINDOW (f), NULL, | ||
| 7291 | f->left_pos, f->top_pos, | ||
| 7292 | rect.right - rect.left, | ||
| 7293 | rect.bottom - rect.top, | ||
| 7294 | SWP_NOZORDER | SWP_NOACTIVATE); | ||
| 7295 | else | ||
| 7296 | my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP, | ||
| 7297 | f->left_pos, f->top_pos, | ||
| 7298 | rect.right - rect.left, | ||
| 7299 | rect.bottom - rect.top, | ||
| 7300 | SWP_NOACTIVATE); | ||
| 7301 | |||
| 7302 | change_frame_size (f, width, height, false, true, false); | ||
| 7303 | SET_FRAME_GARBAGED (f); | ||
| 7304 | |||
| 7305 | /* If cursor was outside the new size, mark it as off. */ | ||
| 7306 | mark_window_cursors_off (XWINDOW (f->root_window)); | ||
| 7307 | |||
| 7308 | /* Clear out any recollection of where the mouse highlighting was, | ||
| 7309 | since it might be in a place that's outside the new frame size. | ||
| 7310 | Actually checking whether it is outside is a pain in the neck, | ||
| 7311 | so don't try--just let the highlighting be done afresh with new | ||
| 7312 | size. */ | ||
| 7313 | cancel_mouse_face (f); | ||
| 7314 | |||
| 7315 | unblock_input (); | ||
| 7316 | |||
| 7317 | do_pending_window_change (false); | ||
| 7318 | } | ||
| 7240 | 7319 | ||
| 7241 | /* Mouse warping. */ | 7320 | /* Mouse warping. */ |
| 7242 | 7321 | ||
| @@ -7891,6 +7970,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo) | |||
| 7891 | terminal->fullscreen_hook = w32fullscreen_hook; | 7970 | terminal->fullscreen_hook = w32fullscreen_hook; |
| 7892 | terminal->iconify_frame_hook = w32_iconify_frame; | 7971 | terminal->iconify_frame_hook = w32_iconify_frame; |
| 7893 | terminal->set_window_size_hook = w32_set_window_size; | 7972 | terminal->set_window_size_hook = w32_set_window_size; |
| 7973 | terminal->set_window_size_and_position_hook = w32_set_window_size_and_position; | ||
| 7894 | terminal->set_frame_offset_hook = w32_set_offset; | 7974 | terminal->set_frame_offset_hook = w32_set_offset; |
| 7895 | terminal->set_frame_alpha_hook = w32_set_frame_alpha; | 7975 | terminal->set_frame_alpha_hook = w32_set_frame_alpha; |
| 7896 | terminal->set_new_font_hook = w32_new_font; | 7976 | terminal->set_new_font_hook = w32_new_font; |
diff --git a/src/xterm.c b/src/xterm.c index 9a6131ebb7d..088eaee83c9 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -28563,6 +28563,59 @@ x_set_window_size (struct frame *f, bool change_gravity, | |||
| 28563 | do_pending_window_change (false); | 28563 | do_pending_window_change (false); |
| 28564 | } | 28564 | } |
| 28565 | 28565 | ||
| 28566 | static void | ||
| 28567 | x_set_window_size_and_position_1 (struct frame *f, int width, int height) | ||
| 28568 | { | ||
| 28569 | int x = f->left_pos; | ||
| 28570 | int y = f->top_pos; | ||
| 28571 | |||
| 28572 | x_wm_set_size_hint (f, 0, false); | ||
| 28573 | |||
| 28574 | XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), | ||
| 28575 | x, y, width, height + FRAME_MENUBAR_HEIGHT (f)); | ||
| 28576 | |||
| 28577 | SET_FRAME_GARBAGED (f); | ||
| 28578 | |||
| 28579 | if (FRAME_VISIBLE_P (f)) | ||
| 28580 | x_wait_for_event (f, ConfigureNotify); | ||
| 28581 | else | ||
| 28582 | /* Call adjust_frame_size right away as with GTK. It might be | ||
| 28583 | tempting to clear out f->new_width and f->new_height here. */ | ||
| 28584 | adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), | ||
| 28585 | FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), | ||
| 28586 | 5, 0, Qx_set_window_size_1); | ||
| 28587 | } | ||
| 28588 | |||
| 28589 | void | ||
| 28590 | x_set_window_size_and_position (struct frame *f, int width, int height) | ||
| 28591 | { | ||
| 28592 | block_input (); | ||
| 28593 | |||
| 28594 | #ifdef USE_GTK | ||
| 28595 | if (FRAME_GTK_WIDGET (f)) | ||
| 28596 | xg_frame_set_size_and_position (f, width, height); | ||
| 28597 | else | ||
| 28598 | x_set_window_size_and_position_1 (f, width, height); | ||
| 28599 | #else /* not USE_GTK */ | ||
| 28600 | x_set_window_size_and_position_1 (f, width, height); | ||
| 28601 | #endif /* USE_GTK */ | ||
| 28602 | |||
| 28603 | x_clear_under_internal_border (f); | ||
| 28604 | |||
| 28605 | /* If cursor was outside the new size, mark it as off. */ | ||
| 28606 | mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); | ||
| 28607 | |||
| 28608 | /* Clear out any recollection of where the mouse highlighting was, | ||
| 28609 | since it might be in a place that's outside the new frame size. | ||
| 28610 | Actually checking whether it is outside is a pain in the neck, | ||
| 28611 | so don't try--just let the highlighting be done afresh with new size. */ | ||
| 28612 | cancel_mouse_face (f); | ||
| 28613 | |||
| 28614 | unblock_input (); | ||
| 28615 | |||
| 28616 | do_pending_window_change (false); | ||
| 28617 | } | ||
| 28618 | |||
| 28566 | /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */ | 28619 | /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */ |
| 28567 | 28620 | ||
| 28568 | void | 28621 | void |
| @@ -32148,6 +32201,7 @@ x_create_terminal (struct x_display_info *dpyinfo) | |||
| 32148 | terminal->fullscreen_hook = XTfullscreen_hook; | 32201 | terminal->fullscreen_hook = XTfullscreen_hook; |
| 32149 | terminal->iconify_frame_hook = x_iconify_frame; | 32202 | terminal->iconify_frame_hook = x_iconify_frame; |
| 32150 | terminal->set_window_size_hook = x_set_window_size; | 32203 | terminal->set_window_size_hook = x_set_window_size; |
| 32204 | terminal->set_window_size_and_position_hook = x_set_window_size_and_position; | ||
| 32151 | terminal->set_frame_offset_hook = x_set_offset; | 32205 | terminal->set_frame_offset_hook = x_set_offset; |
| 32152 | terminal->set_frame_alpha_hook = x_set_frame_alpha; | 32206 | terminal->set_frame_alpha_hook = x_set_frame_alpha; |
| 32153 | terminal->set_new_font_hook = x_new_font; | 32207 | terminal->set_new_font_hook = x_new_font; |
diff --git a/src/xterm.h b/src/xterm.h index 661f6ae78b7..199fcd2edf0 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1766,6 +1766,7 @@ extern void x_ignore_errors_for_next_request (struct x_display_info *, | |||
| 1766 | extern void x_stop_ignoring_errors (struct x_display_info *); | 1766 | extern void x_stop_ignoring_errors (struct x_display_info *); |
| 1767 | extern void x_clear_errors (Display *); | 1767 | extern void x_clear_errors (Display *); |
| 1768 | extern void x_set_window_size (struct frame *, bool, int, int); | 1768 | extern void x_set_window_size (struct frame *, bool, int, int); |
| 1769 | extern void x_set_window_size_and_position (struct frame *, int, int); | ||
| 1769 | extern void x_set_last_user_time_from_lisp (struct x_display_info *, Time); | 1770 | extern void x_set_last_user_time_from_lisp (struct x_display_info *, Time); |
| 1770 | extern void x_make_frame_visible (struct frame *); | 1771 | extern void x_make_frame_visible (struct frame *); |
| 1771 | extern void x_make_frame_invisible (struct frame *); | 1772 | extern void x_make_frame_invisible (struct frame *); |