On Thu, Jan 29, 2015 at 07:06:49PM +0200, Giulio Camuffo wrote:
> This patch adds the maximize button to the window frame for the windows
> which set the MWM_DECOR_MAXIMIZE hint, and it wires it with the shell
> via a new method in weston_shell_interface.
> Additionally, it also listens for the wm hints coming from the client,
> but it doesn't support maximizing a window only vertically or horizontally.
> The window will be maximized only when both directions are maximized.
> Reviewed-by: Daniel Stone <[email protected]>
Reviewed-by: Bryce Harrington <[email protected]>
> ---
> 
> v4: fixed the warning

Thanks, applied:
   8aeeac8..6b4b241  master -> master

 
>  desktop-shell/shell.c     | 72 +++++++++++++++++++++++-------------
>  src/compositor.h          |  1 +
>  xwayland/window-manager.c | 93 
> ++++++++++++++++++++++++++++++++++++++++-------
>  xwayland/xwayland.h       |  2 +
>  4 files changed, 129 insertions(+), 39 deletions(-)
> 
> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> index f6d9c79..16a0178 100644
> --- a/desktop-shell/shell.c
> +++ b/desktop-shell/shell.c
> @@ -3000,6 +3000,51 @@ shell_interface_set_fullscreen(struct shell_surface 
> *shsurf,
>       set_fullscreen(shsurf, method, framerate, output);
>  }
>  
> +static struct weston_output *
> +get_focused_output(struct weston_compositor *compositor)
> +{
> +     struct weston_seat *seat;
> +     struct weston_output *output = NULL;
> +
> +     wl_list_for_each(seat, &compositor->seat_list, link) {
> +             /* Priority has touch focus, then pointer and
> +              * then keyboard focus. We should probably have
> +              * three for loops and check frist for touch,
> +              * then for pointer, etc. but unless somebody has some
> +              * objections, I think this is sufficient. */
> +             if (seat->touch && seat->touch->focus)
> +                     output = seat->touch->focus->output;
> +             else if (seat->pointer && seat->pointer->focus)
> +                     output = seat->pointer->focus->output;
> +             else if (seat->keyboard && seat->keyboard->focus)
> +                     output = seat->keyboard->focus->output;
> +
> +             if (output)
> +                     break;
> +     }
> +
> +     return output;
> +}
> +
> +static void
> +shell_interface_set_maximized(struct shell_surface *shsurf)
> +{
> +     struct weston_output *output;
> +
> +     surface_clear_next_states(shsurf);
> +     shsurf->next_state.maximized = true;
> +     shsurf->state_changed = true;
> +     shsurf->type = SHELL_SURFACE_TOPLEVEL;
> +
> +     if (!weston_surface_is_mapped(shsurf->surface))
> +             output = get_focused_output(shsurf->surface->compositor);
> +     else
> +             output = shsurf->surface->output;
> +
> +     shell_surface_set_output(shsurf, output);
> +     send_configure_for_surface(shsurf);
> +}
> +
>  static int
>  shell_interface_move(struct shell_surface *shsurf, struct weston_seat *ws)
>  {
> @@ -3605,32 +3650,6 @@ get_primary_view(void *shell, struct shell_surface 
> *shsurf)
>       return shsurf->view;
>  }
>  
> -static struct weston_output *
> -get_focused_output(struct weston_compositor *compositor)
> -{
> -     struct weston_seat *seat;
> -     struct weston_output *output = NULL;
> -
> -     wl_list_for_each(seat, &compositor->seat_list, link) {
> -             /* Priority has touch focus, then pointer and
> -              * then keyboard focus. We should probably have
> -              * three for loops and check frist for touch,
> -              * then for pointer, etc. but unless somebody has some
> -              * objections, I think this is sufficient. */
> -             if (seat->touch && seat->touch->focus)
> -                     output = seat->touch->focus->output;
> -             else if (seat->pointer && seat->pointer->focus)
> -                     output = seat->pointer->focus->output;
> -             else if (seat->keyboard && seat->keyboard->focus)
> -                     output = seat->keyboard->focus->output;
> -
> -             if (output)
> -                     break;
> -     }
> -
> -     return output;
> -}
> -
>  static void
>  shell_get_shell_surface(struct wl_client *client,
>                       struct wl_resource *resource,
> @@ -6629,6 +6648,7 @@ module_init(struct weston_compositor *ec,
>       ec->shell_interface.resize = surface_resize;
>       ec->shell_interface.set_title = set_title;
>       ec->shell_interface.set_window_geometry = set_window_geometry;
> +     ec->shell_interface.set_maximized = shell_interface_set_maximized;
>  
>       weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
>       weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
> diff --git a/src/compositor.h b/src/compositor.h
> index aa87ec0..5c0ea74 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -121,6 +121,7 @@ struct weston_shell_interface {
>       void (*set_window_geometry)(struct shell_surface *shsurf,
>                                   int32_t x, int32_t y,
>                                   int32_t width, int32_t height);
> +     void (*set_maximized)(struct shell_surface *shsurf);
>  };
>  
>  struct weston_animation {
> diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
> index 4d3611f..07c2ef3 100644
> --- a/xwayland/window-manager.c
> +++ b/xwayland/window-manager.c
> @@ -144,6 +144,8 @@ struct weston_wm_window {
>       int fullscreen;
>       int has_alpha;
>       int delete_window;
> +     int maximized_vert;
> +     int maximized_horz;
>       struct wm_size_hints size_hints;
>       struct motif_wm_hints motif_hints;
>       struct wl_list link;
> @@ -472,6 +474,10 @@ weston_wm_window_read_properties(struct weston_wm_window 
> *window)
>                       for (i = 0; i < reply->value_len; i++)
>                               if (atom[i] == wm->atom.net_wm_state_fullscreen)
>                                       window->fullscreen = 1;
> +                             if (atom[i] == 
> wm->atom.net_wm_state_maximized_vert)
> +                                     window->maximized_vert = 1;
> +                             if (atom[i] == 
> wm->atom.net_wm_state_maximized_horz)
> +                                     window->maximized_horz = 1;
>                       break;
>               case TYPE_MOTIF_WM_HINTS:
>                       memcpy(&window->motif_hints,
> @@ -479,7 +485,7 @@ weston_wm_window_read_properties(struct weston_wm_window 
> *window)
>                              sizeof window->motif_hints);
>                       if (window->motif_hints.flags & MWM_HINTS_DECORATIONS)
>                               window->decorate =
> -                                     window->motif_hints.decorations > 0;
> +                                     window->motif_hints.decorations;
>                       break;
>               default:
>                       break;
> @@ -789,12 +795,16 @@ static void
>  weston_wm_window_set_net_wm_state(struct weston_wm_window *window)
>  {
>       struct weston_wm *wm = window->wm;
> -     uint32_t property[1];
> +     uint32_t property[3];
>       int i;
>  
>       i = 0;
>       if (window->fullscreen)
>               property[i++] = wm->atom.net_wm_state_fullscreen;
> +     if (window->maximized_vert)
> +             property[i++] = wm->atom.net_wm_state_maximized_vert;
> +     if (window->maximized_horz)
> +             property[i++] = wm->atom.net_wm_state_maximized_horz;
>  
>       xcb_change_property(wm->conn,
>                           XCB_PROP_MODE_REPLACE,
> @@ -811,10 +821,14 @@ weston_wm_window_create_frame(struct weston_wm_window 
> *window)
>       struct weston_wm *wm = window->wm;
>       uint32_t values[3];
>       int x, y, width, height;
> +     int buttons = FRAME_BUTTON_CLOSE;
> +
> +     if (window->decorate & MWM_DECOR_MAXIMIZE)
> +             buttons |= FRAME_BUTTON_MAXIMIZE;
>  
>       window->frame = frame_create(window->wm->theme,
>                                    window->width, window->height,
> -                                  FRAME_BUTTON_CLOSE, window->name);
> +                                  buttons, window->name);
>       frame_resize_inside(window->frame, window->width, window->height);
>  
>       weston_wm_window_get_frame_size(window, &width, &height);
> @@ -1332,6 +1346,28 @@ static void
>  weston_wm_window_configure(void *data);
>  
>  static void
> +weston_wm_window_set_toplevel(struct weston_wm_window *window)
> +{
> +     struct weston_shell_interface *shell_interface =
> +             &window->wm->server->compositor->shell_interface;
> +
> +     shell_interface->set_toplevel(window->shsurf);
> +     window->width = window->saved_width;
> +     window->height = window->saved_height;
> +     if (window->frame)
> +             frame_resize_inside(window->frame,
> +                                     window->width,
> +                                     window->height);
> +     weston_wm_window_configure(window);
> +}
> +
> +static inline bool
> +weston_wm_window_is_maximized(struct weston_wm_window *window)
> +{
> +     return window->maximized_horz && window->maximized_vert;
> +}
> +
> +static void
>  weston_wm_window_handle_state(struct weston_wm_window *window,
>                             xcb_client_message_event_t *client_message)
>  {
> @@ -1339,6 +1375,7 @@ weston_wm_window_handle_state(struct weston_wm_window 
> *window,
>       struct weston_shell_interface *shell_interface =
>               &wm->server->compositor->shell_interface;
>       uint32_t action, property;
> +     int maximized = weston_wm_window_is_maximized(window);
>  
>       action = client_message->data.data32[0];
>       property = client_message->data.data32[1];
> @@ -1356,15 +1393,26 @@ weston_wm_window_handle_state(struct weston_wm_window 
> *window,
>                                                               0, NULL);
>               } else {
>                       if (window->shsurf)
> -                             shell_interface->set_toplevel(window->shsurf);
> -
> -                     window->width = window->saved_width;
> -                     window->height = window->saved_height;
> -                     if (window->frame)
> -                             frame_resize_inside(window->frame,
> -                                                 window->width,
> -                                                 window->height);
> -                     weston_wm_window_configure(window);
> +                             weston_wm_window_set_toplevel(window);
> +             }
> +     } else {
> +             if (property == wm->atom.net_wm_state_maximized_vert &&
> +                 update_state(action, &window->maximized_vert))
> +                     weston_wm_window_set_net_wm_state(window);
> +             if (property == wm->atom.net_wm_state_maximized_horz &&
> +                 update_state(action, &window->maximized_horz))
> +                     weston_wm_window_set_net_wm_state(window);
> +
> +             if (maximized != weston_wm_window_is_maximized(window)) {
> +                     if (weston_wm_window_is_maximized(window)) {
> +                             window->saved_width = window->width;
> +                             window->saved_height = window->height;
> +
> +                             if (window->shsurf)
> +                                     
> shell_interface->set_maximized(window->shsurf);
> +                     } else if (window->shsurf) {
> +                             weston_wm_window_set_toplevel(window);
> +                     }
>               }
>       }
>  }
> @@ -1696,6 +1744,19 @@ weston_wm_handle_button(struct weston_wm *wm, 
> xcb_generic_event_t *event)
>               weston_wm_window_close(window, button->time);
>               frame_status_clear(window->frame, FRAME_STATUS_CLOSE);
>       }
> +
> +     if (frame_status(window->frame) & FRAME_STATUS_MAXIMIZE) {
> +             window->maximized_horz = !window->maximized_horz;
> +             window->maximized_vert = !window->maximized_vert;
> +             if (weston_wm_window_is_maximized(window)) {
> +                     window->saved_width = window->width;
> +                     window->saved_height = window->height;
> +                     shell_interface->set_maximized(window->shsurf);
> +             } else {
> +                     weston_wm_window_set_toplevel(window);
> +             }
> +             frame_status_clear(window->frame, FRAME_STATUS_MAXIMIZE);
> +     }
>  }
>  
>  static void
> @@ -1884,6 +1945,8 @@ weston_wm_get_resources(struct weston_wm *wm)
>               { "_NET_WM_PID",        F(atom.net_wm_pid) },
>               { "_NET_WM_ICON",       F(atom.net_wm_icon) },
>               { "_NET_WM_STATE",      F(atom.net_wm_state) },
> +             { "_NET_WM_STATE_MAXIMIZED_VERT", 
> F(atom.net_wm_state_maximized_vert) },
> +             { "_NET_WM_STATE_MAXIMIZED_HORZ", 
> F(atom.net_wm_state_maximized_horz) },
>               { "_NET_WM_STATE_FULLSCREEN", F(atom.net_wm_state_fullscreen) },
>               { "_NET_WM_USER_TIME", F(atom.net_wm_user_time) },
>               { "_NET_WM_ICON_NAME", F(atom.net_wm_icon_name) },
> @@ -2061,7 +2124,7 @@ weston_wm_create(struct weston_xserver *wxs, int fd)
>       struct wl_event_loop *loop;
>       xcb_screen_iterator_t s;
>       uint32_t values[1];
> -     xcb_atom_t supported[3];
> +     xcb_atom_t supported[5];
>  
>       wm = zalloc(sizeof *wm);
>       if (wm == NULL)
> @@ -2112,6 +2175,8 @@ weston_wm_create(struct weston_xserver *wxs, int fd)
>       supported[0] = wm->atom.net_wm_moveresize;
>       supported[1] = wm->atom.net_wm_state;
>       supported[2] = wm->atom.net_wm_state_fullscreen;
> +     supported[3] = wm->atom.net_wm_state_maximized_vert;
> +     supported[4] = wm->atom.net_wm_state_maximized_horz;
>       xcb_change_property(wm->conn,
>                           XCB_PROP_MODE_REPLACE,
>                           wm->screen->root,
> @@ -2389,6 +2454,8 @@ xserver_map_shell_surface(struct weston_wm_window 
> *window,
>                                              parent->surface,
>                                              window->x - parent->x,
>                                              window->y - parent->y, flags);
> +     } else if (weston_wm_window_is_maximized(window)) {
> +             shell_interface->set_maximized(window->shsurf);
>       } else {
>               if (weston_wm_window_type_inactive(window)) {
>                       shell_interface->set_xwayland(window->shsurf,
> diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h
> index b42110b..54cbf6d 100644
> --- a/xwayland/xwayland.h
> +++ b/xwayland/xwayland.h
> @@ -102,6 +102,8 @@ struct weston_wm {
>               xcb_atom_t               net_wm_pid;
>               xcb_atom_t               net_wm_icon;
>               xcb_atom_t               net_wm_state;
> +             xcb_atom_t               net_wm_state_maximized_vert;
> +             xcb_atom_t               net_wm_state_maximized_horz;
>               xcb_atom_t               net_wm_state_fullscreen;
>               xcb_atom_t               net_wm_user_time;
>               xcb_atom_t               net_wm_icon_name;
> -- 
> 2.2.2
> 
> _______________________________________________
> wayland-devel mailing list
> [email protected]
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to