mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 12:28:22 +01:00
Add support for _NET_WM_FULLSCREEN_MONITORS
This patch adds the _NET_WM_FULLSCREEN_MONITORS hint as defined in EWMH which is based on Xinerama. It's allowing a window to be displayed fullscreen on multiple monitors. Issue mentioned at https://github.com/window-maker/wmaker/issues/8 Specs at https://specifications.freedesktop.org/wm-spec/1.5/ar01s06.html#idm45763309187776 GTK test program used https://bugzilla.gnome.org/show_bug.cgi?id=414476
This commit is contained in:
committed by
Carlos R. Mafra
parent
ac75047aef
commit
4d658341d2
@@ -912,6 +912,54 @@ void wUnmaximizeWindow(WWindow *wwin)
|
|||||||
WMPostNotificationName(WMNChangedState, wwin, "maximize");
|
WMPostNotificationName(WMNChangedState, wwin, "maximize");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
void wFullscreenMonitorsWindow(WWindow *wwin, unsigned long top, unsigned long bottom,
|
||||||
|
unsigned long left, unsigned long right)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
long monitor;
|
||||||
|
WMRect rect1, rect2;
|
||||||
|
|
||||||
|
if ((int)top < wwin->screen_ptr->xine_info.count &&
|
||||||
|
(int)bottom < wwin->screen_ptr->xine_info.count &&
|
||||||
|
(int)left < wwin->screen_ptr->xine_info.count &&
|
||||||
|
(int)right < wwin->screen_ptr->xine_info.count) {
|
||||||
|
wwin->flags.fullscreen_monitors[0] = top;
|
||||||
|
wwin->flags.fullscreen_monitors[1] = bottom;
|
||||||
|
wwin->flags.fullscreen_monitors[2] = left;
|
||||||
|
wwin->flags.fullscreen_monitors[3] = right;
|
||||||
|
} else {
|
||||||
|
wwin->flags.fullscreen_monitors[0] = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wwin->flags.fullscreen = True;
|
||||||
|
wWindowConfigureBorders(wwin);
|
||||||
|
ChangeStackingLevel(wwin->frame->core, WMFullscreenLevel);
|
||||||
|
|
||||||
|
wwin->bfs_geometry.x = wwin->frame_x;
|
||||||
|
wwin->bfs_geometry.y = wwin->frame_y;
|
||||||
|
wwin->bfs_geometry.width = wwin->frame->core->width;
|
||||||
|
wwin->bfs_geometry.height = wwin->frame->core->height;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
monitor = wwin->flags.fullscreen_monitors[i];
|
||||||
|
rect1 = wwin->screen_ptr->xine_info.screens[monitor];
|
||||||
|
|
||||||
|
for (i = 1; i <= 3; i++) {
|
||||||
|
monitor = wwin->flags.fullscreen_monitors[i];
|
||||||
|
rect2 = wwin->screen_ptr->xine_info.screens[monitor];
|
||||||
|
wGetRectUnion(&rect1, &rect2, &rect1);
|
||||||
|
}
|
||||||
|
wWindowConfigure(wwin, rect1.pos.x, rect1.pos.y, rect1.size.width, rect1.size.height);
|
||||||
|
|
||||||
|
wwin->screen_ptr->bfs_focused_window = wwin->screen_ptr->focused_window;
|
||||||
|
wSetFocusTo(wwin->screen_ptr, wwin);
|
||||||
|
|
||||||
|
WMPostNotificationName(WMNChangedState, wwin, "fullscreen");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void wFullscreenWindow(WWindow *wwin)
|
void wFullscreenWindow(WWindow *wwin)
|
||||||
{
|
{
|
||||||
int head;
|
int head;
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ void wArrangeIcons(WScreen *scr, Bool arrangeAll);
|
|||||||
|
|
||||||
void wMakeWindowVisible(WWindow *wwin);
|
void wMakeWindowVisible(WWindow *wwin);
|
||||||
|
|
||||||
|
void wFullscreenMonitorsWindow(WWindow *wwin, unsigned long top, unsigned long bottom,
|
||||||
|
unsigned long left, unsigned long right);
|
||||||
|
|
||||||
void wFullscreenWindow(WWindow *wwin);
|
void wFullscreenWindow(WWindow *wwin);
|
||||||
void wUnfullscreenWindow(WWindow *wwin);
|
void wUnfullscreenWindow(WWindow *wwin);
|
||||||
|
|
||||||
|
|||||||
@@ -688,6 +688,9 @@ WWindow *wManageWindow(WScreen *scr, Window window)
|
|||||||
XChangeWindowAttributes(dpy, window, CWEventMask | CWDontPropagate | CWSaveUnder, &attribs);
|
XChangeWindowAttributes(dpy, window, CWEventMask | CWDontPropagate | CWSaveUnder, &attribs);
|
||||||
XSetWindowBorderWidth(dpy, window, 0);
|
XSetWindowBorderWidth(dpy, window, 0);
|
||||||
|
|
||||||
|
if (wwin->wm_class != NULL && strcmp(wwin->wm_class, "DockApp") != 0)
|
||||||
|
wwin->flags.fullscreen_monitors[0] = -1;
|
||||||
|
|
||||||
/* get hints from GNUstep app */
|
/* get hints from GNUstep app */
|
||||||
if (wwin->wm_class != NULL && strcmp(wwin->wm_class, "GNUstep") == 0)
|
if (wwin->wm_class != NULL && strcmp(wwin->wm_class, "GNUstep") == 0)
|
||||||
wwin->flags.is_gnustep = 1;
|
wwin->flags.is_gnustep = 1;
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ typedef struct WWindow {
|
|||||||
unsigned int maximized:7;
|
unsigned int maximized:7;
|
||||||
unsigned int old_maximized:7;
|
unsigned int old_maximized:7;
|
||||||
unsigned int fullscreen:1;
|
unsigned int fullscreen:1;
|
||||||
|
long fullscreen_monitors[4];
|
||||||
unsigned int omnipresent:1;
|
unsigned int omnipresent:1;
|
||||||
unsigned int semi_focused:1;
|
unsigned int semi_focused:1;
|
||||||
/* window type flags */
|
/* window type flags */
|
||||||
|
|||||||
54
src/wmspec.c
54
src/wmspec.c
@@ -77,6 +77,9 @@ static Atom net_wm_visible_name; /* TODO (unnecessary?) */
|
|||||||
static Atom net_wm_icon_name;
|
static Atom net_wm_icon_name;
|
||||||
static Atom net_wm_visible_icon_name; /* TODO (unnecessary?) */
|
static Atom net_wm_visible_icon_name; /* TODO (unnecessary?) */
|
||||||
static Atom net_wm_desktop;
|
static Atom net_wm_desktop;
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
static Atom net_wm_fullscreen_monitors;
|
||||||
|
#endif
|
||||||
static Atom net_wm_window_type;
|
static Atom net_wm_window_type;
|
||||||
static Atom net_wm_window_type_desktop;
|
static Atom net_wm_window_type_desktop;
|
||||||
static Atom net_wm_window_type_dock;
|
static Atom net_wm_window_type_dock;
|
||||||
@@ -161,6 +164,9 @@ static atomitem_t atomNames[] = {
|
|||||||
{"_NET_WM_ICON_NAME", &net_wm_icon_name},
|
{"_NET_WM_ICON_NAME", &net_wm_icon_name},
|
||||||
{"_NET_WM_VISIBLE_ICON_NAME", &net_wm_visible_icon_name},
|
{"_NET_WM_VISIBLE_ICON_NAME", &net_wm_visible_icon_name},
|
||||||
{"_NET_WM_DESKTOP", &net_wm_desktop},
|
{"_NET_WM_DESKTOP", &net_wm_desktop},
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
{"_NET_WM_FULLSCREEN_MONITORS", &net_wm_fullscreen_monitors},
|
||||||
|
#endif
|
||||||
{"_NET_WM_WINDOW_TYPE", &net_wm_window_type},
|
{"_NET_WM_WINDOW_TYPE", &net_wm_window_type},
|
||||||
{"_NET_WM_WINDOW_TYPE_DESKTOP", &net_wm_window_type_desktop},
|
{"_NET_WM_WINDOW_TYPE_DESKTOP", &net_wm_window_type_desktop},
|
||||||
{"_NET_WM_WINDOW_TYPE_DOCK", &net_wm_window_type_dock},
|
{"_NET_WM_WINDOW_TYPE_DOCK", &net_wm_window_type_dock},
|
||||||
@@ -287,6 +293,9 @@ static void setSupportedHints(WScreen *scr)
|
|||||||
atom[i++] = net_wm_moveresize;
|
atom[i++] = net_wm_moveresize;
|
||||||
#endif
|
#endif
|
||||||
atom[i++] = net_wm_desktop;
|
atom[i++] = net_wm_desktop;
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
atom[i++] = net_wm_fullscreen_monitors;
|
||||||
|
#endif
|
||||||
atom[i++] = net_wm_window_type;
|
atom[i++] = net_wm_window_type;
|
||||||
atom[i++] = net_wm_window_type_desktop;
|
atom[i++] = net_wm_window_type_desktop;
|
||||||
atom[i++] = net_wm_window_type_dock;
|
atom[i++] = net_wm_window_type_dock;
|
||||||
@@ -1027,6 +1036,9 @@ static void updateStateHint(WWindow *wwin, Bool changedWorkspace, Bool del)
|
|||||||
{ /* changeable */
|
{ /* changeable */
|
||||||
if (del) {
|
if (del) {
|
||||||
XDeleteProperty(dpy, wwin->client_win, net_wm_state);
|
XDeleteProperty(dpy, wwin->client_win, net_wm_state);
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
XDeleteProperty(dpy, wwin->client_win, net_wm_fullscreen_monitors);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Atom state[15]; /* nr of defined state atoms */
|
Atom state[15]; /* nr of defined state atoms */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -1067,6 +1079,20 @@ static void updateStateHint(WWindow *wwin, Bool changedWorkspace, Bool del)
|
|||||||
|
|
||||||
XChangeProperty(dpy, wwin->client_win, net_wm_state, XA_ATOM, 32,
|
XChangeProperty(dpy, wwin->client_win, net_wm_state, XA_ATOM, 32,
|
||||||
PropModeReplace, (unsigned char *)state, i);
|
PropModeReplace, (unsigned char *)state, i);
|
||||||
|
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
if (wwin->flags.fullscreen && (wwin->flags.fullscreen_monitors[0] != -1)) {
|
||||||
|
unsigned long data[4];
|
||||||
|
|
||||||
|
data[0] = wwin->flags.fullscreen_monitors[0];
|
||||||
|
data[1] = wwin->flags.fullscreen_monitors[1];
|
||||||
|
data[2] = wwin->flags.fullscreen_monitors[2];
|
||||||
|
data[3] = wwin->flags.fullscreen_monitors[3];
|
||||||
|
|
||||||
|
XChangeProperty(dpy, wwin->client_win, net_wm_fullscreen_monitors, XA_CARDINAL, 32,
|
||||||
|
PropModeReplace, (unsigned char *)data, 4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1260,8 +1286,10 @@ static void doStateAtom(WWindow *wwin, Atom state, int set, Bool init)
|
|||||||
} else {
|
} else {
|
||||||
if (set)
|
if (set)
|
||||||
wFullscreenWindow(wwin);
|
wFullscreenWindow(wwin);
|
||||||
else
|
else {
|
||||||
wUnfullscreenWindow(wwin);
|
wUnfullscreenWindow(wwin);
|
||||||
|
wwin->flags.fullscreen_monitors[0] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (state == net_wm_state_above) {
|
} else if (state == net_wm_state_above) {
|
||||||
if (set == _NET_WM_STATE_TOGGLE)
|
if (set == _NET_WM_STATE_TOGGLE)
|
||||||
@@ -1759,8 +1787,30 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *event)
|
|||||||
wWindowChangeWorkspace(wwin, desktop);
|
wWindowChangeWorkspace(wwin, desktop);
|
||||||
}
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
|
||||||
|
|
||||||
|
#ifdef USE_XINERAMA
|
||||||
|
} else if (event->message_type == net_wm_fullscreen_monitors) {
|
||||||
|
unsigned long top, bottom, left, right, src_indication;
|
||||||
|
|
||||||
|
top = event->data.l[0];
|
||||||
|
bottom = event->data.l[1];
|
||||||
|
left = event->data.l[2];
|
||||||
|
right = event->data.l[3];
|
||||||
|
src_indication = event->data.l[4];
|
||||||
|
|
||||||
|
if (src_indication > 1)
|
||||||
|
wwarning("_NET_WM_FULLSCREEN_MONITORS source indication %ld not supported", src_indication);
|
||||||
|
|
||||||
|
wFullscreenMonitorsWindow(wwin, top, bottom, left, right);
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_WMSPEC
|
||||||
|
wmessage("processClientMessage unsupported type %s", XGetAtomName(dpy, event->message_type));
|
||||||
|
#endif
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -410,3 +410,33 @@ WMPoint wGetPointToCenterRectInHead(WScreen * scr, int head, int width, int heig
|
|||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the bounding rect of the union of two rectangles */
|
||||||
|
void wGetRectUnion(const WMRect *rect1, const WMRect *rect2, WMRect *dest)
|
||||||
|
{
|
||||||
|
int dest_x, dest_y;
|
||||||
|
int dest_w, dest_h;
|
||||||
|
|
||||||
|
dest_x = rect1->pos.x;
|
||||||
|
dest_y = rect1->pos.y;
|
||||||
|
dest_w = rect1->size.width;
|
||||||
|
dest_h = rect1->size.height;
|
||||||
|
|
||||||
|
if (rect2->pos.x < dest_x) {
|
||||||
|
dest_w += dest_x - rect2->pos.x;
|
||||||
|
dest_x = rect2->pos.x;
|
||||||
|
}
|
||||||
|
if (rect2->pos.y < dest_y) {
|
||||||
|
dest_h += dest_y - rect2->pos.y;
|
||||||
|
dest_y = rect2->pos.y;
|
||||||
|
}
|
||||||
|
if (rect2->pos.x + rect2->size.width > dest_x + dest_w)
|
||||||
|
dest_w = rect2->pos.x + rect2->size.width - dest_x;
|
||||||
|
if (rect2->pos.y + rect2->size.height > dest_y + dest_h)
|
||||||
|
dest_h = rect2->pos.y + rect2->size.height - dest_y;
|
||||||
|
|
||||||
|
dest->pos.x = dest_x;
|
||||||
|
dest->pos.y = dest_y;
|
||||||
|
dest->size.width = dest_w;
|
||||||
|
dest->size.height = dest_h;
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr, Bool no
|
|||||||
|
|
||||||
WMPoint wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height);
|
WMPoint wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height);
|
||||||
|
|
||||||
|
void wGetRectUnion(const WMRect *rect1, const WMRect *rect2, WMRect *dest);
|
||||||
|
|
||||||
Bool wWindowTouchesHead(WWindow *wwin, int head);
|
Bool wWindowTouchesHead(WWindow *wwin, int head);
|
||||||
Bool wAppIconTouchesHead(WAppIcon *aicon, int head);
|
Bool wAppIconTouchesHead(WAppIcon *aicon, int head);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user