codehenry / xmonad

Automatically exported from code.google.com/p/xmonad
0 stars 0 forks source link

xmonad gives bogus configure events #566

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Compile the program below.
2. Run it.
3. Move the mouse pointer between windows.

What is the expected output? What do you see instead?

I don't expect to see configure events being generated and I certainly don't 
expect bogus broken ones to be generated.

What version of the product are you using? On what operating system?
xmonad 0.10, Linux

Are you using an xmonad.hs?  Please attach it and the output of "xmonad
--recompile".

import XMonad

import qualified XMonad.StackSet as W

import XMonad.Layout.MouseResizableTile
import XMonad.Layout.WindowNavigation
import XMonad.Layout.LayoutHints
import XMonad.Layout.Fullscreen

import XMonad.Hooks.Minimize
import XMonad.Layout.Minimize
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.FadeInactive

import XMonad.Util.EZConfig
import XMonad.Util.Run

import XMonad.Prompt
import XMonad.Prompt.RunOrRaise
import XMonad.Prompt.Shell

import XMonad.Config.Kde

main = do
  spawn "xmodmap -e 'keycode 135 = Super_R'"
  xmonad myConfig

baseConfig = kde4Config

myConfig = baseConfig
 { modMask = mod4Mask
 , borderWidth = 0
 , workspaces = fmap show [1 .. 4]
 , handleEventHook = myEventHook (handleEventHook baseConfig)
 , layoutHook = myLayout
 , manageHook = myManageHook (manageHook baseConfig)
 , logHook = myLogHook (logHook baseConfig)
 } `additionalKeysP`
 [ ("M-a", windows W.focusUp)
 , ("M-e", windows W.focusDown)

 , ("M-C-a", windows W.swapUp)
 , ("M-C-e", windows W.swapDown)

 , ("M-k", sendMessage ShrinkSlave)
 , ("M-j", sendMessage ExpandSlave)

 , ("M-p", shellPrompt $ defaultXPConfig {
           position = Top,
           height = 20
       })

 , ("M-<Return>", spawn "exec emacs")
 , ("M-S-<Return>", spawn "exec abrowser")
 ]

myEventHook baseHook =
  minimizeEventHook
  <+> hintsEventHook
  <+> baseHook
  <+> fullscreenEventHook

myManageHook baseHook = composeAll [
  baseHook
  , className =? "Do" --> doFloat
  , className =? "plasma-desktop" --> doFloat
  , className =? "Plasma-desktop" --> doFloat
  , className =? "klipper" --> doFloat
  , className =? "Klipper" --> doFloat
  , fullscreenManageHook]

myLayout =
  ( fullscreenFull
  . windowNavigation
  . avoidStrutsOn []
  . layoutHintsToCenter
  . minimize
  ) myBasicLayout

myBasicLayout = tileLayout ||| tileLayout { isMirrored = True } ||| Full where
  tileLayout = mouseResizableTile {
    draggerType = FixedDragger {
                gapWidth = 5
                , draggerWidth = 6
       }
    }

myLogHook baseLogHook = do
  baseLogHook
  fadeInactiveLogHook 0xee000000

Please provide any additional information below.

The C program:

#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glx.h>
#include <xcb/xcb.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <unistd.h>

static int errnum_from_connection(xcb_connection_t * connection)
{
    switch (xcb_connection_has_error(connection)) {
    case 0:
        return 0;

    case XCB_CONN_ERROR:
        return EPROTO;

    case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
        return ENOSYS;

    case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
        return ENOMEM;

    case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
        return EINVAL;

    case XCB_CONN_CLOSED_PARSE_ERR:
        return EINVAL;

    default:
        assert(false);
    }
}

int main(int argc, char *argv[])
{
    int error_status = 0;

    Display * display = XOpenDisplay(NULL);
    if (NULL == display) {
        perror("XOpenDisplay");
    }

    xcb_connection_t * connection = XGetXCBConnection(display);
    unsigned screen_number = XDefaultScreen(display);

    xcb_screen_t * screen = NULL;
    {
        xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
        for (size_t ii = 0; ii < screen_number; ++ii) {
            if (0 == iter.rem) {
                break;
            }

            xcb_screen_next (&iter);
        }

        if (0 == iter.rem) {
            error_status = EINVAL;
            goto disconnect;
        }

        screen = iter.data;
    }

    /* Query framebuffer configurations */
    GLXFBConfig fb_config;
    {
        static int const attrib_list[] = {
            GLX_BUFFER_SIZE, 0,       /* color index buffer size */
            GLX_LEVEL, 0    ,         /* buffer-level */
            GLX_DOUBLEBUFFER, True,   /* double buffer */

            GLX_STEREO, False,
            GLX_AUX_BUFFERS, 0,

            GLX_RED_SIZE, GLX_DONT_CARE,
            GLX_GREEN_SIZE, GLX_DONT_CARE,
            GLX_BLUE_SIZE, GLX_DONT_CARE,
            GLX_ALPHA_SIZE, GLX_DONT_CARE,

            GLX_DEPTH_SIZE, 16,

            GLX_STENCIL_SIZE, 0,
            GLX_ACCUM_RED_SIZE, 0,
            GLX_ACCUM_GREEN_SIZE, 0,
            GLX_ACCUM_BLUE_SIZE, 0,
            GLX_ACCUM_ALPHA_SIZE, 0,
            GLX_RENDER_TYPE, GLX_RGBA_BIT,

            GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,

            GLX_X_RENDERABLE, True,

            GLX_X_VISUAL_TYPE, GLX_DONT_CARE,

            GLX_CONFIG_CAVEAT, GLX_DONT_CARE,

            GLX_TRANSPARENT_TYPE, GLX_NONE,

            GLX_TRANSPARENT_INDEX_VALUE, GLX_DONT_CARE,
            GLX_TRANSPARENT_RED_VALUE, GLX_DONT_CARE,
            GLX_TRANSPARENT_GREEN_VALUE, GLX_DONT_CARE,
            GLX_TRANSPARENT_BLUE_VALUE, GLX_DONT_CARE,
            GLX_TRANSPARENT_ALPHA_VALUE, GLX_DONT_CARE,
            None
        };

        int configs_count;
        GLXFBConfig *configs = glXChooseFBConfig(display, screen_number,
                                                 attrib_list,
                                                 &configs_count);
        if (NULL == configs) {
            error_status = ENOSYS;
            goto disconnect;
        }
        fb_config = configs[0];
        XFree(configs);
    }

    int visual_id;
    switch (glXGetFBConfigAttrib(display, fb_config, GLX_VISUAL_ID, &visual_id)) {
    case GLX_NO_EXTENSION:
    case GLX_BAD_ATTRIBUTE:
        error_status = ENOSYS;
        goto disconnect;

    default:
        break;
    }

    GLXContext glx_context = glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, true);
    if (NULL == glx_context) {
        error_status = ENOSYS;
        goto disconnect;
    }

    xcb_colormap_t colormap = xcb_generate_id(connection);
    if ((error_status = errnum_from_connection(connection)) != 0) {
        goto destroy_glx_context;
    }

    xcb_create_colormap(connection, XCB_COLORMAP_ALLOC_NONE,
                        colormap,
                        screen->root,
                        visual_id);
    if ((error_status = errnum_from_connection(connection)) != 0) {
        goto destroy_glx_context;
    }

    xcb_window_t window = xcb_generate_id(connection);
    if ((error_status = errnum_from_connection(connection)) != 0) {
        goto destroy_glx_context;
    }

    {
        uint32_t values[] = {XCB_EVENT_MASK_STRUCTURE_NOTIFY, colormap, 0};
        xcb_create_window(connection,
                          XCB_COPY_FROM_PARENT,
                          window,
                          screen->root,
                          0, 0,
                          540, 480,
                          0,
                          XCB_WINDOW_CLASS_INPUT_OUTPUT,
                          visual_id,
                          XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, values);
    }
    if ((error_status = errnum_from_connection(connection)) != 0) {
        goto disconnect;
    }

    xcb_map_window(connection, window);
    if ((error_status = errnum_from_connection(connection)) != 0) {
        goto destroy_window;
    }

    xcb_flush(connection);
    if ((error_status = errnum_from_connection(connection)) != 0) {
        goto destroy_window;
    }

    GLXWindow glxwindow = glXCreateWindow(display,
                                          fb_config,
                                          window,
                                          0);
    if (!window) {
        error_status = ENOSYS;
        goto destroy_window;
    }

    xcb_atom_t wm_delete_window;
    {
        xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, 1, 12,
                                                          "WM_PROTOCOLS");
        if ((error_status = errnum_from_connection(connection)) != 0) {
            goto destroy_glx_window;
        }

        xcb_generic_error_t *error = NULL;
        xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(connection, cookie, &error);
        if ((error_status = errnum_from_connection(connection)) != 0) {
            goto destroy_glx_window;
        }
        if (error != NULL) {
            free(error);
            error_status = ENOSYS;
            goto destroy_glx_window;
        }

        xcb_atom_t wm_protocols = reply->atom;
        free(reply);

        xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(connection, 0, 16,
                                                           "WM_DELETE_WINDOW");
        if ((error_status = errnum_from_connection(connection)) != 0) {
            goto destroy_glx_window;
        }

        xcb_intern_atom_reply_t* reply2 = xcb_intern_atom_reply(connection, cookie2, &error);
        if ((error_status = errnum_from_connection(connection)) != 0) {
            goto destroy_glx_window;
        }
        if (error != NULL) {
            free(error);
            error_status = ENOSYS;
            goto destroy_glx_window;
        }

        wm_delete_window = reply2->atom;
        free(reply2);

        xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, wm_protocols, 4, 32, 1,
                            &wm_delete_window);
        if ((error_status = errnum_from_connection(connection)) != 0) {
            goto destroy_glx_window;
        }
    }

    if (!glXMakeContextCurrent(display,
                               glxwindow,
                               glxwindow,
                               glx_context)) {
        error_status = ENOSYS;
        goto destroy_glx_window;
    }

    for (;;) {
        /* Handle GUI events first before rendering */
        /* We have to use the Xlib event queue because of broken Mesa
         * libraries which abuse it.
         */
        XEvent event;
        XNextEvent(display, &event);
        switch (event.type) {
            {
            case ConfigureNotify:;
                XConfigureEvent* configure_event = (void*)&event;

                fprintf(stderr,
                        "Configure:\n"
                        "serial: %lu\n"
                        "send_event: %u\n"
                        "display: %p\n"
                        "x: %i y: %i\n"
                        "width: %i height: %i!\n"
                        "border_width: %u\n",
                        configure_event->serial,
                        configure_event->send_event,
                        configure_event->display,
                        configure_event->x, configure_event->y,
                        configure_event->width, configure_event->height,
                        configure_event->border_width);

                glViewport(0, 0, configure_event->width, configure_event->height);
                glClear(GL_COLOR_BUFFER_BIT);
                glXSwapBuffers(display, glxwindow);
                break;
            }

        case ClientMessage:;
            goto cleanup_gl;

        default:
            /* Unknown event type, ignore it */
            break;
        }
    }

 cleanup_gl:

 destroy_glx_window:
    glXDestroyWindow(display, glxwindow);

 destroy_window:
    xcb_destroy_window(connection, window);
    {
        int errnum = errnum_from_connection(connection);
        if (0 == error_status) {
            error_status = errnum;
        }
    }

 destroy_glx_context:
    glXMakeContextCurrent(display, None, None, NULL);
    glXDestroyContext(display, glx_context);

 disconnect:
    xcb_flush(connection);
    {
        int errnum = errnum_from_connection(connection);
        if (0 == error_status) {
            error_status = errnum;
        }
    }

    XCloseDisplay(display);

 shutdown:

    return error_status;
}

Original issue reported on code.google.com by StevensE...@gmail.com on 3 May 2014 at 5:11

GoogleCodeExporter commented 8 years ago
I should mention that the windows need to be console windows (the kind that 
have to be multiples of the console character size) to trigger the configure 
events.

Also, here is a much simpler version of the code.

#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int error_status = 0;

    Display * display = XOpenDisplay(NULL);
    if (NULL == display) {
        perror("XOpenDisplay");
    }

    unsigned screen_number = XDefaultScreen(display);

    /* Query framebuffer configurations */
    XVisualInfo visual_info;
    {
        static int const attrib_list[] = {
            GLX_RGBA, True,

            GLX_RED_SIZE, 5,
            GLX_GREEN_SIZE, 5,
            GLX_BLUE_SIZE, 3,

            GLX_DOUBLEBUFFER, True,
            GLX_DEPTH_SIZE, 16,
            None
        };

        XVisualInfo *ptr = glXChooseVisual(display, screen_number,
                                           (int*)attrib_list);
        if (NULL == ptr) {
            error_status = ENOSYS;
            goto disconnect;
        }
        visual_info = *ptr;
        XFree(ptr);
    }

    Colormap cmap = XCreateColormap(display, DefaultRootWindow(display),
                                    visual_info.visual, AllocNone);

    XSetWindowAttributes attributes;
    memset(&attributes, 0, sizeof attributes);

    attributes.colormap = cmap;
    attributes.event_mask = StructureNotifyMask;

    Window window = XCreateWindow(display,
                                  RootWindow(display, visual_info.screen),
                                  0, 0,
                                  600, 600,
                                  0,
                                  visual_info.depth,
                                  InputOutput, visual_info.visual,
                                  CWColormap | CWEventMask, &attributes);

    XMapWindow(display, window);

    GLXContext glx_context = glXCreateContext(display, &visual_info, NULL, GL_TRUE);
    if (NULL == glx_context) {
        error_status = ENOSYS;
        goto destroy_window;
    }

    if (!glXMakeContextCurrent(display,
                               window,
                               window,
                               glx_context)) {
        error_status = ENOSYS;
        goto destroy_window;
    }

    for (;;) {
        /* Handle GUI events first before rendering */
        /* We have to use the Xlib event queue because of broken Mesa
         * libraries which abuse it.
         */
        XEvent event;
        XNextEvent(display, &event);
        switch (event.type) {
            {
            case ConfigureNotify:;
                XConfigureEvent* configure_event = &event.xconfigure;

                fprintf(stderr,
                        "Configure:\n"
                        "serial: %lu\n"
                        "send_event: %u\n"
                        "display: %p\n"
                        "x: %i y: %i\n"
                        "width: %i height: %i!\n"
                        "border_width: %u\n",
                        configure_event->serial,
                        configure_event->send_event,
                        configure_event->display,
                        configure_event->x, configure_event->y,
                        configure_event->width, configure_event->height,
                        configure_event->border_width);

                glViewport(0, 0, configure_event->width, configure_event->height);
                glClear(GL_COLOR_BUFFER_BIT);
                glXSwapBuffers(display, window);
                break;
            }

        case ClientMessage:;
            goto destroy_glx_context;

        default:
            /* Unknown event type, ignore it */
            break;
        }
    }

 destroy_glx_context:
    glXMakeContextCurrent(display, None, None, NULL);
    glXDestroyContext(display, glx_context);

 destroy_window:
    XDestroyWindow(display, window);

 disconnect:
    XCloseDisplay(display);

 shutdown:

    return error_status;
}

Original comment by StevensE...@gmail.com on 3 May 2014 at 7:43

GoogleCodeExporter commented 8 years ago
Does this happen with the default configuration? If not, could you spend a 
little bit of time to try to minimize your config for us?

For others reading: compiling the given C program requires -lX11 -lGL in the 
compile line.

Original comment by daniel.w...@gmail.com on 4 May 2014 at 9:57

GoogleCodeExporter commented 8 years ago
(I do not see configure events happening in my config, even when testing with a 
terminal and a gvim open, which both specify resize increments in their window 
manager hints.)

Original comment by daniel.w...@gmail.com on 4 May 2014 at 9:58

GoogleCodeExporter commented 8 years ago
I'm not having a good weekend so have not been looking closely at this, but the 
first comment points to (and my initial suspicion was) the layout hints module, 
and probably hintsEventHook in particular. (Also my personal observation is 
that that module seems to cause more problems than it fixes....)

Original comment by allber...@gmail.com on 4 May 2014 at 10:02

GoogleCodeExporter commented 8 years ago
Yep layoutHints seems to be causing the problem. Thank you, very much.

Original comment by StevensE...@gmail.com on 8 May 2014 at 9:30