#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
-
-
struct weston_wm_window {
struct weston_wm *wm;
xcb_window_t id;
xcb_atom_t type;
int width, height;
int x, y;
+ int saved_width, saved_height;
int decorate;
int override_redirect;
+ int fullscreen;
};
static struct weston_wm_window *
/* We reuse some predefined, but otherwise useles atoms */
#define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0
#define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1
+#define TYPE_NET_WM_STATE XCB_ATOM_CUT_BUFFER2
static void
weston_wm_window_read_properties(struct weston_wm_window *window)
{ XCB_ATOM_WM_NAME, XCB_ATOM_STRING, F(name) },
{ XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, F(transient_for) },
{ wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, F(protocols) },
+ { wm->atom.net_wm_state, TYPE_NET_WM_STATE },
{ wm->atom.net_wm_window_type, XCB_ATOM_ATOM, F(type) },
{ wm->atom.net_wm_name, XCB_ATOM_STRING, F(name) },
{ wm->atom.net_wm_pid, XCB_ATOM_CARDINAL, F(pid) },
break;
case TYPE_WM_PROTOCOLS:
break;
+ case TYPE_NET_WM_STATE:
+ window->fullscreen = 0;
+ atom = xcb_get_property_value(reply);
+ for (i = 0; i < reply->value_len; i++)
+ if (atom[i] == wm->atom.net_wm_state_fullscreen)
+ window->fullscreen = 1;
+ break;
case TYPE_MOTIF_WM_HINTS:
hints = xcb_get_property_value(reply);
if (hints->flags & MWM_HINTS_DECORATIONS)
{
struct theme *t = window->wm->theme;
- if (window->decorate) {
+ if (window->fullscreen) {
+ *width = window->width;
+ *height = window->height;
+ } else if (window->decorate) {
*width = window->width + (t->margin + t->width) * 2;
*height = window->height +
t->margin * 2 + t->width + t->titlebar_height;
{
struct theme *t = window->wm->theme;
- if (window->decorate) {
+ if (window->fullscreen) {
+ *x = 0;
+ *y = 0;
+ } else if (window->decorate) {
*x = t->margin + t->width;
*y = t->margin + t->titlebar_height;
} else {
}
static void
+weston_wm_window_send_configure_notify(struct weston_wm_window *window)
+{
+ xcb_configure_notify_event_t configure_notify;
+ struct weston_wm *wm = window->wm;
+ int x, y;
+
+ weston_wm_window_get_child_position(window, &x, &y);
+ configure_notify.response_type = XCB_CONFIGURE_NOTIFY;
+ configure_notify.pad0 = 0;
+ configure_notify.event = window->id;
+ configure_notify.window = window->id;
+ configure_notify.above_sibling = XCB_WINDOW_NONE;
+ configure_notify.x = x;
+ configure_notify.y = y;
+ configure_notify.width = window->width;
+ configure_notify.height = window->height;
+ configure_notify.border_width = 0;
+ configure_notify.override_redirect = 0;
+ configure_notify.pad1 = 0;
+
+ xcb_send_event(wm->conn, 0, window->id,
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY,
+ (char *) &configure_notify);
+}
+
+static void
weston_wm_handle_configure_request(struct weston_wm *wm, xcb_generic_event_t *event)
{
xcb_configure_request_event_t *configure_request =
window = hash_table_lookup(wm->window_hash, configure_request->window);
+ if (window->fullscreen) {
+ weston_wm_window_send_configure_notify(window);
+ return;
+ }
+
if (configure_request->value_mask & XCB_CONFIG_WINDOW_WIDTH)
window->width = configure_request->width;
if (configure_request->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
#define ICCCM_ICONIC_STATE 3
static void
-weston_wm_window_set_state(struct weston_wm_window *window, int32_t state)
+weston_wm_window_set_wm_state(struct weston_wm_window *window, int32_t state)
{
struct weston_wm *wm = window->wm;
uint32_t property[2];
}
static void
+weston_wm_window_set_net_wm_state(struct weston_wm_window *window)
+{
+ struct weston_wm *wm = window->wm;
+ uint32_t property[1];
+ int i;
+
+ i = 0;
+ if (window->fullscreen)
+ property[i++] = wm->atom.net_wm_state_fullscreen;
+
+ xcb_change_property(wm->conn,
+ XCB_PROP_MODE_REPLACE,
+ window->id,
+ wm->atom.net_wm_state,
+ XCB_ATOM_ATOM,
+ 32, /* format */
+ i, property);
+}
+
+static void
weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event)
{
xcb_map_request_event_t *map_request =
weston_log("XCB_MAP_REQUEST (window %d, %p, frame %d)\n",
window->id, window, window->frame_id);
+ weston_wm_window_set_wm_state(window, ICCCM_NORMAL_STATE);
+ weston_wm_window_set_net_wm_state(window);
+
xcb_map_window(wm->conn, map_request->window);
xcb_map_window(wm->conn, window->frame_id);
- weston_wm_window_set_state(window, ICCCM_NORMAL_STATE);
window->cairo_surface =
cairo_xcb_surface_create_with_xrender_format(wm->conn,
if (window->frame_id) {
xcb_reparent_window(wm->conn, window->id, wm->wm_window, 0, 0);
xcb_destroy_window(wm->conn, window->frame_id);
- weston_wm_window_set_state(window, ICCCM_WITHDRAWN_STATE);
+ weston_wm_window_set_wm_state(window, ICCCM_WITHDRAWN_STATE);
hash_table_remove(wm->window_hash, window->frame_id);
window->frame_id = XCB_WINDOW_NONE;
}
cairo_xcb_surface_set_size(window->cairo_surface, width, height);
cr = cairo_create(window->cairo_surface);
- if (window->decorate) {
+ if (window->fullscreen) {
+ /* nothing */
+ } else if (window->decorate) {
if (wm->focus_window == window)
flags |= THEME_FRAME_ACTIVE;
}
}
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
+#define _NET_WM_STATE_TOGGLE 2
+
+static int
+update_state(int action, int *state)
+{
+ int new_state, changed;
+
+ switch (action) {
+ case _NET_WM_STATE_REMOVE:
+ new_state = 0;
+ break;
+ case _NET_WM_STATE_ADD:
+ new_state = 1;
+ break;
+ case _NET_WM_STATE_TOGGLE:
+ new_state = !*state;
+ break;
+ default:
+ return 0;
+ }
+
+ changed = (*state != new_state);
+ *state = new_state;
+
+ return changed;
+}
+
+static void
+weston_wm_window_configure(void *data);
+
+static void
+weston_wm_window_handle_state(struct weston_wm_window *window,
+ xcb_client_message_event_t *client_message)
+{
+ struct weston_wm *wm = window->wm;
+ struct weston_shell_interface *shell_interface =
+ &wm->server->compositor->shell_interface;
+ uint32_t action, property;
+
+ action = client_message->data.data32[0];
+ property = client_message->data.data32[1];
+
+ if (property == wm->atom.net_wm_state_fullscreen &&
+ update_state(action, &window->fullscreen)) {
+ weston_wm_window_set_net_wm_state(window);
+ if (window->fullscreen) {
+ window->saved_width = window->width;
+ window->saved_height = window->height;
+ shell_interface->set_fullscreen(window->shsurf,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ 0, NULL);
+ } else {
+ shell_interface->set_toplevel(window->shsurf);
+ window->width = window->saved_width;
+ window->height = window->saved_height;
+ weston_wm_window_configure(window);
+ }
+ }
+}
+
static void
weston_wm_handle_client_message(struct weston_wm *wm,
xcb_generic_event_t *event)
window = hash_table_lookup(wm->window_hash, client_message->window);
- weston_log("XCB_CLIENT_MESSAGE (%s %d %d %d %d %d)\n",
- get_atom_name(wm->conn, client_message->type),
- client_message->data.data32[0],
- client_message->data.data32[1],
- client_message->data.data32[2],
- client_message->data.data32[3],
- client_message->data.data32[4]);
+ weston_log("XCB_CLIENT_MESSAGE (%s %d %d %d %d %d win %d)\n",
+ get_atom_name(wm->conn, client_message->type),
+ client_message->data.data32[0],
+ client_message->data.data32[1],
+ client_message->data.data32[2],
+ client_message->data.data32[3],
+ client_message->data.data32[4],
+ client_message->window);
if (client_message->type == wm->atom.net_wm_moveresize)
weston_wm_window_handle_moveresize(window, client_message);
+ else if (client_message->type == wm->atom.net_wm_state)
+ weston_wm_window_handle_state(window, client_message);
}
enum cursor_type {
xcb_screen_iterator_t s;
uint32_t values[1];
int sv[2];
- xcb_atom_t supported[1];
+ xcb_atom_t supported[3];
wm = malloc(sizeof *wm);
if (wm == NULL)
weston_wm_create_wm_window(wm);
supported[0] = wm->atom.net_wm_moveresize;
+ supported[1] = wm->atom.net_wm_state;
+ supported[2] = wm->atom.net_wm_state_fullscreen;
xcb_change_property(wm->conn,
XCB_PROP_MODE_REPLACE,
wm->screen->root,
{
struct weston_wm_window *window = data;
struct weston_wm *wm = window->wm;
- uint32_t values[2];
- int width, height;
+ uint32_t values[4];
+ int x, y, width, height;
- values[0] = window->width;
- values[1] = window->height;
+ weston_wm_window_get_child_position(window, &x, &y);
+ values[0] = x;
+ values[1] = y;
+ values[2] = window->width;
+ values[3] = window->height;
xcb_configure_window(wm->conn,
window->id,
+ XCB_CONFIG_WINDOW_X |
+ XCB_CONFIG_WINDOW_Y |
XCB_CONFIG_WINDOW_WIDTH |
XCB_CONFIG_WINDOW_HEIGHT,
values);
struct weston_wm *wm = window->wm;
struct theme *t = window->wm->theme;
- if (window->decorate) {
+ if (window->fullscreen) {
+ window->width = width;
+ window->height = height;
+ } else if (window->decorate) {
window->width = width - 2 * (t->margin + t->width);
window->height = height - 2 * t->margin -
t->titlebar_height - t->width;
window->surface,
&shell_client);
- /* ICCCM 4.1.1 */
- if (!window->override_redirect) {
+ if (window->fullscreen) {
+ window->saved_width = window->width;
+ window->saved_height = window->height;
+ shell_interface->set_fullscreen(window->shsurf,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ 0, NULL);
+ return;
+ } else if (!window->override_redirect) {
+ /* ICCCM 4.1.1 */
shell_interface->set_toplevel(window->shsurf);
return;
}