Check-in [17ccc163e4]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixed the sporadic recognitions of key bindings, especially the ones with modifiers. The problem turned out to be a lack of additional grabs with the various combinations of the lock modifiers; without these, the Caps Lock, Num Lock, etc. totally screw up the key binding logic because the X server doesn't even recognize them and, therefore, doesn't generate the necessary keyboard events.

Got the idea for this from a cursory perusal of the code for xbindkeys. And now (at long last) key bindings work flawlessly! Getting close to the 0.2.0 release...

Timelines: family | ancestors | descendants | both | dev1.x
Files: files | file ages | folders
SHA1:17ccc163e41043a9c1b2da391833e44d1178ce13
User & Date: manuv 2013-07-28 12:14:33
Context
2013-07-28
12:49
Centralized Boost.Python converter registration in python.cc because, for example, both minxlib::display and minxlib::window return STL vectors of window objects and we would like to avoid registering duplicate converters for the same types, a situation more likely to arise when the converters are registered from the pythonize() functions of the different classes. check-in: 471330b4ef user: manuv tags: dev1.x
12:14
Fixed the sporadic recognitions of key bindings, especially the ones with modifiers. The problem turned out to be a lack of additional grabs with the various combinations of the lock modifiers; without these, the Caps Lock, Num Lock, etc. totally screw up the key binding logic because the X server doesn't even recognize them and, therefore, doesn't generate the necessary keyboard events.

Got the idea for this from a cursory perusal of the code for xbindkeys. And now (at long last) key bindings work flawlessly! Getting close to the 0.2.0 release... check-in: 17ccc163e4 user: manuv tags: dev1.x

01:29
Added support for making layouts invisible. check-in: d02dcfd679 user: manuv tags: dev1.x
Changes

Changes to layout/base.py.

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
        @param w The @ref minxlib::window "minxlib.window" to be managed.

        This method tells the layout that it should manage the given
        window, which involves, among other things, reparenting the
        client window so that this layout becomes its parent.

        """
        w.select_events(minxlib.key_press_mask | minxlib.focus_change_mask)
        w.reparent(self.window)

    # Reparent notification
    def reparented(self, w):
        """Reparent notification.

        @param w The @ref minxlib::window "minxlib.window" that was reparented.







|







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
        @param w The @ref minxlib::window "minxlib.window" to be managed.

        This method tells the layout that it should manage the given
        window, which involves, among other things, reparenting the
        client window so that this layout becomes its parent.

        """
        w.select_events(minxlib.focus_change_mask)
        w.reparent(self.window)

    # Reparent notification
    def reparented(self, w):
        """Reparent notification.

        @param w The @ref minxlib::window "minxlib.window" that was reparented.

Changes to minxlib/window.cc.

307
308
309
310
311
312
313
314


315
316

317
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337







338
339
340
341
342
343
344
...
348
349
350
351
352
353
354

355
356






















357
358
359
360
361
362
363

    KeyCode keycode = XKeysymToKeycode(m_display, keysym) ;
    if (keycode == 0) {
        logger.warning() << "no keycode matching \"" << key << '"';
        return ;
    }
    logger.debug() << "keycode for \"" << key << "\" = "
                   << dec << static_cast<int>(keycode) ;



    // Setup map for modifier short-hands

    typedef std::map<std::string, unsigned int> modmap ;
    static modmap modifier_masks ;

    if (modifier_masks.empty()) {
        modifier_masks["C" ] = ControlMask ;
        modifier_masks["S" ] = ShiftMask;
        modifier_masks["M1"] = Mod1Mask ;
        modifier_masks["M2"] = Mod2Mask ;
        modifier_masks["M3"] = Mod3Mask ;
        modifier_masks["M4"] = Mod4Mask ;
        modifier_masks["M5"] = Mod5Mask ;

        // Now for ALT and META short-hands
        XModifierKeymap*  mkmap = XGetModifierMapping(m_display) ;
        if (mkmap) {
            modifier_masks["A"] = modmask(XK_Alt_L , mkmap, m_display);
            modifier_masks["M"] = modmask(XK_Meta_L, mkmap, m_display);
            uint32_t mask =
                keymap::ignore_lock_modifiers(mkmap, m_display) ;
            logger.debug() << "set modifier testing mask to 0x"
                           << hex << setw(4) << setfill('0') << mask ;
            XFreeModifiermap(mkmap) ;







        }
    }

    // First n-1 strings of split are the modifiers
    split.pop_back() ;
    unsigned int mask = 0 ;
    BOOST_FOREACH(const std::string& s, split)
................................................................................
            mask |= it->second ;
    }
    if (!mask)
        mask = AnyModifier ;
    logger.debug() << "modifier mask for \""   << key_binding << "\" = 0x"
                   << hex << setw(4) << setfill('0') << mask ;


    XGrabKey(m_display, keycode, mask, m_id,
             False, GrabModeAsync, GrabModeAsync) ;






















    keymap::bind(keycode, mask, key_binding) ;
}

//----------------------- WINDOW VISIBILITY ----------------------------

void window::show()
{







|
>
>

|
>


>









|


|
|





>
>
>
>
>
>
>







 







>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

    KeyCode keycode = XKeysymToKeycode(m_display, keysym) ;
    if (keycode == 0) {
        logger.warning() << "no keycode matching \"" << key << '"';
        return ;
    }
    logger.debug() << "keycode for \"" << key << "\" = "
                   << dec << static_cast<int>(keycode) << " (0x"
                   << hex << setw(4) << setfill('0')
                   << static_cast<int>(keycode) << ')' ;

    // Setup map for modifier short-hands and also initialize the list of
    // masks for the different lock modifiers.
    typedef std::map<std::string, unsigned int> modmap ;
    static modmap modifier_masks ;
    static std::vector<uint32_t> lock_masks;
    if (modifier_masks.empty()) {
        modifier_masks["C" ] = ControlMask ;
        modifier_masks["S" ] = ShiftMask;
        modifier_masks["M1"] = Mod1Mask ;
        modifier_masks["M2"] = Mod2Mask ;
        modifier_masks["M3"] = Mod3Mask ;
        modifier_masks["M4"] = Mod4Mask ;
        modifier_masks["M5"] = Mod5Mask ;

        // Now for ALT and META short-hands and the lock masks
        XModifierKeymap*  mkmap = XGetModifierMapping(m_display) ;
        if (mkmap) {
            modifier_masks["A"] = modmask(XK_Alt_L , mkmap, m_display) ;
            modifier_masks["M"] = modmask(XK_Meta_L, mkmap, m_display) ;
            uint32_t mask =
                keymap::ignore_lock_modifiers(mkmap, m_display) ;
            logger.debug() << "set modifier testing mask to 0x"
                           << hex << setw(4) << setfill('0') << mask ;
            XFreeModifiermap(mkmap) ;

            mask = ~mask & 0xFF ;
            logger.debug() << "lock masks = 0x"
                           << hex << setw(4) << setfill('0') << mask ;
            for (int i = 0; i < 8; ++i)
                if (mask & (1 << i))
                    lock_masks.push_back(1 << i) ;
        }
    }

    // First n-1 strings of split are the modifiers
    split.pop_back() ;
    unsigned int mask = 0 ;
    BOOST_FOREACH(const std::string& s, split)
................................................................................
            mask |= it->second ;
    }
    if (!mask)
        mask = AnyModifier ;
    logger.debug() << "modifier mask for \""   << key_binding << "\" = 0x"
                   << hex << setw(4) << setfill('0') << mask ;

    // Setup primary grab for key binding using plain modifier mask
    XGrabKey(m_display, keycode, mask, m_id,
             False, GrabModeAsync, GrabModeAsync) ;

    // Setup additional grabs with modifiers augmented with lock masks
    if (mask != AnyModifier) {
        unsigned int n = (1 << lock_masks.size()) - 1 ;
        for (unsigned int i = 1; i <= n; ++i) {
            uint32_t  lock_mask = 0;
            for (unsigned int j = 0; j < lock_masks.size(); ++j)
                if (i & (1 << j))
                    lock_mask |= lock_masks[j] ;

            logger.debug() << "setting up additional grab for \""
                           << key_binding << "\" with modifier mask 0x"
                           << hex << setw(4) << setfill('0')
                           << (mask | lock_mask) ;
            XGrabKey(m_display, keycode, mask | lock_mask, m_id,
                     False, GrabModeAsync, GrabModeAsync) ;
        }
    }

    // Store mapping between grab and key binding name so we can
    // translate keyboard events to the named key bindings as specified
    // by Minx's end-users.
    keymap::bind(keycode, mask, key_binding) ;
}

//----------------------- WINDOW VISIBILITY ----------------------------

void window::show()
{