Notify clients on mode_switch()

This patch implements the notification of clients during mode_switch.
As discussed on IRC, clients are notified of mode_switch only when the
"native" mode is changed and activated. That means that if the native
mode is changed and the compositor had activated a temporary mode for
a fullscreen surface, the clients will be notified only when the native
mode is restored.
The scaling factor is treated the same way as modes.
dev
Hardening 11 years ago committed by Kristian Høgsberg
parent ff39efa5c0
commit 57388e44e5
  1. 1
      src/compositor-drm.c
  2. 1
      src/compositor-fbdev.c
  3. 1
      src/compositor-headless.c
  4. 29
      src/compositor-rdp.c
  5. 1
      src/compositor-rpi.c
  6. 1
      src/compositor-wayland.c
  7. 1
      src/compositor-x11.c
  8. 91
      src/compositor.c
  9. 13
      src/compositor.h
  10. 12
      src/shell.c

@ -1944,7 +1944,6 @@ create_output_for_connector(struct drm_compositor *ec,
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
output->base.connection_internal = 1; output->base.connection_internal = 1;
output->base.original_mode = output->base.current_mode;
output->base.start_repaint_loop = drm_output_start_repaint_loop; output->base.start_repaint_loop = drm_output_start_repaint_loop;
output->base.repaint = drm_output_repaint; output->base.repaint = drm_output_repaint;
output->base.destroy = drm_output_destroy; output->base.destroy = drm_output_destroy;

@ -544,7 +544,6 @@ fbdev_output_create(struct fbdev_compositor *compositor,
wl_list_insert(&output->base.mode_list, &output->mode.link); wl_list_insert(&output->base.mode_list, &output->mode.link);
output->base.current_mode = &output->mode; output->base.current_mode = &output->mode;
output->base.original_mode = &output->mode;
output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
output->base.make = "unknown"; output->base.make = "unknown";
output->base.model = output->fb_info.id; output->base.model = output->fb_info.id;

@ -120,7 +120,6 @@ headless_compositor_create_output(struct headless_compositor *c,
output->finish_frame_timer = output->finish_frame_timer =
wl_event_loop_add_timer(loop, finish_frame_handler, output); wl_event_loop_add_timer(loop, finish_frame_handler, output);
output->base.original_mode = output->base.current_mode;
output->base.start_repaint_loop = headless_output_start_repaint_loop; output->base.start_repaint_loop = headless_output_start_repaint_loop;
output->base.repaint = headless_output_repaint; output->base.repaint = headless_output_repaint;
output->base.destroy = headless_output_destroy; output->base.destroy = headless_output_destroy;

@ -372,9 +372,10 @@ rdp_switch_mode(struct weston_output *output, struct weston_mode *target_mode) {
if(local_mode == output->current_mode) if(local_mode == output->current_mode)
return 0; return 0;
output->current_mode->flags = 0; output->current_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
output->current_mode = local_mode; output->current_mode = local_mode;
output->current_mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; output->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
pixman_renderer_output_destroy(output); pixman_renderer_output_destroy(output);
pixman_renderer_output_create(output); pixman_renderer_output_create(output);
@ -466,7 +467,7 @@ rdp_compositor_create_output(struct rdp_compositor *c, int width, int height,
goto out_free_output_and_modes; goto out_free_output_and_modes;
} }
output->base.current_mode = currentMode; output->base.current_mode = output->base.native_mode = currentMode;
weston_output_init(&output->base, &c->base, 0, 0, width, height, weston_output_init(&output->base, &c->base, 0, 0, width, height,
WL_OUTPUT_TRANSFORM_NORMAL, 1); WL_OUTPUT_TRANSFORM_NORMAL, 1);
@ -489,7 +490,6 @@ rdp_compositor_create_output(struct rdp_compositor *c, int width, int height,
loop = wl_display_get_event_loop(c->base.wl_display); loop = wl_display_get_event_loop(c->base.wl_display);
output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output); output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
output->base.original_mode = output->base.current_mode;
output->base.start_repaint_loop = rdp_output_start_repaint_loop; output->base.start_repaint_loop = rdp_output_start_repaint_loop;
output->base.repaint = rdp_output_repaint; output->base.repaint = rdp_output_repaint;
output->base.destroy = rdp_output_destroy; output->base.destroy = rdp_output_destroy;
@ -679,23 +679,26 @@ xf_peer_post_connect(freerdp_peer* client)
output = c->output; output = c->output;
settings = client->settings; settings = client->settings;
if(!settings->SurfaceCommandsEnabled) { if (!settings->SurfaceCommandsEnabled) {
weston_log("client doesn't support required SurfaceCommands\n"); weston_log("client doesn't support required SurfaceCommands\n");
return FALSE; return FALSE;
} }
if(output->base.width != (int)settings->DesktopWidth || if (output->base.width != (int)settings->DesktopWidth ||
output->base.height != (int)settings->DesktopHeight) output->base.height != (int)settings->DesktopHeight)
{ {
if(!settings->DesktopResize) { struct weston_mode new_mode;
weston_log("client don't support desktopResize()\n"); struct weston_mode *target_mode;
new_mode.width = (int)settings->DesktopWidth;
new_mode.height = (int)settings->DesktopHeight;
target_mode = find_matching_mode(&output->base, &new_mode);
if (!target_mode) {
weston_log("client mode not found\n");
return FALSE; return FALSE;
} }
weston_output_switch_mode(&output->base, target_mode, 1, WESTON_MODE_SWITCH_SET_NATIVE);
/* force the client size */ output->base.width = new_mode.width;
settings->DesktopWidth = output->base.width; output->base.height = new_mode.height;
settings->DesktopHeight = output->base.height;
client->update->DesktopResize(client->context);
} }
weston_log("kbd_layout:%x kbd_type:%x kbd_subType:%x kbd_functionKeys:%x\n", weston_log("kbd_layout:%x kbd_type:%x kbd_subType:%x kbd_functionKeys:%x\n",

@ -370,7 +370,6 @@ rpi_output_create(struct rpi_compositor *compositor, uint32_t transform)
wl_list_insert(&output->base.mode_list, &output->mode.link); wl_list_insert(&output->base.mode_list, &output->mode.link);
output->base.current_mode = &output->mode; output->base.current_mode = &output->mode;
output->base.original_mode = &output->mode;
output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
output->base.make = "unknown"; output->base.make = "unknown";
output->base.model = "unknown"; output->base.model = "unknown";

@ -295,7 +295,6 @@ wayland_compositor_create_output(struct wayland_compositor *c,
&shell_surface_listener, output); &shell_surface_listener, output);
wl_shell_surface_set_toplevel(output->parent.shell_surface); wl_shell_surface_set_toplevel(output->parent.shell_surface);
output->base.original_mode = output->base.current_mode;
output->base.start_repaint_loop = wayland_output_start_repaint_loop; output->base.start_repaint_loop = wayland_output_start_repaint_loop;
output->base.repaint = wayland_output_repaint; output->base.repaint = wayland_output_repaint;
output->base.destroy = wayland_output_destroy; output->base.destroy = wayland_output_destroy;

@ -892,7 +892,6 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
output->base.set_dpms = NULL; output->base.set_dpms = NULL;
output->base.switch_mode = NULL; output->base.switch_mode = NULL;
output->base.current_mode = &output->mode; output->base.current_mode = &output->mode;
output->base.original_mode = output->base.current_mode;
output->base.make = "xwayland"; output->base.make = "xwayland";
output->base.model = "none"; output->base.model = "none";
weston_output_init(&output->base, &c->base, weston_output_init(&output->base, &c->base,

@ -96,20 +96,76 @@ static void
weston_compositor_build_surface_list(struct weston_compositor *compositor); weston_compositor_build_surface_list(struct weston_compositor *compositor);
WL_EXPORT int WL_EXPORT int
weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode, int32_t scale) weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode,
int32_t scale, enum weston_mode_switch_op op)
{ {
struct weston_seat *seat; struct weston_seat *seat;
struct wl_resource *resource;
pixman_region32_t old_output_region; pixman_region32_t old_output_region;
int ret; int ret, notify_mode_changed, notify_scale_changed;
int temporary_mode, temporary_scale;
if (!output->switch_mode) if (!output->switch_mode)
return -1; return -1;
ret = output->switch_mode(output, mode); temporary_mode = (output->original_mode != 0);
if (ret < 0) temporary_scale = (output->current_scale != output->original_scale);
return ret; ret = 0;
notify_mode_changed = 0;
notify_scale_changed = 0;
switch(op) {
case WESTON_MODE_SWITCH_SET_NATIVE:
output->native_mode = mode;
if (!temporary_mode) {
notify_mode_changed = 1;
ret = output->switch_mode(output, mode);
if (ret < 0)
return ret;
}
output->native_scale = scale;
if(!temporary_scale)
notify_scale_changed = 1;
break;
case WESTON_MODE_SWITCH_SET_TEMPORARY:
if (!temporary_mode)
output->original_mode = output->native_mode;
if (!temporary_scale)
output->original_scale = output->native_scale;
ret = output->switch_mode(output, mode);
if (ret < 0)
return ret;
output->current_scale = scale; output->current_mode = mode;
output->current_scale = scale;
break;
case WESTON_MODE_SWITCH_RESTORE_NATIVE:
if (!temporary_mode) {
weston_log("already in the native mode\n");
return -1;
}
notify_mode_changed = (output->original_mode != output->native_mode);
ret = output->switch_mode(output, mode);
if (ret < 0)
return ret;
if (output->original_scale != output->native_scale) {
notify_scale_changed = 1;
scale = output->native_scale;
output->original_scale = scale;
}
output->original_mode = 0;
output->current_scale = output->native_scale;
break;
default:
weston_log("unknown weston_switch_mode_op %d\n", op);
break;
}
pixman_region32_init(&old_output_region); pixman_region32_init(&old_output_region);
pixman_region32_copy(&old_output_region, &output->region); pixman_region32_copy(&old_output_region, &output->region);
@ -152,6 +208,25 @@ weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode
pixman_region32_fini(&old_output_region); pixman_region32_fini(&old_output_region);
/* notify clients of the changes */
if (notify_mode_changed || notify_scale_changed) {
wl_resource_for_each(resource, &output->resource_list) {
if(notify_mode_changed) {
wl_output_send_mode(resource,
mode->flags | WL_OUTPUT_MODE_CURRENT,
mode->width,
mode->height,
mode->refresh);
}
if (notify_scale_changed)
wl_output_send_scale(resource, scale);
if (wl_resource_get_version(resource) >= 2)
wl_output_send_done(resource);
}
}
return ret; return ret;
} }
@ -1874,7 +1949,7 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
* If this commit would cause the surface to move by the * If this commit would cause the surface to move by the
* attach(dx, dy) parameters, the old damage region must be * attach(dx, dy) parameters, the old damage region must be
* translated to correspond to the new surface coordinate system * translated to correspond to the new surface coordinate system
* origin. * original_mode.
*/ */
pixman_region32_translate(&sub->cached.damage, pixman_region32_translate(&sub->cached.damage,
-surface->pending.sx, -surface->pending.sy); -surface->pending.sx, -surface->pending.sy);
@ -2728,7 +2803,7 @@ weston_output_transform_scale_init(struct weston_output *output, uint32_t transf
break; break;
} }
output->current_scale = scale; output->native_scale = output->current_scale = scale;
output->width /= scale; output->width /= scale;
output->height /= scale; output->height /= scale;
} }

@ -174,6 +174,12 @@ enum dpms_enum {
WESTON_DPMS_OFF WESTON_DPMS_OFF
}; };
enum weston_mode_switch_op {
WESTON_MODE_SWITCH_SET_NATIVE,
WESTON_MODE_SWITCH_SET_TEMPORARY,
WESTON_MODE_SWITCH_RESTORE_NATIVE
};
struct weston_output { struct weston_output {
uint32_t id; uint32_t id;
char *name; char *name;
@ -203,11 +209,13 @@ struct weston_output {
char *make, *model, *serial_number; char *make, *model, *serial_number;
uint32_t subpixel; uint32_t subpixel;
uint32_t transform; uint32_t transform;
int32_t native_scale;
int32_t current_scale; int32_t current_scale;
int32_t original_scale;
struct weston_mode *native_mode;
struct weston_mode *current_mode; struct weston_mode *current_mode;
struct weston_mode *original_mode; struct weston_mode *original_mode;
int32_t original_scale;
struct wl_list mode_list; struct wl_list mode_list;
void (*start_repaint_loop)(struct weston_output *output); void (*start_repaint_loop)(struct weston_output *output);
@ -1211,7 +1219,8 @@ void
weston_surface_destroy(struct weston_surface *surface); weston_surface_destroy(struct weston_surface *surface);
int int
weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode, int32_t scale); weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode,
int32_t scale, enum weston_mode_switch_op op);
int int
noop_renderer_init(struct weston_compositor *ec); noop_renderer_init(struct weston_compositor *ec);

@ -1627,11 +1627,12 @@ get_default_output(struct weston_compositor *compositor)
static void static void
restore_output_mode(struct weston_output *output) restore_output_mode(struct weston_output *output)
{ {
if (output->current != output->origin || if (output->current_mode != output->original_mode ||
(int32_t)output->scale != output->origin_scale) (int32_t)output->current_scale != output->original_scale)
weston_output_switch_mode(output, weston_output_switch_mode(output,
output->origin, output->original_mode,
output->origin_scale); output->original_scale,
WESTON_MODE_SWITCH_RESTORE_NATIVE);
} }
static void static void
@ -1958,7 +1959,8 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
surf_height * surface->buffer_scale, surf_height * surface->buffer_scale,
shsurf->fullscreen.framerate}; shsurf->fullscreen.framerate};
if (weston_output_switch_mode(output, &mode, surface->buffer_scale) == 0) { if (weston_output_switch_mode(output, &mode, surface->buffer_scale,
WESTON_MODE_SWITCH_SET_TEMPORARY) == 0) {
weston_surface_set_position(surface, weston_surface_set_position(surface,
output->x - surf_x, output->x - surf_x,
output->y - surf_y); output->y - surf_y);

Loading…
Cancel
Save