Compute frame workareas on Haiku

* lisp/frame.el (display-monitor-attributes-list): Implement
specially on Haiku as well.
* src/haiku_support.cc (get_zoom_rect): New function.  Extract
CalculateZoomRect here.
(class EmacsWindow, SetFullscreen): Use that instead of
CalculateZoomRect.
(be_get_explicit_workarea): New function.
* src/haiku_support.h: Update prototypes.
* src/haikufns.c (Fhaiku_display_monitor_attributes_list): New
function.
(syms_of_haikufns): Register new subr.
This commit is contained in:
Po Lu 2022-05-21 06:28:06 +00:00
parent b7b14e9203
commit 3e3fe06307
4 changed files with 155 additions and 72 deletions

View file

@ -2376,6 +2376,8 @@ If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(&optional terminal))
(declare-function pgtk-display-monitor-attributes-list "pgtkfns.c"
(&optional terminal))
(declare-function haiku-display-monitor-attributes-list "haikufns.c"
(&optional terminal))
(defun display-monitor-attributes-list (&optional display)
"Return a list of physical monitor attributes on DISPLAY.
@ -2427,6 +2429,8 @@ monitors."
(ns-display-monitor-attributes-list display))
((eq frame-type 'pgtk)
(pgtk-display-monitor-attributes-list display))
((eq frame-type 'haiku)
(haiku-display-monitor-attributes-list display))
(t
(let ((geometry (list 0 0 (display-pixel-width display)
(display-pixel-height display))))

View file

@ -449,6 +449,80 @@ map_normal (uint32_t kc, uint32_t *ch)
key_map_lock.Unlock ();
}
static BRect
get_zoom_rect (BWindow *window)
{
BScreen screen;
BDeskbar deskbar;
BRect screen_frame;
BRect frame;
BRect deskbar_frame;
BRect window_frame;
BRect decorator_frame;
if (!screen.IsValid ())
gui_abort ("Failed to calculate screen rect");
screen_frame = frame = screen.Frame ();
deskbar_frame = deskbar.Frame ();
if (!(modifiers () & B_SHIFT_KEY) && !deskbar.IsAutoHide ())
{
switch (deskbar.Location ())
{
case B_DESKBAR_TOP:
frame.top = deskbar_frame.bottom + 2;
break;
case B_DESKBAR_BOTTOM:
case B_DESKBAR_LEFT_BOTTOM:
case B_DESKBAR_RIGHT_BOTTOM:
frame.bottom = deskbar_frame.top - 2;
break;
case B_DESKBAR_LEFT_TOP:
if (!deskbar.IsExpanded ())
frame.top = deskbar_frame.bottom + 2;
else if (!deskbar.IsAlwaysOnTop ()
&& !deskbar.IsAutoRaise ())
frame.left = deskbar_frame.right + 2;
break;
default:
if (deskbar.IsExpanded ()
&& !deskbar.IsAlwaysOnTop ()
&& !deskbar.IsAutoRaise ())
frame.right = deskbar_frame.left - 2;
}
}
if (window)
{
window_frame = window->Frame ();
decorator_frame = window->DecoratorFrame ();
frame.top += (window_frame.top
- decorator_frame.top);
frame.bottom -= (decorator_frame.bottom
- window_frame.bottom);
frame.left += (window_frame.left
- decorator_frame.left);
frame.right -= (decorator_frame.right
- window_frame.right);
if (frame.top > deskbar_frame.bottom
|| frame.bottom < deskbar_frame.top)
{
frame.left = screen_frame.left + (window_frame.left
- decorator_frame.left);
frame.right = screen_frame.right - (decorator_frame.right
- window_frame.right);
}
}
return frame;
}
class Emacs : public BApplication
{
public:
@ -593,77 +667,6 @@ class EmacsWindow : public BWindow
SetFeel (B_NORMAL_WINDOW_FEEL);
}
BRect
CalculateZoomRect (void)
{
BScreen screen (this);
BDeskbar deskbar;
BRect screen_frame;
BRect frame;
BRect deskbar_frame;
BRect window_frame;
BRect decorator_frame;
if (!screen.IsValid ())
gui_abort ("Failed to calculate screen rect");
screen_frame = frame = screen.Frame ();
deskbar_frame = deskbar.Frame ();
if (!(modifiers () & B_SHIFT_KEY) && !deskbar.IsAutoHide ())
{
switch (deskbar.Location ())
{
case B_DESKBAR_TOP:
frame.top = deskbar_frame.bottom + 2;
break;
case B_DESKBAR_BOTTOM:
case B_DESKBAR_LEFT_BOTTOM:
case B_DESKBAR_RIGHT_BOTTOM:
frame.bottom = deskbar_frame.top - 2;
break;
case B_DESKBAR_LEFT_TOP:
if (!deskbar.IsExpanded ())
frame.top = deskbar_frame.bottom + 2;
else if (!deskbar.IsAlwaysOnTop ()
&& !deskbar.IsAutoRaise ())
frame.left = deskbar_frame.right + 2;
break;
default:
if (deskbar.IsExpanded ()
&& !deskbar.IsAlwaysOnTop ()
&& !deskbar.IsAutoRaise ())
frame.right = deskbar_frame.left - 2;
}
}
window_frame = Frame ();
decorator_frame = DecoratorFrame ();
frame.top += (window_frame.top
- decorator_frame.top);
frame.bottom -= (decorator_frame.bottom
- window_frame.bottom);
frame.left += (window_frame.left
- decorator_frame.left);
frame.right -= (decorator_frame.right
- window_frame.right);
if (frame.top > deskbar_frame.bottom
|| frame.bottom < deskbar_frame.top)
{
frame.left = screen_frame.left + (window_frame.left
- decorator_frame.left);
frame.right = screen_frame.right - (decorator_frame.right
- window_frame.right);
}
return frame;
}
void
UpwardsSubset (EmacsWindow *w)
{
@ -1248,7 +1251,7 @@ class EmacsWindow : public BWindow
{
case FULLSCREEN_MODE_MAXIMIZED:
pre_zoom_rect = frame;
zoom_rect = CalculateZoomRect ();
zoom_rect = get_zoom_rect (this);
BWindow::Zoom (zoom_rect.LeftTop (),
BE_RECT_WIDTH (zoom_rect) - 1,
BE_RECT_HEIGHT (zoom_rect) - 1);
@ -5210,3 +5213,26 @@ be_set_window_fullscreen_mode (void *window, enum haiku_fullscreen_mode mode)
w->SetFullscreen (mode);
w->UnlockLooper ();
}
bool
be_get_explicit_workarea (int *x, int *y, int *width, int *height)
{
BDeskbar deskbar;
BRect zoom;
deskbar_location location;
location = deskbar.Location ();
if (location != B_DESKBAR_TOP
&& location != B_DESKBAR_BOTTOM)
return false;
zoom = get_zoom_rect (NULL);
*x = zoom.left;
*y = zoom.top;
*width = BE_RECT_WIDTH (zoom);
*height = BE_RECT_HEIGHT (zoom);
return true;
}

View file

@ -702,6 +702,7 @@ extern void be_set_window_fullscreen_mode (void *, enum haiku_fullscreen_mode);
extern void be_lock_window (void *);
extern void be_unlock_window (void *);
extern bool be_get_explicit_workarea (int *, int *, int *, int *);
#ifdef __cplusplus
}

View file

@ -3021,6 +3021,57 @@ call this function yourself. */)
return Qnil;
}
DEFUN ("haiku-display-monitor-attributes-list",
Fhaiku_display_monitor_attributes_list,
Shaiku_display_monitor_attributes_list,
0, 1, 0,
doc: /* Return a list of physical monitor attributes on the display TERMINAL.
The optional argument TERMINAL specifies which display to ask about.
TERMINAL should be a terminal object, a frame or a display name (a string).
If omitted or nil, that stands for the selected frame's display.
Internal use only, use `display-monitor-attributes-list' instead. */)
(Lisp_Object terminal)
{
struct MonitorInfo monitor;
struct haiku_display_info *dpyinfo;
Lisp_Object frames, tail, tem;
dpyinfo = check_haiku_display_info (terminal);
frames = Qnil;
FOR_EACH_FRAME (tail, tem)
{
maybe_quit ();
if (FRAME_HAIKU_P (XFRAME (tem))
&& !FRAME_TOOLTIP_P (XFRAME (tem)))
frames = Fcons (tem, frames);
}
monitor.geom.x = 0;
monitor.geom.y = 0;
be_get_screen_dimensions ((int *) &monitor.geom.width,
(int *) &monitor.geom.height);
monitor.mm_width = (monitor.geom.width
/ (dpyinfo->resx / 25.4));
monitor.mm_height = (monitor.geom.height
/ (dpyinfo->resy / 25.4));
monitor.name = (char *) "BeOS monitor";
if (!be_get_explicit_workarea ((int *) &monitor.work.x,
(int *) &monitor.work.y,
(int *) &monitor.work.width,
(int *) &monitor.work.height))
monitor.work = monitor.geom;
return make_monitor_attribute_list (&monitor, 1, 0,
make_vector (1, frames),
"fallback");
}
frame_parm_handler haiku_frame_parm_handlers[] =
{
gui_set_autoraise,
@ -3126,6 +3177,7 @@ syms_of_haikufns (void)
defsubr (&Sx_display_save_under);
defsubr (&Shaiku_frame_restack);
defsubr (&Shaiku_save_session_reply);
defsubr (&Shaiku_display_monitor_attributes_list);
tip_timer = Qnil;
staticpro (&tip_timer);