summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/internal/mem.txt7
-rw-r--r--doc/ints.txt1
-rw-r--r--doc/keys.txt8
-rw-r--r--fs-skel/sys/startup.rc2
-rw-r--r--makefile8
-rw-r--r--src/boot.asm4
-rw-r--r--src/kernel/idt.c6
-rw-r--r--src/kernel/isrs.asm17
-rw-r--r--src/kernel/kbd.c84
-rw-r--r--src/kernel/paging.c4
-rw-r--r--src/kernel/task.c6
-rw-r--r--src/kernel/window.c131
-rw-r--r--src/kernel/window.h3
-rw-r--r--src/shared/include/winact.h12
-rw-r--r--src/user/knob/format.c52
-rw-r--r--src/user/mdemo/main.c42
16 files changed, 304 insertions, 83 deletions
diff --git a/doc/internal/mem.txt b/doc/internal/mem.txt
index 72b72ec..252a5ad 100644
--- a/doc/internal/mem.txt
+++ b/doc/internal/mem.txt
@@ -17,9 +17,10 @@
0x0000.5000 - 0x0000.5fff (4k): kernel page directory
0x0001.0000 - 0x0001.ffff (64k): BIOS memory map
-
-0x0003.0000 - 0x0003.7fff (32k): kernel text, data, rodata
-0x0003.8000 - 0x0003.ffff (32k): kernel stack
+0x0002.0000 - 0x0002.0fff (4k): kernel stack guard
+0x0002.1000 - 0x0002.efff (56k): kernel stack
+0x0002.f000 - 0x0002.ffff (4k): kernel stack guard
+0x0003.0000 - 0x0003.ffff (64k): kernel text, data, rodata
0x0004.0000 - 0x0005.ffff (128k): pagemap
0x0006.0000 - 0x0007.ffff (128k): shared kernel page tables
diff --git a/doc/ints.txt b/doc/ints.txt
index 095298f..a2625ae 100644
--- a/doc/ints.txt
+++ b/doc/ints.txt
@@ -15,7 +15,6 @@ see table 1
file system calls have units of bytes unless otherwise specified.
functions returning handles or pointers use 0 to indicate error.
-see keys.txt for the return type of the "get key" system call.
the edx register of "start task" is a pointer to a null-terminated string.
a pointer to a readonly copy of this string is put into the new task's edx.
the esi register is passed through directly, and is meant to be a task handle.
diff --git a/doc/keys.txt b/doc/keys.txt
index bccd47a..1ea8d9b 100644
--- a/doc/keys.txt
+++ b/doc/keys.txt
@@ -8,12 +8,6 @@ the top 24 bits indicate several flags. these are seen in table 2, where bit 0
is the lowest bit of the second lowest byte of the keycode, and bit 23 is the
highest bit of the highest byte of the keycode.
-the "get key" system call returns 0 if there is not a key available. it is
-recommended to make the system call and, if it returns 0, yield to the scheduler
-and then loop back to making the system call. this way your task does not block
-the cpu while waiting for keyboard input. see the "get_key_char" function in
-user.c of the "knob" library for an example of this.
-
table 1:
@@ -50,7 +44,7 @@ table 1:
0xaa | F11
0xab | F12
0xac | unassigned
- .... | unassigned
+ ... | unassigned
0xaf | unassigned
0xb0 | numpad 0
0xb1 | numpad 1
diff --git a/fs-skel/sys/startup.rc b/fs-skel/sys/startup.rc
index 3897399..4a3992c 100644
--- a/fs-skel/sys/startup.rc
+++ b/fs-skel/sys/startup.rc
@@ -1 +1 @@
-bin/mkpopup Press Win+Space to open a terminal.\nPress Win+Arrow Key to move a window around.\nPress Win+Page Up/Down to shuffle windows.\nTry typing 'dirlist bin' into a terminal!\nPress Escape to close this window. \ No newline at end of file
+bin/mkpopup Press Win+Space to open a terminal with a shell.\nPress Win+Arrow Key to move a window around.\nClick on a window to focus it.\nPress escape to close this window.\nTo list all of the installed programs,\n type "dirlist bin" into a shell. \ No newline at end of file
diff --git a/makefile b/makefile
index 073f130..f71c6eb 100644
--- a/makefile
+++ b/makefile
@@ -10,7 +10,7 @@ out/disk.vdi: out/disk.img
out/disk.img: out/kernel.bin out/boot.bin out/fs
mkdir -p obj
- mkfs.fat -C -f 1 -F 16 -n "PORTLAND OS" -R 65 -s 1 -S 512 obj/shadow.img 8192
+ mkfs.fat -C -f 1 -F 16 -n "PORTLAND OS" -R 129 -s 1 -S 512 obj/shadow.img 8192
echo -n -e '\xeb\x3c' > obj/jmp.bin
dd if=obj/jmp.bin of=obj/shadow.img obs=2 conv=notrunc
dd if=out/boot.bin of=obj/shadow.img obs=1 seek=62 conv=notrunc
@@ -38,7 +38,7 @@ out/fs/bin/%: obj/%.elf
out/fs: out/fs/bin/init out/fs/bin/highway out/fs/bin/meminfo \
out/fs/bin/terminal out/fs/bin/hello out/fs/bin/mkpopup \
out/fs/bin/dirlist out/fs/bin/ttt out/fs/bin/time \
- out/fs/bin/filetest
+ out/fs/bin/filetest out/fs/bin/mdemo
touch out/fs
cp -r fs-skel/* out/fs/
@@ -136,4 +136,8 @@ obj/time.elf: obj/time/time.o obj/libterm.so obj/knob.so \
obj/filetest.elf: obj/filetest/filetest.o obj/libterm.so obj/knob.so \
obj/c.rto
+ ld -T src/user/runtimes/c/elf.ld $^ -o $@
+
+obj/mdemo.elf: obj/mdemo/main.o obj/popups.so obj/libfont.so \
+ obj/knob.so obj/c.rto
ld -T src/user/runtimes/c/elf.ld $^ -o $@ \ No newline at end of file
diff --git a/src/boot.asm b/src/boot.asm
index 74a3e5e..f56d6a6 100644
--- a/src/boot.asm
+++ b/src/boot.asm
@@ -1,7 +1,7 @@
bits 16
org 0x7c3e
-kernel_sectors equ 64
+kernel_sectors equ 128
kernel_segment equ 0x3000
support_flags equ 0x4000
@@ -195,7 +195,7 @@ pmode:
mov ds, ax
mov es, ax
mov ss, ax
- mov esp, 0x00040000
+ mov esp, 0x0002f000
xor ebp, ebp
diff --git a/src/kernel/idt.c b/src/kernel/idt.c
index 1a78da0..f07ef1d 100644
--- a/src/kernel/idt.c
+++ b/src/kernel/idt.c
@@ -219,6 +219,7 @@ extern isr_t quit_isr;
extern isr_t yield_isr;
extern isr_t kbd_isr;
+extern isr_t mouse_isr;
extern isr_t udf_isr;
extern isr_t dfa_isr;
@@ -325,6 +326,7 @@ void init_idt() {
register_int(0x39, &yield_isr, 3);
register_int(0x21, &kbd_isr, 0);
+ register_int(0x2c, &mouse_isr, 0);
register_int(0x08, &udf_isr, 0);
register_int(0x08, &dfa_isr, 0);
@@ -346,8 +348,8 @@ void init_idt() {
outb(PIC_MDATA, 0x01);
outb(PIC_SDATA, 0x01);
- outb(PIC_MDATA, 0xfd);
- outb(PIC_SDATA, 0xff);
+ outb(PIC_MDATA, 0xf9);
+ outb(PIC_SDATA, 0xef);
asm volatile (
"lidt %0"
diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm
index 1aba884..70bab19 100644
--- a/src/kernel/isrs.asm
+++ b/src/kernel/isrs.asm
@@ -5,6 +5,7 @@ global quit_isr
global yield_isr
global _start_user_mode
global kbd_isr
+global mouse_isr
global udf_isr
global dfa_isr
@@ -133,6 +134,22 @@ _start_user_mode:
sub esp, 4
jmp yield_isr.return_to_task
+mouse_isr:
+ push eax
+ push ecx
+ push edx
+
+ call on_kbd_isr
+
+ mov al, 0x20
+ out 0x00a0, al
+ out 0x0020, al
+
+ pop edx
+ pop ecx
+ pop eax
+ iret
+
kbd_isr:
push eax
push ecx
diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c
index 47894cd..004706f 100644
--- a/src/kernel/kbd.c
+++ b/src/kernel/kbd.c
@@ -21,16 +21,36 @@ enum {
enum {
PS2C_READ_CONFIG = 0x20,
PS2C_WRITE_CONFIG = 0x60,
+ PS2C_AUX_ENABLE = 0xa8,
PS2C_DISABLE = 0xad,
- PS2C_ENABLE = 0xae
+ PS2C_ENABLE = 0xae,
+ PS2C_SEND_AUX = 0xd4
};
enum {
- PS2S_CODE_READY = 0x01
+ PS2S_CODE_READY = 0x01,
+ PS2S_DONT_SEND = 0x02,
+ PS2S_FROM_MOUSE = 0x20
};
enum {
- PS2G_XT_COMPAT = 0x40
+ PS2G_KBD_IRQ = 0x01,
+ PS2G_MOUSE_IRQ = 0x02,
+ PS2G_KBD_OFF = 0x10,
+ PS2G_MOUSE_OFF = 0x20,
+ PS2G_XT_COMPAT = 0x40
+};
+
+enum {
+ MFB_BUTTON_ONE = 0x01,
+ MFB_BUTTON_TWO = 0x02,
+ MFB_BUTTON_MID = 0x04,
+ MFB_X_SIGN = 0x10,
+ MFB_Y_SIGN = 0x20
+};
+
+enum {
+ MC_ENABLE_REPORT = 0xf4
};
static uint32_t n_scantabs;
@@ -55,7 +75,16 @@ void init_kbd() {
outb(PS2_CMD, PS2C_READ_CONFIG);
uint8_t config = inb(PS2_DATA);
outb(PS2_CMD, PS2C_WRITE_CONFIG);
- outb(PS2_DATA, config | PS2G_XT_COMPAT);
+ outb(PS2_DATA, (config | PS2G_XT_COMPAT | PS2G_MOUSE_IRQ | PS2G_KBD_IRQ) & ~(PS2G_MOUSE_OFF | PS2G_KBD_OFF));
+
+ outb(PS2_CMD, PS2C_SEND_AUX);
+ while (inb(PS2_CMD) & PS2S_DONT_SEND)
+ ;
+ outb(PS2_DATA, MC_ENABLE_REPORT);
+ while (!(inb(PS2_CMD) & PS2S_CODE_READY))
+ ;
+ if (inb(PS2_DATA) != 0xfa)
+ PANIC("didn't get ACK after enabling mouse reporting");
uint32_t layout_len;
if (!try_get_sz_setting("kbd-layout", scantab_path + SCANTAB_DIR_LEN, LAYOUT_NAME_MAX_LEN, &layout_len))
@@ -107,11 +136,54 @@ static inline uint8_t get_next_code_byte() {
return cb;
}
+static inline uint8_t get_wait() {
+ for (uint32_t i = 0; i < 1000000; ++i)
+ ;
+ return inb(PS2_DATA);
+}
+
static enum key_modifiers_t keymods = 0;
+bool last_mouse_one = false;
+bool last_mouse_two = false;
+bool last_mouse_mid = false;
+
enum kbd_isr_result on_kbd_isr() {
-//logf(LOG_INFO, "on_kbd_isr()");
- while (inb(PS2_CMD) & PS2S_CODE_READY) {
+ uint8_t code;
+ while ((code = inb(PS2_CMD)) & PS2S_CODE_READY) {
+ if (code & PS2S_FROM_MOUSE) {
+ const uint8_t first = get_wait();
+ const uint8_t x = get_wait();
+ const uint8_t y = get_wait();
+
+ if (x || y || (first & (MFB_X_SIGN | MFB_Y_SIGN)))
+ move_mouse_by((first & MFB_Y_SIGN) ? 256 - y : -y,
+ (first & MFB_X_SIGN) ? x - 256 : x);
+
+ const bool mouse_one = first & MFB_BUTTON_ONE;
+ const bool mouse_two = first & MFB_BUTTON_TWO;
+ const bool mouse_mid = first & MFB_BUTTON_MID;
+
+ if (mouse_one && !last_mouse_one)
+ mouse_button(LEFT, false);
+ if (mouse_two && !last_mouse_two)
+ mouse_button(RIGHT, false);
+ if (mouse_mid && !last_mouse_mid)
+ mouse_button(MIDDLE, false);
+
+ if (!mouse_one && last_mouse_one)
+ mouse_button(LEFT, true);
+ if (!mouse_two && last_mouse_two)
+ mouse_button(RIGHT, true);
+ if (!mouse_mid && last_mouse_mid)
+ mouse_button(MIDDLE, true);
+
+ last_mouse_one = mouse_one;
+ last_mouse_two = mouse_two;
+ last_mouse_mid = mouse_mid;
+ continue;
+ }
+
last_code_byte = 0;
uint8_t code[256];
uint8_t code_i = 0;
diff --git a/src/kernel/paging.c b/src/kernel/paging.c
index 0432ab6..dc7ca27 100644
--- a/src/kernel/paging.c
+++ b/src/kernel/paging.c
@@ -115,11 +115,15 @@ void init_paging() {
for (uint32_t i = 0; i < 1048576; ++i)
KPAGE_TABLE_0[i] = (i * 4096) | PE_WRITABLE | PE_PRESENT;
+ KPAGE_TABLE_0[0x00020] &= ~PE_PRESENT;
+ KPAGE_TABLE_0[0x0002f] &= ~PE_PRESENT;
for (uint16_t i = 0; i < 1024; ++i)
KPAGE_DIR[i] = (uint32_t)(KPAGE_TABLE_0 + i * 1024) | PE_WRITABLE | PE_PRESENT;
for (uint16_t i = 0; i < KERNEL_END / 4096; ++i)
kmap[i] = (i * 4096) | PE_USER | PE_PRESENT;
+ kmap[0x00020] &= ~PE_PRESENT;
+ kmap[0x0002f] &= ~PE_PRESENT;
asm volatile (
"mov $0x00005000, %%eax\n"
diff --git a/src/kernel/task.c b/src/kernel/task.c
index 93310bc..077eea6 100644
--- a/src/kernel/task.c
+++ b/src/kernel/task.c
@@ -62,11 +62,11 @@ uint32_t new_task(struct task_state state) {
static void tmp_halt() {
//logf(LOG_INFO, "scheduler halting");
- TSS->esp0 = 0x0003c000;
+ TSS->esp0 = 0x00028000;
asm("sti\n"
"hlt\n"
"cli");
- TSS->esp0 = 0x00040000;
+ TSS->esp0 = 0x0002f000;
//logf(LOG_INFO, "scheduler resumed");
}
@@ -121,7 +121,7 @@ void init_tasks() {
ipc_pipes[i].buffer = 0;
TSS->ss0 = 0x18;
- TSS->esp0 = 0x00040000;
+ TSS->esp0 = 0x0002f000;
//TSS->cs = 0x13;
//TSS->ds = 0x1b;
//TSS->ss = 0x1b;
diff --git a/src/kernel/window.c b/src/kernel/window.c
index e7cf30d..bc36578 100644
--- a/src/kernel/window.c
+++ b/src/kernel/window.c
@@ -71,6 +71,49 @@ static void load_mode_params() {
);
}
+static inline void blit_pixel(uint32_t *into, struct pixel from) {
+ *into &= pix_clear_mask;
+ *into |= (from.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off;
+ *into |= (from.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off;
+ *into |= (from.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off;
+}
+
+static uint16_t mouse_y;
+static uint16_t mouse_x;
+
+#define MOUSE_WIDTH 8
+#define MOUSE_HEIGHT 8
+
+#define B {.r = 0, .g = 0, .b = 0, .pad = 0}
+#define W {.r = 255, .g = 255, .b = 255, .pad = 0}
+#define T {.pad = 1}
+
+static const struct pixel mouse_image[] = {
+ W, W, W, W, W, W, T, T,
+ W, B, B, B, W, T, T, T,
+ W, B, B, B, W, W, T, T,
+ W, B, B, B, B, W, W, T,
+ W, W, W, B, B, B, W, T,
+ W, T, W, W, B, B, B, W,
+ T, T, T, W, W, B, W, W,
+ T, T, T, T, W, W, W, T
+};
+
+static void blit_mouse() {
+ uint16_t y_max = mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height - mouse_y : MOUSE_HEIGHT;
+ uint16_t x_max = mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width - mouse_x : MOUSE_WIDTH;
+ void *row = VBE_MODE_INFO->frame_buf + mouse_y * VBE_MODE_INFO->pitch + mouse_x * (VBE_MODE_INFO->bpp / 8);
+ for (uint16_t y = 0; y < y_max; ++y) {
+ uint32_t *out_pix = row;
+ for (uint16_t x = 0; x < x_max; ++x) {
+ if (!mouse_image[y * MOUSE_WIDTH + x].pad)
+ blit_pixel(out_pix, mouse_image[y * MOUSE_WIDTH + x]);
+ out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8);
+ }
+ row += VBE_MODE_INFO->pitch;
+ }
+}
+
static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) {
void *row = VBE_MODE_INFO->frame_buf + y_min * VBE_MODE_INFO->pitch + x_min * (VBE_MODE_INFO->bpp / 8);
const struct super_pixel *from_row = buffer + y_min * VBE_MODE_INFO->width + x_min;
@@ -78,16 +121,17 @@ static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max)
uint32_t *out_pix = row;
const struct super_pixel *from = from_row;
for (uint16_t x = x_min; x < x_max; ++x) {
- *out_pix &= pix_clear_mask;
- *out_pix |= (from->p.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off;
- *out_pix |= (from->p.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off;
- *out_pix |= (from->p.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off;
+ blit_pixel(out_pix, from->p);
out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8);
++from;
}
row += VBE_MODE_INFO->pitch;
from_row += VBE_MODE_INFO->width;
}
+
+ if ((y_min < mouse_y) && (y_max > mouse_y) &&
+ (x_min < mouse_x) && (x_max > mouse_x))
+ blit_mouse();
}
#define POWER_OFF_MESSAGE_PITCH 45
@@ -343,8 +387,6 @@ static void send_action(struct window *w, struct window_action packet) {
#define RUN_COMMAND_FILE "sys/winspace.rc"
enum wm_action {
- WM_SHUFFLE_UP,
- WM_SHUFFLE_DOWN,
WM_MOVE_LEFT,
WM_MOVE_RIGHT,
WM_MOVE_UP,
@@ -355,8 +397,6 @@ enum wm_action {
};
static struct key_packet keybinds[] = {
- {.key_id = KEY_PAGE_DOWN, .modifiers = WINS},
- {.key_id = KEY_PAGE_UP, .modifiers = WINS},
{.key_id = KEY_LEFT_ARROW, .modifiers = WINS},
{.key_id = KEY_RIGHT_ARROW, .modifiers = WINS},
{.key_id = KEY_UP_ARROW, .modifiers = WINS},
@@ -393,6 +433,10 @@ void init_win() {
paint_bg();
blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height);
+ mouse_x = (VBE_MODE_INFO->width - MOUSE_WIDTH) / 2;
+ mouse_y = (VBE_MODE_INFO->height - MOUSE_HEIGHT) / 2;
+ blit_mouse();
+
const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE);
if (!fid)
PANIC("Couldn't open " RUN_COMMAND_FILE ".");
@@ -425,34 +469,7 @@ void on_action(struct window_action packet) {
for (uint8_t i = 0; i < N_WM_ACTIONS; ++i)
if (fuzzy_key_match(keybinds[i], packet.as_key)) {
switch_to_kernel_cr3();
- struct window *old_top, *old_bottom;
switch (i) {
- case WM_SHUFFLE_UP:
- if (!top_window || !top_window->below)
- break;
- old_top = top_window;
- old_bottom = bottom_window;
- top_window = old_top->below;
- top_window->above = 0;
- old_top->below = 0;
- old_top->above = old_bottom;
- old_bottom->below = old_top;
- bottom_window = old_top;
- paint_and_above(bottom_window->above);
- break;
- case WM_SHUFFLE_DOWN:
- if (!top_window || !top_window->below)
- break;
- old_top = top_window;
- old_bottom = bottom_window;
- bottom_window = old_bottom->above;
- bottom_window->below = 0;
- old_bottom->above = 0;
- old_bottom->below = old_top;
- old_top->above = old_bottom;
- top_window = old_bottom;
- paint_and_above(top_window);
- break;
case WM_MOVE_LEFT:
if (top_window) {
top_window->xpos -= MOVE_BY;
@@ -487,4 +504,48 @@ void on_action(struct window_action packet) {
if (top_window)
send_action(top_window, packet);
+}
+
+void move_mouse_by(int16_t y, int16_t x) {
+//logf(LOG_INFO, "old mouse coords: (%d, %d)", mouse_x, mouse_y);
+ switch_to_kernel_cr3();
+ blit(mouse_x, mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width : mouse_x + MOUSE_WIDTH,
+ mouse_y, mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height : mouse_y + MOUSE_HEIGHT);
+ mouse_y = (-y > mouse_y) ? 0 : (y + mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height) ? VBE_MODE_INFO->height - MOUSE_HEIGHT : y + mouse_y;
+ mouse_x = (-x > mouse_x) ? 0 : (x + mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width) ? VBE_MODE_INFO->width - MOUSE_WIDTH : x + mouse_x;
+ blit_mouse();
+ switch_to_task_cr3();
+//logf(LOG_INFO, "new mouse coords: (%d, %d)", mouse_x, mouse_y);
+}
+
+static void focus(struct window *w) {
+ send_action(top_window, (struct window_action){.action_type = FOCUS_LEAVE});
+
+ if (w->below)
+ w->below->above = w->above;
+ else
+ bottom_window = w->above;
+ w->above->below = w->below;
+ w->above = 0;
+ w->below = top_window;
+ top_window->above = w;
+ top_window = w;
+
+ send_action(w, (struct window_action){.action_type = FOCUS_ENTER});
+}
+
+void mouse_button(enum mouse_button which, bool up) {
+ if (!top_window)
+ return;
+
+ struct window *const clicked_on = buffer[mouse_y * VBE_MODE_INFO->width + mouse_x].from_window;
+ if (!clicked_on)
+ return;
+
+ if (clicked_on != top_window) {
+ focus(clicked_on);
+ paint_and_above(clicked_on);
+ }
+
+ send_action(clicked_on, (struct window_action){.action_type = up ? MOUSE_UP : MOUSE_DOWN, .as_mouse = {.y = mouse_y - clicked_on->ypos, .x = mouse_x - clicked_on->xpos, .which = which}});
} \ No newline at end of file
diff --git a/src/kernel/window.h b/src/kernel/window.h
index 0a83845..a1f9716 100644
--- a/src/kernel/window.h
+++ b/src/kernel/window.h
@@ -33,4 +33,7 @@ void delete_any_windows_from(struct task_state *tstate);
void show_shutdown();
+void move_mouse_by(int16_t y, int16_t x);
+void mouse_button(enum mouse_button which, bool up);
+
#endif
diff --git a/src/shared/include/winact.h b/src/shared/include/winact.h
index bc18cb4..8b32d00 100644
--- a/src/shared/include/winact.h
+++ b/src/shared/include/winact.h
@@ -9,10 +9,20 @@ struct window_action {
KEY_DOWN,
KEY_UP,
FOCUS_ENTER,
- FOCUS_LEAVE
+ FOCUS_LEAVE,
+ MOUSE_DOWN,
+ MOUSE_UP
} action_type;
union {
struct key_packet as_key;
+ struct {
+ //0, 0 is upper-left-most pixel not counting border
+ //packets are also sent for the border pixels,
+ // so this may be a negative value in those cases
+ int16_t y;
+ int16_t x;
+ enum mouse_button {LEFT, RIGHT, MIDDLE} which;
+ } as_mouse;
};
} __attribute__ ((__packed__));
diff --git a/src/user/knob/format.c b/src/user/knob/format.c
index c5d2447..cdc1687 100644
--- a/src/user/knob/format.c
+++ b/src/user/knob/format.c
@@ -42,8 +42,8 @@ struct format_spec {
CHAR,
STRING,
UNSIGNED_DECIMAL,
- HEXADECIMAL
- //TODO: signed decimal
+ HEXADECIMAL,
+ SIGNED_DECIMAL
} kind;
};
@@ -73,6 +73,9 @@ static const char *get_format(const char *from, struct format_spec *format_out)
case 'x':
format_out->kind = HEXADECIMAL;
break;
+ case 'd':
+ format_out->kind = SIGNED_DECIMAL;
+ break;
default:
format_out->kind = UNKNOWN;
break;
@@ -81,7 +84,17 @@ static const char *get_format(const char *from, struct format_spec *format_out)
return from + 1;
}
-//char debug[] = "-- format_v: fmt = \" \"...";
+static uint8_t get_digits(uint32_t k) {
+ if (k >= 1000000000)
+ return 10;
+ uint8_t r = 1;
+ uint32_t n = 10;
+ while (k >= n) {
+ ++r;
+ n *= 10;
+ }
+ return r;
+}
//allocates new memory
char *format_v(const char *fmt, va_list args) {
@@ -92,11 +105,6 @@ char *format_v(const char *fmt, va_list args) {
buf_i = buf;
while (*fmt) {
- //debug[20] = *fmt;
- //debug[21] = fmt[1];
- //debug[22] = fmt[2];
- //_system_log(debug);
-
if (*fmt != '%') {
ensure(1);
*(buf_i++) = *(fmt++);
@@ -137,20 +145,24 @@ char *format_v(const char *fmt, va_list args) {
continue;
uint32_t k;
- case UNSIGNED_DECIMAL:
+ case SIGNED_DECIMAL:
k = va_arg(args, uint32_t);
- if (!form.len) {
- if (k >= 1000000000)
- form.len = 10;
- else {
- uint32_t n = 10;
- ++form.len;
- while (k >= n) {
- ++form.len;
- n *= 10;
- }
- }
+ bool is_neg = k & 0x80000000;
+ if (is_neg) {
+ ensure(1);
+ *(buf_i++) = '-';
+ k = -k;
}
+ if (!form.len)
+ form.len = get_digits(k);
+ else if (is_neg)
+ --form.len;
+ goto print_dec;
+ case UNSIGNED_DECIMAL:
+ k = va_arg(args, uint32_t);
+ if (!form.len)
+ form.len = get_digits(k);
+ print_dec:
ensure(form.len);
const uint32_t len_backup = form.len;
while (form.len--) {
diff --git a/src/user/mdemo/main.c b/src/user/mdemo/main.c
new file mode 100644
index 0000000..fc7de80
--- /dev/null
+++ b/src/user/mdemo/main.c
@@ -0,0 +1,42 @@
+#include <pland/syscall.h>
+#include <popups/info.h>
+
+#define TEXT_COLOR ((_pixel_t){.r = 0x00, .g = 0x00, .b = 0x00})
+#define BG_COLOR ((_pixel_t){.r = 0xbf, .g = 0xbf, .b = 0xbf})
+
+static const char *const mb_names[] = {
+ "left", "right", "middle"
+};
+
+void main() {
+ struct popup main_win;
+ info_popup(&main_win, "Click me!", TEXT_COLOR, BG_COLOR);
+
+ while (1) {
+ struct window_action winact;
+ _get_win_action(main_win.handle, &winact);
+
+ switch (winact.action_type) {
+ struct popup modal;
+ case NOT_READY:
+ _wait_for_action();
+ _yield_task();
+ continue;
+
+ case KEY_DOWN:
+ return;
+
+ case MOUSE_DOWN:
+ info_popupf(&modal,
+ "Got %s click at (%d, %d)!",
+ TEXT_COLOR, BG_COLOR,
+ mb_names[winact.as_mouse.which],
+ winact.as_mouse.x, winact.as_mouse.y);
+ make_modal(&modal);
+ continue;
+
+ default:
+ continue;
+ }
+ }
+} \ No newline at end of file