1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 20:32:00 -08:00

Fix race conditions processing frame fullscreen state on Haiku

* doc/lispref/frames.texi (Size Parameters): Remove note saying
Haiku doesn't support `fullwidth' and `fullboth'.

* src/haiku_support.cc (subset_windows, class EmacsWindow)
(Unparent, ParentTo): Stop calling old fullscreen functions.
(ClearFullscreen, FullscreenRectForMode, SetFullscreen): New
functions.  Completely rewrite old zoom and fullscreen handling
code.
(Zoom): Send a ZOOM_EVENT and don't actually zoom.
(BWindow_zoom, EmacsWindow_make_fullscreen, EmacsWindow_unzoom):
Delete functions.
(be_set_window_fullscreen_mode): New function.

* src/haiku_support.h (struct haiku_zoom_event): Remove
`zoomed_p' parameter.
(enum haiku_fullscreen_mode): New enum.  Update prototypes.

* src/haikufns.c (Fx_display_pixel_height): Return height
instead of width.

* src/haikuterm.c (haiku_make_fullscreen_consistent)
(haiku_read_socket, haiku_fullscreen): Adjust to always set zoom
and fullscreen in the main thread instead of the UI threads.

* src/haikuterm.h (struct haiku_output): Remove flag `zoomed_p'
and add field `fullscreen_mode'.
This commit is contained in:
Po Lu 2022-05-19 03:43:39 +00:00
parent bc604417f8
commit 4dfaefcffc
6 changed files with 183 additions and 147 deletions

View file

@ -1734,16 +1734,14 @@ fit will be clipped by the window manager.
@item fullscreen
This parameter specifies whether to maximize the frame's width, height
or both. Its value can be @code{fullwidth}, @code{fullheight},
@code{fullboth}, or @code{maximized}.@footnote{On Haiku, setting
@code{fullscreen} to @code{fullwidth} or @code{fullheight} has no
effect.} A @dfn{fullwidth} frame is as
@code{fullboth}, or @code{maximized}. A @dfn{fullwidth} frame is as
wide as possible, a @dfn{fullheight} frame is as tall as possible, and
a @dfn{fullboth} frame is both as wide and as tall as possible. A
@dfn{maximized} frame is like a ``fullboth'' frame, except that it usually
keeps its title bar and the buttons for resizing
and closing the frame. Also, maximized frames typically avoid hiding
any task bar or panels displayed on the desktop. A ``fullboth'' frame,
on the other hand, usually omits the title bar and occupies the entire
@dfn{maximized} frame is like a ``fullboth'' frame, except that it
usually keeps its title bar and the buttons for resizing and closing
the frame. Also, maximized frames typically avoid hiding any task bar
or panels displayed on the desktop. A ``fullboth'' frame, on the
other hand, usually omits the title bar and occupies the entire
available screen space.
Full-height and full-width frames are more similar to maximized

View file

@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <attribute.h>
#include <app/Application.h>
#include <app/Cursor.h>
@ -518,33 +519,42 @@ public:
struct child_frame *next;
int xoff, yoff;
EmacsWindow *window;
} *subset_windows = NULL;
} *subset_windows;
EmacsWindow *parent = NULL;
EmacsWindow *parent;
BRect pre_fullscreen_rect;
BRect pre_zoom_rect;
int x_before_zoom = INT_MIN;
int y_before_zoom = INT_MIN;
bool fullscreen_p = false;
bool zoomed_p = false;
bool shown_flag = false;
volatile int was_shown_p = 0;
bool menu_bar_active_p = false;
bool override_redirect_p = false;
int x_before_zoom;
int y_before_zoom;
bool shown_flag;
volatile bool was_shown_p;
bool menu_bar_active_p;
bool override_redirect_p;
window_look pre_override_redirect_look;
window_feel pre_override_redirect_feel;
uint32 pre_override_redirect_workspaces;
int window_id;
bool *menus_begun = NULL;
bool *menus_begun;
enum haiku_z_group z_group;
bool tooltip_p = false;
bool tooltip_p;
enum haiku_fullscreen_mode fullscreen_mode;
EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK,
B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS)
B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS),
subset_windows (NULL),
parent (NULL),
x_before_zoom (INT_MIN),
y_before_zoom (INT_MIN),
shown_flag (false),
was_shown_p (false),
menu_bar_active_p (false),
override_redirect_p (false),
window_id (current_window_id),
menus_begun (NULL),
z_group (Z_GROUP_NONE),
tooltip_p (false),
fullscreen_mode (FULLSCREEN_MODE_NONE)
{
window_id = current_window_id++;
z_group = Z_GROUP_NONE;
/* This pulse rate is used by scroll bars for repeating a button
action while a button is held down. */
SetPulseRate (30000);
@ -711,12 +721,6 @@ public:
RecomputeFeel ();
UpwardsUnSubsetChildren (parent);
this->RemoveFromSubset (this);
if (fullscreen_p)
{
fullscreen_p = 0;
MakeFullscreen (1);
}
child_frame_lock.Unlock ();
}
@ -766,11 +770,6 @@ public:
this->AddToSubset (this);
if (!IsHidden () && this->parent)
UpwardsSubsetChildren (parent);
if (fullscreen_p)
{
fullscreen_p = 0;
MakeFullscreen (1);
}
window->LinkChild (this);
child_frame_lock.Unlock ();
@ -1161,41 +1160,103 @@ public:
}
void
Zoom (BPoint o, float w, float h)
ClearFullscreen (void)
{
struct haiku_zoom_event rq;
BRect rect;
rq.window = this;
if (fullscreen_p)
MakeFullscreen (0);
if (!zoomed_p)
switch (fullscreen_mode)
{
pre_zoom_rect = Frame ();
zoomed_p = true;
rect = CalculateZoomRect ();
}
else
{
zoomed_p = false;
rect = pre_zoom_rect;
case FULLSCREEN_MODE_MAXIMIZED:
BWindow::Zoom (pre_zoom_rect.LeftTop (),
BE_RECT_WIDTH (pre_zoom_rect) - 1,
BE_RECT_HEIGHT (pre_zoom_rect) - 1);
break;
case FULLSCREEN_MODE_BOTH:
case FULLSCREEN_MODE_HEIGHT:
case FULLSCREEN_MODE_WIDTH:
MoveTo (pre_fullscreen_rect.LeftTop ());
ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1,
BE_RECT_HEIGHT (pre_fullscreen_rect) - 1);
SetFlags (Flags () & ~(B_NOT_MOVABLE
| B_NOT_ZOOMABLE
| B_NOT_RESIZABLE));
break;
case FULLSCREEN_MODE_NONE:
break;
}
rq.zoomed = zoomed_p;
haiku_write (ZOOM_EVENT, &rq);
fullscreen_mode = FULLSCREEN_MODE_NONE;
}
BWindow::Zoom (rect.LeftTop (), BE_RECT_WIDTH (rect) - 1,
BE_RECT_HEIGHT (rect) - 1);
BRect
FullscreenRectForMode (enum haiku_fullscreen_mode mode)
{
BScreen screen (this);
BRect frame;
if (!screen.IsValid ())
return BRect (0, 0, 0, 0);
frame = screen.Frame ();
if (mode == FULLSCREEN_MODE_HEIGHT)
frame.right -= BE_RECT_WIDTH (frame) / 2;
else if (mode == FULLSCREEN_MODE_WIDTH)
frame.bottom -= BE_RECT_HEIGHT (frame) / 2;
return frame;
}
void
UnZoom (void)
SetFullscreen (enum haiku_fullscreen_mode mode)
{
if (!zoomed_p)
BRect zoom_rect;
if (fullscreen_mode == mode)
return;
BWindow::Zoom ();
ClearFullscreen ();
switch (mode)
{
case FULLSCREEN_MODE_MAXIMIZED:
pre_zoom_rect = Frame ();
zoom_rect = CalculateZoomRect ();
BWindow::Zoom (zoom_rect.LeftTop (),
BE_RECT_WIDTH (zoom_rect) - 1,
BE_RECT_HEIGHT (zoom_rect) - 1);
break;
case FULLSCREEN_MODE_BOTH:
SetFlags (Flags () | B_NOT_MOVABLE);
FALLTHROUGH;
case FULLSCREEN_MODE_HEIGHT:
case FULLSCREEN_MODE_WIDTH:
SetFlags (Flags () | B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
pre_fullscreen_rect = Frame ();
zoom_rect = FullscreenRectForMode (mode);
ResizeTo (BE_RECT_WIDTH (zoom_rect) - 1,
BE_RECT_HEIGHT (zoom_rect) - 1);
MoveTo (zoom_rect.left, zoom_rect.top);
break;
case FULLSCREEN_MODE_NONE:
break;
}
fullscreen_mode = mode;
}
void
Zoom (BPoint o, float w, float h)
{
struct haiku_zoom_event rq;
rq.window = this;
haiku_write (ZOOM_EVENT, &rq);
}
void
@ -1218,51 +1279,6 @@ public:
child_frame_lock.Lock ();
gui_abort ("Trying to calculate offsets for a child frame that doesn't exist");
}
void
MakeFullscreen (int make_fullscreen_p)
{
BScreen screen (this);
uint32 flags;
BRect screen_frame;
if (!screen.IsValid ())
gui_abort ("Trying to make a window fullscreen without a screen");
screen_frame = screen.Frame ();
UnZoom ();
if (make_fullscreen_p == fullscreen_p)
return;
fullscreen_p = make_fullscreen_p;
flags = Flags ();
if (fullscreen_p)
{
if (zoomed_p)
UnZoom ();
flags |= B_NOT_MOVABLE | B_NOT_ZOOMABLE;
pre_fullscreen_rect = Frame ();
MoveTo (0, 0);
ResizeTo (BE_RECT_WIDTH (screen_frame) - 1,
BE_RECT_HEIGHT (screen_frame) - 1);
}
else
{
flags &= ~(B_NOT_MOVABLE | B_NOT_ZOOMABLE);
/* Use MoveTo directly since pre_fullscreen_rect isn't
adjusted for decorator sizes. */
MoveTo (pre_fullscreen_rect.left,
pre_fullscreen_rect.top);
ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect) - 1,
BE_RECT_HEIGHT (pre_fullscreen_rect) - 1);
}
SetFlags (flags);
}
};
class EmacsMenuBar : public BMenuBar
@ -4486,30 +4502,6 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p,
return file_name;
}
/* Zoom WINDOW. */
void
BWindow_zoom (void *window)
{
BWindow *w = (BWindow *) window;
w->Zoom ();
}
/* Make WINDOW fullscreen if FULLSCREEN_P. */
void
EmacsWindow_make_fullscreen (void *window, int fullscreen_p)
{
EmacsWindow *w = (EmacsWindow *) window;
w->MakeFullscreen (fullscreen_p);
}
/* Unzoom (maximize) WINDOW. */
void
EmacsWindow_unzoom (void *window)
{
EmacsWindow *w = (EmacsWindow *) window;
w->UnZoom ();
}
/* Move the pointer into MBAR and start tracking. Return whether the
menu bar was opened correctly. */
bool
@ -5180,3 +5172,15 @@ be_unlock_window (void *window)
wnd->UnlockLooper ();
}
void
be_set_window_fullscreen_mode (void *window, enum haiku_fullscreen_mode mode)
{
EmacsWindow *w = (EmacsWindow *) window;
if (!w->LockLooper ())
gui_abort ("Failed to lock window to set fullscreen mode");
w->SetFullscreen (mode);
w->UnlockLooper ();
}

View file

@ -249,7 +249,6 @@ struct haiku_menu_bar_help_event
struct haiku_zoom_event
{
void *window;
bool zoomed;
};
enum haiku_font_specification
@ -316,6 +315,15 @@ enum haiku_font_weight
HAIKU_MEDIUM = 2000,
};
enum haiku_fullscreen_mode
{
FULLSCREEN_MODE_NONE,
FULLSCREEN_MODE_WIDTH,
FULLSCREEN_MODE_HEIGHT,
FULLSCREEN_MODE_BOTH,
FULLSCREEN_MODE_MAXIMIZED,
};
struct haiku_font_pattern
{
/* Bitmask indicating which fields are set. */
@ -495,7 +503,6 @@ extern void BWindow_center_on_screen (void *);
extern void BWindow_change_decoration (void *, int);
extern void BWindow_set_tooltip_decoration (void *);
extern void BWindow_set_avoid_focus (void *, int);
extern void BWindow_zoom (void *);
extern void BWindow_set_size_alignment (void *, int, int);
extern void BWindow_sync (void *);
extern void BWindow_send_behind (void *, void *);
@ -623,8 +630,6 @@ extern void BAlert_delete (void *);
extern void EmacsWindow_parent_to (void *, void *);
extern void EmacsWindow_unparent (void *);
extern void EmacsWindow_move_weak_child (void *, void *, int, int);
extern void EmacsWindow_make_fullscreen (void *, int);
extern void EmacsWindow_unzoom (void *);
extern void be_get_version_string (char *, int);
extern int be_get_display_planes (void);
@ -690,6 +695,7 @@ extern status_t be_roster_launch (const char *, const char *, char **,
extern void be_get_window_decorator_dimensions (void *, int *, int *, int *, int *);
extern void be_get_window_decorator_frame (void *, int *, int *, int *, int *);
extern void be_send_move_frame_event (void *);
extern void be_set_window_fullscreen_mode (void *, enum haiku_fullscreen_mode);
extern void be_lock_window (void *);
extern void be_unlock_window (void *);

View file

@ -2281,7 +2281,7 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_heigh
check_haiku_display_info (terminal);
be_get_screen_dimensions (&width, &height);
return make_fixnum (width);
return make_fixnum (height);
}
DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,

View file

@ -3018,11 +3018,20 @@ static struct redisplay_interface haiku_redisplay_interface =
static void
haiku_make_fullscreen_consistent (struct frame *f)
{
Lisp_Object lval = get_frame_param (f, Qfullscreen);
Lisp_Object lval;
struct haiku_output *output;
if (!EQ (lval, Qmaximized) && FRAME_OUTPUT_DATA (f)->zoomed_p)
output = FRAME_OUTPUT_DATA (f);
if (output->fullscreen_mode == FULLSCREEN_MODE_BOTH)
lval = Qfullboth;
else if (output->fullscreen_mode == FULLSCREEN_MODE_WIDTH)
lval = Qfullwidth;
else if (output->fullscreen_mode == FULLSCREEN_MODE_HEIGHT)
lval = Qfullheight;
else if (output->fullscreen_mode == FULLSCREEN_MODE_MAXIMIZED)
lval = Qmaximized;
else if (EQ (lval, Qmaximized) && !FRAME_OUTPUT_DATA (f)->zoomed_p)
else
lval = Qnil;
store_frame_param (f, Qfullscreen, lval);
@ -3857,14 +3866,20 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
case ZOOM_EVENT:
{
struct haiku_zoom_event *b = buf;
struct frame *f = haiku_window_to_frame (b->window);
struct haiku_output *output;
if (!f)
continue;
FRAME_OUTPUT_DATA (f)->zoomed_p = b->zoomed;
haiku_make_fullscreen_consistent (f);
output = FRAME_OUTPUT_DATA (f);
if (output->fullscreen_mode == FULLSCREEN_MAXIMIZED)
f->want_fullscreen = FULLSCREEN_NONE;
else
f->want_fullscreen = FULLSCREEN_MAXIMIZED;
FRAME_TERMINAL (f)->fullscreen_hook (f);
break;
}
case DRAG_AND_DROP_EVENT:
@ -4096,6 +4111,8 @@ haiku_toggle_invisible_pointer (struct frame *f, bool invisible_p)
static void
haiku_fullscreen (struct frame *f)
{
enum haiku_fullscreen_mode mode;
/* When FRAME_OUTPUT_DATA (f)->configury_done is false, the frame is
being created, and its regular width and height have not yet been
set. This function will be called again by haiku_create_frame,
@ -4104,18 +4121,22 @@ haiku_fullscreen (struct frame *f)
return;
if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
BWindow_zoom (FRAME_HAIKU_WINDOW (f));
mode = FULLSCREEN_MODE_MAXIMIZED;
else if (f->want_fullscreen == FULLSCREEN_BOTH)
EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 1);
mode = FULLSCREEN_MODE_BOTH;
else if (f->want_fullscreen == FULLSCREEN_WIDTH)
mode = FULLSCREEN_MODE_WIDTH;
else if (f->want_fullscreen == FULLSCREEN_HEIGHT)
mode = FULLSCREEN_MODE_HEIGHT;
else
{
EmacsWindow_make_fullscreen (FRAME_HAIKU_WINDOW (f), 0);
EmacsWindow_unzoom (FRAME_HAIKU_WINDOW (f));
}
mode = FULLSCREEN_MODE_NONE;
f->want_fullscreen = FULLSCREEN_NONE;
be_set_window_fullscreen_mode (FRAME_HAIKU_WINDOW (f), mode);
FRAME_OUTPUT_DATA (f)->fullscreen_mode = mode;
haiku_update_size_hints (f);
haiku_make_fullscreen_consistent (f);
}
static struct terminal *

View file

@ -160,13 +160,16 @@ struct haiku_output
int fontset;
int baseline_offset;
bool_bf zoomed_p : 1;
/* Whether or not the hourglass cursor is currently being
displayed. */
bool_bf hourglass_p : 1;
/* Whether or not the menu bar is open. */
bool_bf menu_bar_open_p : 1;
/* Whether or not there is data in a back buffer that hasn't been
displayed yet. */
bool dirty_p;
bool_bf dirty_p : 1;
struct font *font;
@ -201,6 +204,10 @@ struct haiku_output
and top_pos in that the decorator and parent frames are not taken
into account. */
int frame_x, frame_y;
/* The current fullscreen mode of this frame. This should be `enum
haiku_fullscreen_mode', but that isn't available here. */
int fullscreen_mode;
};
struct x_output