[PATCH] Fix cursor + selection
From: Chris Heath <hidden>
Date: 2003-09-02 01:41:12
I noticed that the framebuffer console overwrites the mouse pointer and selected text when the cursor flashes. The attached patch fixes that. It is rather long, but basically all I've done is moved a huge chunk of code from fbcon_cursor into a helper function, and called that helper from fbcon_putc and fbcon_putcs. The patch is against James's latest fbdev patch that he posted to linux-kernel. Chris
--- linux-2.6.0-test4-fbdev/drivers/video/console/fbcon.c 2003-09-01 20:13:17.000000000 -0400
+++ linux-2.6.0-test4-cdh1/drivers/video/console/fbcon.c 2003-09-01 19:55:07.000000000 -0400@@ -811,6 +811,116 @@ } } +static void update_cursor(struct vc_data *vc, struct fb_info *info, int c) +{ + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + unsigned int scan_align = info->sprite.scan_align - 1; + unsigned int buf_align = info->sprite.buf_align - 1; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; + struct display *p = &fb_display[vc->vc_num]; + int y = real_y(p, vc->vc_y), d_pitch, dsize; + int s_pitch = (vc->vc_font.width + 7) >> 3; + int size = s_pitch * vc->vc_font.height; + struct fb_cursor cursor; + u8 *src, *dst; + + memset(&cursor, 0, sizeof(struct fb_cursor)); + if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) || + info->cursor.image.bg_color != attr_bgcol(bgshift, c)) { + cursor.image.fg_color = attr_fgcol(fgshift, c); + cursor.image.bg_color = attr_bgcol(bgshift, c); + cursor.image.depth = 1; + cursor.set |= FB_CUR_SETCMAP; + } + src = vc->vc_font.data + ((c & charmask) * size); + if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) || + info->cursor.image.bg_color != attr_bgcol(bgshift, c)) { + cursor.image.fg_color = attr_fgcol(fgshift, c); + cursor.image.bg_color = attr_bgcol(bgshift, c); + cursor.image.depth = 1; + cursor.set |= FB_CUR_SETCMAP; + } + + if ((info->cursor.image.dx != (vc->vc_font.width * vc->vc_x)) || + (info->cursor.image.dy != (vc->vc_font.height * y))) { + cursor.image.dx = vc->vc_font.width * vc->vc_x; + cursor.image.dy = vc->vc_font.height * y; + cursor.set |= FB_CUR_SETPOS; + } + + if (info->cursor.image.height != vc->vc_font.height || + info->cursor.image.width != vc->vc_font.width) { + cursor.image.height = vc->vc_font.height; + cursor.image.width = vc->vc_font.width; + cursor.set |= FB_CUR_SETSIZE; + } + + if (info->cursor.hot.x || info->cursor.hot.y) { + cursor.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + d_pitch = (s_pitch + scan_align) & ~scan_align; + dsize = d_pitch * vc->vc_font.height + buf_align; + dsize &= ~buf_align; + + if ((cursor.set & FB_CUR_SETSIZE) || + ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)) { + char *mask = kmalloc(dsize, GFP_ATOMIC); + int cur_height, i, j, k; + + if (!mask) + return; + + memset(mask, 0, dsize); + + if (info->cursor.mask) + kfree(info->cursor.mask); + info->cursor.mask = mask; + + p->cursor_shape = vc->vc_cursor_type & 0x0f; + + switch (vc->vc_cursor_type & 0x0f) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + i = (vc->vc_font.height - cur_height) * d_pitch; + for (j = 0; j < cur_height; j++) { + for (k = 0; k < s_pitch; k++) + mask[i++] = 0xff; + i += (d_pitch - s_pitch); + } + } + src = vc->vc_font.data + ((c & charmask) * size); + dst = fb_get_buffer_offset(info, &info->sprite, dsize); + move_buf_aligned(info, &info->sprite, dst, src, d_pitch, s_pitch, + vc->vc_font.height); + info->cursor.image.data = dst; + cursor.set |= FB_CUR_SETSHAPE; + info->cursor.rop = ROP_XOR; + info->fbops->fb_cursor(info, &cursor); + atomic_dec(&info->sprite.count); + smp_mb__after_atomic_dec(); +} + /* ====================================================================== */
@@ -917,6 +1027,9 @@ info->fbops->fb_imageblit(info, &image); atomic_dec(&info->pixmap.count); smp_mb__after_atomic_dec(); + + if (ypos == vc->vc_y && xpos == vc->vc_x) + update_cursor(vc, info, c); } static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
@@ -932,22 +1045,17 @@ return; accel_putcs(vc, info, s, count, real_y(p, ypos), xpos); + + if (ypos == vc->vc_y && xpos <= vc->vc_x && xpos + count > vc->vc_x) + update_cursor(vc, info, s[vc->vc_x - xpos]); } static void fbcon_cursor(struct vc_data *vc, int mode) { struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; - unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; - unsigned int scan_align = info->sprite.scan_align - 1; - unsigned int buf_align = info->sprite.buf_align - 1; - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; - int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; struct display *p = &fb_display[vc->vc_num]; - int y = real_y(p, vc->vc_y), d_pitch, dsize; - int s_pitch = (vc->vc_font.width + 7) >> 3; - int size = s_pitch * vc->vc_font.height, c; - struct fb_cursor cursor; - u8 *src, *dst; + int y = real_y(p, vc->vc_y); + int c; if (mode & CM_SOFTBACK) { mode &= ~CM_SOFTBACK;
@@ -967,95 +1075,11 @@ } if (mode != CM_ERASE) { - memset(&cursor, 0, sizeof(struct fb_cursor)); info->cursor.enable = 1; c = scr_readw((u16 *) vc->vc_pos); + update_cursor(vc, info, c); - src = vc->vc_font.data + ((c & charmask) * size); - if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) || - info->cursor.image.bg_color != attr_bgcol(bgshift, c)) { - cursor.image.fg_color = attr_fgcol(fgshift, c); - cursor.image.bg_color = attr_bgcol(bgshift, c); - cursor.image.depth = 1; - cursor.set |= FB_CUR_SETCMAP; - } - - if ((info->cursor.image.dx != (vc->vc_font.width * vc->vc_x)) || - (info->cursor.image.dy != (vc->vc_font.height * y))) { - cursor.image.dx = vc->vc_font.width * vc->vc_x; - cursor.image.dy = vc->vc_font.height * y; - cursor.set |= FB_CUR_SETPOS; - } - - if (info->cursor.image.height != vc->vc_font.height || - info->cursor.image.width != vc->vc_font.width) { - cursor.image.height = vc->vc_font.height; - cursor.image.width = vc->vc_font.width; - cursor.set |= FB_CUR_SETSIZE; - } - - if (info->cursor.hot.x || info->cursor.hot.y) { - cursor.hot.x = cursor.hot.y = 0; - cursor.set |= FB_CUR_SETHOT; - } - - src = vc->vc_font.data + ((c & charmask) * size); - - d_pitch = (s_pitch + scan_align) & ~scan_align; - dsize = d_pitch * vc->vc_font.height + buf_align; - dsize &= ~buf_align; - dst = fb_get_buffer_offset(info, &info->sprite, dsize); - move_buf_aligned(info, &info->sprite, dst, src, d_pitch, s_pitch, vc->vc_font.height); - info->cursor.image.data = dst; - cursor.set |= FB_CUR_SETSHAPE; - - if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)) { - char *mask = kmalloc(dsize, GFP_ATOMIC); - int cur_height, i, j, k; - - if (!mask) return; - - memset(mask, 0, dsize); - - if (info->cursor.mask) - kfree(info->cursor.mask); - info->cursor.mask = mask; - - p->cursor_shape = vc->vc_cursor_type & 0x0f; - - switch (vc->vc_cursor_type & 0x0f) { - case CUR_NONE: - cur_height = 0; - break; - case CUR_UNDERLINE: - cur_height = (vc->vc_font.height < 10) ? 1 : 2; - break; - case CUR_LOWER_THIRD: - cur_height = vc->vc_font.height/3; - break; - case CUR_LOWER_HALF: - cur_height = vc->vc_font.height >> 1; - break; - case CUR_TWO_THIRDS: - cur_height = (vc->vc_font.height << 1)/3; - break; - case CUR_BLOCK: - default: - cur_height = vc->vc_font.height; - break; - } - i = (vc->vc_font.height - cur_height) * d_pitch; - for (j = 0; j < cur_height; j++) { - for (k = 0; k < s_pitch; k++) - mask[i++] = 0xff; - i += (d_pitch - s_pitch); - } - } - info->cursor.rop = ROP_XOR; - info->fbops->fb_cursor(info, &cursor); - atomic_dec(&info->sprite.count); - smp_mb__after_atomic_dec(); mod_timer(&cursor_timer, jiffies + HZ/5); vbl_cursor_cnt = CURSOR_DRAW_DELAY; } -------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf