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
This commit is contained in:
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_HORZ;
Atom atom__NET_WM_STATE_MAXIMIZED_VERT; Atom atom__NET_WM_STATE_MAXIMIZED_VERT;
Atom atom__NET_WM_PING; 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; Atom atom_WM_DELETE_WINDOW;
b32 has_xfixes; b32 has_xfixes;
@ -1601,6 +1604,7 @@ LinuxInputInit(Display *dpy, Window XWindow)
KeyPressMask | KeyReleaseMask | KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask | ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask | EnterWindowMask | LeaveWindowMask |
PropertyChangeMask |
PointerMotionMask | PointerMotionMask |
FocusChangeMask | FocusChangeMask |
StructureNotifyMask | StructureNotifyMask |
@ -1840,93 +1844,66 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
// Behold the true nature of this wonderful OS: // Behold the true nature of this wonderful OS:
// (thanks again to Casey for providing this stuff) // (thanks again to Casey for providing this stuff)
Colormap cmap; #define BASE_W 800
XSetWindowAttributes swa; #define BASE_H 600
b32 window_setup_success = 0;
if (linuxvars.settings.set_window_size){ if (linuxvars.settings.set_window_size){
*WinWidth = linuxvars.settings.window_w; *WinWidth = linuxvars.settings.window_w;
*WinHeight = linuxvars.settings.window_h; *WinHeight = linuxvars.settings.window_h;
} else { } else {
*WinWidth = 800; *WinWidth = BASE_W;
*WinHeight = 600; *WinHeight = BASE_H;
} }
int XScreenCount = ScreenCount(linuxvars.XDisplay); if (!GLXCanUseFBConfig(linuxvars.XDisplay)){
glx_config_result Config = {};
if(!GLXCanUseFBConfig(linuxvars.XDisplay)){
fprintf(stderr, "Your GLX version is too old.\n"); fprintf(stderr, "Your GLX version is too old.\n");
return false; return false;
} }
// TODO(inso): maybe should try the default screen first? or only the default without iterating. glx_config_result Config = ChooseGLXConfig(linuxvars.XDisplay, DefaultScreen(linuxvars.XDisplay));
if (!Config.Found){
for(int XScreenIndex = 0; fprintf(stderr, "Could not create GLX FBConfig.\n");
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;
}
}
} }
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"); fprintf(stderr, "Error creating window.\n");
return false; return false;
} }
//NOTE(inso): Set the window's type to normal //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( XChangeProperty(
linuxvars.XDisplay, linuxvars.XDisplay,
linuxvars.XWindow, linuxvars.XWindow,
_NET_WM_WINDOW_TYPE, linuxvars.atom__NET_WM_WINDOW_TYPE,
XA_ATOM, XA_ATOM,
32, 32,
PropModeReplace, PropModeReplace,
(unsigned char*)&_NET_WIN_TYPE_NORMAL, (unsigned char*)&linuxvars.atom__NET_WM_WINDOW_TYPE_NORMAL,
1 1
); );
//NOTE(inso): window managers want the PID as a window property for some reason. //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(); pid_t pid = getpid();
XChangeProperty( XChangeProperty(
linuxvars.XDisplay, linuxvars.XDisplay,
linuxvars.XWindow, linuxvars.XWindow,
_NET_WM_PID, linuxvars.atom__NET_WM_PID,
XA_CARDINAL, XA_CARDINAL,
32, 32,
PropModeReplace, PropModeReplace,
@ -1939,45 +1916,53 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
//NOTE(inso): set wm properties //NOTE(inso): set wm properties
XStoreName(linuxvars.XDisplay, linuxvars.XWindow, WINDOW_NAME); 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(); XSizeHints *sz_hints = XAllocSizeHints();
XWMHints *wm_hints = XAllocWMHints(); XWMHints *wm_hints = XAllocWMHints();
XClassHint *cl_hints = XAllocClassHint(); 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->flags |= USPosition;
sz_hints->x = linuxvars.settings.window_x; sz_hints->x = linuxvars.settings.window_x;
sz_hints->y = linuxvars.settings.window_y; sz_hints->y = linuxvars.settings.window_y;
} }
wm_hints->flags |= InputHint; wm_hints->flags |= InputHint | StateHint;
wm_hints->input = True; wm_hints->input = True;
wm_hints->initial_state = NormalState;
cl_hints->res_name = "4coder"; cl_hints->res_name = "4coder";
cl_hints->res_class = "4coder"; cl_hints->res_class = "4coder";
char* win_name_list[] = { WINDOW_NAME };
XTextProperty win_name;
XStringListToTextProperty(win_name_list, 1, &win_name);
XSetWMProperties( XSetWMProperties(
linuxvars.XDisplay, linuxvars.XDisplay,
linuxvars.XWindow, linuxvars.XWindow,
&win_name, &win_name, NULL,
NULL, argv, argc,
argv, sz_hints, wm_hints, cl_hints
argc,
sz_hints,
wm_hints,
cl_hints
); );
XFree(win_name.value);
XFree(sz_hints); XFree(sz_hints);
XFree(wm_hints); XFree(wm_hints);
XFree(cl_hints); XFree(cl_hints);
XFree(win_name.value);
LinuxSetIcon(linuxvars.XDisplay, linuxvars.XWindow); LinuxSetIcon(linuxvars.XDisplay, linuxvars.XWindow);
//NOTE(inso): make the window visible //NOTE(inso): make the window visible
@ -1987,15 +1972,7 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
GLXContext GLContext = GLXContext GLContext =
InitializeOpenGLContext(linuxvars.XDisplay, linuxvars.XWindow, Config.BestConfig, IsLegacy); 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); XRaiseWindow(linuxvars.XDisplay, linuxvars.XWindow);
XSync(linuxvars.XDisplay, False);
if (linuxvars.settings.set_window_pos){ if (linuxvars.settings.set_window_pos){
XMoveWindow( XMoveWindow(
@ -2009,6 +1986,14 @@ b32 LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
if (linuxvars.settings.maximize_window){ if (linuxvars.settings.maximize_window){
LinuxMaximizeWindow(linuxvars.XDisplay, linuxvars.XWindow, 1); 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[] = { Atom wm_protos[] = {
linuxvars.atom_WM_DELETE_WINDOW, linuxvars.atom_WM_DELETE_WINDOW,
@ -2495,7 +2480,7 @@ main(int argc, char **argv)
sem_init(&linuxvars.thread_semaphores[BACKGROUND_THREADS], 0, 0); sem_init(&linuxvars.thread_semaphores[BACKGROUND_THREADS], 0, 0);
exchange_vars.thread.queues[BACKGROUND_THREADS].semaphore = 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){ for(i32 i = 0; i < linuxvars.groups[BACKGROUND_THREADS].count; ++i){
Thread_Context *thread = linuxvars.groups[BACKGROUND_THREADS].threads + i; Thread_Context *thread = linuxvars.groups[BACKGROUND_THREADS].threads + i;
@ -2531,6 +2516,9 @@ main(int argc, char **argv)
LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ); LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT); LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
LOAD_ATOM(_NET_WM_PING); 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); LOAD_ATOM(WM_DELETE_WINDOW);
#undef LOAD_ATOM #undef LOAD_ATOM