Re: Help packaging the latest pidgin.
"Neil Munro" <[email protected]>
| Newsgroups | gmane.comp.autopackage.devel |
|---|---|
| Message-ID | <[email protected]> |
Ok here's the latest attempt. I looked at the patch file which shows this:
- piece = gdk_pixbuf_new_from_file_at_scale (IMAGEDIR "/lb-middle.png",
+ filename = g_build_filename (imagedir, "lb-middle.png", NULL);
+
+ piece = gdk_pixbuf_new_from_file_at_scale (filename,
width, height,
FALSE,
NULL);
I assume this is to make it easier to free the memory at the end of the
function and g_free is run on filename? If it's just about right I shall run
through the finch part of Pidgin see if I can't get the basics of it
autopackaged.
On 01/02/2008, Isak Savo <[email protected]> wrote:
>
> 2008/2/1, Neil Munro <[email protected]>:
> > Ok so I have looked at the lb-window.c for the correct version of the
> > program and have attached what I have done so far. The website shows me
> an
> > example of what I should alter, however I found some things in the code
> I
> > THINK look like they may also need patching, if they don't fine, but
> here's
> > an example of one of the instances:
> >
> > piece = gdk_pixbuf_new_from_file_at_scale (IMAGEDIR
> > "/lb-middle.png",
> > width, height,
> > FALSE,
> > NULL);
> >
> > The way I am thinking is that it should look like this:
> >
> > piece = gdk_pixbuf_new_from_file_at_scale(
> > g_build_filename( IMAGEDIR, "lb-middle.png", NULL ),
> > width, height,
> > FALSE,
> > NULL);
> >
>
> Yes and no :)
>
> Yes, it needs changing, but you'r change suggestion is incorrect. You
> see, IMAGEDIR is a string constant, determined at compile time. You
> want to change it to something that is determined at runtime (i.e.
> using binreloc).
>
> So the correct way would be:
> /* imagedir is of type gchar* and was initialized somewhere else,
> by calling gbr_find_datadir and adding /images/ or somthing to it. */
> piece = gdk_pixbuf_new_from_file_at_scale( g_build_filename(
> imagedir, "lb-middle.png", NULL ),
> width, height,
> FALSE,
> NULL);
> Also note that you are leaking memory here. g_build_filename expects
> the return value to be free'd by the caller, which you don't do. If
> this code is run several times, it could be a problem.
>
> > I'm not sure though, but I think it's obvious WHY I think it needs
> changing.
> > Also further reading on I have created the glib'd binreloc c and h files
> and
> > moved them into /src in the gnome-launch-box directory, however I'm not
> > entirely sure where to stick them, I downloaded the patch file to see if
> it
> > could be of help, and while it gave me some ideas, I realize if I am to
> > build pidgin, I won't have the liberty of looking at someone else's
> patch so
> > I try not to rely on it.
>
> > Also with regards to the tutorial
> >
> > " Grab binreloc from autopackage CVS, then run the generate.pl script.
> In
> > this instance, we want the glib-ized version not the raw C version so
> pass
> > "glib" as a parameter. It'll output two files: binreloc.c and binreloc.h
> .
> > Add them to Makefile.am and re-run autogen, and now it's integrated with
> our
> > project."
>
> No, apparently they don't have an autogen script. Just run "autoconf"
> (if you change configure.ac) and "automake" if you modifify
> Makefile.am
>
> > There is no autogen.sh file, so I had to fall back upon configure to see
> if
> > it would work, not sure if you wanna change the tutorial to reflect this
> or
> > not. Configure seems to run cleanly though.
>
> See above, you need to call autoconf and/or automake if you change
> Makefile.am and configure.ac.
>
> > What do I do with this code?
> >
> > static gchar *imagedir;
> >
> > /* will be called automatically before main() */
> > static void __attribute__((constructor))
> > locate_image_dir ()
> > {
> > if (gbr_init (NULL))
> >
> > imagedir = g_build_filename (gbr_find_data_dir (DATADIR), "lb",
> "images",
> > NULL);
> > else
> > imagedir = DATADIR "/lb/images";
> > }
> >
> > It's not clear what I am supposed to do with it. It reads "Now we just
> > change "IMAGEDIR" to "imagedir" in the
> >
> > window_pixbuf_fill_corner function and we're done. Let's test it!" I
> imagine
> > that I stick that function at the top
> > of the file and the change from IMAGEDIR to imagedir is the magic that
> glues
> > all this together?
>
> imagedir (lowercase) is a variable calculated at runtime. IMAGEDIR
> (uppercase) is a constant calculated at compile time.
>
> It doesn't matter where you put that code, as the __attribute__
> (constructor) thing will make sure that it gets called before any
> other function (as long as gcc is used to compile at least).
>
> -Isak
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: autopackage-dev-unsubscribe-OfajU3CKLf1/[email protected]
> For additional commands, e-mail: autopackage-dev-help-OfajU3CKLf1/[email protected]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: autopackage-dev-unsubscribe-OfajU3CKLf1/[email protected]
For additional commands, e-mail: autopackage-dev-help-OfajU3CKLf1/[email protected]
lb-window.c
(text/x-csrc, 27.5 KB)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2005 Imendio AB
*
* This library 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; either version 2 of the
* License, or (at your option) any later version.
*
* This library 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 library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* lb-window.c
*/
#include "config.h"
#include <string.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "lb-window.h"
#include "lb-item.h"
#include "lb-icon-box.h"
#include "lb-utils.h"
#include "lb-action.h"
#define FRAME_SIZE 30
#define SEARCH_TIMEOUT 150
#define SEARCH_RESET_TIMEOUT 2000
typedef enum {
LB_WINDOW_CORNER_TOP_LEFT,
LB_WINDOW_CORNER_TOP_RIGHT,
LB_WINDOW_CORNER_BOTTOM_LEFT,
LB_WINDOW_CORNER_BOTTOM_RIGHT
} LbWindowCorner;
typedef enum {
LB_WINDOW_FOCUS_ITEM,
LB_WINDOW_FOCUS_ACTION
} LbWindowFocus;
enum {
COL_OBJECT,
COL_PIXBUF,
COL_NAME,
NUM_COLS
};
enum {
PROP_0,
PROP_MANAGER,
};
typedef struct {
LbModuleManager *manager;
LbWindowFocus focus;
GString *search_string;
LbItem *current_item;
LbAction *current_action;
GtkWidget *result_hbox;
GtkWidget *item_icon_box;
GtkWidget *action_icon_box;
GtkWidget *result_treeview;
GdkPixbuf *empty_pixbuf;
GdkPixbuf *unknown_pixbuf;
guint search_timeout_id;
gboolean reset_search;
guint search_reset_timeout_id;
} LbWindowPriv;
static void lb_window_finalize (GObject *object);
static void lb_window_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void lb_window_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void window_realize_cb (GtkWidget *widget,
LbWindow *window);
static void window_set_focus (LbWindow *window,
LbWindowFocus focus);
static void window_set_item (LbWindow *window,
LbItem *item,
const gchar *match);
static void window_set_action (LbWindow *window,
LbAction *action,
const gchar *match);
static void window_queue_search (LbWindow *window);
static gboolean window_search_timeout_cb (LbWindow *window);
static gboolean window_search_reset_timeout_cb (LbWindow *window);
static void window_perform_search (LbWindow *window,
const gchar *str);
static void window_result_row_selected_cb (GtkTreeSelection *selection,
LbWindow *window);
static void window_reset_result (LbWindow *window);
static gboolean window_key_press_event_cb (GtkWidget *widget,
GdkEventKey *event,
LbWindow *window);
static gboolean window_get_is_visible (LbWindow *window);
static void window_update_background (LbWindow *window);
static void window_start_reset_timeout (LbWindow *window);
G_DEFINE_TYPE (LbWindow, lb_window, GTK_TYPE_WINDOW);
#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LB_TYPE_WINDOW, LbWindowPriv))
static void
lb_window_class_init (LbWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = lb_window_finalize;
object_class->set_property = lb_window_set_property;
object_class->get_property = lb_window_get_property;
g_object_class_install_property (object_class, PROP_MANAGER,
g_param_spec_object ("manager",
NULL, NULL,
LB_TYPE_MODULE_MANAGER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (LbWindowPriv));
}
static void
lb_window_init (LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
GtkWidget *vbox;
GtkWidget *sw;
GtkListStore *store;
GtkTreeViewColumn *column;
GtkCellRenderer *cell;
GtkTreeSelection *selection;
gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
priv->focus = LB_WINDOW_FOCUS_ITEM;
priv->search_timeout_id = 0;
priv->search_reset_timeout_id = 0;
priv->reset_search = FALSE;
priv->search_string = g_string_new (NULL);
priv->empty_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
TRUE,
8,
64, 64);
gdk_pixbuf_fill (priv->empty_pixbuf, 0x00000000);
priv->unknown_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
TRUE,
8,
64, 64);
gdk_pixbuf_fill (priv->unknown_pixbuf, 0x00000000);
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 18);
gtk_widget_show (vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
priv->result_hbox = gtk_hbox_new (FALSE, 12);
gtk_widget_show (priv->result_hbox);
gtk_box_pack_start (GTK_BOX (vbox),
priv->result_hbox, FALSE, FALSE, 0);
priv->item_icon_box = lb_icon_box_new (NULL, priv->empty_pixbuf);
gtk_frame_set_shadow_type (GTK_FRAME (priv->item_icon_box),
GTK_SHADOW_IN);
gtk_widget_show (priv->item_icon_box);
gtk_box_pack_start (GTK_BOX (priv->result_hbox), priv->item_icon_box,
TRUE, TRUE, 0);
priv->action_icon_box = lb_icon_box_new (NULL, priv->empty_pixbuf);
gtk_widget_show (priv->action_icon_box);
gtk_box_pack_start (GTK_BOX (priv->result_hbox), priv->action_icon_box,
TRUE, TRUE, 0);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_size_request (sw, -1, 64 * 4);
gtk_widget_show (sw);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_IN);
priv->result_treeview = gtk_tree_view_new ();
gtk_widget_show (priv->result_treeview);
gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->result_treeview), FALSE);
gtk_container_add (GTK_CONTAINER (sw), priv->result_treeview);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->result_treeview), FALSE);
store = gtk_list_store_new (NUM_COLS,
LB_TYPE_OBJECT,
GDK_TYPE_PIXBUF,
G_TYPE_STRING);
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->result_treeview),
GTK_TREE_MODEL (store));
column = gtk_tree_view_column_new ();
cell = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, cell, FALSE);
gtk_tree_view_column_add_attribute (column,
cell,
"pixbuf",
COL_PIXBUF);
cell = gtk_cell_renderer_text_new ();
g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_tree_view_column_pack_start (column, cell, TRUE);
gtk_tree_view_column_add_attribute (column,
cell,
"markup",
COL_NAME);
gtk_tree_view_append_column (GTK_TREE_VIEW (priv->result_treeview), column);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->result_treeview));
g_signal_connect (selection, "changed",
G_CALLBACK (window_result_row_selected_cb),
window);
g_signal_connect (window, "key_press_event",
G_CALLBACK (window_key_press_event_cb),
window);
g_signal_connect (window, "realize",
G_CALLBACK (window_realize_cb),
window);
}
static void
lb_window_finalize (GObject *object)
{
LbWindow *window = LB_WINDOW (object);
LbWindowPriv *priv = GET_PRIV (window);
if (priv->search_timeout_id) {
g_source_remove (priv->search_timeout_id);
}
if (priv->search_reset_timeout_id) {
g_source_remove (priv->search_reset_timeout_id);
}
if (priv->current_item) {
g_object_unref (priv->current_item);
}
if (priv->current_action) {
g_object_unref (priv->current_action);
}
g_string_free (priv->search_string, TRUE);
g_object_unref (priv->unknown_pixbuf);
g_object_unref (priv->empty_pixbuf);
G_OBJECT_CLASS (lb_window_parent_class)->finalize (object);
}
static void
lb_window_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
LbWindow *window = LB_WINDOW (object);
LbWindowPriv *priv = GET_PRIV (window);
switch (property_id) {
case PROP_MANAGER:
priv->manager = LB_MODULE_MANAGER (g_value_dup_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
lb_window_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
LbWindow *window = LB_WINDOW (object);
LbWindowPriv *priv = GET_PRIV (window);
switch (property_id) {
case PROP_MANAGER:
g_value_set_object (value, priv->manager);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
window_realize_cb (GtkWidget *widget,
LbWindow *window)
{
window_update_background (LB_WINDOW (window));
}
GtkWidget *
lb_window_new (LbModuleManager *manager)
{
GtkWidget *window;
window = g_object_new (LB_TYPE_WINDOW,
"type", GTK_WINDOW_POPUP,
"manager", manager,
NULL);
return window;
}
static void
window_set_focus (LbWindow *window,
LbWindowFocus focus)
{
LbWindowPriv *priv = GET_PRIV (window);
GtkListStore *store;
if (priv->focus == focus) {
return;
}
if (focus == LB_WINDOW_FOCUS_ACTION) {
if (! priv->current_action) {
return;
}
}
store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->result_treeview)));
gtk_list_store_clear (store);
g_string_truncate (priv->search_string, 0);
if (focus == LB_WINDOW_FOCUS_ACTION) {
gtk_frame_set_shadow_type (GTK_FRAME (priv->item_icon_box),
GTK_SHADOW_NONE);
gtk_frame_set_shadow_type (GTK_FRAME (priv->action_icon_box),
GTK_SHADOW_IN);
} else {
gtk_frame_set_shadow_type (GTK_FRAME (priv->item_icon_box),
GTK_SHADOW_IN);
gtk_frame_set_shadow_type (GTK_FRAME (priv->action_icon_box),
GTK_SHADOW_NONE);
}
priv->focus = focus;
window_queue_search (window);
}
static void
window_set_item (LbWindow *window,
LbItem *item,
const gchar *match)
{
LbWindowPriv *priv = GET_PRIV (window);
if (priv->current_item == item) {
return;
}
if (priv->current_item) {
g_object_unref (priv->current_item);
priv->current_item = NULL;
}
if (item) {
GdkPixbuf *pixbuf;
gchar *markup = NULL;
GList *actions;
priv->current_item = g_object_ref (item);
g_object_get (item, "pixbuf", &pixbuf, NULL);
if (match) {
markup = lb_string_markup_substring (LB_OBJECT (item)->name,
match, "u");
}
if (! markup) {
markup = g_markup_escape_text (LB_OBJECT (item)->name,
-1);
}
g_object_set (priv->item_icon_box,
"caption", markup,
"pixbuf", pixbuf ? pixbuf : priv->unknown_pixbuf,
NULL);
if (pixbuf)
g_object_unref (pixbuf);
g_free (markup);
actions = lb_item_get_actions (item, NULL);
if (! actions) {
lb_module_manager_set_actions (priv->manager, item);
actions = lb_item_get_actions (item, NULL);
}
if (actions) {
window_set_action (window, actions->data, NULL);
g_list_free (actions);
} else {
window_set_action (window, NULL, NULL);
}
} else {
g_object_set (priv->item_icon_box,
"caption", NULL,
"pixbuf", priv->empty_pixbuf,
NULL);
window_set_action (window, NULL, NULL);
}
}
static void
window_set_action (LbWindow *window,
LbAction *action,
const gchar *match)
{
LbWindowPriv *priv = GET_PRIV (window);
if (priv->current_action == action) {
return;
}
if (priv->current_action) {
g_object_unref (priv->current_action);
priv->current_action = NULL;
}
if (action) {
GdkPixbuf *pixbuf;
gchar *markup = NULL;
priv->current_action = g_object_ref (action);
g_object_get (LB_OBJECT (action), "pixbuf", &pixbuf, NULL);
if (match) {
markup = lb_string_markup_substring (LB_OBJECT (action)->name,
match, "u");
}
if (! markup) {
markup = g_markup_escape_text (LB_OBJECT (action)->name,
-1);
}
g_object_set (priv->action_icon_box,
"caption", markup,
"pixbuf", pixbuf ? pixbuf : priv->unknown_pixbuf,
NULL);
if (pixbuf)
g_object_unref (pixbuf);
g_free (markup);
} else {
g_object_set (priv->action_icon_box,
"caption", NULL,
"pixbuf", priv->empty_pixbuf,
NULL);
}
}
static void
window_queue_search (LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
LbObject *current;
LbIconBox *icon_box;
if (priv->focus == LB_WINDOW_FOCUS_ITEM) {
current = LB_OBJECT (priv->current_item);
icon_box = LB_ICON_BOX (priv->item_icon_box);
} else {
current = LB_OBJECT (priv->current_action);
icon_box = LB_ICON_BOX (priv->action_icon_box);
}
/* If we already have a match, try matching further on it. */
if (current) {
if (lb_string_has_substring (current->name,
priv->search_string->str)) {
gchar *markup;
markup = lb_string_markup_substring (current->name,
priv->search_string->str, "u");
g_object_set (icon_box,
"caption", markup ? markup : current->name,
NULL);
g_free (markup);
} else {
if (priv->focus == LB_WINDOW_FOCUS_ITEM) {
window_set_item (window, NULL, NULL);
} else {
window_set_action (window, NULL, NULL);
}
g_object_set (icon_box,
"caption", priv->search_string->str,
NULL);
}
} else {
g_object_set (icon_box,
"caption", priv->search_string->str,
NULL);
}
if (priv->search_timeout_id) {
g_source_remove (priv->search_timeout_id);
}
priv->search_timeout_id = g_timeout_add (SEARCH_TIMEOUT,
(GSourceFunc) window_search_timeout_cb,
window);
}
static gboolean
window_search_timeout_cb (LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
priv->search_timeout_id = 0;
window_perform_search (window, priv->search_string->str);
return FALSE;
}
static gboolean
window_search_reset_timeout_cb (LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
priv->search_reset_timeout_id = 0;
priv->reset_search = TRUE;
return FALSE;
}
static void
window_perform_search (LbWindow *window,
const gchar *str)
{
LbWindowPriv *priv;
GList *list, *l;
GtkListStore *store;
GtkTreeSelection *selection;
gboolean selected = FALSE;
priv = GET_PRIV (window);
window_reset_result (window);
if (str && str[0] == '\0') {
str = NULL;
}
if (! str && priv->focus == LB_WINDOW_FOCUS_ITEM) {
return;
}
if (priv->focus == LB_WINDOW_FOCUS_ITEM) {
list = lb_module_manager_query (priv->manager, str);
} else {
list = lb_item_get_actions (priv->current_item, str);
}
if (!list) {
return;
}
store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->result_treeview)));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->result_treeview));
for (l = list; l; l = l->next) {
GtkTreeIter iter;
LbObject *object;
GdkPixbuf *pixbuf;
gchar *markup;
object = LB_OBJECT (l->data);
markup = lb_string_markup_substring (object->name, str, "b");
g_object_get (object, "pixbuf", &pixbuf, NULL);
if (!pixbuf) {
pixbuf = g_object_ref (priv->unknown_pixbuf);
}
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COL_OBJECT, object,
COL_PIXBUF, pixbuf,
COL_NAME, markup ? markup : object->name,
-1);
g_object_unref (pixbuf);
g_free (markup);
if (! selected) {
gtk_tree_selection_select_iter (selection, &iter);
selected = TRUE;
}
}
g_list_free (list);
}
static void
window_result_row_selected_cb (GtkTreeSelection *selection,
LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
GtkTreeModel *model;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
LbObject *object;
gtk_tree_model_get (model, &iter,
COL_OBJECT, &object,
-1);
if (priv->focus == LB_WINDOW_FOCUS_ITEM) {
window_set_item (window, LB_ITEM (object),
priv->search_string->str);
} else {
window_set_action (window, LB_ACTION (object),
priv->search_string->str);
}
g_object_unref (object);
}
}
static void
window_reset_result (LbWindow *window)
{
LbWindowPriv *priv;
GtkListStore *store;
priv = GET_PRIV (window);
priv->reset_search = FALSE;
store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->result_treeview)));
gtk_list_store_clear (store);
if (priv->focus == LB_WINDOW_FOCUS_ITEM) {
window_set_item (window, NULL, NULL);
g_object_set (priv->item_icon_box,
"caption", priv->search_string->str, NULL);
} else {
window_set_action (window, NULL, NULL);
g_object_set (priv->action_icon_box,
"caption", priv->search_string->str, NULL);
}
}
/* Test some search stuff. */
static void
window_string_utf8_remove_last_char (GString *string)
{
gchar *ptr;
glong utf8_len;
utf8_len = g_utf8_strlen (string->str, -1);
if (utf8_len == 0) {
return;
}
utf8_len--;
ptr = g_utf8_offset_to_pointer (string->str, utf8_len);
g_string_truncate (string, string->len - strlen (ptr));
}
static gboolean
window_key_press_event_cb (GtkWidget *widget,
GdkEventKey *event,
LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
if (event->state & GDK_CONTROL_MASK) {
return TRUE;
}
switch (event->keyval) {
case GDK_Escape:
gtk_widget_hide (GTK_WIDGET (window));
return TRUE;
case GDK_BackSpace:
if (priv->search_string->len == 0) {
return TRUE;
}
window_string_utf8_remove_last_char (priv->search_string);
window_queue_search (window);
return TRUE;
case GDK_Tab:
if (priv->focus == LB_WINDOW_FOCUS_ITEM) {
if (priv->current_action) {
window_set_focus (window,
LB_WINDOW_FOCUS_ACTION);
}
} else {
window_set_focus (window, LB_WINDOW_FOCUS_ITEM);
}
return TRUE;
case GDK_Up:
case GDK_Down: {
GtkTreeView *tv;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
tv = GTK_TREE_VIEW (priv->result_treeview);
selection = gtk_tree_view_get_selection (tv);
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
GtkTreePath *path;
path = gtk_tree_model_get_path (model, &iter);
if (event->keyval == GDK_Up) {
gtk_tree_path_prev (path);
} else {
gtk_tree_path_next (path);
}
gtk_tree_selection_select_path (selection, path);
gtk_tree_view_scroll_to_cell (tv, path,
NULL, FALSE, 0.0, 0.0);
gtk_tree_path_free (path);
}
}
return TRUE;
case GDK_Return:
case GDK_ISO_Enter:
if (priv->current_action) {
lb_action_activate (priv->current_action);
}
gtk_widget_hide (GTK_WIDGET (window));
return TRUE;
default:
if (priv->reset_search) {
g_string_truncate (priv->search_string, 0);
window_reset_result (window);
}
if (event->length > 0) {
g_string_append_unichar (priv->search_string,
gdk_keyval_to_unicode (event->keyval));
} else {
return TRUE;
}
}
window_queue_search (window);
window_start_reset_timeout (window);
return TRUE;
}
static gboolean
window_grab (LbWindow *window)
{
GdkWindow *gdk_window;
guint32 time;
gdk_window = GTK_WIDGET (window)->window;
time = gdk_x11_get_server_time (gdk_window);
if ((gdk_pointer_grab (gdk_window, TRUE,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK,
NULL, NULL, time) == 0)) {
if (gdk_keyboard_grab (gdk_window, TRUE, time) == 0) {
return TRUE;
} else {
gdk_pointer_ungrab (time);
return FALSE;
}
}
return FALSE;
}
void
lb_window_present (LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
if (!window_get_is_visible (window)) {
if (GTK_WIDGET_REALIZED (window)) {
window_update_background (window);
}
g_string_truncate (priv->search_string, 0);
window_reset_result (window);
gtk_window_present (GTK_WINDOW (window));
}
if (!window_grab (window)) {
/* g_print ("Couldn't grab.\n"); */
}
}
static gchar *imagedir;
/* will be called automatically before main() */
static void __attribute__((constructor))
locate_image_dir ()
{
if (gbr_init (NULL))
imagedir = g_build_filename (gbr_find_data_dir (DATADIR), "lb", "images", NULL);
else
imagedir = DATADIR "/lb/images";
}
/*
* Hack to get a transparent rounded window.
*/
static void
window_pixbuf_fill_middle (LbWindow *window,
GdkPixbuf *pixbuf)
{
gint frame_width, frame_height;
GdkPixbuf *piece;
gint width, height;
frame_width = gdk_pixbuf_get_width (pixbuf);
frame_height = gdk_pixbuf_get_height (pixbuf);
width = frame_width - 2 * FRAME_SIZE;
height = FRAME_SIZE;
// Should this be patched? Neil
filename = g_build_filename (imagedir, "lb-middle.png", NULL);
piece = gdk_pixbuf_new_from_file_at_scale(filename, "lb-middle.png",
width, height,
FALSE,
NULL);
g_return_if_fail (piece != NULL);
gdk_pixbuf_copy_area (piece,
0, 0,
width, height,
pixbuf,
FRAME_SIZE, 0);
gdk_pixbuf_copy_area (piece,
0, 0,
width, height,
pixbuf,
FRAME_SIZE, frame_height - FRAME_SIZE);
g_object_unref (piece);
width = FRAME_SIZE;
height = frame_height - 2 * FRAME_SIZE;
// Should this be patched? Neil
filename = g_build_filename (imagedir, "lb-middle.png", NULL);
piece = gdk_pixbuf_new_from_file_at_scale( filename, "lb-middle.png",
width, height,
FALSE,
NULL);
g_return_if_fail (piece != NULL);
gdk_pixbuf_copy_area (piece,
0, 0,
width, height,
pixbuf,
0, FRAME_SIZE);
gdk_pixbuf_copy_area (piece,
0, 0,
width, height,
pixbuf,
frame_width - FRAME_SIZE, FRAME_SIZE);
g_object_unref (piece);
width = frame_width - 2 * FRAME_SIZE;
height = frame_height - 2 * FRAME_SIZE;
// Should this be patched? Neil
filename = g_build_filename (imagedir, "lb-middle.png", NULL);
piece = gdk_pixbuf_new_from_file_at_scale( filename, "lb-middle.png",
width, height,
FALSE,
NULL);
g_return_if_fail (piece != NULL);
gdk_pixbuf_copy_area (piece,
0, 0,
width, height,
pixbuf,
FRAME_SIZE, FRAME_SIZE);
g_object_unref (piece);
g_free( filename );
}
static void
window_pixbuf_fill_corner (LbWindow *window,
GdkPixbuf *pixbuf,
LbWindowCorner corner)
{
gint frame_width, frame_height;
GdkPixbuf *piece;
gint width, height;
const gchar *filename;
gint x, y;
frame_width = gdk_pixbuf_get_width (pixbuf);
frame_height = gdk_pixbuf_get_height (pixbuf);
// Changed the below, as the tutorial showed me.
switch (corner) {
case LB_WINDOW_CORNER_TOP_LEFT:
filename = g_build_filename( imagedir, "lb-top-left.png", NULL );
break;
case LB_WINDOW_CORNER_TOP_RIGHT:
filename = g_build_filename( imagedir, "lb-top-right.png", NULL );
break;
case LB_WINDOW_CORNER_BOTTOM_LEFT:
filename = g_build_filename( imagedir, "lb-bottom-left.png", NULL );
break;
case LB_WINDOW_CORNER_BOTTOM_RIGHT:
filename = g_build_filename( imagedir, "lb-bottom-right.png", NULL );
break;
default:
filename = NULL;
g_assert_not_reached ();
}
piece = gdk_pixbuf_new_from_file (filename, NULL);
g_return_if_fail (piece != NULL);
width = gdk_pixbuf_get_width (piece);
height = gdk_pixbuf_get_height (piece);
switch (corner) {
case LB_WINDOW_CORNER_TOP_LEFT:
x = 0;
y = 0;
break;
case LB_WINDOW_CORNER_TOP_RIGHT:
x = frame_width - width;
y = 0;
break;
case LB_WINDOW_CORNER_BOTTOM_LEFT:
x = 0;
y = frame_height - height;
break;
case LB_WINDOW_CORNER_BOTTOM_RIGHT:
x = frame_width - width;
y = frame_height - height;
break;
default:
x = 0;
y = 0;
g_assert_not_reached ();
}
gdk_pixbuf_copy_area (piece,
0, 0,
width, height,
pixbuf,
x, y);
g_object_unref (piece);
}
static void
window_pixbuf_overlay_frame (LbWindow *window, GdkPixbuf *pixbuf)
{
GdkPixbuf *tmp;
gint frame_width, frame_height;
frame_width = gdk_pixbuf_get_width (pixbuf);
frame_height = gdk_pixbuf_get_height (pixbuf);
tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
TRUE,
8,
frame_width, frame_height);
gdk_pixbuf_fill (tmp, 0x00000000);
window_pixbuf_fill_corner (window,
tmp,
LB_WINDOW_CORNER_TOP_LEFT);
window_pixbuf_fill_corner (window,
tmp,
LB_WINDOW_CORNER_TOP_RIGHT);
window_pixbuf_fill_corner (window,
tmp,
LB_WINDOW_CORNER_BOTTOM_LEFT);
window_pixbuf_fill_corner (window,
tmp,
LB_WINDOW_CORNER_BOTTOM_RIGHT);
window_pixbuf_fill_middle (window, tmp);
gdk_pixbuf_composite (tmp,
pixbuf,
0, 0,
frame_width, frame_height,
0, 0, /* offset */
1, 1, /* scale */
GDK_INTERP_NEAREST,
225);
}
static gboolean
window_get_is_visible (LbWindow *window)
{
gboolean visible;
g_object_get (window,
"visible", &visible,
NULL);
if (GTK_WIDGET (window)->window) {
visible = visible && !(gdk_window_get_state (GTK_WIDGET (window)->window) & GDK_WINDOW_STATE_ICONIFIED);
}
return visible;
}
static void
window_update_background (LbWindow *window)
{
LbWindowPriv *priv;
GdkScreen *screen;
GdkPixbuf *pixbuf;
gint screen_width, screen_height;
gint x, y;
gint width, height;
GdkPixmap *pixmap;
priv = GET_PRIV (window);
screen = gtk_widget_get_screen (GTK_WIDGET (window));
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
screen_width = gdk_screen_get_width (screen);
screen_height = gdk_screen_get_height (screen);
x = screen_width / 2 - width / 2;
y = screen_height / 2 - height / 2;
pixbuf = gdk_pixbuf_get_from_drawable (
NULL,
gdk_screen_get_root_window (screen),
gdk_screen_get_system_colormap (screen),
x, y,
0, 0,
width, height);
g_assert (pixbuf != NULL);
gtk_window_move (GTK_WINDOW (window), x, y);
window_pixbuf_overlay_frame (window, pixbuf);
/* Put the resulting image on the window. */
pixmap = gdk_pixmap_new (GTK_WIDGET (window)->window,
width,
height,
-1);
gdk_draw_pixbuf (pixmap,
NULL, /* clipping gc */
pixbuf,
0, 0, /* src */
0, 0, /* dst */
width, height,
GDK_RGB_DITHER_NONE,
0, 0);
gdk_window_set_back_pixmap (GTK_WIDGET (window)->window, pixmap, FALSE);
g_object_unref (pixbuf);
g_object_unref (pixmap);
gtk_widget_queue_draw (GTK_WIDGET (window));
}
static void
window_start_reset_timeout (LbWindow *window)
{
LbWindowPriv *priv = GET_PRIV (window);
if (priv->search_reset_timeout_id) {
g_source_remove (priv->search_reset_timeout_id);
}
priv->search_reset_timeout_id = g_timeout_add (SEARCH_RESET_TIMEOUT,
(GSourceFunc) window_search_reset_timeout_cb,
window);
}