From e158c4832aa1d5dc8603fb9c33cac3f7cc19abc9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 21 Jun 2017 14:25:13 +0200 Subject: added the widget and the composite widget classes --- src/Makefile | 13 ++-- src/boot/stage2_real_functions.asm | 2 +- src/gui/composite_widget.c | 137 +++++++++++++++++++++++++++++++++++++ src/gui/composite_widget.h | 32 +++++++++ src/gui/widget.c | 74 ++++++++++++++++++-- src/gui/widget.h | 19 ++++- 6 files changed, 262 insertions(+), 15 deletions(-) create mode 100644 src/gui/composite_widget.c create mode 100644 src/gui/composite_widget.h diff --git a/src/Makefile b/src/Makefile index 497a0d4..02ab439 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,16 +11,16 @@ all: image.bin kernel.sym # truncate to correct number of sectors, we have # 512 (boot, stage 1) + N * 512 (N currenty is 5, stage 2) for boot.bin -# + M * 512 (M is currently 159) for kernel.bin +# + M * 512 (M is currently 169) for kernel.bin # (M + N + 1 is the number of sectors to be read in stage 2, as stage 1 # loads only the first sector, and stage 1 loads 5 sectors of stage 2, -# adapt NOF_LOAD_SECTORS to 159) +# adapt NOF_LOAD_SECTORS to 169) # then we make sure the image has the size of a 1.44 MB floppy # (emulators like qemu do some guess work for CHS resolution based # on the size of the image) image.bin: boot.bin kernel.bin magic.bin cat boot.bin kernel.bin > image.tmp - truncate -s 83968 image.tmp + truncate -s 89088 image.tmp cat image.tmp magic.bin > image.bin truncate -s 1474560 image.bin @@ -33,7 +33,7 @@ kernel.bin: kernel.elf kernel.sym: kernel.elf $(OBJCOPY) --only-keep-debug kernel.elf kernel.sym -kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o gui/widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o +kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o gui/widget.o gui/composite_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o $(LD) -o kernel.elf -N -n -Ttext 0x8800 --oformat elf32-i386 \ kernel/kernel.o kernel/kernel_asm.o \ kernel/console.o kernel/vgatext.o kernel/serial.o \ @@ -44,7 +44,7 @@ kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext. drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o \ drivers/video/vga.o drivers/video/vga_font.o \ libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o \ - gui/widget.o + gui/widget.o gui/composite_widget.o magic.bin: boot/magic.asm $(NASM) boot/magic.asm -DMAGIC='"$(MAGIC)"' -f bin -o magic.bin @@ -106,6 +106,9 @@ libc/setjmp.o: libc/setjmp.asm gui/widget.o: gui/widget.c gui/widget.h $(CC) $(CFLAGS) -c -o gui/widget.o gui/widget.c +gui/composite_widget.o: gui/composite_widget.c gui/composite_widget.h + $(CC) $(CFLAGS) -c -o gui/composite_widget.o gui/composite_widget.c + clean: -rm -f boot.bin kernel.bin kernel.sym kernel.elf image.bin magic.bin boot.map image.tmp \ serial.log \ diff --git a/src/boot/stage2_real_functions.asm b/src/boot/stage2_real_functions.asm index cc2ad26..61aa81e 100644 --- a/src/boot/stage2_real_functions.asm +++ b/src/boot/stage2_real_functions.asm @@ -2,7 +2,7 @@ ; (note: the first sector gets loaded by the BIOS, the ; next 5 sectors are read by the simple stage 1 loader, ; so subtract 6 here!) -NOF_LOAD_SECTORS equ 159 +NOF_LOAD_SECTORS equ 169 ; data sections used for reading the kernel from disk SECTORS_PER_CYLINDER: diff --git a/src/gui/composite_widget.c b/src/gui/composite_widget.c new file mode 100644 index 0000000..e9cc166 --- /dev/null +++ b/src/gui/composite_widget.c @@ -0,0 +1,137 @@ +#include "composite_widget.h" + +#include "string.h" +#include "stddef.h" + +static composite_widget_vtable_t composite_widget_vtable = { + { + composite_widget_draw, + composite_widget_get_focus, + widget_model_to_screen, + widget_contains_coordinate, + composite_widget_on_mouse_down, + composite_widget_on_mouse_up, + composite_widget_on_mouse_move, + composite_widget_on_key_down, + composite_widget_on_key_up + }, + composite_widget_add_child +}; + +void composite_widget_init( composite_widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h ) +{ + memset( widget, 0, sizeof( composite_widget_t ) ); + + widget_init( &widget->base, parent, x, y, w, h ); + + widget->nof_children = 0; + widget->focused_child = NULL; + memset( widget->children, 0, MAX_NOF_WIDGET_CHILDREN * sizeof( widget_t * ) ); + + widget->vtable = &composite_widget_vtable; +} + +void composite_widget_draw( void *obj, graphics_context_t *context ) +{ + composite_widget_t *widget = obj; + + widget->base.vtable->draw( obj, context ); + + for( int i = widget->nof_children - 1; i >= 0; i-- ) { + widget_t *child = widget->children[i]; + child->vtable->draw( child, context ); + } +} + +void composite_widget_get_focus( void *obj, widget_t *widget ) +{ + composite_widget_t *o = obj; + + o->focused_child = widget; + + o->base.vtable->get_focus( o, widget ); +} + +void composite_widget_add_child( void *obj, widget_t *child ) +{ + composite_widget_t *widget = obj; + + if( widget->nof_children >= MAX_NOF_WIDGET_CHILDREN ) { + // TODO: kernel_panic, but in an indirect way because + // the GUI framework should not depend on the kernel. + // Maybe something like a runtime context similar to + // the graphics context? + return; + } + + widget->children[widget->nof_children++] = child; +} + +void composite_widget_on_mouse_down( void *obj, const int x, const int y ) +{ + composite_widget_t *widget = obj; + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, x - widget->base.x, y - widget->base.y ) ) { + child->vtable->on_mouse_down( child, x - widget->base.x, y - widget->base.y ); + break; + } + } +} + +void composite_widget_on_mouse_up( void *obj, const int x, const int y ) +{ + composite_widget_t *widget = obj; + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, x - widget->base.x, y - widget->base.y ) ) { + child->vtable->on_mouse_up( child, x - widget->base.x, y - widget->base.y ); + break; + } + } +} + +void composite_widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y ) +{ + composite_widget_t *widget = obj; + widget_t *moved_out_from = NULL; + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, old_x - widget->base.x, old_y - widget->base.y ) ) { + child->vtable->on_mouse_move( child, old_x - widget->base.x, old_y - widget->base.y, x - widget->base.x, y - widget->base.y ); + moved_out_from = child; + break; + } + } + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, x - widget->base.x, y - widget->base.y ) ) { + if( moved_out_from != NULL ) { + child->vtable->on_mouse_move( child, old_x - widget->base.x, old_y - widget->base.y, x - widget->base.x, y - widget->base.y ); + break; + } + } + } +} + +void composite_widget_on_key_down( void *obj, char c ) +{ + composite_widget_t *widget = obj; + + if( widget->focused_child != NULL ) { + widget->focused_child->vtable->on_key_down( widget->focused_child, c ); + } +} + +void composite_widget_on_key_up( void *obj, char c ) +{ + composite_widget_t *widget = obj; + + if( widget->focused_child != NULL ) { + widget->focused_child->vtable->on_key_up( widget->focused_child, c ); + } +} diff --git a/src/gui/composite_widget.h b/src/gui/composite_widget.h new file mode 100644 index 0000000..d3ba90a --- /dev/null +++ b/src/gui/composite_widget.h @@ -0,0 +1,32 @@ +#ifndef COMPOSITE_WIDGET_H +#define COMPOSITE_WIDGET_H + +#include "widget.h" + +#define MAX_NOF_WIDGET_CHILDREN 100 + +typedef struct { + widget_vtable_t base; + void (*add_child)( void *obj, widget_t *child ); +} composite_widget_vtable_t; + +typedef struct { + widget_t base; + composite_widget_vtable_t *vtable; + widget_t *children[MAX_NOF_WIDGET_CHILDREN]; + int nof_children; + widget_t *focused_child; +} composite_widget_t; + +void composite_widget_init( composite_widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h ); + +void composite_widget_draw( void *obj, graphics_context_t *context ); +void composite_widget_get_focus( void *obj, widget_t *widget ); +void composite_widget_on_mouse_down( void *obj, const int x, const int y ); +void composite_widget_on_mouse_up( void *obj, const int x, const int y ); +void composite_widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y ); +void composite_widget_on_key_down( void *obj, char c ); +void composite_widget_on_key_up( void *obj, char c ); +void composite_widget_add_child( void *obj, widget_t *child ); + +#endif // COMPOSITE_WIDGET_H diff --git a/src/gui/widget.c b/src/gui/widget.c index 313fd49..cd77d03 100644 --- a/src/gui/widget.c +++ b/src/gui/widget.c @@ -5,12 +5,14 @@ static widget_vtable_t widget_vtable = { widget_draw, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + widget_get_focus, + widget_model_to_screen, + widget_contains_coordinate, + widget_on_mouse_down, + widget_on_mouse_up, + widget_on_mouse_move, + widget_on_key_down, + widget_on_key_up }; void widget_init( widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h ) @@ -29,7 +31,65 @@ void widget_init( widget_t *widget, widget_t *parent, const int x, const int y, void widget_draw( void *obj, graphics_context_t *context ) { widget_t *widget = obj; + int x = 0; + int y = 0; - vga_draw_rectangle( context, widget->x, widget->y, widget->w, widget->h, + widget->vtable->model_to_screen( widget, &x, &y ); + + vga_draw_rectangle( context, x, y, widget->w, widget->h, vga_make_RGB( 0xFF, 0xFF, 0xFF ) ); } + +void widget_get_focus( void *obj, widget_t *widget ) +{ + widget_t *o = obj; + + if( o->parent != NULL ) { + o->parent->vtable->get_focus( widget->parent, widget ); + } +} + +void widget_model_to_screen( void *obj, int *x, int *y ) +{ + widget_t *widget = obj; + + if( widget->parent != NULL ) { + widget->parent->vtable->model_to_screen( widget->parent, x, y ); + } + + *x += widget->x; + *y += widget->y; +} + +bool widget_contains_coordinate( void *obj, const int x, const int y ) +{ + widget_t *widget = obj; + + return widget->x <= x && x < widget->x + widget->w && + widget->y <= y && y < widget->y + widget->h; +} + +void widget_on_mouse_down( void *obj, const int x, const int y ) +{ + widget_t *widget = obj; + + if( widget->focusable ) { + widget->vtable->get_focus( widget, widget ); + } +} + +void widget_on_mouse_up( void *obj, const int x, const int y ) +{ +} + +void widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y ) +{ +} + +void widget_on_key_down( void *obj, char c ) +{ +} + +void widget_on_key_up( void *obj, char c ) +{ +} diff --git a/src/gui/widget.h b/src/gui/widget.h index a1e9a21..1fd23ac 100644 --- a/src/gui/widget.h +++ b/src/gui/widget.h @@ -3,14 +3,20 @@ #include "graphics_context.h" +#include + +struct widget_t; + typedef struct { void (*draw)( void *obj, graphics_context_t *context ); - void (*get_focus)( void *obj ); - void (*widget_model_to_screen)( void *obj, int *x, int *y ); + void (*get_focus)( void *obj, struct widget_t *widget ); + void (*model_to_screen)( void *obj, int *x, int *y ); + bool (*contains_coordinate)( void *obj, const int x, const int y ); void (*on_mouse_down)( void *obj, const int x, const int y ); void (*on_mouse_up)( void *obj, const int x, const int y ); void (*on_mouse_move)( void *obj, const int old_x, const int old_y, const int x, const int y ); void (*on_key_down)( void *obj, char c ); + void (*on_key_up)( void *obj, char c ); } widget_vtable_t; typedef struct widget_t { @@ -18,6 +24,7 @@ typedef struct widget_t { int y; int w; int h; + bool focusable; struct widget_t *parent; widget_vtable_t *vtable; } widget_t; @@ -25,5 +32,13 @@ typedef struct widget_t { void widget_init( widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h ); void widget_draw( void *obj, graphics_context_t *context ); +void widget_get_focus( void *obj, widget_t *widget ); +void widget_model_to_screen( void *obj, int *x, int *y ); +bool widget_contains_coordinate( void *obj, const int x, const int y ); +void widget_on_mouse_down( void *obj, const int x, const int y ); +void widget_on_mouse_up( void *obj, const int x, const int y ); +void widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y ); +void widget_on_key_down( void *obj, char c ); +void widget_on_key_up( void *obj, char c ); #endif // WIDGET_H -- cgit v1.2.3-54-g00ecf