forked from 12to11/12to11
Send correct surface bounds to xdg_toplevel resources
* compositor.h (struct _RoleFuncs) (struct _XdgRoleImplementationFuncs): New role functions `outputs_changed'. * output.c (NoticeOutputsMaybeChanged): Call surface outputs_changed hook if it exists. (XLGetMaxOutputBounds): New function. * xdg_surface.c (OutputsChanged): New function. (XLGetXdgSurface): Add new role function. * xdg_toplevel.c (CurrentWindowGeometry): New function. (SendStates): Factor out geometry calculation to that function. (SendOutputBounds): New function. (Commit, OutputsChanged): Send output bounds whenever appropriate. (XLGetXdgToplevel): Add new impl func.
This commit is contained in:
parent
6e062e2e2f
commit
276445926e
4 changed files with 129 additions and 10 deletions
|
@ -1083,6 +1083,7 @@ struct _RoleFuncs
|
|||
void (*note_child_synced) (Surface *, Role *);
|
||||
void (*select_extra_events) (Surface *, Role *, unsigned long);
|
||||
void (*note_focus) (Surface *, Role *, FocusMode);
|
||||
void (*outputs_changed) (Surface *, Role *);
|
||||
};
|
||||
|
||||
struct _Role
|
||||
|
@ -1156,6 +1157,7 @@ extern void *XLAddScaleChangeCallback (void *, void (*) (void *, int));
|
|||
extern void XLRemoveScaleChangeCallback (void *);
|
||||
extern void XLClearOutputs (Surface *);
|
||||
extern void XLOutputSetChangeFunction (void (*) (Time));
|
||||
extern void XLGetMaxOutputBounds (int *, int *, int *, int *);
|
||||
|
||||
/* Defined in atoms.c. */
|
||||
|
||||
|
@ -1275,6 +1277,7 @@ struct _XdgRoleImplementationFuncs
|
|||
void (*commit_inside_frame) (Role *, XdgRoleImplementation *);
|
||||
Bool (*is_window_mapped) (Role *, XdgRoleImplementation *);
|
||||
void (*note_focus) (Role *, XdgRoleImplementation *, FocusMode);
|
||||
void (*outputs_changed) (Role *, XdgRoleImplementation *);
|
||||
};
|
||||
|
||||
struct _XdgRoleImplementation
|
||||
|
|
52
output.c
52
output.c
|
@ -653,7 +653,13 @@ NoticeOutputsMaybeChanged (void)
|
|||
|
||||
surface = all_surfaces.next;
|
||||
for (; surface != &all_surfaces; surface = surface->next)
|
||||
{
|
||||
pixman_region32_clear (&surface->output_region);
|
||||
|
||||
if (surface->role
|
||||
&& surface->role->funcs.outputs_changed)
|
||||
surface->role->funcs.outputs_changed (surface, surface->role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1091,6 +1097,51 @@ XLOutputSetChangeFunction (void (*change_func) (Time))
|
|||
change_hook = change_func;
|
||||
}
|
||||
|
||||
void
|
||||
XLGetMaxOutputBounds (int *x_min, int *y_min, int *x_max,
|
||||
int *y_max)
|
||||
{
|
||||
int x1, y1, x2, y2;
|
||||
Output *output;
|
||||
XLList *tem;
|
||||
|
||||
x1 = y1 = INT_MAX;
|
||||
x2 = y2 = INT_MIN;
|
||||
|
||||
if (!all_outputs)
|
||||
{
|
||||
*x_min = 0;
|
||||
*y_min = 0;
|
||||
*x_max = DisplayWidth (compositor.display,
|
||||
DefaultScreen (compositor.display)) - 1;
|
||||
*y_max = DisplayHeight (compositor.display,
|
||||
DefaultScreen (compositor.display)) - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (tem = all_outputs; tem; tem = tem->next)
|
||||
{
|
||||
output = tem->data;
|
||||
|
||||
if (output->x < x1)
|
||||
x1 = output->x;
|
||||
|
||||
if (output->y < y1)
|
||||
y1 = output->y;
|
||||
|
||||
if (output->x + output->width - 1 > x2)
|
||||
x2 = output->x + output->width - 1;
|
||||
|
||||
if (output->y + output->height - 1 > y2)
|
||||
y2 = output->y + output->height - 1;
|
||||
}
|
||||
|
||||
*x_min = x1;
|
||||
*y_min = y1;
|
||||
*x_max = x2;
|
||||
*y_max = y2;
|
||||
}
|
||||
|
||||
void
|
||||
XLInitRROutputs (void)
|
||||
{
|
||||
|
@ -1153,3 +1204,4 @@ XLInitRROutputs (void)
|
|||
all_outputs = BuildOutputTree ();
|
||||
MakeGlobalsForOutputTree (all_outputs);
|
||||
}
|
||||
|
||||
|
|
|
@ -1457,6 +1457,17 @@ NoteFocus (Surface *surface, Role *role, FocusMode focus)
|
|||
focus);
|
||||
}
|
||||
|
||||
static void
|
||||
OutputsChanged (Surface *surface, Role *role)
|
||||
{
|
||||
XdgRole *xdg_role;
|
||||
|
||||
xdg_role = XdgRoleFromRole (role);
|
||||
|
||||
if (xdg_role->impl && xdg_role->impl->funcs.outputs_changed)
|
||||
xdg_role->impl->funcs.outputs_changed (role, xdg_role->impl);
|
||||
}
|
||||
|
||||
void
|
||||
XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, struct wl_resource *surface_resource)
|
||||
|
@ -1543,6 +1554,7 @@ XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
|
|||
role->role.funcs.note_child_synced = NoteChildSynced;
|
||||
role->role.funcs.select_extra_events = SelectExtraEvents;
|
||||
role->role.funcs.note_focus = NoteFocus;
|
||||
role->role.funcs.outputs_changed = OutputsChanged;
|
||||
|
||||
attrs.colormap = compositor.colormap;
|
||||
attrs.border_pixel = border_pixel;
|
||||
|
|
|
@ -572,6 +572,22 @@ WriteStates (XdgToplevel *toplevel)
|
|||
AddState (toplevel, XDG_TOPLEVEL_STATE_RESIZING);
|
||||
}
|
||||
|
||||
static void
|
||||
CurrentWindowGeometry (XdgToplevel *toplevel,
|
||||
int *width, int *height)
|
||||
{
|
||||
/* Calculate the current window geometry for sending a configure
|
||||
event. */
|
||||
|
||||
TruncateScaleToSurface (toplevel->role->surface,
|
||||
toplevel->width,
|
||||
toplevel->height,
|
||||
width, height);
|
||||
|
||||
XLXdgRoleCalcNewWindowSize (toplevel->role, *width,
|
||||
*height, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
SendStates (XdgToplevel *toplevel)
|
||||
{
|
||||
|
@ -579,16 +595,9 @@ SendStates (XdgToplevel *toplevel)
|
|||
|
||||
WriteStates (toplevel);
|
||||
|
||||
/* Adjust the width and height we're sending by the window geometry.
|
||||
toplevel->role->surface should not be NULL here. */
|
||||
|
||||
TruncateScaleToSurface (toplevel->role->surface,
|
||||
toplevel->width, toplevel->height,
|
||||
&width, &height);
|
||||
|
||||
XLXdgRoleCalcNewWindowSize (toplevel->role, width,
|
||||
height, &width, &height);
|
||||
/* toplevel->role->surface should not be NULL here. */
|
||||
|
||||
CurrentWindowGeometry (toplevel, &width, &height);
|
||||
SendConfigure (toplevel, width, height);
|
||||
}
|
||||
|
||||
|
@ -1218,6 +1227,17 @@ AckConfigure (Role *role, XdgRoleImplementation *impl, uint32_t serial)
|
|||
toplevel->conf_reply = False;
|
||||
}
|
||||
|
||||
static void
|
||||
SendOutputBounds (XdgToplevel *toplevel)
|
||||
{
|
||||
int x_min, y_min, x_max, y_max;
|
||||
|
||||
XLGetMaxOutputBounds (&x_min, &y_min, &x_max, &y_max);
|
||||
xdg_toplevel_send_configure_bounds (toplevel->resource,
|
||||
x_max - x_min + 1,
|
||||
y_max - y_min + 1);
|
||||
}
|
||||
|
||||
static void
|
||||
Commit (Role *role, Surface *surface, XdgRoleImplementation *impl)
|
||||
{
|
||||
|
@ -1255,6 +1275,14 @@ Commit (Role *role, Surface *surface, XdgRoleImplementation *impl)
|
|||
Unmap (toplevel);
|
||||
|
||||
FlushConfigurationTimer (toplevel);
|
||||
|
||||
if (wl_resource_get_version (toplevel->resource) >= 4)
|
||||
/* Send the maximum bounds of the window to the client. It
|
||||
isn't possible to predict where the window will be mapped,
|
||||
so unfortunately the precise output bounds can't be used
|
||||
here. */
|
||||
SendOutputBounds (toplevel);
|
||||
|
||||
SendConfigure (toplevel, 0, 0);
|
||||
}
|
||||
else if (!toplevel->conf_reply)
|
||||
|
@ -2181,6 +2209,29 @@ NoteFocus (Role *role, XdgRoleImplementation *impl, FocusMode mode)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
OutputsChanged (Role *role, XdgRoleImplementation *impl)
|
||||
{
|
||||
XdgToplevel *toplevel;
|
||||
int width, height;
|
||||
|
||||
toplevel = ToplevelFromRoleImpl (impl);
|
||||
|
||||
/* The list of outputs changed. Send the new bounds to the
|
||||
client. */
|
||||
if (toplevel->resource)
|
||||
{
|
||||
if (wl_resource_get_version (toplevel->resource) < 4)
|
||||
/* The client is too old to accept configure_bounds. */
|
||||
return;
|
||||
|
||||
/* Send the updated bounds to the toplevel. */
|
||||
SendOutputBounds (toplevel);
|
||||
CurrentWindowGeometry (toplevel, &width, &height);
|
||||
SendConfigure (toplevel, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_interface xdg_toplevel_impl =
|
||||
{
|
||||
.destroy = Destroy,
|
||||
|
@ -2242,6 +2293,7 @@ XLGetXdgToplevel (struct wl_client *client, struct wl_resource *resource,
|
|||
toplevel->impl.funcs.post_resize = PostResize;
|
||||
toplevel->impl.funcs.commit_inside_frame = CommitInsideFrame;
|
||||
toplevel->impl.funcs.is_window_mapped = IsWindowMapped;
|
||||
toplevel->impl.funcs.outputs_changed = OutputsChanged;
|
||||
|
||||
if (!XLWmSupportsHint (_NET_WM_STATE_FOCUSED))
|
||||
/* If _NET_WM_STATE_FOCUSED is unsupported, fall back to utilizing
|
||||
|
|
Loading…
Add table
Reference in a new issue