Beispiel #1
0
static void SendKeyboardEvent(GKeyboard *k) {
    GSourceListener	*psl;

    // Send to the "All Keyboards" source listeners
    psl = 0;
    while ((psl = geventGetSourceListener((GSourceHandle)&KeyboardTimer, psl)))
        SendKeyboardEventToListener(psl, k);

    // Send to the keyboard specific source listeners
    psl = 0;
    while ((psl = geventGetSourceListener((GSourceHandle)k, psl)))
        SendKeyboardEventToListener(psl, k);
}
Beispiel #2
0
// The reading callback function
static void DialCallback(uint16_t instance, uint16_t rawvalue) {
	struct DialStatus_t *pds;
	GSourceListener		*psl;
	GEventDial			*pe;

	/* Get the information we need */
	pds = DialStatus+instance;

	/* Range scale - if needed */
	if (pds->max != GINPUT_DIAL_MAX_VALUE)
		rawvalue = (uint16_t)((uint32_t)rawvalue * pds->max / GINPUT_DIAL_MAX_VALUE);

	/* Forget about changes below our sensitivity threshold */
	if (rawvalue >= pds->lastvalue) {
		if (rawvalue - pds->lastvalue < pds->sensitivity) return;
	} else {
		if (pds->lastvalue - rawvalue < pds->sensitivity) return;
	}

	/* Save the value */
	pds->lastvalue = rawvalue;

	// Send the event to the listeners that are interested.
	psl = 0;
	while ((psl = geventGetSourceListener((GSourceHandle)(DialStatus+instance), psl))) {
		if (!(pe = (GEventDial *)geventGetEventBuffer(psl)))
			continue;
		pe->type = GEVENT_DIAL;
		pe->instance = instance;
		pe->value = pds->lastvalue;
		geventSendEvent(psl);
	}
}
Beispiel #3
0
void _gwinSendEvent(GHandle gh, GEventType type) {
	GSourceListener	*	psl;
	GEventGWin *		pge;

	// Trigger a GWIN Event
	psl = 0;
	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
		if (!(pge = (GEventGWin *)geventGetEventBuffer(psl)))
			continue;
		pge->type = type;
		pge->gwin = gh;
		#if GWIN_WIDGET_TAGS
			pge->tag = (gh->flags & GWIN_FLG_WIDGET) ? ((GWidgetObject *)gh)->tag : 0;
		#endif
		geventSendEvent(psl);
	}
}
Beispiel #4
0
// Send the button event
static void SendButtonEvent(GWidgetObject *gw) {
	GSourceListener	*	psl;
	GEvent *			pe;
	#define pbe			((GEventGWinButton *)pe)

	// Trigger a GWIN Button Event
	psl = 0;
	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
		if (!(pe = geventGetEventBuffer(psl)))
			continue;
		pbe->type = GEVENT_GWIN_BUTTON;
		pbe->button = (GHandle)gw;
		geventSendEvent(psl);
	}

	#undef pbe
}
Beispiel #5
0
// Send the checkbox event
static void SendCheckboxEvent(GWidgetObject *gw) {
	GSourceListener	*	psl;
	GEvent *			pe;
	#define pce			((GEventGWinCheckbox *)pe)

	// Trigger a GWIN Checkbox Event
	psl = 0;
	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
		if (!(pe = geventGetEventBuffer(psl)))
			continue;
		pce->type = GEVENT_GWIN_CHECKBOX;
		pce->checkbox = &gw->g;
		pce->isChecked = (gw->g.flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
		geventSendEvent(psl);
	}

	#undef pce
}
// Send the button event
static void SendRadioEvent(GWidgetObject *gw) {
	GSourceListener	*	psl;
	GEvent *			pe;
	#define pbe			((GEventGWinRadio *)pe)

	// Trigger a GWIN Button Event
	psl = 0;
	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
		if (!(pe = geventGetEventBuffer(psl)))
			continue;
		pbe->type = GEVENT_GWIN_RADIO;
		pbe->gwin = (GHandle)gw;
		pbe->group = ((GRadioObject *)gw)->group;
		#if GWIN_WIDGET_TAGS
			pbe->tag = gw->tag;
		#endif
		geventSendEvent(psl);
	}

	#undef pbe
}
static void sendListEvent(GWidgetObject *gw, int item) {
	GSourceListener*	psl;
	GEvent*				pe;

	// Trigger a GWIN list event
	psl = 0;

	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
		if (!(pe = geventGetEventBuffer(psl)))
			continue;

		ple->type = GEVENT_GWIN_LIST;
		ple->gwin = (GHandle)gw;
		ple->item = item;
		#if GWIN_WIDGET_TAGS
			ple->tag = gw->tag;
		#endif

		geventSendEvent(psl);
	}
}
Beispiel #8
0
	static void HighSpeedGTimerCallback(void *param) {
		(void) param;
		GSourceListener	*psl;
		GEventADC		*pe;

		psl = 0;
		while ((psl = geventGetSourceListener((GSourceHandle)(&HighSpeedGTimer), psl))) {
			if (!(pe = (GEventADC *)geventGetEventBuffer(psl))) {
				// This listener is missing - save this.
				psl->srcflags |= GADC_HSADC_LOSTEVENT;
				continue;
			}

			pe->type = GEVENT_ADC;
			pe->count = hs.lastcount;
			pe->buffer = hs.lastbuffer;
			pe->flags = hs.lastflags | psl->srcflags;
			psl->srcflags = 0;
			geventSendEvent(psl);
		}
	}
Beispiel #9
0
	static void AudGTimerCallback(void *param) {
		(void) param;
		GSourceListener	*psl;
		GEventADC		*pe;

		psl = 0;
		while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
			if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
				// This listener is missing - save this.
				psl->srcflags |= GADC_AUDIO_IN_LOSTEVENT;
				continue;
			}

			pe->type = GEVENT_AUDIO_IN;
			pe->channel = aud.channel;
			pe->count = lastcount;
			pe->buffer = lastbuffer;
			pe->flags = psl->srcflags;
			psl->srcflags = 0;
			geventSendEvent(psl);
		}
	}
Beispiel #10
0
static void MousePoll(void *param) {
	(void) param;
	GSourceListener	*psl;
	GEventMouse		*pe;
	unsigned 		meta;
	uint16_t		tbtns;
	uint32_t		cdiff;
	uint32_t		mdiff;

	// Save the last mouse state
	MouseConfig.last_buttons = MouseConfig.t.buttons;

	// Get the new mouse reading
	get_calibrated_reading(&MouseConfig.t);

	// Calculate out new event meta value and handle CLICK and CXTCLICK
	meta = GMETA_NONE;

	// Calculate the position difference from our movement reference (update the reference if out of range)
	mdiff = (MouseConfig.t.x - MouseConfig.movepos.x) * (MouseConfig.t.x - MouseConfig.movepos.x) +
		(MouseConfig.t.y - MouseConfig.movepos.y) * (MouseConfig.t.y - MouseConfig.movepos.y);
	if (mdiff > GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER) {
		MouseConfig.movepos.x = MouseConfig.t.x;
		MouseConfig.movepos.y = MouseConfig.t.y;
	}
	
	// Check if the click has moved outside the click area and if so cancel the click
	if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
		cdiff = (MouseConfig.t.x - MouseConfig.clickpos.x) * (MouseConfig.t.x - MouseConfig.clickpos.x) +
			(MouseConfig.t.y - MouseConfig.clickpos.y) * (MouseConfig.t.y - MouseConfig.clickpos.y);
		if (cdiff > GINPUT_MOUSE_MAX_CLICK_JITTER * GINPUT_MOUSE_MAX_CLICK_JITTER)
			MouseConfig.flags &= ~FLG_CLICK_TIMER;
	}

	// Mouse down
	tbtns = MouseConfig.t.buttons & ~MouseConfig.last_buttons;
	if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
		meta |= GMETA_MOUSE_DOWN;
	if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
		MouseConfig.clickpos.x = MouseConfig.t.x;
		MouseConfig.clickpos.y = MouseConfig.t.y;
		MouseConfig.clicktime = chTimeNow();
		MouseConfig.flags |= FLG_CLICK_TIMER;
	}

	// Mouse up
	tbtns = ~MouseConfig.t.buttons & MouseConfig.last_buttons;
	if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
		meta |= GMETA_MOUSE_UP;
	if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
		if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
			if ((tbtns & GINPUT_MOUSE_BTN_LEFT)
					#if GINPUT_MOUSE_CLICK_TIME != TIME_INFINITE
						&& chTimeNow() - MouseConfig.clicktime < MS2ST(GINPUT_MOUSE_CLICK_TIME)
					#endif
					)
				meta |= GMETA_MOUSE_CLICK;
			else
				meta |= GMETA_MOUSE_CXTCLICK;
			MouseConfig.flags &= ~FLG_CLICK_TIMER;
		}
	}

	// Send the event to the listeners that are interested.
	psl = 0;
	while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
		if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
			// This listener is missing - save the meta events that have happened
			psl->srcflags |= meta;
			continue;
		}

		// If we haven't really moved (and there are no meta events) don't bother sending the event
		if (mdiff <= GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER && !psl->srcflags && !meta && !(psl->listenflags & GLISTEN_MOUSENOFILTER))
			continue;

		// Send the event if we are listening for it
		if (((MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
				|| (!(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
				|| (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
			pe->type = GINPUT_MOUSE_EVENT_TYPE;
			pe->instance = 0;
			pe->x = MouseConfig.t.x;
			pe->y = MouseConfig.t.y;
			pe->z = MouseConfig.t.z;
			pe->current_buttons = MouseConfig.t.buttons;
			pe->last_buttons = MouseConfig.last_buttons;
			pe->meta = meta;
			if (psl->srcflags) {
				pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
				pe->meta |= psl->srcflags;
				psl->srcflags = 0;
			}
			geventSendEvent(psl);
		}
	}
}
static void GetMouseReading(GMouse *m) {
	GMouseReading	r;

	// Step 1 - Get the Raw Reading
	{
		m->flags &= ~GMOUSE_FLG_NEEDREAD;
		if (!gmvmt(m)->get(m, &r))
			return;
	}

	// Step 2 - Handle touch and button 0 debouncing
	{
		// Clean off button garbage
		r.buttons &= GINPUT_MOUSE_BTN_MASK;

		#if !GINPUT_TOUCH_NOTOUCH
			// If touch then calculate button 0 from z
			if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH)) {
				if (gmvmt(m)->z_min <= gmvmt(m)->z_max) {
					if (r.z >= gmvmt(m)->z_touchon)			r.buttons |= GINPUT_MOUSE_BTN_LEFT;
					else if (r.z <= gmvmt(m)->z_touchoff)	r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
					else									return;				// bad transitional reading
				} else {
					if (r.z <= gmvmt(m)->z_touchon)			r.buttons |= GINPUT_MOUSE_BTN_LEFT;
					else if (r.z >= gmvmt(m)->z_touchoff)	r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
					else									return;				// bad transitional reading
				}
			}

			// Devices with poor button 0 transitioning need debouncing
			if ((gmvmt(m)->d.flags & GMOUSE_VFLG_POORUPDOWN)) {
				// Are we in a transition test
				if ((m->flags & GMOUSE_FLG_INDELTA)) {
					if (!((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
						// Transition failed
						m->flags &= ~GMOUSE_FLG_INDELTA;
						return;
					}
					// Transition succeeded
					m->flags &= ~GMOUSE_FLG_INDELTA;

				// Should we start a transition test
				} else if (((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
					m->flags |= GMOUSE_FLG_INDELTA;
					return;
				}
			}
		#endif

		#if !GINPUT_TOUCH_NOCALIBRATE_GUI
			// Stop here with just the raw x,y reading during calibration
			if ((m->flags & GMOUSE_FLG_IN_CAL)) {
				if ((r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
					m->r.x = r.x;
					m->r.y = r.y;
				}
				m->r.buttons = r.buttons;
				return;
			}
		#endif
	}

	// Step 3 - Apply calibration, rotation and display clipping
	{
		// If the mouse is up we may need to keep our previous position
		if ((gmvmt(m)->d.flags & GMOUSE_VFLG_ONLY_DOWN) && !(r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
			r.x = m->r.x;
			r.y = m->r.y;

		} else {

			#if !GINPUT_TOUCH_NOCALIBRATE
				// Do we need to calibrate the reading?
				if ((m->flags & GMOUSE_FLG_CALIBRATE))
					CalibrationTransform(&r, &m->caldata);
			#endif

			// We can't clip or rotate if we don't have a display
			if (m->display) {
				coord_t			w, h;

				// We now need display information
				w = gdispGGetWidth(m->display);
				h = gdispGGetHeight(m->display);

				#if GDISP_NEED_CONTROL
					// Do we need to rotate the reading to match the display
					if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
						coord_t		t;

						switch(gdispGGetOrientation(m->display)) {
							case GDISP_ROTATE_0:
								break;
							case GDISP_ROTATE_90:
								t = r.x;
								r.x = w - 1 - r.y;
								r.y = t;
								break;
							case GDISP_ROTATE_180:
								r.x = w - 1 - r.x;
								r.y = h - 1 - r.y;
								break;
							case GDISP_ROTATE_270:
								t = r.y;
								r.y = h - 1 - r.x;
								r.x = t;
								break;
							default:
								break;
						}
					}
				#endif

				// Do we need to clip the reading to the display
				if ((m->flags & GMOUSE_FLG_CLIP)) {
					if (r.x < 0)		r.x = 0;
					else if (r.x >= w)	r.x = w-1;
					if (r.y < 0)		r.y = 0;
					else if (r.y >= h)	r.y = h-1;
				}
			}
		}
	}

	// Step 4 - Apply jitter detection
	#if !GINPUT_TOUCH_NOTOUCH
	{
		const GMouseJitter	*pj;
		uint32_t			diff;

		// Are we in pen or finger mode
		pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter;

		// Is this just movement jitter
		if (pj->move > 0) {
			diff = (uint32_t)(r.x - m->r.x) * (uint32_t)(r.x - m->r.x) + (uint32_t)(r.y - m->r.y) * (uint32_t)(r.y - m->r.y);
			if (diff < (uint32_t)pj->move * (uint32_t)pj->move) {
				r.x = m->r.x;
				r.y = m->r.y;
			}
		}

		// Check if the click has moved outside the click area and if so cancel the click
		if (pj->click > 0 && (m->flags & GMOUSE_FLG_CLICK_TIMER)) {
			diff = (uint32_t)(r.x - m->clickpos.x) * (uint32_t)(r.x - m->clickpos.x) + (uint32_t)(r.y - m->clickpos.y) * (uint32_t)(r.y - m->clickpos.y);
			if (diff > (uint32_t)pj->click * (uint32_t)pj->click)
				m->flags &= ~GMOUSE_FLG_CLICK_TIMER;
		}
	}
	#endif

	// Step 5 - Click, context-click and other meta event detection
	{
		uint16_t		upbtns, dnbtns;

		// Calculate button transitions
		dnbtns = r.buttons & ~m->r.buttons;
		upbtns = ~r.buttons & m->r.buttons;

		// Left mouse down generates the Mouse-down meta event
		if ((dnbtns & GINPUT_MOUSE_BTN_LEFT))
			r.buttons |= GMETA_MOUSE_DOWN;

		// Left mouse up generates the Mouse-up meta event
		if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
			r.buttons |= GMETA_MOUSE_UP;

		// Left/Right mouse down starts the click timer
		if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
			m->clickpos.x = r.x;
			m->clickpos.y = r.y;
			m->clicktime = gfxSystemTicks();
			m->flags |= GMOUSE_FLG_CLICK_TIMER;
		}

		// Left/Right mouse up with the click timer still running may generate a click or context click
		if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT)) && (m->flags & GMOUSE_FLG_CLICK_TIMER)) {
			m->flags &= ~GMOUSE_FLG_CLICK_TIMER;
			m->clicktime = gfxSystemTicks() - m->clicktime;

			// Was this a short click?
			if (m->clicktime <= gfxMillisecondsToTicks(GINPUT_MOUSE_CLICK_TIME)) {
				if ((upbtns & GINPUT_MOUSE_BTN_RIGHT))
					r.buttons |= GMETA_MOUSE_CXTCLICK;
				if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
					r.buttons |= GMETA_MOUSE_CLICK;
			}

			#if !GINPUT_TOUCH_NOTOUCH
				// Was this a long click on a touch device?
				if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH) && m->clicktime >= gfxMillisecondsToTicks(GINPUT_TOUCH_CXTCLICK_TIME))
					r.buttons |= GMETA_MOUSE_CXTCLICK;
			#endif
		}
	}

	// Step 6 - Send the event to the listeners that are interested.
	{
		GSourceListener	*psl;

		// Send to the "All Mice" source listeners
		psl = 0;
		while ((psl = geventGetSourceListener((GSourceHandle)&MouseTimer, psl)))
			SendMouseEvent(psl, m, &r);

		// Send to the mouse specific source listeners
		psl = 0;
		while ((psl = geventGetSourceListener((GSourceHandle)m, psl)))
			SendMouseEvent(psl, m, &r);
	}

	// Step 7 - Finally save the results
	m->r.x = r.x;
	m->r.y = r.y;
	m->r.z = r.z;
	m->r.buttons = r.buttons;
}
Beispiel #12
0
static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
    (void)arg;

    GListener event_listener;
    geventListenerInit(&event_listener);
    geventAttachSource(&event_listener, (GSourceHandle)&current_status, 0);

    visualizer_keyboard_status_t initial_status = {
        .default_layer = 0xFFFFFFFF,
        .layer = 0xFFFFFFFF,
        .mods = 0xFF,
        .leds = 0xFFFFFFFF,
        .suspended = false,
    };

    visualizer_state_t state = {
        .status = initial_status,
        .current_lcd_color = 0,
#ifdef LCD_ENABLE
        .font_fixed5x8 = gdispOpenFont("fixed_5x8"),
        .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12")
#endif
    };
    initialize_user_visualizer(&state);
    state.prev_lcd_color = state.current_lcd_color;

#ifdef LCD_BACKLIGHT_ENABLE
    lcd_backlight_color(
            LCD_HUE(state.current_lcd_color),
            LCD_SAT(state.current_lcd_color),
            LCD_INT(state.current_lcd_color));
#endif

    systemticks_t sleep_time = TIME_INFINITE;
    systemticks_t current_time = gfxSystemTicks();

    while(true) {
        systemticks_t new_time = gfxSystemTicks();
        systemticks_t delta = new_time - current_time;
        current_time = new_time;
        bool enabled = visualizer_enabled;
        if (!same_status(&state.status, &current_status)) {
            if (visualizer_enabled) {
                if (current_status.suspended) {
                    stop_all_keyframe_animations();
                    visualizer_enabled = false;
                    state.status = current_status;
                    user_visualizer_suspend(&state);
                }
                else {
                    state.status = current_status;
                    update_user_visualizer_state(&state);
                }
                state.prev_lcd_color = state.current_lcd_color;
            }
        }
        if (!enabled && state.status.suspended && current_status.suspended == false) {
            // Setting the status to the initial status will force an update
            // when the visualizer is enabled again
            state.status = initial_status;
            state.status.suspended = false;
            stop_all_keyframe_animations();
            user_visualizer_resume(&state);
            state.prev_lcd_color = state.current_lcd_color;
        }
        sleep_time = TIME_INFINITE;
        for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) {
            if (animations[i]) {
                update_keyframe_animation(animations[i], &state, delta, &sleep_time);
            }
        }
#ifdef LED_ENABLE
        gdispGFlush(LED_DISPLAY);
#endif

#ifdef EMULATOR
        draw_emulator();
#endif
        // The animation can enable the visualizer
        // And we might need to update the state when that happens
        // so don't sleep
        if (enabled != visualizer_enabled) {
            sleep_time = 0;
        }

        systemticks_t after_update = gfxSystemTicks();
        unsigned update_delta = after_update - current_time;
        if (sleep_time != TIME_INFINITE) {
            if (sleep_time > update_delta) {
                sleep_time -= update_delta;
            }
            else {
                sleep_time = 0;
            }
        }
        dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time);
#ifdef PROTOCOL_CHIBIOS
        // The gEventWait function really takes milliseconds, even if the documentation says ticks.
        // Unfortunately there's no generic ugfx conversion from system time to milliseconds,
        // so let's do it in a platform dependent way.

        // On windows the system ticks is the same as milliseconds anyway
        if (sleep_time != TIME_INFINITE) {
            sleep_time = ST2MS(sleep_time);
        }
#endif
        geventEventWait(&event_listener, sleep_time);
    }
#ifdef LCD_ENABLE
    gdispCloseFont(state.font_fixed5x8);
    gdispCloseFont(state.font_dejavusansbold12);
#endif

    return 0;
}

void visualizer_init(void) {
    gfxInit();

#ifdef LCD_BACKLIGHT_ENABLE
    lcd_backlight_init();
#endif

#ifdef SERIAL_LINK_ENABLE
    add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) );
#endif

#ifdef LCD_ENABLE
    LCD_DISPLAY = get_lcd_display();
#endif
#ifdef LED_ENABLE
    LED_DISPLAY = get_led_display();
#endif

    // We are using a low priority thread, the idea is to have it run only
    // when the main thread is sleeping during the matrix scanning
    gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack),
                              VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL);
}

void update_status(bool changed) {
    if (changed) {
        GSourceListener* listener = geventGetSourceListener((GSourceHandle)&current_status, NULL);
        if (listener) {
            geventSendEvent(listener);
        }
    }
#ifdef SERIAL_LINK_ENABLE
    static systime_t last_update = 0;
    systime_t current_update = chVTGetSystemTimeX();
    systime_t delta = current_update - last_update;
    if (changed || delta > MS2ST(10)) {
        last_update = current_update;
        visualizer_keyboard_status_t* r = begin_write_current_status();
        *r = current_status;
        end_write_current_status();
    }
#endif
}

uint8_t visualizer_get_mods() {
  uint8_t mods = get_mods();

#ifndef NO_ACTION_ONESHOT
  if (!has_oneshot_mods_timed_out()) {
    mods |= get_oneshot_mods();
  }
#endif  
  return mods;
}

void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds) {
    // Note that there's a small race condition here, the thread could read
    // a state where one of these are set but not the other. But this should
    // not really matter as it will be fixed during the next loop step.
    // Alternatively a mutex could be used instead of the volatile variables

    bool changed = false;
#ifdef SERIAL_LINK_ENABLE
    if (is_serial_link_connected ()) {
        visualizer_keyboard_status_t* new_status = read_current_status();
        if (new_status) {
            if (!same_status(&current_status, new_status)) {
                changed = true;
                current_status = *new_status;
            }
        }
    }
    else {
#else
   {
#endif
        visualizer_keyboard_status_t new_status = {
            .layer = state,
            .default_layer = default_state,
            .mods = mods,
            .leds = leds,
            .suspended = current_status.suspended,
        };
        if (!same_status(&current_status, &new_status)) {
            changed = true;
            current_status = new_status;
        }
    }
    update_status(changed);
}

void visualizer_suspend(void) {
    current_status.suspended = true;
    update_status(true);
}

void visualizer_resume(void) {
    current_status.suspended = false;
    update_status(true);
}
Beispiel #13
0
	static void mouseDown(GWidgetObject *gw, coord_t mx, coord_t my) {
		GHandle		ph, gh;
		int			cnt;

		if (my < 0 || my > ((GTabsetObject *)gw)->border_top)
			return;

		// Work out which tab was pressed
		{
			coord_t		x, w, y;

			cnt = 0;
			x = w = 0;
			y = GWIN_TABSET_TABHEIGHT;
			gh = 0;
			for(ph = gwinGetFirstChild(&gw->g); ph; ph = gwinGetSibling(ph)) {
				if (ph->vmt == (gwinVMT *)&tabpageVMT) {
					w = gdispGetStringWidth(((GWidgetObject *)ph)->text, gw->g.font) + TEXT_PADDING*2;
					x += w;
					if (x > gw->g.width) {
						y += GWIN_TABSET_TABHEIGHT;
						x = w;
					}
					if (my < y && mx < x) {
						gh = ph;
						break;
					}
					cnt++;
				}
			}
			if (!gh || (gh->flags & GWIN_FLG_VISIBLE))
				return;
		}

		// Mark the existing tab as not visible
		for(ph = gwinGetFirstChild(&gw->g); ph; ph = gwinGetSibling(ph)) {
			if (ph->vmt == (gwinVMT *)&tabpageVMT && (ph->flags & GWIN_FLG_VISIBLE)) {
				// Mark this page invisible
				ph->flags &= ~GWIN_FLG_VISIBLE;
				break;
			}
		}

		// Mark this tab as visible
		gh->flags |= GWIN_FLG_VISIBLE;
		_gwinRippleVisibility();

		// Force a redraw of the whole tabset
		_gwinUpdate(&gw->g);

		// Send the Tabset Event
		{
			GSourceListener	*	psl;
			GEventGWinTabset *	pge;

			psl = 0;
			while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
				if (!(pge = (GEventGWinTabset *)geventGetEventBuffer(psl)))
					continue;
				pge->type = GEVENT_GWIN_TABSET;
				pge->gwin = &gw->g;
				#if GWIN_WIDGET_TAGS
					pge->tag = gw->tag;
				#endif
				pge->ghPage = gh;
				pge->nPage = cnt;
				geventSendEvent(psl);
			}
		}
	}