xwm: Detect WM_NORMAL_HINTS fullscreen attempts

This commit is contained in:
Kristian Høgsberg 2013-08-31 00:12:25 -07:00
parent 59f44c184d
commit 1a7a57f0d9
2 changed files with 71 additions and 7 deletions

View file

@ -40,6 +40,32 @@
#include "xserver-server-protocol.h" #include "xserver-server-protocol.h"
#include "hash.h" #include "hash.h"
struct wm_size_hints {
uint32_t flags;
int32_t x, y;
int32_t width, height; /* should set so old wm's don't mess up */
int32_t min_width, min_height;
int32_t max_width, max_height;
int32_t width_inc, height_inc;
struct {
int32_t x;
int32_t y;
} min_aspect, max_aspect;
int32_t base_width, base_height;
int32_t win_gravity;
};
#define USPosition (1L << 0)
#define USSize (1L << 1)
#define PPosition (1L << 2)
#define PSize (1L << 3)
#define PMinSize (1L << 4)
#define PMaxSize (1L << 5)
#define PResizeInc (1L << 6)
#define PAspect (1L << 7)
#define PBaseSize (1L << 8)
#define PWinGravity (1L << 9)
struct motif_wm_hints { struct motif_wm_hints {
uint32_t flags; uint32_t flags;
uint32_t functions; uint32_t functions;
@ -117,6 +143,8 @@ struct weston_wm_window {
int override_redirect; int override_redirect;
int fullscreen; int fullscreen;
int has_alpha; int has_alpha;
struct wm_size_hints size_hints;
struct motif_wm_hints motif_hints;
}; };
static struct weston_wm_window * static struct weston_wm_window *
@ -332,6 +360,7 @@ read_and_dump_property(struct weston_wm *wm,
#define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0 #define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0
#define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1 #define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1
#define TYPE_NET_WM_STATE XCB_ATOM_CUT_BUFFER2 #define TYPE_NET_WM_STATE XCB_ATOM_CUT_BUFFER2
#define TYPE_WM_NORMAL_HINTS XCB_ATOM_CUT_BUFFER3
static void static void
weston_wm_window_read_properties(struct weston_wm_window *window) weston_wm_window_read_properties(struct weston_wm_window *window)
@ -348,6 +377,7 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
{ XCB_ATOM_WM_NAME, XCB_ATOM_STRING, F(name) }, { XCB_ATOM_WM_NAME, XCB_ATOM_STRING, F(name) },
{ XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, F(transient_for) }, { XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, F(transient_for) },
{ wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, F(protocols) }, { wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, F(protocols) },
{ wm->atom.wm_normal_hints, TYPE_WM_NORMAL_HINTS, F(protocols) },
{ wm->atom.net_wm_state, TYPE_NET_WM_STATE }, { wm->atom.net_wm_state, TYPE_NET_WM_STATE },
{ wm->atom.net_wm_window_type, XCB_ATOM_ATOM, F(type) }, { 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_name, XCB_ATOM_STRING, F(name) },
@ -363,7 +393,6 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
uint32_t *xid; uint32_t *xid;
xcb_atom_t *atom; xcb_atom_t *atom;
uint32_t i; uint32_t i;
struct motif_wm_hints *hints;
if (!window->properties_dirty) if (!window->properties_dirty)
return; return;
@ -377,6 +406,9 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
XCB_ATOM_ANY, 0, 2048); XCB_ATOM_ANY, 0, 2048);
window->decorate = !window->override_redirect; window->decorate = !window->override_redirect;
window->size_hints.flags = 0;
window->motif_hints.flags = 0;
for (i = 0; i < ARRAY_LENGTH(props); i++) { for (i = 0; i < ARRAY_LENGTH(props); i++) {
reply = xcb_get_property_reply(wm->conn, cookie[i], NULL); reply = xcb_get_property_reply(wm->conn, cookie[i], NULL);
if (!reply) if (!reply)
@ -414,6 +446,11 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
break; break;
case TYPE_WM_PROTOCOLS: case TYPE_WM_PROTOCOLS:
break; break;
case TYPE_WM_NORMAL_HINTS:
memcpy(&window->size_hints,
xcb_get_property_value(reply),
sizeof window->size_hints);
break;
case TYPE_NET_WM_STATE: case TYPE_NET_WM_STATE:
window->fullscreen = 0; window->fullscreen = 0;
atom = xcb_get_property_value(reply); atom = xcb_get_property_value(reply);
@ -422,9 +459,12 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
window->fullscreen = 1; window->fullscreen = 1;
break; break;
case TYPE_MOTIF_WM_HINTS: case TYPE_MOTIF_WM_HINTS:
hints = xcb_get_property_value(reply); memcpy(&window->motif_hints,
if (hints->flags & MWM_HINTS_DECORATIONS) xcb_get_property_value(reply),
window->decorate = hints->decorations > 0; sizeof window->motif_hints);
if (window->motif_hints.flags & MWM_HINTS_DECORATIONS)
window->decorate =
window->motif_hints.decorations > 0;
break; break;
default: default:
break; break;
@ -1516,6 +1556,7 @@ weston_wm_get_resources(struct weston_wm *wm)
static const struct { const char *name; int offset; } atoms[] = { static const struct { const char *name; int offset; } atoms[] = {
{ "WM_PROTOCOLS", F(atom.wm_protocols) }, { "WM_PROTOCOLS", F(atom.wm_protocols) },
{ "WM_NORMAL_HINTS", F(atom.wm_normal_hints) },
{ "WM_TAKE_FOCUS", F(atom.wm_take_focus) }, { "WM_TAKE_FOCUS", F(atom.wm_take_focus) },
{ "WM_DELETE_WINDOW", F(atom.wm_delete_window) }, { "WM_DELETE_WINDOW", F(atom.wm_delete_window) },
{ "WM_STATE", F(atom.wm_state) }, { "WM_STATE", F(atom.wm_state) },
@ -1905,6 +1946,8 @@ legacy_fullscreen(struct weston_wm *wm,
{ {
struct weston_compositor *compositor = wm->server->compositor; struct weston_compositor *compositor = wm->server->compositor;
struct weston_output *output; struct weston_output *output;
uint32_t minmax = PMinSize | PMaxSize;
int matching_size;
/* Heuristics for detecting legacy fullscreen windows... */ /* Heuristics for detecting legacy fullscreen windows... */
@ -1917,6 +1960,26 @@ legacy_fullscreen(struct weston_wm *wm,
*output_ret = output; *output_ret = output;
return 1; return 1;
} }
matching_size = 0;
if ((window->size_hints.flags & (USSize |PSize)) &&
window->size_hints.width == output->width &&
window->size_hints.height == output->height)
matching_size = 1;
if ((window->size_hints.flags & minmax) == minmax &&
window->size_hints.min_width == output->width &&
window->size_hints.min_height == output->height &&
window->size_hints.max_width == output->width &&
window->size_hints.max_height == output->height)
matching_size = 1;
if (matching_size && !window->decorate &&
(window->size_hints.flags & (USPosition | PPosition)) &&
window->size_hints.x == output->x &&
window->size_hints.y == output->y) {
*output_ret = output;
return 1;
}
} }
return 0; return 0;
@ -1944,14 +2007,14 @@ xserver_map_shell_surface(struct weston_wm *wm,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0, NULL); 0, NULL);
return; return;
} else if (!window->override_redirect) {
shell_interface->set_toplevel(window->shsurf);
return;
} else if (legacy_fullscreen(wm, window, &output)) { } else if (legacy_fullscreen(wm, window, &output)) {
window->fullscreen = 1; window->fullscreen = 1;
shell_interface->set_fullscreen(window->shsurf, shell_interface->set_fullscreen(window->shsurf,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0, output); 0, output);
} else if (!window->override_redirect) {
shell_interface->set_toplevel(window->shsurf);
return;
} else { } else {
shell_interface->set_xwayland(window->shsurf, shell_interface->set_xwayland(window->shsurf,
window->x, window->x,

View file

@ -80,6 +80,7 @@ struct weston_wm {
struct { struct {
xcb_atom_t wm_protocols; xcb_atom_t wm_protocols;
xcb_atom_t wm_normal_hints;
xcb_atom_t wm_take_focus; xcb_atom_t wm_take_focus;
xcb_atom_t wm_delete_window; xcb_atom_t wm_delete_window;
xcb_atom_t wm_state; xcb_atom_t wm_state;