コード例 #1
0
ファイル: xview.c プロジェクト: sonald/semacs
static se_key se_key_event_process( Display *display, XKeyEvent kev )
{
    int index = 0;
    int mask = 0;
    
    if ( kev.state & ShiftMask ) {
        mask = 0x01;
    }
    if ( kev.state & LockMask ) {
        mask |= 0x02;
    }
    if ( mask ) index = 1;
    
    KeySym key_sym = XKeycodeToKeysym( display, kev.keycode, index );
    if ( key_sym == NoSymbol ) {
        se_debug( "NoSymbol for keycode %d", kev.keycode );
    }

    se_key sekey = se_key_null_init();
    char *key_str = XKeysymToString( key_sym );

    // FIXME: this is a simplified version, since KeySym actually follow latin-1
    // except for some terminal control keys
    if ( g_str_has_prefix(key_str, "Alt")
         || g_str_has_prefix(key_str, "Meta")
         || g_str_has_prefix(key_str, "Super")
         || g_str_has_prefix(key_str, "Control")
         || g_str_has_prefix(key_str, "Shift") ) {
        return sekey;
    }
    sekey.ascii = key_sym;
    
    if ( kev.state & ControlMask ) {
        sekey.modifiers |= ControlDown;
    }
    if ( kev.state & ShiftMask ) {
        sekey.modifiers |= ShiftDown;
    }
    if ( kev.state & Mod1Mask ) {
        sekey.modifiers |= MetaDown;
    }

    if ( kev.state & Mod4Mask ) {
        // this is no good, Mod4 can be map to other keysym
        sekey.modifiers |= SuperDown;
    }

    if ( sekey.modifiers == ShiftDown ) { // here Shift is not part of combination
                                        // only change case of char
        sekey.modifiers = 0;
    }
    
    se_debug( "sekey(%s): %s", key_str, se_key_to_string(sekey) );
    return sekey;
}
コード例 #2
0
ファイル: xview.c プロジェクト: sonald/semacs
static se_key se_delayed_wait_key(se_text_xviewer* viewer)
{
    se_debug( "waiting for a key..." );    
    XEvent ev;
    while ( XCheckWindowEvent( viewer->env->display, viewer->view,
                               KeyPressMask, &ev ) == False ) {
        usleep( 100 );
    }

    /* g_assert( ev.type == KeyPress ); */
    se_debug( "wait for a key done" );
    return se_key_event_process( viewer->env->display, ev.xkey );
}
コード例 #3
0
    virtual ActivePet* findByWindow(HWND window) {
	    DWORD pid = 0;
	    GetWindowThreadProcessId(window, &pid);
        auto_privilege se_debug(SE_DEBUG_NAME);
        auto_handle process(::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid));
	    return findByProcess(process.get());
    }
コード例 #4
0
ファイル: xview.c プロジェクト: sonald/semacs
/*
 * This function chooses the "more desirable" of two input styles.  The
 * style with the more complicated Preedit style is returned, and if the
 * styles have the same Preedit styles, then the style with the more
 * complicated Status style is returned.  There is no "official" way to
 * order interaction styles; this one seems reasonable, though.
 * This is a long procedure for a simple heuristic.
 */
static XIMStyle ChooseBetterStyle(XIMStyle style1, XIMStyle style2)
{
    XIMStyle s,t;
    XIMStyle preedit = XIMPreeditArea | XIMPreeditCallbacks |
        XIMPreeditPosition | XIMPreeditNothing | XIMPreeditNone;
    XIMStyle status = XIMStatusArea | XIMStatusCallbacks |
        XIMStatusNothing | XIMStatusNone;
    if (style1 == 0) {
        se_debug("use style2");
        return style2;
    }
    
    if (style2 == 0) {
        se_debug("use style1");
        return style1;
    }
    
    if ((style1 & (preedit | status)) == (style2 & (preedit | status)))
        return style1;
    s = style1 & preedit;
    t = style2 & preedit;
    if (s != t) {
        if (s | t | XIMPreeditCallbacks)
            return (s == XIMPreeditCallbacks)?style1:style2;
        else if (s | t | XIMPreeditPosition)
            return (s == XIMPreeditPosition)?style1:style2;
        else if (s | t | XIMPreeditArea)
            return (s == XIMPreeditArea)?style1:style2;
        else if (s | t | XIMPreeditNothing)
            return (s == XIMPreeditNothing)?style1:style2;
    }
    else { /* if preedit flags are the same, compare status flags */
        s = style1 & status;
        t = style2 & status;
        if (s | t | XIMStatusCallbacks)
            return (s == XIMStatusCallbacks)?style1:style2;
        else if (s | t | XIMStatusArea)
            return (s == XIMStatusArea)?style1:style2;
        else if (s | t | XIMStatusNothing)
            return (s == XIMStatusNothing)?style1:style2;
    }

    return 0;
}
コード例 #5
0
ファイル: xview.c プロジェクト: sonald/semacs
static void se_text_xviewer_updateSize( se_text_xviewer* viewer, int width, int height )
{
    assert( viewer );
    assert( width && height );
    
    viewer->physicalWidth = width;
    viewer->physicalHeight = height;

    const se_env* env = viewer->env;
    viewer->columns = width / env->glyphMaxWidth;
    viewer->rows = height / env->glyphMaxHeight;

    se_debug( "new size in pixels (%d, %d), in chars (%d, %d)",
              width, height, viewer->columns, viewer->rows );    
    //TODO: check if cursor if out of display
}
コード例 #6
0
ファイル: xview.c プロジェクト: sonald/semacs
static void dump_style( XIMStyle best_style )
{
    GString *style_str = g_string_new("");
    if ( best_style & XIMPreeditCallbacks)
        g_string_append_printf( style_str, ",%s", "XIMPreeditCallbacks");
    if ( best_style & XIMPreeditPosition )
        g_string_append_printf( style_str, ",%s", "XIMPreeditPosition");
    if ( best_style & XIMPreeditArea     )
        g_string_append_printf( style_str, ",%s", "XIMPreeditArea");
    if ( best_style & XIMPreeditNothing  )
        g_string_append_printf( style_str, ",%s", "XIMPreeditNothing");
    if ( best_style & XIMPreeditNone     )
        g_string_append_printf( style_str, ",%s", "XIMPreeditNone");
    if ( best_style & XIMStatusCallbacks )
        g_string_append_printf( style_str, ",%s", "XIMStatusCallbacks");
    if ( best_style & XIMStatusArea      )
        g_string_append_printf( style_str, ",%s", "XIMStatusArea");
    if ( best_style & XIMStatusNothing   )
        g_string_append_printf( style_str, ",%s", "XIMStatusNothing");
    if ( best_style & XIMStatusNone      )
        g_string_append_printf( style_str, ",%s", "XIMStatusNone");
    se_debug("best_style: %s", style_str->str );
    g_string_free( style_str, True );
}
コード例 #7
0
ファイル: xview.c プロジェクト: sonald/semacs
// return TRUE if input is a composed str from IM, and returned from arg str
static gboolean se_text_xviewer_lookup_string(se_text_xviewer* viewer, XKeyEvent* kev,
                                             GString *str)
{
    char buf[64] = "";
    int buf_len = sizeof buf - 1;
    KeySym keysym;
    Status status;
    Xutf8LookupString( viewer->xic, kev, buf, buf_len, &keysym, &status );
    gboolean composed_input = FALSE;
    switch (status) {
    case XBufferOverflow:
        se_warn("XBufferOverflow");
        break;
        
    case XLookupNone:
        se_debug("XLookupNone");        
        break;
                
    case XLookupKeySym:
        if (status == XLookupKeySym) {
            se_debug( "XLookupKeySym: sym: %s", XKeysymToString(keysym) );
        }
        break;
        
    case XLookupBoth:
        se_debug( "XLookupBoth: sym: %s", XKeysymToString(keysym) );
        se_debug( "XLookupBoth: buf: [%s]", buf );
        if ((keysym == XK_Delete) || (keysym == XK_BackSpace)) {
            se_debug("delete");
            break;
        }
        break;
                
    case XLookupChars:
        se_debug( "XLookupChars: buf: [%s]", buf );
        g_string_printf( str, "%s", buf );
        composed_input = TRUE;
        break;
    }

    return composed_input;
}
コード例 #8
0
ファイル: xview.c プロジェクト: sonald/semacs
static void se_draw_buffer_point( se_text_xviewer* viewer )
{
    se_env *env = viewer->env;
    se_world *world = viewer->env->world;
    g_assert( world );

    se_buffer *cur_buf = world->current;
    g_assert( cur_buf );

    se_cursor point_cur = {
        .row = cur_buf->getLine( cur_buf ),
        .column = cur_buf->getCurrentColumn( cur_buf )
    };
    se_position point_pos = se_text_cursor_to_physical( viewer, point_cur );
    point_pos.y -= (env->glyphMaxHeight - env->glyphAscent)/2;
    

    XRenderColor renderClr = {
        .red = 0x00,
        .green = 0xffff,
        .blue = 0x00,
        .alpha = 0x00
    };
        
    XftColor clr;
    XftColorAllocValue( env->display, env->visual, env->colormap, &renderClr, &clr );
    
    XftDrawRect( viewer->xftDraw, &clr, point_pos.x, point_pos.y, 2, env->glyphMaxHeight );

    XftColorFree( env->display, env->visual, env->colormap, &clr );
}

// send draw event and do real update in redisplay routine
static void se_text_xviewer_repaint( se_text_xviewer* viewer )
{
    XWindowAttributes attrs;
    XGetWindowAttributes( viewer->env->display, viewer->view, &attrs);
    viewer->updateSize( viewer, attrs.width, attrs.height );

    //refill text viewer
    se_world *world = viewer->env->world;
    g_assert( world );

    se_buffer *cur_buf = world->current;
    g_assert( cur_buf );

    //FIXME: this is slow algo just as a demo, change it later
    se_line* lp = cur_buf->lines;
    int nr_lines = cur_buf->getLineCount( cur_buf );
    se_debug( "paint rect: rows: %d", nr_lines );
    
    for (int r = 0; r < MIN(viewer->rows, nr_lines); ++r) {
        const char* buf = se_line_getData( lp );
        int cols = se_line_getLineLength( lp );
        if ( buf[cols-1] == '\n' ) cols--;
        memcpy( (viewer->content + r*SE_MAX_ROWS), buf, cols );
        *(viewer->content + r*SE_MAX_ROWS+cols) = '\0';
        /* se_debug( "draw No.%d: [%s]", r, buf ); */
        lp = lp->next;
    }
}
コード例 #9
0
ファイル: xview.c プロジェクト: sonald/semacs
int main_loop(int argc, char *argv[])
{
    setup_language();
    se_env* env = se_env_init();
    se_text_xviewer* viewer = se_text_xviewer_create( env );
    
    long im_event_mask;
    XGetICValues( viewer->xic, XNFilterEvents, &im_event_mask, NULL );

    int mask = ExposureMask | ButtonPressMask | ButtonReleaseMask
        | KeyPressMask | KeyReleaseMask | SubstructureNotifyMask
        | FocusChangeMask
        | im_event_mask;
    XSelectInput( env->display, viewer->view, mask );
    XSetICFocus( viewer->xic );
    
    viewer->repaint( viewer );    
    viewer->show( viewer );
    
    while ( 1 ) { // sync the first expose event
        XEvent ev;
        XNextEvent( env->display, &ev );
        if ( ev.xany.window == viewer->view && ev.type == Expose ) {
            viewer->redisplay( viewer );
            break;
        }
    }

    while( !env->exitLoop ) {
        XEvent ev;
        XNextEvent( env->display, &ev );
        if ( XFilterEvent( &ev, None ) == True ) {
            se_debug("IM filtered event: %s", XEventTypeString(ev.type) );
            continue;
        }
        
        if ( ev.xany.window != viewer->view ) {
            se_msg( "skip event does not forward to view" );
            continue;
        }
        
        switch( ev.type ) {
        case Expose:
            se_debug( "Expose" );
            if ( ev.xexpose.count > 0 )
                break;

            viewer->redisplay( viewer );
            break;

        case KeyPress:
        case KeyRelease:
            viewer->key_handler( viewer, &ev );
            break;

        case ConfigureNotify:
        case MapNotify:
            se_debug( "confiugration changed" );
            viewer->configure_change_handler( viewer, &ev );
            break;

        default:
            break;
        }
    }

    se_debug( "exit loop" );

    XUnsetICFocus( viewer->xic );
    XDestroyIC( viewer->xic );
    se_env_release( env );
    return 0;
}
コード例 #10
0
ファイル: xview.c プロジェクト: sonald/semacs
se_text_xviewer* se_text_xviewer_create( se_env* env )
{
    se_text_xviewer* viewer = g_malloc0( sizeof(se_text_xviewer) );
    if ( !viewer ) {
        se_error( "can not malloc a viewer obj" );
    }

    viewer->env = env;
    
    int width = 800;
    int height = 600;
    
    viewer->view = XCreateSimpleWindow(
        env->display, env->root, 0, 0, width, height, 0,
        BlackPixel(env->display, env->screen),
        WhitePixel(env->display, env->screen) );
    
    viewer->key_handler = se_text_xviewer_key_event;
    viewer->mouse_handler = se_text_xviewer_mouse_event;
    viewer->configure_change_handler = se_text_xviewer_configure_change_handler;

    viewer->show = se_text_xviewer_show;
    viewer->repaint = se_text_xviewer_repaint;
    viewer->redisplay = se_text_xviewer_redisplay;
    viewer->updateSize = se_text_xviewer_updateSize;
    
    se_text_xviewer_draw_create( viewer );

    viewer->content = g_malloc0( SE_MAX_COLUMNS * SE_MAX_ROWS );

    XIMStyles *im_supported_styles;
    XIMStyle app_supported_styles;
    XIMStyle style;
    XIMStyle best_style;

    XGetIMValues( env->xim, XNQueryInputStyle, &im_supported_styles, NULL );
    app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditArea
        | XIMStatusNone | XIMStatusNothing | XIMStatusArea;
    best_style = 0;
    se_debug( "styles count: %d", im_supported_styles->count_styles );
    for(int i=0; i < im_supported_styles->count_styles; i++) {
        style = im_supported_styles->supported_styles[i];
        dump_style( style );
        if ((style & app_supported_styles) == style) /* if we can handle it */
            best_style = ChooseBetterStyle(style, best_style);
    }

    /* if we couldn't support any of them, print an error and exit */
    if (best_style == 0) {
        se_error("commonly supported interaction style.");
        exit(1);
    }
    XFree(im_supported_styles);
    dump_style( best_style );
    
    viewer->xic = XCreateIC(env->xim, XNInputStyle, best_style,
                            XNClientWindow, viewer->view,
                            NULL);
    if ( viewer->xic == NULL ) {
        se_debug(" create xic failed" );
        exit(1);        
    }
    se_debug( "XLocaleOfIM: %s", XLocaleOfIM( env->xim ) );
    
    return viewer;
}
コード例 #11
0
ファイル: xview.c プロジェクト: sonald/semacs
void se_text_xviewer_mouse_event(se_text_xviewer* viewer, XEvent* ev )
{
    se_debug( "enter mouse event" );
}
コード例 #12
0
ファイル: xview.c プロジェクト: sonald/semacs
static void se_text_xviewer_redisplay(se_text_xviewer* viewer )
{
    se_debug( "redisplay" );
    
    se_env *env = viewer->env;
    XRenderColor renderClr = {
        .red = 0x0,
        .green = 0x0,
        .blue = 0x0,
        .alpha = 0xffff
    };
        
    XftColor clr;
    XftColorAllocValue( env->display, env->visual, env->colormap, &renderClr, &clr );

    se_world *world = viewer->env->world;
    g_assert( world );
    se_buffer *cur_buf = world->current;
    g_assert( cur_buf );
    int nr_lines = cur_buf->getLineCount( cur_buf );
    se_debug( "update buf %s [%d, %d]", cur_buf->getBufferName(cur_buf),
              viewer->columns, MIN(viewer->rows, nr_lines) );    

    // this clear the whole window ( slow )
    XClearArea( env->display, viewer->view, 0, 0, 0, 0, False );
    
    viewer->cursor = (se_cursor){ 0, 0 };
    for (int r = 0; r < MIN(viewer->rows, nr_lines); ++r) {
        char *data = viewer->content + r*SE_MAX_ROWS;
        int data_len = strlen( data );
        se_draw_text_utf8( viewer, &clr, viewer->cursor,
                           data, MIN(data_len, viewer->columns) );
        viewer->cursor = (se_cursor){0, viewer->cursor.row + 1};
    }

    se_draw_buffer_point( viewer );
    XftColorFree( env->display, env->visual, env->colormap, &clr );
}

void se_text_xviewer_configure_change_handler(se_text_xviewer* viewer, XEvent* ev )
{
    se_debug( "enter configure_change_handler" );
    gboolean need_update = FALSE;
    
    if ( ev->type == ConfigureRequest ) {
        XConfigureEvent configEv = ev->xconfigure;
        if ( viewer->physicalWidth != configEv.width
             || viewer->physicalHeight != configEv.height ) {
            need_update = TRUE;
        }
        
    } else if ( ev->type == ResizeRequest ) {
        XResizeRequestEvent resizeEv = ev->xresizerequest;
        if ( viewer->physicalWidth != resizeEv.width
             || viewer->physicalHeight != resizeEv.height ) {
            need_update = TRUE;
        }
    }

    if ( need_update ) {
        XWindowAttributes attrs;
        XGetWindowAttributes( viewer->env->display, viewer->view, &attrs);
        viewer->updateSize( viewer, attrs.width, attrs.height );
    }
}