File:  [RetroPC.NET] / np2 / x11 / gtk / Attic / gtkmain.c
Revision 1.1: download - view: text, annotated - select for diffs
Mon Nov 17 01:43:45 2003 JST (21 years, 11 months ago) by monaka
Branches: MAIN
CVS tags: HEAD
Neko Project II for X11 (only support GTK+ GUI Toolkit)

/*
 * Copyright (c) 2003 NONAKA Kimihiro
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "compiler.h"

#include "np2.h"
#include "pccore.h"
#include "scrndraw.h"
#include "timing.h"
#include "toolkit.h"

#include "joymng.h"
#include "mousemng.h"
#include "scrnmng.h"
#include "soundmng.h"

#include "gtk/xnp2.h"
#include "gtk/gtkkeyboard.h"
#include "gtk/gtkmenu.h"

#include <gdk/gdkkeysyms.h>

#include "resources/np2.xbm"


#define	APPNAME		"NP2"

#define	EVENT_MASK \
			(GDK_BUTTON1_MOTION_MASK	\
			 | GDK_BUTTON2_MOTION_MASK	\
			 | GDK_BUTTON3_MOTION_MASK	\
			 | GDK_POINTER_MOTION_MASK	\
			 | GDK_KEY_PRESS_MASK		\
			 | GDK_KEY_RELEASE_MASK		\
			 | GDK_BUTTON_PRESS_MASK	\
			 | GDK_BUTTON_RELEASE_MASK	\
			 | GDK_ENTER_NOTIFY_MASK	\
			 | GDK_LEAVE_NOTIFY_MASK	\
			 | GDK_EXPOSURE_MASK)



/*
 - Signal: gint GtkWidget::expose_event (GtkWidget *WIDGET,
          GdkEventExpose *EVENT)
*/
static gint
expose(GtkWidget *w, GdkEventExpose *ev)
{

	UNUSED(w);

	if (ev->type == GDK_EXPOSE) {
		if (ev->count == 0) {
			scrndraw_redraw();
		}
		return TRUE;
	}
	return FALSE;
}

/*
 - Signal: gint GtkWidget::key_press_event (GtkWidget *WIDGET,
          GdkEventKey *EVENT)
*/
static gint
key_press(GtkWidget *w, GdkEventKey *ev)
{

	UNUSED(w);

	if (ev->type == GDK_KEY_PRESS) {
		if ((ev->keyval == GDK_F12) && (np2oscfg.F12COPY == 0))
			xmenu_toggle_item(MOUSE_MODE, !np2oscfg.MOUSE_SW, TRUE);
		else
			gtkkbd_keydown(ev->keyval);
		return TRUE;
	}
	return FALSE;
}

/*
 - Signal: gint GtkWidget::key_release_event (GtkWidget *WIDGET,
          GdkEventKey *EVENT)
*/
static gint
key_release(GtkWidget *w, GdkEventKey *ev)
{

	UNUSED(w);

	if (ev->type == GDK_KEY_RELEASE) {
		if ((ev->keyval != GDK_F12) || (np2oscfg.F12COPY != 0))
			gtkkbd_keyup(ev->keyval);
		return TRUE;
	}
	return FALSE;
}

/*
 - Signal: gint GtkWidget::button_press_event (GtkWidget *WIDGET,
          GdkEventButton *EVENT)
*/
static gint
button_press(GtkWidget *w, GdkEventButton *ev)
{

	UNUSED(w);

	if (ev->type == GDK_BUTTON_PRESS) {
		switch (ev->button) {
		case 1:
			mouse_btn(MOUSE_LEFTDOWN);
			break;

		case 2:
			xmenu_toggle_item(MOUSE_MODE, !np2oscfg.MOUSE_SW, TRUE);
			break;

		case 3:
			mouse_btn(MOUSE_RIGHTDOWN);
			break;
		}
		return TRUE;
	}
	return FALSE;
}

/*
 - Signal: gint GtkWidget::button_release_event (GtkWidget *WIDGET,
          GdkEventButton *EVENT)
*/
static gint
button_release(GtkWidget *w, GdkEventButton *ev)
{

	UNUSED(w);

	if (ev->type == GDK_BUTTON_RELEASE) {
		switch (ev->button) {
		case 1:
			mouse_btn(MOUSE_LEFTUP);
			break;

		case 2:
			break;

		case 3:
			mouse_btn(MOUSE_RIGHTUP);
			break;
		}
		return TRUE;
	}
	return FALSE;
}

/*
 - Signal: gint GtkWidget::enter_notify_event (GtkWidget *WIDGET,
          GdkEventCrossing *EVENT)
*/
static gint
enter_notify(GtkWidget *w, GdkEventCrossing *ev)
{

	UNUSED(w);

	if (ev->type == GDK_ENTER_NOTIFY) {
		scrndraw_redraw();
		return TRUE;
	}
	return FALSE;
}


/*
 * misc
 */
static void
set_icon_bitmap(GtkWidget *w)
{
	GdkPixmap *icon_pixmap;

	gdk_window_set_icon_name(w->window, APPNAME);
	icon_pixmap = gdk_bitmap_create_from_data(
	    w->window, np2_bits, np2_width, np2_height);
	gdk_window_set_icon(w->window, NULL, icon_pixmap, NULL);
}

#if 0
static GtkWidget*
create_pixmap(GtkWidget *widget, gchar **data)
{
	GtkWidget *pixmap;
	GdkColormap *colormap;
	GdkPixmap *gdkpixmap;
	GdkBitmap *mask;

	colormap = gtk_widget_get_colormap(widget);
	gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d(
	    NULL, colormap, &mask, NULL, data);
	if (gdkpixmap == NULL) {
		g_warning("Couldn't create pixmap.");
		return NULL;
	}

	pixmap = gtk_pixmap_new(gdkpixmap, mask);
	gdk_pixmap_unref(gdkpixmap);
	gdk_bitmap_unref(mask);

	return pixmap;
}
#endif


/*
 * idle process
 */
static gint idle_process(gpointer *p);

static int install_count = 0;
static int idle_id;

void
install_idle_process(void)
{

	if (install_count++ == 0) {
		idle_id = gtk_idle_add((GtkFunction)idle_process, drawarea);
		soundmng_play();
	}
}

void
uninstall_idle_process(void)
{

	if (--install_count == 0) {
		soundmng_stop();
		gtk_idle_remove(idle_id);
	}
}


/*
 * toolkit
 */
const char *
gui_gtk_get_toolkit(void)
{

	return "gtk";
}

BOOL
gui_gtk_arginit(int *argcp, char ***argvp)
{

	gtk_set_locale();
	gtk_rc_add_default_file(".np2rc");
	gtk_init(argcp, argvp);

	return SUCCESS;
}

void
gui_gtk_widget_create(void)
{
	GtkWidget *main_vbox;
	GtkWidget *menubar;

	/* ウィンドウ作成 */
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE);
	gtk_window_set_title(GTK_WINDOW(window), np2oscfg.titles);

	main_vbox = gtk_vbox_new(FALSE, 2);
	gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
	gtk_container_add(GTK_CONTAINER(window), main_vbox);
	gtk_widget_show(main_vbox);

	/* メニューバー	*/
	menubar = create_menu(window);
	gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
	gtk_widget_show(menubar);

	/* 画面領域 */
	drawarea = gtk_drawing_area_new();
	gtk_drawing_area_size(GTK_DRAWING_AREA(drawarea), 640, 400);
	gtk_box_pack_start(GTK_BOX(main_vbox), drawarea, FALSE, TRUE, 0);
	gtk_widget_show(drawarea);

	gtk_widget_realize(window);
	set_icon_bitmap(window);

	/* setup signal */
	gtk_signal_connect(GTK_OBJECT(window), "destroy", 
	    GTK_SIGNAL_FUNC(gtk_main_quit), "WM destroy");
	gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
	    GTK_SIGNAL_FUNC(key_press), NULL);
	gtk_signal_connect(GTK_OBJECT(window), "key_release_event",
	    GTK_SIGNAL_FUNC(key_release), NULL);
	gtk_signal_connect(GTK_OBJECT(window), "button_press_event",
	    GTK_SIGNAL_FUNC(button_press), NULL);
	gtk_signal_connect(GTK_OBJECT(window), "button_release_event",
	    GTK_SIGNAL_FUNC(button_release), NULL);

	/* setup drawarea signal */
	gtk_signal_connect(GTK_OBJECT(drawarea), "expose_event",
	    GTK_SIGNAL_FUNC(expose), NULL);
	gtk_signal_connect(GTK_OBJECT(drawarea), "enter_notify_event",
	    GTK_SIGNAL_FUNC(enter_notify), NULL);

	gtk_widget_add_events(window, EVENT_MASK);
}

void
gui_gtk_widget_show(void)
{

	gtk_widget_show(window);
}

void
gui_gtk_widget_mainloop(void)
{

	install_idle_process();
	gtk_main();
	uninstall_idle_process();
}

void
gui_gtk_widget_quit(void)
{

	gtk_main_quit();
}

void
gui_gtk_set_window_title(const char* str)
{

	gtk_window_set_title(GTK_WINDOW(window), str);
}

/* toolkit data */
gui_toolkit_t gtk_toolkit = {
	gui_gtk_get_toolkit,
	gui_gtk_arginit,
	gui_gtk_widget_create,
	gui_gtk_widget_show,
	gui_gtk_widget_mainloop,
	gui_gtk_widget_quit,
	gui_gtk_set_window_title,
};


/*
 * Idle process
 */
static gint
idle_process(gpointer *p)
{

	UNUSED(p);

	if (np2oscfg.NOWAIT) {
		joy_flash();
		mousemng_callback();
		pccore_exec(framecnt == 0);
		if (np2oscfg.DRAW_SKIP) {
			/* nowait frame skip */
			framecnt++;
			if (framecnt >= np2oscfg.DRAW_SKIP) {
				processwait(0);
			}
		} else {
			/* nowait auto skip */
			framecnt = 1;
			if (timing_getcount()) {
				processwait(0);
			}
		}
	} else if (np2oscfg.DRAW_SKIP) {
		/* frame skip */
		if (framecnt < np2oscfg.DRAW_SKIP) {
			joy_flash();
			mousemng_callback();
			pccore_exec(framecnt == 0);
			framecnt++;
		} else {
			processwait(np2oscfg.DRAW_SKIP);
		}
	} else {
		/* auto skip */
		if (waitcnt == 0) {
			UINT cnt;
			joy_flash();
			mousemng_callback();
			pccore_exec(framecnt == 0);
			framecnt++;
			cnt = timing_getcount();
			if (framecnt > cnt) {
				waitcnt = framecnt;
				if (framemax > 1) {
					framemax--;
				}
			} else if (framecnt >= framemax) {
				if (framemax < 12) {
					framemax++;
				}
				if (cnt >= 12) {
					timing_reset();
				} else {
					timing_setcount(cnt - framecnt);
				}
				framereset(0);
			}
		} else {
			processwait(waitcnt);
			waitcnt = framecnt;
		}
	}
	return TRUE;
}

RetroPC.NET-CVS <cvs@retropc.net>