2009-07-10 01:18:57 +00:00
|
|
|
a work-in-progress
|
|
|
|
|
|
|
|
Subject: Update PS3 twin GUI program
|
|
|
|
|
|
|
|
Update the PS3 twin GUI program to work with petitboot-multi-ui.
|
|
|
|
|
|
|
|
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
|
|
|
|
---
|
2009-08-26 22:02:51 +00:00
|
|
|
Makefile.in | 1
|
|
|
|
configure.ac | 12
|
|
|
|
rules.mk | 14
|
|
|
|
ui/twin/ps3-twin.c | 1441 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
4 files changed, 1463 insertions(+), 5 deletions(-)
|
2009-07-10 01:18:57 +00:00
|
|
|
|
2009-08-26 22:02:51 +00:00
|
|
|
--- a/Makefile.in
|
|
|
|
+++ b/Makefile.in
|
|
|
|
@@ -18,6 +18,7 @@ twin_LDFLAGS = @twin_LIBS@
|
|
|
|
|
|
|
|
# build target
|
|
|
|
ENABLE_PS3 = @ENABLE_PS3@
|
|
|
|
+ENABLE_X11 = @ENABLE_X11@
|
|
|
|
|
|
|
|
# other programs
|
|
|
|
INSTALL = @INSTALL@
|
|
|
|
--- a/configure.ac
|
|
|
|
+++ b/configure.ac
|
|
|
|
@@ -56,7 +56,17 @@ AS_IF([test "x$with_twin" != xno],
|
|
|
|
[if test "x$with_twin" != xcheck; then
|
|
|
|
AC_MSG_FAILURE([--with-twin was given, but test for twin failed])
|
|
|
|
fi],
|
|
|
|
- [${twin_LIBS}])])
|
|
|
|
+ [${twin_LIBS}])
|
|
|
|
+ AC_CHECK_HEADERS([libtwin/twin_x11.h])])
|
|
|
|
+
|
|
|
|
+AC_ARG_ENABLE([x11],
|
|
|
|
+ [AS_HELP_STRING([--enable-x11],
|
|
|
|
+ [build for x11])],
|
|
|
|
+ [],
|
|
|
|
+ [enable_x11=check])
|
|
|
|
+
|
|
|
|
+AS_IF([test "x$enable_x11" != xno], [AC_SUBST([ENABLE_X11], ["y"])], [])
|
|
|
|
+
|
|
|
|
|
|
|
|
mkdir -p discover lib/list lib/log lib/pb-protocol lib/system lib/talloc \
|
|
|
|
lib/waiter test ui/common ui/ncurses ui/test ui/twin utils
|
2009-07-10 01:18:57 +00:00
|
|
|
--- a/rules.mk
|
|
|
|
+++ b/rules.mk
|
|
|
|
@@ -54,7 +54,7 @@ ui_common_objs = ui/common/discover-clie
|
|
|
|
ui/common/url.o
|
|
|
|
ncurses_objs = ui/ncurses/nc-scr.o ui/ncurses/nc-menu.o ui/ncurses/nc-ked.o \
|
|
|
|
ui/ncurses/nc-cui.o
|
|
|
|
-twin_objs = ui/twin/pb-twin.o
|
|
|
|
+twin_objs =
|
|
|
|
|
|
|
|
# Makefiles
|
|
|
|
makefiles = Makefile $(top_srcdir)/rules.mk
|
2009-08-26 22:02:51 +00:00
|
|
|
@@ -89,11 +89,17 @@ $(pb_test): $(pb_test_objs)
|
2009-08-24 20:24:28 +00:00
|
|
|
$(LINK.o) -o $@ $^
|
|
|
|
|
|
|
|
# twin gui
|
|
|
|
-pb_twin_objs = $(client_objs) $(twin_objs) ui/twin/ps3-twin.o
|
|
|
|
+pb_twin_objs-y$(ENABLE_PS3) += ui/twin/pb-twin.o
|
|
|
|
+pb_twin_objs-$(ENABLE_PS3) += ui/twin/ps3-twin.o ui/common/ps3.o
|
2009-08-26 22:02:51 +00:00
|
|
|
+pb_twin_cflags-$(ENABLE_X11) += -DUSE_X11
|
2009-08-24 20:24:28 +00:00
|
|
|
+pb_twin_ldflags-$(ENABLE_PS3) += -lps3-utils
|
|
|
|
+
|
|
|
|
+pb_twin_objs = $(client_objs) $(twin_objs) $(pb_twin_objs-y)
|
|
|
|
$(pb_twin_objs): $(makefiles)
|
|
|
|
|
|
|
|
-$(pb_twin): LDFLAGS+=$(twin_LDFLAGS) $(LIBTWIN)
|
|
|
|
-$(pb_twin): CFLAGS+=$(twin_CFLAGS)
|
|
|
|
+$(pb_twin): LDFLAGS += $(pb_twin_ldflags-y) $(twin_LDFLAGS) $(LIBTWIN)
|
2009-08-26 22:02:51 +00:00
|
|
|
+$(pb_twin): CFLAGS += $(pb_twin_cflags-y) $(twin_CFLAGS) \
|
2009-08-24 20:24:28 +00:00
|
|
|
+ -DPB_ARTWORK_PATH='"$(pkgdatadir)/artwork/"'
|
|
|
|
|
|
|
|
$(pb_twin): $(pb_twin_objs)
|
|
|
|
$(LINK.o) -o $@ $^
|
2009-07-10 01:18:57 +00:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/ui/twin/ps3-twin.c
|
2009-08-26 22:02:51 +00:00
|
|
|
@@ -0,0 +1,1441 @@
|
2009-07-10 01:18:57 +00:00
|
|
|
+/*
|
|
|
|
+ * Petitboot twin bootloader for the PS3 game console
|
|
|
|
+ *
|
2009-08-24 20:24:28 +00:00
|
|
|
+ * Copyright (C) 2009 Sony Computer Entertainment Inc.
|
|
|
|
+ * Copyright 2009 Sony Corp.
|
|
|
|
+ *
|
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
|
+ * the Free Software Foundation; version 2 of the License.
|
|
|
|
+ *
|
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
+ * GNU General Public License for more details.
|
|
|
|
+ *
|
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
|
+ * along with this program; if not, write to the Free Software
|
|
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
2009-07-10 01:18:57 +00:00
|
|
|
+ */
|
|
|
|
+
|
2009-08-24 20:24:28 +00:00
|
|
|
+#if defined(HAVE_CONFIG_H)
|
|
|
|
+#include "config.h"
|
|
|
|
+#endif
|
2009-07-10 01:18:57 +00:00
|
|
|
+
|
2009-08-24 20:24:28 +00:00
|
|
|
+#define _GNU_SOURCE
|
2009-07-10 01:18:57 +00:00
|
|
|
+#include <assert.h>
|
2009-08-24 20:24:28 +00:00
|
|
|
+#include <errno.h>
|
|
|
|
+#include <getopt.h>
|
2009-07-10 01:18:57 +00:00
|
|
|
+#include <signal.h>
|
2009-08-24 20:24:28 +00:00
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <sys/time.h>
|
2009-07-10 01:18:57 +00:00
|
|
|
+#include <libtwin/twin.h>
|
|
|
|
+#include <libtwin/twin_fbdev.h>
|
2009-08-24 20:24:28 +00:00
|
|
|
+#include <libtwin/twin_jpeg.h>
|
|
|
|
+#include <libtwin/twin_linux_mouse.h>
|
|
|
|
+#include <libtwin/twin_linux_js.h>
|
|
|
|
+#include <libtwin/twin_png.h>
|
2009-08-26 22:02:51 +00:00
|
|
|
+#if defined(HAVE_LIBTWIN_TWIN_X11_H)
|
2009-08-24 20:24:28 +00:00
|
|
|
+# include <libtwin/twin_x11.h>
|
|
|
|
+#endif
|
|
|
|
+#include <linux/input.h>
|
2009-07-10 01:18:57 +00:00
|
|
|
+
|
|
|
|
+#include "log/log.h"
|
2009-08-24 20:24:28 +00:00
|
|
|
+#include "talloc/talloc.h"
|
|
|
|
+#include "waiter/waiter.h"
|
|
|
|
+#include "ui/common/discover-client.h"
|
|
|
|
+#include "ui/common/ps3.h"
|
|
|
|
+#include "ui/common/timer.h"
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+// twin-ui.c/h
|
|
|
|
+
|
|
|
|
+#define DBG(fmt, args...) pb_log("DBG: " fmt, ## args)
|
|
|
|
+#define DBGS(fmt, args...) \
|
|
|
|
+ pb_log("DBG:%s:%d: " fmt, __func__, __LINE__, ## args)
|
|
|
|
+
|
|
|
|
+/* control to keyboard mappings for the sixaxis controller */
|
|
|
|
+uint8_t sixaxis_map[] = {
|
|
|
|
+ 0, /* 0 Select */
|
|
|
|
+ 0, /* 1 L3 */
|
|
|
|
+ 0, /* 2 R3 */
|
|
|
|
+ 0, /* 3 Start */
|
|
|
|
+ KEY_UP, /* 4 Dpad Up */
|
|
|
|
+ KEY_RIGHT, /* 5 Dpad Right */
|
|
|
|
+ KEY_DOWN, /* 6 Dpad Down */
|
|
|
|
+ KEY_LEFT, /* 7 Dpad Left */
|
|
|
|
+ 0, /* 8 L2 */
|
|
|
|
+ 0, /* 9 R2 */
|
|
|
|
+ 0, /* 10 L1 */
|
|
|
|
+ 0, /* 11 R1 */
|
|
|
|
+ 0, /* 12 Triangle */
|
|
|
|
+ KEY_ENTER, /* 13 Circle */
|
|
|
|
+ 0, /* 14 Cross */
|
|
|
|
+ KEY_DELETE, /* 15 Square */
|
|
|
|
+ 0, /* 16 PS Button */
|
|
|
|
+ 0, /* 17 nothing */
|
|
|
|
+ 0, /* 18 nothing */
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define PBOOT_LEFT_PANE_SIZE 160
|
|
|
|
+#define PBOOT_LEFT_PANE_COLOR 0x80000000
|
|
|
|
+#define PBOOT_LEFT_LINE_COLOR 0xff000000
|
|
|
|
+
|
|
|
|
+#define PBOOT_LEFT_FOCUS_WIDTH 80
|
|
|
|
+#define PBOOT_LEFT_FOCUS_HEIGHT 80
|
|
|
|
+#define PBOOT_LEFT_FOCUS_XOFF 40
|
|
|
|
+#define PBOOT_LEFT_FOCUS_YOFF 40
|
|
|
|
+#define PBOOT_LEFT_FOCUS_XRAD (6 * TWIN_FIXED_ONE)
|
|
|
|
+#define PBOOT_LEFT_FOCUS_YRAD (6 * TWIN_FIXED_ONE)
|
|
|
|
+
|
|
|
|
+#define PBOOT_RIGHT_FOCUS_XOFF 20
|
|
|
|
+#define PBOOT_RIGHT_FOCUS_YOFF 60
|
|
|
|
+#define PBOOT_RIGHT_FOCUS_HEIGHT 80
|
|
|
|
+#define PBOOT_RIGHT_FOCUS_XRAD (6 * TWIN_FIXED_ONE)
|
|
|
|
+#define PBOOT_RIGHT_FOCUS_YRAD (6 * TWIN_FIXED_ONE)
|
|
|
|
+
|
|
|
|
+#define PBOOT_LEFT_ICON_WIDTH 64
|
|
|
|
+#define PBOOT_LEFT_ICON_HEIGHT 64
|
|
|
|
+#define PBOOT_LEFT_ICON_XOFF 50
|
|
|
|
+#define PBOOT_LEFT_ICON_YOFF 50
|
|
|
|
+#define PBOOT_LEFT_ICON_STRIDE 100
|
|
|
|
+
|
|
|
|
+#define PBOOT_RIGHT_OPTION_LMARGIN 30
|
|
|
|
+#define PBOOT_RIGHT_OPTION_RMARGIN 30
|
|
|
|
+#define PBOOT_RIGHT_OPTION_TMARGIN 70
|
|
|
|
+#define PBOOT_RIGHT_OPTION_HEIGHT 64
|
|
|
|
+#define PBOOT_RIGHT_OPTION_STRIDE 100
|
|
|
|
+#define PBOOT_RIGHT_TITLE_TEXT_SIZE (30 * TWIN_FIXED_ONE)
|
|
|
|
+#define PBOOT_RIGHT_SUBTITLE_TEXT_SIZE (18 * TWIN_FIXED_ONE)
|
|
|
|
+#define PBOOT_RIGHT_TITLE_XOFFSET 80
|
|
|
|
+#define PBOOT_RIGHT_TITLE_YOFFSET 30
|
|
|
|
+#define PBOOT_RIGHT_SUBTITLE_XOFFSET 100
|
|
|
|
+#define PBOOT_RIGHT_SUBTITLE_YOFFSET 50
|
|
|
|
+#define PBOOT_RIGHT_BADGE_XOFFSET 2
|
|
|
|
+#define PBOOT_RIGHT_BADGE_YOFFSET 0
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#define PBOOT_RIGHT_TITLE_COLOR 0xff000000
|
|
|
|
+#define PBOOT_RIGHT_SUBTITLE_COLOR 0xff400000
|
|
|
|
+
|
|
|
|
+#define PBOOT_FOCUS_COLOR 0x10404040
|
|
|
|
+
|
|
|
|
+#define PBOOT_STATUS_PANE_COLOR 0x60606060
|
|
|
|
+#define PBOOT_STATUS_PANE_HEIGHT 20
|
|
|
|
+#define PBOOT_STATUS_PANE_XYMARGIN 20
|
|
|
|
+#define PBOOT_STATUS_TEXT_MARGIN 10
|
|
|
|
+#define PBOOT_STATUS_TEXT_SIZE (16 * TWIN_FIXED_ONE)
|
|
|
|
+#define PBOOT_STATUS_TEXT_COLOR 0xff000000
|
|
|
|
+
|
|
|
|
+#define PBOOT_MAX_OPTION 100
|
|
|
|
+#define PBOOT_MAX_DEV 10
|
|
|
|
+
|
|
|
|
+struct pbt_option
|
|
|
|
+{
|
|
|
|
+ char *title;
|
|
|
|
+ char *subtitle;
|
|
|
|
+ twin_pixmap_t *badge;
|
|
|
|
+ twin_pixmap_t *cache;
|
|
|
|
+ twin_rect_t box;
|
|
|
|
+ void *data;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct pbt_device
|
|
|
|
+{
|
|
|
|
+ char *id;
|
|
|
|
+ twin_pixmap_t *badge;
|
|
|
|
+ twin_rect_t box;
|
|
|
|
+ int option_count;
|
|
|
|
+ struct pbt_option options[PBOOT_MAX_OPTION];
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+enum pbt_sig {
|
|
|
|
+ pbt_scr_sig = 111,
|
|
|
|
+ pbt_menu_sig = 222,
|
|
|
|
+ pbt_pane_sig = 333,
|
|
|
|
+ pb_removed_sig = -555,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct pbt_cursor {
|
|
|
|
+ twin_pixmap_t *pixmap;
|
|
|
|
+ int hx;
|
|
|
|
+ int hy;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct pbt_scr {
|
|
|
|
+ enum pbt_sig sig;
|
|
|
|
+ struct pbt_cursor cursor;
|
|
|
|
+ twin_screen_t *tscreen;
|
2009-08-26 22:02:51 +00:00
|
|
|
+#if defined(HAVE_LIBTWIN_TWIN_X11_H)
|
2009-08-24 20:24:28 +00:00
|
|
|
+ twin_x11_t *x11;
|
|
|
|
+#endif
|
2009-08-26 22:02:51 +00:00
|
|
|
+ twin_fbdev_t *fbdev;
|
2009-08-24 20:24:28 +00:00
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct pbt_frame {
|
|
|
|
+ twin_label_t *title;
|
|
|
|
+ twin_label_t *help;
|
|
|
|
+ twin_label_t *status;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct pbt_pane - A twin menu pane.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+struct pbt_pane {
|
|
|
|
+ enum pbt_sig sig;
|
|
|
|
+ twin_window_t *window;
|
|
|
|
+ twin_rect_t focus_box;
|
|
|
|
+ int focus_start;
|
|
|
|
+ int focus_target;
|
|
|
|
+ int focus_curindex;
|
|
|
|
+ int mouse_target;
|
|
|
|
+ int has_focus;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct pbt_menu - A twin menu.
|
|
|
|
+ * @sig: Sanity check signature.
|
|
|
|
+ * @scr: The screen this menu is associated with.
|
|
|
|
+ * @dp: The device pane instance.
|
|
|
|
+ * @op: The option pane instance.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+struct pbt_menu {
|
|
|
|
+ enum pbt_sig sig;
|
|
|
|
+ struct pbt_scr *scr;
|
|
|
|
+ struct pbt_pane *dp;
|
|
|
|
+ struct pbt_pane *op;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// helper
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+static struct pbt_scr *pbt_scr_from_tscreen(twin_screen_t *tscreen);
|
|
|
|
+
|
|
|
|
+static struct pbt_menu *pbt_menu_from_twindow(twin_window_t *twindow)
|
|
|
|
+{
|
|
|
|
+ struct pbt_menu *menu = twindow->client_data;
|
|
|
|
+
|
|
|
|
+ assert(menu);
|
|
|
|
+ assert(menu->sig == pbt_menu_sig);
|
|
|
|
+ return menu;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+static struct pbt_menu *pbt_menu_from_arg(void *arg)
|
|
|
|
+{
|
|
|
|
+ struct pbt_menu *menu = arg;
|
|
|
|
+
|
|
|
|
+ assert(menu);
|
|
|
|
+ assert(menu->sig == pbt_menu_sig);
|
|
|
|
+ return menu;
|
|
|
|
+}
|
|
|
|
+*/
|
|
|
|
+
|
|
|
|
+static struct pbt_pane *pbt_pane_from_arg(void *arg)
|
|
|
|
+{
|
|
|
|
+ struct pbt_pane *pane = arg;
|
|
|
|
+
|
|
|
|
+ assert(pane);
|
|
|
|
+ assert(pane->sig == pbt_pane_sig);
|
|
|
|
+ return pane;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static twin_bool_t pbt_rect_intersect(twin_rect_t r1, twin_rect_t r2)
|
|
|
|
+{
|
|
|
|
+ // FIXME: move this to twin!!!
|
|
|
|
+ return !(r1.left > r2.right ||
|
|
|
|
+ r1.right < r2.left ||
|
|
|
|
+ r1.top > r2.bottom ||
|
|
|
|
+ r1.bottom < r2.top);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static twin_pixmap_t * pbt_load_background(twin_screen_t *tscreen)
|
|
|
|
+{
|
|
|
|
+ static const char *bgd = PB_ARTWORK_PATH "/background.jpg";
|
|
|
|
+ twin_pixmap_t *rawpix;
|
|
|
|
+ twin_pixmap_t *scaledpix;
|
|
|
|
+
|
|
|
|
+ rawpix = twin_jpeg_to_pixmap(bgd, TWIN_ARGB32);
|
|
|
|
+
|
|
|
|
+ if (!rawpix) {
|
|
|
|
+ pb_log("%s: loading image %s failed\n", __func__, bgd);
|
|
|
|
+ return twin_make_pattern();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (tscreen->height == rawpix->height &&
|
|
|
|
+ tscreen->width == rawpix->width)
|
|
|
|
+ return rawpix;
|
|
|
|
+
|
|
|
|
+ /* Scale as needed. */
|
|
|
|
+
|
|
|
|
+ twin_fixed_t sx, sy;
|
|
|
|
+ twin_operand_t srcop;
|
|
|
|
+
|
|
|
|
+ scaledpix = twin_pixmap_create(TWIN_ARGB32,
|
|
|
|
+ tscreen->width,
|
|
|
|
+ tscreen->height);
|
|
|
|
+ if (!scaledpix) {
|
|
|
|
+ pb_log("%s: scale %s failed\n", __func__, bgd);
|
|
|
|
+ twin_pixmap_destroy(rawpix);
|
|
|
|
+ return twin_make_pattern();
|
|
|
|
+ }
|
|
|
|
+ sx = twin_fixed_div(twin_int_to_fixed(rawpix->width),
|
|
|
|
+ twin_int_to_fixed(tscreen->width));
|
|
|
|
+ sy = twin_fixed_div(twin_int_to_fixed(rawpix->height),
|
|
|
|
+ twin_int_to_fixed(tscreen->height));
|
|
|
|
+
|
|
|
|
+ twin_matrix_scale(&rawpix->transform, sx, sy);
|
|
|
|
+ srcop.source_kind = TWIN_PIXMAP;
|
|
|
|
+ srcop.u.pixmap = rawpix;
|
|
|
|
+ twin_composite(scaledpix, 0, 0, &srcop, 0, 0,
|
|
|
|
+ NULL, 0, 0, TWIN_SOURCE,
|
|
|
|
+ tscreen->width, tscreen->height);
|
|
|
|
+
|
|
|
|
+ twin_pixmap_destroy(rawpix);
|
|
|
|
+ return scaledpix;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// option
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+static void pbt_option_execute(struct pbt_menu *menu)
|
|
|
|
+{
|
|
|
|
+#if 0
|
|
|
|
+ pboot_device_t *dev = pboot_devices[pboot_dev_sel];
|
|
|
|
+ pboot_option_t *opt = &dev->options[menu->op->focus_curindex];
|
|
|
|
+
|
|
|
|
+ pb_log("Selected device %s\n", opt->title);
|
|
|
|
+ pboot_message("booting %s...", opt->title);
|
|
|
|
+
|
|
|
|
+ /* Give user feedback, make sure errors and panics will be seen */
|
|
|
|
+ pboot_exec_option(opt->data);
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// device
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// scr
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+static twin_bool_t pbt_scr_event(twin_screen_t *tscreen, twin_event_t *event)
|
|
|
|
+{
|
|
|
|
+ struct pbt_scr *scr = pbt_scr_from_tscreen(tscreen);
|
|
|
|
+
|
|
|
|
+ switch(event->kind) {
|
|
|
|
+ case TwinEventEnter:
|
|
|
|
+ case TwinEventMotion:
|
|
|
|
+ case TwinEventLeave:
|
|
|
|
+ case TwinEventButtonDown:
|
|
|
|
+ case TwinEventButtonUp:
|
|
|
|
+ if (scr->cursor.pixmap)
|
|
|
|
+ twin_screen_set_cursor(tscreen, scr->cursor.pixmap,
|
|
|
|
+ scr->cursor.hx, scr->cursor.hy);
|
|
|
|
+ break;
|
|
|
|
+ case TwinEventJoyButton:
|
|
|
|
+ /* map joystick events into key events */
|
|
|
|
+ if (event->u.js.control >= sizeof(sixaxis_map))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ event->u.key.key = sixaxis_map[event->u.js.control];
|
|
|
|
+ if (event->u.js.value == 0) {
|
|
|
|
+ event->kind = TwinEventKeyUp;
|
|
|
|
+ break;
|
|
|
|
+ } else {
|
|
|
|
+ event->kind = TwinEventKeyDown;
|
|
|
|
+ }
|
|
|
|
+ /* fall through.. */
|
|
|
|
+ case TwinEventKeyDown:
|
|
|
|
+ switch(event->u.key.key) {
|
|
|
|
+ case KEY_0:
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case KEY_BACKSPACE:
|
|
|
|
+ case KEY_DELETE:
|
|
|
|
+ return TWIN_FALSE;
|
|
|
|
+ }
|
|
|
|
+ case TwinEventKeyUp:
|
|
|
|
+ twin_screen_set_cursor(tscreen, NULL, 0, 0);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return TWIN_FALSE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// pane
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+static int pbt_pane_has_focus(const struct pbt_pane *pane)
|
|
|
|
+{
|
|
|
|
+ return pane->has_focus;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static twin_time_t pbt_pane_timeout(twin_time_t now, void *closure)
|
|
|
|
+{
|
|
|
|
+ const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 1, 2, 2, 3 };
|
|
|
|
+ struct pbt_pane *pane = pbt_pane_from_arg(closure);
|
|
|
|
+ int dir = 1, dist, pos;
|
|
|
|
+
|
|
|
|
+ dist = abs(pane->focus_target - pane->focus_start);
|
|
|
|
+ dir = dist > 5 ? 5 : dist;
|
|
|
|
+ pos = pane->focus_target - (int)pane->focus_box.top;
|
|
|
|
+ if (pos == 0) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ if (pos < 0) {
|
|
|
|
+ dir = -dir;
|
|
|
|
+ pos = -pos;
|
|
|
|
+ }
|
|
|
|
+ twin_window_damage(pane->window,
|
|
|
|
+ pane->focus_box.left,
|
|
|
|
+ pane->focus_box.top,
|
|
|
|
+ pane->focus_box.right,
|
|
|
|
+ pane->focus_box.bottom);
|
|
|
|
+
|
|
|
|
+ pane->focus_box.top += dir;
|
|
|
|
+ pane->focus_box.bottom += dir;
|
|
|
|
+
|
|
|
|
+ twin_window_damage(pane->window,
|
|
|
|
+ pane->focus_box.left,
|
|
|
|
+ pane->focus_box.top,
|
|
|
|
+ pane->focus_box.right,
|
|
|
|
+ pane->focus_box.bottom);
|
|
|
|
+
|
|
|
|
+ twin_window_queue_paint(pane->window);
|
|
|
|
+
|
|
|
|
+ return accel[(pos * 10) / dist];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// menu
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pbt_menu_set_focus - Set the menu's pane of focus.
|
|
|
|
+ * @menu: The menu to operate on.
|
|
|
|
+ * @pane: The pane that will have the focus.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static void pbt_menu_set_focus(struct pbt_menu *menu, struct pbt_pane *pane)
|
|
|
|
+{
|
|
|
|
+ assert(!pane->has_focus);
|
|
|
|
+
|
|
|
|
+ if (pane == menu->dp) {
|
|
|
|
+ menu->dp->has_focus = 1;
|
|
|
|
+ menu->op->has_focus = 0;
|
|
|
|
+ } else if (pane == menu->op) {
|
|
|
|
+ menu->dp->has_focus = 0;
|
|
|
|
+ menu->op->has_focus = 1;
|
|
|
|
+// pbt_menu_set_option_focus(menu, 0);
|
|
|
|
+ } else
|
|
|
|
+ assert(0 && "bad logic");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pbt_menu_pane_select(struct pbt_menu *menu, struct pbt_pane *pane)
|
|
|
|
+{
|
|
|
|
+ if(pbt_pane_has_focus(pane))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ twin_screen_set_active(menu->scr->tscreen, pane->window->pixmap);
|
|
|
|
+
|
|
|
|
+ twin_window_damage(menu->dp->window,
|
|
|
|
+ menu->dp->focus_box.left,
|
|
|
|
+ menu->dp->focus_box.top,
|
|
|
|
+ menu->dp->focus_box.right,
|
|
|
|
+ menu->dp->focus_box.bottom);
|
|
|
|
+ twin_window_damage(menu->op->window,
|
|
|
|
+ menu->op->focus_box.left,
|
|
|
|
+ menu->op->focus_box.top,
|
|
|
|
+ menu->op->focus_box.right,
|
|
|
|
+ menu->op->focus_box.bottom);
|
|
|
|
+
|
|
|
|
+ twin_window_queue_paint(menu->dp->window);
|
|
|
|
+ twin_window_queue_paint(menu->op->window);
|
|
|
|
+
|
|
|
|
+ pbt_menu_set_focus(menu, pane);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static struct pbt_pane *pbt_device_pane_create(struct pbt_menu *menu);
|
|
|
|
+static struct pbt_pane *pbt_option_pane_create(struct pbt_menu *menu);
|
|
|
|
+
|
|
|
|
+static struct pbt_menu *pbt_menu_create(void *ctx, struct pbt_scr *scr)
|
|
|
|
+{
|
|
|
|
+ struct pbt_menu *menu = talloc_zero(ctx, struct pbt_menu);
|
|
|
|
+
|
|
|
|
+ if (!menu)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ assert(scr && scr->sig == pbt_scr_sig);
|
|
|
|
+
|
|
|
|
+ menu->sig = pbt_menu_sig;
|
|
|
|
+ menu->scr = scr;
|
|
|
|
+
|
|
|
|
+ menu->dp = pbt_device_pane_create(menu);
|
|
|
|
+
|
|
|
|
+ if (!menu->dp)
|
|
|
|
+ goto fail_dp;
|
|
|
|
+
|
|
|
|
+ menu->op = pbt_option_pane_create(menu);
|
|
|
|
+
|
|
|
|
+ if (!menu->op)
|
|
|
|
+ goto fail_op;
|
|
|
|
+
|
|
|
|
+ return menu;
|
|
|
|
+
|
|
|
|
+fail_op:
|
|
|
|
+ //clean dp
|
|
|
|
+fail_dp:
|
|
|
|
+ talloc_free(menu);
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// device_pane
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+static void pbt_device_pane_draw(twin_window_t *window)
|
|
|
|
+{
|
|
|
|
+ struct pbt_pane *dp = pbt_menu_from_twindow(window)->dp;
|
|
|
|
+ twin_pixmap_t *px = window->pixmap;
|
|
|
|
+ twin_path_t *path;
|
|
|
|
+ twin_fixed_t x, y, w, h;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ /* Fill background */
|
|
|
|
+ twin_fill(px, PBOOT_LEFT_PANE_COLOR, TWIN_SOURCE, 0, 0, px->width,
|
|
|
|
+ px->height);
|
|
|
|
+
|
|
|
|
+ /* Create a path for use later */
|
|
|
|
+ path = twin_path_create();
|
|
|
|
+ assert(path);
|
|
|
|
+
|
|
|
|
+ /* Draw right line if needed */
|
|
|
|
+ if (px->clip.right > (PBOOT_LEFT_PANE_SIZE - 4)) {
|
|
|
|
+ x = twin_int_to_fixed(PBOOT_LEFT_PANE_SIZE - 4);
|
|
|
|
+ y = twin_int_to_fixed(px->height);
|
|
|
|
+ twin_path_rectangle(path, x, 0, 0x40000, y);
|
|
|
|
+ twin_paint_path(px, PBOOT_LEFT_LINE_COLOR, path);
|
|
|
|
+ twin_path_empty(path);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Draw focus box */
|
|
|
|
+ if (dp->focus_curindex >= 0 &&
|
|
|
|
+ pbt_rect_intersect(dp->focus_box, px->clip)) {
|
|
|
|
+ x = twin_int_to_fixed(dp->focus_box.left + 2);
|
|
|
|
+ y = twin_int_to_fixed(dp->focus_box.top + 2);
|
|
|
|
+ w = twin_int_to_fixed(dp->focus_box.right -
|
|
|
|
+ dp->focus_box.left - 4);
|
|
|
|
+ h = twin_int_to_fixed(dp->focus_box.bottom -
|
|
|
|
+ dp->focus_box.top - 4);
|
|
|
|
+ twin_path_rounded_rectangle(path, x, y, w, h,
|
|
|
|
+ PBOOT_LEFT_FOCUS_XRAD,
|
|
|
|
+ PBOOT_LEFT_FOCUS_YRAD);
|
|
|
|
+ if (pbt_pane_has_focus(dp))
|
|
|
|
+ twin_paint_path(px, PBOOT_FOCUS_COLOR, path);
|
|
|
|
+ else
|
|
|
|
+ twin_paint_stroke(px, PBOOT_FOCUS_COLOR, path,
|
|
|
|
+ 4 * TWIN_FIXED_ONE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+#if 0
|
|
|
|
+ /* Draw icons */
|
|
|
|
+ for (i = 0; i < pboot_dev_count; i++) {
|
|
|
|
+ pboot_device_t *dev = pboot_devices[i];
|
|
|
|
+ twin_operand_t src;
|
|
|
|
+
|
|
|
|
+ if (!twin_rect_intersect(dev->box, px->clip))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ src.source_kind = TWIN_PIXMAP;
|
|
|
|
+ src.u.pixmap = dev->badge;
|
|
|
|
+
|
|
|
|
+ twin_composite(px, dev->box.left, dev->box.top,
|
|
|
|
+ &src, 0, 0, NULL, 0, 0, TWIN_OVER,
|
|
|
|
+ dev->box.right - dev->box.left,
|
|
|
|
+ dev->box.bottom - dev->box.top);
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ /* Destroy path */
|
|
|
|
+ twin_path_destroy(path);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void pbt_device_pane_set_focus(struct pbt_menu *menu, int index)
|
|
|
|
+{
|
|
|
|
+#if 0
|
|
|
|
+ if (index >= pboot_dev_count)
|
|
|
|
+ return;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ menu->dp->focus_start = menu->dp->focus_box.top;
|
|
|
|
+
|
|
|
|
+ if (index < 0)
|
|
|
|
+ menu->dp->focus_target = 0 - PBOOT_LEFT_FOCUS_HEIGHT;
|
|
|
|
+ else
|
|
|
|
+ menu->dp->focus_target = PBOOT_LEFT_FOCUS_YOFF +
|
|
|
|
+ PBOOT_LEFT_ICON_STRIDE * index;
|
|
|
|
+
|
|
|
|
+ menu->dp->focus_curindex = index;
|
|
|
|
+
|
|
|
|
+ twin_set_timeout(pbt_pane_timeout, 0, menu->dp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pbt_device_pane_mousetrack(struct pbt_menu *menu, twin_coord_t x,
|
|
|
|
+ twin_coord_t y)
|
|
|
|
+{
|
|
|
|
+ int candidate = -1;
|
|
|
|
+ twin_coord_t icon_top;
|
|
|
|
+
|
|
|
|
+ if (x < PBOOT_LEFT_ICON_XOFF ||
|
|
|
|
+ x > (PBOOT_LEFT_ICON_XOFF + PBOOT_LEFT_ICON_WIDTH))
|
|
|
|
+ goto miss;
|
|
|
|
+
|
|
|
|
+ if (y < PBOOT_LEFT_ICON_YOFF)
|
|
|
|
+ goto miss;
|
|
|
|
+
|
|
|
|
+ candidate = (y - PBOOT_LEFT_ICON_YOFF) / PBOOT_LEFT_ICON_STRIDE;
|
|
|
|
+
|
|
|
|
+#if 0
|
|
|
|
+ if (candidate >= pboot_dev_count) {
|
|
|
|
+ candidate = -1;
|
|
|
|
+ goto miss;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+ if (candidate == menu->dp->mouse_target)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ icon_top = PBOOT_LEFT_ICON_YOFF + candidate * PBOOT_LEFT_ICON_STRIDE;
|
|
|
|
+
|
|
|
|
+ if (y > (icon_top + PBOOT_LEFT_ICON_HEIGHT)) {
|
|
|
|
+ candidate = -1;
|
|
|
|
+ goto miss;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* The mouse hit an icon that wasn't the same
|
|
|
|
+ * as the previous one, trigger a focus change.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ pbt_device_pane_set_focus(menu, candidate);
|
|
|
|
+
|
|
|
|
+ miss:
|
|
|
|
+ menu->dp->mouse_target = candidate;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static twin_bool_t pbt_device_pane_event(twin_window_t *window,
|
|
|
|
+ twin_event_t *event)
|
|
|
|
+{
|
|
|
|
+ struct pbt_menu *menu = pbt_menu_from_twindow(window);
|
|
|
|
+
|
|
|
|
+ /* filter out all mouse events */
|
|
|
|
+ switch(event->kind) {
|
|
|
|
+ case TwinEventEnter:
|
|
|
|
+ case TwinEventMotion:
|
|
|
|
+ case TwinEventLeave:
|
|
|
|
+ pbt_menu_pane_select(menu, menu->dp);
|
|
|
|
+ pbt_device_pane_mousetrack(menu, event->u.pointer.x,
|
|
|
|
+ event->u.pointer.y);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case TwinEventButtonDown:
|
|
|
|
+ case TwinEventButtonUp:
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case TwinEventKeyDown:
|
|
|
|
+ switch(event->u.key.key) {
|
|
|
|
+ case KEY_UP:
|
|
|
|
+ if (menu->dp->focus_curindex > 0)
|
|
|
|
+ pbt_device_pane_set_focus(menu,
|
|
|
|
+ menu->dp->focus_curindex - 1);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case KEY_DOWN:
|
|
|
|
+ pbt_device_pane_set_focus(menu, menu->dp->focus_curindex + 1);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case KEY_RIGHT:
|
|
|
|
+ pbt_menu_pane_select(menu, menu->op);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return TWIN_FALSE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct pbt_pane *pbt_device_pane_create(struct pbt_menu *menu)
|
|
|
|
+{
|
|
|
|
+ struct pbt_pane *pane = talloc_zero(menu, struct pbt_pane);
|
|
|
|
+
|
|
|
|
+ if (!pane)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ pane->sig = pbt_pane_sig;
|
|
|
|
+ pane->window = twin_window_create(menu->scr->tscreen, TWIN_ARGB32,
|
|
|
|
+ TwinWindowPlain, 0, 0, PBOOT_LEFT_PANE_SIZE,
|
|
|
|
+ menu->scr->tscreen->height);
|
|
|
|
+
|
|
|
|
+ if (!pane->window)
|
|
|
|
+ goto fail_window;
|
|
|
|
+
|
|
|
|
+ pane->window->draw = pbt_device_pane_draw;
|
|
|
|
+ pane->window->event = pbt_device_pane_event;
|
|
|
|
+ pane->window->client_data = menu;
|
|
|
|
+
|
|
|
|
+ pane->focus_curindex = -1;
|
|
|
|
+ pane->focus_box.left = PBOOT_LEFT_FOCUS_XOFF;
|
|
|
|
+ pane->focus_box.top = -2 * PBOOT_LEFT_FOCUS_HEIGHT;
|
|
|
|
+ pane->focus_box.right = pane->focus_box.left + PBOOT_LEFT_FOCUS_WIDTH;
|
|
|
|
+ pane->focus_box.bottom = pane->focus_box.top + PBOOT_LEFT_FOCUS_HEIGHT;
|
|
|
|
+
|
|
|
|
+ pane->mouse_target = -1;
|
|
|
|
+
|
|
|
|
+ twin_window_show(pane->window);
|
|
|
|
+ twin_window_queue_paint(pane->window);
|
|
|
|
+
|
|
|
|
+ return pane;
|
|
|
|
+
|
|
|
|
+fail_window:
|
|
|
|
+ talloc_free(pane);
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// option_pane
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+static void pbt_option_pane_set_focus(struct pbt_menu *menu, int index)
|
|
|
|
+{
|
|
|
|
+#if 0
|
|
|
|
+ pboot_device_t *dev;
|
|
|
|
+
|
|
|
|
+ if (pboot_dev_sel < 0 || pboot_dev_sel >= pboot_dev_count)
|
|
|
|
+ return;
|
|
|
|
+ dev = pboot_devices[pboot_dev_sel];
|
|
|
|
+ if (index < 0 || index >= dev->option_count)
|
|
|
|
+ return;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ menu->op->focus_start = menu->op->focus_box.top;
|
|
|
|
+ menu->op->focus_target = PBOOT_RIGHT_FOCUS_YOFF +
|
|
|
|
+ PBOOT_RIGHT_OPTION_STRIDE * index;
|
|
|
|
+ menu->op->focus_curindex = index;
|
|
|
|
+
|
|
|
|
+ twin_set_timeout(pbt_pane_timeout, 0, menu->op);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pbt_option_pane_draw(twin_window_t *window)
|
|
|
|
+{
|
|
|
|
+ struct pbt_pane *op = pbt_menu_from_twindow(window)->op;
|
|
|
|
+ twin_pixmap_t *px = window->pixmap;
|
|
|
|
+// pboot_device_t *dev;
|
|
|
|
+ twin_path_t *path;
|
|
|
|
+ twin_fixed_t x, y, w, h;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ /* Fill background */
|
|
|
|
+ twin_fill(px, 0x00000000, TWIN_SOURCE, 0, 0, px->width, px->height);
|
|
|
|
+
|
|
|
|
+ /* Nothing to draw, return */
|
|
|
|
+// if (pboot_dev_sel < 0)
|
|
|
|
+// return;
|
|
|
|
+
|
|
|
|
+ /* Create a path for use later */
|
|
|
|
+ path = twin_path_create();
|
|
|
|
+ assert(path);
|
|
|
|
+
|
|
|
|
+ /* Draw focus box */
|
|
|
|
+ if (op->focus_curindex >= 0 &&
|
|
|
|
+ pbt_rect_intersect(op->focus_box, px->clip)) {
|
|
|
|
+ x = twin_int_to_fixed(op->focus_box.left + 2);
|
|
|
|
+ y = twin_int_to_fixed(op->focus_box.top + 2);
|
|
|
|
+ w = twin_int_to_fixed(op->focus_box.right -
|
|
|
|
+ op->focus_box.left - 4);
|
|
|
|
+ h = twin_int_to_fixed(op->focus_box.bottom -
|
|
|
|
+ op->focus_box.top - 4);
|
|
|
|
+ twin_path_rounded_rectangle(path, x, y, w, h,
|
|
|
|
+ PBOOT_RIGHT_FOCUS_XRAD,
|
|
|
|
+ PBOOT_RIGHT_FOCUS_YRAD);
|
|
|
|
+ if (pbt_pane_has_focus(op))
|
|
|
|
+ twin_paint_path(px, PBOOT_FOCUS_COLOR, path);
|
|
|
|
+ else
|
|
|
|
+ twin_paint_stroke(px, PBOOT_FOCUS_COLOR, path,
|
|
|
|
+ 4 * TWIN_FIXED_ONE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Get device and iterate through options */
|
|
|
|
+/*
|
|
|
|
+ dev = pboot_devices[pboot_dev_sel];
|
|
|
|
+ for (i = 0; i < dev->option_count; i++) {
|
|
|
|
+ pboot_option_t *opt = &dev->options[i];
|
|
|
|
+ twin_operand_t src;
|
|
|
|
+
|
|
|
|
+ if (opt->title == NULL)
|
|
|
|
+ continue;
|
|
|
|
+ if (!pbt_rect_intersect(opt->box, px->clip))
|
|
|
|
+ continue;
|
|
|
|
+ if (opt->cache == NULL)
|
|
|
|
+ pboot_draw_option_cache(dev, opt, i);
|
|
|
|
+
|
|
|
|
+ src.source_kind = TWIN_PIXMAP;
|
|
|
|
+ src.u.pixmap = opt->cache;
|
|
|
|
+
|
|
|
|
+ twin_composite(px, opt->box.left, opt->box.top,
|
|
|
|
+ &src, 0, 0, NULL, 0, 0, TWIN_OVER,
|
|
|
|
+ opt->box.right - opt->box.left,
|
|
|
|
+ opt->box.bottom - opt->box.top);
|
|
|
|
+ }
|
|
|
|
+*/
|
|
|
|
+ /* Destroy path */
|
|
|
|
+ twin_path_destroy(path);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pbt_option_pane_mousetrack(struct pbt_menu *menu, twin_coord_t x,
|
|
|
|
+ twin_coord_t y)
|
|
|
|
+{
|
|
|
|
+ int candidate = -1;
|
|
|
|
+
|
|
|
|
+ if (y < PBOOT_RIGHT_OPTION_TMARGIN)
|
|
|
|
+ goto miss;
|
|
|
|
+
|
|
|
|
+#if 0
|
|
|
|
+ pboot_device_t *dev;
|
|
|
|
+ pboot_option_t *opt;
|
|
|
|
+
|
|
|
|
+ if (pboot_dev_sel < 0 || pboot_dev_sel >= pboot_dev_count)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ dev = pboot_devices[pboot_dev_sel];
|
|
|
|
+
|
|
|
|
+ candidate = (y - PBOOT_RIGHT_OPTION_TMARGIN) /
|
|
|
|
+ PBOOT_RIGHT_OPTION_STRIDE;
|
|
|
|
+
|
|
|
|
+ if (candidate >= dev->option_count) {
|
|
|
|
+ candidate = -1;
|
|
|
|
+ goto miss;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (candidate == op->mouse_target)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ opt = &dev->options[candidate];
|
|
|
|
+
|
|
|
|
+ if (x < opt->box.left || x > opt->box.right ||
|
|
|
|
+ y < opt->box.top || y > opt->box.bottom) {
|
|
|
|
+ candidate = -1;
|
|
|
|
+ goto miss;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ pbt_option_pane_set_focus(menu, candidate);
|
|
|
|
+
|
|
|
|
+miss:
|
|
|
|
+ menu->op->mouse_target = candidate;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static twin_bool_t pbt_option_pane_event(twin_window_t *window,
|
|
|
|
+ twin_event_t *event)
|
|
|
|
+{
|
|
|
|
+ struct pbt_menu *menu = pbt_menu_from_twindow(window);
|
|
|
|
+
|
|
|
|
+ /* filter out all mouse events */
|
|
|
|
+ switch(event->kind) {
|
|
|
|
+ case TwinEventEnter:
|
|
|
|
+ case TwinEventMotion:
|
|
|
|
+ case TwinEventLeave:
|
|
|
|
+ pbt_menu_pane_select(menu, menu->op);
|
|
|
|
+ pbt_option_pane_mousetrack(menu, event->u.pointer.x,
|
|
|
|
+ event->u.pointer.y);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case TwinEventButtonDown:
|
|
|
|
+ pbt_menu_pane_select(menu, menu->op);
|
|
|
|
+ pbt_option_pane_mousetrack(menu, event->u.pointer.x,
|
|
|
|
+ event->u.pointer.y);
|
|
|
|
+ pbt_option_execute(menu);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case TwinEventButtonUp:
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case TwinEventKeyDown:
|
|
|
|
+ switch(event->u.key.key) {
|
|
|
|
+ case KEY_UP:
|
|
|
|
+ //pbt_menu_set_option_focus(menu, menu->op->focus_curindex - 1);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case KEY_DOWN:
|
|
|
|
+ //pbt_menu_set_option_focus(menu, menu->op->focus_curindex + 1);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case KEY_LEFT:
|
|
|
|
+ pbt_menu_pane_select(menu, menu->dp);
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+ case KEY_ENTER:
|
|
|
|
+ pbt_option_execute(menu);
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return TWIN_FALSE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct pbt_pane *pbt_option_pane_create(struct pbt_menu *menu)
|
|
|
|
+{
|
|
|
|
+ struct pbt_pane *pane = talloc_zero(menu, struct pbt_pane);
|
|
|
|
+
|
|
|
|
+ if (!pane)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ pane->sig = pbt_pane_sig;
|
|
|
|
+ pane->window = twin_window_create(menu->scr->tscreen, TWIN_ARGB32,
|
|
|
|
+ TwinWindowPlain, PBOOT_LEFT_PANE_SIZE, 0,
|
|
|
|
+ menu->scr->tscreen->width - PBOOT_LEFT_PANE_SIZE,
|
|
|
|
+ menu->scr->tscreen->height);
|
|
|
|
+
|
|
|
|
+ if (!pane->window)
|
|
|
|
+ goto fail_window;
|
|
|
|
+
|
|
|
|
+ pane->window->draw = pbt_option_pane_draw;
|
|
|
|
+ pane->window->event = pbt_option_pane_event;
|
|
|
|
+ pane->window->client_data = menu;
|
|
|
|
+
|
|
|
|
+ pane->focus_curindex = -1;
|
|
|
|
+ pane->focus_box.left = PBOOT_RIGHT_FOCUS_XOFF;
|
|
|
|
+ pane->focus_box.top = -2 * PBOOT_RIGHT_FOCUS_HEIGHT;
|
|
|
|
+ pane->focus_box.right = pane->window->pixmap->width
|
|
|
|
+ - 2 * PBOOT_RIGHT_FOCUS_XOFF;
|
|
|
|
+ pane->focus_box.bottom = pane->focus_box.top + PBOOT_RIGHT_FOCUS_HEIGHT;
|
|
|
|
+
|
|
|
|
+ pane->mouse_target = -1;
|
|
|
|
+
|
|
|
|
+ twin_window_show(pane->window);
|
|
|
|
+ twin_window_queue_paint(pane->window);
|
|
|
|
+
|
|
|
|
+ return pane;
|
|
|
|
+
|
|
|
|
+fail_window:
|
|
|
|
+ talloc_free(pane);
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//==============================================================================
|
|
|
|
+// junk
|
|
|
|
+//==============================================================================
|
|
|
|
+
|
|
|
|
+#if 0
|
|
|
|
+
|
|
|
|
+static pboot_device_t *pboot_devices[PBOOT_MAX_DEV];
|
|
|
|
+static int pboot_dev_count;
|
|
|
|
+static int pboot_dev_sel = -1;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int pboot_vmode_change = -1;
|
|
|
|
+
|
|
|
|
+static void pboot_message(const char *fmt, ...)
|
|
|
|
+{
|
|
|
|
+ va_list ap;
|
|
|
|
+ char *msg;
|
|
|
|
+
|
|
|
|
+ va_start(ap, fmt);
|
|
|
|
+ vasprintf(&msg, fmt, ap);
|
|
|
|
+ va_end(ap);
|
|
|
|
+
|
|
|
|
+ pb_log(msg);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pboot_draw_option_cache(pboot_device_t *dev, pboot_option_t *opt,
|
|
|
|
+ int index)
|
|
|
|
+{
|
|
|
|
+ twin_pixmap_t *px;
|
|
|
|
+ twin_path_t *path;
|
|
|
|
+ twin_fixed_t tx, ty;
|
|
|
|
+
|
|
|
|
+ /* Create pixmap */
|
|
|
|
+ px = twin_pixmap_create(TWIN_ARGB32, opt->box.right - opt->box.left,
|
|
|
|
+ opt->box.bottom - opt->box.top);
|
|
|
|
+ assert(px);
|
|
|
|
+ opt->cache = px;
|
|
|
|
+
|
|
|
|
+ /* Fill background */
|
|
|
|
+ twin_fill(px, 0x00000000, TWIN_SOURCE, 0, 0, px->width, px->height);
|
|
|
|
+
|
|
|
|
+ /* Allocate a path for drawing */
|
|
|
|
+ path = twin_path_create();
|
|
|
|
+ assert(path);
|
|
|
|
+
|
|
|
|
+#if 0
|
|
|
|
+ /* TEST - Bounding rectangle */
|
|
|
|
+ twin_path_rectangle(path, 0, 0,
|
|
|
|
+ twin_int_to_fixed(px->width),
|
|
|
|
+ twin_int_to_fixed(px->height));
|
|
|
|
+ twin_paint_path(px, PBOOT_RIGHT_TITLE_COLOR, path);
|
|
|
|
+ twin_path_empty(path);
|
|
|
|
+ twin_fill(px, 0x00000000, TWIN_SOURCE, 2, 2,
|
|
|
|
+ px->width - 3, px->height - 3);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ /* Draw texts */
|
|
|
|
+ twin_path_set_font_size(path, PBOOT_RIGHT_TITLE_TEXT_SIZE);
|
|
|
|
+ twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
|
|
|
|
+ tx = twin_int_to_fixed(PBOOT_RIGHT_TITLE_XOFFSET);
|
|
|
|
+ ty = twin_int_to_fixed(PBOOT_RIGHT_TITLE_YOFFSET);
|
|
|
|
+ twin_path_move (path, tx, ty);
|
|
|
|
+ twin_path_utf8 (path, opt->title);
|
|
|
|
+ twin_paint_path (px, PBOOT_RIGHT_TITLE_COLOR, path);
|
|
|
|
+ twin_path_empty (path);
|
|
|
|
+
|
|
|
|
+ if (opt->subtitle) {
|
|
|
|
+ twin_path_set_font_size(path, PBOOT_RIGHT_SUBTITLE_TEXT_SIZE);
|
|
|
|
+ twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
|
|
|
|
+ tx = twin_int_to_fixed(PBOOT_RIGHT_SUBTITLE_XOFFSET);
|
|
|
|
+ ty = twin_int_to_fixed(PBOOT_RIGHT_SUBTITLE_YOFFSET);
|
|
|
|
+ twin_path_move (path, tx, ty);
|
|
|
|
+ twin_path_utf8 (path, opt->subtitle);
|
|
|
|
+ twin_paint_path (px, PBOOT_RIGHT_SUBTITLE_COLOR, path);
|
|
|
|
+ twin_path_empty (path);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (opt->badge) {
|
|
|
|
+ twin_operand_t src;
|
|
|
|
+
|
|
|
|
+ src.source_kind = TWIN_PIXMAP;
|
|
|
|
+ src.u.pixmap = opt->badge;
|
|
|
|
+
|
|
|
|
+ twin_composite(px, PBOOT_RIGHT_BADGE_XOFFSET,
|
|
|
|
+ PBOOT_RIGHT_BADGE_YOFFSET,
|
|
|
|
+ &src, 0, 0, NULL, 0, 0, TWIN_OVER,
|
|
|
|
+ opt->badge->width, opt->badge->height);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* Destroy path */
|
|
|
|
+ twin_path_destroy(path);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int pboot_add_option(int devindex, const char *title,
|
|
|
|
+ const char *subtitle, twin_pixmap_t *badge, void *data)
|
|
|
|
+{
|
|
|
|
+ pboot_device_t *dev;
|
|
|
|
+ pboot_option_t *opt;
|
|
|
|
+ twin_coord_t width;
|
|
|
|
+ int index;
|
|
|
|
+ struct pbt_menu *menu = NULL;
|
|
|
|
+
|
|
|
|
+ if (devindex < 0 || devindex >= pboot_dev_count)
|
|
|
|
+ return -1;
|
|
|
|
+ dev = pboot_devices[devindex];
|
|
|
|
+
|
|
|
|
+ if (dev->option_count >= PBOOT_MAX_OPTION)
|
|
|
|
+ return -1;
|
|
|
|
+ index = dev->option_count++;
|
|
|
|
+ opt = &dev->options[index];
|
|
|
|
+
|
|
|
|
+ opt->title = malloc(strlen(title) + 1);
|
|
|
|
+ strcpy(opt->title, title);
|
|
|
|
+
|
|
|
|
+ if (subtitle) {
|
|
|
|
+ opt->subtitle = malloc(strlen(subtitle) + 1);
|
|
|
|
+ strcpy(opt->subtitle, subtitle);
|
|
|
|
+ } else
|
|
|
|
+ opt->subtitle = NULL;
|
|
|
|
+
|
|
|
|
+ opt->badge = badge;
|
|
|
|
+ opt->cache = NULL;
|
|
|
|
+
|
|
|
|
+ width = menu->op->window->pixmap->width -
|
|
|
|
+ (PBOOT_RIGHT_OPTION_LMARGIN + PBOOT_RIGHT_OPTION_RMARGIN);
|
|
|
|
+
|
|
|
|
+ opt->box.left = PBOOT_RIGHT_OPTION_LMARGIN;
|
|
|
|
+ opt->box.right = opt->box.left + width;
|
|
|
|
+ opt->box.top = PBOOT_RIGHT_OPTION_TMARGIN +
|
|
|
|
+ index * PBOOT_RIGHT_OPTION_STRIDE;
|
|
|
|
+ opt->box.bottom = opt->box.top + PBOOT_RIGHT_OPTION_HEIGHT;
|
|
|
|
+
|
|
|
|
+ opt->data = data;
|
|
|
|
+ return index;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pboot_set_device_select(struct pbt_menu *menu, int sel, int force)
|
|
|
|
+{
|
|
|
|
+ pb_log("%s: %d -> %d\n", __FUNCTION__, pboot_dev_sel, sel);
|
|
|
|
+ if (!force && sel == pboot_dev_sel)
|
|
|
|
+ return;
|
|
|
|
+ if (sel >= pboot_dev_count)
|
|
|
|
+ return;
|
|
|
|
+ pboot_dev_sel = sel;
|
|
|
|
+ if (force) {
|
|
|
|
+ menu->dp->focus_curindex = sel;
|
|
|
|
+ if (sel < 0)
|
|
|
|
+ menu->dp->focus_target = 0 - PBOOT_LEFT_FOCUS_HEIGHT;
|
|
|
|
+ else
|
|
|
|
+ menu->dp->focus_target = PBOOT_LEFT_FOCUS_YOFF +
|
|
|
|
+ PBOOT_LEFT_ICON_STRIDE * sel;
|
|
|
|
+ menu->op->focus_box.bottom = menu->dp->focus_target;
|
|
|
|
+ menu->op->focus_box.bottom = menu->op->focus_box.top +
|
|
|
|
+ PBOOT_RIGHT_FOCUS_HEIGHT;
|
|
|
|
+ twin_window_damage(menu->dp->window,
|
|
|
|
+ 0, 0,
|
|
|
|
+ menu->dp->window->pixmap->width,
|
|
|
|
+ menu->dp->window->pixmap->height);
|
|
|
|
+ twin_window_queue_paint(menu->dp->window);
|
|
|
|
+ }
|
|
|
|
+ menu->op->focus_curindex = -1;
|
|
|
|
+ menu->op->mouse_target = -1;
|
|
|
|
+ menu->op->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
|
|
|
|
+ menu->op->focus_box.bottom = menu->op->focus_box.top +
|
|
|
|
+ PBOOT_RIGHT_FOCUS_HEIGHT;
|
|
|
|
+ twin_window_damage(menu->op->window, 0, 0,
|
|
|
|
+ menu->op->window->pixmap->width,
|
|
|
|
+ menu->op->window->pixmap->height);
|
|
|
|
+ twin_window_queue_paint(menu->op->window);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void pboot_quit(void)
|
|
|
|
+{
|
|
|
|
+ kill(0, SIGINT);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int pboot_add_device(const char *dev_id, twin_pixmap_t *pixmap)
|
|
|
|
+{
|
|
|
|
+ int index;
|
|
|
|
+ pboot_device_t *dev;
|
|
|
|
+
|
|
|
|
+ struct pbt_menu *menu = NULL;
|
|
|
|
+
|
|
|
|
+ if (pboot_dev_count >= PBOOT_MAX_DEV)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ index = pboot_dev_count++;
|
|
|
|
+
|
|
|
|
+ dev = malloc(sizeof(*dev));
|
|
|
|
+ memset(dev, 0, sizeof(*dev));
|
|
|
|
+ dev->id = malloc(strlen(dev_id) + 1);
|
|
|
|
+ strcpy(dev->id, dev_id);
|
|
|
|
+ dev->badge = pixmap;
|
|
|
|
+ dev->box.left = PBOOT_LEFT_ICON_XOFF;
|
|
|
|
+ dev->box.right = dev->box.left + PBOOT_LEFT_ICON_WIDTH;
|
|
|
|
+ dev->box.top = PBOOT_LEFT_ICON_YOFF +
|
|
|
|
+ PBOOT_LEFT_ICON_STRIDE * index;
|
|
|
|
+ dev->box.bottom = dev->box.top + PBOOT_LEFT_ICON_HEIGHT;
|
|
|
|
+
|
|
|
|
+ pboot_devices[index] = dev;
|
|
|
|
+
|
|
|
|
+ twin_window_damage(menu->dp->window,
|
|
|
|
+ dev->box.left, dev->box.top,
|
|
|
|
+ dev->box.right, dev->box.bottom);
|
|
|
|
+ twin_window_queue_paint(menu->dp->window);
|
|
|
|
+
|
|
|
|
+ return index;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int pboot_remove_device(const char *dev_id)
|
|
|
|
+{
|
|
|
|
+ pboot_device_t *dev = NULL;
|
|
|
|
+ int i, newsel = pboot_dev_sel;
|
|
|
|
+
|
|
|
|
+ struct pbt_menu *menu = NULL;
|
|
|
|
+
|
|
|
|
+ /* find the matching device */
|
|
|
|
+ for (i = 0; i < pboot_dev_count; i++) {
|
|
|
|
+ if (!strcmp(pboot_devices[i]->id, dev_id)) {
|
|
|
|
+ dev = pboot_devices[i];
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!dev)
|
|
|
|
+ return TWIN_FALSE;
|
|
|
|
+
|
|
|
|
+ memmove(pboot_devices + i, pboot_devices + i + 1,
|
|
|
|
+ sizeof(*pboot_devices) * (pboot_dev_count + i - 1));
|
|
|
|
+ pboot_devices[--pboot_dev_count] = NULL;
|
|
|
|
+
|
|
|
|
+ /* select the newly-focussed device */
|
|
|
|
+ if (pboot_dev_sel > i)
|
|
|
|
+ newsel = pboot_dev_sel - 1;
|
|
|
|
+ else if (pboot_dev_sel == i && i >= pboot_dev_count)
|
|
|
|
+ newsel = pboot_dev_count - 1;
|
|
|
|
+ pboot_set_device_select(menu, newsel, 1);
|
|
|
|
+
|
|
|
|
+ /* todo: free device & options */
|
|
|
|
+
|
|
|
|
+ return TWIN_TRUE;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+//------------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+static void print_version(void)
|
|
|
|
+{
|
|
|
|
+ printf("pb-twin (" PACKAGE_NAME ") " PACKAGE_VERSION "\n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void print_usage(void)
|
|
|
|
+{
|
|
|
|
+ print_version();
|
|
|
|
+ printf(
|
|
|
|
+"Usage: pb-twin [-h, --help] [-l, --log log-file] [-r, --reset-defaults]\n"
|
|
|
|
+" [-t, --timeout] [-V, --version]\n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * enum opt_value - Tri-state options variables.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+enum opt_value {opt_undef = 0, opt_yes, opt_no};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct opts - Values from command line options.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+struct opts {
|
|
|
|
+ enum opt_value show_help;
|
|
|
|
+ const char *log_file;
|
|
|
|
+ enum opt_value reset_defaults;
|
|
|
|
+ enum opt_value use_timeout;
|
|
|
|
+ enum opt_value show_version;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * opts_parse - Parse the command line options.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static int opts_parse(struct opts *opts, int argc, char *argv[])
|
|
|
|
+{
|
|
|
|
+ static const struct option long_options[] = {
|
|
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
|
|
+ {"log", required_argument, NULL, 'l'},
|
|
|
|
+ {"reset-defaults", no_argument, NULL, 'r'},
|
|
|
|
+ {"timeout", no_argument, NULL, 't'},
|
|
|
|
+ {"version", no_argument, NULL, 'V'},
|
|
|
|
+ { NULL, 0, NULL, 0},
|
|
|
|
+ };
|
|
|
|
+ static const char short_options[] = "hl:trV";
|
|
|
|
+ static const struct opts default_values = {
|
|
|
|
+ .log_file = "pb-twin.log",
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ *opts = default_values;
|
|
|
|
+
|
|
|
|
+ while (1) {
|
|
|
|
+ int c = getopt_long(argc, argv, short_options, long_options,
|
|
|
|
+ NULL);
|
|
|
|
+
|
|
|
|
+ if (c == EOF)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ switch (c) {
|
|
|
|
+ case 'h':
|
|
|
|
+ opts->show_help = opt_yes;
|
|
|
|
+ break;
|
|
|
|
+ case 'l':
|
|
|
|
+ opts->log_file = optarg;
|
|
|
|
+ break;
|
|
|
|
+ case 't':
|
|
|
|
+ opts->use_timeout = opt_yes;
|
|
|
|
+ break;
|
|
|
|
+ case 'r':
|
|
|
|
+ opts->reset_defaults = opt_yes;
|
|
|
|
+ break;
|
|
|
|
+ case 'V':
|
|
|
|
+ opts->show_version = opt_yes;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ opts->show_help = opt_yes;
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return optind != argc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * struct ps3_gui - Main gui program instance.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct ps3_gui {
|
|
|
|
+ struct ui_timer timer;
|
|
|
|
+ struct ps3_flash_values values;
|
|
|
|
+ int dirty_values;
|
|
|
|
+
|
|
|
|
+ struct pbt_scr scr;
|
|
|
|
+ struct pbt_frame frame;
|
|
|
|
+ struct pbt_menu *menu;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct ps3_gui ps3;
|
|
|
|
+
|
|
|
|
+static struct pbt_scr *pbt_scr_from_tscreen(twin_screen_t *tscreen)
|
|
|
|
+{
|
|
|
|
+ assert(ps3.scr.sig == pbt_scr_sig);
|
|
|
|
+ assert(ps3.scr.tscreen == tscreen);
|
|
|
|
+ return &ps3.scr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void sig_handler(int signum)
|
|
|
|
+{
|
|
|
|
+ DBGS("%d\n", signum);
|
|
|
|
+
|
|
|
|
+ switch (signum) {
|
|
|
|
+ case SIGALRM:
|
|
|
|
+ ui_timer_sigalrm(&ps3.timer);
|
|
|
|
+ break;
|
|
|
|
+ case SIGWINCH:
|
|
|
|
+// if (ps3.gui)
|
|
|
|
+// gui_resize(ps3.gui);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ assert(0 && "unknown sig");
|
|
|
|
+ /* fall through */
|
|
|
|
+ case SIGINT:
|
|
|
|
+ case SIGHUP:
|
|
|
|
+ case SIGTERM:
|
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
|
+// if (ps3.gui)
|
|
|
|
+// gui_abort(ps3.gui);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
2009-07-10 01:18:57 +00:00
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * main - twin bootloader main routine.
|
|
|
|
+ */
|
|
|
|
+
|
2009-08-24 20:24:28 +00:00
|
|
|
+int main(int argc, char *argv[])
|
2009-07-10 01:18:57 +00:00
|
|
|
+{
|
2009-08-24 20:24:28 +00:00
|
|
|
+ static struct sigaction sa;
|
|
|
|
+ static struct opts opts;
|
|
|
|
+ int result;
|
|
|
|
+ int ui_result;
|
|
|
|
+ unsigned int mode;
|
2009-07-10 01:18:57 +00:00
|
|
|
+ FILE *log;
|
|
|
|
+
|
2009-08-24 20:24:28 +00:00
|
|
|
+ result = opts_parse(&opts, argc, argv);
|
|
|
|
+
|
|
|
|
+ if (result) {
|
|
|
|
+ print_usage();
|
|
|
|
+ return EXIT_FAILURE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (opts.show_help == opt_yes) {
|
|
|
|
+ print_usage();
|
|
|
|
+ return EXIT_SUCCESS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (opts.show_version == opt_yes) {
|
|
|
|
+ print_version();
|
|
|
|
+ return EXIT_SUCCESS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ log = fopen(opts.log_file, "a");
|
2009-07-10 01:18:57 +00:00
|
|
|
+ assert(log);
|
|
|
|
+ pb_log_set_stream(log);
|
|
|
|
+
|
|
|
|
+#if defined(DEBUG)
|
|
|
|
+ pb_log_always_flush(1);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ pb_log("--- pb-twin ---\n");
|
|
|
|
+
|
2009-08-24 20:24:28 +00:00
|
|
|
+ sa.sa_handler = sig_handler;
|
|
|
|
+ result = sigaction(SIGALRM, &sa, NULL);
|
|
|
|
+ result += sigaction(SIGHUP, &sa, NULL);
|
|
|
|
+ result += sigaction(SIGINT, &sa, NULL);
|
|
|
|
+ result += sigaction(SIGTERM, &sa, NULL);
|
|
|
|
+ result += sigaction(SIGWINCH, &sa, NULL);
|
|
|
|
+
|
|
|
|
+ if (result) {
|
|
|
|
+ pb_log("%s sigaction failed.\n", __func__);
|
|
|
|
+ return EXIT_FAILURE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ps3.values = ps3_flash_defaults;
|
|
|
|
+
|
|
|
|
+ if (opts.reset_defaults != opt_yes)
|
|
|
|
+ ps3.dirty_values = ps3_flash_get_values(&ps3.values);
|
|
|
|
+
|
|
|
|
+ twin_feature_init(); // need it???
|
|
|
|
+
|
|
|
|
+ /* Setup screen. */
|
|
|
|
+
|
|
|
|
+ ps3.scr.sig = pbt_scr_sig;
|
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+#if defined(HAVE_LIBTWIN_TWIN_X11_H)
|
|
|
|
+# if defined(USE_X11)
|
|
|
|
+ if (1) {
|
|
|
|
+# else
|
|
|
|
+ if (0) {
|
|
|
|
+# endif
|
|
|
|
+ ps3.scr.x11 = twin_x11_create(XOpenDisplay(0), 1024, 768);
|
|
|
|
+
|
|
|
|
+ if (!ps3.scr.x11) {
|
|
|
|
+ perror("failed to create x11 screen !\n");
|
|
|
|
+ return EXIT_FAILURE;
|
|
|
|
+ }
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ ps3.scr.tscreen = ps3.scr.x11->screen;
|
|
|
|
+ } else {
|
2009-08-24 20:24:28 +00:00
|
|
|
+#else
|
2009-08-26 22:02:51 +00:00
|
|
|
+ if (1) {
|
|
|
|
+#endif
|
|
|
|
+ result = ps3_get_video_mode(&mode);
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ /* Current becomes default if ps3_flash_get_values() failed. */
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ if (ps3.dirty_values && !result)
|
|
|
|
+ ps3.values.video_mode = mode;
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ /* Set mode if not at default. */
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ if (!result && (ps3.values.video_mode != (uint16_t)mode))
|
|
|
|
+ ps3_set_video_mode(ps3.values.video_mode);
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ ps3.scr.fbdev = twin_fbdev_create(-1, SIGUSR1);
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ if (!ps3.scr.fbdev) {
|
|
|
|
+ perror("failed to create fbdev screen !\n");
|
|
|
|
+ return EXIT_FAILURE;
|
|
|
|
+ }
|
2009-07-10 01:18:57 +00:00
|
|
|
+
|
2009-08-26 22:02:51 +00:00
|
|
|
+ ps3.scr.tscreen = ps3.scr.fbdev->screen;
|
|
|
|
+ }
|
2009-08-24 20:24:28 +00:00
|
|
|
+
|
|
|
|
+ ps3.scr.tscreen->event_filter = pbt_scr_event;
|
|
|
|
+
|
|
|
|
+ twin_screen_set_background(ps3.scr.tscreen,
|
|
|
|
+ pbt_load_background(ps3.scr.tscreen));
|
|
|
|
+
|
|
|
|
+ /* setup menu */
|
|
|
|
+
|
|
|
|
+ ps3.menu = pbt_menu_create(NULL, &ps3.scr);
|
|
|
|
+
|
|
|
|
+ pbt_device_pane_set_focus(ps3.menu, 0);
|
|
|
|
+ twin_screen_set_active(ps3.scr.tscreen, ps3.menu->dp->window->pixmap);
|
|
|
|
+
|
|
|
|
+ /* Console switch */
|
|
|
|
+
|
|
|
|
+ if (ps3.scr.fbdev)
|
|
|
|
+ twin_fbdev_activate(ps3.scr.fbdev);
|
|
|
|
+
|
|
|
|
+ /* run twin */
|
|
|
|
+
|
|
|
|
+// twin_toplevel_show(ps3.toplevel);
|
|
|
|
+ twin_dispatch();
|
|
|
|
+
|
2009-07-10 01:18:57 +00:00
|
|
|
+ pb_log("--- end ---\n");
|
|
|
|
+
|
2009-08-24 20:24:28 +00:00
|
|
|
+ return ui_result ? EXIT_FAILURE : EXIT_SUCCESS;
|
2009-07-10 01:18:57 +00:00
|
|
|
+}
|