6 ex__gui__cursor_8c
gullradriel edited this page 2026-10-09 00:55:18 +02:00

examples/ex_gui_cursor.c

Functions

Name
void mouse(N_GUI_CTX * gui, int type, int x, int y)
Send one mouse event.
int main(void )
void expect_true(const char * label, int cond)
Assert a condition, logging which check failed.

Attributes

Name
int failures
Count of failed assertions.

Defines

Name
ALLEGRO_UNSTABLE

Functions Documentation

function mouse

static void mouse(
    N_GUI_CTX * gui,
    int type,
    int x,
    int y
)

Send one mouse event.

Parameters:

  • gui GUI context.
  • type The ALLEGRO_EVENT_MOUSE_* type.
  • x Cursor x.
  • y Cursor y.

function main

int main(
    void 
)

function expect_true

static void expect_true(
    const char * label,
    int cond
)

Assert a condition, logging which check failed.

Parameters:

  • label What is being checked.
  • cond Non-zero to pass.

Attributes Documentation

variable failures

static int failures = 0;

Count of failed assertions.

Macros Documentation

define ALLEGRO_UNSTABLE

#define ALLEGRO_UNSTABLE 1

Source code

/*
 * Nilorea Library
 * Copyright (C) 2005-2026 Castagnier Mickael
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#define ALLEGRO_UNSTABLE 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "nilorea/n_common.h"
#include "nilorea/n_gui.h"
#include "nilorea/n_log.h"

static int failures = 0;

static void expect_true(const char* label, int cond) {
    if (!cond) {
        n_log(LOG_ERR, "%s: FAILED", label);
        failures++;
    } else {
        n_log(LOG_INFO, "%s: OK", label);
    }
}

static void mouse(N_GUI_CTX* gui, int type, int x, int y) {
    ALLEGRO_EVENT ev;
    memset(&ev, 0, sizeof(ev));
    ev.type = (unsigned int)type;
    ev.mouse.x = x;
    ev.mouse.y = y;
    ev.mouse.button = 1;
    n_gui_process_event(gui, ev);
}

int main(void) {
    ALLEGRO_FONT* font;
    N_GUI_CTX* gui;
    int win, sp;
    ALLEGRO_MOUSE_CURSOR* custom = (ALLEGRO_MOUSE_CURSOR*)1;

    set_log_level(LOG_ERR);
    if (!al_init() || !al_init_font_addon()) {
        n_log(LOG_ERR, "allegro init failed");
        return 1;
    }
    font = al_create_builtin_font(); /* no display needed */
    if (!font) {
        n_log(LOG_ERR, "al_create_builtin_font failed");
        return 1;
    }
    gui = n_gui_new_ctx(font);
    if (!gui) {
        n_log(LOG_ERR, "n_gui_new_ctx failed");
        al_destroy_font(font);
        return 1;
    }
    n_gui_set_display_size(gui, 800.0f, 600.0f);
    /* A window with a vertical split pane down the middle of its left half,
       and nothing of the GUI's on the right: the right is "the application's
       own area", where its picking tool would be. */
    win = n_gui_add_window(gui, "W", 0.0f, 0.0f, 400.0f, 600.0f);
    n_gui_window_set_flags(gui, win, N_GUI_WIN_FRAMELESS);
    sp = n_gui_add_splitpane(gui, win, 0.0f, 0.0f, 400.0f, 600.0f, N_GUI_SPLIT_VERTICAL, 0.5f, NULL, NULL);
    n_gui_open_window(gui, win);
    expect_true("split pane created", sp >= 0);

    n_gui_get_cursor(gui, &custom);
    expect_true("the default until asked", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT && custom == NULL);

    n_gui_set_cursor(gui, ALLEGRO_SYSTEM_MOUSE_CURSOR_PRECISION, NULL);
    expect_true("applied at once", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_PRECISION);
    mouse(gui, ALLEGRO_EVENT_MOUSE_AXES, 600, 300);
    expect_true("kept over the application's area", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_PRECISION);

    /* Over the divider the GUI's own resize cursor wins, and the
       application's comes back when the pointer leaves it. */
    mouse(gui, ALLEGRO_EVENT_MOUSE_AXES, 200, 300);
    expect_true("the divider shows its resize cursor", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E);
    mouse(gui, ALLEGRO_EVENT_MOUSE_AXES, 600, 300);
    expect_true("and the application's comes back", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_PRECISION);

    /* A press held is a drag, which keeps the cursor it started with. */
    mouse(gui, ALLEGRO_EVENT_MOUSE_BUTTON_DOWN, 600, 300);
    n_gui_set_cursor(gui, ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE, NULL);
    expect_true("not changed under a held press", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_PRECISION);
    mouse(gui, ALLEGRO_EVENT_MOUSE_BUTTON_UP, 600, 300);
    mouse(gui, ALLEGRO_EVENT_MOUSE_AXES, 601, 300);
    expect_true("changed once it is let go", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE);

    n_gui_set_cursor(gui, ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT, NULL);
    mouse(gui, ALLEGRO_EVENT_MOUSE_AXES, 600, 300);
    n_gui_get_cursor(gui, &custom);
    expect_true("the default hands back to the GUI", n_gui_get_cursor(gui, NULL) == ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT && custom == NULL);

    n_gui_destroy_ctx(&gui);
    al_destroy_font(font);
    if (failures) {
        n_log(LOG_ERR, "ex_gui_cursor: %d failure(s)", failures);
        return 1;
    }
    n_log(LOG_NOTICE, "ex_gui_cursor: all checks passed");
    return 0;
}