Ejemplo n.º 1
0
void ensure_scrolled_window_row_visible(widget_t list, int row, int num_rows)
{
  /* view files file list */
  /*   called in snd-file.c on vdat->file_list which is a vbox; its parent is a viewport */
  /* also used in slist_moveto below */
  GtkWidget *parent;
  GtkAdjustment *v;
  gdouble maximum, size, new_value, minimum;
  parent = gtk_widget_get_parent(list);
  v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(parent));
  maximum = v->upper;
  minimum = v->lower;
  size = v->page_size;
  maximum -= size;
  if (row == 0)
    new_value = 0.0;
  else
    {
      if (row >= (num_rows - 1))
	new_value = maximum;
      else new_value = ((row + 0.5) * ((maximum - minimum) / (float)(num_rows - 1)));
    }
  if (new_value != v->value)
    gtk_adjustment_set_value(v, new_value);
}
Ejemplo n.º 2
0
static gboolean scroll_callback(GtkWidget * w, GdkEventScroll * evt,
                                gpointer data)
  {
  bg_nle_timeline_t * t = data;
  double new_val;
  GtkAdjustment * adj = gtk_viewport_get_vadjustment(GTK_VIEWPORT(t->preview_window));
  
  //  gtk_scrollbar_get_adjustment(GTK_SCROLLBAR(t->scrollbar));
  
  if(evt->direction == GDK_SCROLL_UP)
    {
    new_val = adj->value - 3 * adj->step_increment;
    gtk_adjustment_set_value(adj, new_val);
    return TRUE;
    }
  else if(evt->direction == GDK_SCROLL_DOWN)
    {
    new_val = adj->value + 3 * adj->step_increment;
    if(new_val > adj->upper - adj->page_size)
      new_val = adj->upper - adj->page_size;
    gtk_adjustment_set_value(adj, new_val);
    return TRUE;
    }
  
  return FALSE;
  }
Ejemplo n.º 3
0
bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
{
	CALLED();
	if (g->view == NULL)
		return false;
	if (!g->view->LockLooper())
		return false;

#warning XXX: report to view frame ?
	if (g->view->ScrollBar(B_HORIZONTAL))
		*sx = (int)g->view->ScrollBar(B_HORIZONTAL)->Value();
	if (g->view->ScrollBar(B_VERTICAL))
		*sy = (int)g->view->ScrollBar(B_VERTICAL)->Value();
		
	g->view->UnlockLooper();
#warning WRITEME
#if 0 /* GTK */
	GtkAdjustment *vadj = gtk_viewport_get_vadjustment(g->viewport);
	GtkAdjustment *hadj = gtk_viewport_get_hadjustment(g->viewport);

	assert(vadj);
	assert(hadj);

	*sy = (int)(gtk_adjustment_get_value(vadj));
	*sx = (int)(gtk_adjustment_get_value(hadj));

#endif
	return true;
}
Ejemplo n.º 4
0
static gboolean
wrap_table_child_focus_in (GtkWidget *widget,
                           GdkEventFocus *event,
                           gpointer data)
{
    gint x, y;
    GtkWidget *container, *viewport;
    GtkAdjustment *hadj, *vadj;

    container = gtk_widget_get_parent (widget);
    if (container)
    {
        viewport = gtk_widget_get_parent (container);
    }
    g_assert (container && viewport);
    g_assert (GTK_IS_VIEWPORT (viewport));
    g_return_val_if_fail (gtk_widget_get_realized (viewport), FALSE);

    if (!wrap_table_child_visible_in (widget, viewport))
    {
        hadj = gtk_viewport_get_hadjustment (GTK_VIEWPORT (viewport));
        vadj = gtk_viewport_get_vadjustment (GTK_VIEWPORT (viewport));

        gtk_widget_translate_coordinates (widget, container, 0, 0, &x, &y);

        gtk_adjustment_set_value (hadj, MIN (x, hadj->upper - hadj->page_size));
        gtk_adjustment_set_value (vadj, MIN (y, vadj->upper - vadj->page_size));
    }

    return FALSE;
}
Ejemplo n.º 5
0
static void
cv_tabs_sizealloc (GtkWidget *widget, GtkAllocation *allocation, chanview *cv)
{
    GdkWindow *parent_win;
    GtkAdjustment *adj;
    GtkWidget *inner;
    gint viewport_size;

    inner = ((tabview *)cv)->inner;
    parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));

    if (cv->vertical)
    {
        adj = gtk_viewport_get_vadjustment (GTK_VIEWPORT (gtk_widget_get_parent (inner)));
        gdk_window_get_geometry (parent_win, 0, 0, 0, &viewport_size, 0);
    } else
    {
        adj = gtk_viewport_get_hadjustment (GTK_VIEWPORT (gtk_widget_get_parent (inner)));
        gdk_window_get_geometry (parent_win, 0, 0, &viewport_size, 0, 0);
    }

    if (gtk_adjustment_get_upper (adj) <= viewport_size)
    {
        gtk_widget_hide (((tabview *)cv)->b1);
        gtk_widget_hide (((tabview *)cv)->b2);
    } else
    {
        gtk_widget_show (((tabview *)cv)->b1);
        gtk_widget_show (((tabview *)cv)->b2);
    }
}
Ejemplo n.º 6
0
/*
 *	CBoardDevice::Init()
 *
 *  Initializes the device
 *
 *	Returns:	True if the initializing was successful and false if it failed.
 */
bool CBoardDevice::Init(GtkFixed *board_area, CBoardDeviceGroup *device_group)
{
	this->device_group = device_group;

	// Load the bitmap
	GdkPixbuf *bg_pixbuf = gdk_pixbuf_new_from_stream(CFile(image_file.c_str()).get_input_stream(), NULL, NULL);
	if(bg_pixbuf == NULL)
		return false;

	bitmap_x = bitmap_y = 0;
	
	width = gdk_pixbuf_get_width(bg_pixbuf);
	height = gdk_pixbuf_get_height(bg_pixbuf);

	// Check if the type is LED, PUSH or TOGGLE
	if(!strcmp(type.c_str(), "LED") ||
	   !strcmp(type.c_str(), "PUSH") ||
	   !strcmp(type.c_str(), "TOGGLE"))
	{
		// Set the appropriate width and height of the bitmap
		width = width / 2;

		// Check if PUSH because pushbuttons have the value 1 if they are up
		if(!strcmp(type.c_str(), "PUSH"))
			bitmap_x = 1;
	}
	// Check if the type is SSLED
	else if(!strcmp(type.c_str(), "SSLED"))
	{
		// Set the appropriate width and height of the bitmap
		width = width / 8;
		height = height / 16;
	}
	
	GtkWidget *bg_viewport = gtk_viewport_new(NULL, NULL);
	gtk_widget_set_events(bg_viewport, GDK_BUTTON_RELEASE_MASK);
	g_signal_connect(G_OBJECT(bg_viewport), "button-press-event", G_CALLBACK(device_button_pressed), this);
	g_signal_connect(G_OBJECT(bg_viewport), "button-release-event", G_CALLBACK(device_button_released), this);
	gtk_widget_show(bg_viewport);
	
	GtkWidget *bg_image = gtk_image_new_from_pixbuf(bg_pixbuf);
	gtk_widget_show(bg_image);
	
	gtk_container_add((GtkContainer*)bg_viewport, bg_image);
	gtk_viewport_set_shadow_type((GtkViewport*)bg_viewport, GTK_SHADOW_NONE);
	gtk_widget_set_size_request(bg_viewport, width, height);
	gtk_adjustment_set_upper(gtk_viewport_get_hadjustment((GtkViewport*)bg_viewport), width);
	gtk_adjustment_set_upper(gtk_viewport_get_vadjustment((GtkViewport*)bg_viewport), height);
	gtk_fixed_put(board_area, bg_viewport, coords.x, coords.y);
	
	g_object_unref(bg_pixbuf);
	
	viewport = (GtkViewport*)bg_viewport;
	
	ShowCorrectImage();

	return true;
}
Ejemplo n.º 7
0
static void
tab_scroll_right_down_clicked (GtkWidget *widget, chanview *cv)
{
    GtkAdjustment *adj;
    gint viewport_size;
    gfloat new_value;
    GtkWidget *inner;
    GdkWindow *parent_win;
    gdouble i;

    inner = ((tabview *)cv)->inner;
    parent_win = gtk_widget_get_window (gtk_widget_get_parent (inner));

    if (cv->vertical)
    {
        adj = gtk_viewport_get_vadjustment (GTK_VIEWPORT (gtk_widget_get_parent(inner)));
        gdk_window_get_geometry (parent_win, 0, 0, 0, &viewport_size, 0);
    } else
    {
        adj = gtk_viewport_get_hadjustment (GTK_VIEWPORT (gtk_widget_get_parent(inner)));
        gdk_window_get_geometry (parent_win, 0, 0, &viewport_size, 0, 0);
    }

    new_value = tab_search_offset (inner, gtk_adjustment_get_value (adj), 1, cv->vertical);

    if (new_value == 0 || new_value + viewport_size > gtk_adjustment_get_upper (adj))
        new_value = gtk_adjustment_get_upper (adj) - viewport_size;

    if (!tab_right_is_moving)
    {
        tab_right_is_moving = 1;

        for (i = gtk_adjustment_get_value (adj); ((i < new_value) && (tab_right_is_moving)); i += 0.1)
        {
            gtk_adjustment_set_value (adj, i);
            while (g_main_context_pending (NULL))
                g_main_context_iteration (NULL, TRUE);
        }

        gtk_adjustment_set_value (adj, new_value);

        tab_right_is_moving = 0;                /* hSP: set to false in case we didnt get stopped (the normal case) */
    }
    else
    {
        tab_right_is_moving = 0;                /* hSP: jump directly to next element if user is clicking faster than we can scroll.. */
    }
}
Ejemplo n.º 8
0
/* Returns the vertical scrollbar's adjustment, used to
 * connect the vertical scrollbar to the child widget's
 * vertical scroll functionality. */
int
clip_GTK_VIEWPORTGETVADJUSTMENT (ClipMachine *cm)
{
    C_widget *cvp = _fetch_cw_arg(cm);
    ClipVar * cv  = RETPTR(cm);
    GtkAdjustment* adj;
    C_widget *cadj;
    CHECKCWID(cvp,GTK_IS_VIEWPORT);
    adj = gtk_viewport_get_vadjustment (GTK_VIEWPORT(cvp->widget));
    cadj = _list_get_cwidget(cm, adj);
    if (!cadj) cadj = _register_widget(cm, (GtkWidget*)adj, NULL);
    if (cadj) _clip_mclone(cm, cv, &cadj->obj);
    return 0;
err:
    return 1;
}
Ejemplo n.º 9
0
void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
{
	CALLED();
	if (g->view == NULL)
		return;
	if (!g->view->LockLooper())
		return;

#warning XXX: report to view frame ?
	if (g->view->ScrollBar(B_HORIZONTAL))
		g->view->ScrollBar(B_HORIZONTAL)->SetValue(sx);
	if (g->view->ScrollBar(B_VERTICAL))
		g->view->ScrollBar(B_VERTICAL)->SetValue(sy);
		
	g->view->UnlockLooper();
#warning WRITEME
#if 0 /* GTK */
	GtkAdjustment *vadj = gtk_viewport_get_vadjustment(g->viewport);
	GtkAdjustment *hadj = gtk_viewport_get_hadjustment(g->viewport);
	gdouble vlower, vpage, vupper, hlower, hpage, hupper, x = (double)sx, y = (double)sy;
	
	assert(vadj);
	assert(hadj);
	
	g_object_get(vadj, "page-size", &vpage, "lower", &vlower, "upper", &vupper, NULL);
	g_object_get(hadj, "page-size", &hpage, "lower", &hlower, "upper", &hupper, NULL);
	
	if (x < hlower)
		x = hlower;
	if (x > (hupper - hpage))
		x = hupper - hpage;
	if (y < vlower)
		y = vlower;
	if (y > (vupper - vpage))
		y = vupper - vpage;
	
	gtk_adjustment_set_value(vadj, y);
	gtk_adjustment_set_value(hadj, x);
#endif
}
Ejemplo n.º 10
0
static void
lyric_show_viewport_size_allocate(GtkWidget *widget,GtkAllocation *allocation)
{
    LyricShowViewport *lsv;
    lsv = LYRIC_SHOW_VIEWPORT(widget);

    if(gtk_widget_get_realized(widget))
    {
        gdk_window_invalidate_rect(gtk_widget_get_window(widget),NULL,TRUE);
    }

    GTK_WIDGET_CLASS(lyric_show_viewport_parent_class)->size_allocate(widget,allocation);
    if(gtk_widget_get_visible(lsv->priv->lyricbox))
    {
        gtk_bin_instance_set_increment_height(GTK_BIN_INSTANCE(lsv->priv->box_bin),allocation->height);
    }else{
        gtk_bin_instance_set_increment_height(GTK_BIN_INSTANCE(lsv->priv->box_bin),0);
    }
#if 0
    g_warning("x:%5d,y:%5d,width:%6d,heigth:%d",
            allocation->x,allocation->y,
            allocation->width,allocation->height);
#endif

    if(gtk_widget_get_visible(lsv->priv->lyricbox))
    {
        gdouble value = (lsv->priv->pos+lsv->priv->pressed_pos);///-allocation->height/2.0;
        GtkAdjustment *adj = 

#if GTK_CHECK_VERSION(3,2,0)
        gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(widget));
#else
        gtk_viewport_get_vadjustment(GTK_VIEWPORT(lsv));
#endif
        gtk_adjustment_set_value(adj,value);
    }
}
Ejemplo n.º 11
0
bg_nle_timeline_t * bg_nle_timeline_create(bg_nle_project_t * p)
  {
  GtkWidget * box;
  //  GtkWidget * table;
  GtkSizeGroup * size_group;
  //  GtkWidget * table1;
  GtkStyle *style;
  GtkWidget * frame;
  
  int i;

  bg_nle_timeline_t * ret = calloc(1, sizeof(*ret));  

  //  GtkObject *adj = gtk_adjustment_new( 0, 0, 100, 1, 10, 0 );

  ret->p = p;

  bg_nle_time_range_copy(&ret->tr.selection,
                         &p->selection);
  bg_nle_time_range_copy(&ret->tr.visible,
                         &p->visible);
  bg_nle_time_range_copy(&ret->tr.in_out,
                         &p->in_out);
  ret->tr.cursor_pos = p->cursor_pos;
  
  //  ret->tr.set_visible = visibility_changed_callback;
  //  ret->tr.set_zoom = zoom_changed_callback;
  //  ret->tr.set_selection = selection_changed_callback;
  //  ret->tr.set_in_out = in_out_changed_callback;
  ret->tr.motion_callback = timewidget_motion_callback;
  ret->tr.motion_callback_data = ret;
  ret->tr.ti = &ret->time_info;
    
  ret->ruler = bg_nle_time_ruler_create(&ret->tr);
  
  //  ret->paned = gtk_hpaned_new();
  
  ret->edit_insert =
    create_pixmap_radio_button(ret, "gmerlerra/edit_insert.png",
                                TRS("Insert mode"), &ret->edit_insert_id,
                                &ret->edit_mode_group);

  ret->edit_overwrite =
    create_pixmap_radio_button(ret, "gmerlerra/edit_overwrite.png",
                                TRS("Overwrite mode"), &ret->edit_overwrite_id,
                                &ret->edit_mode_group);
  
  
  ret->preview_window = gtk_viewport_new(NULL, NULL);

  gtk_widget_set_events(ret->preview_window,
                        GDK_POINTER_MOTION_MASK|GDK_BUTTON_PRESS_MASK);

  g_signal_connect(ret->preview_window,
                   "scroll-event",
                   G_CALLBACK(scroll_callback), ret);
  g_signal_connect(ret->preview_window,
                   "motion-notify-event",
                   G_CALLBACK(motion_notify_callback), ret);
  g_signal_connect(ret->preview_window,
                   "size-allocate", G_CALLBACK(size_allocate_callback),
                   ret);

  
  ret->scrollbar =
    gtk_vscrollbar_new(gtk_viewport_get_vadjustment(GTK_VIEWPORT(ret->preview_window)));
  gtk_widget_show(ret->scrollbar);
  
  //  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ret->preview_window),
  //                                 GTK_POLICY_NEVER, GTK_POLICY_NEVER);


  ret->panel_window =
    gtk_viewport_new(NULL, gtk_viewport_get_vadjustment(GTK_VIEWPORT(ret->preview_window)));

  gtk_widget_set_events(ret->panel_window,
                        GDK_BUTTON_PRESS_MASK);

  g_signal_connect(ret->panel_window,
                   "scroll-event",
                   G_CALLBACK(scroll_callback), ret);

  
  gtk_viewport_set_shadow_type(GTK_VIEWPORT(ret->preview_window),
                               GTK_SHADOW_NONE);
  gtk_viewport_set_shadow_type(GTK_VIEWPORT(ret->panel_window),
                               GTK_SHADOW_NONE);

  gtk_widget_set_size_request(ret->panel_window, -1, 0);
  gtk_widget_set_size_request(ret->preview_window, -1, 0);
  
  //  ret->panel_window =
  //    gtk_scrolled_window_new((GtkAdjustment *)0,
  //                            GTK_ADJUSTMENT(adj));
  
  //  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ret->panel_window),
  //                                 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
  
  ret->preview_box = gtk_vbox_new(FALSE, 1);
  ret->panel_box = gtk_vbox_new(FALSE, 1);

  gtk_container_add(GTK_CONTAINER(ret->preview_window), ret->preview_box);
  gtk_container_add(GTK_CONTAINER(ret->panel_window), ret->panel_box);
  
  gtk_widget_show(ret->preview_box);
  gtk_widget_show(ret->panel_box);

  gtk_widget_show(ret->preview_window);
  gtk_widget_show(ret->panel_window);
    
  /* Pack */
  
  box = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(box), 
                     ret->edit_insert, FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(box), 
                     ret->edit_overwrite, FALSE, TRUE, 0);
  
  gtk_widget_show(box);

  size_group = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL);
  gtk_size_group_add_widget(size_group, box);
  gtk_size_group_add_widget(size_group, bg_nle_time_ruler_get_widget(ret->ruler));
  g_object_unref(size_group);

  
  ret->table = gtk_table_new(2, 3, 0);

  /* Button box */
  frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 0); 

  style = gtk_style_copy(frame->style);
  style->xthickness = 1;
  style->ythickness = 1;
  gtk_widget_set_style(frame, style);
  g_object_unref(style);


  gtk_container_add(GTK_CONTAINER(frame), box);
  gtk_widget_show(frame);
  
  gtk_table_attach(GTK_TABLE(ret->table),
                   frame,
                   0, 1, 0, 1,
                   GTK_FILL|GTK_SHRINK, GTK_FILL|GTK_SHRINK, 0, 0);

  /* Panel window */
  frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 0); 

  style = gtk_style_copy(frame->style);
  style->xthickness = 1;
  style->ythickness = 1;
  gtk_widget_set_style(frame, style);
  g_object_unref(style);
  
  gtk_container_add(GTK_CONTAINER(frame), ret->panel_window);
  gtk_widget_show(frame);
  
  
  gtk_table_attach(GTK_TABLE(ret->table),
                   frame,
                   0, 1, 1, 2,
                   GTK_FILL|GTK_SHRINK, GTK_EXPAND|GTK_FILL, 0, 0);
  
  //  gtk_widget_show(table);

  //  gtk_paned_add1(GTK_PANED(ret->paned), table);
  
  //  table = gtk_table_new(2, 1, 0);

  /* Time ruler */
  frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 0); 

  style = gtk_style_copy(frame->style);
  style->xthickness = 1;
  style->ythickness = 1;
  gtk_widget_set_style(frame, style);
  g_object_unref(style);
  
  gtk_container_add(GTK_CONTAINER(frame), bg_nle_time_ruler_get_widget(ret->ruler));
  gtk_widget_show(frame);
  
  gtk_table_attach(GTK_TABLE(ret->table),
                   frame,
                   1, 2, 0, 1,
                   GTK_EXPAND|GTK_FILL, GTK_FILL|GTK_SHRINK, 0, 0);
  
  /* Preview window */

  frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 0); 

  style = gtk_style_copy(frame->style);
  style->xthickness = 1;
  style->ythickness = 1;
  gtk_widget_set_style(frame, style);
  g_object_unref(style);
  
  gtk_container_add(GTK_CONTAINER(frame), ret->preview_window);
  gtk_widget_show(frame);

  
  gtk_table_attach(GTK_TABLE(ret->table),
                   frame,
                   1, 2, 1, 2,
                   GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
  
  gtk_table_attach(GTK_TABLE(ret->table),
                   ret->scrollbar,
                   2, 3, 1, 2,
                   GTK_FILL|GTK_SHRINK, GTK_EXPAND|GTK_FILL, 0, 0);
  
  gtk_widget_show(ret->table);
  //  gtk_paned_add2(GTK_PANED(ret->paned), table);

  //  gtk_widget_show(ret->paned);
  /* Add tracks */

  if(ret->p->num_tracks)
    ret->tracks = calloc(ret->p->num_tracks, sizeof(*ret->tracks));

  for(i = 0; i < ret->p->num_tracks; i++)
    {
    ret->tracks[ret->num_tracks] =
      bg_nle_track_widget_create(ret->p->tracks[i], &ret->tr, ret->ruler);

    gtk_box_pack_start(GTK_BOX(ret->panel_box),
                       bg_nle_track_widget_get_panel(ret->tracks[ret->num_tracks]),
                       FALSE, FALSE, 0);
    
    gtk_box_pack_start(GTK_BOX(ret->preview_box),
                       bg_nle_track_widget_get_preview(ret->tracks[ret->num_tracks]),
                       FALSE, FALSE, 0);
    ret->num_tracks++;
    }

  /* Add outstreams */

  if(ret->p->num_outstreams)
    {
    ret->outstreams = calloc(ret->p->num_outstreams, sizeof(*ret->outstreams));

    for(i = 0; i < ret->p->num_outstreams; i++)
      {
      ret->outstreams[ret->num_outstreams] =
        bg_nle_outstream_widget_create(ret->p->outstreams[i], ret->ruler, &ret->tr);

      gtk_box_pack_start(GTK_BOX(ret->panel_box),
                         bg_nle_outstream_widget_get_panel(ret->outstreams[ret->num_outstreams]),
                         FALSE, FALSE, 0);
    
      gtk_box_pack_start(GTK_BOX(ret->preview_box),
                         bg_nle_outstream_widget_get_preview(ret->outstreams[ret->num_outstreams]),
                         FALSE, FALSE, 0);
      ret->num_outstreams++;
      }
    }

  /* Set radio buttons */
  
  bg_nle_timeline_set_edit_mode(ret, ret->p->edit_mode);
  return ret;
  }
Ejemplo n.º 12
0
					/*if (simple_p)
						nskey = (uint32_t)0;*/
					break;
			}
		}
	} else {
		nskey = utf8_to_ucs4(bytes, numbytes);
	}

	bool done = browser_window_key_press(g->bw, nskey);
	LOG(("nskey %d %d", nskey, done));
	//if (browser_window_key_press(g->bw, nskey))
		return;
	
}

#warning WRITEME
#if 0 /* GTK */
gboolean nsbeos_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
					gpointer data)
{
	struct gui_window *g = data;
	uint32_t nskey = gdkkey_to_nskey(event);

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

	if (event->state == 0) {
		double value;
		GtkAdjustment *vscroll = gtk_viewport_get_vadjustment(g->viewport);

		GtkAdjustment *hscroll = gtk_viewport_get_hadjustment(g->viewport);

		GtkAdjustment *scroll;

		const GtkAllocation *const alloc =
			&GTK_WIDGET(g->viewport)->allocation;

		switch (event->keyval) {
		default:
			return TRUE;

		case GDK_Home:
		case GDK_KP_Home:
			scroll = vscroll;
			value = scroll->lower;
			break;

		case GDK_End:
		case GDK_KP_End:
			scroll = vscroll;
			value = scroll->upper - alloc->height;
			if (value < scroll->lower)
				value = scroll->lower;
			break;

		case GDK_Left:
		case GDK_KP_Left:
			scroll = hscroll;
			value = gtk_adjustment_get_value(scroll) -
						scroll->step_increment;
			if (value < scroll->lower)
				value = scroll->lower;
			break;

		case GDK_Up:
		case GDK_KP_Up:
			scroll = vscroll;
			value = gtk_adjustment_get_value(scroll) -
						scroll->step_increment;
			if (value < scroll->lower)
				value = scroll->lower;
			break;

		case GDK_Right:
		case GDK_KP_Right:
			scroll = hscroll;
			value = gtk_adjustment_get_value(scroll) +
						scroll->step_increment;
			if (value > scroll->upper - alloc->width)
				value = scroll->upper - alloc->width;
			break;

		case GDK_Down:
		case GDK_KP_Down:
			scroll = vscroll;
			value = gtk_adjustment_get_value(scroll) +
						scroll->step_increment;
			if (value > scroll->upper - alloc->height)
				value = scroll->upper - alloc->height;
			break;

		case GDK_Page_Up:
		case GDK_KP_Page_Up:
			scroll = vscroll;
			value = gtk_adjustment_get_value(scroll) -
						scroll->page_increment;
			if (value < scroll->lower)
				value = scroll->lower;
			break;

		case GDK_Page_Down:
		case GDK_KP_Page_Down:
			scroll = vscroll;
			value = gtk_adjustment_get_value(scroll) +
						scroll->page_increment;
			if (value > scroll->upper - alloc->height)
				value = scroll->upper - alloc->height;
			break;
		}

		gtk_adjustment_set_value(scroll, value);
	}

	return TRUE;
}