Created
April 16, 2017 18:22
-
-
Save tom-seddon/988cb157b09b3dccaeab7b3374361af1 to your computer and use it in GitHub Desktop.
Some Xlib junk, vaguely along the lines of GetWindowPlacement/SetWindowPlacement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <shared/system.h> | |
#include "x11.h" | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
#include <X11/extensions/Xinerama.h> | |
#include <string.h> | |
#include <shared/log.h> | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
static const char NET_WM_STATE[]="_NET_WM_STATE"; | |
static const char NET_WM_STATE_MAXIMIZED_HORZ[]="_NET_WM_STATE_MAXIMIZED_HORZ"; | |
static const char NET_WM_STATE_MAXIMIZED_VERT[]="_NET_WM_STATE_MAXIMIZED_VERT"; | |
enum { | |
_NET_WM_STATE_REMOVE=0, // remove/unset property | |
_NET_WM_STATE_ADD=1, // add/set property | |
_NET_WM_STATE_TOGGLE=2, // toggle property | |
}; | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
template<class T> | |
static void Free(T **p_ptr) { | |
if(*p_ptr) { | |
XFree(*p_ptr); | |
*p_ptr=nullptr; | |
} | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
static void *GetWindowProperty(unsigned long *num_items, | |
Display *display, | |
Window window, | |
Atom property) | |
{ | |
Atom actual_type; | |
int actual_format; | |
unsigned long tmp_num_items,bytes_after; | |
unsigned char *prop; | |
int result=XGetWindowProperty(display, /* display */ | |
window, /* window */ | |
property, /* property */ | |
0, /* long_offset */ | |
~0L, /* long_length */ | |
False, /* delete */ | |
AnyPropertyType, /* req_type */ | |
&actual_type, /* actual_type_return */ | |
&actual_format, /* actual_format_return */ | |
&tmp_num_items, /* nitems_return */ | |
&bytes_after, /* bytes_after_return */ | |
&prop); /* prop_return */ | |
if(result==Success) { | |
/* char *n=XGetAtomName(display,property); */ | |
/* printf("Property %s, actual format=%d\n",n,actual_format); */ | |
/* XFree(n); */ | |
} else { | |
tmp_num_items=0; | |
prop=NULL; | |
} | |
if(num_items) { | |
*num_items=tmp_num_items; | |
} | |
return prop; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
static bool IsWindowManagerStateSet(Display *display, | |
Window window, | |
const char *atom_name) | |
{ | |
Atom net_wm_state=XInternAtom(display,NET_WM_STATE,False); | |
if(net_wm_state==None) { | |
return false; | |
} | |
Atom atom=XInternAtom(display,atom_name,False); | |
if(atom==None) { | |
return false; | |
} | |
bool set=false; | |
unsigned long num_ws; | |
if(auto ws=(Atom *)GetWindowProperty(&num_ws, | |
display, | |
window, | |
net_wm_state)) | |
{ | |
for(unsigned long ws_idx=0;ws_idx<num_ws;++ws_idx) { | |
if(ws[ws_idx]==atom) { | |
set=true; | |
break; | |
} | |
} | |
Free(&ws); | |
} | |
return set; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
bool GetXWindowPlacement(XWindowPlacement *placement, | |
Display *display, | |
uint64_t window) | |
{ | |
if(!display||window==0) { | |
return false; | |
} | |
XWindowAttributes xwa; | |
if(!XGetWindowAttributes(display,window,&xwa)) { | |
return false; | |
} | |
Window child; | |
if(!XTranslateCoordinates(display,window,xwa.root,0,0,&xwa.x,&xwa.y,&child)) { | |
return false; | |
} | |
if(xwa.width<0||xwa.height<0) { | |
return false; | |
} | |
placement->valid=1; | |
placement->hmax=IsWindowManagerStateSet(display,window,NET_WM_STATE_MAXIMIZED_HORZ); | |
placement->vmax=IsWindowManagerStateSet(display,window,NET_WM_STATE_MAXIMIZED_VERT); | |
if(!placement->hmax) { | |
placement->x=xwa.x; | |
placement->w=(unsigned)xwa.width; | |
} | |
if(!placement->vmax) { | |
placement->y=xwa.y; | |
placement->h=(unsigned)xwa.height; | |
} | |
return true; | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
static void SetWindowMaximizedFlag(Display *display, | |
Window window, | |
const char *name, | |
bool state) | |
{ | |
Atom net_wm_state=XInternAtom(display,NET_WM_STATE,False); | |
if(net_wm_state==None) { | |
return; | |
} | |
Atom atom=XInternAtom(display,name,False); | |
if(atom==None) { | |
return; | |
} | |
XEvent e; | |
memset(&e,0,sizeof e); | |
e.xany.type=ClientMessage; | |
e.xclient.message_type=net_wm_state; | |
e.xclient.format=32; | |
e.xclient.window=window; | |
e.xclient.data.l[0]=state?_NET_WM_STATE_ADD:_NET_WM_STATE_REMOVE; | |
e.xclient.data.l[1]=(long)atom; | |
// http://standards.freedesktop.org/wm-spec/1.3/ar01s07.html#sourceindication | |
e.xclient.data.l[3]=2; /* "pagers and other Clients that | |
* represent direct user actions" */ | |
XSendEvent(display, | |
XDefaultRootWindow(display), | |
True, | |
SubstructureNotifyMask|SubstructureRedirectMask, | |
&e); | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
void SetXWindowPlacement(Display *display, | |
uint64_t window, | |
const XWindowPlacement &placement) | |
{ | |
if(!placement.valid) { | |
return; | |
} | |
//OU_LOG(OUTPUT,"%s: x=%d y=%d w=%d h=%d\n",__func__,placement.x,placement.y,placement.w,placement.h); | |
SetWindowMaximizedFlag(display,window,NET_WM_STATE_MAXIMIZED_HORZ,false); | |
SetWindowMaximizedFlag(display,window,NET_WM_STATE_MAXIMIZED_VERT,false); | |
if(placement.x!=INT_MIN&&placement.y!=INT_MIN) { | |
XMoveWindow(display,window,placement.x,placement.y); | |
} | |
if(placement.w>0&&placement.h>0) { | |
XResizeWindow(display,window,placement.w,placement.h); | |
} | |
if(placement.hmax) { | |
SetWindowMaximizedFlag(display,window,NET_WM_STATE_MAXIMIZED_HORZ,true); | |
} | |
if(placement.vmax) { | |
SetWindowMaximizedFlag(display,window,NET_WM_STATE_MAXIMIZED_VERT,true); | |
} | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef HEADER_710C85347C9F4264A30F6361CB5DB1F7// -*- mode:c++ -*- | |
#define HEADER_710C85347C9F4264A30F6361CB5DB1F7 | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
#include <limits.h> | |
struct _XDisplay; | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
// X11 analogue of WINDOWPLACEMENT. This just gets stuffed in the | |
// BeebWindows placementdata bit. Probably needs some better | |
// mechanism... | |
#include <shared/pshpack1.h> | |
struct XWindowPlacement { | |
// if false, the Set operation is a no-op. | |
int8_t valid=false; | |
// horizontally/vertically maximized flags | |
uint8_t hmax=0; | |
uint8_t vmax=0; | |
// Window rect in display coordinates. | |
// | |
// If x or y is INT_MIN, the position isn't set; if width or | |
// height is 0, the size isn't set. | |
int32_t x=INT_MIN,y=INT_MIN; | |
unsigned w=0,h=0; | |
}; | |
#include <shared/poppack.h> | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
// If the window is in one axis, the coordinate and size on that axis | |
// is not set, as there doesn't seem to be any way to get the | |
// unmaximized size of an X window. So this grabs that info if it's | |
// available, and leaves the old values in place if it isn't. | |
bool GetXWindowPlacement(XWindowPlacement *placement, | |
_XDisplay *display, | |
uint64_t window); | |
void SetXWindowPlacement(_XDisplay *display, | |
uint64_t window, | |
const XWindowPlacement &placement); | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment