コード例 #1
0
ファイル: window.cpp プロジェクト: pcwalton/NetSurf
void nsbeos_window_expose_event(BView *view, gui_window *g, BMessage *message)
{
	BRect updateRect;
	hlcache_handle *c;
	float scale = g->bw->scale;
	struct rect clip;

	struct redraw_context ctx = { true, true, &nsbeos_plotters };

	assert(g);
	assert(g->bw);

	struct gui_window *z;
	for (z = window_list; z && z != g; z = z->next)
		continue;
	assert(z);
	assert(g->view == view);

	// we'll be resizing = reflowing = redrawing everything anyway...
	if (g->pending_resizes > 1)
		return;

	if (message->FindRect("rect", &updateRect) < B_OK)
		return;

	c = g->bw->current_content;
	if (c == NULL)
		return;

	if (!view->LockLooper())
		return;
	nsbeos_current_gc_set(view);

	if (view->Window())
		view->Window()->BeginViewTransaction();

	clip.x0 = (int)updateRect.left;
	clip.y0 = (int)updateRect.top;
	clip.x1 = (int)updateRect.right + 1;
	clip.y1 = (int)updateRect.bottom + 1;

	browser_window_redraw(g->bw, 0, 0, &clip, &ctx);

	if (g->careth != 0)
		nsbeos_plot_caret(g->caretx, g->carety, g->careth);

	if (view->Window())
		view->Window()->EndViewTransaction();

	// reset clipping just in case
	view->ConstrainClippingRegion(NULL);
	nsbeos_current_gc_set(NULL);
	view->UnlockLooper();
}
コード例 #2
0
ファイル: browser.c プロジェクト: pcwalton/NetSurf
static void browser_redraw_content( struct gui_window * gw, int xoff, int yoff,
								struct rect * area )
{
	CMP_BROWSER b = gw->browser;

	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &atari_plotters
	};

	LOG(("%s : %d,%d - %d,%d\n", b->bw->name, area->x0,
		area->y0, area->x1, area->y1
	));


	browser_window_redraw( b->bw, -b->scroll.current.x,
			-b->scroll.current.y, area, &ctx );

}

/*
	area: the browser canvas
*/
void browser_restore_caret_background( struct gui_window * gw, LGRECT * area)
{
	CMP_BROWSER b = gw->browser;
	LGRECT rect;
	if( area == NULL ){
		browser_get_rect( gw, BR_CONTENT, &rect );
		area = &rect;
	}
	/* This call restores the background and releases the memory: */
	// TODO: only release memory/clear flag when the caret is not clipped.
	// TODO: apply clipping.
	w_put_bkgr( &app,
			area->g_x-b->scroll.current.x+b->caret.current.g_x,
			area->g_y-b->scroll.current.y+b->caret.current.g_y,
			gw->browser->caret.current.g_w,
			gw->browser->caret.current.g_h,
			&gw->browser->caret.background
	);
	gw->browser->caret.background.fd_addr = NULL;
}
コード例 #3
0
ファイル: window.c プロジェクト: galexcode/NetSurf68k
static gboolean 
nsgtk_window_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data)
{
	struct gui_window *gw = data;
	struct gui_window *z;
	struct rect clip;
	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &nsgtk_plotters
	};

	double x1;
	double y1;
	double x2;
	double y2;

	assert(gw);
	assert(gw->bw);

	for (z = window_list; z && z != gw; z = z->next)
		continue;
	assert(z);
	assert(GTK_WIDGET(gw->layout) == widget);

	current_widget = (GtkWidget *)gw->layout;
	current_cr = cr;

	cairo_clip_extents(cr, &x1, &y1, &x2, &y2);

	clip.x0 = x1;
	clip.y0 = y1;
	clip.x1 = x2;
	clip.y1 = y2;

	browser_window_redraw(gw->bw, 0, 0, &clip, &ctx);

	if (gw->careth != 0) {
		nsgtk_plot_caret(gw->caretx, gw->carety, gw->careth);
	}

	current_widget = NULL;

	return FALSE;
}

#else

static gboolean 
nsgtk_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
	struct gui_window *gw = data;
	struct gui_window *z;
	struct rect clip;
	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &nsgtk_plotters
	};

	assert(gw);
	assert(gw->bw);

	for (z = window_list; z && z != gw; z = z->next)
		continue;
	assert(z);
	assert(GTK_WIDGET(gw->layout) == widget);

	current_widget = (GtkWidget *)gw->layout;
	current_cr = gdk_cairo_create(nsgtk_layout_get_bin_window(gw->layout));

	clip.x0 = event->area.x;
	clip.y0 = event->area.y;
	clip.x1 = event->area.x + event->area.width;
	clip.y1 = event->area.y + event->area.height;

	browser_window_redraw(gw->bw, 0, 0, &clip, &ctx);

	if (gw->careth != 0) {
		nsgtk_plot_caret(gw->caretx, gw->carety, gw->careth);
	}

	cairo_destroy(current_cr);

	current_widget = NULL;

	return FALSE;
}

#endif

static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
					  GdkEventMotion *event, gpointer data)
{
	struct gui_window *g = data;
	bool shift = event->state & GDK_SHIFT_MASK;
	bool ctrl = event->state & GDK_CONTROL_MASK;

	if ((abs(event->x - g->last_x) < 5) &&
	    (abs(event->y - g->last_y) < 5)) {
		/* Mouse hasn't moved far enough from press coordinate for this
		 * to be considered a drag. */
		return FALSE;
	} else {
		/* This is a drag, ensure it's always treated as such, even if
		 * we drag back over the press location */
		g->last_x = INT_MIN;
		g->last_y = INT_MIN;
	}

	if (g->mouse.state & BROWSER_MOUSE_PRESS_1) {
		/* Start button 1 drag */
		browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_1,
				g->mouse.pressed_x, g->mouse.pressed_y);

		/* Replace PRESS with HOLDING and declare drag in progress */
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_1 |
				BROWSER_MOUSE_HOLDING_1);
		g->mouse.state |= BROWSER_MOUSE_DRAG_ON;
	} else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
		/* Start button 2 drag */
		browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_2,
				g->mouse.pressed_x, g->mouse.pressed_y);

		/* Replace PRESS with HOLDING and declare drag in progress */
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_2 |
				BROWSER_MOUSE_HOLDING_2);
		g->mouse.state |= BROWSER_MOUSE_DRAG_ON;
	}

	/* Handle modifiers being removed */
	if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
		g->mouse.state ^= BROWSER_MOUSE_MOD_1;
	if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
		g->mouse.state ^= BROWSER_MOUSE_MOD_2;

	browser_window_mouse_track(g->bw, g->mouse.state,
			event->x / g->bw->scale, event->y / g->bw->scale);

	return TRUE;
}

static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
					 GdkEventButton *event, gpointer data)
{
	struct gui_window *g = data;

	gtk_widget_grab_focus(GTK_WIDGET(g->layout));
	gtk_widget_hide(GTK_WIDGET(nsgtk_scaffolding_history_window(
			g->scaffold)->window));

	g->mouse.pressed_x = event->x / g->bw->scale;
	g->mouse.pressed_y = event->y / g->bw->scale;

	switch (event->button) {
	case 1:	/* Left button, usually. Pass to core as BUTTON 1. */
		g->mouse.state = BROWSER_MOUSE_PRESS_1;
		break;

	case 2:	/* Middle button, usually. Pass to core as BUTTON 2 */
		g->mouse.state = BROWSER_MOUSE_PRESS_2;
		break;

	case 3:	/* Right button, usually. Action button, context menu. */
		browser_window_remove_caret(g->bw);
		nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse.pressed_x,
				g->mouse.pressed_y);
		return TRUE;

	default:
		return FALSE;
	}

	/* Handle the modifiers too */
	if (event->state & GDK_SHIFT_MASK)
		g->mouse.state |= BROWSER_MOUSE_MOD_1;
	if (event->state & GDK_CONTROL_MASK)
		g->mouse.state |= BROWSER_MOUSE_MOD_2;

	/* Record where we pressed, for use when determining whether to start
	 * a drag in motion notify events. */
	g->last_x = event->x;
	g->last_y = event->y;

	browser_window_mouse_click(g->bw, g->mouse.state, g->mouse.pressed_x,
			g->mouse.pressed_y);

	return TRUE;
}

static gboolean nsgtk_window_button_release_event(GtkWidget *widget,
					 GdkEventButton *event, gpointer data)
{
	struct gui_window *g = data;
	bool shift = event->state & GDK_SHIFT_MASK;
	bool ctrl = event->state & GDK_CONTROL_MASK;

	/* If the mouse state is PRESS then we are waiting for a release to emit
	 * a click event, otherwise just reset the state to nothing */
	if (g->mouse.state & BROWSER_MOUSE_PRESS_1)
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1);
	else if (g->mouse.state & BROWSER_MOUSE_PRESS_2)
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2);

	/* Handle modifiers being removed */
	if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
		g->mouse.state ^= BROWSER_MOUSE_MOD_1;
	if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
		g->mouse.state ^= BROWSER_MOUSE_MOD_2;

	if (g->mouse.state & (BROWSER_MOUSE_CLICK_1|BROWSER_MOUSE_CLICK_2)) {
		browser_window_mouse_click(g->bw, g->mouse.state,
				event->x / g->bw->scale,
				event->y / g->bw->scale);
	} else {
		browser_window_mouse_track(g->bw, 0, event->x / g->bw->scale,
				event->y / g->bw->scale);
	}

	g->mouse.state = 0;
	return TRUE;
}

static gboolean nsgtk_window_scroll_event(GtkWidget *widget,
				GdkEventScroll *event, gpointer data)
{
	struct gui_window *g = data;
	double value;
	GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
	GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
	GtkAllocation alloc;

	LOG(("%d", event->direction));
	switch (event->direction) {
	case GDK_SCROLL_LEFT:
		if (browser_window_scroll_at_point(g->bw,
				event->x / g->bw->scale,
				event->y / g->bw->scale,
				-100, 0) != true) {
			/* core did not handle event do horizontal scroll */

			value = gtk_adjustment_get_value(hscroll) -
				(nsgtk_adjustment_get_step_increment(hscroll) *2);

			if (value < nsgtk_adjustment_get_lower(hscroll)) {
				value = nsgtk_adjustment_get_lower(hscroll);
			}

			gtk_adjustment_set_value(hscroll, value);
		}
		break;

	case GDK_SCROLL_UP:
		if (browser_window_scroll_at_point(g->bw,
				event->x / g->bw->scale,
				event->y / g->bw->scale,
				0, -100) != true) {
			/* core did not handle event change vertical
			 * adjustment. 
			 */

			value = gtk_adjustment_get_value(vscroll) -
				(nsgtk_adjustment_get_step_increment(vscroll) * 2);

			if (value < nsgtk_adjustment_get_lower(vscroll)) {
				value = nsgtk_adjustment_get_lower(vscroll);
			}

			gtk_adjustment_set_value(vscroll, value);
		}
		break;

	case GDK_SCROLL_RIGHT:
		if (browser_window_scroll_at_point(g->bw,
				event->x / g->bw->scale,
				event->y / g->bw->scale,
				100, 0) != true) {

			/* core did not handle event change horizontal
			 * adjustment. 
			 */

			value = gtk_adjustment_get_value(hscroll) +
				(nsgtk_adjustment_get_step_increment(hscroll) * 2);

			/* @todo consider gtk_widget_get_allocated_width() */
			nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

			if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width) {
				value = nsgtk_adjustment_get_upper(hscroll) - 
					alloc.width;
			}

			gtk_adjustment_set_value(hscroll, value);
		}
		break;

	case GDK_SCROLL_DOWN:
		if (browser_window_scroll_at_point(g->bw,
				event->x / g->bw->scale,
				event->y / g->bw->scale,
				0, 100) != true) {
			/* core did not handle event change vertical
			 * adjustment. 
			 */

			value = gtk_adjustment_get_value(vscroll) +
				(nsgtk_adjustment_get_step_increment(vscroll) * 2);
			/* @todo consider gtk_widget_get_allocated_height */
			nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

			if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height) {
				value = nsgtk_adjustment_get_upper(vscroll) - 
					alloc.height;
			}

			gtk_adjustment_set_value(vscroll, value);
		}
		break;

	default:
		break;
	}

	return TRUE;
}

static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
				GdkEventKey *event, gpointer data)
{
	struct gui_window *g = data;
	uint32_t nskey = gtk_gui_gdkkey_to_nskey(event);

	if (browser_window_key_press(g->bw, nskey))
		return TRUE;

	if ((event->state & 0x7) != 0) 
		return TRUE;

	double value;
	GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
	GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
	GtkAllocation alloc;

	/* @todo consider gtk_widget_get_allocated_width() */
	nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

	switch (event->keyval) {

	case GDK_KEY(Home):
	case GDK_KEY(KP_Home):
		value = nsgtk_adjustment_get_lower(vscroll);
		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(End):
	case GDK_KEY(KP_End):
		value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;

		if (value < nsgtk_adjustment_get_lower(vscroll))
			value = nsgtk_adjustment_get_lower(vscroll);

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Left):
	case GDK_KEY(KP_Left):
		value = gtk_adjustment_get_value(hscroll) -
			nsgtk_adjustment_get_step_increment(hscroll);

		if (value < nsgtk_adjustment_get_lower(hscroll))
			value = nsgtk_adjustment_get_lower(hscroll);

		gtk_adjustment_set_value(hscroll, value);
		break;

	case GDK_KEY(Up):
	case GDK_KEY(KP_Up):
		value = gtk_adjustment_get_value(vscroll) -
			nsgtk_adjustment_get_step_increment(vscroll);

		if (value < nsgtk_adjustment_get_lower(vscroll))
			value = nsgtk_adjustment_get_lower(vscroll);

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Right):
	case GDK_KEY(KP_Right):
		value = gtk_adjustment_get_value(hscroll) +
			nsgtk_adjustment_get_step_increment(hscroll);

		if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width)
			value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;

		gtk_adjustment_set_value(hscroll, value);
		break;

	case GDK_KEY(Down):
	case GDK_KEY(KP_Down):
		value = gtk_adjustment_get_value(vscroll) +
			nsgtk_adjustment_get_step_increment(vscroll);

		if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
			value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Page_Up):
	case GDK_KEY(KP_Page_Up):
		value = gtk_adjustment_get_value(vscroll) -
			nsgtk_adjustment_get_page_increment(vscroll);

		if (value < nsgtk_adjustment_get_lower(vscroll))
			value = nsgtk_adjustment_get_lower(vscroll);

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Page_Down):
	case GDK_KEY(KP_Page_Down):
		value = gtk_adjustment_get_value(vscroll) +
			nsgtk_adjustment_get_page_increment(vscroll);

		if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
			value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;

		gtk_adjustment_set_value(vscroll, value);
		break;

	default:
		break;

	}

	return TRUE;
}

static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
		GtkAllocation *allocation, gpointer data)
{
	struct gui_window *g = data;

	g->bw->reformat_pending = true;
	browser_reformat_pending = true;

	if (g->paned != NULL) {
		/* Set status bar / scroll bar proportion according to
		 * option_toolbar_status_width */
		/* TODO: Probably want to detect when the user adjusts the
		 *       status bar width, remember that proportion for the
		 *       window, and use that here. */
		gtk_paned_set_position(g->paned, 
				       (nsoption_int(toolbar_status_width) *
					allocation->width) / 10000);
	}

	return TRUE;
}

/* Core interface docuemnted in desktop/gui.h to create a gui_window */
struct gui_window *gui_create_browser_window(struct browser_window *bw,
					     struct browser_window *clone,
					     bool new_tab)
{
	struct gui_window *g; /**< what we're creating to return */

	g = calloc(1, sizeof(*g));
	if (!g) {
		warn_user("NoMemory", 0);
		return 0;
	}

	LOG(("Creating gui window %p for browser window %p", g, bw));

	g->bw = bw;
	g->paned = NULL;
	g->mouse.state = 0;
	g->current_pointer = GUI_POINTER_DEFAULT;
	if (clone != NULL) {
		bw->scale = clone->scale;
	} else {
		bw->scale = (float) nsoption_int(scale) / 100.0;
	}

	g->careth = 0;

	if (new_tab) {
		assert(clone != NULL);
		g->scaffold = clone->window->scaffold;
	} else {
		/* Now construct and attach a scaffold */
		g->scaffold = nsgtk_new_scaffolding(g);
	}

	if (g->scaffold == NULL) {
		warn_user("NoMemory", 0);
		free(g);
		return NULL;
	}

	/* Construct our primary elements */

	/* top-level document (not a frame) => create a new tab */
	GError* error = NULL;
	GtkBuilder* xml = gtk_builder_new();
	if (!gtk_builder_add_from_file(xml, 
				       glade_file_location->tabcontents, 
				       &error)) {
		g_warning ("Couldn't load builder file: %s", error->message);
		g_error_free(error);
		return 0;
	}

	g->layout = GTK_LAYOUT(gtk_builder_get_object(xml, "layout"));
	g->status_bar = GTK_LABEL(gtk_builder_get_object(xml, "status_bar"));
	g->paned = GTK_PANED(gtk_builder_get_object(xml, "hpaned1"));

	/* connect the scrollbars to the layout widget */
	nsgtk_layout_set_hadjustment(g->layout,
			gtk_range_get_adjustment(GTK_RANGE(
			gtk_builder_get_object(xml, "hscrollbar"))));
	nsgtk_layout_set_vadjustment(g->layout,
			gtk_range_get_adjustment(GTK_RANGE(
			gtk_builder_get_object(xml, "vscrollbar"))));

	/* add the tab to the scaffold */
	bool tempback = true;
	switch (temp_open_background) {
	case -1:
		tempback = !(nsoption_bool(focus_new));
		break;
	case 0:
		tempback = false;
		break;
	case 1:
		tempback = true;
		break;
	}

	GtkWidget *tab_contents = GTK_WIDGET(gtk_builder_get_object(xml, "tabContents"));
	g_object_set_data(G_OBJECT(tab_contents), "gui_window", g);
	nsgtk_tab_add(g, tab_contents, tempback);

	g_object_unref(xml);

	/* Attach ourselves to the list (push_top) */
	if (window_list)
		window_list->prev = g;
	g->next = window_list;
	g->prev = NULL;
	window_list = g;

	/* set the events we're interested in receiving from the browser's
	 * drawing area.
	 */
	gtk_widget_add_events(GTK_WIDGET(g->layout),
				GDK_EXPOSURE_MASK |
				GDK_LEAVE_NOTIFY_MASK |
				GDK_BUTTON_PRESS_MASK |
				GDK_BUTTON_RELEASE_MASK |
				GDK_POINTER_MOTION_MASK |
				GDK_POINTER_MOTION_HINT_MASK |
				GDK_KEY_PRESS_MASK |
				GDK_KEY_RELEASE_MASK |
				GDK_SCROLL_MASK);
	nsgtk_widget_set_can_focus(GTK_WIDGET(g->layout), TRUE);

	/* set the default background colour of the drawing area to white. */
	nsgtk_widget_override_background_color(GTK_WIDGET(g->layout), 
					       GTK_STATE_NORMAL, 0, 0xffff, 0xffff, 0xffff);


	nsgtk_connect_draw_event(GTK_WIDGET(g->layout), G_CALLBACK(nsgtk_window_draw_event), g);

#define CONNECT(obj, sig, callback, ptr) \
	g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))

	CONNECT(g->layout, "motion_notify_event",
			nsgtk_window_motion_notify_event, g);
	g->signalhandler[NSGTK_WINDOW_SIGNAL_CLICK] =
			CONNECT(g->layout, "button_press_event",
			nsgtk_window_button_press_event, g);
	CONNECT(g->layout, "button_release_event",
			nsgtk_window_button_release_event, g);
	CONNECT(g->layout, "key_press_event",
			nsgtk_window_keypress_event, g);
	CONNECT(g->layout, "size_allocate",
			nsgtk_window_size_allocate_event, g);
	CONNECT(g->layout, "scroll_event",
			nsgtk_window_scroll_event, g);
	return g;
}



void nsgtk_reflow_all_windows(void)
{
	for (struct gui_window *g = window_list; g; g = g->next) {
		nsgtk_tab_options_changed(
				nsgtk_scaffolding_notebook(g->scaffold));
		g->bw->reformat_pending = true;
	}

	browser_reformat_pending = true;
}


/**
 * Process pending reformats
 */

void nsgtk_window_process_reformats(void)
{
	struct gui_window *g;
	GtkAllocation alloc;

	browser_reformat_pending = false;
	for (g = window_list; g; g = g->next) {
		if (!g->bw->reformat_pending)
			continue;

		g->bw->reformat_pending = false;

		/* @todo consider gtk_widget_get_allocated_width() */
		nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

		browser_window_reformat(g->bw, false, alloc.width, alloc.height);
	}
}


void nsgtk_window_destroy_browser(struct gui_window *g)
{
	browser_window_destroy(g->bw);
}

void gui_window_destroy(struct gui_window *g)
{
	if (g->prev)
		g->prev->next = g->next;
	else
		window_list = g->next;

	if (g->next)
		g->next->prev = g->prev;


	LOG(("Destroying gui_window %p", g));
	assert(g != NULL);
	assert(g->bw != NULL);
	LOG(("	   Scaffolding: %p", g->scaffold));
	LOG(("	   Window name: %s", g->bw->name));

	/* tab => remove tab */
	gtk_widget_destroy(gtk_widget_get_parent(GTK_WIDGET(g->layout)));
}

/**
 * set favicon
 */
void gui_window_set_icon(struct gui_window *gw, hlcache_handle *icon)
{
	struct bitmap *icon_bitmap = NULL;

	/* free any existing icon */
	if (gw->icon != NULL) {
		g_object_unref(gw->icon);
		gw->icon = NULL;
	}

	if (icon != NULL) {
		icon_bitmap = content_get_bitmap(icon);
		if (icon_bitmap != NULL) {
			LOG(("Using %p bitmap", icon_bitmap));
			gw->icon = nsgdk_pixbuf_get_from_surface(icon_bitmap->surface, 16, 16);
		} 
	} 

	if (gw->icon == NULL) {
		LOG(("Using default favicon"));
		g_object_ref(favicon_pixbuf);
		gw->icon = favicon_pixbuf;
	}

	nsgtk_scaffolding_set_icon(gw);
}

static void nsgtk_redraw_caret(struct gui_window *g)
{
	int sx, sy;

	if (g->careth == 0)
		return;

	gui_window_get_scroll(g, &sx, &sy);

	gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
			g->caretx - sx, g->carety - sy, 1, g->careth + 1);

}
コード例 #4
0
ファイル: gui.c プロジェクト: bkeepers/cheribsd
static void
fb_redraw(fbtk_widget_t *widget,
	  struct browser_widget_s *bwidget,
	  struct browser_window *bw)
{
	int x;
	int y;
	int caret_x, caret_y, caret_h;
	struct rect clip;
	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &fb_plotters
	};
	nsfb_t *nsfb = fbtk_get_nsfb(widget);
	float scale = browser_window_get_scale(bw);

	LOG(("%d,%d to %d,%d",
	     bwidget->redraw_box.x0,
	     bwidget->redraw_box.y0,
	     bwidget->redraw_box.x1,
	     bwidget->redraw_box.y1));

	x = fbtk_get_absx(widget);
	y = fbtk_get_absy(widget);

	/* adjust clipping co-ordinates according to window location */
	bwidget->redraw_box.y0 += y;
	bwidget->redraw_box.y1 += y;
	bwidget->redraw_box.x0 += x;
	bwidget->redraw_box.x1 += x;

	nsfb_claim(nsfb, &bwidget->redraw_box);

	/* redraw bounding box is relative to window */
	clip.x0 = bwidget->redraw_box.x0;
	clip.y0 = bwidget->redraw_box.y0;
	clip.x1 = bwidget->redraw_box.x1;
	clip.y1 = bwidget->redraw_box.y1;

	browser_window_redraw(bw,
			(x - bwidget->scrollx) / scale,
			(y - bwidget->scrolly) / scale,
			&clip, &ctx);

	if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
		/* This widget has caret, so render it */
		nsfb_bbox_t line;
		nsfb_plot_pen_t pen;

		line.x0 = x - bwidget->scrollx + caret_x;
		line.y0 = y - bwidget->scrolly + caret_y;
		line.x1 = x - bwidget->scrollx + caret_x;
		line.y1 = y - bwidget->scrolly + caret_y + caret_h;

		pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
		pen.stroke_width = 1;
		pen.stroke_colour = 0xFF0000FF;

		nsfb_plot_line(nsfb, &line, &pen);
	}

	nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box);

	bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX;
	bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = INT_MIN;
	bwidget->redraw_required = false;
}

static int
fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
{
	struct gui_window *gw = cbi->context;
	struct browser_widget_s *bwidget;

	bwidget = fbtk_get_userpw(widget);
	if (bwidget == NULL) {
		LOG(("browser widget from widget %p was null", widget));
		return -1;
	}

	if (bwidget->pan_required) {
		fb_pan(widget, bwidget, gw->bw);
	}

	if (bwidget->redraw_required) {
		fb_redraw(widget, bwidget, gw->bw);
	} else {
		bwidget->redraw_box.x0 = 0;
		bwidget->redraw_box.y0 = 0;
		bwidget->redraw_box.x1 = fbtk_get_width(widget);
		bwidget->redraw_box.y1 = fbtk_get_height(widget);
		fb_redraw(widget, bwidget, gw->bw);
	}
	return 0;
}

static int fb_browser_window_destroy(fbtk_widget_t *widget,
		fbtk_callback_info *cbi)
{
	struct browser_widget_s *browser_widget;

	if (widget == NULL) {
		return 0;
	}

	/* Free private data */
	browser_widget = fbtk_get_userpw(widget);
	free(browser_widget);

	return 0;
}


static const char *fename;
static int febpp;
static int fewidth;
static int feheight;
static const char *feurl;

static bool
process_cmdline(int argc, char** argv)
{
	int opt;

	LOG(("argc %d, argv %p", argc, argv));

	fename = "mtl";
	febpp = 32;

	fewidth = nsoption_int(window_width);
	if (fewidth <= 0) {
		fewidth = 800;
	}
	feheight = nsoption_int(window_height);
	if (feheight <= 0) {
		feheight = 480;
	}

	if ((nsoption_charp(homepage_url) != NULL) && 
	    (nsoption_charp(homepage_url)[0] != '\0')) {
		feurl = nsoption_charp(homepage_url);
	} else {
		feurl = NETSURF_HOMEPAGE;
	}

	while((opt = getopt(argc, argv, "f:b:w:h:")) != -1) {
		switch (opt) {
		case 'f':
			fename = optarg;
			break;

		case 'b':
			febpp = atoi(optarg);
			break;

		case 'w':
			fewidth = atoi(optarg);
			break;

		case 'h':
			feheight = atoi(optarg);
			break;

		default:
			fprintf(stderr,
				"Usage: %s [-f frontend] [-b bpp] url\n",
				argv[0]);
			return false;
		}
	}

	if (optind < argc) {
		feurl = argv[optind];
	}

	return true;
}
コード例 #5
0
ファイル: window.c プロジェクト: ysei/NetSurf
static gboolean
nsgtk_window_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data)
{
	struct gui_window *gw = data;
	struct gui_window *z;
	struct rect clip;
	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &nsgtk_plotters
	};

	double x1;
	double y1;
	double x2;
	double y2;

	assert(gw);
	assert(gw->bw);

	for (z = window_list; z && z != gw; z = z->next)
		continue;
	assert(z);
	assert(GTK_WIDGET(gw->layout) == widget);

	current_widget = (GtkWidget *)gw->layout;
	current_cr = cr;

	GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(gw->layout);
	GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(gw->layout);

	cairo_clip_extents(cr, &x1, &y1, &x2, &y2);

	clip.x0 = x1;
	clip.y0 = y1;
	clip.x1 = x2;
	clip.y1 = y2;

	browser_window_redraw(gw->bw,
			      -gtk_adjustment_get_value(hscroll),
			      -gtk_adjustment_get_value(vscroll),
			      &clip,
			      &ctx);

	if (gw->careth != 0) {
		nsgtk_plot_caret(gw->caretx, gw->carety, gw->careth);
	}

	current_widget = NULL;

	return FALSE;
}

#else

static gboolean
nsgtk_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
	struct gui_window *gw = data;
	struct gui_window *z;
	struct rect clip;
	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &nsgtk_plotters
	};

	assert(gw);
	assert(gw->bw);

	for (z = window_list; z && z != gw; z = z->next)
		continue;
	assert(z);
	assert(GTK_WIDGET(gw->layout) == widget);

	current_widget = (GtkWidget *)gw->layout;
	current_cr = gdk_cairo_create(nsgtk_layout_get_bin_window(gw->layout));

	clip.x0 = event->area.x;
	clip.y0 = event->area.y;
	clip.x1 = event->area.x + event->area.width;
	clip.y1 = event->area.y + event->area.height;

	browser_window_redraw(gw->bw, 0, 0, &clip, &ctx);

	if (gw->careth != 0) {
		nsgtk_plot_caret(gw->caretx, gw->carety, gw->careth);
	}

	cairo_destroy(current_cr);

	current_widget = NULL;

	return FALSE;
}

#endif

static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
					  GdkEventMotion *event, gpointer data)
{
	struct gui_window *g = data;
	bool shift = event->state & GDK_SHIFT_MASK;
	bool ctrl = event->state & GDK_CONTROL_MASK;

	if ((abs(event->x - g->last_x) < 5) &&
	    (abs(event->y - g->last_y) < 5)) {
		/* Mouse hasn't moved far enough from press coordinate for this
		 * to be considered a drag. */
		return FALSE;
	} else {
		/* This is a drag, ensure it's always treated as such, even if
		 * we drag back over the press location */
		g->last_x = INT_MIN;
		g->last_y = INT_MIN;
	}

	if (g->mouse.state & BROWSER_MOUSE_PRESS_1) {
		/* Start button 1 drag */
		browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_1,
				g->mouse.pressed_x, g->mouse.pressed_y);

		/* Replace PRESS with HOLDING and declare drag in progress */
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_1 |
				BROWSER_MOUSE_HOLDING_1);
		g->mouse.state |= BROWSER_MOUSE_DRAG_ON;
	} else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
		/* Start button 2 drag */
		browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG_2,
				g->mouse.pressed_x, g->mouse.pressed_y);

		/* Replace PRESS with HOLDING and declare drag in progress */
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_2 |
				BROWSER_MOUSE_HOLDING_2);
		g->mouse.state |= BROWSER_MOUSE_DRAG_ON;
	}

	/* Handle modifiers being removed */
	if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
		g->mouse.state ^= BROWSER_MOUSE_MOD_1;
	if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
		g->mouse.state ^= BROWSER_MOUSE_MOD_2;

	browser_window_mouse_track(g->bw, g->mouse.state,
			event->x / browser_window_get_scale(g->bw),
			event->y / browser_window_get_scale(g->bw));

	return TRUE;
}

static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
					 GdkEventButton *event, gpointer data)
{
	struct gui_window *g = data;

	gtk_widget_grab_focus(GTK_WIDGET(g->layout));
	gtk_widget_hide(GTK_WIDGET(nsgtk_scaffolding_history_window(
			g->scaffold)->window));

	g->mouse.pressed_x = event->x / browser_window_get_scale(g->bw);
	g->mouse.pressed_y = event->y / browser_window_get_scale(g->bw);

	switch (event->button) {
	case 1:	/* Left button, usually. Pass to core as BUTTON 1. */
		g->mouse.state = BROWSER_MOUSE_PRESS_1;
		break;

	case 2:	/* Middle button, usually. Pass to core as BUTTON 2 */
		g->mouse.state = BROWSER_MOUSE_PRESS_2;
		break;

	case 3:	/* Right button, usually. Action button, context menu. */
		browser_window_remove_caret(g->bw, true);
		nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse.pressed_x,
				g->mouse.pressed_y);
		return TRUE;

	default:
		return FALSE;
	}

	/* Modify for double & triple clicks */
	if (event->type == GDK_3BUTTON_PRESS)
		g->mouse.state |= BROWSER_MOUSE_TRIPLE_CLICK;
	else if (event->type == GDK_2BUTTON_PRESS)
		g->mouse.state |= BROWSER_MOUSE_DOUBLE_CLICK;

	/* Handle the modifiers too */
	if (event->state & GDK_SHIFT_MASK)
		g->mouse.state |= BROWSER_MOUSE_MOD_1;
	if (event->state & GDK_CONTROL_MASK)
		g->mouse.state |= BROWSER_MOUSE_MOD_2;

	/* Record where we pressed, for use when determining whether to start
	 * a drag in motion notify events. */
	g->last_x = event->x;
	g->last_y = event->y;

	browser_window_mouse_click(g->bw, g->mouse.state, g->mouse.pressed_x,
			g->mouse.pressed_y);

	return TRUE;
}

static gboolean nsgtk_window_button_release_event(GtkWidget *widget,
					 GdkEventButton *event, gpointer data)
{
	struct gui_window *g = data;
	bool shift = event->state & GDK_SHIFT_MASK;
	bool ctrl = event->state & GDK_CONTROL_MASK;

	/* If the mouse state is PRESS then we are waiting for a release to emit
	 * a click event, otherwise just reset the state to nothing */
	if (g->mouse.state & BROWSER_MOUSE_PRESS_1)
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1);
	else if (g->mouse.state & BROWSER_MOUSE_PRESS_2)
		g->mouse.state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2);

	/* Handle modifiers being removed */
	if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
		g->mouse.state ^= BROWSER_MOUSE_MOD_1;
	if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
		g->mouse.state ^= BROWSER_MOUSE_MOD_2;

	if (g->mouse.state & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) {
		browser_window_mouse_click(g->bw, g->mouse.state,
				event->x / browser_window_get_scale(g->bw),
				event->y / browser_window_get_scale(g->bw));
	} else {
		browser_window_mouse_track(g->bw, 0,
				event->x / browser_window_get_scale(g->bw),
				event->y / browser_window_get_scale(g->bw));
	}

	g->mouse.state = 0;
	return TRUE;
}

static gboolean
nsgtk_window_scroll_event(GtkWidget *widget,
			  GdkEventScroll *event,
			  gpointer data)
{
	struct gui_window *g = data;
	double value;
	double deltax = 0;
	double deltay = 0;
	GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
	GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
	GtkAllocation alloc;

	switch (event->direction) {
	case GDK_SCROLL_LEFT:
		deltax = -1.0;
		break;

	case GDK_SCROLL_UP:
		deltay = -1.0;
		break;

	case GDK_SCROLL_RIGHT:
		deltax = 1.0;
		break;

	case GDK_SCROLL_DOWN:
		deltay = 1.0;
		break;

#if GTK_CHECK_VERSION(3,4,0)
	case GDK_SCROLL_SMOOTH:
		gdk_event_get_scroll_deltas((GdkEvent *)event, &deltax, &deltay);
		break;
#endif
	default:
		LOG(("Unhandled mouse scroll direction"));
		return TRUE;
	}

	deltax *= nsgtk_adjustment_get_step_increment(hscroll);
	deltay *= nsgtk_adjustment_get_step_increment(vscroll);

	if (browser_window_scroll_at_point(g->bw,
			event->x / browser_window_get_scale(g->bw),
			event->y / browser_window_get_scale(g->bw),
			deltax, deltay) != true) {

		/* core did not handle event so change adjustments */

		/* Horizontal */
		if (deltax != 0) {
			value = gtk_adjustment_get_value(hscroll) + deltax;

			/* @todo consider gtk_widget_get_allocated_width() */
			nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

			if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width) {
				value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;
			}
			if (value < nsgtk_adjustment_get_lower(hscroll)) {
				value = nsgtk_adjustment_get_lower(hscroll);
			}

			gtk_adjustment_set_value(hscroll, value);
		}

		/* Vertical */
		if (deltay != 0) {
			value = gtk_adjustment_get_value(vscroll) + deltay;

			/* @todo consider gtk_widget_get_allocated_height */
			nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

			if (value > (nsgtk_adjustment_get_upper(vscroll) - alloc.height)) {
				value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;
			}
			if (value < nsgtk_adjustment_get_lower(vscroll)) {
				value = nsgtk_adjustment_get_lower(vscroll);
			}

			gtk_adjustment_set_value(vscroll, value);
		}
	}

	return TRUE;
}

static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
				GdkEventKey *event, gpointer data)
{
	struct gui_window *g = data;
	uint32_t nskey = gtk_gui_gdkkey_to_nskey(event);

	if (browser_window_key_press(g->bw, nskey))
		return TRUE;

	if ((event->state & 0x7) != 0)
		return TRUE;

	double value;
	GtkAdjustment *vscroll = nsgtk_layout_get_vadjustment(g->layout);
	GtkAdjustment *hscroll = nsgtk_layout_get_hadjustment(g->layout);
	GtkAllocation alloc;

	/* @todo consider gtk_widget_get_allocated_width() */
	nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

	switch (event->keyval) {

	case GDK_KEY(Home):
	case GDK_KEY(KP_Home):
		value = nsgtk_adjustment_get_lower(vscroll);
		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(End):
	case GDK_KEY(KP_End):
		value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;

		if (value < nsgtk_adjustment_get_lower(vscroll))
			value = nsgtk_adjustment_get_lower(vscroll);

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Left):
	case GDK_KEY(KP_Left):
		value = gtk_adjustment_get_value(hscroll) -
			nsgtk_adjustment_get_step_increment(hscroll);

		if (value < nsgtk_adjustment_get_lower(hscroll))
			value = nsgtk_adjustment_get_lower(hscroll);

		gtk_adjustment_set_value(hscroll, value);
		break;

	case GDK_KEY(Up):
	case GDK_KEY(KP_Up):
		value = gtk_adjustment_get_value(vscroll) -
			nsgtk_adjustment_get_step_increment(vscroll);

		if (value < nsgtk_adjustment_get_lower(vscroll))
			value = nsgtk_adjustment_get_lower(vscroll);

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Right):
	case GDK_KEY(KP_Right):
		value = gtk_adjustment_get_value(hscroll) +
			nsgtk_adjustment_get_step_increment(hscroll);

		if (value > nsgtk_adjustment_get_upper(hscroll) - alloc.width)
			value = nsgtk_adjustment_get_upper(hscroll) - alloc.width;

		gtk_adjustment_set_value(hscroll, value);
		break;

	case GDK_KEY(Down):
	case GDK_KEY(KP_Down):
		value = gtk_adjustment_get_value(vscroll) +
			nsgtk_adjustment_get_step_increment(vscroll);

		if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
			value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Page_Up):
	case GDK_KEY(KP_Page_Up):
		value = gtk_adjustment_get_value(vscroll) -
			nsgtk_adjustment_get_page_increment(vscroll);

		if (value < nsgtk_adjustment_get_lower(vscroll))
			value = nsgtk_adjustment_get_lower(vscroll);

		gtk_adjustment_set_value(vscroll, value);
		break;

	case GDK_KEY(Page_Down):
	case GDK_KEY(KP_Page_Down):
		value = gtk_adjustment_get_value(vscroll) +
			nsgtk_adjustment_get_page_increment(vscroll);

		if (value > nsgtk_adjustment_get_upper(vscroll) - alloc.height)
			value = nsgtk_adjustment_get_upper(vscroll) - alloc.height;

		gtk_adjustment_set_value(vscroll, value);
		break;

	default:
		break;

	}

	return TRUE;
}

static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
		GtkAllocation *allocation, gpointer data)
{
	struct gui_window *g = data;

	g->bw->reformat_pending = true;
	browser_reformat_pending = true;


	return TRUE;
}


/**  when the pane position is changed update the user option
 *
 * The slightly awkward implementation with the first allocation flag
 * is necessary because the initial window creation does not cause an
 * allocate-event signal so the position value in the pane is incorrect
 * and we cannot know what it should be until after the allocation
 * (which did not generate a signal) is done as the user position is a
 * percentage of pane total width not an absolute value.
 */
static void
nsgtk_paned_notify__position(GObject *gobject, GParamSpec *pspec, gpointer data)
{
	struct gui_window *g = data;
	GtkAllocation pane_alloc;

	gtk_widget_get_allocation(GTK_WIDGET(g->paned), &pane_alloc);

	if (g->paned_sized == false)
	{
		g->paned_sized = true;
		gtk_paned_set_position(g->paned,
		(nsoption_int(toolbar_status_size) * pane_alloc.width) / 10000);
		return;
	}

	nsoption_set_int(toolbar_status_size,
	 ((gtk_paned_get_position(g->paned) * 10000) / (pane_alloc.width - 1)));
}

/** Set status bar / scroll bar proportion according to user option
 * when pane is resized.
 */
static gboolean nsgtk_paned_size_allocate_event(GtkWidget *widget,
		GtkAllocation *allocation, gpointer data)
{
	gtk_paned_set_position(GTK_PANED(widget),
	       (nsoption_int(toolbar_status_size) * allocation->width) / 10000);

	return TRUE;
}

/* destroy the browsing context as there is nothing to display it now */
static void window_destroy(GtkWidget *widget, gpointer data)
{
	struct gui_window *gw = data;

	browser_window_destroy(gw->bw);
}

/* Core interface documented in desktop/gui.h to create a gui_window */
static struct gui_window *
gui_window_create(struct browser_window *bw,
		struct gui_window *existing,
		gui_window_create_flags flags)
{
	struct gui_window *g; /**< what we're creating to return */
	GError* error = NULL;
	bool tempback;
	GtkBuilder* xml;

	/* open builder file first to ease error handling on faliure */
	xml = gtk_builder_new();
	if (!gtk_builder_add_from_file(xml,
				       glade_file_location->tabcontents,
				       &error)) {
		g_warning ("Couldn't load builder file: %s", error->message);
		g_error_free(error);
		return NULL;
	}

	g = calloc(1, sizeof(*g));
	if (!g) {
		warn_user("NoMemory", 0);
		g_object_unref(xml);
		return NULL;
	}

	LOG(("Creating gui window %p for browser window %p", g, bw));

	g->bw = bw;
	g->mouse.state = 0;
	g->current_pointer = GUI_POINTER_DEFAULT;
	if (flags & GW_CREATE_CLONE) {
		assert(existing != NULL);
		bw->scale = existing->bw->scale;
	} else {
		bw->scale = nsoption_int(scale) / 100;
	}

	/* attach scaffold */
	if (flags & GW_CREATE_TAB) {
		assert(existing != NULL);
		g->scaffold = existing->scaffold;
	} else {
		/* Now construct and attach a scaffold */
		g->scaffold = nsgtk_new_scaffolding(g);
	}
	if (g->scaffold == NULL) {
		warn_user("NoMemory", 0);
		free(g);
		g_object_unref(xml);
		return NULL;
	}

	/* Construct our primary elements */
	g->container = GTK_WIDGET(gtk_builder_get_object(xml, "tabContents"));
	g->layout = GTK_LAYOUT(gtk_builder_get_object(xml, "layout"));
	g->status_bar = GTK_LABEL(gtk_builder_get_object(xml, "status_bar"));
	g->paned = GTK_PANED(gtk_builder_get_object(xml, "hpaned1"));


	/* add new gui window to global list (push_top) */
	if (window_list) {
		window_list->prev = g;
	}
	g->next = window_list;
	g->prev = NULL;
	window_list = g;

	/* set the events we're interested in receiving from the browser's
	 * drawing area.
	 */
	gtk_widget_add_events(GTK_WIDGET(g->layout),
				GDK_EXPOSURE_MASK |
				GDK_LEAVE_NOTIFY_MASK |
				GDK_BUTTON_PRESS_MASK |
				GDK_BUTTON_RELEASE_MASK |
				GDK_POINTER_MOTION_MASK |
				GDK_POINTER_MOTION_HINT_MASK |
				GDK_KEY_PRESS_MASK |
				GDK_KEY_RELEASE_MASK |
				GDK_SCROLL_MASK);
	nsgtk_widget_set_can_focus(GTK_WIDGET(g->layout), TRUE);

	/* set the default background colour of the drawing area to white. */
	nsgtk_widget_override_background_color(GTK_WIDGET(g->layout),
					       GTK_STATE_NORMAL,
					       0, 0xffff, 0xffff, 0xffff);

	nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
				 G_CALLBACK(nsgtk_window_draw_event), g);

	/* layout signals */
	CONNECT(g->layout, "motion-notify-event",
			nsgtk_window_motion_notify_event, g);
	g->signalhandler[NSGTK_WINDOW_SIGNAL_CLICK] =
			CONNECT(g->layout, "button-press-event",
			nsgtk_window_button_press_event, g);
	CONNECT(g->layout, "button-release-event",
			nsgtk_window_button_release_event, g);
	CONNECT(g->layout, "key-press-event",
			nsgtk_window_keypress_event, g);
	CONNECT(g->layout, "size-allocate",
			nsgtk_window_size_allocate_event, g);
	CONNECT(g->layout, "scroll-event",
			nsgtk_window_scroll_event, g);

	/* status pane signals */
	CONNECT(g->paned, "size-allocate",
		nsgtk_paned_size_allocate_event, g);

	CONNECT(g->paned, "notify::position",
		nsgtk_paned_notify__position, g);

	/* gtk container destructor */
	CONNECT(g->container, "destroy",
		window_destroy, g);

	/* add the tab container to the scaffold notebook */
	switch (temp_open_background) {
	case -1:
		tempback = !(nsoption_bool(focus_new));
		break;
	case 0:
		tempback = false;
		break;
	default:
		tempback = true;
		break;
	}
	nsgtk_tab_add(g, g->container, tempback);

	/* safe to drop the reference to the xml as the container is
	 * referenced by the notebook now.
	 */
	g_object_unref(xml);

	return g;
}



void nsgtk_reflow_all_windows(void)
{
	for (struct gui_window *g = window_list; g; g = g->next) {
		nsgtk_tab_options_changed(
				nsgtk_scaffolding_notebook(g->scaffold));
		g->bw->reformat_pending = true;
	}

	browser_reformat_pending = true;
}


/**
 * Process pending reformats
 */

void nsgtk_window_process_reformats(void)
{
	struct gui_window *g;
	GtkAllocation alloc;

	browser_reformat_pending = false;
	for (g = window_list; g; g = g->next) {
		if (!g->bw->reformat_pending)
			continue;

		g->bw->reformat_pending = false;

		/* @todo consider gtk_widget_get_allocated_width() */
		nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc);

		browser_window_reformat(g->bw, false, alloc.width, alloc.height);
	}
}

void nsgtk_window_destroy_browser(struct gui_window *gw)
{
	/* remove tab */
	gtk_widget_destroy(gw->container);
}
コード例 #6
0
ファイル: browser.c プロジェクト: pcwalton/NetSurf
void browser_redraw( struct gui_window * gw )
{
	LGRECT bwrect;
	struct s_browser * b = gw->browser;
	short todo[4];
	struct rect clip;
	/* used for clipping of content redraw: */
	struct rect redraw_area;

	if( b->attached == false || b->bw->current_content == NULL ) {
		return;
	}

	browser_get_rect(gw, BR_CONTENT, &bwrect);

	plotter->resize(plotter, bwrect.g_w, bwrect.g_h);
	plotter->move(plotter, bwrect.g_x, bwrect.g_y );
	clip.x0 = 0;
	clip.y0 = 0;
	clip.x1 = bwrect.g_w;
	clip.y1 = bwrect.g_h;
	plotter->set_clip( plotter, &clip );
	if( plotter->lock(plotter) == 0 )
		return;

	if( b->scroll.required == true && b->bw->current_content != NULL) {
		browser_process_scroll( gw, bwrect );
		b->scroll.required = false;
	}

	if ((b->redraw.areas_used > 0) && b->bw->current_content != NULL ) {
		if( (plotter->flags & PLOT_FLAG_OFFSCREEN) == 0 ) {

			int i;
			GRECT area;
			GRECT fbwork;
			short wf_top[4];
			todo[0] = bwrect.g_x;
			todo[1] = bwrect.g_y;
			todo[2] = todo[0] + bwrect.g_w-1;
			todo[3] = todo[1] + bwrect.g_h-1;
			vs_clip(plotter->vdi_handle, 1, (short*)&todo[0]);

			wind_get( 0, WF_TOP, &wf_top[0], &wf_top[1],
						&wf_top[2], &wf_top[3] );

			if( wf_top[0] == gw->root->handle->handle
				&& wf_top[1] == _AESapid ){
				/* The window is on top, so there is no need to walk the 	*/
				/* AES rectangle list. 										*/
				for( i=0; i<b->redraw.areas_used; i++ ){
					fbwork.g_x = todo[0] - bwrect.g_x;
					fbwork.g_y = todo[1] - bwrect.g_y;
					if( fbwork.g_x < 0 ){
						fbwork.g_w = todo[2] + todo[0];
						fbwork.g_x = 0;
					} else {
						fbwork.g_w = todo[2];
					}
					if( fbwork.g_y < 0 ){
						fbwork.g_h = todo[3] + todo[1];
						fbwork.g_y = 0;
					} else {
						fbwork.g_h = todo[3];
					}
					area.g_x = b->redraw.areas[i].x0;
					area.g_y = b->redraw.areas[i].y0;
					area.g_w = b->redraw.areas[i].x1 - b->redraw.areas[i].x0;
					area.g_h = b->redraw.areas[i].y1 - b->redraw.areas[i].y0;
					if (rc_intersect((GRECT *)&fbwork,(GRECT *)&area)) {
						redraw_area.x0 = area.g_x;
						redraw_area.y0 = area.g_y;
						redraw_area.x1 = area.g_x + area.g_w;
						redraw_area.y1 = area.g_y + area.g_h;
						browser_redraw_content( gw, 0, 0, &redraw_area );
					} else {
						/* the area should be kept scheduled for later redraw,*/
						/* but because this is onscreen plotter, it doesn't   */
						/* make much sense anyway...						  */
					}
				}
			} else {
				/* walk the AES rectangle list: */
				if( wind_get(gw->root->handle->handle, WF_FIRSTXYWH,
								&todo[0], &todo[1], &todo[2], &todo[3] )!=0 ) {
					while (todo[2] && todo[3]) {
						/* convert screen to framebuffer coords: */
						fbwork.g_x = todo[0] - bwrect.g_x;
						fbwork.g_y = todo[1] - bwrect.g_y;
						if( fbwork.g_x < 0 ){
							fbwork.g_w = todo[2] + todo[0];
							fbwork.g_x = 0;
						} else {
							fbwork.g_w = todo[2];
						}
						if( fbwork.g_y < 0 ){
							fbwork.g_h = todo[3] + todo[1];
							fbwork.g_y = 0;
						} else {
							fbwork.g_h = todo[3];
						}
						/* walk the redraw requests: */
						for( i=0; i<b->redraw.areas_used; i++ ){
							area.g_x = b->redraw.areas[i].x0;
							area.g_y = b->redraw.areas[i].y0;
							area.g_w = b->redraw.areas[i].x1 - b->redraw.areas[i].x0;
							area.g_h = b->redraw.areas[i].y1 - b->redraw.areas[i].y0;
							if (rc_intersect((GRECT *)&fbwork,(GRECT *)&area)) {
								redraw_area.x0 = area.g_x;
								redraw_area.y0 = area.g_y;
								redraw_area.x1 = area.g_x + area.g_w;
								redraw_area.y1 = area.g_y + area.g_h;
								browser_redraw_content( gw, 0, 0, &redraw_area );
							} else {
								/* the area should be kept scheduled for later redraw,*/
								/* but because this is onscreen plotter, it doesn't   */
								/* make much sense anyway...						  */
							}

						}
						if (wind_get(gw->root->handle->handle, WF_NEXTXYWH,
								&todo[0], &todo[1], &todo[2], &todo[3])==0) {
							break;
						}
					}
				}
			}


			vs_clip(plotter->vdi_handle, 0, (short*)&todo);
		} else {

			/* its save to do a complete redraw without knowledge about GEM windows :) */
			/* walk the redraw requests: */
			int i;
			for( i=0; i<b->redraw.areas_used; i++ ){
				struct redraw_context ctx = {
					.interactive = true,
					.background_images = true,
					.plot = &atari_plotters
				};
				browser_window_redraw( b->bw, -b->scroll.current.x,
						-b->scroll.current.y, &b->redraw.areas[i], &ctx );
			}
			GRECT area;
			area.g_x = bwrect.g_x;
			area.g_y = bwrect.g_y;
			area.g_w = bwrect.g_w;
			area.g_h = bwrect.g_h;
			//plotter->blit( plotter, &area );
		}
		b->redraw.areas_used = 0;
	}
	if( b->caret.redraw == true && 	b->bw->current_content != NULL ) {
		LGRECT area;
		todo[0] = bwrect.g_x;
		todo[1] = bwrect.g_y;
		todo[2] = todo[0] + bwrect.g_w;
		todo[3] = todo[1] + bwrect.g_h;
		area.g_x = bwrect.g_x;
		area.g_y = bwrect.g_y;
		area.g_w = bwrect.g_w;
		area.g_h = bwrect.g_h;
		vs_clip(plotter->vdi_handle, 1, (short*)&todo[0]);
		browser_redraw_caret( gw, &area );
		vs_clip(plotter->vdi_handle, 0, (short*)&todo[0]);
		b->caret.redraw = false;
	}
	plotter->unlock(plotter);
	/* TODO: if we use offscreen bitmap, trigger content redraw here */
}

static void __CDECL browser_evnt_redraw( COMPONENT * c, long buff[8], void * data)
{
	struct gui_window * gw = (struct gui_window *) data;
	CMP_BROWSER b = gw->browser;
	LGRECT work, lclip;

	browser_get_rect( gw, BR_CONTENT, &work );
	lclip = work;
	if ( !rc_lintersect( (LGRECT*)&buff[4], &lclip ) ) return;

	if( b->bw->current_content == NULL ){
		short pxy[4];
		pxy[0] = lclip.g_x;
		pxy[1] = lclip.g_y;
		pxy[2] = lclip.g_x + lclip.g_w - 1;
		pxy[3] = lclip.g_y + lclip.g_h - 1;
		vsf_color( gw->root->handle->graf->handle, WHITE );
		vsf_perimeter( gw->root->handle->graf->handle, 0);
		vsf_interior( gw->root->handle->graf->handle, FIS_SOLID );
		vsf_style( gw->root->handle->graf->handle, 1);
		v_bar( gw->root->handle->graf->handle, (short*)&pxy );
		return;
	}

	/* convert redraw coords to framebuffer coords: */
	lclip.g_x -= work.g_x;
	lclip.g_y -= work.g_y;

	if( lclip.g_x < 0 ) {
		lclip.g_w = work.g_w + lclip.g_x;
		lclip.g_x = 0;
	}

	if( lclip.g_y < 0 ) {
		lclip.g_h = work.g_h + lclip.g_y;
		lclip.g_y = 0;
	}

	if( lclip.g_h > 0 && lclip.g_w > 0 ) {

		if( gw->browser->reformat_pending == true ){
			LGRECT newsize;
			gw->browser->reformat_pending = false;
			browser_get_rect(gw, BR_CONTENT, &newsize);
			/* this call will also schedule an redraw for the complete */
			/* area. */
			/* Resize must be handled here, because otherwise */
			/* a redraw is scheduled twice (1. by the frontend, 2. by AES) */
			browser_window_reformat(b->bw, false, newsize.g_w, newsize.g_h );
		} else {
			browser_schedule_redraw( gw, lclip.g_x, lclip.g_y,
				lclip.g_x + lclip.g_w, lclip.g_y + lclip.g_h
			);
		}
	}

	return;
}