linux: a few small improvements:

* Add PropertyChangeMask to events, makes compiz redraw better with (un)maximizing
* Create the window on the default screen instead of iterating through all of them
* Set backing store hint, looks nicer when moving stuff over the 4ed window
* Set some other WM hints like min/max/default size, gravity, etc since most other
  apps seem to set them
master
insofaras 2016-05-31 00:30:06 +01:00
parent 4815ab8620
commit 16677d3f90
1 changed files with 69 additions and 81 deletions

View File

@ -136,6 +136,9 @@ struct Linux_Vars{
Atom atom__NET_WM_STATE_MAXIMIZED_HORZ;
Atom atom__NET_WM_STATE_MAXIMIZED_VERT;
Atom atom__NET_WM_PING;
Atom atom__NET_WM_WINDOW_TYPE;
Atom atom__NET_WM_WINDOW_TYPE_NORMAL;
Atom atom__NET_WM_PID;
Atom atom_WM_DELETE_WINDOW;
b32 has_xfixes;
@ -1601,6 +1604,7 @@ LinuxInputInit(Display *dpy, Window XWindow)
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PropertyChangeMask |
PointerMotionMask |
FocusChangeMask |
StructureNotifyMask |
@ -1840,93 +1844,66 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
// Behold the true nature of this wonderful OS:
// (thanks again to Casey for providing this stuff)
Colormap cmap;
XSetWindowAttributes swa;
b32 window_setup_success = 0;
#define BASE_W 800
#define BASE_H 600
if (linuxvars.settings.set_window_size){
*WinWidth = linuxvars.settings.window_w;
*WinHeight = linuxvars.settings.window_h;
} else {
*WinWidth = 800;
*WinHeight = 600;
*WinWidth = BASE_W;
*WinHeight = BASE_H;
}
int XScreenCount = ScreenCount(linuxvars.XDisplay);
glx_config_result Config = {};
if(!GLXCanUseFBConfig(linuxvars.XDisplay)){
if (!GLXCanUseFBConfig(linuxvars.XDisplay)){
fprintf(stderr, "Your GLX version is too old.\n");
return false;
}
// TODO(inso): maybe should try the default screen first? or only the default without iterating.
for(int XScreenIndex = 0;
XScreenIndex < XScreenCount;
++XScreenIndex)
{
Screen *XScreen = ScreenOfDisplay(linuxvars.XDisplay, XScreenIndex);
i32 ScrnWidth, ScrnHeight;
ScrnWidth = WidthOfScreen(XScreen);
ScrnHeight = HeightOfScreen(XScreen);
if (ScrnWidth + 50 < *WinWidth) *WinWidth = ScrnWidth + 50;
if (ScrnHeight + 50 < *WinHeight) *WinHeight = ScrnHeight + 50;
Config = ChooseGLXConfig(linuxvars.XDisplay, XScreenIndex);
if(Config.Found)
{
swa.colormap = cmap = XCreateColormap(linuxvars.XDisplay,
RootWindow(linuxvars.XDisplay, Config.BestInfo.screen ),
Config.BestInfo.visual, AllocNone);
swa.background_pixmap = None;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
linuxvars.XWindow =
XCreateWindow(linuxvars.XDisplay,
RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
0, 0, *WinWidth, *WinHeight,
0, Config.BestInfo.depth, InputOutput,
Config.BestInfo.visual,
CWBorderPixel|CWColormap|CWEventMask, &swa);
if(linuxvars.XWindow)
{
window_setup_success = 1;
break;
}
}
glx_config_result Config = ChooseGLXConfig(linuxvars.XDisplay, DefaultScreen(linuxvars.XDisplay));
if (!Config.Found){
fprintf(stderr, "Could not create GLX FBConfig.\n");
}
if (!window_setup_success){
XSetWindowAttributes swa = {};
swa.backing_store = WhenMapped;
swa.event_mask = StructureNotifyMask;
swa.bit_gravity = NorthWestGravity;
swa.colormap = XCreateColormap(linuxvars.XDisplay,
RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
Config.BestInfo.visual, AllocNone);
linuxvars.XWindow =
XCreateWindow(linuxvars.XDisplay,
RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
0, 0, *WinWidth, *WinHeight,
0, Config.BestInfo.depth, InputOutput,
Config.BestInfo.visual,
CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
if (!linuxvars.XWindow){
fprintf(stderr, "Error creating window.\n");
return false;
}
//NOTE(inso): Set the window's type to normal
Atom _NET_WM_WINDOW_TYPE = XInternAtom(linuxvars.XDisplay, "_NET_WM_WINDOW_TYPE", False);
Atom _NET_WIN_TYPE_NORMAL = XInternAtom(linuxvars.XDisplay, "_NET_WM_WINDOW_TYPE_NORMAL", False);
XChangeProperty(
linuxvars.XDisplay,
linuxvars.XWindow,
_NET_WM_WINDOW_TYPE,
linuxvars.atom__NET_WM_WINDOW_TYPE,
XA_ATOM,
32,
PropModeReplace,
(unsigned char*)&_NET_WIN_TYPE_NORMAL,
(unsigned char*)&linuxvars.atom__NET_WM_WINDOW_TYPE_NORMAL,
1
);
//NOTE(inso): window managers want the PID as a window property for some reason.
Atom _NET_WM_PID = XInternAtom(linuxvars.XDisplay, "_NET_WM_PID", False);
pid_t pid = getpid();
XChangeProperty(
linuxvars.XDisplay,
linuxvars.XWindow,
_NET_WM_PID,
linuxvars.atom__NET_WM_PID,
XA_CARDINAL,
32,
PropModeReplace,
@ -1939,45 +1916,53 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
//NOTE(inso): set wm properties
XStoreName(linuxvars.XDisplay, linuxvars.XWindow, WINDOW_NAME);
char* win_name_list[] = { WINDOW_NAME };
XTextProperty win_name;
XStringListToTextProperty(win_name_list, 1, &win_name);
XSizeHints *sz_hints = XAllocSizeHints();
XWMHints *wm_hints = XAllocWMHints();
XClassHint *cl_hints = XAllocClassHint();
if(linuxvars.settings.set_window_pos){
sz_hints->flags = PMinSize | PMaxSize | PBaseSize | PWinGravity;
sz_hints->min_width = 50;
sz_hints->min_height = 50;
sz_hints->max_width = sz_hints->max_height = (1UL << 16UL);
sz_hints->base_width = BASE_W;
sz_hints->base_height = BASE_H;
sz_hints->win_gravity = NorthWestGravity;
if (linuxvars.settings.set_window_pos){
sz_hints->flags |= USPosition;
sz_hints->x = linuxvars.settings.window_x;
sz_hints->y = linuxvars.settings.window_y;
}
wm_hints->flags |= InputHint;
wm_hints->flags |= InputHint | StateHint;
wm_hints->input = True;
wm_hints->initial_state = NormalState;
cl_hints->res_name = "4coder";
cl_hints->res_class = "4coder";
char* win_name_list[] = { WINDOW_NAME };
XTextProperty win_name;
XStringListToTextProperty(win_name_list, 1, &win_name);
XSetWMProperties(
linuxvars.XDisplay,
linuxvars.XWindow,
&win_name,
NULL,
argv,
argc,
sz_hints,
wm_hints,
cl_hints
&win_name, NULL,
argv, argc,
sz_hints, wm_hints, cl_hints
);
XFree(win_name.value);
XFree(sz_hints);
XFree(wm_hints);
XFree(cl_hints);
XFree(win_name.value);
LinuxSetIcon(linuxvars.XDisplay, linuxvars.XWindow);
//NOTE(inso): make the window visible
@ -1987,15 +1972,7 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
GLXContext GLContext =
InitializeOpenGLContext(linuxvars.XDisplay, linuxvars.XWindow, Config.BestConfig, IsLegacy);
XWindowAttributes WinAttribs;
if(XGetWindowAttributes(linuxvars.XDisplay, linuxvars.XWindow, &WinAttribs))
{
*WinWidth = WinAttribs.width;
*WinHeight = WinAttribs.height;
}
XRaiseWindow(linuxvars.XDisplay, linuxvars.XWindow);
XSync(linuxvars.XDisplay, False);
if (linuxvars.settings.set_window_pos){
XMoveWindow(
@ -2009,6 +1986,14 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
if (linuxvars.settings.maximize_window){
LinuxMaximizeWindow(linuxvars.XDisplay, linuxvars.XWindow, 1);
}
XSync(linuxvars.XDisplay, False);
XWindowAttributes WinAttribs;
if (XGetWindowAttributes(linuxvars.XDisplay, linuxvars.XWindow, &WinAttribs))
{
*WinWidth = WinAttribs.width;
*WinHeight = WinAttribs.height;
}
Atom wm_protos[] = {
linuxvars.atom_WM_DELETE_WINDOW,
@ -2495,7 +2480,7 @@ main(int argc, char **argv)
sem_init(&linuxvars.thread_semaphores[BACKGROUND_THREADS], 0, 0);
exchange_vars.thread.queues[BACKGROUND_THREADS].semaphore =
LinuxSemToHandle(&linuxvars.thread_semaphores[BACKGROUND_THREADS]);
LinuxSemToHandle(&linuxvars.thread_semaphores[BACKGROUND_THREADS]);
for(i32 i = 0; i < linuxvars.groups[BACKGROUND_THREADS].count; ++i){
Thread_Context *thread = linuxvars.groups[BACKGROUND_THREADS].threads + i;
@ -2522,7 +2507,7 @@ main(int argc, char **argv)
fprintf(stderr, "Can't open display!\n");
return 1;
}
#define LOAD_ATOM(x) linuxvars.atom_##x = XInternAtom(linuxvars.XDisplay, #x, False);
LOAD_ATOM(CLIPBOARD);
@ -2531,6 +2516,9 @@ main(int argc, char **argv)
LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
LOAD_ATOM(_NET_WM_PING);
LOAD_ATOM(_NET_WM_WINDOW_TYPE);
LOAD_ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
LOAD_ATOM(_NET_WM_PID);
LOAD_ATOM(WM_DELETE_WINDOW);
#undef LOAD_ATOM