Changeset 7bf29e5 in mainline for uspace/lib


Ignore:
Timestamp:
2025-01-09T11:29:38Z (7 months ago)
Author:
Miroslav Cimerman <mc@…>
Children:
a5c2960e
Parents:
bc3d695 (diff), 4e1221c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge 'upstream/master' into helenraid-para

Location:
uspace/lib
Files:
18 added
48 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/abs32le/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_abs32le_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     44
     45        sp[-1] = (uintptr_t) arg;
     46        sp[-2] = (uintptr_t) main;
     47
     48        return (uintptr_t) sp;
     49}
     50
    3851#endif
    3952
  • uspace/lib/c/arch/abs32le/src/thread_entry.c

    rbc3d695 r7bf29e5  
    3030 */
    3131
     32#include <stdbool.h>
    3233#include <stddef.h>
    3334#include "../../../generic/private/thread.h"
     
    3536void __thread_entry(void)
    3637{
    37         __thread_main(NULL);
     38        while (true)
     39                ;
    3840}
    3941
  • uspace/lib/c/arch/amd64/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_amd64_THREAD_H_
    3737
     38#include <align.h>
     39#include <stddef.h>
     40#include <stdint.h>
     41
     42static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     43    void (*main)(void *), void *arg)
     44{
     45        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     46
     47        *--sp = (uintptr_t) arg;
     48        *--sp = (uintptr_t) main;
     49
     50        return (uintptr_t) sp;
     51}
     52
    3853#endif
    3954
  • uspace/lib/c/arch/amd64/src/thread_entry.S

    rbc3d695 r7bf29e5  
    3535#
    3636SYMBOL_BEGIN(__thread_entry)
     37        # Pop libc thread entry function and argument
     38        popq %rax
     39        popq %rdi
     40
    3741        #
    3842        # Create the first stack frame.
     
    4246        movq %rsp, %rbp
    4347
    44         #
    45         # RAX contains address of uarg
    46         #
    47         movq %rax, %rdi
    48         call FUNCTION_REF(__thread_main)
     48        call *%rax
    4949SYMBOL_END(__thread_entry)
  • uspace/lib/c/arch/arm32/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3737#define _LIBC_arm32_THREAD_H_
    3838
     39#include <align.h>
     40
     41static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     42    void (*main)(void *), void *arg)
     43{
     44        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     45
     46        *--sp = (uintptr_t) main;
     47        *--sp = (uintptr_t) arg;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3952#endif
    4053
  • uspace/lib/c/arch/arm32/src/thread_entry.S

    rbc3d695 r7bf29e5  
    3535#
    3636SYMBOL(__thread_entry)
     37        # Pop libc entry function and its argument.
     38        pop { r0, r4 }
     39
    3740        #
    3841        # Create the first stack frame.
     
    4346        sub fp, ip, #4
    4447
    45         b __thread_main
     48        bx r4
  • uspace/lib/c/arch/arm64/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_arm64_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     44
     45        *--sp = (uintptr_t) arg;
     46        *--sp = (uintptr_t) main;
     47
     48        return (uintptr_t) sp;
     49}
     50
    3851#endif
    3952
  • uspace/lib/c/arch/arm64/src/thread_entry.S

    rbc3d695 r7bf29e5  
    3535#
    3636SYMBOL(__thread_entry)
    37         #
     37        # Load entry function and argument from stack.
     38        ldp x1, x0, [sp], #16
     39
    3840        # Create the first stack frame.
    39         #
    4041        mov x29, #0
    4142        stp x29, x30, [sp, #-16]!
    4243        mov x29, sp
    4344
    44         b __thread_main
     45        br x1
  • uspace/lib/c/arch/ia32/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_ia32_THREAD_H_
    3737
     38#include <align.h>
     39#include <stddef.h>
     40#include <stdint.h>
     41
     42static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     43    void (*main)(void *), void *arg)
     44{
     45        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     46
     47        *--sp = (uintptr_t) arg;
     48        *--sp = (uintptr_t) main;
     49
     50        return (uintptr_t) sp;
     51}
     52
    3853#endif
    3954
  • uspace/lib/c/arch/ia32/src/syscall.S

    rbc3d695 r7bf29e5  
    7777        pushl %ebp
    7878        mov %esp, %ebp
    79         lea ra, %edi
    8079        movl 20(%esp), %edx     # First argument.
    8180        movl 24(%esp), %ecx     # Second argument.
     
    8382        movl 32(%esp), %esi     # Fourth argument.
    8483        movl 44(%esp), %eax     # Syscall number.
    85         sysenter
    86 ra:
     84        call 1f
    8785        movw %cs, %cx
    8886        addw $8, %cx
     
    9593        popl %ebx
    9694        ret
     95
     96        /* Trampoline for entering kernel */
     971:
     98        pop %edi
     99        sysenter
    97100FUNCTION_END(__syscall_fast)
  • uspace/lib/c/arch/ia32/src/thread_entry.S

    rbc3d695 r7bf29e5  
    4141        # Do not set %gs, it contains descriptor that can see TLS
    4242
     43        # Pop libc thread main function.
     44        popl %eax
     45        # Pop argument.
     46        popl %ebx
     47
    4348        #
    4449        # Create the first stack frame.
     
    4853        mov %esp, %ebp
    4954
    50         #
    51         # EAX contains address of uarg.
    52         #
    53         pushl %eax
    54         call __thread_main
     55        pushl %ebx
     56        call *%eax
    5557
    5658        #
  • uspace/lib/c/arch/ia64/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_ia64_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) (ALIGN_DOWN((uintptr_t) stack + stack_size / 2, 16));
     44
     45        /* Store data under stack pointer */
     46        sp[-1] = (uintptr_t) arg;
     47        sp[-2] = (uintptr_t) main;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3852#endif
    3953
  • uspace/lib/c/arch/ia64/src/thread_entry.S

    rbc3d695 r7bf29e5  
    3737        alloc loc0 = ar.pfs, 0, 1, 1, 0
    3838
    39 #ifndef CONFIG_RTLD
    40         # XXX This does not work in a shared library
    41         movl gp = __gp
    42 #endif
     39        add r8 = -8, sp ;;
     40        # Entry function argument
     41        ld8 out0 = [r8], -8 ;;
    4342
    44         #
    45         # r8 contains address of uarg structure.
    46         #
     43        # Entry function descriptor
     44        ld8 r8 = [r8] ;;
     45        # Entry function address
     46        ld8 r9 = [r8], 8 ;;
     47        # Entry function global pointer
     48        ld8 gp = [r8] ;;
    4749
    48         mov out0 = r8 ;;
    49         # XXX br.call.sptk.many b0 = FUNCTION_REF(__thread_main)
    50         br.call.sptk.many b0 = __thread_main
     50        mov b1 = r9 ;;
     51
     52        br.call.sptk.many b0 = b1 ;;
    5153
    5254        #
  • uspace/lib/c/arch/mips32/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3737#define _LIBC_mips32_THREAD_H_
    3838
     39#include <align.h>
     40
     41static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     42    void (*main)(void *), void *arg)
     43{
     44        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     45
     46        sp[-1] = (uintptr_t) arg;
     47        sp[-2] = (uintptr_t) main;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3952#endif
    4053
  • uspace/lib/c/arch/mips32/src/thread_entry.S

    rbc3d695 r7bf29e5  
    4040#
    4141SYMBOL(__thread_entry)
    42         .ent __thread_entry
    43         .frame $sp, ABI_STACK_FRAME, $ra
    44         .cpload $t9
     42        # All registers should be zero, including $fp and $ra.
     43        # Instead of setting up a stack frame here, we leave it for __thread_main.
    4544
    46         #
    47         # v0 contains address of uarg.
    48         #
    49         add $a0, $v0, 0
     45        # Function argument.
     46        lw $a0, -4($sp)
     47        # Function pointer.
     48        lw $t0, -8($sp)
    5049
    51         # Allocate the stack frame.
    52         addiu $sp, -ABI_STACK_FRAME
    53 
    54         # Allow PIC code
    55         .cprestore 16
    56 
    57         jal __thread_main
     50        j $t0
    5851        nop
    59 
    60         #
    61         # Not reached.
    62         #
    63         addiu $sp, ABI_STACK_FRAME
    64         .end __thread_entry
  • uspace/lib/c/arch/ppc32/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_ppc32_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size - sizeof(void *), 16);
     44
     45        sp[0] = 0;
     46        sp[-1] = (uintptr_t) arg;
     47        sp[-2] = (uintptr_t) main;
     48
     49        return (uintptr_t) sp;
     50}
     51
    3852#endif
    3953
  • uspace/lib/c/arch/ppc32/src/thread_entry.S

    rbc3d695 r7bf29e5  
    3535#
    3636SYMBOL(__thread_entry)
    37         #
    38         # Create the first stack frame.
    39         #
    40         li %r4, 0
    41         stw %r4, 0(%r1)
    42         stwu %r1, -16(%r1)
     37        # Load function and argument.
     38        lwz %r3, -4(%r1)
     39        lwz %r4, -8(%r1)
    4340
    44         b __thread_main
     41        # Clear LR
     42        li %r0, 0
     43        mtlr %r0
    4544
     45        mtctr %r4
     46        bctr
  • uspace/lib/c/arch/riscv64/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3636#define _LIBC_riscv64_THREAD_H_
    3737
     38#include <align.h>
     39
     40static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     41    void (*main)(void *), void *arg)
     42{
     43        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size, 16);
     44
     45        sp[-1] = (uintptr_t) arg;
     46        sp[-2] = (uintptr_t) main;
     47
     48        return (uintptr_t) sp;
     49}
     50
    3851#endif
    3952
  • uspace/lib/c/arch/riscv64/src/thread_entry.c

    rbc3d695 r7bf29e5  
    3535void __thread_entry(void)
    3636{
    37         __thread_main((void *) 0);
     37        // TODO
     38        while (true)
     39                ;
    3840}
    3941
  • uspace/lib/c/arch/sparc64/include/libarch/thread.h

    rbc3d695 r7bf29e5  
    3535#define _LIBC_sparc64_THREAD_H_
    3636
     37#include <assert.h>
     38#include <align.h>
     39#include <libarch/stack.h>
     40
     41static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
     42    void (*main)(void *), void *arg)
     43{
     44        /* We must leave space above the stack pointer for initial register spill area. */
     45        uintptr_t *sp = (uintptr_t *) ALIGN_DOWN((uintptr_t) stack + stack_size - STACK_WINDOW_SAVE_AREA_SIZE - STACK_ARG_SAVE_AREA_SIZE, 16);
     46
     47        sp[-1] = (uintptr_t) arg;
     48        sp[-2] = (uintptr_t) main;
     49
     50        return ((uintptr_t) sp) - STACK_BIAS;
     51}
     52
    3753#endif
    3854
  • uspace/lib/c/arch/sparc64/src/thread_entry.S

    rbc3d695 r7bf29e5  
    3535#
    3636SYMBOL(__thread_entry)
     37        add %sp, 0x7ff, %g1
     38
    3739        #
    3840        # Create the first stack frame.
     
    4345
    4446        #
    45         # Propagate the input arguments to the new window.
     47        # Load libc entry point address and argument from stack
    4648        #
     49        ldn [%g1 - 8], %o0
     50        ldn [%g1 - 16], %g1
    4751
    48         call __thread_main              ! %o0 contains address of uarg
    49         mov %i0, %o0
     52        jmpl %g1, %r0
     53        # Wipe link register
     54        xor %o7, %o7, %o7
    5055
    5156        ! not reached
  • uspace/lib/c/generic/malloc.c

    rbc3d695 r7bf29e5  
    3838#include <stdbool.h>
    3939#include <stddef.h>
     40#include <stdio.h>
    4041#include <as.h>
    4142#include <align.h>
     
    725726 *
    726727 */
    727 static void *malloc_internal(const size_t size, const size_t align)
     728static void *malloc_internal(size_t size, size_t align)
    728729{
    729730        malloc_assert(first_heap_area != NULL);
    730731
     732        if (size == 0)
     733                size = 1;
     734
    731735        if (align == 0)
    732                 return NULL;
     736                align = BASE_ALIGN;
    733737
    734738        size_t falign = lcm(align, BASE_ALIGN);
     
    821825 *
    822826 */
    823 void *realloc(void *const addr, const size_t size)
     827void *realloc(void *const addr, size_t size)
    824828{
    825829        if (size == 0) {
    826                 free(addr);
    827                 return NULL;
     830                fprintf(stderr, "realloc() called with size 0\n");
     831                size = 1;
    828832        }
    829833
     
    930934}
    931935
     936/** Reallocate memory for an array
     937 *
     938 * Same as realloc(ptr, nelem * elsize), except the multiplication is checked
     939 * for numerical overflow. Borrowed from POSIX 2024.
     940 *
     941 * @param ptr
     942 * @param nelem
     943 * @param elsize
     944 *
     945 * @return Reallocated memory or NULL.
     946 */
     947void *reallocarray(void *ptr, size_t nelem, size_t elsize)
     948{
     949        if (nelem > SIZE_MAX / elsize)
     950                return NULL;
     951
     952        return realloc(ptr, nelem * elsize);
     953}
     954
    932955/** Free a memory block
    933956 *
  • uspace/lib/c/generic/private/fibril.h

    rbc3d695 r7bf29e5  
    3333#include <context.h>
    3434#include <tls.h>
    35 #include <abi/proc/uarg.h>
    3635#include <fibril.h>
    3736#include <ipc/common.h>
     
    5049        context_t ctx;
    5150
    52         uspace_arg_t uarg;
    5351        link_t link;
    5452        void *stack;
  • uspace/lib/c/generic/private/thread.h

    rbc3d695 r7bf29e5  
    3737
    3838#include <time.h>
    39 #include <abi/proc/uarg.h>
    4039#include <libarch/thread.h>
    4140#include <abi/proc/thread.h>
    4241
    4342extern void __thread_entry(void);
    44 extern void __thread_main(uspace_arg_t *);
    4543
    46 extern errno_t thread_create(void (*)(void *), void *, const char *,
    47     thread_id_t *);
     44extern errno_t thread_create(errno_t (*)(void *), void *, const char *);
    4845extern void thread_exit(int) __attribute__((noreturn));
    49 extern void thread_detach(thread_id_t);
    5046extern thread_id_t thread_get_id(void);
    5147extern void thread_usleep(usec_t);
  • uspace/lib/c/generic/thread/fibril.c

    rbc3d695 r7bf29e5  
    781781}
    782782
    783 static void _runner_fn(void *arg)
     783static errno_t _runner_fn(void *arg)
    784784{
    785785        _helper_fibril_fn(arg);
     786        return EOK;
    786787}
    787788
     
    808809
    809810        for (int i = 0; i < n; i++) {
    810                 thread_id_t tid;
    811                 rc = thread_create(_runner_fn, NULL, "fibril runner", &tid);
     811                rc = thread_create(_runner_fn, NULL, "fibril runner");
    812812                if (rc != EOK)
    813813                        return i;
    814                 thread_detach(tid);
    815814        }
    816815
  • uspace/lib/c/generic/thread/thread.c

    rbc3d695 r7bf29e5  
    3737#include <stdlib.h>
    3838#include <libarch/faddr.h>
    39 #include <abi/proc/uarg.h>
    4039#include <fibril.h>
    4140#include <stack.h>
     
    5453 * and exit when thread returns back.
    5554 *
    56  * @param uarg Pointer to userspace argument structure.
     55 * @param arg Fibril pointer.
    5756 *
    5857 */
    59 void __thread_main(uspace_arg_t *uarg)
     58static void __thread_main(void *arg)
    6059{
     60        fibril_t *fibril = arg;
     61
    6162        assert(!__tcb_is_set());
    62 
    63         fibril_t *fibril = uarg->uspace_thread_arg;
    6463        assert(fibril);
    6564
    6665        __tcb_set(fibril->tcb);
    6766
    68         uarg->uspace_thread_function(fibril->arg);
     67        fibril->func(fibril->arg);
    6968        /*
    7069         * XXX: we cannot free the userspace stack while running on it
     
    9089 * @return Zero on success or a code from @ref errno.h on failure.
    9190 */
    92 errno_t thread_create(void (*function)(void *), void *arg, const char *name,
    93     thread_id_t *tid)
     91errno_t thread_create(errno_t (*func)(void *), void *arg, const char *name)
    9492{
    95         uspace_arg_t *uarg = calloc(1, sizeof(uspace_arg_t));
    96         if (!uarg)
     93        fibril_t *fibril = fibril_alloc();
     94        if (!fibril)
    9795                return ENOMEM;
    9896
    99         fibril_t *fibril = fibril_alloc();
    100         if (!fibril) {
    101                 free(uarg);
    102                 return ENOMEM;
    103         }
     97        fibril->func = func;
     98        fibril->arg = arg;
    10499
    105100        size_t stack_size = stack_size_get();
     
    109104        if (stack == AS_MAP_FAILED) {
    110105                fibril_teardown(fibril);
    111                 free(uarg);
    112106                return ENOMEM;
    113107        }
    114108
    115         fibril->arg = arg;
    116         uarg->uspace_entry = (void *) FADDR(__thread_entry);
    117         uarg->uspace_stack = stack;
    118         uarg->uspace_stack_size = stack_size;
    119         uarg->uspace_thread_function = function;
    120         uarg->uspace_thread_arg = fibril;
    121         uarg->uspace_uarg = uarg;
     109        uintptr_t sp = arch_thread_prepare(stack, stack_size, __thread_main,
     110            fibril);
    122111
    123         errno_t rc = (errno_t) __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg,
    124             (sysarg_t) name, (sysarg_t) str_size(name), (sysarg_t) tid);
     112        errno_t rc = (errno_t) __SYSCALL4(SYS_THREAD_CREATE,
     113            (sysarg_t) FADDR(__thread_entry), sp,
     114            (sysarg_t) name, (sysarg_t) str_size(name));
    125115
    126116        if (rc != EOK) {
     
    130120                 */
    131121                as_area_destroy(stack);
    132                 free(uarg);
    133122        }
    134123
     
    148137        while (true)
    149138                ;
    150 }
    151 
    152 /** Detach thread.
    153  *
    154  * Currently not implemented.
    155  *
    156  * @param thread TID.
    157  */
    158 void thread_detach(thread_id_t thread)
    159 {
    160139}
    161140
  • uspace/lib/c/include/align.h

    rbc3d695 r7bf29e5  
    4141 * @param a             Size of alignment, must be power of 2.
    4242 */
    43 #define ALIGN_DOWN(s, a)        ((s) & ~((a) - 1))
     43#define ALIGN_DOWN(s, a)        ((s) & ~((typeof(s))(a) - 1))
    4444
    4545/** Align to the nearest higher address which is a power of two.
     
    4848 * @param a             Size of alignment, must be power of 2.
    4949 */
    50 #define ALIGN_UP(s, a)          ((long)((s) + ((a) - 1)) & ~((long) (a) - 1))
     50#define ALIGN_UP(s, a)          ((((s) + ((a) - 1)) & ~((typeof(s))(a) - 1)))
    5151
    5252/** Round up to the nearest higher boundary.
  • uspace/lib/c/meson.build

    rbc3d695 r7bf29e5  
    5959
    6060src += files(
     61        'common/adt/bitmap.c',
    6162        'common/adt/checksum.c',
    6263        'common/adt/circ_buf.c',
  • uspace/lib/c/test/double_to_str.c

    rbc3d695 r7bf29e5  
    176176        PCUT_ASSERT_INT_EQUALS(-3, dec);
    177177        PCUT_ASSERT_STR_EQUALS("1100", buf);
     178
     179        d = extract_ieee_double(768.0);
     180        ret = double_to_fixed_str(d, -1, 3, buf, size, &dec);
     181        PCUT_ASSERT_INT_EQUALS(4, ret);
     182        PCUT_ASSERT_INT_EQUALS(-3, dec);
     183        PCUT_ASSERT_STR_EQUALS("768", buf);
    178184}
    179185
  • uspace/lib/clui/src/tinput.c

    rbc3d695 r7bf29e5  
    113113static void tinput_display_tail(tinput_t *ti, size_t start, size_t pad)
    114114{
    115         char32_t *dbuf = malloc((INPUT_MAX_SIZE + 1) * sizeof(char32_t));
    116         if (!dbuf)
    117                 return;
    118 
     115        char32_t stash;
    119116        size_t sa;
    120117        size_t sb;
    121118        tinput_sel_get_bounds(ti, &sa, &sb);
     119        assert(sa <= sb);
    122120
    123121        tinput_console_set_lpos(ti, ti->text_coord + start);
    124122        console_set_style(ti->console, STYLE_NORMAL);
    125123
    126         size_t p = start;
    127         if (p < sa) {
    128                 memcpy(dbuf, ti->buffer + p, (sa - p) * sizeof(char32_t));
    129                 dbuf[sa - p] = '\0';
    130                 printf("%ls", dbuf);
    131                 p = sa;
    132         }
    133 
    134         if (p < sb) {
     124        sa = max(start, sa);
     125        sb = max(start, sb);
     126
     127        if (start < sa) {
     128                stash = ti->buffer[sa];
     129                ti->buffer[sa] = L'\0';
     130                printf("%ls", &ti->buffer[start]);
     131                ti->buffer[sa] = stash;
     132        }
     133
     134        if (sa < sb) {
    135135                console_flush(ti->console);
    136136                console_set_style(ti->console, STYLE_SELECTED);
    137137
    138                 memcpy(dbuf, ti->buffer + p,
    139                     (sb - p) * sizeof(char32_t));
    140                 dbuf[sb - p] = '\0';
    141                 printf("%ls", dbuf);
    142                 p = sb;
    143         }
     138                stash = ti->buffer[sb];
     139                ti->buffer[sb] = L'\0';
     140                printf("%ls", &ti->buffer[sa]);
     141                ti->buffer[sb] = stash;
     142
     143                console_flush(ti->console);
     144                console_set_style(ti->console, STYLE_NORMAL);
     145        }
     146
     147        if (sb < ti->nc) {
     148                ti->buffer[ti->nc] = L'\0';
     149                printf("%ls", &ti->buffer[sb]);
     150        }
     151
     152        for (; pad > 0; pad--)
     153                putuchar(' ');
    144154
    145155        console_flush(ti->console);
    146         console_set_style(ti->console, STYLE_NORMAL);
    147 
    148         if (p < ti->nc) {
    149                 memcpy(dbuf, ti->buffer + p,
    150                     (ti->nc - p) * sizeof(char32_t));
    151                 dbuf[ti->nc - p] = '\0';
    152                 printf("%ls", dbuf);
    153         }
    154 
    155         for (p = 0; p < pad; p++)
    156                 putuchar(' ');
    157 
    158         console_flush(ti->console);
    159 
    160         free(dbuf);
    161156}
    162157
     
    218213        tinput_display_prompt(ti);
    219214
    220         /* The screen might have scrolled after priting the prompt */
     215        /* The screen might have scrolled after printing the prompt */
    221216        tinput_update_origin_coord(ti, ti->prompt_coord + str_width(ti->prompt));
    222217
     
    237232                return;
    238233
    239         unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1;
    240         if (new_width % ti->con_cols == 0) {
    241                 /* Advancing to new line. */
    242                 sysarg_t new_height = (new_width / ti->con_cols) + 1;
    243                 if (new_height >= ti->con_rows) {
    244                         /* Disallow text longer than 1 page for now. */
    245                         return;
    246                 }
    247         }
     234        /* Disallow text longer than 1 page for now. */
     235        unsigned prompt_len = ti->text_coord - ti->prompt_coord;
     236        if (prompt_len + ti->nc + 1 >= ti->con_cols * ti->con_rows)
     237                return;
    248238
    249239        size_t i;
     
    881871}
    882872
     873static errno_t tinput_resize(tinput_t *ti)
     874{
     875        assert(ti->prompt_coord % ti->con_cols == 0);
     876
     877        errno_t rc = console_get_size(ti->console, &ti->con_cols, &ti->con_rows);
     878        if (rc != EOK)
     879                return rc;
     880
     881        sysarg_t col, row;
     882        rc = console_get_pos(ti->console, &col, &row);
     883        if (rc != EOK)
     884                return rc;
     885
     886        assert(ti->prompt_coord <= ti->text_coord);
     887        unsigned prompt_len = ti->text_coord - ti->prompt_coord;
     888
     889        size_t new_caret_coord = row * ti->con_cols + col;
     890
     891        if (prompt_len <= new_caret_coord && ti->pos <= new_caret_coord - prompt_len) {
     892                ti->text_coord = new_caret_coord - ti->pos;
     893                ti->prompt_coord = ti->text_coord - prompt_len;
     894
     895                unsigned prompt_col = ti->prompt_coord % ti->con_cols;
     896                if (prompt_col != 0) {
     897                        /*
     898                         * Prompt doesn't seem to start at column 0, which means
     899                         * the console didn't reflow the line like we expected it to.
     900                         * Change offsets a bit to recover.
     901                         */
     902                        fprintf(stderr, "Unexpected prompt position after resize.\n");
     903                        ti->prompt_coord -= prompt_col;
     904                        ti->text_coord -= prompt_col;
     905
     906                        console_cursor_visibility(ti->console, false);
     907                        tinput_display_prompt(ti);
     908                        tinput_display_tail(ti, 0, prompt_col);
     909                        tinput_position_caret(ti);
     910                        console_cursor_visibility(ti->console, true);
     911                }
     912
     913                assert(ti->prompt_coord % ti->con_cols == 0);
     914        } else {
     915                /*
     916                 * Overflown screen.
     917                 * We will just trim the buffer and rewrite everything.
     918                 */
     919                console_clear(ti->console);
     920
     921                ti->nc = min(ti->nc, ti->con_cols * ti->con_rows - prompt_len - 1);
     922                ti->pos = min(ti->pos, ti->nc);
     923                ti->sel_start = min(ti->sel_start, ti->nc);
     924
     925                ti->prompt_coord = 0;
     926                ti->text_coord = prompt_len;
     927
     928                console_cursor_visibility(ti->console, false);
     929                tinput_display_prompt(ti);
     930                tinput_display_tail(ti, 0, 0);
     931                tinput_position_caret(ti);
     932                console_cursor_visibility(ti->console, true);
     933        }
     934
     935        assert(ti->nc + ti->text_coord < ti->con_cols * ti->con_rows);
     936
     937        return EOK;
     938}
     939
    883940/** Read in one line of input with initial text provided.
    884941 *
     
    927984                        tinput_pos(ti, &ev.ev.pos);
    928985                        break;
     986                case CEV_RESIZE:
     987                        tinput_resize(ti);
     988                        break;
    929989                }
    930990        }
  • uspace/lib/console/include/io/cons_event.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3636#define _LIBCONSOLE_IO_CONS_EVENT_H_
    3737
    38 #include <adt/list.h>
    3938#include <io/kbd_event.h>
    4039#include <io/pos_event.h>
     
    4443        CEV_KEY,
    4544        /** Position event */
    46         CEV_POS
     45        CEV_POS,
     46        /** Resize event */
     47        CEV_RESIZE,
    4748} cons_event_type_t;
    4849
    4950/** Console event structure. */
    5051typedef struct {
    51         /** List handle */
    52         link_t link;
    53 
    5452        /** Event type */
    5553        cons_event_type_t type;
  • uspace/lib/console/src/con_srv.c

    rbc3d695 r7bf29e5  
    5353                ipc_set_arg4(icall, event->ev.key.mods);
    5454                ipc_set_arg5(icall, event->ev.key.c);
    55                 break;
     55                return EOK;
    5656        case CEV_POS:
    5757                ipc_set_arg2(icall, (event->ev.pos.pos_id << 16) | (event->ev.pos.type & 0xffff));
     
    5959                ipc_set_arg4(icall, event->ev.pos.hpos);
    6060                ipc_set_arg5(icall, event->ev.pos.vpos);
    61                 break;
    62         default:
    63                 return EIO;
    64         }
    65 
    66         return EOK;
     61                return EOK;
     62        case CEV_RESIZE:
     63                ipc_set_arg2(icall, 0);
     64                ipc_set_arg3(icall, 0);
     65                ipc_set_arg4(icall, 0);
     66                ipc_set_arg5(icall, 0);
     67                return EOK;
     68        }
     69
     70        return EIO;
    6771}
    6872
     
    462466                }
    463467
    464                 if (!received)
     468                if (!received || srv->srvs->aborted)
    465469                        break;
    466470
  • uspace/lib/console/src/console.c

    rbc3d695 r7bf29e5  
    193193                event->ev.key.mods = ipc_get_arg4(call);
    194194                event->ev.key.c = ipc_get_arg5(call);
    195                 break;
     195                return EOK;
    196196        case CEV_POS:
    197197                event->ev.pos.pos_id = ipc_get_arg2(call) >> 16;
     
    200200                event->ev.pos.hpos = ipc_get_arg4(call);
    201201                event->ev.pos.vpos = ipc_get_arg5(call);
    202                 break;
    203         default:
    204                 return EIO;
    205         }
    206 
    207         return EOK;
     202                return EOK;
     203        case CEV_RESIZE:
     204                return EOK;
     205        }
     206
     207        return EIO;
    208208}
    209209
  • uspace/lib/display/include/display.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4848extern errno_t display_open(const char *, display_t **);
    4949extern void display_close(display_t *);
     50extern void display_lock(display_t *);
     51extern void display_unlock(display_t *);
    5052extern errno_t display_get_info(display_t *, display_info_t *);
    5153
  • uspace/lib/display/include/types/display/wndparams.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4242        /** Popup window (capture events, no focus) */
    4343        wndf_popup = 0x1,
     44        /** Window does not receive focus */
     45        wndf_nofocus = 0x2,
    4446        /** Topmost window */
    45         wndf_topmost = 0x2,
     47        wndf_topmost = 0x4,
    4648        /** Set specific initial window position */
    47         wndf_setpos = 0x4,
     49        wndf_setpos = 0x8,
    4850        /** Window is minimized */
    49         wndf_minimized = 0x8,
     51        wndf_minimized = 0x10,
    5052        /** Window is maximized */
    51         wndf_maximized = 0x10,
     53        wndf_maximized = 0x20,
    5254        /** Special system window */
    53         wndf_system = 0x20,
     55        wndf_system = 0x40,
    5456        /** Maximized windows should avoid this window */
    55         wndf_avoid = 0x40
     57        wndf_avoid = 0x80
    5658} display_wnd_flags_t;
    5759
  • uspace/lib/display/src/display.c

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    138138}
    139139
     140/*
     141 * Lock display.
     142 *
     143 * While display is locked, display event handlers will not be called.
     144 *
     145 * @param display Display
     146 */
     147void display_lock(display_t *display)
     148{
     149        fibril_mutex_lock(&display->lock);
     150}
     151
     152/*
     153 * Unlock display.
     154 *
     155 * @param display Display
     156 */
     157void display_unlock(display_t *display)
     158{
     159        fibril_mutex_unlock(&display->lock);
     160}
     161
    140162/** Initialize window parameters structure.
    141163 *
     
    700722        display_wnd_ev_t event;
    701723
     724        display_lock(display);
     725
    702726        while (true) {
    703                 fibril_mutex_lock(&display->lock);
    704 
    705727                if (display->sess != NULL)
    706728                        rc = display_get_event(display, &window, &event);
    707729                else
    708730                        rc = ENOENT;
    709 
    710                 fibril_mutex_unlock(&display->lock);
    711731
    712732                if (rc != EOK)
     
    752772        }
    753773
     774        display_unlock(display);
    754775        async_answer_0(icall, EOK);
    755776}
  • uspace/lib/input/include/io/kbd_event.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3636#define _LIBINPUT_IO_KBD_EVENT_H_
    3737
    38 #include <adt/list.h>
    3938#include <inttypes.h>
    4039#include <io/keycode.h>
     
    4847/** Console event structure. */
    4948typedef struct {
    50         /** List handle */
    51         link_t link;
    52 
    5349        /** Keyboard device ID */
    5450        sysarg_t kbd_id;
  • uspace/lib/meson.build

    rbc3d695 r7bf29e5  
    9090        'scsi',
    9191        'sif',
     92        'system',
    9293        'tbarcfg',
     94        'termui',
    9395        'trackmod',
    9496        'untar',
     
    120122
    121123        'ui',
     124        'vt',
    122125]
    123126
  • uspace/lib/output/include/io/concaps.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3838typedef enum {
    3939        CONSOLE_CAP_NONE = 0,
    40         CONSOLE_CAP_STYLE = 1,
    41         CONSOLE_CAP_INDEXED = 2,
    42         CONSOLE_CAP_RGB = 4
     40        CONSOLE_CAP_CURSORCTL = 1,
     41        CONSOLE_CAP_STYLE = 2,
     42        CONSOLE_CAP_INDEXED = 4,
     43        CONSOLE_CAP_RGB = 8
    4344} console_caps_t;
    4445
  • uspace/lib/system/include/system_srv.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2011 Martin Decky
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup output
     29/** @addtogroup libsystem
    3030 * @{
    3131 */
     32/** @file System control protocol server stub
     33 */
    3234
    33 #ifndef OUTPUT_PROTO_VT100_H_
    34 #define OUTPUT_PROTO_VT100_H_
     35#ifndef _LIBSYSTEM_SYSTEM_SRV_H_
     36#define _LIBSYSTEM_SYSTEM_SRV_H_
    3537
    36 #include <io/charfield.h>
     38#include <async.h>
     39#include <errno.h>
    3740
    38 typedef void (*vt100_putuchar_t)(char32_t ch);
    39 typedef void (*vt100_control_puts_t)(const char *str);
    40 typedef void (*vt100_flush_t)(void);
     41typedef struct system_ops system_ops_t;
    4142
     43/** System server structure (per client session) */
    4244typedef struct {
    43         sysarg_t cols;
    44         sysarg_t rows;
     45        async_sess_t *client_sess;
     46        system_ops_t *ops;
     47        void *arg;
     48} system_srv_t;
    4549
    46         sysarg_t cur_col;
    47         sysarg_t cur_row;
    48         char_attrs_t cur_attrs;
     50struct system_ops {
     51        errno_t (*shutdown)(void *);
     52};
    4953
    50         vt100_putuchar_t putuchar;
    51         vt100_control_puts_t control_puts;
    52         vt100_flush_t flush;
    53 } vt100_state_t;
    54 
    55 extern vt100_state_t *vt100_state_create(sysarg_t, sysarg_t, vt100_putuchar_t,
    56     vt100_control_puts_t, vt100_flush_t);
    57 extern void vt100_state_destroy(vt100_state_t *);
    58 
    59 extern errno_t vt100_yield(vt100_state_t *);
    60 extern errno_t vt100_claim(vt100_state_t *);
    61 extern void vt100_get_dimensions(vt100_state_t *, sysarg_t *, sysarg_t *);
    62 
    63 extern void vt100_goto(vt100_state_t *, sysarg_t, sysarg_t);
    64 extern void vt100_set_attr(vt100_state_t *, char_attrs_t);
    65 extern void vt100_cursor_visibility(vt100_state_t *, bool);
    66 extern void vt100_putuchar(vt100_state_t *, char32_t);
    67 extern void vt100_flush(vt100_state_t *);
     54extern void system_conn(ipc_call_t *, system_srv_t *);
     55extern void system_srv_initialize(system_srv_t *);
     56extern void system_srv_shutdown_complete(system_srv_t *);
     57extern void system_srv_shutdown_failed(system_srv_t *);
    6858
    6959#endif
  • uspace/lib/ui/include/types/ui/msgdialog.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4545typedef struct ui_msg_dialog ui_msg_dialog_t;
    4646
     47enum {
     48        /** Maximum number of buttons in message dialog. */
     49        ui_msg_dialog_maxbtn = 2
     50};
     51
     52/** Which choices the user can select from. */
     53typedef enum {
     54        /** OK (the default) */
     55        umdc_ok,
     56        /** OK, Cancel */
     57        umdc_ok_cancel
     58} ui_msg_dialog_choice_t;
     59
    4760/** Message dialog parameters */
    4861typedef struct {
     
    5164        /** Message text */
    5265        const char *text;
     66        /** The choice that the user is given */
     67        ui_msg_dialog_choice_t choice;
    5368} ui_msg_dialog_params_t;
    5469
  • uspace/lib/ui/include/types/ui/testctl.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3636#ifndef _UI_TYPES_TESTCTL_H
    3737#define _UI_TYPES_TESTCTL_H
     38
     39#include <errno.h>
     40#include <io/kbd_event.h>
     41#include <io/pos_event.h>
     42#include <stdbool.h>
     43#include <types/ui/event.h>
    3844
    3945struct ui_test_ctl;
  • uspace/lib/ui/include/types/ui/window.h

    rbc3d695 r7bf29e5  
    5858        /** Place window to the bottom-right corner of the screen */
    5959        ui_wnd_place_bottom_right,
     60        /** Place window to the center of the screen */
     61        ui_wnd_place_center,
    6062        /** Place window accross the entire screen */
    6163        ui_wnd_place_full_screen,
     
    6870        /** Popup window */
    6971        ui_wndf_popup = 0x1,
     72        /** Window does not receive focus */
     73        ui_wndf_nofocus = 0x2,
    7074        /** Topmost window */
    71         ui_wndf_topmost = 0x2,
     75        ui_wndf_topmost = 0x4,
    7276        /** Special system window */
    73         ui_wndf_system = 0x4,
     77        ui_wndf_system = 0x8,
    7478        /** Maximized windows should avoid this window */
    75         ui_wndf_avoid = 0x8
     79        ui_wndf_avoid = 0x10
    7680} ui_wnd_flags_t;
    7781
     
    8084        /** Window rectangle */
    8185        gfx_rect_t rect;
     86        /** Minimum size to which window can be resized */
     87        gfx_coord2_t min_size;
    8288        /** Window caption */
    8389        const char *caption;
  • uspace/lib/ui/private/msgdialog.h

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3838#define _UI_PRIVATE_MSGDIALOG_H
    3939
     40#include <types/ui/msgdialog.h>
     41#include <ui/pbutton.h>
     42#include <ui/window.h>
     43
    4044/** Actual structure of message dialog.
    4145 *
     
    4549        /** Dialog window */
    4650        struct ui_window *window;
    47         /** OK button */
    48         struct ui_pbutton *bok;
     51        /** Buttons */
     52        struct ui_pbutton *btn[ui_msg_dialog_maxbtn];
    4953        /** Message dialog callbacks */
    5054        struct ui_msg_dialog_cb *cb;
  • uspace/lib/ui/src/filedialog.c

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    396396 *
    397397 * @param window Window
    398  * @param arg Argument (ui_prompt_dialog_t *)
     398 * @param arg Argument (ui_file_dialog_t *)
    399399 * @param event Keyboard event
    400400 */
     
    427427                }
    428428        }
    429 
    430429}
    431430
  • uspace/lib/ui/src/msgdialog.c

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4747
    4848static void ui_msg_dialog_wnd_close(ui_window_t *, void *);
     49static void ui_msg_dialog_wnd_kbd(ui_window_t *, void *, kbd_event_t *);
    4950
    5051ui_window_cb_t ui_msg_dialog_wnd_cb = {
    51         .close = ui_msg_dialog_wnd_close
     52        .close = ui_msg_dialog_wnd_close,
     53        .kbd = ui_msg_dialog_wnd_kbd
    5254};
    5355
     
    5658ui_pbutton_cb_t ui_msg_dialog_btn_cb = {
    5759        .clicked = ui_msg_dialog_btn_clicked
     60};
     61
     62static const char *ui_msg_dialog_captions[][ui_msg_dialog_maxbtn + 1] = {
     63        [umdc_ok] = { "OK", NULL },
     64        [umdc_ok_cancel] = { "OK", "Cancel", NULL }
    5865};
    5966
     
    8693        ui_fixed_t *fixed = NULL;
    8794        ui_label_t *label = NULL;
    88         ui_pbutton_t *bok = NULL;
     95        ui_pbutton_t *btn[ui_msg_dialog_maxbtn];
     96        const char **cp;
     97        unsigned i, nb;
    8998        gfx_rect_t rect;
     99        gfx_coord_t bw, bpad, btnsw, bp0x;
    90100        ui_resource_t *ui_res;
     101
     102        for (i = 0; i < ui_msg_dialog_maxbtn; i++)
     103                btn[i] = NULL;
    91104
    92105        dialog = calloc(1, sizeof(ui_msg_dialog_t));
     
    103116                wparams.rect.p0.x = 0;
    104117                wparams.rect.p0.y = 0;
    105                 wparams.rect.p1.x = 40;
     118                wparams.rect.p1.x = 60;
    106119                wparams.rect.p1.y = 7;
    107120        } else {
    108121                wparams.rect.p0.x = 0;
    109122                wparams.rect.p0.y = 0;
    110                 wparams.rect.p1.x = 200;
     123                wparams.rect.p1.x = 400;
    111124                wparams.rect.p1.y = 110;
    112125        }
     
    132145                rect.p0.x = 3;
    133146                rect.p0.y = 2;
    134                 rect.p1.x = 17;
     147                rect.p1.x = 57;
    135148                rect.p1.y = 3;
    136149        } else {
    137150                rect.p0.x = 10;
    138151                rect.p0.y = 35;
    139                 rect.p1.x = 190;
     152                rect.p1.x = 390;
    140153                rect.p1.y = 50;
    141154        }
     
    150163        label = NULL;
    151164
    152         rc = ui_pbutton_create(ui_res, "OK", &bok);
    153         if (rc != EOK)
    154                 goto error;
    155 
    156         ui_pbutton_set_cb(bok, &ui_msg_dialog_btn_cb, dialog);
    157 
    158         /* FIXME: Auto layout */
     165        i = 0;
     166        assert(params->choice == umdc_ok || params->choice == umdc_ok_cancel);
     167        cp = ui_msg_dialog_captions[params->choice];
     168
     169        while (*cp != NULL) {
     170                rc = ui_pbutton_create(ui_res, *cp, &btn[i]);
     171                if (rc != EOK)
     172                        goto error;
     173
     174                ui_pbutton_set_cb(btn[i], &ui_msg_dialog_btn_cb, dialog);
     175                ++cp;
     176                ++i;
     177        }
     178
     179        nb = i;
     180
    159181        if (ui_is_textmode(ui)) {
    160                 rect.p0.x = 8;
    161                 rect.p0.y = 4;
    162                 rect.p1.x = 12;
    163                 rect.p1.y = 5;
     182                bw = 12;
     183                bpad = 2;
    164184        } else {
    165                 rect.p0.x = 55;
    166                 rect.p0.y = 60;
    167                 rect.p1.x = 145;
    168                 rect.p1.y = 88;
    169         }
    170 
    171         ui_pbutton_set_rect(bok, &rect);
    172 
    173         ui_pbutton_set_default(bok, true);
    174 
    175         rc = ui_fixed_add(fixed, ui_pbutton_ctl(bok));
    176         if (rc != EOK)
    177                 goto error;
    178 
    179         dialog->bok = bok;
    180         bok = NULL;
     185                bw = 90;
     186                bpad = 10;
     187        }
     188
     189        btnsw = (nb - 1) * (bw + bpad) + bw;
     190        bp0x = (wparams.rect.p0.x + wparams.rect.p1.x - btnsw) / 2;
     191
     192        for (i = 0; i < nb; i++) {
     193                /* FIXME: Auto layout */
     194                if (ui_is_textmode(ui)) {
     195                        rect.p0.x = bp0x + i * (bw + bpad);
     196                        rect.p0.y = 4;
     197                        rect.p1.x = bp0x + bw + i * (bw + bpad);
     198                        rect.p1.y = 5;
     199                } else {
     200                        rect.p0.x = bp0x + i * (bw + bpad);
     201                        rect.p0.y = 60;
     202                        rect.p1.x = bp0x + bw + i * (bw + bpad);
     203                        rect.p1.y = 88;
     204                }
     205
     206                ui_pbutton_set_rect(btn[i], &rect);
     207
     208                rc = ui_fixed_add(fixed, ui_pbutton_ctl(btn[i]));
     209                if (rc != EOK)
     210                        goto error;
     211        }
     212
     213        ui_pbutton_set_default(btn[0], true);
     214
     215        for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
     216                dialog->btn[i] = btn[i];
     217                btn[i] = NULL;
     218        }
    181219
    182220        ui_window_add(window, ui_fixed_ctl(fixed));
     
    191229        return EOK;
    192230error:
    193         if (bok != NULL)
    194                 ui_pbutton_destroy(bok);
     231        for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
     232                if (btn[i] != NULL)
     233                        ui_pbutton_destroy(btn[i]);
     234        }
    195235        if (label != NULL)
    196236                ui_label_destroy(label);
     
    243283}
    244284
     285/** Message dialog window keyboard event handler.
     286 *
     287 * @param window Window
     288 * @param arg Argument (ui_msg_dialog_t *)
     289 * @param event Keyboard event
     290 */
     291static void ui_msg_dialog_wnd_kbd(ui_window_t *window, void *arg,
     292    kbd_event_t *event)
     293{
     294        ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
     295        ui_evclaim_t claim;
     296
     297        claim = ui_window_def_kbd(window, event);
     298        if (claim == ui_claimed)
     299                return;
     300
     301        if (event->type == KEY_PRESS &&
     302            (event->mods & (KM_CTRL | KM_SHIFT | KM_ALT)) == 0) {
     303                if (event->key == KC_ENTER) {
     304                        /* OK / default button */
     305                        if (dialog->cb != NULL && dialog->cb->button != NULL) {
     306                                dialog->cb->button(dialog, dialog->arg, 0);
     307                                return;
     308                        }
     309                } else if (event->key == KC_ESCAPE) {
     310                        /* Cancel */
     311                        if (dialog->cb != NULL && dialog->cb->close != NULL) {
     312                                dialog->cb->close(dialog, dialog->arg);
     313                                return;
     314                        }
     315                }
     316        }
     317
     318}
     319
    245320/** Message dialog button click handler.
    246321 *
     
    251326{
    252327        ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
    253 
    254         if (dialog->cb != NULL && dialog->cb->button != NULL)
    255                 dialog->cb->button(dialog, dialog->arg, 0);
     328        unsigned i;
     329
     330        if (dialog->cb != NULL && dialog->cb->button != NULL) {
     331                for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
     332                        if (dialog->btn[i] == pbutton)
     333                                dialog->cb->button(dialog, dialog->arg, i);
     334                }
     335        }
    256336}
    257337
  • uspace/lib/ui/src/ui.c

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2023 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    357357
    358358                break;
     359        case CEV_RESIZE:
     360                ui_lock(ui);
     361                ui_window_send_resize(awnd);
     362                ui_unlock(ui);
     363                break;
    359364        }
    360365}
     
    563568void ui_lock(ui_t *ui)
    564569{
     570        if (ui->display != NULL)
     571                display_lock(ui->display);
    565572        fibril_mutex_lock(&ui->lock);
    566573}
     
    577584{
    578585        fibril_mutex_unlock(&ui->lock);
     586        if (ui->display != NULL)
     587                display_unlock(ui->display);
    579588}
    580589
  • uspace/lib/ui/src/window.c

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    189189        switch (params->placement) {
    190190        case ui_wnd_place_default:
    191                 assert(ui_is_fullscreen(window->ui));
     191        case ui_wnd_place_center:
     192                assert(params->placement != ui_wnd_place_default ||
     193                    ui_is_fullscreen(window->ui));
    192194                /* Center window */
    193195                gfx_rect_dims(&params->rect, &dims);
     
    343345        dparams.rect = params->rect;
    344346        dparams.caption = params->caption;
    345         /* Only allow making the window larger */
    346         gfx_rect_dims(&params->rect, &dparams.min_size);
     347        dparams.min_size = params->min_size;
    347348
    348349        /*
     
    358359        if ((params->flags & ui_wndf_popup) != 0)
    359360                dparams.flags |= wndf_popup;
     361        if ((params->flags & ui_wndf_nofocus) != 0)
     362                dparams.flags |= wndf_nofocus;
    360363        if ((params->flags & ui_wndf_topmost) != 0)
    361364                dparams.flags |= wndf_topmost;
     
    975978        ui_t *ui = window->ui;
    976979
    977         ui_lock(ui);
     980        fibril_mutex_lock(&ui->lock);
    978981        ui_window_send_close(window);
    979         ui_unlock(ui);
     982        fibril_mutex_unlock(&ui->lock);
    980983}
    981984
     
    986989        ui_t *ui = window->ui;
    987990
    988         ui_lock(ui);
     991        fibril_mutex_lock(&ui->lock);
    989992        (void)nfocus;
    990993
     
    995998
    996999        ui_window_send_focus(window, nfocus);
    997         ui_unlock(ui);
     1000        fibril_mutex_unlock(&ui->lock);
    9981001}
    9991002
     
    10041007        ui_t *ui = window->ui;
    10051008
    1006         ui_lock(ui);
     1009        fibril_mutex_lock(&ui->lock);
    10071010        ui_window_send_kbd(window, kbd_event);
    1008         ui_unlock(ui);
     1011        fibril_mutex_unlock(&ui->lock);
    10091012}
    10101013
     
    10201023                return;
    10211024
    1022         ui_lock(ui);
     1025        fibril_mutex_lock(&ui->lock);
    10231026
    10241027        claim = ui_wdecor_pos_event(window->wdecor, event);
    10251028        if (claim == ui_claimed) {
    1026                 ui_unlock(ui);
     1029                fibril_mutex_unlock(&ui->lock);
    10271030                return;
    10281031        }
    10291032
    10301033        ui_window_send_pos(window, event);
    1031         ui_unlock(ui);
     1034        fibril_mutex_unlock(&ui->lock);
    10321035}
    10331036
     
    10451048                return;
    10461049
    1047         ui_lock(ui);
     1050        fibril_mutex_lock(&ui->lock);
    10481051        (void) ui_window_resize(window, rect);
    10491052        ui_window_send_resize(window);
    1050         ui_unlock(ui);
     1053        fibril_mutex_unlock(&ui->lock);
    10511054}
    10521055
     
    10571060        ui_t *ui = window->ui;
    10581061
    1059         ui_lock(ui);
     1062        fibril_mutex_lock(&ui->lock);
    10601063
    10611064        if (window->wdecor != NULL && nfocus == 0) {
     
    10651068
    10661069        ui_window_send_unfocus(window, nfocus);
    1067         ui_unlock(ui);
     1070        fibril_mutex_unlock(&ui->lock);
    10681071}
    10691072
     
    12951298void ui_window_send_minimize(ui_window_t *window)
    12961299{
    1297         if (window->cb != NULL && window->cb->maximize != NULL)
     1300        if (window->cb != NULL && window->cb->minimize != NULL)
    12981301                window->cb->minimize(window, window->arg);
    12991302        else
  • uspace/lib/ui/test/msgdialog.c

    rbc3d695 r7bf29e5  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    9292        ui_msg_dialog_params_t params;
    9393        ui_msg_dialog_t *dialog = NULL;
     94        unsigned i;
    9495        test_cb_resp_t resp;
    9596
     
    100101        params.caption = "Message";
    101102        params.text = "Hello";
     103        params.choice = umdc_ok_cancel;
    102104
    103105        rc = ui_msg_dialog_create(ui, &params, &dialog);
     
    106108
    107109        /* Button callback with no callbacks set */
    108         ui_pbutton_clicked(dialog->bok);
     110        ui_pbutton_clicked(dialog->btn[0]);
    109111
    110112        /* Button callback with callback not implemented */
    111113        ui_msg_dialog_set_cb(dialog, &dummy_msg_dialog_cb, NULL);
    112         ui_pbutton_clicked(dialog->bok);
     114        ui_pbutton_clicked(dialog->btn[0]);
    113115
    114         /* Button callback with real callback set */
    115         resp.button = false;
    116         resp.bnum = 123;
    117         ui_msg_dialog_set_cb(dialog, &test_msg_dialog_cb, &resp);
    118         ui_pbutton_clicked(dialog->bok);
    119         PCUT_ASSERT_TRUE(resp.button);
    120         PCUT_ASSERT_INT_EQUALS(0, resp.bnum);
     116        for (i = 0; i < 2; i++) {
     117                /* Button callback with real callback set */
     118                resp.button = false;
     119                resp.bnum = 123;
     120                ui_msg_dialog_set_cb(dialog, &test_msg_dialog_cb, &resp);
     121                ui_pbutton_clicked(dialog->btn[i]);
     122                PCUT_ASSERT_TRUE(resp.button);
     123                PCUT_ASSERT_INT_EQUALS(i, resp.bnum);
     124        }
    121125
    122126        ui_msg_dialog_destroy(dialog);
Note: See TracChangeset for help on using the changeset viewer.